You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by jo...@apache.org on 2005/08/25 14:03:57 UTC

svn commit: r240047 - in /apr/apr/trunk: build/apr_network.m4 configure.in network_io/unix/sockopt.c test/testsockopt.c

Author: jorton
Date: Thu Aug 25 05:03:51 2005
New Revision: 240047

URL: http://svn.apache.org/viewcvs?rev=240047&view=rev
Log:
Allow setting both the TCP_NODELAY and TCP_CORK socket options for
Linux >=2.6:

* build/apr_network.m4 (APR_CHECK_TCP_NODELAY_WITH_CORK): New macro.

* configure.in: Use it.

* network_io/unix/sockopt.c (apr_socket_opt_set): If
HAVE_TCP_NODELAY_WITH_CORK is defined, don't toggle TCP_NODELAY when
setting TCP_CORK.

* test/testsockopt.c (corkable): Don't test that TCP_NODELAY and
TCP_CORK are mutually exclusive; caller shouldn't care.

Reviewed by: Justin Erenkrantz

Modified:
    apr/apr/trunk/build/apr_network.m4
    apr/apr/trunk/configure.in
    apr/apr/trunk/network_io/unix/sockopt.c
    apr/apr/trunk/test/testsockopt.c

Modified: apr/apr/trunk/build/apr_network.m4
URL: http://svn.apache.org/viewcvs/apr/apr/trunk/build/apr_network.m4?rev=240047&r1=240046&r2=240047&view=diff
==============================================================================
--- apr/apr/trunk/build/apr_network.m4 (original)
+++ apr/apr/trunk/build/apr_network.m4 Thu Aug 25 05:03:51 2005
@@ -368,6 +368,60 @@
 ])
 
 dnl
