diff options
author | Dave Reisner <dreisner@archlinux.org> | 2012-01-24 01:28:06 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2012-02-09 18:53:51 +0100 |
commit | 705f0f7a5b6120bb783d139c9266b285a4c8acd8 (patch) | |
tree | 25e53650101274f8f178cd7f2468ee2fe4f3da28 /lib | |
parent | ea055407fa45c4247042e7370d463364f03c3136 (diff) |
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.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/connect.c | 32 | ||||
-rw-r--r-- | lib/url.c | 18 | ||||
-rw-r--r-- | lib/urldata.h | 4 |
3 files changed, 54 insertions, 0 deletions
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, @@ -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 { |