Skip to content

Commit

Permalink
connect: add support for new TCP Fast Open API on Linux
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ghedo authored and bagder committed Nov 24, 2017
1 parent 9f691be commit 979b012
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 5 deletions.
1 change: 1 addition & 0 deletions configure.ac
Expand Up @@ -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 \
Expand Down
19 changes: 16 additions & 3 deletions lib/connect.c
Expand Up @@ -28,8 +28,10 @@
#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>
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion lib/sendf.c
Expand Up @@ -22,6 +22,10 @@

#include "curl_setup.h"

#ifdef HAVE_LINUX_TCP_H
#include <linux/tcp.h>
#endif

#include <curl/curl.h>

#include "urldata.h"
Expand Down Expand Up @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion lib/setopt.c
Expand Up @@ -26,6 +26,10 @@
#include <limits.h>
#endif

#ifdef HAVE_LINUX_TCP_H
#include <linux/tcp.h>
#endif

#include "urldata.h"
#include "url.h"
#include "progress.h"
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 979b012

Please sign in to comment.