Newer
Older
* Figure out what maximum time we have left
*************************************************************/
Daniel Stenberg
committed
long timeout_per_addr;
Daniel Stenberg
committed
DEBUGASSERT(sockconn);
Daniel Stenberg
committed
*connected = FALSE; /* default to not connected */
Daniel Stenberg
committed
/* get the timeout left */
timeout_ms = Curl_timeleft(conn, &before, TRUE);
Daniel Stenberg
committed
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "Connection time-out");
return CURLE_OPERATION_TIMEDOUT;
Daniel Stenberg
committed
Curl_expire(data, timeout_ms);
Daniel Stenberg
committed
/* Max time for each address */
num_addr = Curl_num_addresses(remotehost->addr);
timeout_per_addr = timeout_ms / num_addr;
Daniel Stenberg
committed
ai = remotehost->addr;
Daniel Stenberg
committed
/* Below is the loop that attempts to connect to all IP-addresses we
Daniel Stenberg
committed
* know for the given host. One by one until one IP succeeds.
Daniel Stenberg
committed
*/
Daniel Stenberg
committed
Daniel Stenberg
committed
if(data->state.used_interface == Curl_if_multi)
/* don't hang when doing multi */
Daniel Stenberg
committed
timeout_per_addr = 0;
Daniel Stenberg
committed
Daniel Stenberg
committed
* Connecting with a Curl_addrinfo chain
Daniel Stenberg
committed
for (curr_addr = ai, aliasindex=0; curr_addr;
Daniel Stenberg
committed
curr_addr = curr_addr->ai_next, aliasindex++) {
Daniel Stenberg
committed
Daniel Stenberg
committed
/* start connecting to the IP curr_addr points to */
sockfd = singleipconnect(conn, curr_addr, timeout_per_addr, connected);
Daniel Stenberg
committed
Daniel Stenberg
committed
if(sockfd != CURL_SOCKET_BAD)
Daniel Stenberg
committed
break;
/* get a new timeout for next attempt */
after = Curl_tvnow();
timeout_ms -= Curl_tvdiff(after, before);
if(timeout_ms < 0) {
failf(data, "connect() timed out!");
return CURLE_OPERATION_TIMEDOUT;
before = after;
Daniel Stenberg
committed
} /* end of connect-to-each-address loop */
*sockconn = sockfd; /* the socket descriptor we've connected */
Daniel Stenberg
committed
if(sockfd == CURL_SOCKET_BAD) {
failf(data, "couldn't connect to host");
return CURLE_COULDNT_CONNECT;
}
/* leave the socket in non-blocking mode */
/* store the address we use */
Daniel Stenberg
committed
if(addr)
*addr = curr_addr;
data->info.numconnects++; /* to track the number of connections made */
Daniel Stenberg
committed
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
/*
* Used to extract socket and connectdata struct for the most recent
* transfer on the given SessionHandle.
*
* The socket 'long' will be -1 in case of failure!
*/
CURLcode Curl_getconnectinfo(struct SessionHandle *data,
long *param_longp,
struct connectdata **connp)
{
if((data->state.lastconnect != -1) &&
(data->state.connc->connects[data->state.lastconnect] != NULL)) {
struct connectdata *c =
data->state.connc->connects[data->state.lastconnect];
if(connp)
/* only store this if the caller cares for it */
*connp = c;
*param_longp = c->sock[FIRSTSOCKET];
/* we have a socket connected, let's determine if the server shut down */
/* determine if ssl */
if(c->ssl[FIRSTSOCKET].use) {
/* use the SSL context */
if(!Curl_ssl_check_cxn(c))
*param_longp = -1; /* FIN received */
}
/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
#ifdef MSG_PEEK
else {
/* use the socket */
char buf;
if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
(RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
*param_longp = -1; /* FIN received */
}
}
#endif
}
else
*param_longp = -1;
return CURLE_OK;
}