Revision: 14855
Author:   adrian.chadd
Date:     Sat Jul  2 01:02:04 2011
Log:      Begin fleshing out the replacement commConnectStart() API.


http://code.google.com/p/lusca-cache/source/detail?r=14855

Modified:
 /playpen/LUSCA_HEAD_ipv6/src/comm2.c
 /playpen/LUSCA_HEAD_ipv6/src/protos.h

=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/comm2.c        Fri Jul  1 23:41:29 2011
+++ /playpen/LUSCA_HEAD_ipv6/src/comm2.c        Sat Jul  2 01:02:04 2011
@@ -57,36 +57,46 @@
     int tries;
     int addrcount;
     int connstart;
+    const char *comm_note;
+    int comm_tos;
+    int comm_flags;
 } ConnectStateDataNew;

 static PF commConnectFree;
 static PF commConnectHandle;
 static IPH commConnectDnsHandle;
 static void commConnectCallback(ConnectStateDataNew * cs, int status);
-static int commResetFD(ConnectStateDataNew * cs);
 static int commRetryConnect(ConnectStateDataNew * cs);
 CBDATA_TYPE(ConnectStateDataNew);

+/*
+ * Attempt to connect to host:port.
+ * addr6 can specify a fixed v4 or v6 address; or NULL for host lookup.
+ *
+ * flags: additional comm flags
+ * tos: TOS for newly created sockets
+ * note: note for newly created sockets
+ */
 void
-commConnectStartNew(int fd, const char *host, u_short port, CNCB * callback,
-    void *data, sqaddr_t *addr6)
+commConnectStartNew(const char *host, u_short port, CNCB * callback,
+    void *data, sqaddr_t *addr6, int flags, int tos, const char *note)
 {
     ConnectStateDataNew *cs;
-    debug(5, 3) ("commConnectStart: FD %d, %s:%d\n", fd, host, (int) port);
-    /*
- * XXX this wasn't ever here (it was in comm_init()) so its possible this may slow things - * XXX down a little; eventually this should migrate to a squid-specific comm_init() - * XXX (comm_local_init() ? comm_connect_init()? so its called once like the old init
-     * XXX function was. -adrian
-     */
+ debug(5, 3) ("%s: new connection to %s:%d\n", __func__, host, (int) port);
     CBDATA_INIT_TYPE(ConnectStateDataNew);
     cs = cbdataAlloc(ConnectStateDataNew);
-    cs->fd = fd;
+    cs->fd = -1;            /* Will need to be created */
     cs->host = xstrdup(host);
     cs->port = port;
     cs->callback = callback;
     cs->data = data;
+    cs->comm_flags = flags;
+    cs->comm_tos = tos;
+    cs->comm_flags = flags;
+
     sqinet_init(&cs->in_addr6);
+
+    /* Do we have a local address? Use it */
     if (addr6 != NULL) {
         sqinet_init(&cs->in_addr6);
        sqinet_copy(&cs->in_addr6, addr6);
@@ -95,10 +105,66 @@
        cs->addrcount = 0;
     }
     cbdataLock(cs->data);
-    comm_add_close_handler(fd, commConnectFree, cs);
+
+    /* Begin the host lookup */
     ipcache_nbgethostbyname(host, commConnectDnsHandle, cs);
 }

