tcpkeepalive: support setting TCP keep-alive parameters on Solaris <11.4

Solaris didn't support TCP_KEEPIDLE and TCP_KEEPINTVL until 11.4,
before that it use TCP_KEEPALIVE_THRESHOLD and TCP_KEEPALIVE_ABORT_THRESHOLD
as the substitute. Therefore, for Solaris <11.4 we need to use this substitute
for setting TCP keep-alive parameters.

Ref:
https://docs.oracle.com/cd/E86824_01/html/E54777/tcp-7p.html
https://docs.oracle.com/cd/E88353_01/html/E37851/tcp-4p.html

Closes #13864
This commit is contained in:
Andy Pan 2024-06-03 15:15:55 +08:00 committed by Daniel Stenberg
parent 4edbd52267
commit f51fa8f169
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 38 additions and 5 deletions

View File

@ -19,9 +19,10 @@ Example:
Set the time a connection needs to remain idle before sending keepalive probes
and the time between individual keepalive probes. It is currently effective on
operating systems offering the `TCP_KEEPIDLE` and `TCP_KEEPINTVL` socket
options (meaning Linux, 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 9 or 10. This option has no effect if --no-keepalive is used.
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.
If unspecified, the option defaults to 60 seconds.

View File

@ -143,8 +143,10 @@ static void nosigpipe(struct Curl_easy *data,
#endif
#if defined(USE_WINSOCK) || \
(defined(__sun) && !defined(TCP_KEEPIDLE)) || \
(defined(__DragonFly__) && __DragonFly_version < 500702)
/* DragonFlyBSD < 500702 and Windows use millisecond units */
/* Solaris < 11.4, DragonFlyBSD < 500702 and Windows
* use millisecond units. */
#define KEEPALIVE_FACTOR(x) (x *= 1000)
#else
#define KEEPALIVE_FACTOR(x)
@ -210,6 +212,16 @@ tcpkeepalive(struct Curl_easy *data,
"%" CURL_FORMAT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
}
#elif defined(TCP_KEEPALIVE_THRESHOLD)
/* Solaris <11.4 style */
optval = curlx_sltosi(data->set.tcp_keepidle);
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD,
(void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set TCP_KEEPALIVE_THRESHOLD on fd "
"%" CURL_FORMAT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
}
#endif
#ifdef TCP_KEEPINTVL
optval = curlx_sltosi(data->set.tcp_keepintvl);
@ -220,6 +232,26 @@ tcpkeepalive(struct Curl_easy *data,
"%" CURL_FORMAT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
}
#elif defined(TCP_KEEPALIVE_ABORT_THRESHOLD)
/* Solaris <11.4 style */
/* 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.
*
* 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);
KEEPALIVE_FACTOR(optval);
if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD,
(void *)&optval, sizeof(optval)) < 0) {
infof(data, "Failed to set TCP_KEEPALIVE_ABORT_THRESHOLD on fd "
"%" CURL_FORMAT_SOCKET_T ": errno %d",
sockfd, SOCKERRNO);
}
#endif
#endif
}