Hi there.

In function Curl_is_connected a connection error like
code 111 "Connection refused" will be overwritten with
code 115 "Operation now in progress".

e.g.

* About to connect() to nonitor.de port 22 (#0)
*   Trying 212.1.39.66... * Connection refused
* Failed connect to nonitor.de:22; Operation now in progress
* Expire cleared
* Closing connection #0

In line 687 the correct error is grab by verifyconnect(sockfd, &error)
and the next line stores the error in data struct.

This will be overwritten at line 697 with SOCKERRNO. This is only
usefull if trynextip(..) has done s.t. on a new socket. If the
there was no next address, then the previously detected error should
not be overwritten, because SOCKERRNO will return the (outdated)
errno set by the non-blocking connect.

The simplest fix would be to call SET_SOCKERRNO(errro) after line 687:

659   /* check for connect without timeout as we want to return immediately */
660   rc = waitconnect(conn, sockfd, 0);
661 
662   if(WAITCONN_CONNECTED == rc) {
663     int error;
664     if(verifyconnect(sockfd, &error)) {
665       /* we are connected, awesome! */
666       conn->bits.tcpconnect = TRUE;
667       *connected = TRUE;
668       Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
669       Curl_verboseconnect(conn);
670       Curl_updateconninfo(conn, sockfd);
671 
672       return CURLE_OK;
673     }
674     /* nope, not connected for real */
675     data->state.os_errno = error;
676     infof(data, "Connection failed\n");
677     code = trynextip(conn, sockindex, connected);
678     if(code)
679       failf(data, "Failed connect to %s:%ld; %s",
680             conn->host.name, conn->port, Curl_strerror(conn, error));
681   }
682   else if(WAITCONN_TIMEOUT != rc) {
683     int error = 0;
684 
685     /* nope, not connected  */
686     if(WAITCONN_FDSET_ERROR == rc) {
687       (void)verifyconnect(sockfd, &error);
688       data->state.os_errno = error;
+++       SET_SOCKERRNO(error); 
689       infof(data, "%s\n",Curl_strerror(conn,error));
690     }
691     else
692       infof(data, "Connection failed\n");
693 
694     code = trynextip(conn, sockindex, connected);
695 
696     if(code) {
697       error = SOCKERRNO;
698       data->state.os_errno = error;
699       failf(data, "Failed connect to %s:%ld; %s",
700             conn->host.name, conn->port, Curl_strerror(conn, error));
701     }
702   }
703   /*
704    * If the connection failed here, we should attempt to connect to the 
"next
705    * address" for the given host.
706    */
707 
708   return code;
709 }


While hacking the bug I've noticed that line 677-680 and 694-701 are same
with a small difference: In the first block the error overwritting is missing.
And the comment in line 703-706 is weird, because trynextip is already
called (unless WAITCONN_TIMEOUT).

To clean this up, I've written a patch. I hope, it breaks nothing...


Greetings,
Dirk Manske
diff --git a/lib/connect.c b/lib/connect.c
index 0495887..8a48637 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -658,9 +658,13 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 
   /* check for connect without timeout as we want to return immediately */
   rc = waitconnect(conn, sockfd, 0);
+  if(WAITCONN_TIMEOUT == rc) {
+      /* not an error, but also no connection yet */
+      return code;
+  }
 
+  int error = 0;
   if(WAITCONN_CONNECTED == rc) {
-    int error;
     if(verifyconnect(sockfd, &error)) {
       /* we are connected, awesome! */
       conn->bits.tcpconnect = TRUE;
@@ -672,38 +676,34 @@ CURLcode Curl_is_connected(struct connectdata *conn,
       return CURLE_OK;
     }
     /* nope, not connected for real */
-    data->state.os_errno = error;
-    infof(data, "Connection failed\n");
-    code = trynextip(conn, sockindex, connected);
-    if(code)
-      failf(data, "Failed connect to %s:%ld; %s",
-            conn->host.name, conn->port, Curl_strerror(conn, error));
   }
-  else if(WAITCONN_TIMEOUT != rc) {
-    int error = 0;
-
+  else {
     /* nope, not connected  */
     if(WAITCONN_FDSET_ERROR == rc) {
       (void)verifyconnect(sockfd, &error);
-      data->state.os_errno = error;
       infof(data, "%s\n",Curl_strerror(conn,error));
     }
     else
       infof(data, "Connection failed\n");
-
-    code = trynextip(conn, sockindex, connected);
-
-    if(code) {
-      error = SOCKERRNO;
-      data->state.os_errno = error;
-      failf(data, "Failed connect to %s:%ld; %s",
-            conn->host.name, conn->port, Curl_strerror(conn, error));
-    }
   }
+
   /*
-   * If the connection failed here, we should attempt to connect to the "next
-   * address" for the given host.
+   * The connection failed here, we should attempt to connect to the "next
+   * address" for the given host. But first remember the latest error.
    */
+  if(error) {
+      data->state.os_errno = error;
+      SET_SOCKERRNO(error);
+  }
+
+  code = trynextip(conn, sockindex, connected);
+
+  if(code) {
+    error = SOCKERRNO;
+    data->state.os_errno = error;
+    failf(data, "Failed connect to %s:%ld; %s",
+          conn->host.name, conn->port, Curl_strerror(conn, error));
+  }
 
   return code;
 }
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html

Reply via email to