Newer
Older
* pointer with the connected socket.
*/
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
const struct Curl_dns_entry *remotehost,
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
/* 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
/*
* Used to extract socket and connectdata struct for the most recent
* transfer on the given SessionHandle.
*
* The returned socket will be CURL_SOCKET_BAD in case of failure!
Daniel Stenberg
committed
*/
curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
struct connectdata **connp)
Daniel Stenberg
committed
{
curl_socket_t sockfd;
Daniel Stenberg
committed
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;
sockfd = c->sock[FIRSTSOCKET];
Daniel Stenberg
committed
/* 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))
return CURL_SOCKET_BAD; /* FIN received */
Daniel Stenberg
committed
}
/* 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) {
return CURL_SOCKET_BAD; /* FIN received */
Daniel Stenberg
committed
}
}
#endif
}
else
return CURL_SOCKET_BAD;
Daniel Stenberg
committed