cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: TCP_NODELAY

From: Joe Halpin <j.p.h_at_comcast.net>
Date: Sun, 21 Mar 2004 15:53:06 -0600

Tor Arntsen wrote:
> On Mar 21, 21:01, "codemastr" wrote:
>
>>Well Windows does support it as well. I'm just wondering more about some of
>>the less-common OSes (IRIX, VMS, etc.)
>
> No worries about IRIX, IRIX supports almost every standard out there, and
> much better than AIX (which also has TCP_NODELAY, btw). "If it works on Linux
> it works on IRIX, although not necessarily the other way around" is a good
> rule of thumb (here at kspt we've developed for IRIX and Linux for years).
> My only VMS machine died a while ago so I don't know about that one.
>
> [...]
>
>>But really, I don't see any need for an autoconf check. Just enclose the
>>code in #ifdef TCP_NODELAY. If that is defined, then TCP_NODELAY exists. If
>>it is not defined, then TCP_NODELAY does not exist. That seems like a
>>workable solution to me...
>
> I agree.

Ok, here's my second try :-)

Joe

? .in
Index: docs/MANUAL
===================================================================
RCS file: /repository/curl/docs/MANUAL,v
retrieving revision 1.24
diff -u -r1.24 MANUAL
--- docs/MANUAL 3 Feb 2004 15:59:06 -0000 1.24
+++ docs/MANUAL 21 Mar 2004 21:47:18 -0000
@@ -748,6 +748,13 @@
 
   The usage of the -x/--proxy flag overrides the environment variables.
 
+ Additionally, curl looks for CURL_TCP_NODELAY in the environment. If it's
+ defined, the TCP_NODELAY option will be set when connecting to the
+ remote host. This will allow small TCP segments to be sent without
+ waiting for acknowledgements. This may improve performance. It may
+ also cause congestion on the network. You should understand this
+ option before using it.
+
 NETRC
 
   Unix introduced the .netrc concept a long time ago. It is a way for a user
Index: docs/curl.1
===================================================================
RCS file: /repository/curl/docs/curl.1,v
retrieving revision 1.118
diff -u -r1.118 curl.1
--- docs/curl.1 5 Mar 2004 07:55:02 -0000 1.118
+++ docs/curl.1 21 Mar 2004 21:47:19 -0000
@@ -995,6 +995,8 @@
 .IP "NO_PROXY <comma-separated list of hosts>"
 list of host names that shouldn't go through any proxy. If set to a asterisk
 '*' only, it matches all hosts.
+.IP "CURL_TCP_NODELAY"
+Tells curl to set the TCP_NODELAY option when making a connection.
 .SH EXIT CODES
 There exists a bunch of different error codes and their corresponding error
 messages that may appear during bad conditions. At the time of this writing,
Index: docs/libcurl/curl_easy_setopt.3
===================================================================
RCS file: /repository/curl/docs/libcurl/curl_easy_setopt.3,v
retrieving revision 1.82
diff -u -r1.82 curl_easy_setopt.3
--- docs/libcurl/curl_easy_setopt.3 12 Mar 2004 09:14:45 -0000 1.82
+++ docs/libcurl/curl_easy_setopt.3 21 Mar 2004 21:47:21 -0000
@@ -295,6 +295,10 @@
 .IP CURLOPT_PORT
 Pass a long specifying what remote port number to connect to, instead of the
 one specified in the URL or the default port for the used protocol.
+.IP CURLOPT_TCP_NODELAY
+Pass a long specifying whether the TCP_NODELAY option should be set or
+cleared (1 = set, 0 = clear). The option is cleared by default. This
+will have no effect after the connection has been established.
 .SH NAMES and PASSWORDS OPTIONS (Authentication)
 .IP CURLOPT_NETRC
 This parameter controls the preference of libcurl between using user names and
Index: include/curl/curl.h
===================================================================
RCS file: /repository/curl/include/curl/curl.h,v
retrieving revision 1.243
diff -u -r1.243 curl.h
--- include/curl/curl.h 12 Mar 2004 08:55:50 -0000 1.243
+++ include/curl/curl.h 21 Mar 2004 21:47:23 -0000
@@ -786,6 +786,9 @@
   /* The _LARGE version of the standard POSTFIELDSIZE option */
   CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
 
+ /* Enable the TCP_NODELAY option */
+ CINIT(TCP_NODELAY, LONG, 121),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
Index: lib/connect.c
===================================================================
RCS file: /repository/curl/lib/connect.c,v
retrieving revision 1.82
diff -u -r1.82 connect.c
--- lib/connect.c 17 Mar 2004 12:46:45 -0000 1.82
+++ lib/connect.c 21 Mar 2004 21:47:23 -0000
@@ -31,6 +31,7 @@
 #endif
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#include <netinet/tcp.h> /* for TCP_NODELAY */
 #endif
 #include <sys/ioctl.h>
 #ifdef HAVE_UNISTD_H
@@ -581,6 +582,18 @@
     sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
     if (sockfd == CURL_SOCKET_BAD)
       continue;
+
+ else if(1 == conn->tcp_nodelay)
+ {
+# ifdef TCP_NODELAY
+ socklen_t onoff = (socklen_t) data->tcp_nodelay;
+ infof(data,"Setting TCP_NODELAY for IPV6\n");
+ if(setsockopt(sockfd,IPPROTO_TCP,TCP_NODELAY,&onoff,sizeof onoff) < 0)
+ infof(data, "Could not set TCP_NODELAY: %s\n", strerror(errno));
+# else
+ infof(data,"TCP_NODELAY is not supported on this system\n");
+# endif
+ }
 #else
   /*
    * Connecting with old style IPv4-only support
@@ -600,6 +613,18 @@
       return CURLE_COULDNT_CONNECT; /* big time error */
     }
 
