You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by tr...@locus.apache.org on 2000/08/01 22:59:53 UTC

cvs commit: apache-2.0/src/lib/apr/network_io/win32 networkio.h sockaddr.c sockets.c

trawick     00/08/01 13:59:53

  Modified:    src      CHANGES
               src/lib/apr/network_io/win32 networkio.h sockaddr.c
                        sockets.c
  Log:
  Fix problems with APR sockaddr handling on Win32.  It didn't always
  return the right information on the local socket address.  This
  change uses the Unix logic for delaying/avoiding getsockname() to
  ensure that it is done when needed.
  Submitted by:	Gregory Nicholls <gn...@level8.com>
  Reviewed by:	Jeff Trawick
  
  Revision  Changes    Path
  1.190     +4 -0      apache-2.0/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/CHANGES,v
  retrieving revision 1.189
  retrieving revision 1.190
  diff -u -r1.189 -r1.190
  --- CHANGES	2000/08/01 19:33:15	1.189
  +++ CHANGES	2000/08/01 20:59:51	1.190
  @@ -1,4 +1,8 @@
   Changes with Apache 2.0a5
  +  *) Fix problems with APR sockaddr handling on Win32.  It didn't always
  +     return the right information on the local socket address.
  +     [Gregory Nicholls <gn...@level8.com>]
  +
     *) ap_recv() on Win32: Set bytes-read to 0 on error.  
        [Gregory Nicholls <gn...@level8.com>]
   
  
  
  
  1.12      +2 -0      apache-2.0/src/lib/apr/network_io/win32/networkio.h
  
  Index: networkio.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/win32/networkio.h,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- networkio.h	2000/07/06 15:13:25	1.11
  +++ networkio.h	2000/08/01 20:59:52	1.12
  @@ -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 {
  
  
  
  1.10      +39 -0     apache-2.0/src/lib/apr/network_io/win32/sockaddr.c
  
  Index: sockaddr.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/win32/sockaddr.c,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- sockaddr.c	2000/07/25 00:42:13	1.9
  +++ sockaddr.c	2000/08/01 20:59:52	1.10
  @@ -58,7 +58,22 @@
   #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)
   {
       sock->local_addr->sin_port = htons((short)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;
   }
  
  
  
  1.35      +42 -12    apache-2.0/src/lib/apr/network_io/win32/sockets.c
  
  Index: sockets.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/win32/sockets.c,v
  retrieving revision 1.34
  retrieving revision 1.35
  diff -u -r1.34 -r1.35
  --- sockets.c	2000/07/25 15:50:52	1.34
  +++ sockets.c	2000/08/01 20:59:52	1.35
  @@ -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,27 @@
       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) {
  -            FD_ZERO(&temp);
  -            FD_SET(sock->sock, &temp);
  -            if (select(sock->sock+1, NULL, &temp, NULL, NULL) == 1) {
  -                return APR_SUCCESS;
  -            }
  +        if (lasterror != WSAEWOULDBLOCK) {
  +            return lasterror;
           }
  -        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) == SOCKET_ERROR) {
  +            return WSAGetLastError();
  +        }
  +    }
  +    /* 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 +302,7 @@
           (*sock)->timeout = -1;
           (*sock)->disconnected = 0;
       }
  +    (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
       (*sock)->sock = *thesock;
       return APR_SUCCESS;
   }