You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@apr.apache.org by David Reid <dr...@jetnet.co.uk> on 2001/01/08 23:30:32 UTC

[PATCH] track socket options...

Folks,

This is a small patch that's very much a starting point.  Basically
following Deans suggestion we should be tracking what options we have set on
a socket and using the cached information to avoid system calls.  I've used
an int and the system defined values as that way we can use the mask for non
APR values, i.e. things like TCP_CORK.  By caching the values we also get a
working apr_getsocketopt which is useful.

This throws up some questions though.  Is this the right way to go?  How do
we store things like blocking/non blocking?  Oh well, comments?  Jeff? dean?

I've got a start of a test program but I won't clutter the bandwidth with
that just yet :)  Oh and I know this patch isn't yet ready to commit as it's
not yet complete :)

david

Index: include/arch/unix/networkio.h
===================================================================
RCS file: /home/cvs/apr/include/arch/unix/networkio.h,v
retrieving revision 1.35
diff -u -r1.35 networkio.h
--- include/arch/unix/networkio.h 2000/11/16 14:48:50 1.35
+++ include/arch/unix/networkio.h 2001/01/08 22:09:53
@@ -130,6 +130,7 @@
 #endif
     int local_port_unknown;
     int local_interface_unknown;
+    int netmask;
 };

 struct apr_pollfd_t {
Index: network_io/unix/sockopt.c
===================================================================
RCS file: /home/cvs/apr/network_io/unix/sockopt.c,v
retrieving revision 1.40
diff -u -r1.40 sockopt.c
--- network_io/unix/sockopt.c 2000/12/18 17:00:42 1.40
+++ network_io/unix/sockopt.c 2001/01/08 22:31:08
@@ -55,6 +55,19 @@
 #include "networkio.h"
 #include "apr_strings.h"

+static int is_option_set(int mask, int option)
+{
+    return (mask & option) == option;
+}
+
+static void set_option(int *mask, int option, int on)
+{
+    if (on)
+        *mask |= option;
+    else
+        *mask &= ~option;
+}
+
 static apr_status_t soblock(int sd)
 {
 /* BeOS uses setsockopt at present for non blocking... */
@@ -121,27 +134,39 @@
         one = 0;
     if (opt & APR_SO_KEEPALIVE) {
 #ifdef SO_KEEPALIVE
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void
*)&one, sizeof(int)) == -1) {
-            return errno;
+        if (on != is_option_set(sock->netmask, SO_KEEPALIVE)){
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void
*)&one, sizeof(int)) == -1) {
+                return errno;
+            }
+            set_option(&sock->netmask,SO_KEEPALIVE, on);
         }
 #else
         return APR_ENOTIMPL;
 #endif
     }
     if (opt & APR_SO_DEBUG) {
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void *)&one,
sizeof(int)) == -1) {
-            return errno;
+        if (on != is_option_set(sock->netmask, SO_DEBUG)){
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void
*)&one, sizeof(int)) == -1) {
+                return errno;
+            }
+            set_option(&sock->netmask, SO_DEBUG, on);
         }
     }
     if (opt & APR_SO_REUSEADDR) {
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void
*)&one, sizeof(int)) == -1) {
-            return errno;
+        if (on != is_option_set(sock->netmask, SO_REUSEADDR)){
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void
*)&one, sizeof(int)) == -1) {
+                return errno;
+            }
+            set_option(&sock->netmask, SO_REUSEADDR, on);
         }
     }
     if (opt & APR_SO_SNDBUF) {
 #ifdef SO_SNDBUF
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, (void *)&on,
sizeof(int)) == -1) {
-            return errno;
+        if (is_option_set(sock->netmask, SO_SNDBUF) != on){
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, (void
*)&on, sizeof(int)) == -1) {
+                return errno;
+            }
+            set_option(&sock->netmask, SO_SNDBUF, on);
         }
 #else
         return APR_ENOTIMPL;
@@ -159,11 +184,14 @@
     }
     if (opt & APR_SO_LINGER) {
 #ifdef SO_LINGER
-        struct linger li;
-        li.l_onoff = on;
-        li.l_linger = MAX_SECS_TO_LINGER;
-        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *)
&li, sizeof(struct linger)) == -1) {
-            return errno;
+        if (is_option_set(sock->netmask, SO_LINGER) != on){
+            struct linger li;
+            li.l_onoff = on;
+            li.l_linger = MAX_SECS_TO_LINGER;
+            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *)
&li, sizeof(struct linger)) == -1) {
+                return errno;
+            }
+            set_option(&sock->netmask, SO_LINGER, on);
         }
 #else
         return APR_ENOTIMPL;
