diff options
author | corvid <devnull@localhost> | 2016-07-07 14:15:03 +0000 |
---|---|---|
committer | corvid <devnull@localhost> | 2016-07-07 14:15:03 +0000 |
commit | bd99337e366388866dfae20ecdc2e5ae58011320 (patch) | |
tree | 9a3db1d35525c6bef94844dcea5f8a50e7f23749 /src/IO/http.c | |
parent | d2500adc3523727581fcb417c77367b964124e3d (diff) |
try all IP addrs when connect()ing
as mentioned in the previous commit msg
Diffstat (limited to 'src/IO/http.c')
-rw-r--r-- | src/IO/http.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/src/IO/http.c b/src/IO/http.c index 30b36eb4..760497ec 100644 --- a/src/IO/http.c +++ b/src/IO/http.c @@ -63,6 +63,7 @@ typedef struct { 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 @@ static void Http_connect_socket_cb(int fd, void *data) 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_cb(int fd, void *data) */ static void Http_connect_socket(ChainLink *Info) { - int i; DilloHost *dh; + SocketData_t *S = a_Klist_get_data(ValidSocks, VOIDP2INT(Info->LocalKey)); + + for (; (dh = dList_nth_data(S->addr_list, S->addr_list_idx)); + S->addr_list_idx++) { #ifdef ENABLE_IPV6 - struct sockaddr_in6 name; + struct sockaddr_in6 name; #else - struct sockaddr_in name; + struct sockaddr_in name; #endif - socklen_t socket_len = 0; - SocketData_t *S = a_Klist_get_data(ValidSocks, VOIDP2INT(Info->LocalKey)); + socklen_t socket_len = 0; - /* TODO: iterate this address list until success, or end-of-list */ - for (i = 0; (dh = dList_nth_data(S->addr_list, i)); ++i) { + 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 @@ static void Http_connect_socket(ChainLink *Info) /* 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 @@ static void Http_dns_cb(int Status, Dlist *addr_list, void *data) /* 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)); |