httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Gregory Nicholls <gnicho...@level8.com>
Subject [PATCH] Modified WinNT socket layer in APR
Date Wed, 26 Jul 2000 13:21:38 GMT
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;
 }



Mime
View raw message