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/06/29 00:36:31 UTC

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

trawick     00/06/28 15:36:30

  Modified:    src/lib/apr/network_io/unix networkio.h sockaddr.c sockets.c
  Log:
  APR network_io for Unix:
    Defer/avoid getsockname() whenever possible.
  
  Revision  Changes    Path
  1.30      +2 -0      apache-2.0/src/lib/apr/network_io/unix/networkio.h
  
  Index: networkio.h
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/networkio.h,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- networkio.h	2000/06/22 00:36:04	1.29
  +++ networkio.h	2000/06/28 22:36:28	1.30
  @@ -126,6 +126,8 @@
   #ifndef HAVE_POLL
       int connected;
   #endif
  +    int local_port_unknown;
  +    int local_interface_unknown;
   };
   
   struct ap_pollfd_t {
  
  
  
  1.13      +40 -0     apache-2.0/src/lib/apr/network_io/unix/sockaddr.c
  
  Index: sockaddr.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/sockaddr.c,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- sockaddr.c	2000/06/26 20:37:42	1.12
  +++ sockaddr.c	2000/06/28 22:36:28	1.13
  @@ -70,8 +70,32 @@
   
   
   
  +static ap_status_t get_local_addr(ap_socket_t *sock)
  +{
  +    socklen_t namelen = sizeof(*sock->local_addr);
  +
  +    if (getsockname(sock->socketdes, (struct sockaddr *)sock->local_addr, 
  +                    &namelen) < 0) {
  +        return errno;
  +    }
  +    else {
  +        sock->local_port_unknown = sock->local_interface_unknown = 0;
  +        return APR_SUCCESS;
  +    }
  +}
  +
  +
  +
   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;
   }
  @@ -130,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;
   }
  @@ -147,6 +179,14 @@
   #if APR_HAVE_NETINET_IN_H
   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.50      +32 -10    apache-2.0/src/lib/apr/network_io/unix/sockets.c
  
  Index: sockets.c
  ===================================================================
  RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/sockets.c,v
  retrieving revision 1.49
  retrieving revision 1.50
  diff -u -r1.49 -r1.50
  --- sockets.c	2000/06/26 20:37:42	1.49
  +++ sockets.c	2000/06/28 22:36:28	1.50
  @@ -115,8 +115,12 @@
   {
       if (bind(sock->socketdes, (struct sockaddr *)sock->local_addr, sock->addr_len) == -1)
           return errno;
  -    else
  +    else {
  +        if (sock->local_addr->sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */
  +            sock->local_port_unknown = 1; /* kernel got us an ephemeral port */
  +        }
           return APR_SUCCESS;
  +    }
   }
   
   ap_status_t ap_listen(ap_socket_t *sock, ap_int32_t backlog)
  @@ -151,9 +155,22 @@
           return errno;
       }
   
  -    if (getsockname((*new)->socketdes, (struct sockaddr *)(*new)->local_addr, 
  -                    &((*new)->addr_len)) < 0) {
  -	return errno;
  +    *(*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), 
  @@ -197,8 +214,16 @@
           return errno;
       }
       else {
  -        socklen_t namelen = sizeof(*sock->local_addr);
  -        getsockname(sock->socketdes, (struct sockaddr *)sock->local_addr, &namelen);
  +        if (sock->local_addr->sin_port == 0) {
  +            /* connect() got us an ephemeral port */
  +            sock->local_port_unknown = 1;
  +        }
  +        if (sock->local_addr->sin_addr.s_addr == 0) {
  +            /* not bound to specific local interface; connect() had to assign
  +             * one for the socket
  +             */
  +            sock->local_interface_unknown = 1;
  +        }
   #ifndef HAVE_POLL
   	sock->connected=1;
   #endif
  @@ -240,11 +265,8 @@
        
           (*sock)->addr_len = sizeof(*(*sock)->local_addr);
           (*sock)->timeout = -1;
  -        if (getsockname(*thesock, (struct sockaddr *)(*sock)->local_addr, 
  -                        &((*sock)->addr_len)) < 0) {
  -            return errno;
  -        }
       }
  +    (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1;
       (*sock)->socketdes = *thesock;
       return APR_SUCCESS;
   }