From 3e8b3a031180b226854ba493e77d5b3a58d06229 Mon Sep 17 00:00:00 2001 From: Hubert Tarasiuk Date: Sun, 24 May 2015 15:55:11 +0200 Subject: [PATCH 7/9] Support TCP Fast Open in connect_to_host and connect_to_ip. * src/connect.c (cwt_context): Hold initial data in context. * src/connect.c (connect_with_timeout_callback): Send TCP TFO segment when initial data is given. * src/connect.c (connect_with_timeout): Forward initial data into context. * src/connect.c (connect_to_ip): Forward initial data. * src/connect.c (connect_to_host): Forward initial data. * src/connect.h: Update connect_to_host and connect_to_ip headers with initial data for TCP TFO. * src/ftp.c (getftp): Do not use TFO for now -> pass NULL. * src/http.c (establish_connection): Do not use TFO for now -> pass NULL. --- src/connect.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ src/connect.h | 5 +++-- src/ftp.c | 4 ++-- src/http.c | 2 +- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/connect.c b/src/connect.c index 45eb57f..4f93e2f 100644 --- a/src/connect.c +++ b/src/connect.c @@ -224,13 +224,38 @@ struct cwt_context { const struct sockaddr *addr; socklen_t addrlen; int result; + const char *initial_data; + size_t initial_data_len; }; static void connect_with_timeout_callback (void *arg) { struct cwt_context *ctx = (struct cwt_context *)arg; - ctx->result = connect (ctx->fd, ctx->addr, ctx->addrlen); +#ifdef HAVE_TFO + if (ctx->initial_data != NULL) + { + ssize_t ret = sendto (ctx->fd, ctx->initial_data, ctx->initial_data_len, + MSG_FASTOPEN, ctx->addr, ctx->addrlen); + if (ret <= 0) + ctx->result = ret; + else if (ret == ctx->initial_data_len) + ctx->result = ret; + else + { + /* We did not manage to send everything with sendto. + Transfer rest of data using fd_write. */ + ctx->result = fd_write (ctx->fd, + ctx->initial_data + ret, + ctx->initial_data_len - ret, + -1); + } + } + else +#endif + { + ctx->result = connect (ctx->fd, ctx->addr, ctx->addrlen); + } } /* Like connect, but specifies a timeout. If connecting takes longer @@ -239,12 +264,15 @@ connect_with_timeout_callback (void *arg) static int connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen, + const char *initial_data, size_t initial_data_len, double timeout) { struct cwt_context ctx; ctx.fd = fd; ctx.addr = addr; ctx.addrlen = addrlen; + ctx.initial_data = initial_data; + ctx.initial_data_len = initial_data_len; if (run_with_timeout (timeout, connect_with_timeout_callback, &ctx)) { @@ -262,11 +290,14 @@ connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen, connecting to. */ int -connect_to_ip (const ip_address *ip, int port, const char *print) +connect_to_ip (const ip_address *ip, int port, const char *print, + const char *initial_data, size_t initial_data_len, + ssize_t *connect_result) { struct sockaddr_storage ss; struct sockaddr *sa = (struct sockaddr *)&ss; int sock; + ssize_t my_connect_result; /* If PRINT is non-NULL, print the "Connecting to..." line, with PRINT being the host name we're connecting to. */ @@ -351,9 +382,12 @@ connect_to_ip (const ip_address *ip, int port, const char *print) } } + if (!connect_result) + connect_result = &my_connect_result; + *connect_result = connect_with_timeout (sock, sa, sockaddr_size (sa), initial_data, + initial_data_len, opt.connect_timeout); /* Connect the socket to the remote endpoint. */ - if (connect_with_timeout (sock, sa, sockaddr_size (sa), - opt.connect_timeout) < 0) + if (*connect_result < 0) goto err; /* Success. */ @@ -384,7 +418,8 @@ connect_to_ip (const ip_address *ip, int port, const char *print) DNS until connecting to one of them succeeds. */ int -connect_to_host (const char *host, int port) +connect_to_host (const char *host, int port, const char *init_data, + size_t init_data_len, ssize_t *connect_result) { int i, start, end; int sock; @@ -404,7 +439,8 @@ connect_to_host (const char *host, int port) for (i = start; i < end; i++) { const ip_address *ip = address_list_address_at (al, i); - sock = connect_to_ip (ip, port, host); + sock = connect_to_ip (ip, port, host, init_data, init_data_len, + connect_result); if (sock >= 0) { /* Success. */ diff --git a/src/connect.h b/src/connect.h index 5ea2616..44fdd74 100644 --- a/src/connect.h +++ b/src/connect.h @@ -40,8 +40,9 @@ as that of the covered work. */ enum { E_HOST = -100 }; -int connect_to_host (const char *, int); -int connect_to_ip (const ip_address *, int, const char *); +int connect_to_host (const char *, int, const char *, size_t, ssize_t *); +int connect_to_ip (const ip_address *, int, const char *, const char *, size_t, + ssize_t *); int bind_local (const ip_address *, int *); int accept_connection (int); diff --git a/src/ftp.c b/src/ftp.c index 68f1a33..36621e8 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -297,7 +297,7 @@ getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread, /* First: Establish the control connection. */ - csock = connect_to_host (host, port); + csock = connect_to_host (host, port, NULL, 0, NULL); if (csock == E_HOST) return HOSTERR; else if (csock < 0) @@ -870,7 +870,7 @@ Error in server response, closing control connection.\n")); { DEBUGP (("trying to connect to %s port %d\n", print_address (&passive_addr), passive_port)); - dtsock = connect_to_ip (&passive_addr, passive_port, NULL); + dtsock = connect_to_ip (&passive_addr, passive_port, NULL, NULL, 0, NULL); if (dtsock < 0) { int save_errno = errno; diff --git a/src/http.c b/src/http.c index 65fcc87..788f5fa 100644 --- a/src/http.c +++ b/src/http.c @@ -1999,7 +1999,7 @@ establish_connection (struct url *u, struct url **conn_ref, if (sock < 0) { - sock = connect_to_host (conn->host, conn->port); + sock = connect_to_host (conn->host, conn->port, NULL, 0, NULL); if (sock == E_HOST) return HOSTERR; else if (sock < 0) -- 2.4.1