You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/10/13 15:47:31 UTC

svn commit: r824758 - /commons/sandbox/runtime/trunk/src/main/native/os/win32/pipe.c

Author: mturk
Date: Tue Oct 13 13:47:31 2009
New Revision: 824758

URL: http://svn.apache.org/viewvc?rev=824758&view=rev
Log:
Port APR's socket pipe

Modified:
    commons/sandbox/runtime/trunk/src/main/native/os/win32/pipe.c

Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/pipe.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/pipe.c?rev=824758&r1=824757&r2=824758&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/pipe.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/pipe.c Tue Oct 13 13:47:31 2009
@@ -28,3 +28,136 @@
  * Windows pipe functions
  *
  */
+
+static volatile LONG pipe_id = 0;
+static apr_status_t create_socket_pipe(SOCKET *rd, SOCKET *wr)
+{
+    static int id = 0;
+    FD_SET rs;
+    SOCKET ls;
+    struct timeval socktm;
+    struct sockaddr_in pa;
+    struct sockaddr_in la;
+    struct sockaddr_in ca;
+    int nrd;
+    int rv = 0;
+    int ll = (int)sizeof(la);
+    int cl = (int)sizeof(ca);
+    int bm = 1;
+    int uid[2];
+    int iid[2];
+
+    *rd = INVALID_SOCKET;
+    *wr = INVALID_SOCKET;
+
+    /* Create the unique socket identifier
+     * so that we know the connection originated
+     * from us.
+     */
+    uid[0] = GetCurrentProcessId();
+    uid[1] = (int)InterlockedIncrement(&pipe_id);
+    if ((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
+        return ACR_GET_NETOS_ERROR();
+    }
+
+    pa.sin_family = AF_INET;
+    pa.sin_port   = 0;
+    pa.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+    if (bind(ls, (SOCKADDR *)&pa, sizeof(pa)) == SOCKET_ERROR) {
+        rv =  ACR_GET_NETOS_ERROR();
+        goto cleanup;
+    }
+    if (getsockname(ls, (SOCKADDR *)&la, &ll) == SOCKET_ERROR) {
+        rv =  ACR_GET_NETOS_ERROR();
+        goto cleanup;
+    }
+    if (listen(ls, 1) == SOCKET_ERROR) {
+        rv =  ACR_GET_NETOS_ERROR();
+        goto cleanup;
+    }
+    if ((*wr = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
+        rv = ACR_GET_NETOS_ERROR();
+        goto cleanup;
+    }
+    if (connect(*wr, (SOCKADDR *)&la, sizeof(la)) == SOCKET_ERROR) {
+        rv =  ACR_GET_NETOS_ERROR();
+        goto cleanup;
+    }
+    if (send(*wr, (char *)uid, sizeof(uid), 0) != sizeof(uid)) {
+        if ((rv =  ACR_GET_NETOS_ERROR()) == 0) {
+            rv = ACR_EINCOMPLETE;
+        }
+        goto cleanup;
+    }
+    if (ioctlsocket(ls, FIONBIO, &bm) == SOCKET_ERROR) {
+        rv = ACR_GET_NETOS_ERROR();
+        goto cleanup;
+    }
+    for (;;) {
+        int ns;
+        /* Listening socket is nonblocking by now.
+         * The accept should create the socket
+         * immediatelly because we are connected already.
+         * However on buys systems this can take a while
+         * until winsock gets a chance to handle the events.
+         */
+        FD_ZERO(&rs);
+        FD_SET(ls, &rs);
+
+        socktm.tv_sec  = 1;
+        socktm.tv_usec = 0;
+        if ((ns = select(0, &rs, NULL, NULL, &socktm)) == SOCKET_ERROR) {
+            /* Accept still not signaled */
+            Sleep(100);
+            continue;
+        }
+        if (ns == 0) {
+            /* No connections in the last second */
+            continue;
+        }
+        if ((*rd = accept(ls, (SOCKADDR *)&ca, &cl)) == INVALID_SOCKET) {
+            rv =  ACR_GET_NETOS_ERROR();
+            goto cleanup;
+        }
+        /* Verify the connection by reading the send identification.
+         */
+        nrd = recv(*rd, (char *)iid, sizeof(iid), 0);
+        if (nrd == sizeof(iid)) {
+            if (memcmp(uid, iid, sizeof(uid)) == 0) {
+                /* Wow, we recived what we send.
+                 * Put read side of the pipe to the blocking
+                 * mode and return.
+                 */
+                bm = 0;
+                if (ioctlsocket(*rd, FIONBIO, &bm) == SOCKET_ERROR) {
+                    rv = ACR_GET_NETOS_ERROR();
+                    goto cleanup;
+                }
+                break;
+            }
+        }
+        else if (nrd == SOCKET_ERROR) {
+            rv =  ACR_GET_NETOS_ERROR();
+            goto cleanup;
+        }
+        closesocket(*rd);
+    }
+    /* We don't need the listening socket any more
+     */
+    closesocket(ls);
+    return 0;
+
+cleanup:
+    /* Don't leak resources on failure
+     */
+    if (*rd != INVALID_SOCKET)
+        closesocket(*rd);
+    if (*wr != INVALID_SOCKET)
+        closesocket(*wr);
+
+    *rd = INVALID_SOCKET;
+    *wr = INVALID_SOCKET;
+    closesocket(ls);
+    return rv;
+}