Loading lib/connect.c +61 −52 Original line number Diff line number Diff line Loading @@ -490,7 +490,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* check for connect without timeout as we want to return immediately */ rc = waitconnect(sockfd, 0); if(0 == rc) { if(WAITCONN_CONNECTED == rc) { if (verifyconnect(sockfd, NULL)) { /* we are connected, awesome! */ *connected = TRUE; Loading @@ -500,7 +500,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, 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)); Loading Loading @@ -549,22 +549,22 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; int rc, error; curl_socket_t sockfd = CURL_SOCKET_BAD; int aliasindex=0; char *hostname; int rc, error; int aliasindex; int num_addr; const char *hostname; bool conected; 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 */ Loading Loading @@ -600,31 +600,38 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } /* 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 */ Loading @@ -634,18 +641,24 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ 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 */ Loading @@ -661,7 +674,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ 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 Loading @@ -682,9 +695,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* 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! */ Loading @@ -694,26 +707,27 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } /* 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)) { conected = verifyconnect(sockfd, &error); if(!rc && conected) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ break; } /* nope, not connected for real */ rc = -1; } if(WAITCONN_TIMEOUT == rc) infof(data, "Timeout\n"); else verifyconnect(sockfd,&error); /* get non-blocking error */ infof(data, "%s\n", Curl_strerror(conn, error)); /* connect failed or timed out */ sclose(sockfd); Loading @@ -727,24 +741,19 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ 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) Loading lib/hostip.c +38 −0 Original line number Diff line number Diff line Loading @@ -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 <curl/mprintf.h> Loading Loading @@ -167,6 +168,43 @@ void Curl_global_host_cache_dtor(void) } } /* * 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). Loading lib/hostip.h +7 −5 Original line number Diff line number Diff line Loading @@ -102,6 +102,9 @@ curl_hash *Curl_mk_dnscache(void); /* 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); Loading Loading @@ -133,12 +136,11 @@ void Curl_hostent_relocate(struct hostent *h, long offset); 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); /* Loading lib/hostip6.c +0 −21 Original line number Diff line number Diff line Loading @@ -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 <curl/mprintf.h> Loading @@ -106,26 +105,6 @@ void Curl_freeaddrinfo(Curl_addrinfo *p) 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 Loading lib/hostthre.c +1 −1 Original line number Diff line number Diff line Loading @@ -142,7 +142,7 @@ static void dump_addrinfo (struct connectdata *conn, const struct addrinfo *ai) trace_it(" fam %2d, CNAME %s, ", ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>"); 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())); Loading Loading
lib/connect.c +61 −52 Original line number Diff line number Diff line Loading @@ -490,7 +490,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, /* check for connect without timeout as we want to return immediately */ rc = waitconnect(sockfd, 0); if(0 == rc) { if(WAITCONN_CONNECTED == rc) { if (verifyconnect(sockfd, NULL)) { /* we are connected, awesome! */ *connected = TRUE; Loading @@ -500,7 +500,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, 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)); Loading Loading @@ -549,22 +549,22 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; int rc, error; curl_socket_t sockfd = CURL_SOCKET_BAD; int aliasindex=0; char *hostname; int rc, error; int aliasindex; int num_addr; const char *hostname; bool conected; 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 */ Loading Loading @@ -600,31 +600,38 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } /* 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 */ Loading @@ -634,18 +641,24 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ 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 */ Loading @@ -661,7 +674,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ 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 Loading @@ -682,9 +695,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* 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! */ Loading @@ -694,26 +707,27 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ } } /* 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)) { conected = verifyconnect(sockfd, &error); if(!rc && conected) { /* we are connected, awesome! */ *connected = TRUE; /* this is a true connect */ break; } /* nope, not connected for real */ rc = -1; } if(WAITCONN_TIMEOUT == rc) infof(data, "Timeout\n"); else verifyconnect(sockfd,&error); /* get non-blocking error */ infof(data, "%s\n", Curl_strerror(conn, error)); /* connect failed or timed out */ sclose(sockfd); Loading @@ -727,24 +741,19 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ 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) Loading
lib/hostip.c +38 −0 Original line number Diff line number Diff line Loading @@ -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 <curl/mprintf.h> Loading Loading @@ -167,6 +168,43 @@ void Curl_global_host_cache_dtor(void) } } /* * 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). Loading
lib/hostip.h +7 −5 Original line number Diff line number Diff line Loading @@ -102,6 +102,9 @@ curl_hash *Curl_mk_dnscache(void); /* 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); Loading Loading @@ -133,12 +136,11 @@ void Curl_hostent_relocate(struct hostent *h, long offset); 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); /* Loading
lib/hostip6.c +0 −21 Original line number Diff line number Diff line Loading @@ -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 <curl/mprintf.h> Loading @@ -106,26 +105,6 @@ void Curl_freeaddrinfo(Curl_addrinfo *p) 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 Loading
lib/hostthre.c +1 −1 Original line number Diff line number Diff line Loading @@ -142,7 +142,7 @@ static void dump_addrinfo (struct connectdata *conn, const struct addrinfo *ai) trace_it(" fam %2d, CNAME %s, ", ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>"); 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())); Loading