+
+/*
+ * Close the destination socket.
+ */
+static void
+commConnectCloseSocket(ConnectStateDataNew *cs)
+{
+       if (cs->fd == -1)
+               return;
+       debug(5, 1) ("%s: FD (%d): closing\n", __func__, cs->fd);
+       comm_remove_close_handler(cs->fd, commConnectFree, cs);
+       comm_close(cs->fd);
+       cs->fd = -1;
+}
+
+/*
+ * Create a comm socket matching the destination
+ * record.
+ */
+static int
+commConnectCreateSocket(ConnectStateDataNew *cs)
+{
+       int af;
+       sqaddr_t a;
+
+       /* Does a socket exist? It shouldn't at this point. */
+       if (cs->fd != -1) {
+               debug(5, 1) ("%s: FD (%d) exists when it shouldn't!\n",
+                   __func__, cs->fd);
+               comm_remove_close_handler(cs->fd, commConnectFree, cs);
+               comm_close(cs->fd);
+               cs->fd = -1;
+       }
+
+       /* Create a new socket for the given destination address */
+       af = sqinet_get_family(&cs->in_addr6);
+
+       /* XXX there's not outgoing address support at the present moment */
+       sqinet_init(&a);
+       sqinet_set_family(&a, af);
+       sqinet_set_anyaddr(&a);
+       cs->fd = comm_open6(SOCK_STREAM, IPPROTO_TCP, &a,
+           cs->comm_flags | COMM_NONBLOCKING, cs->comm_tos, cs->comm_note);
+       sqinet_done(&a);
+
+       /* Did socket creation fail? Then pass it up the stack */
+       if (cs->fd == -1)
+               return -1;
+
+       /* Setup the close handler */
+       comm_add_close_handler(cs->fd, commConnectFree, cs);
+
+       return cs->fd;
+}
+
 static void
 commConnectDnsHandle(const ipcache_addrs * ia, void *data)
 {
@@ -108,6 +174,11 @@
        if (cs->addrcount > 0) {
            fd_table[cs->fd].flags.dnsfailed = 1;
            cs->connstart = squid_curtime;
+           if (commConnectCreateSocket(cs) == -1) {
+               debug(5, 3) ("%s: socket problem: %s\n", __func__, cs->host);
+               commConnectCallback(cs, COMM_ERR_CONNECT);
+               return;
+           }
            commConnectHandle(cs->fd, cs);
        } else {
            debug(5, 3) ("commConnectDnsHandle: Unknown host: %s\n", cs->host);
@@ -128,6 +199,13 @@
        ipcacheCycleAddr(cs->host, NULL);
     cs->addrcount = ia->count;
     cs->connstart = squid_curtime;
+
+    /* Create the initial outbound socket */
+    if (commConnectCreateSocket(cs) == -1) {
+        debug(5, 3) ("%s: socket problem: %s\n", __func__, cs->host);
+        commConnectCallback(cs, COMM_ERR_CONNECT);
+        return;
+    }
     commConnectHandle(cs->fd, cs);
 }

@@ -159,88 +237,6 @@
     cbdataFree(cs);
 }

