aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/connect.c115
-rw-r--r--lib/url.c6
2 files changed, 79 insertions, 42 deletions
diff --git a/lib/connect.c b/lib/connect.c
index a5c2ddeb4..a71e3b3e2 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -132,6 +132,7 @@ int waitconnect(int sockfd, /* socket */
int timeout_msec)
{
fd_set fd;
+ fd_set errfd;
struct timeval interval;
int rc;
@@ -139,12 +140,15 @@ int waitconnect(int sockfd, /* socket */
FD_ZERO(&fd);
FD_SET(sockfd, &fd);
+ FD_ZERO(&errfd);
+ FD_SET(sockfd, &errfd);
+
interval.tv_sec = timeout_msec/1000;
timeout_msec -= interval.tv_sec*1000;
interval.tv_usec = timeout_msec*1000;
- rc = select(sockfd+1, NULL, &fd, NULL, &interval);
+ rc = select(sockfd+1, NULL, &fd, &errfd, &interval);
if(-1 == rc)
/* error, no connect here, try next */
return -1;
@@ -153,10 +157,16 @@ int waitconnect(int sockfd, /* socket */
/* timeout, no connect today */
return 1;
+ if(FD_ISSET(sockfd, &errfd)) {
+ /* error condition caught */
+ return 2;
+ }
+
/* we have a connect! */
return 0;
}
+#ifndef ENABLE_IPV6
static CURLcode bindlocal(struct connectdata *conn,
int sockfd)
{
@@ -171,7 +181,6 @@ static CURLcode bindlocal(struct connectdata *conn,
#define INADDR_NONE (unsigned long) ~0
#endif
-#ifndef ENABLE_IPV6
struct SessionHandle *data = conn->data;
/*************************************************************
@@ -284,12 +293,12 @@ static CURLcode bindlocal(struct connectdata *conn,
return CURLE_OK;
} /* end of device selection support */
-#endif /* end of HAVE_INET_NTOA */
+#endif /* end of HAVE_INET_NTOA */
#endif /* end of not WIN32 */
-#endif /*ENABLE_IPV6*/
return CURLE_HTTP_PORT_FAILED;
}
+#endif /* end of ipv4-specific section */
/*
* TCP connect to the given host with timeout, proxy or remote doesn't matter.
@@ -341,54 +350,82 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
}
#ifdef ENABLE_IPV6
- struct addrinfo *ai;
/*
* Connecting with IPv6 support is so much easier and cleanly done
*/
- port =0; /* we already have port in the 'remotehost' struct */
-
- for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
- sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (sockfd < 0)
- continue;
+ {
+ struct addrinfo *ai;
- /* set socket non-blocking */
- nonblock(sockfd, TRUE);
+ for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
+ sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (sockfd < 0)
+ continue;
- rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
+ /* set socket non-blocking */
+ nonblock(sockfd, TRUE);
- if(0 == rc)
- /* direct connect, awesome! */
- break;
-
- /* asynchronous connect, wait for connect or timeout */
- rc = waitconnect(sockfd, timeout_ms);
- if(0 != rc) {
- /* connect failed or timed out */
- sclose(sockfd);
- sockfd = -1;
+ rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
- /* get a new timeout for next attempt */
- after = Curl_tvnow();
- timeout_ms -= (long)(Curl_tvdiff(after, before)*1000);
- if(timeout_ms < 0)
+ if(-1 == rc) {
+ int error;
+#ifdef WIN32
+ error = (int)GetLastError();
+#else
+ error = errno;
+#endif
+ switch (error) {
+ case EINPROGRESS:
+ case EWOULDBLOCK:
+#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
+ /* On some platforms EAGAIN and EWOULDBLOCK are the
+ * same value, and on others they are different, hence
+ * the odd #if
+ */
+ case EAGAIN:
+#endif
+ case EINTR:
+
+ /* asynchronous connect, wait for connect or timeout */
+ rc = waitconnect(sockfd, timeout_ms);
+ break;
+ case ECONNREFUSED: /* no one listening */
+ default:
+ /* unknown error, fallthrough and try another address! */
+ failf(data, "Failed to connect to IP number %d", aliasindex+1);
+ break;
+ }
+ }
+ if(0 == rc)
+ /* direct connect, awesome! */
break;
- before = after;
- continue;
+
+ else {
+ /* connect failed or timed out */
+ sclose(sockfd);
+ sockfd = -1;
+
+ /* get a new timeout for next attempt */
+ after = Curl_tvnow();
+ timeout_ms -= (long)(Curl_tvdiff(after, before)*1000);
+ if(timeout_ms < 0) {
+ failf(data, "connect() timed out!");
+ return CURLE_OPERATION_TIMEOUTED;
+ }
+ before = after;
+ continue;
+ }
+ }
+ if (sockfd < 0) {
+ failf(data, "connect() failed");
+ return CURLE_COULDNT_CONNECT;
}
/* now disable the non-blocking mode again */
nonblock(sockfd, FALSE);
- break;
- }
- if (sockfd < 0) {
- failf(data, strerror(errno));
- return CURLE_COULDNT_CONNECT;
- }
-
- if(addr)
- *addr = ai; /* the address we ended up connected to */
+ if(addr)
+ *addr = ai; /* the address we ended up connected to */
+ }
#else
/*
* Connecting with IPv4-only support
diff --git a/lib/url.c b/lib/url.c
index bbd40e827..bc4ae3b2c 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -1949,7 +1949,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
if(!conn->hostaddr) {
/* it might already be set if reusing a connection */
conn->hostaddr = Curl_getaddrinfo(data, conn->name, conn->port,
- &conn->hostent_buf);
+ &conn->hostent_buf);
}
if(!conn->hostaddr) {
failf(data, "Couldn't resolve host '%s'", conn->name);
@@ -1963,7 +1963,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
/* resolve proxy */
/* it might already be set if reusing a connection */
conn->hostaddr = Curl_getaddrinfo(data, conn->proxyhost, conn->port,
- &conn->hostent_buf);
+ &conn->hostent_buf);
if(!conn->hostaddr) {
failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
@@ -2040,7 +2040,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
#else
const int niflags = NI_NUMERICHOST;
#endif
- struct addrinfo *ai = conn->ai;
+ struct addrinfo *ai = conn->serv_addr;
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0,
niflags)) {