Skip to content

Commit

Permalink
housekeeping: Add housekeeping for connections
Browse files Browse the repository at this point in the history
Add functionality so that protocols can do custom keepalive on their
connections, when an external API function is called.
  • Loading branch information
maxdymond committed Jul 4, 2017
1 parent 7121a99 commit 6ad9973
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/curl/easy.h
Expand Up @@ -29,6 +29,7 @@ CURL_EXTERN CURL *curl_easy_init(void);
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
CURL_EXTERN CURLcode curl_easy_housekeeping(CURL *curl);

/*
* NAME curl_easy_getinfo()
Expand Down
15 changes: 15 additions & 0 deletions lib/easy.c
Expand Up @@ -1137,3 +1137,18 @@ CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer,

return result;
}

/*
* Performs housekeeping functions.
*/
CURLcode curl_easy_housekeeping(struct Curl_easy *data)
{
if(data->multi_easy) {
/* Use the common function to do housekeeping for connections. */
return Curl_housekeeping(&data->multi_easy->conn_cache, data);
}
else {
/* No connections, so just return success */
return CURLE_OK;
}
}
28 changes: 27 additions & 1 deletion lib/http2.c
Expand Up @@ -181,17 +181,43 @@ static bool http2_connisdead(struct connectdata *check)
return ret_val;
}


static unsigned int http2_conncheck(struct connectdata *check,
unsigned int checks_to_perform)
{
unsigned int ret_val = CONNRESULT_NONE;
struct http_conn *c = &check->proto.httpc;
int rc;
bool send_frames = false;

if(checks_to_perform & CONNCHECK_ISDEAD) {
if(http2_connisdead(check))
ret_val |= CONNRESULT_DEAD;
}

if(checks_to_perform & CONNCHECK_KEEPALIVE) {
struct timeval now = Curl_tvnow();
time_t elapsed = Curl_tvdiff(now, check->keepalive);

if(elapsed > 60000L) {
/* Perform an HTTP/2 PING */
rc = nghttp2_submit_ping(c->h2, 0, ZERO_NULL);
infof(check->data, "Sending HTTP/2 PING (returned %d)\n", rc);

if(!rc) {
/* Successfully added a PING frame to the session. Need to flag this
so the frame is sent. */
send_frames = true;
}

check->keepalive = now;
}
}

if(send_frames) {
rc = nghttp2_session_send(c->h2);
infof(check->data, "HTTP/2 session send returned %d \n", rc);
}

return ret_val;
}

Expand Down
29 changes: 29 additions & 0 deletions lib/url.c
Expand Up @@ -4196,6 +4196,9 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
/* Store creation time to help future close decision making */
conn->created = Curl_tvnow();

/* Store current time to give a baseline to keepalive connection times. */
conn->keepalive = Curl_tvnow();

conn->data = data; /* Setup the association between this connection
and the Curl_easy */

Expand Down Expand Up @@ -7153,3 +7156,29 @@ static unsigned int get_protocol_family(unsigned int protocol)

return family;
}

/*
* Wrapper to call housekeeping functions in Curl_conncache_foreach()
*
* Returns always 0.
*/
static int housekeeping(struct connectdata *conn,
void *param)
{
if(conn->handler->connection_check) {
/* Do a protocol-specific keepalive check on the connection. */
conn->handler->connection_check(conn, CONNCHECK_KEEPALIVE);
}

return 0; /* continue iteration */
}

CURLcode Curl_housekeeping(struct conncache *conn_cache,
void *data)
{
/* Loop over every connection and do housekeeping. */
Curl_conncache_foreach(conn_cache,
data,
housekeeping);
return CURLE_OK;
}
3 changes: 3 additions & 0 deletions lib/url.h
Expand Up @@ -90,4 +90,7 @@ void Curl_verboseconnect(struct connectdata *conn);
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
!conn->bits.proxy_ssl_connected[SECONDARYSOCKET])

CURLcode Curl_housekeeping(struct conncache *conn_cache,
void *data);

#endif /* HEADER_CURL_URL_H */
6 changes: 6 additions & 0 deletions lib/urldata.h
Expand Up @@ -867,6 +867,7 @@ struct Curl_handler {

#define CONNCHECK_NONE 0 /* No checks */
#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */
#define CONNCHECK_KEEPALIVE (1<<1) /* Perform any keepalive function. */

#define CONNRESULT_NONE 0 /* No extra information. */
#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */
Expand Down Expand Up @@ -1051,6 +1052,11 @@ struct connectdata {

long ip_version; /* copied from the Curl_easy at creation time */

/* Protocols can use a custom keepalive mechanism to keep connections alive.
This allows those protocols to track the last time the keepalive mechanism
was used on this connection. */
struct timeval keepalive;

/**** curl_get() phase fields */

curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */
Expand Down

0 comments on commit 6ad9973

Please sign in to comment.