mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
praise Bjorn Reese for mastering these dusty corners of socket hacking, now
we check for the error state before believing we are connected in IPv6 cases
This commit is contained in:
parent
dd02881788
commit
72dbe9da72
@ -72,6 +72,16 @@
|
|||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static
|
||||||
|
int geterrno(void)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return (int)GetLastError();
|
||||||
|
#else
|
||||||
|
return errno;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
* Curl_nonblock
|
* Curl_nonblock
|
||||||
*
|
*
|
||||||
@ -300,6 +310,19 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#endif /* end of ipv4-specific section */
|
#endif /* end of ipv4-specific section */
|
||||||
|
|
||||||
|
static
|
||||||
|
int socketerror(int sockfd)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
socklen_t errSize = sizeof(err);
|
||||||
|
|
||||||
|
if( -1 == getsockopt(sockfd, SOL_SOCKET, SO_ERROR,
|
||||||
|
(void *)&err, &errSize))
|
||||||
|
err = geterrno();
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TCP connect to the given host with timeout, proxy or remote doesn't matter.
|
* TCP connect to the given host with timeout, proxy or remote doesn't matter.
|
||||||
* There might be more than one IP address to try out. Fill in the passed
|
* There might be more than one IP address to try out. Fill in the passed
|
||||||
@ -355,6 +378,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
struct addrinfo *ai;
|
struct addrinfo *ai;
|
||||||
|
port =0; /* prevent compiler warning */
|
||||||
|
|
||||||
for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
|
for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
|
||||||
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||||
@ -367,12 +391,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
|
rc = connect(sockfd, ai->ai_addr, ai->ai_addrlen);
|
||||||
|
|
||||||
if(-1 == rc) {
|
if(-1 == rc) {
|
||||||
int error;
|
int error=geterrno();
|
||||||
#ifdef WIN32
|
|
||||||
error = (int)GetLastError();
|
|
||||||
#else
|
|
||||||
error = errno;
|
|
||||||
#endif
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case EINPROGRESS:
|
case EINPROGRESS:
|
||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
@ -391,29 +411,35 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
case ECONNREFUSED: /* no one listening */
|
case ECONNREFUSED: /* no one listening */
|
||||||
default:
|
default:
|
||||||
/* unknown error, fallthrough and try another address! */
|
/* unknown error, fallthrough and try another address! */
|
||||||
failf(data, "Failed to connect to IP number %d", aliasindex+1);
|
failf(data, "Failed to connect");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(0 == rc)
|
if(0 == rc) {
|
||||||
/* direct connect, awesome! */
|
/* we might be connected, if the socket says it is OK! Ask it! */
|
||||||
break;
|
int err;
|
||||||
|
|
||||||
else {
|
err = socketerror(sockfd);
|
||||||
/* connect failed or timed out */
|
if ((0 == err) || (EISCONN == err)) {
|
||||||
sclose(sockfd);
|
/* we are connected, awesome! */
|
||||||
sockfd = -1;
|
break;
|
||||||
|
}
|
||||||
/* get a new timeout for next attempt */
|
/* we are _not_ connected, it was a false alert, continue please */
|
||||||
after = Curl_tvnow();
|
|
||||||
timeout_ms -= (long)(Curl_tvdiff(after, before)*1000);
|
|
||||||
if(timeout_ms < 0) {
|
|
||||||
failf(data, "connect() timed out!");
|
|
||||||
return CURLE_OPERATION_TIMEOUTED;
|
|
||||||
}
|
|
||||||
before = after;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* connect failed or timed out */
|
||||||
|
sclose(sockfd);
|
||||||
|
sockfd = -1;
|
||||||
|
|
||||||
|
/* get a new timeout for next attempt */
|
||||||
|
after = Curl_tvnow();
|
||||||
|
timeout_ms -= (long)(Curl_tvdiff(after, before)*1000);
|
||||||
|
if(timeout_ms < 0) {
|
||||||
|
failf(data, "connect() timed out!");
|
||||||
|
return CURLE_OPERATION_TIMEOUTED;
|
||||||
|
}
|
||||||
|
before = after;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (sockfd < 0) {
|
if (sockfd < 0) {
|
||||||
failf(data, "connect() failed");
|
failf(data, "connect() failed");
|
||||||
@ -466,12 +492,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
sizeof(serv_addr));
|
sizeof(serv_addr));
|
||||||
|
|
||||||
if(-1 == rc) {
|
if(-1 == rc) {
|
||||||
int error;
|
int error=geterrno();
|
||||||
#ifdef WIN32
|
|
||||||
error = (int)GetLastError();
|
|
||||||
#else
|
|
||||||
error = errno;
|
|
||||||
#endif
|
|
||||||
switch (error) {
|
switch (error) {
|
||||||
case EINPROGRESS:
|
case EINPROGRESS:
|
||||||
case EWOULDBLOCK:
|
case EWOULDBLOCK:
|
||||||
|
Loading…
Reference in New Issue
Block a user