[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

spipe optimization: avoid socketpair(2) when unnecessary



Hi, all,

Below is a quick hack to eliminate the socket pair used to
pushbits in the case that file descriptor 0 really is a
socket. I'm not convinced that this is the "best" way to
detect the socketness of fd 0, but at least I was able to
use the getsockopt result in a vaguely constructive way.

I built this on Linux, but see no reason for it not to
compile under FreeBSD.

Enjoy,
Bill


--- a/spipe/main.c
+++ b/spipe/main.c
@@ -56,6 +56,9 @@ main(int argc, char * argv[])
        struct proto_secret * K;
        int ch;
        int s[2];
+       int socket0 = 0;
+       int acceptcon;
+       int optsize;
 
        WARNP_INIT;
 
@@ -123,29 +126,40 @@ main(int argc, char * argv[])
        }
 
        /*
-        * Create a socket pair to push bits through.  The spiped protocol
-        * code expects to be handed a socket to read/write bits to, and our
-        * stdin/stdout might not be sockets (in fact, almost certainly aren't
-        * sockets); so we'll hand one end of the socket pair to the spiped
-        * protocol code and shuttle bits between stdin/stdout and the other
-        * end of the socket pair ourselves.
+        * If stdin is a socket, then we can pass
+        * it to the spiped protocol directly.
         */
-       if (socketpair(AF_UNIX, SOCK_STREAM, 0, s)) {
+       optsize = sizeof(acceptcon);
+       if (getsockopt(0, SOL_SOCKET, SO_DEBUG, &acceptcon, &optsize) == 0 && !acceptcon) {
+               socket0 = 1;
+       }
+       else if (socketpair(AF_UNIX, SOCK_STREAM, 0, s)) {
+               /*
+                * Create a socket pair to push bits through. The
+                * spiped protocol code expects to be handed a socket
+                * to read/write bits to, and our stdin/stdout aren't
+                * sockets (as is typical); so we'll hand one end of the
+                * socket pair to the spiped protocol code and shuttle
+                * bits between stdin/stdout and the other end of the
+                * socket pair ourselves.
+                */
                warnp("socketpair");
                exit(1);
        }
 
        /* Set up a connection. */
-       if (proto_conn_create(s[1], sas_t, 0, opt_f, K, opt_o,
+       if (proto_conn_create(socket0 ? 0 : s[1], sas_t, 0, opt_f, K, opt_o,
            callback_conndied, NULL)) {
                warnp("Could not set up connection");
                exit(1);
        }
 
-       /* Push bits from stdin into the socket. */
-       if (pushbits(STDIN_FILENO, s[0]) || pushbits(s[0], STDOUT_FILENO)) {
-               warnp("Could not push bits");
-               exit(1);
+       if (!socket0) {
+               /* Push bits from stdin into the socket. */
+               if (pushbits(STDIN_FILENO, s[0]) || pushbits(s[0], STDOUT_FILENO)) {
+                       warnp("Could not push bits");
+                       exit(1);
+               }
        }
 
        /* Loop until we die. *