From: Martin Willi Date: Thu, 17 Oct 2013 09:56:15 +0000 (+0200) Subject: watcher: Add Windows support X-Git-Tag: 5.2.0dr6~24^2~110 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=93f78d82256fd50623048dcb262b147cad85b902;p=thirdparty%2Fstrongswan.git watcher: Add Windows support Instead of a pipe we use a TCP socketpair (can't select() a _pipe()), and Windsock2 send/recv functions instead of read/write. Currently supported (and required) are file descriptors provided by Winsock only; we might use a separate mechanism for traditional file handles if required (or switch to Windows events and WaitForMultipleObjects) for a future version. --- diff --git a/src/libstrongswan/processing/watcher.c b/src/libstrongswan/processing/watcher.c index 09905646c6..560e47299a 100644 --- a/src/libstrongswan/processing/watcher.c +++ b/src/libstrongswan/processing/watcher.c @@ -24,7 +24,9 @@ #include #include +#ifndef WIN32 #include +#endif #include typedef struct private_watcher_t private_watcher_t; @@ -119,7 +121,14 @@ static void update(private_watcher_t *this) this->pending = TRUE; if (this->notify[1] != -1) { - ignore_result(write(this->notify[1], buf, sizeof(buf))); +#ifdef WIN32 + if (send(this->notify[1], buf, sizeof(buf), 0) == -1) +#else + if (write(this->notify[1], buf, sizeof(buf)) == -1) +#endif + { + DBG1(DBG_JOB, "notifying watcher failed: %s", strerror(errno)); + } } } @@ -293,21 +302,40 @@ static job_requeue_t watch(private_watcher_t *this) { char buf[1]; bool old; + ssize_t len; job_t *job; DBG2(DBG_JOB, "watcher going to select()"); thread_cleanup_push((void*)activate_all, this); old = thread_cancelability(TRUE); + res = select(maxfd + 1, &rd, &wr, &ex, NULL); thread_cancelability(old); thread_cleanup_pop(FALSE); + if (res > 0) { if (this->notify[0] != -1 && FD_ISSET(this->notify[0], &rd)) { - DBG2(DBG_JOB, "watcher got notification, rebuilding"); - while (read(this->notify[0], buf, sizeof(buf)) > 0); + while (TRUE) + { +#ifdef WIN32 + len = recv(this->notify[0], buf, sizeof(buf), 0); +#else + len = read(this->notify[0], buf, sizeof(buf)); +#endif + if (len == -1) + { + if (errno != EAGAIN && errno != EWOULDBLOCK) + { + DBG1(DBG_JOB, "reading watcher notify failed: %s", + strerror(errno)); + } + break; + } + } this->pending = FALSE; + DBG2(DBG_JOB, "watcher got notification, rebuilding"); return JOB_REQUEUE_DIRECT; } @@ -446,13 +474,60 @@ METHOD(watcher_t, destroy, void, free(this); } +#ifdef WIN32 + +/** + * Create notify pipe with a TCP socketpair + */ +static bool create_notify(private_watcher_t *this) +{ + u_long on = 1; + + if (socketpair(AF_INET, SOCK_STREAM, 0, this->notify) == 0) + { + /* use non-blocking I/O on read-end of notify pipe */ + if (ioctlsocket(this->notify[0], FIONBIO, &on) == 0) + { + return TRUE; + } + DBG1(DBG_LIB, "setting watcher notify pipe read-end non-blocking " + "failed: %s", strerror(errno)); + } + return FALSE; +} + +#else /* !WIN32 */ + +/** + * Create a notify pipe with a one-directional pipe + */ +static bool create_notify(private_watcher_t *this) +{ + int flags; + + if (pipe(this->notify) == 0) + { + /* use non-blocking I/O on read-end of notify pipe */ + flags = fcntl(this->notify[0], F_GETFL); + if (flags != -1 && + fcntl(this->notify[0], F_SETFL, flags | O_NONBLOCK) != -1) + { + return TRUE; + } + DBG1(DBG_LIB, "setting watcher notify pipe read-end non-blocking " + "failed: %s", strerror(errno)); + } + return FALSE; +} + +#endif /* !WIN32 */ + /** * See header */ watcher_t *watcher_create() { private_watcher_t *this; - int flags; INIT(this, .public = { @@ -467,18 +542,7 @@ watcher_t *watcher_create() .notify = {-1, -1}, ); - if (pipe(this->notify) == 0) - { - /* use non-blocking I/O on read-end of notify pipe */ - flags = fcntl(this->notify[0], F_GETFL); - if (flags == -1 || - fcntl(this->notify[0], F_SETFL, flags | O_NONBLOCK) == -1) - { - DBG1(DBG_LIB, "setting watcher notify pipe read-end non-blocking " - "failed: %s", strerror(errno)); - } - } - else + if (!create_notify(this)) { DBG1(DBG_LIB, "creating watcher notify pipe failed: %s", strerror(errno));