-/* Reset FD so that we can connect() again */
-static int
-commResetFD(ConnectStateDataNew * cs)
-{
-    int fd2;
-    fde *F;
-    if (!cbdataValid(cs->data))
-       return 0;
-    fd2 = socket(AF_INET, SOCK_STREAM, 0);
-    CommStats.syscalls.sock.sockets++;
-    if (fd2 < 0) {
-       debug(5, 0) ("commResetFD: socket: %s\n", xstrerror());
-       if (ENFILE == errno || EMFILE == errno)
-           fdAdjustReserved();
-       return 0;
-    }
- /* We are about to close the fd (dup2 over it). Unregister from the event loop */
-    commSetEvents(cs->fd, 0, 0);
-#ifdef _SQUID_MSWIN_
-    /* On Windows dup2() can't work correctly on Sockets, the          */
-    /* workaround is to close the destination Socket before call them. */
-    close(cs->fd);
-#endif
-    if (dup2(fd2, cs->fd) < 0) {
-       debug(5, 0) ("commResetFD: dup2: %s\n", xstrerror());
-       if (ENFILE == errno || EMFILE == errno)
-           fdAdjustReserved();
-       close(fd2);
-       return 0;
-    }
-    close(fd2);
-    F = &fd_table[cs->fd];
-    fd_table[cs->fd].flags.called_connect = 0;
-
-    /*
- * The original code assumed the current local port equals the previous local port - * Assume this for now and bite whatever occasional failure will happen because commResetFD()
-     * results in some re-attempt to use a now-allocated local port.
-     *
- * This should later on be modified to re-use the -original- socket address (with or without - * an explicitly set port) rather than F->local_address and F->local_port, which may have been
-     * updated after the initial local bind() and subsequent getsockname().
-     */
-
-    /*
-     * yuck, this has assumptions about comm_open() arguments for
-     * the original socket
-     */
-    assert(F->local_port == sqinet_get_port(&F->local_address));
-    if (F->flags.tproxy_rem) {
- debug(5, 3) ("commResetFD: FD %d: re-starting a tproxy'ed upstream connection\n", cs->fd);
-        if (comm_ips_bind_rem(cs->fd, &F->local_address) != COMM_OK) {
- debug(5, 1) ("commResetFD: FD %d: TPROXY comm_ips_bind_rem() failed? Why?\n", cs->fd);
-            return 0;
-        }
-    } else if (commBind(cs->fd, &F->local_address) != COMM_OK) {
-       debug(5, 0) ("commResetFD: bind: %s\n", xstrerror());
-       return 0;
-    }
-#ifdef IP_TOS
-    if (F->tos) {
-       int tos = F->tos;
- if (setsockopt(cs->fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0) - debug(5, 1) ("commResetFD: setsockopt(IP_TOS) on FD %d: %s\n", cs->fd, xstrerror());
-    }
-#endif
-    if (F->flags.close_on_exec)
-       commSetCloseOnExec(cs->fd);
-    if (F->flags.nonblocking)
-       commSetNonBlocking(cs->fd);
-#ifdef TCP_NODELAY
-    if (F->flags.nodelay)
-       commSetTcpNoDelay(cs->fd);
-#endif
-
-    /* Register the new FD with the event loop */
-    commUpdateEvents(cs->fd);
-    if (Config.tcpRcvBufsz > 0)
-       commSetTcpRcvbuf(cs->fd, Config.tcpRcvBufsz);
-    return 1;
-}
-
 static int
 commRetryConnect(ConnectStateDataNew * cs)
 {
@@ -254,7 +250,12 @@
        if (cs->tries > cs->addrcount)
            return 0;
     }
-    return commResetFD(cs);
+
+    /* The next retry may be a different protocol family */
+    commConnectCloseSocket(cs);
+    if (commConnectCreateSocket(cs) != -1)
+        return 0;
+    return 1;
 }

 static void
@@ -273,6 +274,12 @@

     ConnectStateDataNew *cs = data;

+    if (cs->fd == -1) {
+        debug(5, 1) ("%s: shouldn't have FD=-1, barfing\n", __func__);
+        commConnectCallback(cs, COMM_ERR_CONNECT);
+        return;
+    }
+
/* Create a temporary sqaddr_t which also contains the port we're connecting to */
     /* This should eventually just be folded into cs->in_addr6 -adrian */
     sqinet_init(&a);
=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/protos.h       Fri Jul  1 23:41:29 2011
+++ /playpen/LUSCA_HEAD_ipv6/src/protos.h       Sat Jul  2 01:02:04 2011
@@ -1062,8 +1062,8 @@
 extern void commConnectStart(int fd, const char *, u_short, CNCB *, void *,
     sqaddr_t *addr6);
 extern void
-commConnectStartNew(int fd, const char *host, u_short port, CNCB * callback,
-    void *data, sqaddr_t *addr6);
+commConnectStartNew(const char *host, u_short port, CNCB * callback,
+    void *data, sqaddr_t *addr6, int flags, int tos, const char *note);

 /* client_side_location_rewrite.c */
 extern void clientHttpLocationRewriteCheck(clientHttpRequest * http);

--
You received this message because you are subscribed to the Google Groups 
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/lusca-commit?hl=en.

Reply via email to