diff --git a/include/curl/curl.h b/include/curl/curl.h
index 84229bb..3bd1f26 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -1673,6 +1673,9 @@ typedef enum {
   /* Set E-xclusive stream dependency on another CURL handle */
   CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241),
 
+  /* Enables fast open on client socket */
+  CINIT(TCP_FASTOPEN, LONG, 242),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
diff --git a/lib/connect.c b/lib/connect.c
index 88041dd..84ba36a 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -162,7 +162,7 @@ tcpkeepalive(struct SessionHandle *data,
 static CURLcode
 singleipconnect(struct connectdata *conn,
                 const Curl_addrinfo *ai, /* start connecting to this */
-                curl_socket_t *sock);
+                curl_socket_t *sock, int num);
 
 /*
  * Curl_timeleft() returns the amount of milliseconds left allowed for the
@@ -576,7 +576,8 @@ static CURLcode trynextip(struct connectdata *conn,
       }
 
       if(ai) {
-        result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
+        result = singleipconnect(conn, ai, &conn->tempsock[tempindex]
+                , tempindex);
         if(result == CURLE_COULDNT_CONNECT) {
           ai = ai->ai_next;
           continue;
@@ -761,7 +762,15 @@ CURLcode Curl_is_connected(struct connectdata *conn,
 #endif
 
     /* check socket for connect */
-    rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
+    if(data->set.tcp_fastopen && conn->bits.tcpfastconnect[i]) {
+      printf("fastconnect is set to true\n");
+      rc = CURL_CSELECT_OUT;
+      conn->bits.tcpfastconnect[i] = FALSE;
+    }
+    else {
+      rc = Curl_socket_ready(CURL_SOCKET_BAD, conn->tempsock[i], 0);
+    }
+
 
     if(rc == 0) { /* no connection yet */
       if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
@@ -991,7 +1000,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
  */
 static CURLcode singleipconnect(struct connectdata *conn,
                                 const Curl_addrinfo *ai,
-                                curl_socket_t *sockp)
+                                curl_socket_t *sockp, int num)
 {
   struct Curl_sockaddr_ex addr;
   int rc;
@@ -1083,9 +1092,20 @@ static CURLcode singleipconnect(struct connectdata *conn,
 
   /* Connect TCP sockets, bind UDP */
   if(!isconnected && (conn->socktype == SOCK_STREAM)) {
-    rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
-    if(-1 == rc)
-      error = SOCKERRNO;
+    if(conn->data->set.tcp_fastopen) {
+      printf("singleipconnect: fastopen\n");
+      conn->addrforfastopen[num] = malloc(sizeof(struct Curl_sockaddr_ex));
+      memcpy(conn->addrforfastopen[num],
+             &addr, sizeof(struct Curl_sockaddr_ex));
+      conn->bits.tcpfastconnect[num] = TRUE;
+      *sockp = sockfd;
+    }
+    else {
+      rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
+      if(-1 == rc) {
+        error = SOCKERRNO;
+      }
+    }
   }
   else {
     *sockp = sockfd;
@@ -1164,7 +1184,7 @@ CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
 
   /* start connecting to first IP */
   while(conn->tempaddr[0]) {
-    result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
+    result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]), 0);
     if(!result)
       break;
     conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
diff --git a/lib/curl_setup_once.h b/lib/curl_setup_once.h
index 69d6d47..295465c 100644
--- a/lib/curl_setup_once.h
+++ b/lib/curl_setup_once.h
@@ -121,8 +121,10 @@ struct timeval {
 
 #ifdef HAVE_MSG_NOSIGNAL
 #define SEND_4TH_ARG MSG_NOSIGNAL
+#define SENDTO_4TH_ARG MSG_NOSIGNAL | MSG_FASTOPEN
 #else
 #define SEND_4TH_ARG 0
+#define SENDTO_4TH_ARG MSG_FASTOPEN
 #endif
 
 
@@ -208,6 +210,14 @@ struct timeval {
 #endif
 #endif /* HAVE_SEND */
 
+#ifndef swriteto
+#define swriteto(x,y,z,a,b) (ssize_t)sendto((SEND_TYPE_ARG1)(x), \
+                                    (SEND_TYPE_ARG2)(y), \
+                                    (SEND_TYPE_ARG3)(z), \
+                                    (SEND_TYPE_ARG4)(SENDTO_4TH_ARG), \
+                                    (struct sockaddr *)(a), \
+                                    (int)(b))
+#endif
 
 #if 0
 #if defined(HAVE_RECVFROM)
diff --git a/lib/sendf.c b/lib/sendf.c
index ea666e9..75a5870 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -37,6 +37,7 @@
 /* The last #include files should be: */
 #include "curl_memory.h"
 #include "memdebug.h"
+#include "sockaddr.h"
 
 #ifdef CURL_DO_LINEEND_CONV
 /*
@@ -253,8 +254,20 @@ CURLcode Curl_write(struct connectdata *conn,
 ssize_t Curl_send_plain(struct connectdata *conn, int num,
                         const void *mem, size_t len, CURLcode *code)
 {
+  struct Curl_sockaddr_ex *addr = NULL;
   curl_socket_t sockfd = conn->sock[num];
-  ssize_t bytes_written = swrite(sockfd, mem, len);
+
+  ssize_t bytes_written = 0;
+  if(conn->data->set.tcp_fastopen) {
+    printf("Fast opening\n");
+    addr = conn->addrforfastopen[num];
+    bytes_written = swriteto(sockfd, mem, len,
+                                   &(addr->sa_addr),
+                                   sizeof(addr->sa_addr));
+  }
+  else {
+    bytes_written = swrite(sockfd, mem, len);
+  }
 
   *code = CURLE_OK;
   if(-1 == bytes_written) {
@@ -275,6 +288,10 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
       bytes_written=0;
       *code = CURLE_AGAIN;
     }
+    else if(conn->data->set.tcp_fastopen && EINPROGRESS == err) {
+      bytes_written=0;
+      *code = CURLE_AGAIN;
+    }
     else {
       failf(conn->data, "Send failure: %s",
             Curl_strerror(conn, err));
diff --git a/lib/url.c b/lib/url.c
index d352014..5a364cd 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2686,6 +2686,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
     break;
 #endif
   }
+  case CURLOPT_TCP_FASTOPEN:
+    /*
+     * Enable or disable TCP_FASTOPEN
+     */
+    data->set.tcp_fastopen= (0 != va_arg(param, long))?TRUE:FALSE;
+    break;
   default:
     /* unknown tag and its companion, just ignore: */
     result = CURLE_UNKNOWN_OPTION;
diff --git a/lib/urldata.h b/lib/urldata.h
index fbed8f8..6f96642 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -181,6 +181,7 @@
 #include "smb.h"
 #include "wildcard.h"
 #include "multihandle.h"
+#include "connect.h"
 
 #ifdef HAVE_GSSAPI
 # ifdef HAVE_GSSGNU
@@ -553,6 +554,7 @@ struct ConnectBits {
                  connection */
   bool type_set;  /* type= was used in the URL */
   bool multiplex; /* connection is multiplexed */
+  bool tcpfastconnect[2];
 };
 
 struct hostname {
@@ -1082,6 +1084,9 @@ struct connectdata {
   struct connectbundle *bundle; /* The bundle we are member of */
 
   int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
+
+  struct Curl_sockaddr_ex *addrforfastopen[2];
+
 };
 
 /* The end of connectdata. */
@@ -1661,6 +1666,7 @@ struct UserDefined {
   struct SessionHandle *stream_depends_on;
   bool stream_depends_e; /* set or don't set the Exclusive bit */
   int stream_weight;
+  bool tcp_fastopen;      /* whether to enable FASTOPEN or not */
 };
 
 struct Names {
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 85b8bcf..7f5896e 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -214,6 +214,7 @@ struct OperationConfig {
   char *unix_socket_path;         /* path to Unix domain socket */
   bool falsestart;
   bool path_as_is;
+  bool tcp_fastopen;
   struct GlobalConfig *global;
   struct OperationConfig *prev;
   struct OperationConfig *next;   /* Always last in the struct */
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index fd20cdc..ee08523 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -278,6 +278,7 @@ static const struct LongShort aliases[]= {
   {"#",  "progress-bar",             FALSE},
   {":",  "next",                     FALSE},
   {"~",  "xattr",                    FALSE},
+  {"$l", "tcp-fastopen",            FALSE},
 };
 
 /* Split the argument of -E to 'certname' and 'passphrase' separated by colon.
@@ -805,7 +806,9 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */
         else
           return PARAM_LIBCURL_DOESNT_SUPPORT;
         break;
-
+      case 'l': /* --tcp-fastopen option */
+        config->tcp_fastopen = toggle;
+        break;
       case 'm': /* --ftp-account */
         GetStr(&config->ftp_account, nextarg);
         break;
diff --git a/src/tool_operate.c b/src/tool_operate.c
index e5506c6..700a931 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -1358,6 +1358,9 @@ static CURLcode operate_do(struct GlobalConfig *global,
         if(config->proto_default)
           my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default);
 
+        if(config->tcp_fastopen)
+          my_setopt(curl, CURLOPT_TCP_FASTOPEN, 1L);
+
         /* initialize retry vars for loop below */
         retry_sleep_default = (config->retry_delay) ?
           config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */
