Skip to content

Commit f0de141

Browse files
committed
cf-socket: limit use of TCP_KEEP* to Windows 10.0.16299+ at runtime
Before this patch `TCP_KEEP*` socket options were unconditionally used if the build-time SDK supported them. This caused curl logging errors (or trace messages since curl#19527) on Windows versions missing support for them. After this patch, use them only when the runtime environment supports it and fall back to the alternate method (`SIO_KEEPALIVE_VALS`) dynamically. Also: - log a trace message when using the Win10 method. - document which SDK versions offer `TCP_KEEP*` macros. Ref: https://learn.microsoft.com/windows/win32/winsock/ipproto-tcp-socket-options Ref: https://learn.microsoft.com/windows/win32/winsock/sio-keepalive-vals Reported-by: Aleksandr Sergeev Fixes curl#19520 Follow-up to dc34498 curl#19527 Closes curl#19559
1 parent f2460e2 commit f0de141

1 file changed

Lines changed: 58 additions & 60 deletions

File tree

lib/cf-socket.c

Lines changed: 58 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,7 @@ static void nosigpipe(struct Curl_cfilter *cf,
149149
#define nosigpipe(x,y,z) Curl_nop_stmt
150150
#endif
151151

152-
#if defined(USE_WINSOCK) && \
153-
defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT)
154-
/* Win 10, v 1709 (10.0.16299) and later can use SetSockOpt TCP_KEEP____
155-
* so should use seconds */
156-
#define CURL_WINSOCK_KEEP_SSO
157-
#define KEEPALIVE_FACTOR(x)
158-
#elif defined(USE_WINSOCK) || \
152+
#if defined(USE_WINSOCK) || \
159153
(defined(__sun) && !defined(TCP_KEEPIDLE)) || \
160154
(defined(__DragonFly__) && __DragonFly_version < 500702) || \
161155
(defined(_WIN32) && !defined(TCP_KEEPIDLE))
@@ -166,17 +160,6 @@ static void nosigpipe(struct Curl_cfilter *cf,
166160
#define KEEPALIVE_FACTOR(x)
167161
#endif
168162

169-
/* Offered by mingw-w64 and MS SDK. Latter only when targeting Win7+. */
170-
#if defined(USE_WINSOCK) && !defined(SIO_KEEPALIVE_VALS)
171-
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
172-
173-
struct tcp_keepalive {
174-
u_long onoff;
175-
u_long keepalivetime;
176-
u_long keepaliveinterval;
177-
};
178-
#endif
179-
180163
static void
181164
tcpkeepalive(struct Curl_cfilter *cf,
182165
struct Curl_easy *data,
@@ -192,49 +175,64 @@ tcpkeepalive(struct Curl_cfilter *cf,
192175
sockfd, SOCKERRNO);
193176
}
194177
else {
195-
#ifdef SIO_KEEPALIVE_VALS /* Windows */
196-
/* Windows 10, version 1709 (10.0.16299) and later versions */
197-
#ifdef CURL_WINSOCK_KEEP_SSO
198-
optval = curlx_sltosi(data->set.tcp_keepidle);
199-
KEEPALIVE_FACTOR(optval);
200-
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
201-
(const char *)&optval, sizeof(optval)) < 0) {
202-
CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPIDLE on fd "
203-
"%" FMT_SOCKET_T ": errno %d",
204-
sockfd, SOCKERRNO);
205-
}
206-
optval = curlx_sltosi(data->set.tcp_keepintvl);
207-
KEEPALIVE_FACTOR(optval);
208-
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
209-
(const char *)&optval, sizeof(optval)) < 0) {
210-
CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPINTVL on fd "
211-
"%" FMT_SOCKET_T ": errno %d",
212-
sockfd, SOCKERRNO);
213-
}
214-
optval = curlx_sltosi(data->set.tcp_keepcnt);
215-
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT,
216-
(const char *)&optval, sizeof(optval)) < 0) {
217-
CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPCNT on fd "
218-
"%" FMT_SOCKET_T ": errno %d",
219-
sockfd, SOCKERRNO);
178+
#ifdef USE_WINSOCK
179+
/* Offered by mingw-w64 v12+. MS SDK ~10+/~VS2017+. */
180+
#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT)
181+
/* Windows 10, version 1709 (10.0.16299) and later versions can use
182+
setsockopt() TCP_KEEP*. Older versions return with failure. */
183+
if(curlx_verify_windows_version(10, 0, 16299, PLATFORM_WINNT,
184+
VERSION_GREATER_THAN_EQUAL)) {
185+
CURL_TRC_CF(data, cf, "Set TCP_KEEP* on fd=%" FMT_SOCKET_T, sockfd);
186+
optval = curlx_sltosi(data->set.tcp_keepidle);
187+
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
188+
(const char *)&optval, sizeof(optval)) < 0) {
189+
CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPIDLE on fd "
190+
"%" FMT_SOCKET_T ": errno %d",
191+
sockfd, SOCKERRNO);
192+
}
193+
optval = curlx_sltosi(data->set.tcp_keepintvl);
194+
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
195+
(const char *)&optval, sizeof(optval)) < 0) {
196+
CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPINTVL on fd "
197+
"%" FMT_SOCKET_T ": errno %d",
198+
sockfd, SOCKERRNO);
199+
}
200+
optval = curlx_sltosi(data->set.tcp_keepcnt);
201+
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT,
202+
(const char *)&optval, sizeof(optval)) < 0) {
203+
CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPCNT on fd "
204+
"%" FMT_SOCKET_T ": errno %d",
205+
sockfd, SOCKERRNO);
206+
}
220207
}
221-
#else /* Windows < 10.0.16299 */
222-
struct tcp_keepalive vals;
223-
DWORD dummy;
224-
vals.onoff = 1;
225-
optval = curlx_sltosi(data->set.tcp_keepidle);
226-
KEEPALIVE_FACTOR(optval);
227-
vals.keepalivetime = (u_long)optval;
228-
optval = curlx_sltosi(data->set.tcp_keepintvl);
229-
KEEPALIVE_FACTOR(optval);
230-
vals.keepaliveinterval = (u_long)optval;
231-
if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
232-
NULL, 0, &dummy, NULL, NULL) != 0) {
233-
CURL_TRC_CF(data, cf, "Failed to set SIO_KEEPALIVE_VALS on fd "
234-
"%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO);
208+
else
209+
#endif /* TCP_KEEPIDLE && TCP_KEEPINTVL && TCP_KEEPCNT */
210+
{
211+
/* Offered by mingw-w64 and MS SDK. Latter only when targeting Win7+. */
212+
#ifndef SIO_KEEPALIVE_VALS
213+
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
214+
struct tcp_keepalive {
215+
u_long onoff;
216+
u_long keepalivetime;
217+
u_long keepaliveinterval;
218+
};
219+
#endif
220+
struct tcp_keepalive vals;
221+
DWORD dummy;
222+
vals.onoff = 1;
223+
optval = curlx_sltosi(data->set.tcp_keepidle);
224+
KEEPALIVE_FACTOR(optval);
225+
vals.keepalivetime = (u_long)optval;
226+
optval = curlx_sltosi(data->set.tcp_keepintvl);
227+
KEEPALIVE_FACTOR(optval);
228+
vals.keepaliveinterval = (u_long)optval;
229+
if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID)&vals, sizeof(vals),
230+
NULL, 0, &dummy, NULL, NULL) != 0) {
231+
CURL_TRC_CF(data, cf, "Failed to set SIO_KEEPALIVE_VALS on fd "
232+
"%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO);
233+
}
235234
}
236-
#endif
237-
#else /* !Windows */
235+
#else /* !USE_WINSOCK */
238236
#ifdef TCP_KEEPIDLE
239237
optval = curlx_sltosi(data->set.tcp_keepidle);
240238
KEEPALIVE_FACTOR(optval);
@@ -303,7 +301,7 @@ tcpkeepalive(struct Curl_cfilter *cf,
303301
"%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO);
304302
}
305303
#endif
306-
#endif
304+
#endif /* USE_WINSOCK */
307305
}
308306
}
309307

0 commit comments

Comments
 (0)