]> granicus.if.org Git - curl/commitdiff
connect: add support for new TCP Fast Open API on Linux
authorAlessandro Ghedini <alessandro@ghedini.me>
Sun, 5 Nov 2017 23:59:55 +0000 (23:59 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 24 Nov 2017 09:49:59 +0000 (10:49 +0100)
The new API added in Linux 4.11 only requires setting a socket option
before connecting, without the whole sento() machinery.

Notably, this makes it possible to use TFO with SSL connections on Linux
as well, without the need to mess around with OpenSSL (or whatever other
SSL library) internals.

Closes #2056

configure.ac
lib/connect.c
lib/sendf.c
lib/setopt.c

index c15ff4e4ca7b844c3a22d2a2b31e556939afdfab..a72a612fb378ce2727f7dce2b9e530123da180c0 100755 (executable)
@@ -3275,6 +3275,7 @@ AC_CHECK_HEADERS(
         net/if.h \
         netinet/in.h \
         sys/un.h \
+        linux/tcp.h \
         netinet/tcp.h \
         netdb.h \
         sys/sockio.h \
index 45e18bc07bf275324ea5021b1c02472e16baa8a9..3edb71eb722398055d5b68bc2f7f054aeb54b852 100644 (file)
 #ifdef HAVE_SYS_UN_H
 #include <sys/un.h> /* for sockaddr_un */
 #endif
-#ifdef HAVE_NETINET_TCP_H
-#include <netinet/tcp.h> /* for TCP_NODELAY */
+#ifdef HAVE_LINUX_TCP_H
+#include <linux/tcp.h>
+#elif defined(HAVE_NETINET_TCP_H)
+#include <netinet/tcp.h>
 #endif
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
@@ -989,6 +991,9 @@ static CURLcode singleipconnect(struct connectdata *conn,
   char ipaddress[MAX_IPADR_LEN];
   long port;
   bool is_tcp;
+#ifdef TCP_FASTOPEN_CONNECT
+  int optval = 1;
+#endif
 
   *sockp = CURL_SOCKET_BAD;
 
@@ -1092,7 +1097,15 @@ static CURLcode singleipconnect(struct connectdata *conn,
 #  else
       rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
 #  endif /* HAVE_BUILTIN_AVAILABLE */
-#elif defined(MSG_FASTOPEN) /* Linux */
+#elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */
+      if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
+                    (void *)&optval, sizeof(optval)) < 0)
+        infof(data, "Failed to enable TCP Fast Open on fd %d\n", sockfd);
+      else
+        infof(data, "TCP_FASTOPEN_CONNECT set\n");
+
+      rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+#elif defined(MSG_FASTOPEN) /* old Linux */
       if(conn->given->flags & PROTOPT_SSL)
         rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
       else
index cbdb233fd36717bfe9b64077600b94ad99bf7bf1..a1cb8e4788bd3eb630b544acd4d104dc3815df92 100644 (file)
 
 #include "curl_setup.h"
 
+#ifdef HAVE_LINUX_TCP_H
+#include <linux/tcp.h>
+#endif
+
 #include <curl/curl.h>
 
 #include "urldata.h"
@@ -360,7 +364,7 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
      available. */
   pre_receive_plain(conn, num);
 
-#ifdef MSG_FASTOPEN /* Linux */
+#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
   if(conn->bits.tcp_fastopen) {
     bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
                            conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
index 200bfc5ab206306828e6d1fb9b7983795198da7a..70466bffb8f322ae1c54b7d6ccf0b9919b9a4c4b 100644 (file)
 #include <limits.h>
 #endif
 
+#ifdef HAVE_LINUX_TCP_H
+#include <linux/tcp.h>
+#endif
+
 #include "urldata.h"
 #include "url.h"
 #include "progress.h"
@@ -2450,7 +2454,8 @@ static CURLcode setopt(struct Curl_easy *data, CURLoption option,
     data->set.tcp_keepintvl = arg;
     break;
   case CURLOPT_TCP_FASTOPEN:
-#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
+#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \
+   defined(TCP_FASTOPEN_CONNECT)
     data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
 #else
     result = CURLE_NOT_BUILT_IN;