Newer
Older
curl_socket_t *sockconn, /* the connected socket */
Daniel Stenberg
committed
Curl_addrinfo **addr, /* the one we used */
bool *connected) /* really connected? */
{
struct SessionHandle *data = conn->data;
Daniel Stenberg
committed
curl_socket_t sockfd = CURL_SOCKET_BAD;
int aliasindex;
int num_addr;
Daniel Stenberg
committed
Curl_addrinfo *ai;
Curl_addrinfo *curr_addr;
struct timeval after;
struct timeval before = Curl_tvnow();
/*************************************************************
* 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 */
CURLcode res =
singleipconnect(conn, curr_addr, timeout_per_addr, &sockfd, connected);
if(res)
return res;
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
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
/*
* 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;
}