aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/connect.c32
-rw-r--r--lib/url.c18
-rw-r--r--lib/urldata.h4
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,
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 {