+dnl Determine whether TCP_NODELAY and TCP_CORK can both be set
+dnl on a TCP socket.
+dnl
+AC_DEFUN([APR_CHECK_TCP_NODELAY_WITH_CORK], [
+AC_CACHE_CHECK([whether TCP_NODELAY and TCP_CORK can both be enabled],
+[apr_cv_tcp_nodelay_with_cork],
+[AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+]], [[
+    int fd, flag, rc;
+
+    fd = socket(AF_INET, SOCK_STREAM, 0);
+    if (fd < 0) {
+       exit(1);
+    }
+
+    flag = 1;
+    rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag);
+    if (rc < 0) {
+        perror("setsockopt TCP_NODELAY");
+        exit(2);
+    }
+
+    flag = 1;
+    rc = setsockopt(fd, IPPROTO_TCP, TCP_CORK, &flag, sizeof flag);
+    if (rc < 0) {
+        perror("setsockopt TCP_CORK");
+        exit(3);
+    }
+
+    exit(0);
+]])], [apr_cv_tcp_nodelay_with_cork=yes], [apr_cv_tcp_nodelay_with_cork=no])])
+
+if test "$apr_cv_tcp_nodelay_with_cork" = "yes"; then
+  AC_DEFINE([HAVE_TCP_NODELAY_WITH_CORK], 1,
+            [Define if TCP_NODELAY and TCP_CORK can be enabled at the same time])
+fi
+])
+
+
+dnl
 dnl see if O_NONBLOCK setting is inherited from listening sockets
 dnl
 AC_DEFUN(APR_CHECK_O_NONBLOCK_INHERITED,[

Modified: apr/apr/trunk/configure.in
URL: http://svn.apache.org/viewcvs/apr/apr/trunk/configure.in?rev=240047&r1=240046&r2=240047&view=diff
==============================================================================
--- apr/apr/trunk/configure.in (original)
+++ apr/apr/trunk/configure.in Thu Aug 25 05:03:51 2005
@@ -1879,6 +1879,7 @@
 
 APR_CHECK_TCP_NODELAY_INHERITED
 APR_CHECK_O_NONBLOCK_INHERITED
+APR_CHECK_TCP_NODELAY_WITH_CORK
 
 # Look for a way of corking TCP...
 APR_CHECK_DEFINE(TCP_CORK, netinet/tcp.h)

Modified: apr/apr/trunk/network_io/unix/sockopt.c
URL: http://svn.apache.org/viewcvs/apr/apr/trunk/network_io/unix/sockopt.c?rev=240047&r1=240046&r2=240047&view=diff
==============================================================================
--- apr/apr/trunk/network_io/unix/sockopt.c (original)
+++ apr/apr/trunk/network_io/unix/sockopt.c Thu Aug 25 05:03:51 2005
@@ -242,7 +242,13 @@
         break;
     case APR_TCP_NOPUSH:
 #if APR_TCP_NOPUSH_FLAG
+        /* TCP_NODELAY and TCP_CORK are mutually exclusive on Linux
+         * kernels < 2.6; on newer kernels they can be used together
+         * and TCP_CORK takes preference, which is the desired
+         * behaviour.  On older kernels, TCP_NODELAY must be toggled
+         * to "off" whilst TCP_CORK is in effect. */
         if (apr_is_option_set(sock, APR_TCP_NOPUSH) != on) {
+#ifndef HAVE_TCP_NODELAY_WITH_CORK
             int optlevel = IPPROTO_TCP;
             int optname = TCP_NODELAY;
 
@@ -253,11 +259,9 @@
             }
 #endif
             /* OK we're going to change some settings here... */
-            /* TCP_NODELAY is mutually exclusive, so do we have it set? */
             if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1 && on) {
-                /* If we want to set NOPUSH then if we have the TCP_NODELAY
-                 * flag set we need to switch it off...
-                 */
+                /* Now toggle TCP_NODELAY to off, if TCP_CORK is being
+                 * turned on: */
                 int tmpflag = 0;
                 if (setsockopt(sock->socketdes, optlevel, optname,
                                (void*)&tmpflag, sizeof(int)) == -1) {
@@ -268,13 +272,20 @@
             } else if (on) {
                 apr_set_option(sock, APR_RESET_NODELAY, 0);
             }
+#warning fish
+#endif /* HAVE_TCP_NODELAY_WITH_CORK */
+
             /* OK, now we can just set the TCP_NOPUSH flag accordingly...*/
             if (setsockopt(sock->socketdes, IPPROTO_TCP, APR_TCP_NOPUSH_FLAG,
                            (void*)&on, sizeof(int)) == -1) {
                 return errno;
             }
             apr_set_option(sock, APR_TCP_NOPUSH, on);
+#ifndef HAVE_TCP_NODELAY_WITH_CORK
             if (!on && apr_is_option_set(sock, APR_RESET_NODELAY)) {
+                /* Now, if TCP_CORK was just turned off, turn
+                 * TCP_NODELAY back on again if it was earlier toggled
+                 * to off: */
                 int tmpflag = 1;
                 if (setsockopt(sock->socketdes, optlevel, optname,
                                (void*)&tmpflag, sizeof(int)) == -1) {
@@ -283,6 +294,7 @@
                 apr_set_option(sock, APR_RESET_NODELAY,0);
                 apr_set_option(sock, APR_TCP_NODELAY, 1);
             }
+#endif /* HAVE_TCP_NODELAY_WITH_CORK */
         }
 #else
         return APR_ENOTIMPL;

Modified: apr/apr/trunk/test/testsockopt.c
URL: http://svn.apache.org/viewcvs/apr/apr/trunk/test/testsockopt.c?rev=240047&r1=240046&r2=240047&view=diff
==============================================================================
--- apr/apr/trunk/test/testsockopt.c (original)
+++ apr/apr/trunk/test/testsockopt.c Thu Aug 25 05:03:51 2005
@@ -102,7 +102,9 @@
 
     rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
-    ABTS_INT_EQUAL(tc, 0, ck);
+    /* TCP_NODELAY is now in an unknown state; it may be zero if
+     * TCP_NOPUSH and TCP_NODELAY are mutually exclusive on this
+     * platform, e.g. Linux < 2.6. */
 
     rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
     ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);