From 705f0f7a5b6120bb783d139c9266b285a4c8acd8 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Tue, 24 Jan 2012 01:28:06 +0000 Subject: add library support for tuning TCP_KEEPALIVE This adds three new options to control the behavior of TCP keepalives: - CURLOPT_TCP_KEEPALIVE: enable/disable probes - CURLOPT_TCP_KEEPIDLE: idle time before sending first probe - CURLOPT_TCP_KEEPINTVL: delay between successive probes While not all operating systems support the TCP_KEEPIDLE and TCP_KEEPINTVL knobs, the library will still allow these options to be set by clients, silently ignoring the values. --- docs/libcurl/curl_easy_setopt.3 | 18 ++++++++++++++++++ docs/libcurl/symbols-in-versions | 3 +++ include/curl/curl.h | 7 +++++++ lib/connect.c | 32 ++++++++++++++++++++++++++++++++ lib/url.c | 18 ++++++++++++++++++ lib/urldata.h | 4 ++++ 6 files changed, 82 insertions(+) diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index d94a84b78..a7688a7d0 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -915,6 +915,24 @@ overdone. .IP CURLOPT_ADDRESS_SCOPE Pass a long specifying the scope_id value to use when connecting to IPv6 link-local or site-local addresses. (Added in 7.19.0) + +.IP CURLOPT_TCP_KEEPALIVE +Pass a long. If set to 1, TCP keepalive probes will be sent. The delay and +frequency of these probes can be controlled by the \fICURLOPT_TCP_KEEPIDLE\fP +and \fICURLOPT_TCP_KEEPINTVL\fP options, provided the operating system supports +them. Set to 0 (default behavior) to disable keepalive probes (Added in +7.24.1). + +.IP CURLOPT_TCP_KEEPIDLE +Pass a long. Sets the delay, in seconds, that the operating system will wait +while the connection is idle before sending keepalive probes. Not all operating +systems support this option. (Added in 7.24.1) + +.IP CURLOPT_TCP_KEEPINTVL +Pass a long. Sets the interval, in seconds, that the operating system will wait +between sending keepalive probes. Not all operating systems support this +option. (Added in 7.24.1) + .SH NAMES and PASSWORDS OPTIONS (Authentication) .IP CURLOPT_NETRC This parameter controls the preference of libcurl between using user names and diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index 73d50a2b2..a9f8a9d6e 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -486,6 +486,9 @@ CURLOPT_SSL_SESSIONID_CACHE 7.16.0 CURLOPT_SSL_VERIFYHOST 7.8.1 CURLOPT_SSL_VERIFYPEER 7.4.2 CURLOPT_STDERR 7.1 +CURLOPT_TCP_KEEPALIVE 7.24.1 +CURLOPT_TCP_KEEPIDLE 7.24.1 +CURLOPT_TCP_KEEPINTVL 7.24.1 CURLOPT_TCP_NODELAY 7.11.2 CURLOPT_TELNETOPTIONS 7.7 CURLOPT_TFTP_BLKSIZE 7.19.4 diff --git a/include/curl/curl.h b/include/curl/curl.h index 59a5c796a..2a9957e9c 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -1499,6 +1499,13 @@ typedef enum { of miliseconds. */ CINIT(ACCEPTTIMEOUT_MS, LONG, 212), + /* Set TCP keepalive */ + CINIT(TCP_KEEPALIVE, LONG, 213), + + /* non-universal keepalive knobs (Linux, AIX, HP-UX, more) */ + CINIT(TCP_KEEPIDLE, LONG, 214), + CINIT(TCP_KEEPINTVL, LONG, 215), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/connect.c b/lib/connect.c index b5082d896..5747b0431 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -91,6 +91,35 @@ static bool verifyconnect(curl_socket_t sockfd, int *error); +static void +tcpkeepalive(struct SessionHandle *data, + int sockfd) +{ + int optval = data->set.tcp_keepalive; + + /* only set IDLE and INTVL if setting KEEPALIVE is successful */ + if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd); + } + else { +#ifdef TCP_KEEPIDLE + optval = data->set.tcp_keepidle; + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd); + } +#endif +#ifdef TCP_KEEPINTVL + optval = data->set.tcp_keepintvl; + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, + (void *)&optval, sizeof(optval)) < 0) { + infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd); + } +#endif + } +} + static CURLcode singleipconnect(struct connectdata *conn, const Curl_addrinfo *ai, /* start connecting to this */ @@ -876,6 +905,9 @@ singleipconnect(struct connectdata *conn, Curl_sndbufset(sockfd); + if(data->set.tcp_keepalive) + tcpkeepalive(data, sockfd); + if(data->set.fsockopt) { /* activate callback for setting socket options */ error = data->set.fsockopt(data->set.sockopt_client, diff --git a/lib/url.c b/lib/url.c index 395055f4e..c89234d74 100644 --- a/lib/url.c +++ b/lib/url.c @@ -748,6 +748,13 @@ CURLcode Curl_init_userdefined(struct UserDefined *set) set->chunk_bgn = ZERO_NULL; set->chunk_end = ZERO_NULL; + /* tcp keepalives are disabled by default, but provide reasonable values for + * the interval and idle times. + */ + set->tcp_keepalive = 0; + set->tcp_keepintvl = 60; + set->tcp_keepidle = 60; + return res; } @@ -811,6 +818,7 @@ CURLcode Curl_open(struct SessionHandle **curl) multi stack. */ } + if(res) { Curl_resolver_cleanup(data->state.resolver); if(data->state.headerbuff) @@ -2545,6 +2553,16 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, result = Curl_set_dns_servers(data, va_arg(param, char *)); break; + case CURLOPT_TCP_KEEPALIVE: + data->set.tcp_keepalive = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_TCP_KEEPIDLE: + data->set.tcp_keepidle = va_arg(param, long); + break; + case CURLOPT_TCP_KEEPINTVL: + data->set.tcp_keepintvl = va_arg(param, long); + break; + default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION; diff --git a/lib/urldata.h b/lib/urldata.h index adabf5b73..a959bc716 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1539,6 +1539,10 @@ struct UserDefined { long gssapi_delegation; /* GSSAPI credential delegation, see the documentation of CURLOPT_GSSAPI_DELEGATION */ + + bool tcp_keepalive; /* use TCP keepalives */ + long tcp_keepidle; /* seconds in idle before sending keepalive probe */ + long tcp_keepintvl; /* seconds between TCP keepalive probes */ }; struct Names { -- cgit v1.2.1