summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessandro Ghedini <alessandro@ghedini.me>2016-04-03 13:08:28 +0100
committerDaniel Stenberg <daniel@haxx.se>2016-04-18 23:21:50 +0200
commit03de4e4b2192bec7de94d2d5abd2a25f86c17ac3 (patch)
tree689fd77d0022d451ed0d1a5947519ac493cedc49
parentd49087f6bc95d159eeb1172173fc1e95411041fa (diff)
downloadcurl-03de4e4b2192bec7de94d2d5abd2a25f86c17ac3.tar.gz
connect: implement TCP Fast Open for Linux
Closes #660
-rw-r--r--docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.33
-rw-r--r--lib/connect.c6
-rw-r--r--lib/sendf.c15
-rw-r--r--lib/url.c2
4 files changed, 20 insertions, 6 deletions
diff --git a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3 b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3
index 6f6ddba72..f8f934384 100644
--- a/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3
+++ b/docs/libcurl/opts/CURLOPT_TCP_FASTOPEN.3
@@ -40,7 +40,8 @@ All
.SH EXAMPLE
TODO
.SH AVAILABILITY
-Added in 7.49.0. This option is currently only supported on OS X El Capitan.
+Added in 7.49.0. This option is currently only supported on Linux and OS X
+El Capitan.
.SH RETURN VALUE
Returns CURLE_OK if fast open is supported by the operating system, otherwise
returns CURLE_NOT_BUILT_IN.
diff --git a/lib/connect.c b/lib/connect.c
index a4eb56d00..bfc22992c 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -668,7 +668,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
/* there's no connection! */
return;
- if(!conn->bits.reuse) {
+ if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
int error;
len = sizeof(struct Curl_sockaddr_storage);
@@ -776,7 +776,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
trynextip(conn, sockindex, 1);
}
}
- else if(rc == CURL_CSELECT_OUT) {
+ else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
if(verifyconnect(conn->tempsock[i], &error)) {
/* we are connected with TCP, awesome! */
@@ -1109,6 +1109,8 @@ static CURLcode singleipconnect(struct connectdata *conn,
rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
NULL, 0, NULL, NULL);
+#elif defined(MSG_FASTOPEN) /* Linux */
+ rc = 0; /* Do nothing */
#endif
}
else {
diff --git a/lib/sendf.c b/lib/sendf.c
index ea04ae83e..a75c5c743 100644
--- a/lib/sendf.c
+++ b/lib/sendf.c
@@ -254,7 +254,17 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
const void *mem, size_t len, CURLcode *code)
{
curl_socket_t sockfd = conn->sock[num];
- ssize_t bytes_written = swrite(sockfd, mem, len);
+ ssize_t bytes_written;
+
+#ifdef MSG_FASTOPEN /* Linux */
+ if(conn->bits.tcp_fastopen) {
+ bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
+ conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen);
+ conn->bits.tcp_fastopen = FALSE;
+ }
+ else
+#endif
+ bytes_written = swrite(sockfd, mem, len);
*code = CURLE_OK;
if(-1 == bytes_written) {
@@ -268,7 +278,8 @@ ssize_t Curl_send_plain(struct connectdata *conn, int num,
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
due to its inability to send off data without blocking. We therefor
treat both error codes the same here */
- (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
+ (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err) ||
+ (EINPROGRESS == err)
#endif
) {
/* this is just a case of EWOULDBLOCK */
diff --git a/lib/url.c b/lib/url.c
index e76d4e8e0..f1028f34c 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -2633,7 +2633,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.tcp_keepintvl = va_arg(param, long);
break;
case CURLOPT_TCP_FASTOPEN:
-#if defined(CONNECT_DATA_IDEMPOTENT)
+#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
#else
result = CURLE_NOT_BUILT_IN;