You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Gregory Nicholls <gn...@level8.com> on 2000/07/26 15:21:38 UTC

[PATCH] Modified WinNT socket layer in APR

This is a patch to bring the Winnt socket stuff in APR inline with the Unix
versions. The Win stuff didn't have getsockname calls to retrieve the local
port. I've essentially copied the unix version verbatim. Changes from unix
are minor, replacing errno with WSAGetLastError for instance. The only
significant logic change is in the connect so pay attention there <grin>.
Seems OK on my box but you never know..

    G.

--------------- cut here -------------------------------------
Index: win32/networkio.h
===================================================================
RCS file:
/home/cvspublic/apache-2.0/src/lib/apr/network_io/win32/networkio.h,v
retrieving revision 1.11
diff -u -d -b -r1.11 networkio.h
--- win32/networkio.h 2000/07/06 15:13:25 1.11
+++ win32/networkio.h 2000/07/26 13:06:58
@@ -66,6 +66,8 @@
     size_t addr_len;
     ap_interval_time_t timeout;
     ap_int32_t disconnected;
+    int local_port_unknown;
+    int local_interface_unknown;
 };

 struct ap_pollfd_t {
Index: win32/sockaddr.c
===================================================================
RCS file:
/home/cvspublic/apache-2.0/src/lib/apr/network_io/win32/sockaddr.c,v
retrieving revision 1.9
diff -u -d -b -r1.9 sockaddr.c
--- win32/sockaddr.c 2000/07/25 00:42:13 1.9
+++ win32/sockaddr.c 2000/07/26 13:07:00
@@ -58,6 +58,21 @@
 #include "apr_strings.h"
 #include <string.h>

+static ap_status_t get_local_addr(ap_socket_t *sock)
+{
+    size_t namelen = sizeof(*sock->local_addr);
+
+    if (getsockname(sock->sock, (struct sockaddr *)sock->local_addr,
+                    &namelen) < 0) {
+        return WSAGetLastError();
+    }
+    else {
+        sock->local_port_unknown = sock->local_interface_unknown = 0;
+        return APR_SUCCESS;
+    }
+}
+
+

 ap_status_t ap_set_local_port(ap_socket_t *sock, ap_uint32_t port)
 {
@@ -77,6 +92,14 @@

 ap_status_t ap_get_local_port(ap_uint32_t *port, ap_socket_t *sock)
 {
+    if (sock->local_port_unknown) {
+        ap_status_t rv = get_local_addr(sock);
+
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+    }
+
     *port = ntohs(sock->local_addr->sin_port);
     return APR_SUCCESS;
 }
@@ -131,6 +154,14 @@

 ap_status_t ap_get_local_ipaddr(char **addr, ap_socket_t *sock)
 {
+    if (sock->local_interface_unknown) {
+        ap_status_t rv = get_local_addr(sock);
+
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+    }
+
     *addr = ap_pstrdup(sock->cntxt, inet_ntoa(sock->local_addr->sin_addr));
     return APR_SUCCESS;
 }
@@ -146,6 +177,14 @@

 ap_status_t ap_get_local_name(struct sockaddr_in **name, ap_socket_t *sock)
 {
+    if (sock->local_port_unknown || sock->local_interface_unknown) {
+        ap_status_t rv = get_local_addr(sock);
+
+        if (rv != APR_SUCCESS) {
+            return rv;
+        }
+    }
+
     *name = sock->local_addr;
     return APR_SUCCESS;
 }
Index: win32/sockets.c
===================================================================
RCS file: /home/cvspublic/apache-2.0/src/lib/apr/network_io/win32/sockets.c,v

retrieving revision 1.34
diff -u -d -b -r1.34 sockets.c
--- win32/sockets.c 2000/07/25 15:50:52 1.34
+++ win32/sockets.c 2000/07/26 13:07:02
@@ -150,8 +150,12 @@
     if (bind(sock->sock, (struct sockaddr *)sock->local_addr,
sock->addr_len) == -1) {
         return WSAGetLastError();
     }
-    else
+    else {
+        if (sock->local_addr->sin_port == 0) {
+            sock->local_port_unknown = 1; /* ephemeral port */
+        }
         return APR_SUCCESS;
+    }
 }

 ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog)
@@ -185,6 +189,24 @@
         return WSAGetLastError();
     }

+    *(*new)->local_addr = *sock->local_addr;
+
+    if (sock->local_port_unknown) {
+        /* not likely for a listening socket, but theoretically possible :)
*/
+        (*new)->local_port_unknown = 1;
+    }
+
+    if (sock->local_interface_unknown ||
+        sock->local_addr->sin_addr.s_addr == 0) {
+        /* If the interface address inside the listening socket's local_addr
wasn't
+         * up-to-date, we don't know local interface of the connected socket
either.
+         *
+         * If the listening socket was not bound to a specific interface, we

+         * don't know the local_addr of the connected socket.
+         */
+        (*new)->local_interface_unknown = 1;
+    }
+
     ap_register_cleanup((*new)->cntxt, (void *)(*new),
                         socket_cleanup, ap_null_cleanup);
     return APR_SUCCESS;
@@ -218,20 +240,25 @@
     sock->remote_addr->sin_family = AF_INET;

     if (connect(sock->sock, (const struct sockaddr *)sock->remote_addr,
-                sock->addr_len) == 0) {
-        return APR_SUCCESS;
-    }
-    else {
+                sock->addr_len) == SOCKET_ERROR) {
         lasterror = WSAGetLastError();
-        if (lasterror == WSAEWOULDBLOCK) {
+        if (lasterror != WSAEWOULDBLOCK) return lasterror;
+/* wait for the connect to complete */
             FD_ZERO(&temp);
             FD_SET(sock->sock, &temp);
-            if (select(sock->sock+1, NULL, &temp, NULL, NULL) == 1) {
-                return APR_SUCCESS;
+        if (select(sock->sock+1, NULL, &temp, NULL, NULL) == SOCKET_ERROR) {

+                return WSAGetLastError();
             }
         }
-        return lasterror;
+/* connect was OK .. amazing */
+    if (sock->local_addr->sin_port == 0) {
+        sock->local_port_unknown = 1;
     }
+    if (sock->local_addr->sin_addr.s_addr == 0) {
+/* must be using free-range port */
+        sock->local_interface_unknown = 1;
+    }
+    return APR_SUCCESS;
 }

 ap_status_t ap_get_socketdata(void **data, const char *key, ap_socket_t
*socket)
@@ -273,6 +300,7 @@
         (*sock)->timeout = -1;
         (*sock)->disconnected = 0;
     }
+    (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
     (*sock)->sock = *thesock;
     return APR_SUCCESS;
 }



Re: [PATCH] Modified WinNT socket layer in APR

Posted by Jeff Trawick <tr...@bellsouth.net>.
Gregory Nicholls <gn...@level8.com> writes:

> This is a patch to bring the Winnt socket stuff in APR inline with the Unix
> versions. The Win stuff didn't have getsockname calls to retrieve the local
> port. I've essentially copied the unix version verbatim. Changes from unix
> are minor, replacing errno with WSAGetLastError for instance. The only
> significant logic change is in the connect so pay attention there <grin>.
> Seems OK on my box but you never know..
> 
>     G.
> 
> --------------- cut here -------------------------------------
> Index: win32/networkio.h
> ===================================================================
> RCS file:
> /home/cvspublic/apache-2.0/src/lib/apr/network_io/win32/networkio.h,v
> retrieving revision 1.11
> diff -u -d -b -r1.11 networkio.h

Can you send me another copy of this patch directly?  Note that you
need to change your e-mailer to avoid wrapping any of the lines and I
think you need to turn off the diff -b option as well.  I've tried to
edit the patch manually to make the patch program happy, but I haven't
been able to make it perfectly happy yet.  (I was able to get the
patch program as provided with Cygwin B20 to dump core :) ).

Thanks,

Jeff
-- 
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
     http://www.geocities.com/SiliconValley/Park/9289/
          Born in Roswell... married an alien...