From 6350e6c4c5fab254d67e86e85a5ade70e2e32c36 Mon Sep 17 00:00:00 2001 From: Constantine Verutin Date: Tue, 22 Feb 2011 17:52:50 -0500 Subject: [PATCH] Add new evhttp_{connection_}set_timeout_tv() functions to set finger-grained http timeouts --- evrpc.c | 6 ++-- http-internal.h | 4 +-- http.c | 69 ++++++++++++++++++++++++++++++------------- include/event2/http.h | 15 +++++++++- 4 files changed, 68 insertions(+), 26 deletions(-) diff --git a/evrpc.c b/evrpc.c index 22dd57ac..694666c9 100644 --- a/evrpc.c +++ b/evrpc.c @@ -585,8 +585,8 @@ evrpc_pool_add_connection(struct evrpc_pool *pool, * unless a timeout was specifically set for a connection, * the connection inherits the timeout from the pool. */ - if (connection->timeout == -1) - connection->timeout = pool->timeout; + if (!evutil_timerisset(&connection->timeout)) + evhttp_connection_set_timeout(connection, pool->timeout); /* * if we have any requests pending, schedule them with the new @@ -613,7 +613,7 @@ evrpc_pool_set_timeout(struct evrpc_pool *pool, int timeout_in_secs) { struct evhttp_connection *evcon; TAILQ_FOREACH(evcon, &pool->connections, next) { - evcon->timeout = timeout_in_secs; + evhttp_connection_set_timeout(evcon, timeout_in_secs); } pool->timeout = timeout_in_secs; } diff --git a/http-internal.h b/http-internal.h index 01d29132..05e286ca 100644 --- a/http-internal.h +++ b/http-internal.h @@ -83,7 +83,7 @@ struct evhttp_connection { #define EVHTTP_CON_OUTGOING 0x0002 /* multiple requests possible */ #define EVHTTP_CON_CLOSEDETECT 0x0004 /* detecting if persistent close */ - int timeout; /* timeout in seconds for events */ + struct timeval timeout; /* timeout for events */ int retry_cnt; /* retry count */ int retry_max; /* maximum number of retries */ @@ -152,7 +152,7 @@ struct evhttp { /* NULL if this server is not a vhost */ char *vhost_pattern; - int timeout; + struct timeval timeout; size_t default_max_headers_size; ev_uint64_t default_max_body_size; diff --git a/http.c b/http.c index 1c51b4b3..057a2008 100644 --- a/http.c +++ b/http.c @@ -1342,14 +1342,11 @@ evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg) evhttp_error_cb, evcon); - if (evcon->timeout == -1) + if (!evutil_timerisset(&evcon->timeout)) { bufferevent_settimeout(evcon->bufev, HTTP_READ_TIMEOUT, HTTP_WRITE_TIMEOUT); - else { - struct timeval tv; - tv.tv_sec = evcon->timeout; - tv.tv_usec = 0; - bufferevent_set_timeouts(evcon->bufev, &tv, &tv); + } else { + bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout); } /* try to start requests that have queued up on this connection */ @@ -1986,7 +1983,7 @@ evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase, evcon->max_headers_size = EV_SIZE_MAX; evcon->max_body_size = EV_SIZE_MAX; - evcon->timeout = -1; + evutil_timerclear(&evcon->timeout); evcon->retry_cnt = evcon->retry_max = 0; if ((evcon->address = mm_strdup(address)) == NULL) { @@ -2038,14 +2035,27 @@ void evhttp_connection_set_timeout(struct evhttp_connection *evcon, int timeout_in_secs) { - evcon->timeout = timeout_in_secs; + if (timeout_in_secs == -1) + evhttp_connection_set_timeout_tv(evcon, NULL); + else { + struct timeval tv; + tv.tv_sec = timeout_in_secs; + tv.tv_usec = 0; + evhttp_connection_set_timeout_tv(evcon, &tv); + } +} - if (evcon->timeout == -1) - bufferevent_settimeout(evcon->bufev, - HTTP_READ_TIMEOUT, HTTP_WRITE_TIMEOUT); - else - bufferevent_settimeout(evcon->bufev, - evcon->timeout, evcon->timeout); +void +evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon, + const struct timeval* tv) +{ + if (tv) { + evcon->timeout = *tv; + bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout); + } else { + evutil_timerclear(&evcon->timeout); + bufferevent_settimeout(evcon->bufev, HTTP_READ_TIMEOUT, HTTP_WRITE_TIMEOUT); + } } void @@ -2097,8 +2107,10 @@ evhttp_connection_connect(struct evhttp_connection *evcon) NULL /* evhttp_write_cb */, evhttp_connection_cb, evcon); - bufferevent_settimeout(evcon->bufev, 0, - evcon->timeout != -1 ? evcon->timeout : HTTP_CONNECT_TIMEOUT); + if (!evutil_timerisset(&evcon->timeout)) + bufferevent_settimeout(evcon->bufev, 0, HTTP_CONNECT_TIMEOUT); + else + bufferevent_set_timeouts(evcon->bufev, NULL, &evcon->timeout); /* make sure that we get a write callback */ bufferevent_enable(evcon->bufev, EV_WRITE); @@ -3081,7 +3093,7 @@ evhttp_new_object(void) return (NULL); } - http->timeout = -1; + evutil_timerclear(&http->timeout); evhttp_set_max_headers_size(http, EV_SIZE_MAX); evhttp_set_max_body_size(http, EV_SIZE_MAX); evhttp_set_allowed_methods(http, @@ -3246,7 +3258,24 @@ evhttp_remove_server_alias(struct evhttp *http, const char *alias) void evhttp_set_timeout(struct evhttp* http, int timeout_in_secs) { - http->timeout = timeout_in_secs; + if (timeout_in_secs == -1) { + evhttp_set_timeout_tv(http, NULL); + } else { + struct timeval tv; + tv.tv_sec = timeout_in_secs; + tv.tv_usec = 0; + evhttp_set_timeout_tv(http, &tv); + } +} + +void +evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv) +{ + if (tv) { + http->timeout = *tv; + } else { + evutil_timerclear(&http->timeout); + } } void @@ -3635,8 +3664,8 @@ evhttp_get_request(struct evhttp *http, evutil_socket_t fd, } /* the timeout can be used by the server to close idle connections */ - if (http->timeout != -1) - evhttp_connection_set_timeout(evcon, http->timeout); + if (evutil_timerisset(&http->timeout)) + evhttp_connection_set_timeout_tv(evcon, &http->timeout); /* * if we want to accept more than one request on a connection, diff --git a/include/event2/http.h b/include/event2/http.h index 4ffa7ac6..fc39bc4d 100644 --- a/include/event2/http.h +++ b/include/event2/http.h @@ -295,6 +295,14 @@ int evhttp_remove_server_alias(struct evhttp *http, const char *alias); */ void evhttp_set_timeout(struct evhttp *http, int timeout_in_secs); +/** + * Set the timeout for an HTTP request. + * + * @param http an evhttp object + * @param tv the timeout, or NULL + */ +void evhttp_set_timeout_tv(struct evhttp *http, const struct timeval* tv); + /* Request/Response functionality */ /** @@ -468,10 +476,15 @@ void evhttp_connection_set_local_address(struct evhttp_connection *evcon, void evhttp_connection_set_local_port(struct evhttp_connection *evcon, ev_uint16_t port); -/** Sets the timeout for events related to this connection */ +/** Sets the timeout in seconds for events related to this connection */ void evhttp_connection_set_timeout(struct evhttp_connection *evcon, int timeout_in_secs); +/** Sets the timeout for events related to this connection. Takes a struct + * timeval. */ +void evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon, + const struct timeval *tv); + /** Sets the retry limit for this connection - -1 repeats indefinitely */ void evhttp_connection_set_retries(struct evhttp_connection *evcon, int retry_max); -- 2.50.1