@@ -183,8 +211,11 @@
     }
     if (opt & APR_TCP_NODELAY) {
 #if defined(TCP_NODELAY)
-        if (setsockopt(sock->socketdes, IPPROTO_TCP, TCP_NODELAY, (void
*)&on, sizeof(int)) == -1) {
-            return errno;
+        if (is_option_set(sock->netmask, TCP_NODELAY) != on){
+            if (setsockopt(sock->socketdes, IPPROTO_TCP, TCP_NODELAY, (void
*)&on, sizeof(int)) == -1) {
+                return errno;
+            }
+            set_option(sock->netmask, TCP_NODELAY, on);
         }
 #else
         /* BeOS pre-BONE has TCP_NODELAY set by default.
@@ -205,11 +236,38 @@
 apr_status_t apr_getsocketopt(apr_socket_t *sock, apr_int32_t opt,
apr_int32_t *on)
 {
     switch(opt) {
-    case APR_SO_TIMEOUT:
-        *on = sock->timeout;
-        break;
-    default:
-        return APR_EINVAL;
+        case APR_SO_KEEPALIVE:
+            *on = is_option_set(sock->netmask, SO_KEEPALIVE);
+            break;
+        case APR_SO_DEBUG:
+            *on = is_option_set(sock->netmask, SO_DEBUG);
+            break;
+        case APR_TCP_NODELAY:
+#ifdef TCP_NODELAY
+            *on = is_option_set(sock->netmask, TCP_NODELAY);
+            break;
+#else
+#if BEOS
+            *on = 1;
+            break;
+#endif
+            return APR_ENOTIMPL;
+#endif
+        case APR_SO_REUSEADDR:
+            *on = is_option_set(sock->netmask, SO_REUSEADDR);
+            break;
+        case APR_SO_SNDBUF:
+#ifdef SO_SNDBUF
+            *on = is_option_set(sock->netmask, SO_SNDBUF);
+            break;
+#else
+            return APR_ENOTIMPL;
+#endif
+        case APR_SO_TIMEOUT:
+            *on = sock->timeout;
+            break;
+        default:
+            return APR_EINVAL;
     }
     return APR_SUCCESS;
 }




Re: [PATCH] track socket options...

Posted by David Reid <dr...@jetnet.co.uk>.
OK, so I've reworked the patch and it doesn't break anything so do people
want to see it or shall I just commit?

Basically we now cache the APR_ values and you can set the
TCP_CORK/TCP_NOPUSH via the apr_setsocketopt call.  apr_getsocketopt works
fully as well (using the cached values...)

david

----- Original Message -----
From: "Greg Stein" <gs...@lyra.org>
To: "APR Development List" <de...@apr.apache.org>
Sent: Tuesday, January 09, 2001 2:48 AM
Subject: Re: [PATCH] track socket options...


> On Mon, Jan 08, 2001 at 10:30:32PM -0000, David Reid wrote:
> > Folks,
> >
> > This is a small patch that's very much a starting point.  Basically
> > following Deans suggestion we should be tracking what options we have
set on
> > a socket and using the cached information to avoid system calls.  I've
used
> > an int and the system defined values as that way we can use the mask for
non
> > APR values, i.e. things like TCP_CORK.  By caching the values we also
get a
> > working apr_getsocketopt which is useful.
>
> >From <asm/socket.h> on my Linux box:
>
> #define SO_DEBUG    1
>
> >From <netinet/tcp.h>:
>
> #define      TCP_NODELAY   0x01
>
>
> In other words... you have a collision.
>
> Told ya to use the APR values :-)
>
> (for things like TCP_CORK, just have an internal flag; or possibly go
ahead
> and place it into apr_network_io.h; I mean why not?!)
>
> (oh... and if you create internal flags: leave a comment in
apr_network_io.h
> about where the other flags are to prevent confusion / collision)
>
> The patch seems to go in the right direction. The big thing will be
whether
> APR has some internal uses of setsockopt that will need to tweak the
flags.
> (or just recode the internal one to use apr_setsockopt)
>
> Cheers,
> -g
>
> --
> Greg Stein, http://www.lyra.org/
>


Re: [PATCH] track socket options...

Posted by Greg Stein <gs...@lyra.org>.
On Mon, Jan 08, 2001 at 10:30:32PM -0000, David Reid wrote:
> Folks,
> 
> This is a small patch that's very much a starting point.  Basically
> following Deans suggestion we should be tracking what options we have set on
> a socket and using the cached information to avoid system calls.  I've used
> an int and the system defined values as that way we can use the mask for non
> APR values, i.e. things like TCP_CORK.  By caching the values we also get a
> working apr_getsocketopt which is useful.