Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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.
  • Loading branch information...
commit 705f0f7a5b6120bb783d139c9266b285a4c8acd8 1 parent ea05540
@falconindy falconindy authored committed
View
18 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
View
3  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
View
7 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;
View
32 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,
View
18 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;
View
4 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 {
Please sign in to comment.
Something went wrong with that request. Please try again.