aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2001-10-02 17:18:46 +0000
committerDaniel Stenberg <daniel@haxx.se>2001-10-02 17:18:46 +0000
commit72dbe9da72a827f16cc3c2437482397606096d3e (patch)
treedb21246d912a06867fb964f1deb241801435e221 /lib
parentdd028817884ca3262ae4e136332a7fdf469787e9 (diff)
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
Diffstat (limited to 'lib')
-rw-r--r--lib/connect.c82
1 files changed, 52 insertions, 30 deletions
diff --git a/lib/connect.c b/lib/connect.c
index a71e3b3e2..6e2019e17 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -72,6 +72,16 @@
#include "memdebug.h"
#endif
+static
+int geterrno(void)
+{
+#ifdef WIN32
+ return (int)GetLastError();
+#else
+ return errno;
+#endif
+}
+
/*************************************************************************
* Curl_nonblock
*
@@ -300,6 +310,19 @@ static CURLcode bindlocal(struct connectdata *conn,
}
#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.
* 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;
+ port =0; /* prevent compiler warning */
for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
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);
if(-1 == rc) {
- int error;
-#ifdef WIN32
- error = (int)GetLastError();
-#else
- error = errno;
-#endif
+ int error=geterrno();
+
switch (error) {
case EINPROGRESS:
case EWOULDBLOCK:
@@ -391,29 +411,35 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
case ECONNREFUSED: /* no one listening */
default:
/* unknown error, fallthrough and try another address! */
- failf(data, "Failed to connect to IP number %d", aliasindex+1);
+ failf(data, "Failed to connect");
break;
}
}
- if(0 == rc)
- /* direct connect, awesome! */
- break;
+ if(0 == rc) {
+ /* we might be connected, if the socket says it is OK! Ask it! */
+ int err;
- else {
- /* 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;
+ err = socketerror(sockfd);
+ if ((0 == err) || (EISCONN == err)) {
+ /* we are connected, awesome! */
+ break;
+ }
+ /* we are _not_ connected, it was a false alert, continue please */
}
+
+ /* 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) {
failf(data, "connect() failed");
@@ -466,12 +492,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
sizeof(serv_addr));
if(-1 == rc) {
- int error;
-#ifdef WIN32
- error = (int)GetLastError();
-#else
- error = errno;
-#endif
+ int error=geterrno();
+
switch (error) {
case EINPROGRESS:
case EWOULDBLOCK: