summaryrefslogtreecommitdiff
path: root/lib/connect.c
diff options
context:
space:
mode:
authorBrad G <43330364+bakedpotat0@users.noreply.github.com>2018-11-29 12:17:21 -0600
committerDaniel Stenberg <daniel@haxx.se>2018-12-16 18:46:01 +0100
commit306a47cea67f29a1c7a19a42de85e66acb03f1d7 (patch)
tree61ffad27ec4f7a2d4e155a64d2fa3ad37b9725b7 /lib/connect.c
parent9e6518481cd4e2603b4f9e04d6cfd1a214a72726 (diff)
downloadcurl-TFO-windows.tar.gz
connect: Add TCP Fast Open support for WindowsTFO-windows
This is the former PR #3327, saved by Johannes Schindelin, rebased, squashed and pushed again. Requires Windows 10 ver 1607 or newer
Diffstat (limited to 'lib/connect.c')
-rw-r--r--lib/connect.c57
1 files changed, 55 insertions, 2 deletions
diff --git a/lib/connect.c b/lib/connect.c
index ec3cd3a79..fb6ea4f7a 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -770,8 +770,16 @@ CURLcode Curl_is_connected(struct connectdata *conn,
(void)verifyconnect(conn->tempsock[i], NULL);
#endif
- /* check socket for connect */
- rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
+#ifdef HAVE_CONNECTEX
+ /* socket isn't actually connected until the first attempted write,
+ so it doesn't appear writable here yet; spoof rc to fall into the
+ good branch (socket errors will be detected after the second pass) */
+ if(conn->bits.tcp_fastopen && !conn->fastopen_connected)
+ rc = 1;
+ else
+#endif
+ /* check socket for connect */
+ rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
if(rc == 0) { /* no connection yet */
error = 0;
@@ -994,6 +1002,13 @@ static CURLcode singleipconnect(struct connectdata *conn,
bool is_tcp;
#ifdef TCP_FASTOPEN_CONNECT
int optval = 1;
+#elif defined(HAVE_CONNECTEX)
+ int optval = 1;
+ struct sockaddr_storage ss;
+ struct sockaddr_in *si4 = (struct sockaddr_in *)&ss;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&ss;
+#endif
#endif
*sockp = CURL_SOCKET_BAD;
@@ -1113,7 +1128,45 @@ static CURLcode singleipconnect(struct connectdata *conn,
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
else
rc = 0; /* Do nothing */
+#elif defined(HAVE_CONNECTEX) /* Windows 10 (ver 1607+) */
+ /* Windows uses ConnectEx() which must be called when the first data */
+ /* is ready to be sent. For now, just set up the socket as needed but */
+ /* don't actually connect */
+ if(setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN,
+ (void *)&optval, sizeof(optval)) == SOCKET_ERROR) {
+ infof(data, "Failed to enable TCP Fast Open on fd %d, errno: %d\n",
+ sockfd, SOCKERRNO);
+ return CURLE_FAILED_INIT;
+ }
+ else
+ infof(data, "TCP_FASTOPEN set\n");
+
+ /* ConnectEx() requires a bound socket */
+ if(!conn->bits.bound) {
+ memset(&ss, 0, sizeof(ss));
+
+ if(addr.family == AF_INET) {
+ si4->sin_family = AF_INET;
+ si4->sin_addr.s_addr = INADDR_ANY;
+ }
+#if defined(USE_IPV6)
+ else if(addr.family == AF_INET6) {
+ si6->sin6_family = AF_INET6;
+ si6->sin6_addr = in6addr_any;
+ }
#endif
+ else {
+ infof(data, "Unknown protocol used with TCP Fast Open: %d\n",
+ addr.family);
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
+
+ if(bind(sockfd, (struct sockaddr *)&ss, sizeof(ss)) == 0)
+ rc = 0;
+ }
+ else
+ rc = 0;
+#endif /* defined(HAVE_CONNECTEX) */
}
else {
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);