+ else if(1 == conn->tcp_nodelay)
+ {
+# ifdef TCP_NODELAY
+ socklen_t onoff = (socklen_t) data->tcp_nodelay;
+ infof(data, "Setting TCP_NODELAY for IPV4\n");
+ if(setsockopt(sockfd,IPPROTO_TCP,TCP_NODELAY,&onoff,sizeof onoff) < 0)
+ infof(data, "Could not set TCP_NODELAY: %s\n", strerror(errno));
+# else
+ infof(data,"TCP_NODELAY is not supported on this system\n");
+# endif
+ }
+
     /* nasty address work before connect can be made */
     memset((char *) &serv_addr, '\0', sizeof(serv_addr));
     memcpy((char *)&(serv_addr.sin_addr),
Index: lib/url.c
===================================================================
RCS file: /repository/curl/lib/url.c,v
retrieving revision 1.350
diff -u -r1.350 url.c
--- lib/url.c 12 Mar 2004 08:55:51 -0000 1.350
+++ lib/url.c 21 Mar 2004 21:47:27 -0000
@@ -1303,6 +1303,14 @@
     data->set.max_filesize = va_arg(param, curl_off_t);
     break;
 
+ case CURLOPT_TCP_NODELAY:
+ /*
+ * Enable or disable TCP_NODELAY, which will enable/disable the Nagle
+ * algorithm
+ */
+ data->tcp_nodelay = va_arg(param, long);
+ break;
+
   default:
     /* unknown tag and its companion, just ignore: */
     return CURLE_FAILED_INIT; /* correct this */
@@ -2059,6 +2067,10 @@
   conn->bits.user_passwd = data->set.userpwd?1:0;
   conn->bits.proxy_user_passwd = data->set.proxyuserpwd?1:0;
 
+ /* Pass the nagle flag from the SessionHandle struct to the connectdata
+ * struct so it will be available for Curl_connecthost(). */
+ conn->tcp_nodelay = (data->tcp_nodelay == 0) ? 0 : 1;
+
   /* This initing continues below, see the comment "Continue connectdata
    * initialization here" */
 
Index: lib/urldata.h
===================================================================
RCS file: /repository/curl/lib/urldata.h,v
retrieving revision 1.204
diff -u -r1.204 urldata.h
--- lib/urldata.h 12 Mar 2004 13:06:01 -0000 1.204
+++ lib/urldata.h 21 Mar 2004 21:47:28 -0000
@@ -576,6 +576,9 @@
   /* data used for the asynch name resolve callback */
   struct Curl_async async;
 #endif
+
+ /* This tells Curl_connectHost whether or not to enable TCP_NODELAY */
+ int tcp_nodelay;
 };
 
 /* The end of connectdata. */
@@ -906,6 +909,9 @@
 #if defined(USE_SSLEAY) && defined(HAVE_OPENSSL_ENGINE_H)
   ENGINE* engine;
 #endif /* USE_SSLEAY */
+
+ /* This tells CreateConnection() whether to enable TCP_NODELAY or not */
+ int tcp_nodelay;
 };
 
 #define LIBCURL_NAME "libcurl"
Index: src/main.c
===================================================================
RCS file: /repository/curl/src/main.c,v
retrieving revision 1.247
diff -u -r1.247 main.c
--- src/main.c 17 Mar 2004 12:46:48 -0000 1.247
+++ src/main.c 21 Mar 2004 21:47:32 -0000
@@ -3112,6 +3112,9 @@
         }
 #endif
 
+ if(getenv("CURL_TCP_NODELAY") != 0)
+ curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
+
         curl_easy_setopt(curl, CURLOPT_SSLENGINE, config->engine);
         curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);
 
Received on 2004-03-21