1
0
mirror of https://github.com/moparisthebest/curl synced 2024-12-22 08:08:50 -05:00

multi: connect fail => use next IP address

When using the multi interface and connecting to a host name that
resolves to multiple IP addresses, there was no logic that made it
continue to the next IP if connecting to the first address times
out. This is now corrected.
This commit is contained in:
Daniel Stenberg 2010-12-23 22:19:25 +01:00
parent 7dc9393d3b
commit 5825aa149d
2 changed files with 33 additions and 12 deletions

View File

@ -658,6 +658,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
curl_socket_t sockfd = conn->sock[sockindex]; curl_socket_t sockfd = conn->sock[sockindex];
long allow = DEFAULT_CONNECT_TIMEOUT; long allow = DEFAULT_CONNECT_TIMEOUT;
int error = 0; int error = 0;
struct timeval now;
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
@ -669,8 +670,10 @@ CURLcode Curl_is_connected(struct connectdata *conn,
return CURLE_OK; return CURLE_OK;
} }
now = Curl_tvnow();
/* figure out how long time we have left to connect */ /* figure out how long time we have left to connect */
allow = Curl_timeleft(conn, NULL, TRUE); allow = Curl_timeleft(conn, &now, TRUE);
if(allow < 0) { if(allow < 0) {
/* time-out, bail out, go home */ /* time-out, bail out, go home */
@ -680,9 +683,16 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* check for connect without timeout as we want to return immediately */ /* check for connect without timeout as we want to return immediately */
rc = waitconnect(conn, sockfd, 0); rc = waitconnect(conn, sockfd, 0);
if(WAITCONN_TIMEOUT == rc) if(WAITCONN_TIMEOUT == rc) {
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
infof(data, "After %ldms connect time, move on!\n",
conn->timeoutms_per_addr);
goto next;
}
/* not an error, but also no connection yet */ /* not an error, but also no connection yet */
return code; return code;
}
if(WAITCONN_CONNECTED == rc) { if(WAITCONN_CONNECTED == rc) {
if(verifyconnect(sockfd, &error)) { if(verifyconnect(sockfd, &error)) {
@ -715,6 +725,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
data->state.os_errno = error; data->state.os_errno = error;
SET_SOCKERRNO(error); SET_SOCKERRNO(error);
} }
next:
code = trynextip(conn, sockindex, connected); code = trynextip(conn, sockindex, connected);
@ -928,8 +939,12 @@ singleipconnect(struct connectdata *conn,
curlx_nonblock(sockfd, TRUE); curlx_nonblock(sockfd, TRUE);
/* Connect TCP sockets, bind UDP */ /* Connect TCP sockets, bind UDP */
if(conn->socktype == SOCK_STREAM) if(conn->socktype == SOCK_STREAM) {
rc = connect(sockfd, &addr.sa_addr, addr.addrlen); rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
conn->connecttime = Curl_tvnow();
if(conn->num_addr > 1)
Curl_expire(data, conn->timeoutms_per_addr);
}
else else
rc = 0; rc = 0;
@ -1010,7 +1025,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
curl_socket_t sockfd = CURL_SOCKET_BAD; curl_socket_t sockfd = CURL_SOCKET_BAD;
int aliasindex; int aliasindex;
int num_addr;
Curl_addrinfo *ai; Curl_addrinfo *ai;
Curl_addrinfo *curr_addr; Curl_addrinfo *curr_addr;
@ -1021,7 +1035,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
* Figure out what maximum time we have left * Figure out what maximum time we have left
*************************************************************/ *************************************************************/
long timeout_ms; long timeout_ms;
long timeout_per_addr;
DEBUGASSERT(sockconn); DEBUGASSERT(sockconn);
*connected = FALSE; /* default to not connected */ *connected = FALSE; /* default to not connected */
@ -1036,8 +1049,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
} }
/* Max time for each address */ /* Max time for each address */
num_addr = Curl_num_addresses(remotehost->addr); conn->num_addr = Curl_num_addresses(remotehost->addr);
timeout_per_addr = timeout_ms / num_addr; conn->timeoutms_per_addr = timeout_ms / conn->num_addr;
ai = remotehost->addr; ai = remotehost->addr;
@ -1045,10 +1058,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
* know for the given host. One by one until one IP succeeds. * know for the given host. One by one until one IP succeeds.
*/ */
if(data->state.used_interface == Curl_if_multi)
/* don't hang when doing multi */
timeout_per_addr = 0;
/* /*
* Connecting with a Curl_addrinfo chain * Connecting with a Curl_addrinfo chain
*/ */
@ -1057,7 +1066,10 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
/* start connecting to the IP curr_addr points to */ /* start connecting to the IP curr_addr points to */
CURLcode res = CURLcode res =
singleipconnect(conn, curr_addr, timeout_per_addr, &sockfd, connected); singleipconnect(conn, curr_addr,
/* don't hang when doing multi */
(data->state.used_interface == Curl_if_multi)?0:
conn->timeoutms_per_addr, &sockfd, connected);
if(res) if(res)
return res; return res;

View File

@ -812,6 +812,15 @@ struct connectdata {
struct ConnectBits bits; /* various state-flags for this connection */ struct ConnectBits bits; /* various state-flags for this connection */
/* connecttime: when connect() is called on the current IP address. Used to
be able to track when to move on to try next IP - but only when the multi
interface is used. */
struct timeval connecttime;
/* The two fields below get set in Curl_connecthost */
int num_addr; /* number of addresses to try to connect to */
long timeoutms_per_addr; /* how long time in milliseconds to spend on
trying to connect to each IP address */
const struct Curl_handler * handler; /* Connection's protocol handler. */ const struct Curl_handler * handler; /* Connection's protocol handler. */
long ip_version; /* copied from the SessionHandle at creation time */ long ip_version; /* copied from the SessionHandle at creation time */