]> git.meshlink.io Git - catta/blobdiff - src/compat/windows/wincompat.c
wrap lifetimes of CattaServer and CattaSimplePoll in WSAStartup/WSACleanup
[catta] / src / compat / windows / wincompat.c
index 67cf85364b9047097d82ec6434128c8c31871ecb..4e3145e6e672c73bee5d40d9af5bdaf4c6f4f86b 100644 (file)
@@ -4,6 +4,8 @@
 #include <assert.h>
 #include <stdint.h>
 
+#include <catta/log.h>
+
 // helper: convert WSAGetLastError() to an errno constant
 static int wsa_errno(void)
 {
@@ -29,6 +31,21 @@ static int wsa_errno(void)
     }
 }
 
+void winsock_init(void)
+{
+    WSADATA wsa;
+    int error;
+
+    if((error = WSAStartup(MAKEWORD(2,2), &wsa)) != 0)
+        catta_log_error("WSAStartup() failed: %d", error);
+}
+
+void winsock_exit(void)
+{
+    if(WSACleanup() == SOCKET_ERROR)
+        catta_log_warn("WSACleanup() failed: %d", WSAGetLastError());
+}
+
 ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
 {
     LPFN_WSARECVMSG WSARecvMsg = NULL;
@@ -208,6 +225,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;