From: Sven M. Hallberg Date: Mon, 1 Sep 2014 21:21:27 +0000 (+0200) Subject: add an alias for poll and implement pipe in terms of sockets X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=b9cafcae35680b33ba1e0d6da08a355c5b62faab;p=catta add an alias for poll and implement pipe in terms of sockets --- diff --git a/src/compat/windows/wincompat.c b/src/compat/windows/wincompat.c index 67cf853..4433b5b 100644 --- a/src/compat/windows/wincompat.c +++ b/src/compat/windows/wincompat.c @@ -208,6 +208,52 @@ int ioctl(int d, unsigned long request, int *p) return 0; } +int pipe(int pipefd[2]) +{ + int lsock = INVALID_SOCKET; + struct sockaddr_in laddr; + socklen_t laddrlen = sizeof(laddr); + + pipefd[0] = pipefd[1] = INVALID_SOCKET; + + // bind a listening socket to a TCP port on localhost + laddr.sin_family = AF_INET; + laddr.sin_port = 0; + laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + if((lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) + goto fail; + if(bind(lsock, (struct sockaddr *)&laddr, sizeof(laddr)) == SOCKET_ERROR) + goto fail; + if(listen(lsock, 1) == SOCKET_ERROR) + goto fail; + + // determine which address (i.e. port) we got bound to + if(getsockname(lsock, (struct sockaddr *)&laddr, &laddrlen) == SOCKET_ERROR) + goto fail; + assert(laddrlen == sizeof(laddr)); + laddr.sin_family = AF_INET; + laddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + // connect and accept + if((pipefd[0] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == SOCKET_ERROR) + goto fail; + if(connect(pipefd[0], (const struct sockaddr *)&laddr, sizeof(laddr)) == SOCKET_ERROR) + goto fail; + if((pipefd[1] = accept(lsock, NULL, NULL)) == SOCKET_ERROR) + goto fail; + + // close the listener + closesocket(lsock); + + return 0; + +fail: + errno = wsa_errno(); + closesocket(pipefd[0]); + closesocket(lsock); + return -1; +} + int uname(struct utsname *buf) { SYSTEM_INFO si; diff --git a/src/compat/windows/wincompat.h b/src/compat/windows/wincompat.h index b502022..c736f75 100644 --- a/src/compat/windows/wincompat.h +++ b/src/compat/windows/wincompat.h @@ -83,6 +83,14 @@ ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); int ioctl(int d, unsigned long request, int *p); +// Windows lacks poll, but WSAPoll is good enough for us. +#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout) + +// Windows lacks pipe. It has an equivalent CreatePipe but we really need +// something to give to WSAPoll, so we fake it with a local TCP socket. (ugh) +int pipe(int pipefd[2]); + + // Windows logically doesn't have uname, so we supply a replacement. struct utsname { diff --git a/src/simple-watch.c b/src/simple-watch.c index 253ad50..77da9f8 100644 --- a/src/simple-watch.c +++ b/src/simple-watch.c @@ -33,6 +33,8 @@ #include #include #include +#include "fdutil.h" // catta_set_nonblock +#include "internal.h" // closesocket struct CattaWatch { CattaSimplePoll *simple_poll; @@ -115,20 +117,6 @@ static void clear_wakeup(CattaSimplePoll *s) { break; } -static int set_nonblock(int fd) { - int n; - - assert(fd >= 0); - - if ((n = fcntl(fd, F_GETFL)) < 0) - return -1; - - if (n & O_NONBLOCK) - return 0; - - return fcntl(fd, F_SETFL, n|O_NONBLOCK); -} - static CattaWatch* watch_new(const CattaPoll *api, int fd, CattaWatchEvent event, CattaWatchCallback callback, void *userdata) { CattaWatch *w; CattaSimplePoll *s; @@ -326,8 +314,8 @@ CattaSimplePoll *catta_simple_poll_new(void) { return NULL; } - set_nonblock(s->wakeup_pipe[0]); - set_nonblock(s->wakeup_pipe[1]); + catta_set_nonblock(s->wakeup_pipe[0]); + catta_set_nonblock(s->wakeup_pipe[1]); s->api.userdata = s; @@ -374,10 +362,10 @@ void catta_simple_poll_free(CattaSimplePoll *s) { catta_free(s->pollfds); if (s->wakeup_pipe[0] >= 0) - close(s->wakeup_pipe[0]); + closesocket(s->wakeup_pipe[0]); if (s->wakeup_pipe[1] >= 0) - close(s->wakeup_pipe[1]); + closesocket(s->wakeup_pipe[1]); catta_free(s); }