[PATCH/RFC V2 04/26] library: Add new openconnect_setup_cancel_pipe() call

Kevin Cernekee cernekee at gmail.com
Sun Aug 11 21:49:05 EDT 2013


Most callers will use a simple nonblocking UNIX pipe as their cancel_fd,
so provide a convenience function for creating it.  Also, libopenconnect
will take care of cleaning up pipes created in this manner when the
library instance is freed.

Signed-off-by: Kevin Cernekee <cernekee at gmail.com>
---
 libopenconnect.map.in  |    5 +++++
 library.c              |   24 ++++++++++++++++++++++++
 openconnect-internal.h |    1 +
 openconnect.h          |    5 +++++
 4 files changed, 35 insertions(+)

diff --git a/libopenconnect.map.in b/libopenconnect.map.in
index 16d3380..2845754 100644
--- a/libopenconnect.map.in
+++ b/libopenconnect.map.in
@@ -43,6 +43,11 @@ OPENCONNECT_2.2 {
 	openconnect_set_token_mode;
 } OPENCONNECT_2.1;
 
+OPENCONNECT_2.3 {
+ global:
+	openconnect_setup_cancel_pipe;
+} OPENCONNECT_2.2;
+
 OPENCONNECT_PRIVATE {
  global: @SYMVER_TIME@ @SYMVER_ASPRINTF@ @SYMVER_GETLINE@ @SYMVER_PRINT_ERR@
 	openconnect_SSL_gets;
diff --git a/library.c b/library.c
index 66bf89b..86c3df8 100644
--- a/library.c
+++ b/library.c
@@ -26,6 +26,8 @@
 #include <string.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #ifdef HAVE_LIBSTOKEN
 #include <stoken.h>
@@ -57,6 +59,7 @@ struct openconnect_info *openconnect_vpninfo_new(char *useragent,
 	vpninfo->progress = progress;
 	vpninfo->cbdata = privdata ? : vpninfo;
 	vpninfo->cancel_fd = -1;
+	vpninfo->cancel_fd_write = -1;
 	vpninfo->xmlpost = 1;
 	openconnect_set_reported_os(vpninfo, NULL);
 
@@ -106,6 +109,10 @@ static void free_optlist(struct vpn_option *opt)
 void openconnect_vpninfo_free(struct openconnect_info *vpninfo)
 {
 	openconnect_close_https(vpninfo, 1);
+	if (vpninfo->cancel_fd_write != -1) {
+		close(vpninfo->cancel_fd);
+		close(vpninfo->cancel_fd_write);
+	}
 	free(vpninfo->peer_addr);
 	free_optlist(vpninfo->cookies);
 	free_optlist(vpninfo->cstp_options);
@@ -287,6 +294,23 @@ void openconnect_set_cancel_fd(struct openconnect_info *vpninfo, int fd)
 	vpninfo->cancel_fd = fd;
 }
 
+int openconnect_setup_cancel_pipe(struct openconnect_info *vpninfo)
+{
+	int pipefd[2];
+
+	if (pipe(pipefd) < 0)
+		return -EIO;
+	if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) ||
+	    fcntl(pipefd[1], F_SETFL, O_NONBLOCK)) {
+		close(pipefd[0]);
+		close(pipefd[1]);
+		return -EIO;
+	}
+	vpninfo->cancel_fd = pipefd[0];
+	vpninfo->cancel_fd_write = pipefd[1];
+	return vpninfo->cancel_fd_write;
+}
+
 const char *openconnect_get_version(void)
 {
 	return openconnect_version_str;
diff --git a/openconnect-internal.h b/openconnect-internal.h
index ea59d23..549448c 100644
--- a/openconnect-internal.h
+++ b/openconnect-internal.h
@@ -295,6 +295,7 @@ struct openconnect_info {
 	int dtls_fd;
 	int new_dtls_fd;
 	int cancel_fd;
+	int cancel_fd_write;
 
 	struct pkt *incoming_queue;
 	struct pkt *outgoing_queue;
diff --git a/openconnect.h b/openconnect.h
index d48bc25..47ac8b5 100644
--- a/openconnect.h
+++ b/openconnect.h
@@ -217,6 +217,11 @@ void openconnect_set_cert_expiry_warning(struct openconnect_info *vpninfo,
    cancellation mechanism inactive. */
 void openconnect_set_cancel_fd(struct openconnect_info *vpninfo, int fd);
 
+/* Create a nonblocking pipe, set the read end as the cancel_fd, and return a
+   file descriptor for the write end. Both sides will be closed by
+   openconnect_vpninfo_free(). */
+int openconnect_setup_cancel_pipe(struct openconnect_info *vpninfo);
+
 const char *openconnect_get_version(void);
 
 /* The first (privdata) argument to each of these functions is either
-- 
1.7.9.5




More information about the openconnect-devel mailing list