Add TFO support to socket BIO and s_client/s_server
[openssl.git] / apps / lib / s_socket.c
index e5802d50547f09c5ddd9e1e75ae7c2a39f149ede..1ed5a213afc416a765a6c83a762e3ef3c4caa0b4 100644 (file)
@@ -64,6 +64,8 @@ BIO_ADDR *ourpeer = NULL;
  *  AF_UNSPEC
  * @type: socket type, must be SOCK_STREAM or SOCK_DGRAM
  * @protocol: socket protocol, e.g. IPPROTO_TCP or IPPROTO_UDP (or 0 for any)
+ * @tfo: flag to enable TCP Fast Open
+ * @ba_ret: BIO_ADDR that was connected to for TFO, to be freed by caller
  *
  * This will create a socket and use it to connect to a host:port, or if
  * family == AF_UNIX, to the path found in host.
@@ -76,7 +78,8 @@ BIO_ADDR *ourpeer = NULL;
  */
 int init_client(int *sock, const char *host, const char *port,
                 const char *bindhost, const char *bindport,
-                int family, int type, int protocol)
+                int family, int type, int protocol, int tfo,
+                BIO_ADDR **ba_ret)
 {
     BIO_ADDRINFO *res = NULL;
     BIO_ADDRINFO *bindaddr = NULL;
@@ -84,6 +87,10 @@ int init_client(int *sock, const char *host, const char *port,
     const BIO_ADDRINFO *bi = NULL;
     int found = 0;
     int ret;
+    int options = 0;
+
+    if (tfo && ba_ret != NULL)
+        *ba_ret = NULL;
 
     if (BIO_sock_init() != 1)
         return 0;
@@ -160,14 +167,22 @@ int init_client(int *sock, const char *host, const char *port,
             BIO_free(tmpbio);
         }
 #endif
+        if (BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP) {
+            options |= BIO_SOCK_NODELAY;
+            if (tfo)
+                options |= BIO_SOCK_TFO;
+        }
 
-        if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai),
-                         BIO_ADDRINFO_protocol(ai) == IPPROTO_TCP ? BIO_SOCK_NODELAY : 0)) {
+        if (!BIO_connect(*sock, BIO_ADDRINFO_address(ai), options)) {
             BIO_closesocket(*sock);
             *sock = INVALID_SOCKET;
             continue;
         }
 
+        /* Save the address */
+        if (tfo && ba_ret != NULL)
+            *ba_ret = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
+
         /* Success, don't try any more addresses */
         break;
     }
@@ -278,7 +293,8 @@ int report_server_accept(BIO *out, int asock, int with_address, int with_pid)
  */
 int do_server(int *accept_sock, const char *host, const char *port,
               int family, int type, int protocol, do_server_cb cb,
-              unsigned char *context, int naccept, BIO *bio_s_out)
+              unsigned char *context, int naccept, BIO *bio_s_out,
+              int tfo)
 {
     int asock = 0;
     int sock;
@@ -312,6 +328,8 @@ int do_server(int *accept_sock, const char *host, const char *port,
     sock_protocol = BIO_ADDRINFO_protocol(res);
     sock_address = BIO_ADDRINFO_address(res);
     next = BIO_ADDRINFO_next(res);
+    if (tfo && sock_type == SOCK_STREAM)
+        sock_options |= BIO_SOCK_TFO;
 #ifdef AF_INET6
     if (sock_family == AF_INET6)
         sock_options |= BIO_SOCK_V6_ONLY;