From e9b7e84870bc1bfea4969a57d15e523133b46ecb Mon Sep 17 00:00:00 2001 From: Tim Ruehsen Date: Mon, 25 Jul 2016 13:04:11 +0200 Subject: gnutls-cli: added example usage of TCP fastopen It is enabled with the new --fastopen option. --- src/cli-args.def | 6 ++++++ src/cli.c | 31 +++++++++++++++++++++++++++---- src/socket.c | 22 ++++++++++++++++------ src/socket.h | 7 ++++++- 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/src/cli-args.def b/src/cli-args.def index 96e11073ad..451f80f293 100644 --- a/src/cli-args.def +++ b/src/cli-args.def @@ -121,6 +121,12 @@ flag = { doc = ""; }; +flag = { + name = fastopen; + descrip = "Enable TCP Fast Open"; + doc = ""; +}; + flag = { name = x509fmtder; descrip = "Use DER format for certificates to read from"; diff --git a/src/cli.c b/src/cli.c index 6e87abdc99..98d1c598e0 100644 --- a/src/cli.c +++ b/src/cli.c @@ -41,6 +41,11 @@ #include #include +/* Get TCP_FASTOPEN */ +#ifdef HAVE_NETINET_TCP_H +#include +#endif + #include #include #include @@ -48,6 +53,7 @@ #include #include #include +#include /* Gnulib portability files. */ #include @@ -78,6 +84,7 @@ char service[32]=""; int record_max_size; int fingerprint; int crlf; +int fastopen; unsigned int verbose = 0; int print_cert; @@ -908,7 +915,7 @@ static int try_resume(socket_st * hd) printf ("\n\n- Connecting again- trying to resume previous session\n"); - socket_open(hd, hostname, service, udp, CONNECT_MSG); + socket_open(hd, hostname, service, udp | (fastopen << 1), CONNECT_MSG); if (HAVE_OPT(STARTTLS_PROTO)) socket_starttls(hd, OPT_ARG(STARTTLS_PROTO)); @@ -1211,7 +1218,7 @@ int main(int argc, char **argv) canonicalize_host(hostname, service, sizeof(service)); - socket_open(&hd, hostname, service, udp, CONNECT_MSG); + socket_open(&hd, hostname, service, udp | (fastopen << 1), CONNECT_MSG); hd.verbose = verbose; if (HAVE_OPT(STARTTLS_PROTO)) @@ -1623,6 +1630,15 @@ static void cmd_parser(int argc, char **argv) crlf = HAVE_OPT(CRLF); +#ifdef TCP_FASTOPEN + fastopen = HAVE_OPT(FASTOPEN); +#else + if (HAVE_OPT(FASTOPEN)) { + fprintf(stderr, "TCP Fast Open not supported for this OS\n"); + exit(1); + } +#endif + if (rest != NULL) hostname = rest; @@ -1658,8 +1674,15 @@ static int do_handshake(socket_st * socket) { int ret; - gnutls_transport_set_int(socket->session, socket->fd); - set_read_funcs(socket->session); + if (fastopen && socket->connect_addrlen) { + gnutls_transport_set_fastopen(socket->session, socket->fd, + (struct sockaddr*)&socket->connect_addr, + socket->connect_addrlen); + socket->connect_addrlen = 0; + } else { + gnutls_transport_set_int(socket->session, socket->fd); + set_read_funcs(socket->session); + } do { gnutls_handshake_set_timeout(socket->session, diff --git a/src/socket.c b/src/socket.c index bbb97f1fd4..35fd61534e 100644 --- a/src/socket.c +++ b/src/socket.c @@ -318,6 +318,7 @@ void socket_bye(socket_st * socket) freeaddrinfo(socket->addr_info); socket->addr_info = socket->ptr = NULL; + socket->connect_addrlen = 0; free(socket->ip); free(socket->hostname); @@ -353,10 +354,12 @@ void canonicalize_host(char *hostname, char *service, unsigned service_size) void socket_open(socket_st * hd, const char *hostname, const char *service, - int udp, const char *msg) + int flags, const char *msg) { struct addrinfo hints, *res, *ptr; int sd, err = 0; + int udp = flags & 1; + int fastopen = flags & 2; char buffer[MAX_BUF + 1]; char portname[16] = { 0 }; char *a_hostname = (char*)hostname; @@ -416,14 +419,21 @@ socket_open(socket_st * hd, const char *hostname, const char *service, #endif } + if (fastopen && ptr->ai_socktype == SOCK_STREAM + && (ptr->ai_family == AF_INET || ptr->ai_family == AF_INET6)) { + memcpy(&hd->connect_addr, ptr->ai_addr, ptr->ai_addrlen); + hd->connect_addrlen = ptr->ai_addrlen; - if (msg) - printf("%s '%s:%s'...\n", msg, buffer, portname); + if (msg) + printf("%s '%s:%s' (TFO)...\n", msg, buffer, portname); + } else { + if (msg) + printf("%s '%s:%s'...\n", msg, buffer, portname); - err = connect(sd, ptr->ai_addr, ptr->ai_addrlen); - if (err < 0) { - continue; + if ((err = connect(sd, ptr->ai_addr, ptr->ai_addrlen)) < 0) + continue; } + break; } diff --git a/src/socket.h b/src/socket.h index 4928065f3b..1f1394f812 100644 --- a/src/socket.h +++ b/src/socket.h @@ -1,4 +1,5 @@ #include +#include typedef struct { int fd; @@ -11,6 +12,10 @@ typedef struct { struct addrinfo *addr_info; int verbose; + /* Needed for TCP Fast Open */ + struct sockaddr_storage connect_addr; + socklen_t connect_addrlen; + /* resumption data */ gnutls_datum_t rdata; } socket_st; @@ -24,7 +29,7 @@ ssize_t socket_send(const socket_st * socket, const void *buffer, ssize_t socket_send_range(const socket_st * socket, const void *buffer, int buffer_size, gnutls_range_st * range); void socket_open(socket_st * hd, const char *hostname, const char *service, - int udp, const char *msg); + int flags, const char *msg); void socket_starttls(socket_st * hd, const char *app_proto); void socket_bye(socket_st * socket); -- cgit v1.2.1