cf-socket: disable TCP SYN retransmissions for localhost on Windows
No binary (build failed)
—
(log yok)
| @@ -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 = [ | |
| @@ -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 */ | |