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 13:19:43 -0600

Daniel Stenberg wrote:
> On Thu, 18 Mar 2004, Seshubabu Pasam wrote:
>
>
>>Is it possible to get a handle to the write socket after the connect. I am
>>interested in setting the TCP_NODELAY option on the socket.
>
>
> No, there's currently no such option. I wouldn't mind seeing this offered
> somehow...
>

Here's one possiblity.

Joe

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 19:15:03 -0000
@@ -748,6 +748,13 @@
 
   The usage of the -x/--proxy flag overrides the environment variables.
 
+ Additionally, curl looks for CURL_NAGLE 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 19:15:04 -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_NAGLE"
+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 19:15:09 -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_NAGLE
+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 19:15:10 -0000
@@ -786,6 +786,9 @@
   /* The _LARGE version of the standard POSTFIELDSIZE option */
   CINIT(POSTFIELDSIZE_LARGE, OFF_T, 120),
 
+ /* Enable/disable the TCP Nagle algorithm */
+ CINIT(NAGLE, 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 19:15:11 -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,14 @@
     sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
     if (sockfd == CURL_SOCKET_BAD)
       continue;
+
+ else if(1 == conn->nagle)
+ {
+ socklen_t onoff = (socklen_t) data->nagle;
+ 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
   /*
    * Connecting with old style IPv4-only support
@@ -600,6 +609,15 @@
       return CURLE_COULDNT_CONNECT; /* big time error */
     }
 
+ else if(1 == conn->nagle)
+ {
+ socklen_t onoff = (socklen_t) data->nagle;
+ socklen_t sz = sizeof onoff;
+ 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));
+ }
+
     /* 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 19:15:15 -0000
@@ -1303,6 +1303,14 @@
     data->set.max_filesize = va_arg(param, curl_off_t);
     break;
 
+ case CURLOPT_NAGLE:
+ /*
+ * Enable or disable TCP_NODELAY, which will enable/disable the Nagle
+ * algorithm
+ */
+ data->nagle = 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->nagle = (data->nagle == 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 19:15:16 -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 nagle;
 };
 
 /* 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 nagle;
 };
 
 #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 19:15:20 -0000
@@ -3112,6 +3112,9 @@
         }
 #endif
 
+ if(getenv("CURL_NAGLE") != 0)
+ curl_easy_setopt(curl, CURLOPT_NAGLE, 1);
+
         curl_easy_setopt(curl, CURLOPT_SSLENGINE, config->engine);
         curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1);
 
Received on 2004-03-21