← Commit list

abcb5349e3

Daniel Stenberg
Daniel Stenberg
2026-08-06
SUCCESS Duration: 404s

Subject

cf-socket: disable TCP SYN retransmissions for localhost on Windows

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

.github/scripts/typos.toml+2 -0
@@ -14,6 +14,8 @@ extend-ignore-identifiers-re = [
"^(clen|req_clen|smtp_perform_helo|smtp_state_helo_resp|Tru64|_stati64)$",
"(_ccontains|_controllen|O_WRONLY|secur32)",
"proxys", # this should be limited to tests/http/*. Short for secure proxy.
+ "rto", # (TCP) retransmission timeout
+ "RTO"
]
extend-ignore-re = [
lib/cf-socket.c+56 -5
@@ -81,7 +81,9 @@
#include "curlx/version_win32.h"
#include "curlx/strerr.h"
#include "curlx/strparse.h"
-
+#ifdef _WIN32
+#include <mstcpip.h> /* for TCP_INITIAL_RTO_PARAMETERS */
+#endif
/* retrieves ip address and port from a sockaddr structure. note it calls
* curlx_inet_ntop which sets errno on fail, not SOCKERRNO.
@@ -1141,6 +1143,51 @@ static int cf_socktype(int x)
return x;
}
+#ifdef _WIN32
+
+/* Offered by mingw-w64 v10+, MS SDK 8.0/~VS2012+ */
+#ifndef SIO_TCP_INITIAL_RTO
+#define SIO_TCP_INITIAL_RTO _WSAIOW(IOC_VENDOR, 17)
+#define TCP_INITIAL_RTO_DEFAULT_RTT 0
+
+/* !checksrc! disable TYPEDEFSTRUCT 1 */
+typedef struct _TCP_INITIAL_RTO_PARAMETERS {
+ USHORT Rtt;
+ UCHAR MaxSynRetransmissions;
+} TCP_INITIAL_RTO_PARAMETERS;
+#endif
+
+#ifndef TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS
+#define TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS 0xFE /* -2 */
+#endif
+
+static bool targets_localhost(struct cf_socket_ctx *ctx)
+{
+ return (((ctx->addr.family == AF_INET) &&
+ !strcmp(ctx->ip.remote_ip, "127.0.0.1")) ||
+ ((ctx->addr.family == AF_INET6) &&
+ !strcmp(ctx->ip.remote_ip, "::1")));
+}
+
+/* disable TCP SYN retransmissions for localhost connection on Windows to
+ detect problems faster */
+static void tcplocalhost(struct Curl_cfilter *cf,
+ curl_socket_t sockfd)
+{
+ if(targets_localhost(cf->ctx)) {
+ TCP_INITIAL_RTO_PARAMETERS rto;
+ DWORD bytes = 0;
+ memset(&rto, 0, sizeof(rto));
+ rto.Rtt = TCP_INITIAL_RTO_DEFAULT_RTT;
+ rto.MaxSynRetransmissions = TCP_INITIAL_RTO_NO_SYN_RETRANSMISSIONS;
+ (void)WSAIoctl(sockfd, SIO_TCP_INITIAL_RTO, &rto, sizeof(rto),
+ NULL, 0, &bytes, NULL, NULL);
+ }
+}
+#else
+#define tcplocalhost(x, y)
+#endif
+
static CURLcode cf_socket_open(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
@@ -1214,11 +1261,15 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
is_tcp = (ctx->addr.family == AF_INET) &&
cf_socktype(ctx->addr.socktype) == SOCK_STREAM;
#endif
- if(is_tcp && data->set.tcp_nodelay)
- tcpnodelay(cf, data, ctx->sock);
+ if(is_tcp) {
+ if(data->set.tcp_nodelay)
+ tcpnodelay(cf, data, ctx->sock);
- if(is_tcp && data->set.tcp_keepalive)
- tcpkeepalive(cf, data, ctx->sock);
+ if(data->set.tcp_keepalive)
+ tcpkeepalive(cf, data, ctx->sock);
+
+ tcplocalhost(cf, ctx->sock);
+ }
if(data->set.fsockopt) {
/* activate callback for setting socket options */