apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From traw...@apache.org
Subject svn commit: r1089031 - in /apr/apr/trunk: CHANGES network_io/win32/sockets.c
Date Tue, 05 Apr 2011 13:28:59 GMT
Author: trawick
Date: Tue Apr  5 13:28:59 2011
New Revision: 1089031

URL: http://svn.apache.org/viewvc?rev=1089031&view=rev
Log:
restructure Windows apr_socket_connect() to more closely match
the Unix implementation, fixing the getpeername() optimization
and WSAEISCONN behavior

PR: 48736 (covered WSAISCONN issue)
Submitted by: <inoue ariel-networks.com> (WSAISCONN handling)
Reworked/extended by: trawick

Modified:
    apr/apr/trunk/CHANGES
    apr/apr/trunk/network_io/win32/sockets.c

Modified: apr/apr/trunk/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/trunk/CHANGES?rev=1089031&r1=1089030&r2=1089031&view=diff
==============================================================================
--- apr/apr/trunk/CHANGES [utf-8] (original)
+++ apr/apr/trunk/CHANGES [utf-8] Tue Apr  5 13:28:59 2011
@@ -1,6 +1,9 @@
                                                      -*- coding: utf-8 -*-
 Changes for APR 2.0.0
 
+  *) apr_socket_connect() on Windows: Handle WSAEISCONN.  PR 48736.
+     [<inoue ariel-networks.com>, Jeff Trawick]
+
   *) MinGW/MSYS:  Support shared builds of APR, other general improvements
      to support of this toolchain.  PR 46175.  [Carlo Bramini 
      <carlo.bramix libero.it>]  

Modified: apr/apr/trunk/network_io/win32/sockets.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/network_io/win32/sockets.c?rev=1089031&r1=1089030&r2=1089031&view=diff
==============================================================================
--- apr/apr/trunk/network_io/win32/sockets.c (original)
+++ apr/apr/trunk/network_io/win32/sockets.c Tue Apr  5 13:28:59 2011
@@ -306,6 +306,47 @@ APR_DECLARE(apr_status_t) apr_socket_acc
     return APR_SUCCESS;
 }
 
+static apr_status_t wait_for_connect(apr_socket_t *sock)
+{
+    int rc;
+    struct timeval tv, *tvptr;
+    fd_set wfdset, efdset;
+
+    /* wait for the connect to complete or timeout */
+    FD_ZERO(&wfdset);
+    FD_SET(sock->socketdes, &wfdset);
+    FD_ZERO(&efdset);
+    FD_SET(sock->socketdes, &efdset);
+
+    if (sock->timeout < 0) {
+        tvptr = NULL;
+    }
+    else {
+        /* casts for winsock/timeval definition */
+        tv.tv_sec =  (long)apr_time_sec(sock->timeout);
+        tv.tv_usec = (int)apr_time_usec(sock->timeout);
+        tvptr = &tv;
+    }
+    rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr);
+    if (rc == SOCKET_ERROR) {
+        return apr_get_netos_error();
+    }
+    else if (!rc) {
+        return APR_FROM_OS_ERROR(WSAETIMEDOUT);
+    }
+    /* Evaluate the efdset */
+    if (FD_ISSET(sock->socketdes, &efdset)) {
+        /* The connect failed. */
+        int rclen = sizeof(rc);
+        if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen))
{
+            return apr_get_netos_error();
+        }
+        return APR_FROM_OS_ERROR(rc);
+    }
+
+    return APR_SUCCESS;
+}
+
 APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, 
                                              apr_sockaddr_t *sa)
 {
@@ -317,59 +358,41 @@ APR_DECLARE(apr_status_t) apr_socket_con
 
     if (connect(sock->socketdes, (const struct sockaddr *)&sa->sa.sin,
                 sa->salen) == SOCKET_ERROR) {
-        int rc;
-        struct timeval tv, *tvptr;
-        fd_set wfdset, efdset;
-
         rv = apr_get_netos_error();
-        if (rv != APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) {
-            return rv;
-        }
+    }
+    else {
+        rv = APR_SUCCESS;
+    }
 
+    if (rv == APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) {
         if (sock->timeout == 0) {
             /* Tell the app that the connect is in progress...
              * Gotta play some games here.  connect on Unix will return 
              * EINPROGRESS under the same circumstances that Windows 
              * returns WSAEWOULDBLOCK. Do some adhoc canonicalization...
              */
-            return APR_FROM_OS_ERROR(WSAEINPROGRESS);
-        }
-
-        /* wait for the connect to complete or timeout */
-        FD_ZERO(&wfdset);
-        FD_SET(sock->socketdes, &wfdset);
-        FD_ZERO(&efdset);
-        FD_SET(sock->socketdes, &efdset);
-
-        if (sock->timeout < 0) {
-            tvptr = NULL;
+            rv = APR_FROM_OS_ERROR(WSAEINPROGRESS);
         }
         else {
-            /* casts for winsock/timeval definition */
-            tv.tv_sec =  (long)apr_time_sec(sock->timeout);
-            tv.tv_usec = (int)apr_time_usec(sock->timeout);
-            tvptr = &tv;
-        }
-        rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr);
-        if (rc == SOCKET_ERROR) {
-            return apr_get_netos_error();
-        }
-        else if (!rc) {
-            return APR_FROM_OS_ERROR(WSAETIMEDOUT);
-        }
-        /* Evaluate the efdset */
-        if (FD_ISSET(sock->socketdes, &efdset)) {
-            /* The connect failed. */
-            int rclen = sizeof(rc);
-            if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen))
{
-                return apr_get_netos_error();
+            rv = wait_for_connect(sock);
+            if (rv != APR_SUCCESS) {
+                return rv;
             }
-            return APR_FROM_OS_ERROR(rc);
         }
     }
-    /* connect was OK .. amazing */
-    sock->remote_addr = sa;
+
+    if (memcmp(sa->ipaddr_ptr, generic_inaddr_any, sa->ipaddr_len)) {
+        /* A real remote address was passed in.  If the unspecified
+         * address was used, the actual remote addr will have to be
+         * determined using getpeername() if required. */
+        sock->remote_addr_unknown = 0;
+
+        /* Copy the address structure details in. */
+        sock->remote_addr = sa;
+    }
+
     if (sock->local_addr->sa.sin.sin_port == 0) {
+        /* connect() got us an ephemeral port */
         sock->local_port_unknown = 1;
     }
     if (!memcmp(sock->local_addr->ipaddr_ptr,
@@ -380,6 +403,11 @@ APR_DECLARE(apr_status_t) apr_socket_con
          */
         sock->local_interface_unknown = 1;
     }
+
+    if (rv != APR_SUCCESS && rv != APR_FROM_OS_ERROR(WSAEISCONN)) {
+        return rv;
+    }
+
     return APR_SUCCESS;
 }
 



Mime
View raw message