From b77d627d2425650d1ad7aa5c83c45ec7f542ec60 Mon Sep 17 00:00:00 2001 From: Andy Pan Date: Wed, 5 Jun 2024 11:30:16 +0800 Subject: [PATCH] tcpkeepalive: add CURLOPT_TCP_KEEPCNT and --keepalive-cnt Closes #13885 --- docs/cmdline-opts/Makefile.inc | 1 + docs/cmdline-opts/keepalive-cnt.md | 27 ++++++++ docs/cmdline-opts/keepalive-time.md | 6 +- docs/cmdline-opts/no-keepalive.md | 1 + docs/examples/keepalive.c | 3 + docs/libcurl/curl_easy_setopt.md | 4 ++ docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md | 12 ++-- docs/libcurl/opts/CURLOPT_TCP_KEEPCNT.md | 73 ++++++++++++++++++++++ docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md | 6 +- docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md | 6 +- docs/libcurl/opts/CURLOPT_TCP_NODELAY.md | 2 +- docs/libcurl/opts/Makefile.inc | 1 + docs/libcurl/symbols-in-versions | 1 + docs/options-in-versions | 1 + include/curl/curl.h | 5 +- lib/cf-socket.c | 54 +++++++++++++--- lib/easyoptions.c | 3 +- lib/setopt.c | 8 +++ lib/url.c | 1 + lib/urldata.h | 1 + src/tool_cfgable.h | 3 +- src/tool_getparam.c | 5 ++ src/tool_listhelp.c | 3 + src/tool_operate.c | 2 + tests/http/clients/upload-pausing.c | 1 + 25 files changed, 210 insertions(+), 20 deletions(-) create mode 100644 docs/cmdline-opts/keepalive-cnt.md create mode 100644 docs/libcurl/opts/CURLOPT_TCP_KEEPCNT.md diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc index 087e05c7cf..d69635e495 100644 --- a/docs/cmdline-opts/Makefile.inc +++ b/docs/cmdline-opts/Makefile.inc @@ -142,6 +142,7 @@ DPAGES = \ ipv6.md \ json.md \ junk-session-cookies.md \ + keepalive-cnt.md \ keepalive-time.md \ key-type.md \ key.md \ diff --git a/docs/cmdline-opts/keepalive-cnt.md b/docs/cmdline-opts/keepalive-cnt.md new file mode 100644 index 0000000000..0846db3e2d --- /dev/null +++ b/docs/cmdline-opts/keepalive-cnt.md @@ -0,0 +1,27 @@ +--- +c: Copyright (C) Daniel Stenberg, , et al. +SPDX-License-Identifier: curl +Long: keepalive-cnt +Arg: +Help: Maximum number of keepalive probes +Added: 8.9.0 +Category: connection +Multi: single +See-also: + - keepalive-time + - no-keepalive +Example: + - --keepalive-cnt 3 $URL +--- + +# `--keepalive-cnt` + +Set the maximum number of keepalive probes TCP should send but get no response +before dropping the connection. This option is usually used in conjunction +with --keepalive-time. + +This option is supported on Linux, *BSD/macOS, Windows \>=10.0.16299, Solaris +11.4, and recent AIX, HP-UX and more. This option has no effect if +--no-keepalive is used. + +If unspecified, the option defaults to 9. diff --git a/docs/cmdline-opts/keepalive-time.md b/docs/cmdline-opts/keepalive-time.md index 7116bcdd91..5fd7ab4b8c 100644 --- a/docs/cmdline-opts/keepalive-time.md +++ b/docs/cmdline-opts/keepalive-time.md @@ -9,6 +9,7 @@ Category: connection Multi: single See-also: - no-keepalive + - keepalive-cnt - max-time Example: - --keepalive-time 20 $URL @@ -22,7 +23,8 @@ operating systems offering the `TCP_KEEPIDLE` and `TCP_KEEPINTVL` socket options (meaning Linux, *BSD/macOS, Windows, Solaris, and recent AIX, HP-UX and more). Keepalive is used by the TCP stack to detect broken networks on idle connections. The number of missed keepalive probes before declaring the connection down is OS -dependent and is commonly 8 (*BSD/macOS/AIX), 9 (Linux/AIX) or 5/10 (Windows). -This option has no effect if --no-keepalive is used. +dependent and is commonly 8 (*BSD/macOS/AIX), 9 (Linux/AIX) or 5/10 (Windows), and +this number can be changed by specifying the curl option `keepalive-cnt`. +Note that this option has no effect if --no-keepalive is used. If unspecified, the option defaults to 60 seconds. diff --git a/docs/cmdline-opts/no-keepalive.md b/docs/cmdline-opts/no-keepalive.md index 1829e8c4e4..2c2115fe09 100644 --- a/docs/cmdline-opts/no-keepalive.md +++ b/docs/cmdline-opts/no-keepalive.md @@ -8,6 +8,7 @@ Added: 7.18.0 Multi: boolean See-also: - keepalive-time + - keepalive-cnt Example: - --no-keepalive $URL --- diff --git a/docs/examples/keepalive.c b/docs/examples/keepalive.c index 1c876bb1f5..e06d7ff37b 100644 --- a/docs/examples/keepalive.c +++ b/docs/examples/keepalive.c @@ -44,6 +44,9 @@ int main(void) /* interval time between keep-alive probes: 60 seconds */ curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L); + /* maximum number of keep-alive probes: 3 */ + curl_easy_setopt(curl, CURLOPT_TCP_KEEPCNT, 3L); + curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); res = curl_easy_perform(curl); diff --git a/docs/libcurl/curl_easy_setopt.md b/docs/libcurl/curl_easy_setopt.md index b80d0b6640..e571b60cc3 100644 --- a/docs/libcurl/curl_easy_setopt.md +++ b/docs/libcurl/curl_easy_setopt.md @@ -417,6 +417,10 @@ Idle time before sending keep-alive. See CURLOPT_TCP_KEEPIDLE(3) Interval between keep-alive probes. See CURLOPT_TCP_KEEPINTVL(3) +## CURLOPT_TCP_KEEPCNT + +Maximum number of keep-alive probes. See CURLOPT_TCP_KEEPCNT(3) + ## CURLOPT_UNIX_SOCKET_PATH Path to a Unix domain socket. See CURLOPT_UNIX_SOCKET_PATH(3) diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md b/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md index e9e80ac6a5..1efc6f6b79 100644 --- a/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md +++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPALIVE.md @@ -9,8 +9,9 @@ See-also: - CURLOPT_MAX_RECV_SPEED_LARGE (3) - CURLOPT_TCP_KEEPIDLE (3) - CURLOPT_TCP_KEEPINTVL (3) + - CURLOPT_TCP_KEEPCNT (3) Protocol: - - All + - TCP --- # NAME @@ -29,9 +30,9 @@ CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPALIVE, long probe); Pass a long. If set to 1, TCP keepalive probes are used. The delay and frequency of these probes can be controlled by the -CURLOPT_TCP_KEEPIDLE(3) and CURLOPT_TCP_KEEPINTVL(3) options, -provided the operating system supports them. Set to 0 (default behavior) to -disable keepalive probes +CURLOPT_TCP_KEEPIDLE(3), CURLOPT_TCP_KEEPINTVL(3), and CURLOPT_TCP_KEEPCNT(3) +options, provided the operating system supports them. Set to 0 (default behavior) +to disable keepalive probes. # DEFAULT @@ -55,6 +56,9 @@ int main(void) /* interval time between keep-alive probes: 60 seconds */ curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L); + /* maximum number of keep-alive probes: 3 */ + curl_easy_setopt(curl, CURLOPT_TCP_KEEPCNT, 3L); + curl_easy_perform(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPCNT.md b/docs/libcurl/opts/CURLOPT_TCP_KEEPCNT.md new file mode 100644 index 0000000000..b4ba5b38b0 --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPCNT.md @@ -0,0 +1,73 @@ +--- +c: Copyright (C) Daniel Stenberg, , et al. +SPDX-License-Identifier: curl +Title: CURLOPT_TCP_KEEPCNT +Section: 3 +Source: libcurl +See-also: + - CURLOPT_TCP_KEEPALIVE (3) + - CURLOPT_TCP_KEEPIDLE (3) + - CURLOPT_TCP_KEEPINTVL (3) +Protocol: + - TCP +--- + +# NAME + +CURLOPT_TCP_KEEPCNT - Maximum number of TCP keep-alive probes + +# SYNOPSIS + +~~~c +#include + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TCP_KEEPCNT, long cnt); +~~~ + +# DESCRIPTION + +Pass a long. Sets the number of probes to send before dropping +the connection. Not all operating systems support this option. +(Added in 8.9.0) + +The maximum value this option accepts is INT_MAX or whatever your +system allows. +Any larger value is capped to this amount. + +# DEFAULT + +9 + +# EXAMPLE + +~~~c +int main(void) +{ + CURL *curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); + + /* enable TCP keep-alive for this transfer */ + curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); + + /* set keep-alive idle time to 120 seconds */ + curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L); + + /* interval time between keep-alive probes: 60 seconds */ + curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L); + + /* maximum number of keep-alive probes: 3 */ + curl_easy_setopt(curl, CURLOPT_TCP_KEEPCNT, 3L); + + curl_easy_perform(curl); + } +} +~~~ + +# AVAILABILITY + +Added in v8.9.0 + +# RETURN VALUE + +Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not. diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md b/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md index 5f8841747d..00c2427402 100644 --- a/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md +++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPIDLE.md @@ -7,8 +7,9 @@ Source: libcurl See-also: - CURLOPT_TCP_KEEPALIVE (3) - CURLOPT_TCP_KEEPINTVL (3) + - CURLOPT_TCP_KEEPCNT (3) Protocol: - - All + - TCP --- # NAME @@ -54,6 +55,9 @@ int main(void) /* interval time between keep-alive probes: 60 seconds */ curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L); + /* maximum number of keep-alive probes: 3 */ + curl_easy_setopt(curl, CURLOPT_TCP_KEEPCNT, 3L); + curl_easy_perform(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md b/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md index 405b6ec828..7752b34282 100644 --- a/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md +++ b/docs/libcurl/opts/CURLOPT_TCP_KEEPINTVL.md @@ -7,8 +7,9 @@ Source: libcurl See-also: - CURLOPT_TCP_KEEPALIVE (3) - CURLOPT_TCP_KEEPIDLE (3) + - CURLOPT_TCP_KEEPCNT (3) Protocol: - - All + - TCP --- # NAME @@ -53,6 +54,9 @@ int main(void) /* interval time between keep-alive probes: 60 seconds */ curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L); + /* maximum number of keep-alive probes: 3 */ + curl_easy_setopt(curl, CURLOPT_TCP_KEEPCNT, 3L); + curl_easy_perform(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.md b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.md index a5b15abbf1..c4c83ae54a 100644 --- a/docs/libcurl/opts/CURLOPT_TCP_NODELAY.md +++ b/docs/libcurl/opts/CURLOPT_TCP_NODELAY.md @@ -9,7 +9,7 @@ See-also: - CURLOPT_SOCKOPTFUNCTION (3) - CURLOPT_TCP_KEEPALIVE (3) Protocol: - - All + - TCP --- # NAME diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc index bf5ea7645f..f09c5863d3 100644 --- a/docs/libcurl/opts/Makefile.inc +++ b/docs/libcurl/opts/Makefile.inc @@ -384,6 +384,7 @@ man_MANS = \ CURLOPT_TCP_KEEPALIVE.3 \ CURLOPT_TCP_KEEPIDLE.3 \ CURLOPT_TCP_KEEPINTVL.3 \ + CURLOPT_TCP_KEEPCNT.3 \ CURLOPT_TCP_NODELAY.3 \ CURLOPT_TELNETOPTIONS.3 \ CURLOPT_TFTP_BLKSIZE.3 \ diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index 90ffa378b2..ebf2cee293 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -864,6 +864,7 @@ CURLOPT_TCP_FASTOPEN 7.49.0 CURLOPT_TCP_KEEPALIVE 7.25.0 CURLOPT_TCP_KEEPIDLE 7.25.0 CURLOPT_TCP_KEEPINTVL 7.25.0 +CURLOPT_TCP_KEEPCNT 8.9.0 CURLOPT_TCP_NODELAY 7.11.2 CURLOPT_TELNETOPTIONS 7.7 CURLOPT_TFTP_BLKSIZE 7.19.4 diff --git a/docs/options-in-versions b/docs/options-in-versions index 15f5a54dfb..e329f87230 100644 --- a/docs/options-in-versions +++ b/docs/options-in-versions @@ -107,6 +107,7 @@ --ipv6 (-6) 7.10.8 --json 7.82.0 --junk-session-cookies (-j) 7.9.7 +--keepalive-cnt 8.9.0 --keepalive-time 7.18.0 --key 7.9.3 --key-type 7.9.3 diff --git a/include/curl/curl.h b/include/curl/curl.h index 2e57cd8446..45e5f4840c 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -2218,9 +2218,12 @@ typedef enum { /* millisecond version */ CURLOPT(CURLOPT_SERVER_RESPONSE_TIMEOUT_MS, CURLOPTTYPE_LONG, 324), - /* set ECH configuration */ + /* set ECH configuration */ CURLOPT(CURLOPT_ECH, CURLOPTTYPE_STRINGPOINT, 325), + /* maximum number of keepalive probes (Linux, *BSD, macOS, etc.) */ + CURLOPT(CURLOPT_TCP_KEEPCNT, CURLOPTTYPE_LONG, 326), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/cf-socket.c b/lib/cf-socket.c index c6d002ad02..f608fbe0ba 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -145,8 +145,9 @@ static void nosigpipe(struct Curl_easy *data, #if defined(USE_WINSOCK) || \ (defined(__sun) && !defined(TCP_KEEPIDLE)) || \ - (defined(__DragonFly__) && __DragonFly_version < 500702) -/* Solaris < 11.4, DragonFlyBSD < 500702 and Windows + (defined(__DragonFly__) && __DragonFly_version < 500702) || \ + (defined(_WIN32) && !defined(TCP_KEEPIDLE)) +/* Solaris < 11.4, DragonFlyBSD < 500702 and Windows < 10.0.16299 * use millisecond units. */ #define KEEPALIVE_FACTOR(x) (x *= 1000) #else @@ -177,7 +178,33 @@ tcpkeepalive(struct Curl_easy *data, sockfd, SOCKERRNO); } else { -#if defined(SIO_KEEPALIVE_VALS) +#if defined(SIO_KEEPALIVE_VALS) /* Windows */ +/* Windows 10, version 1709 (10.0.16299) and later versions */ +#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT) + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, + (const char *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPIDLE on fd " + "%" CURL_FORMAT_SOCKET_T ": errno %d", + sockfd, SOCKERRNO); + } + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, + (const char *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPINTVL on fd " + "%" CURL_FORMAT_SOCKET_T ": errno %d", + sockfd, SOCKERRNO); + } + optval = curlx_sltosi(data->set.tcp_keepcnt); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, + (const char *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPCNT on fd " + "%" CURL_FORMAT_SOCKET_T ": errno %d", + sockfd, SOCKERRNO); + } +#else /* Windows < 10.0.16299 */ struct tcp_keepalive vals; DWORD dummy; vals.onoff = 1; @@ -193,7 +220,8 @@ tcpkeepalive(struct Curl_easy *data, "%" CURL_FORMAT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); } -#else +#endif +#else /* !Windows */ #ifdef TCP_KEEPIDLE optval = curlx_sltosi(data->set.tcp_keepidle); KEEPALIVE_FACTOR(optval); @@ -238,14 +266,15 @@ tcpkeepalive(struct Curl_easy *data, /* TCP_KEEPALIVE_ABORT_THRESHOLD should equal to * TCP_KEEPCNT * TCP_KEEPINTVL on other platforms. * The default value of TCP_KEEPCNT is 9 on Linux, - * 8 on *BSD/macOS, 5 or 10 on Windows. We choose - * 9 for Solaris <11.4 because there is no default - * value for TCP_KEEPCNT on Solaris 11.4. + * 8 on *BSD/macOS, 5 or 10 on Windows. We use the + * default config for Solaris <11.4 because there is + * no default value for TCP_KEEPCNT on Solaris 11.4. * * Note that the consequent probes will not be sent * at equal intervals on Solaris, but will be sent * using the exponential backoff algorithm. */ - optval = 9 * curlx_sltosi(data->set.tcp_keepintvl); + optval = curlx_sltosi(data->set.tcp_keepcnt) * + curlx_sltosi(data->set.tcp_keepintvl); KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, (void *)&optval, sizeof(optval)) < 0) { @@ -254,6 +283,15 @@ tcpkeepalive(struct Curl_easy *data, sockfd, SOCKERRNO); } #endif +#ifdef TCP_KEEPCNT + optval = curlx_sltosi(data->set.tcp_keepcnt); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPCNT on fd " + "%" CURL_FORMAT_SOCKET_T ": errno %d", + sockfd, SOCKERRNO); + } +#endif #endif } } diff --git a/lib/easyoptions.c b/lib/easyoptions.c index c79d136707..81091c405a 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -328,6 +328,7 @@ struct curl_easyoption Curl_easyopts[] = { CURLOT_LONG, 0}, {"TCP_FASTOPEN", CURLOPT_TCP_FASTOPEN, CURLOT_LONG, 0}, {"TCP_KEEPALIVE", CURLOPT_TCP_KEEPALIVE, CURLOT_LONG, 0}, + {"TCP_KEEPCNT", CURLOPT_TCP_KEEPCNT, CURLOT_LONG, 0}, {"TCP_KEEPIDLE", CURLOPT_TCP_KEEPIDLE, CURLOT_LONG, 0}, {"TCP_KEEPINTVL", CURLOPT_TCP_KEEPINTVL, CURLOT_LONG, 0}, {"TCP_NODELAY", CURLOPT_TCP_NODELAY, CURLOT_LONG, 0}, @@ -376,6 +377,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (325 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (326 + 1)); } #endif diff --git a/lib/setopt.c b/lib/setopt.c index 7444795829..188ecb2756 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2960,6 +2960,14 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) arg = INT_MAX; data->set.tcp_keepintvl = (int)arg; break; + case CURLOPT_TCP_KEEPCNT: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + else if(arg > INT_MAX) + arg = INT_MAX; + data->set.tcp_keepcnt = (int)arg; + break; case CURLOPT_TCP_FASTOPEN: #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \ defined(TCP_FASTOPEN_CONNECT) diff --git a/lib/url.c b/lib/url.c index 02df5bd489..d3dcfd38d1 100644 --- a/lib/url.c +++ b/lib/url.c @@ -467,6 +467,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data) set->tcp_keepalive = FALSE; set->tcp_keepintvl = 60; set->tcp_keepidle = 60; + set->tcp_keepcnt = 9; set->tcp_fastopen = FALSE; set->tcp_nodelay = TRUE; set->ssl_enable_alpn = TRUE; diff --git a/lib/urldata.h b/lib/urldata.h index 8408565186..e7ce95b41c 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1733,6 +1733,7 @@ struct UserDefined { int tcp_keepidle; /* seconds in idle before sending keepalive probe */ int tcp_keepintvl; /* seconds between TCP keepalive probes */ + int tcp_keepcnt; /* maximum number of keepalive probes */ long expect_100_timeout; /* in milliseconds */ #if defined(USE_HTTP2) || defined(USE_HTTP3) diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index f0e904531a..439f5dd510 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -249,7 +249,8 @@ struct OperationConfig { bool post302; bool post303; bool nokeepalive; /* for keepalive needs */ - long alivetime; + long alivetime; /* keepalive-time */ + long alivecnt; /* keepalive-cnt */ bool content_disposition; /* use Content-disposition filename */ int default_node_flags; /* default flags to search for each 'node', which diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 869b8be0da..e0d754cf12 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -179,6 +179,7 @@ typedef enum { C_JSON, C_JUNK_SESSION_COOKIES, C_KEEPALIVE, + C_KEEPALIVE_CNT, C_KEEPALIVE_TIME, C_KEY, C_KEY_TYPE, @@ -465,6 +466,7 @@ static const struct LongShort aliases[]= { {"json", ARG_STRG, ' ', C_JSON}, {"junk-session-cookies", ARG_BOOL, 'j', C_JUNK_SESSION_COOKIES}, {"keepalive", ARG_BOOL, ' ', C_KEEPALIVE}, + {"keepalive-cnt", ARG_STRG, ' ', C_KEEPALIVE_CNT}, {"keepalive-time", ARG_STRG, ' ', C_KEEPALIVE_TIME}, {"key", ARG_FILE, ' ', C_KEY}, {"key-type", ARG_STRG, ' ', C_KEY_TYPE}, @@ -1826,6 +1828,9 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ case C_KEEPALIVE_TIME: /* --keepalive-time */ err = str2unum(&config->alivetime, nextarg); break; + case C_KEEPALIVE_CNT: /* --keepalive-cnt */ + err = str2unum(&config->alivecnt, nextarg); + break; case C_POST301: /* --post301 */ config->post301 = toggle; break; diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c index 27f49f8fa8..d49f0c15e7 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -324,6 +324,9 @@ const struct helptxt helptext[] = { {"-j, --junk-session-cookies", "Ignore session cookies read from file", CURLHELP_HTTP}, + {" --keepalive-cnt ", + "Maximum number of keepalive probes", + CURLHELP_CONNECTION}, {" --keepalive-time ", "Interval time for keepalive probes", CURLHELP_CONNECTION}, diff --git a/src/tool_operate.c b/src/tool_operate.c index 6471ae4f05..e760e052d9 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -2111,6 +2111,8 @@ static CURLcode single_transfer(struct GlobalConfig *global, my_setopt(curl, CURLOPT_TCP_KEEPIDLE, config->alivetime); my_setopt(curl, CURLOPT_TCP_KEEPINTVL, config->alivetime); } + if(config->alivecnt) + my_setopt(curl, CURLOPT_TCP_KEEPCNT, config->alivecnt); } else my_setopt(curl, CURLOPT_TCP_KEEPALIVE, 0L); diff --git a/tests/http/clients/upload-pausing.c b/tests/http/clients/upload-pausing.c index 8247e4fd9e..24e4701bd2 100644 --- a/tests/http/clients/upload-pausing.c +++ b/tests/http/clients/upload-pausing.c @@ -241,6 +241,7 @@ int main(int argc, char *argv[]) curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L); curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 1L); curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 1L); + curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 1L); /* Enable uploading. */ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); -- 2.47.3