Commit 705f0f7a authored by Dave Reisner's avatar Dave Reisner Committed by Daniel Stenberg
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.
parent ea055407
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -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
+3 −0
Original line number Diff line number Diff line
@@ -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
+7 −0
Original line number Diff line number Diff line
@@ -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;

+32 −0
Original line number Diff line number Diff line
@@ -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,
+18 −0
Original line number Diff line number Diff line
@@ -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;
Loading