From 182cc7eab4b5e5ba25e4d84243c7b7af3e00a59c Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Sat, 21 Aug 2021 09:19:29 +0200 Subject: [PATCH] HTTPS client: add support for timeouts --- include/h.h | 1 + src/ircd.c | 7 +++---- src/url_curl.c | 6 +++--- src/url_unreal.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/include/h.h b/include/h.h index 2bd07f7e9..3e895286d 100644 --- a/include/h.h +++ b/include/h.h @@ -1135,3 +1135,4 @@ extern char *prefix_with_extban(char *remainder, BanContext *b, Extban *extban, extern GeoIPResult *geoip_client(Client *client); extern GeoIPResult *geoip_lookup(char *ip); extern void free_geoip_result(GeoIPResult *r); +extern EVENT(url_socket_timeout); diff --git a/src/ircd.c b/src/ircd.c index d7cefdf13..1dab1b6c8 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -1081,10 +1081,9 @@ int InitUnrealIRCd(int argc, char *argv[]) exit(-1); while (!is_config_read_finished()) { -#ifdef USE_LIBCURL - extern EVENT(curl_socket_timeout); - curl_socket_timeout(NULL); -#endif + gettimeofday(&timeofday_tv, NULL); + timeofday = timeofday_tv.tv_sec; + url_socket_timeout(NULL); fd_select(500); } if (config_test() < 0) diff --git a/src/url_curl.c b/src/url_curl.c index 85a4eb419..a4da6a39c 100644 --- a/src/url_curl.c +++ b/src/url_curl.c @@ -193,7 +193,7 @@ static int url_socket_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *so } /* Handle timeouts. */ -EVENT(curl_socket_timeout) +EVENT(url_socket_timeout) { int dummy; @@ -201,7 +201,7 @@ EVENT(curl_socket_timeout) url_check_multi_handles(); } -static Event *curl_socket_timeout_hdl = NULL; +static Event *url_socket_timeout_hdl = NULL; /* * Initializes the URL system @@ -212,7 +212,7 @@ void url_init(void) multihandle = curl_multi_init(); curl_multi_setopt(multihandle, CURLMOPT_SOCKETFUNCTION, url_socket_cb); - curl_socket_timeout_hdl = EventAdd(NULL, "curl_socket_timeout", curl_socket_timeout, NULL, 500, 0); + url_socket_timeout_hdl = EventAdd(NULL, "url_socket_timeout", url_socket_timeout, NULL, 500, 0); } /* diff --git a/src/url_unreal.c b/src/url_unreal.c index 3e9c8fb87..6ebd15e11 100644 --- a/src/url_unreal.c +++ b/src/url_unreal.c @@ -48,6 +48,8 @@ struct Download int got_response; char *lefttoparse; time_t last_modified; + time_t download_started; + int dns_refcnt; }; /* Variables */ @@ -108,6 +110,7 @@ void download_file_async(const char *url, time_t cachetime, vFP callback, void * char *document; handle = safe_alloc(sizeof(Download)); + handle->download_started = TStime(); AddListItem(handle, downloads); if (!url_parse(url, &host, &port, &document)) @@ -149,6 +152,7 @@ void download_file_async(const char *url, time_t cachetime, vFP callback, void * unreal_https_initiate_connect(handle); } else { /* Hostname, so start resolving... */ + handle->dns_refcnt++; ares_gethostbyname(resolver_channel, handle->hostname, AF_INET, url_resolve_cb, handle); // TODO: check return value? } @@ -162,6 +166,8 @@ void url_resolve_cb(void *arg, int status, int timeouts, struct hostent *he) char ipbuf[HOSTLEN+1]; char *ip = NULL; + handle->dns_refcnt--; + if ((status != 0) || !he->h_addr_list || !he->h_addr_list[0]) { https_cancel(handle, "Unable to resolve hostname '%s'", handle->hostname); @@ -798,3 +804,26 @@ char *url_find_end_of_request(char *header, int totalsize, int *remaining_bytes) } return NULL; } + +#define DOWNLOAD_TIMEOUT 45L + +/* Handle timeouts. */ +EVENT(url_socket_timeout) +{ + Download *d, *d_next; + for (d = downloads; d; d = d_next) + { + d_next = d->next; + if (d->dns_refcnt) + continue; /* can't touch this... */ + if (TStime() - d->download_started > DOWNLOAD_TIMEOUT) + { + https_cancel(d, "Timeout after %ld seconds", DOWNLOAD_TIMEOUT); + } + } +} + +void url_init(void) +{ + EventAdd(NULL, "url_socket_timeout", url_socket_timeout, NULL, 500, 0); +}