[or-cvs] Adopt socketpair implementation from perl. For now, always ...

Nick Mathewson nickm at seul.org
Tue Aug 12 07:43:17 UTC 2003


Update of /home/or/cvsroot/src/common
In directory moria.mit.edu:/tmp/cvs-serv4331/src/common

Modified Files:
	util.c util.h 
Log Message:
Adopt socketpair implementation from perl. For now, always use it.

Index: util.c
===================================================================
RCS file: /home/or/cvsroot/src/common/util.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- util.c	12 Aug 2003 07:01:20 -0000	1.10
+++ util.c	12 Aug 2003 07:43:15 -0000	1.11
@@ -18,6 +18,15 @@
 #ifdef HAVE_FCNTL_H
 #include <fcntl.h>
 #endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
@@ -25,6 +34,8 @@
 #include <unistd.h>
 #endif
 #include <assert.h>
+#include <errno.h>
+#include <string.h>
 
 #include "util.h"
 #include "log.h"
@@ -145,5 +156,98 @@
   _endthread();
 #else
   exit(0);
+#endif
+}
+
+
+/* Fake socket pair over TCP.  Code adapted from perl 5.8.0's util.c */
+int
+tor_socketpair(int family, int type, int protocol, int fd[2])
+{
+#ifdef HAVE_SOCKETPAIR_XXX
+    /* For testing purposes, we never fall back to real socketpairs. */
+    return socketpair(family, type, protocol, fd);
+#else
+    int listener = -1;
+    int connector = -1;
+    int acceptor = -1;
+    struct sockaddr_in listen_addr;
+    struct sockaddr_in connect_addr;
+    size_t size;
+    
+    if (protocol
+#ifdef AF_UNIX
+        || family != AF_UNIX
+#endif
+        ) {
+        errno = EAFNOSUPPORT;
+        return -1;
+    }
+    if (!fd) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    listener = socket(AF_INET, type, 0);
+    if (listener == -1)
+      return -1;
+    memset (&listen_addr, 0, sizeof (listen_addr));
+    listen_addr.sin_family = AF_INET;
+    listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+    listen_addr.sin_port = 0;   /* kernel choses port.  */
+    if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
+        == -1)
+        goto tidy_up_and_fail;
+    if (listen(listener, 1) == -1)
+        goto tidy_up_and_fail;
+
+    connector = socket(AF_INET, type, 0);
+    if (connector == -1)
+        goto tidy_up_and_fail;
+    /* We want to find out the port number to connect to.  */
+    size = sizeof (connect_addr);
+    if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
+        goto tidy_up_and_fail;
+    if (size != sizeof (connect_addr))
+        goto abort_tidy_up_and_fail;
+    if (connect(connector, (struct sockaddr *) &connect_addr,
+                sizeof (connect_addr)) == -1)
+        goto tidy_up_and_fail;
+
+    size = sizeof (listen_addr);
+    acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
+    if (acceptor == -1)
+        goto tidy_up_and_fail;
+    if (size != sizeof(listen_addr))
+        goto abort_tidy_up_and_fail;
+    close(listener);
+    /* Now check we are talking to ourself by matching port and host on the
+       two sockets.  */
+    if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
+        goto tidy_up_and_fail;
+    if (size != sizeof (connect_addr)
+        || listen_addr.sin_family != connect_addr.sin_family
+        || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
+        || listen_addr.sin_port != connect_addr.sin_port) {
+        goto abort_tidy_up_and_fail;
+    }
+    fd[0] = connector;
+    fd[1] = acceptor;
+    return 0;
+
+  abort_tidy_up_and_fail:
+  errno = ECONNABORTED; /* I hope this is portable and appropriate.  */
+  tidy_up_and_fail:
+    {
+        int save_errno = errno;
+        if (listener != -1)
+            close(listener);
+        if (connector != -1)
+	    close(connector);
+        if (acceptor != -1)
+            close(acceptor);
+        errno = save_errno;
+        return -1;
+    }
 #endif
 }

Index: util.h
===================================================================
RCS file: /home/or/cvsroot/src/common/util.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- util.h	12 Aug 2003 07:01:20 -0000	1.5
+++ util.h	12 Aug 2003 07:43:15 -0000	1.6
@@ -52,4 +52,6 @@
 int spawn_func(int (*func)(void *), void *data);
 void spawn_exit();
 
+int tor_socketpair(int family, int type, int protocol, int fd[2]);
+
 #endif



More information about the tor-commits mailing list