mirror of
https://github.com/moparisthebest/curl
synced 2024-10-31 15:45:12 -04:00
singleipconnect: simplify and clean up
Remove timeout argument that's never used. Make the actual connection get detected on a single spot to reduce code duplication. Store the IPv6 state already when the connection is attempted.
This commit is contained in:
parent
32e8467a66
commit
56b7c87c74
140
lib/connect.c
140
lib/connect.c
@ -128,7 +128,6 @@ tcpkeepalive(struct SessionHandle *data,
|
|||||||
static CURLcode
|
static CURLcode
|
||||||
singleipconnect(struct connectdata *conn,
|
singleipconnect(struct connectdata *conn,
|
||||||
const Curl_addrinfo *ai, /* start connecting to this */
|
const Curl_addrinfo *ai, /* start connecting to this */
|
||||||
long timeout_ms,
|
|
||||||
curl_socket_t *sock,
|
curl_socket_t *sock,
|
||||||
bool *connected);
|
bool *connected);
|
||||||
|
|
||||||
@ -199,20 +198,19 @@ long Curl_timeleft(struct SessionHandle *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* waitconnect() waits for a TCP connect on the given socket for the specified
|
* checkconnect() checks for a TCP connect on the given socket.
|
||||||
* number if milliseconds. It returns:
|
* It returns:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define WAITCONN_CONNECTED 0
|
enum chkconn_t {
|
||||||
#define WAITCONN_SELECT_ERROR -1
|
CHKCONN_SELECT_ERROR = -1,
|
||||||
#define WAITCONN_TIMEOUT 1
|
CHKCONN_CONNECTED = 0,
|
||||||
#define WAITCONN_FDSET_ERROR 2
|
CHKCONN_IDLE = 1,
|
||||||
#define WAITCONN_ABORTED 3
|
CHKCONN_FDSET_ERROR = 2
|
||||||
|
};
|
||||||
|
|
||||||
static
|
static enum chkconn_t
|
||||||
int waitconnect(struct connectdata *conn,
|
checkconnect(curl_socket_t sockfd)
|
||||||
curl_socket_t sockfd, /* socket */
|
|
||||||
long timeout_msec)
|
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
#ifdef mpeix
|
#ifdef mpeix
|
||||||
@ -222,34 +220,20 @@ int waitconnect(struct connectdata *conn,
|
|||||||
(void)verifyconnect(sockfd, NULL);
|
(void)verifyconnect(sockfd, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(;;) {
|
rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, 0);
|
||||||
|
|
||||||
/* now select() until we get connect or timeout */
|
if(-1 == rc)
|
||||||
rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, timeout_msec>1000?
|
/* error, no connect here, try next */
|
||||||
1000:timeout_msec);
|
return CHKCONN_SELECT_ERROR;
|
||||||
if(Curl_pgrsUpdate(conn))
|
|
||||||
return WAITCONN_ABORTED;
|
|
||||||
|
|
||||||
if(-1 == rc)
|
else if(rc & CURL_CSELECT_ERR)
|
||||||
/* error, no connect here, try next */
|
/* error condition caught */
|
||||||
return WAITCONN_SELECT_ERROR;
|
return CHKCONN_FDSET_ERROR;
|
||||||
|
|
||||||
else if(0 == rc) {
|
else if(rc)
|
||||||
/* timeout */
|
return CHKCONN_CONNECTED;
|
||||||
timeout_msec -= 1000;
|
|
||||||
if(timeout_msec <= 0)
|
|
||||||
return WAITCONN_TIMEOUT;
|
|
||||||
|
|
||||||
continue;
|
return CHKCONN_IDLE;
|
||||||
}
|
|
||||||
|
|
||||||
if(rc & CURL_CSELECT_ERR)
|
|
||||||
/* error condition caught */
|
|
||||||
return WAITCONN_FDSET_ERROR;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return WAITCONN_CONNECTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode bindlocal(struct connectdata *conn,
|
static CURLcode bindlocal(struct connectdata *conn,
|
||||||
@ -548,7 +532,7 @@ static CURLcode trynextip(struct connectdata *conn,
|
|||||||
ai = conn->ip_addr->ai_next;
|
ai = conn->ip_addr->ai_next;
|
||||||
|
|
||||||
while(ai) {
|
while(ai) {
|
||||||
CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected);
|
CURLcode res = singleipconnect(conn, ai, &sockfd, connected);
|
||||||
if(res)
|
if(res)
|
||||||
return res;
|
return res;
|
||||||
if(sockfd != CURL_SOCKET_BAD) {
|
if(sockfd != CURL_SOCKET_BAD) {
|
||||||
@ -676,21 +660,20 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_is_connected() is used from the multi interface to check if the
|
* Curl_is_connected() checks if the socket has connected.
|
||||||
* firstsocket has connected.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CURLcode Curl_is_connected(struct connectdata *conn,
|
CURLcode Curl_is_connected(struct connectdata *conn,
|
||||||
int sockindex,
|
int sockindex,
|
||||||
bool *connected)
|
bool *connected)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
CURLcode code = CURLE_OK;
|
CURLcode code = CURLE_OK;
|
||||||
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;
|
struct timeval now;
|
||||||
|
enum chkconn_t chk;
|
||||||
|
|
||||||
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
|
DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
|
||||||
|
|
||||||
@ -713,9 +696,9 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
return CURLE_OPERATION_TIMEDOUT;
|
return CURLE_OPERATION_TIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for connect without timeout as we want to return immediately */
|
/* check socket for connect */
|
||||||
rc = waitconnect(conn, sockfd, 0);
|
chk = checkconnect(sockfd);
|
||||||
if(WAITCONN_TIMEOUT == rc) {
|
if(CHKCONN_IDLE == chk) {
|
||||||
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
|
if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
|
||||||
infof(data, "After %ldms connect time, move on!\n",
|
infof(data, "After %ldms connect time, move on!\n",
|
||||||
conn->timeoutms_per_addr);
|
conn->timeoutms_per_addr);
|
||||||
@ -726,7 +709,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(WAITCONN_CONNECTED == rc) {
|
if(CHKCONN_CONNECTED == chk) {
|
||||||
if(verifyconnect(sockfd, &error)) {
|
if(verifyconnect(sockfd, &error)) {
|
||||||
/* we are connected with TCP, awesome! */
|
/* we are connected with TCP, awesome! */
|
||||||
|
|
||||||
@ -736,6 +719,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
return code;
|
return code;
|
||||||
|
|
||||||
conn->bits.tcpconnect[sockindex] = TRUE;
|
conn->bits.tcpconnect[sockindex] = TRUE;
|
||||||
|
|
||||||
*connected = TRUE;
|
*connected = TRUE;
|
||||||
if(sockindex == FIRSTSOCKET)
|
if(sockindex == FIRSTSOCKET)
|
||||||
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
|
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
|
||||||
@ -748,7 +732,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* nope, not connected */
|
/* nope, not connected */
|
||||||
if(WAITCONN_FDSET_ERROR == rc) {
|
if(CHKCONN_FDSET_ERROR == chk) {
|
||||||
(void)verifyconnect(sockfd, &error);
|
(void)verifyconnect(sockfd, &error);
|
||||||
infof(data, "%s\n",Curl_strerror(conn, error));
|
infof(data, "%s\n",Curl_strerror(conn, error));
|
||||||
}
|
}
|
||||||
@ -864,12 +848,11 @@ void Curl_sndbufset(curl_socket_t sockfd)
|
|||||||
* CURL_SOCKET_BAD. Other errors will however return proper errors.
|
* CURL_SOCKET_BAD. Other errors will however return proper errors.
|
||||||
*
|
*
|
||||||
* singleipconnect() connects to the given IP only, and it may return without
|
* singleipconnect() connects to the given IP only, and it may return without
|
||||||
* having connected if used from the multi interface.
|
* having connected.
|
||||||
*/
|
*/
|
||||||
static CURLcode
|
static CURLcode
|
||||||
singleipconnect(struct connectdata *conn,
|
singleipconnect(struct connectdata *conn,
|
||||||
const Curl_addrinfo *ai,
|
const Curl_addrinfo *ai,
|
||||||
long timeout_ms,
|
|
||||||
curl_socket_t *sockp,
|
curl_socket_t *sockp,
|
||||||
bool *connected)
|
bool *connected)
|
||||||
{
|
{
|
||||||
@ -940,17 +923,25 @@ singleipconnect(struct connectdata *conn,
|
|||||||
/* set socket non-blocking */
|
/* set socket non-blocking */
|
||||||
curlx_nonblock(sockfd, TRUE);
|
curlx_nonblock(sockfd, TRUE);
|
||||||
|
|
||||||
|
conn->connecttime = Curl_tvnow();
|
||||||
|
if(conn->num_addr > 1)
|
||||||
|
Curl_expire(data, conn->timeoutms_per_addr);
|
||||||
|
|
||||||
/* Connect TCP sockets, bind UDP */
|
/* Connect TCP sockets, bind UDP */
|
||||||
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
|
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
|
||||||
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
|
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
|
||||||
if(-1 == rc)
|
if(-1 == rc)
|
||||||
error = SOCKERRNO;
|
error = SOCKERRNO;
|
||||||
conn->connecttime = Curl_tvnow();
|
|
||||||
if(conn->num_addr > 1)
|
|
||||||
Curl_expire(data, conn->timeoutms_per_addr);
|
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
*sockp = sockfd;
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
if(-1 == rc) {
|
if(-1 == rc) {
|
||||||
switch (error) {
|
switch (error) {
|
||||||
@ -965,54 +956,22 @@ singleipconnect(struct connectdata *conn,
|
|||||||
case EAGAIN:
|
case EAGAIN:
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
rc = waitconnect(conn, sockfd, timeout_ms);
|
*sockp = sockfd;
|
||||||
if(WAITCONN_ABORTED == rc) {
|
return CURLE_OK;
|
||||||
Curl_closesocket(conn, sockfd);
|
|
||||||
return CURLE_ABORTED_BY_CALLBACK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
/* unknown error, fallthrough and try another address! */
|
/* unknown error, fallthrough and try another address! */
|
||||||
failf(data, "Failed to connect to %s: %s",
|
failf(data, "Failed to connect to %s: %s",
|
||||||
conn->ip_addr_str, Curl_strerror(conn,error));
|
conn->ip_addr_str, Curl_strerror(conn,error));
|
||||||
data->state.os_errno = error;
|
data->state.os_errno = error;
|
||||||
|
|
||||||
|
/* connect failed */
|
||||||
|
Curl_closesocket(conn, sockfd);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
|
|
||||||
connect(). We can be sure of this since connect() cannot return 1. */
|
|
||||||
if(WAITCONN_TIMEOUT == rc) {
|
|
||||||
/* Timeout when running the multi interface */
|
|
||||||
*sockp = sockfd;
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!isconnected)
|
|
||||||
isconnected = verifyconnect(sockfd, &error);
|
|
||||||
|
|
||||||
if(!rc && isconnected) {
|
|
||||||
/* we are connected, awesome! */
|
|
||||||
*connected = TRUE; /* this is a true connect */
|
|
||||||
infof(data, "connected\n");
|
|
||||||
#ifdef ENABLE_IPV6
|
|
||||||
conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Curl_updateconninfo(conn, sockfd);
|
|
||||||
*sockp = sockfd;
|
|
||||||
return CURLE_OK;
|
|
||||||
}
|
|
||||||
else if(WAITCONN_TIMEOUT == rc)
|
|
||||||
infof(data, "Timeout\n");
|
|
||||||
else {
|
|
||||||
data->state.os_errno = error;
|
|
||||||
infof(data, "%s\n", Curl_strerror(conn, error));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* connect failed or timed out */
|
|
||||||
Curl_closesocket(conn, sockfd);
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,7 +1032,6 @@ 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 */
|
||||||
res = singleipconnect(conn, curr_addr,
|
res = singleipconnect(conn, curr_addr,
|
||||||
0, /* don't hang when doing multi */
|
|
||||||
&sockfd, connected);
|
&sockfd, connected);
|
||||||
if(res)
|
if(res)
|
||||||
return res;
|
return res;
|
||||||
|
Loading…
Reference in New Issue
Block a user