changeset 4629:d4b595bd6fd8

try all IP addrs when connect()ing as mentioned in the previous commit msg
author corvid
date Do, 07 Jul 2016 14:15:03 +0000
parents e5b39cfdeb0b
children 29831152e985
files src/IO/http.c
diffstat 1 files changed, 28 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/IO/http.c	Do Jul 07 14:04:58 2016 +0000
+++ b/src/IO/http.c	Do Jul 07 14:15:03 2016 +0000
@@ -63,6 +63,7 @@
    DilloWeb *web;          /* reference to client's web structure */
    DilloUrl *url;
    Dlist *addr_list;       /* Holds the DNS answer */
+   int addr_list_idx;
    ChainLink *Info;        /* Used for CCC asynchronous operations */
    char *connected_to;     /* Used for per-server connection limit */
    uint_t connect_port;
@@ -544,7 +545,9 @@
             MSG("Http_connect_socket_cb connect ERROR: %s.\n",
                 dStrerror(connect_ret));
          }
-         a_Http_connect_done(S->SockFD, FALSE);
+         MSG("Http_connect_socket() will try another IP address.\n");
+         S->addr_list_idx++;
+         Http_connect_socket(S->Info);
       } else if (S->flags & HTTP_SOCKET_TLS) {
          Http_connect_tls(S->Info);
       } else {
@@ -559,18 +562,23 @@
  */
 static void Http_connect_socket(ChainLink *Info)
 {
-   int i;
    DilloHost *dh;
-#ifdef ENABLE_IPV6
-   struct sockaddr_in6 name;
-#else
-   struct sockaddr_in name;
-#endif
-   socklen_t socket_len = 0;
    SocketData_t *S = a_Klist_get_data(ValidSocks, VOIDP2INT(Info->LocalKey));
 
-   /* TODO: iterate this address list until success, or end-of-list */
-   for (i = 0; (dh = dList_nth_data(S->addr_list, i)); ++i) {
+   for (; (dh = dList_nth_data(S->addr_list, S->addr_list_idx));
+        S->addr_list_idx++) {
+#ifdef ENABLE_IPV6
+      struct sockaddr_in6 name;
+#else
+      struct sockaddr_in name;
+#endif
+      socklen_t socket_len = 0;
+
+      if (S->addr_list_idx > 0 && S->SockFD >= 0) {
+         /* clean up the previous one that failed */
+         Http_fd_map_remove_entry(S->SockFD);
+         dClose(S->SockFD);
+      }
       if ((S->SockFD = socket(dh->af, SOCK_STREAM, IPPROTO_TCP)) < 0) {
          MSG("Http_connect_socket socket() ERROR: %s\n", dStrerror(errno));
          continue;
@@ -619,20 +627,27 @@
          /* probably never succeeds immediately on any system */
          if (S->flags & HTTP_SOCKET_TLS) {
             Http_connect_tls(Info);
+            break;
          } else {
             a_Http_connect_done(S->SockFD, TRUE);
+            break;
          }
       } else {
          if (errno == EINPROGRESS) {
             a_IOwatch_add_fd(S->SockFD, DIO_WRITE, Http_connect_socket_cb,
                              Info->LocalKey);
             S->flags |= HTTP_SOCKET_IOWATCH_ACTIVE;
+            break;
          } else {
             MSG("Http_connect_socket connect ERROR: %s\n", dStrerror(errno));
-            a_Http_connect_done(S->SockFD, FALSE);
+            MSG("We will try another IP address.\n");
          }
       }
-      return;
+   } /* for */
+
+   if (S->addr_list_idx >= dList_length(S->addr_list) ) {
+      MSG("Http_connect_socket ran out of IP addrs to try.\n");
+      a_Http_connect_done(S->SockFD, FALSE);
    }
 }
 
@@ -729,6 +744,7 @@
 
             /* Successful DNS answer; save the IP */
             S->addr_list = addr_list;
+            S->addr_list_idx = 0;
             clean_up = FALSE;
             srv = Http_server_get(host, S->connect_port,
                                  (S->flags & HTTP_SOCKET_TLS));