diff -u3 -Hb CVS-latest/lib/connect.c lib/connect.c --- CVS-latest/lib/connect.c Tue Jun 08 17:05:20 2004 +++ lib/connect.c Wed Jun 09 22:24:09 2004 @@ -500,7 +500,7 @@ failf(data, "Connection failed"); return CURLE_COULDNT_CONNECT; } - else if(1 != rc) { + else if(WAITCONN_TIMEOUT != rc) { int error = Curl_ourerrno(); failf(data, "Failed connect to %s:%d; %s", conn->host.name, conn->port, Curl_strerror(conn,error)); @@ -549,22 +549,21 @@ bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; + curl_socket_t sockfd = CURL_SOCKET_BAD; int rc, error; - curl_socket_t sockfd= CURL_SOCKET_BAD; - int aliasindex=0; - char *hostname; + int aliasindex; + int num_addr; + const char *hostname; + Curl_ipconnect *curr_addr; struct timeval after; struct timeval before = Curl_tvnow(); -#ifdef ENABLE_IPV6 - struct addrinfo *ai; -#endif - /************************************************************* * Figure out what maximum time we have left *************************************************************/ - long timeout_ms=300000; /* milliseconds, default to five minutes */ + long timeout_ms=300000; /* milliseconds, default to five minutes total */ + long timeout_per_addr; *connected = FALSE; /* default to not connected */ @@ -600,31 +599,37 @@ } } + /* Max time for each address */ + num_addr = Curl_num_addresses(remotehost->addr); + timeout_per_addr = timeout_ms / num_addr; + hostname = data->change.proxy?conn->proxy.name:conn->host.name; + infof(data, "About to connect() to %s port %d\n", hostname, port); + /* Below is the loop that attempts to connect to all IP-addresses we + * know for the given host. One by one until one IP succeedes. + */ #ifdef ENABLE_IPV6 /* * Connecting with a getaddrinfo chain */ - for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) { - sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sockfd == CURL_SOCKET_BAD) + for (curr_addr = remotehost->addr, aliasindex=0; curr_addr; + curr_addr = curr_addr->ai_next, aliasindex++) { + sockfd = socket(curr_addr->ai_family, curr_addr->ai_socktype, curr_addr->ai_protocol); + if (sockfd == CURL_SOCKET_BAD) { + timeout_per_addr += timeout_per_addr / (num_addr - aliasindex); continue; + } - else if(data->set.tcp_nodelay) - Curl_setNoDelay(conn, sockfd); #else /* * Connecting with old style IPv4-only support */ - - /* This is the loop that attempts to connect to all IP-addresses we - know for the given host. One by one. */ - for(rc=-1, aliasindex=0; - rc && (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; - aliasindex++) { + curr_addr = (Curl_ipconnect*)remotehost->addr->h_addr_list[0]; + for(aliasindex=0; curr_addr; + curr_addr=(Curl_ipconnect*)remotehost->addr->h_addr_list[++aliasindex]) { struct sockaddr_in serv_addr; /* create an IPv4 TCP socket */ @@ -634,18 +639,24 @@ return CURLE_COULDNT_CONNECT; /* big time error */ } - else if(data->set.tcp_nodelay) - Curl_setNoDelay(conn, sockfd); - /* nasty address work before connect can be made */ memset((char *) &serv_addr, '\0', sizeof(serv_addr)); - memcpy((char *)&(serv_addr.sin_addr), - (struct in_addr *)remotehost->addr->h_addr_list[aliasindex], + memcpy((char *)&(serv_addr.sin_addr), curr_addr, sizeof(struct in_addr)); serv_addr.sin_family = remotehost->addr->h_addrtype; serv_addr.sin_port = htons((unsigned short)port); #endif + { + char addr_buf[256] = ""; + + Curl_printable_address(curr_addr, addr_buf, sizeof(addr_buf)); + infof(data, " Trying %s... ", addr_buf); + } + + if(data->set.tcp_nodelay) + Curl_setNoDelay(conn, sockfd); + if(conn->data->set.device) { /* user selected to bind the outgoing socket to a specified "device" before doing connect */ @@ -661,7 +672,7 @@ a defined macro on some platforms and some compilers don't like to mix #ifdefs with macro usage! (AmigaOS is one such platform) */ #ifdef ENABLE_IPV6 - rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen); + rc = connect(sockfd, curr_addr->ai_addr, curr_addr->ai_addrlen); #else rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); #endif @@ -682,9 +693,9 @@ /* asynchronous connect, wait for connect or timeout */ if(data->state.used_interface == Curl_if_multi) /* don't hang when doing multi */ - timeout_ms = 0; + timeout_per_addr = timeout_ms = 0; - rc = waitconnect(sockfd, timeout_ms); + rc = waitconnect(sockfd, timeout_per_addr); break; default: /* unknown error, fallthrough and try another address! */ @@ -694,26 +705,23 @@ } } - /* The '1 == rc' comes from the waitconnect(), and not from connect(). - We can be sure of this since connect() cannot return 1. */ - if((1 == rc) && (data->state.used_interface == Curl_if_multi)) { + /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from + connect(). We can be sure of this since connect() cannot return 1. */ + if((WAITCONN_TIMEOUT == rc) && (data->state.used_interface == Curl_if_multi)) { /* Timeout when running the multi interface, we return here with a CURLE_OK return code. */ rc = 0; break; } - if(0 == rc) { - if (verifyconnect(sockfd,NULL)) { + if(0 == rc && verifyconnect(sockfd,NULL)) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ break; } - /* nope, not connected for real */ - rc = -1; - } - else - verifyconnect(sockfd,&error); /* get non-blocking error */ + + verifyconnect(sockfd, &error); /* get non-blocking error */ + infof(data, "%s\n", Curl_strerror(conn,error)); /* connect failed or timed out */ sclose(sockfd); @@ -727,24 +735,19 @@ return CURLE_OPERATION_TIMEOUTED; } before = after; - } + } /* end of connect-to-each-address loop */ + if (sockfd == CURL_SOCKET_BAD) { /* no good connect was made */ - *sockconn = -1; - failf(data, "Connect failed; %s", Curl_strerror(conn,error)); + *sockconn = CURL_SOCKET_BAD; return CURLE_COULDNT_CONNECT; } /* leave the socket in non-blocking mode */ /* store the address we use */ - if(addr) { -#ifdef ENABLE_IPV6 - *addr = ai; -#else - *addr = (struct in_addr *)remotehost->addr->h_addr_list[aliasindex]; -#endif - } + if(addr) + *addr = curr_addr; /* allow NULL-pointers to get passed in */ if(sockconn) diff -u3 -Hb CVS-latest/lib/hostip.c lib/hostip.c --- CVS-latest/lib/hostip.c Tue May 18 00:07:43 2004 +++ lib/hostip.c Wed Jun 09 22:37:02 2004 @@ -79,6 +79,7 @@ #include "share.h" #include "strerror.h" #include "url.h" +#include "inet_ntop.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -168,6 +169,43 @@ } /* + * Return # of adresses in a Curl_addrinfo struct + */ +int Curl_num_addresses(const Curl_addrinfo *addr) +{ + int i; + +#ifdef ENABLE_IPV6 + for (i = 0; addr; addr = addr->ai_next, i++) +#else + for (i = 0; addr->h_addr_list[i]; i++) +#endif + ; + return (i); +} + +/* + * Curl_printable_address() returns a printable version of the 1st + * address given in the 2nd argument. The result will be stored in + * the buf that is bufsize bytes big. + * + * If the conversion fails, it returns NULL. + */ +const char *Curl_printable_address(const Curl_ipconnect *ip, + char *buf, size_t bufsize) +{ +#ifdef CURLRES_IPV6 + const void *ip4 = &((const struct sockaddr_in*)ip->ai_addr)->sin_addr; + const void *ip6 = &((const struct sockaddr_in6*)ip->ai_addr)->sin6_addr; + int af = ip->ai_family; + + return Curl_inet_ntop(af, af == AF_INET6 ? ip6 : ip4, buf, bufsize); +#else + return Curl_inet_ntop(AF_INET, ip, buf, bufsize); +#endif +} + +/* * Count the number of characters that an integer would use in a string * (base 10). */ diff -u3 -Hb CVS-latest/lib/hostip.h lib/hostip.h --- CVS-latest/lib/hostip.h Mon Apr 26 16:18:00 2004 +++ lib/hostip.h Wed Jun 09 21:09:34 2004 @@ -102,6 +102,9 @@ /* prune old entries from the DNS cache */ void Curl_hostcache_prune(struct SessionHandle *data); +/* Return # of adresses in a Curl_addrinfo struct */ +int Curl_num_addresses (const Curl_addrinfo *addr); + #ifdef CURLDEBUG void curl_dofreeaddrinfo(struct addrinfo *freethis, int line, const char *source); @@ -133,12 +136,11 @@ Curl_addrinfo *Curl_addrinfo_copy(Curl_addrinfo *orig); /* - * (IPv6) Curl_printable_address() returns a printable version of the - * ai->ai_addr address given in the 2nd argument. The first should be the - * ai->ai_family and the result will be stored in the buf that is bufsize - * bytes big. + * Curl_printable_address() returns a printable version of the + * 1st address given in the 2nd argument. The result will be stored + * in the buf that is bufsize bytes big. */ -const char *Curl_printable_address(int af, void *addr, +const char *Curl_printable_address(const Curl_ipconnect *ip, char *buf, size_t bufsize); /* diff -u3 -Hb CVS-latest/lib/hostip6.c lib/hostip6.c --- CVS-latest/lib/hostip6.c Tue May 11 13:30:23 2004 +++ lib/hostip6.c Wed Jun 09 21:20:54 2004 @@ -79,7 +79,6 @@ #include "share.h" #include "strerror.h" #include "url.h" -#include "inet_ntop.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -106,26 +105,6 @@ freeaddrinfo(p); } -/* - * Curl_printable_address() returns a printable version of the ai->ai_addr - * address given in the 2nd argument. The first should be the ai->ai_family - * and the result will be stored in the buf that is bufsize bytes big. - * - * If the conversion fails, it returns NULL. - */ -const char *Curl_printable_address(int af, void *addr, - char *buf, size_t bufsize) -{ - const struct in_addr *addr4 = - &((const struct sockaddr_in*)addr)->sin_addr; - const struct in6_addr *addr6 = - &((const struct sockaddr_in6*)addr)->sin6_addr; - return Curl_inet_ntop(af, af == AF_INET6 ? - (const void *)addr6 : - (const void *)addr4, buf, bufsize); -} - - #ifdef CURLRES_ASYNCH /* * Curl_addrinfo_copy() is used by the asynch callback to copy a given diff -u3 -Hb CVS-latest/lib/hostthre.c lib/hostthre.c --- CVS-latest/lib/hostthre.c Tue May 11 13:30:23 2004 +++ lib/hostthre.c Wed Jun 09 21:15:59 2004 @@ -142,7 +142,7 @@ trace_it(" fam %2d, CNAME %s, ", ai->ai_family, ai->ai_canonname ? ai->ai_canonname : ""); - if (Curl_printable_address(ai->ai_family, ai->ai_addr, buf, sizeof(buf))) + if (Curl_printable_address(ai, buf, sizeof(buf))) trace_it("%s\n", buf); else trace_it("failed; %s\n", Curl_strerror(conn,WSAGetLastError())); diff -u3 -Hb CVS-latest/lib/url.c lib/url.c --- CVS-latest/lib/url.c Wed Jun 09 10:23:55 2004 +++ lib/url.c Wed Jun 09 22:30:41 2004 @@ -1990,22 +1990,18 @@ static void verboseconnect(struct connectdata *conn) { struct SessionHandle *data = conn->data; - const char *host=NULL; - char addrbuf[256]; - - /* Get a printable version of the network address. */ + char addrbuf[256] = ""; #ifdef ENABLE_IPV6 - struct addrinfo *ai = conn->serv_addr; - host = Curl_printable_address(ai->ai_family, ai->ai_addr, - addrbuf, sizeof(addrbuf)); + const Curl_ipconnect *addr = conn->serv_addr; #else - struct in_addr in; - (void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr)); - host = Curl_inet_ntop(AF_INET, &in, addrbuf, sizeof(addrbuf)); + const Curl_ipconnect *addr = &conn->serv_addr.sin_addr; #endif + + /* Get a printable version of the network address. */ + Curl_printable_address(addr, addrbuf, sizeof(addrbuf)); infof(data, "Connected to %s (%s) port %d\n", - conn->bits.httpproxy?conn->proxy.dispname:conn->host.dispname, - host?host:"", conn->port); + conn->bits.httpproxy ? conn->proxy.dispname : conn->host.dispname, + addrbuf[0] ? addrbuf : "??", conn->port); } /*