bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch http_client_context:
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch Shared context between multiple independent HTTP clients. This allows host
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch name lookup data, peer status and idle connections to be shared between
d67f004ebf944adca3ba09ed547febfa75442476Stephan Bosch Acts much like a browser; it is not dedicated to a single host. Client can
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch accept requests to different hosts, which can be served at different IPs.
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch Redirects are handled in the background by making a new connection.
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch Connections to new hosts are created once needed for servicing a request.
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch http_client_request:
d67f004ebf944adca3ba09ed547febfa75442476Stephan Bosch The request semantics are similar to imapc commands. Create a request,
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch optionally modify some aspects of it, and finally submit it. Once finished,
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch a callback is called with the returned response.
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch http_client_host_shared:
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch We maintain a 'cache' of hosts for which we have looked up IPs. This cache
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch is maintained in client context, so multiple clients can share it. One host
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch can have multiple IPs.
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch http_client_host:
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch A host object maintains client-specific information for a host. The queues
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch that the client has for this host are listed here. For one host, there is a
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch separate queue for each used server port.
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch http_client_queue:
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch Requests are queued in a queue object. These queues are maintained for each
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch host:port target and listed in the host object. The queue object is
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch responsible for starting connection attempts to TCP port at the various IPs
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch known for the host.
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch http_client_peer_pool:
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch A peer pool lists all unused and pending connections to a peer, grouped by
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch a compatible configuration, e.g. in terms of SSL and rawlog. Once needed,
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch peers can claim/request an existing/new connection from the pool.
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch http_client_peer_shared:
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch The shared peer object records state information about a peer, which is a
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch service access point (ip:port or unix socket path). The peer object also
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch maintains lists of idle and pending connections to this service, which are
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch grouped in pools with compatible client configuration. Each client has a
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch separate (non-shared) peer object for client-specific state information.
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch http_client_peer:
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch A peer object maintains client-specific information for a peer. Claimed
6776cc851a593b2a893103833e08ed3902ce1933Stephan Bosch connections are dedicated to one peer (and therefore one client).
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch http-client-connection:
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch This is an actual connection to a server. Once a connection is ready to
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch handle requests, it claims a request from a queue object. One connection can
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch service multiple hosts and one host can have multiple associated connections,
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch possibly to different ips and ports.
788e61d347adbdb7c9a4d767e381f4bd8a3526b2Timo Sirainenstatic struct http_client_context *http_client_global_context = NULL;
4977156a495d44a5876be598b561bf1d9579e52eStephan Boschhttp_client_context_add_client(struct http_client_context *cctx,
4977156a495d44a5876be598b561bf1d9579e52eStephan Boschhttp_client_context_remove_client(struct http_client_context *cctx,
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Boschhttp_client_init_shared(struct http_client_context *cctx,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch pool = pool_alloconly_create("http client", 1024);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch /* create private context if none is provided */
2d1ad5742dd723b39c51bcf64c62a600237de8aeTimo Sirainen log_prefix = t_strdup_printf("http-client[%u]: ", id);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->cctx = cctx = http_client_context_create(set);
2d1ad5742dd723b39c51bcf64c62a600237de8aeTimo Sirainen /* FIXME: we could use cctx->event, but it already has a log
2d1ad5742dd723b39c51bcf64c62a600237de8aeTimo Sirainen prefix that we don't want.. should we update event API to
2d1ad5742dd723b39c51bcf64c62a600237de8aeTimo Sirainen support replacing parent's log prefix? */
2d1ad5742dd723b39c51bcf64c62a600237de8aeTimo Sirainen if ((set != NULL && set->debug) || (cctx != NULL && cctx->set.debug))
2d1ad5742dd723b39c51bcf64c62a600237de8aeTimo Sirainen event_set_append_log_prefix(client->event, log_prefix);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch /* merge provided settings with context defaults */
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch p_strdup_empty(pool, set->dns_client_socket_path);
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch client->set.dns_ttl_msecs = set->dns_ttl_msecs;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch if (set->user_agent != NULL && *set->user_agent != '\0')
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.user_agent = p_strdup_empty(pool, set->user_agent);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch if (set->rawlog_dir != NULL && *set->rawlog_dir != '\0')
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.rawlog_dir = p_strdup_empty(pool, set->rawlog_dir);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.ssl = ssl_iostream_settings_dup(pool, set->ssl);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch if (set->proxy_socket_path != NULL && *set->proxy_socket_path != '\0') {
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.proxy_socket_path = p_strdup(pool, set->proxy_socket_path);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.proxy_url = http_url_clone(pool, set->proxy_url);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch if (set->proxy_username != NULL && *set->proxy_username != '\0') {
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.proxy_username = p_strdup_empty(pool, set->proxy_username);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.proxy_password = p_strdup(pool, set->proxy_password);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch } else if (set->proxy_url != NULL && set->proxy_url->user != NULL &&
fcb3882db19a56a4421174576e4c5103de3490a5Stephan Bosch client->set.max_idle_time_msecs = set->max_idle_time_msecs;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.max_parallel_connections = set->max_parallel_connections;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.max_pipelined_requests = set->max_pipelined_requests;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.max_connect_attempts = set->max_connect_attempts;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch if (set->connect_backoff_max_time_msecs > 0) {
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.no_auto_redirect || set->no_auto_redirect;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.no_auto_retry || set->no_auto_retry;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.no_ssl_tunnel || set->no_ssl_tunnel;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.max_redirects = set->max_redirects;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch if (set->request_absolute_timeout_msecs > 0) {
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.request_timeout_msecs = set->request_timeout_msecs;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.connect_timeout_msecs = set->connect_timeout_msecs;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.soft_connect_timeout_msecs = set->soft_connect_timeout_msecs;
a00f5a4cf1d47cbdca0a86c34ea57902e0e24492Stephan Bosch client->set.socket_send_buffer_size = set->socket_send_buffer_size;
a00f5a4cf1d47cbdca0a86c34ea57902e0e24492Stephan Bosch client->set.socket_recv_buffer_size = set->socket_recv_buffer_size;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.max_auto_retry_delay = set->max_auto_retry_delay;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch client->set.debug = client->set.debug || set->debug;
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch i_array_init(&client->delayed_failing_requests, 1);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Boschhttp_client_init(const struct http_client_settings *set)
e7bc4ce82122c30696e60789432ffeb2e26b265bTimo Sirainen return http_client_init_shared(http_client_get_global_context(), set);
ff8a751fb9227a4fd73b2cdaa16d7a2616b3e7e7Timo Sirainenhttp_client_init_private(const struct http_client_settings *set)
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid http_client_deinit(struct http_client **_client)
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch /* destroy requests without calling callbacks */
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch struct http_client_request *next_req = req->next;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* free peers */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* free hosts */
6ab81c81be13f33486746deeffe02a1ef2bcc821Stephan Bosch array_free(&client->delayed_failing_requests);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&client->to_failing_requests);
4977156a495d44a5876be598b561bf1d9579e52eStephan Bosch http_client_context_remove_client(client->cctx, client);
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Boschstatic void http_client_do_switch_ioloop(struct http_client *client)
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch /* move peers */
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch /* move timeouts */
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch io_loop_move_timeout(&client->to_failing_requests);
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Boschstruct ioloop *http_client_switch_ioloop(struct http_client *client)
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Bosch http_client_context_switch_ioloop(client->cctx);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid http_client_wait(struct http_client *client)
e8a1b62fe4a81b211dcccd1a58b44f254074eab6Stephan Bosch struct ioloop *prev_ioloop, *client_ioloop, *prev_client_ioloop;
e8a1b62fe4a81b211dcccd1a58b44f254074eab6Stephan Bosch prev_client_ioloop = http_client_switch_ioloop(client);
856ae2ad98cee79b2719911a3cc131d7f4ec8a90Timo Sirainen dns_client_switch_ioloop(client->set.dns_client);
1a9a35a6b307f8d5b25345af55e40a99162b4072Timo Sirainen /* either we're waiting for network I/O or we're getting out of a
1a9a35a6b307f8d5b25345af55e40a99162b4072Timo Sirainen callback using timeout_add_short(0) */
e8a1b62fe4a81b211dcccd1a58b44f254074eab6Stephan Bosch io_loop_have_immediate_timeouts(client_ioloop));
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch "Waiting for %d requests to finish", client->requests_count);
36409af77b42dc1c18c0691970b2eb07785fbba4Timo Sirainen e_debug(client->event, "All requests finished");
856ae2ad98cee79b2719911a3cc131d7f4ec8a90Timo Sirainen dns_client_switch_ioloop(client->set.dns_client);
17cd0e0963f2fb0e66d49703e8cd0bda1b842468Timo Sirainenunsigned int http_client_get_pending_request_count(struct http_client *client)
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainenint http_client_init_ssl_ctx(struct http_client *client, const char **error_r)
5d31e4b38ef03b002e2ab245a7f8a4c0da3dd03dTimo Sirainen *error_r = "Requested https connection, but no SSL settings given";
ebcf7d6c9222f2c96053516e0c90994bff62dd55Timo Sirainen if (ssl_iostream_client_context_cache_get(client->set.ssl, &client->ssl_ctx, &error) < 0) {
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen *error_r = t_strdup_printf("Couldn't initialize SSL context: %s",
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch * Delayed request errors
fca68889b287d8eed4babe72a231bd6079da012dStephan Boschhttp_client_handle_request_errors(struct http_client *client)
8d845733408c0cb06a8884d12101beb0d40e6869Stephan Bosch array_foreach(&client->delayed_failing_requests, req_idx) {
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch array_clear(&client->delayed_failing_requests);
fca68889b287d8eed4babe72a231bd6079da012dStephan Boschvoid http_client_delay_request_error(struct http_client *client,
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch array_append(&client->delayed_failing_requests, &req, 1);
fca68889b287d8eed4babe72a231bd6079da012dStephan Boschvoid http_client_remove_request_error(struct http_client *client,
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch reqs = array_get(&client->delayed_failing_requests, &count);
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch for (i = 0; i < count; i++) {
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch array_delete(&client->delayed_failing_requests, i, 1);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch * Client shared context
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Boschhttp_client_context_create(const struct http_client_settings *set)
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch pool = pool_alloconly_create("http client context", 1024);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx = p_new(pool, struct http_client_context, 1);
2d1ad5742dd723b39c51bcf64c62a600237de8aeTimo Sirainen event_set_append_log_prefix(cctx->event, "http-client: ");
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch p_strdup_empty(pool, set->dns_client_socket_path);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.dns_ttl_msecs = (set->dns_ttl_msecs == 0 ?
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch HTTP_CLIENT_DEFAULT_DNS_TTL_MSECS : set->dns_ttl_msecs);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.user_agent = p_strdup_empty(pool, set->user_agent);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.rawlog_dir = p_strdup_empty(pool, set->rawlog_dir);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.ssl = ssl_iostream_settings_dup(pool, set->ssl);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch if (set->proxy_socket_path != NULL && *set->proxy_socket_path != '\0') {
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.proxy_socket_path = p_strdup(pool, set->proxy_socket_path);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.proxy_url = http_url_clone(pool, set->proxy_url);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch if (set->proxy_username != NULL && *set->proxy_username != '\0') {
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.proxy_username = p_strdup_empty(pool, set->proxy_username);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.proxy_password = p_strdup(pool, set->proxy_password);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.max_idle_time_msecs = set->max_idle_time_msecs;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch (set->max_pipelined_requests > 0 ? set->max_pipelined_requests : 1);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch (set->max_parallel_connections > 0 ? set->max_parallel_connections : 1);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.max_connect_attempts = set->max_connect_attempts;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.no_auto_redirect = set->no_auto_redirect;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.response_hdr_limits = set->response_hdr_limits;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.connect_timeout_msecs = set->connect_timeout_msecs;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.soft_connect_timeout_msecs = set->soft_connect_timeout_msecs;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.max_auto_retry_delay = set->max_auto_retry_delay;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.socket_send_buffer_size = set->socket_send_buffer_size;
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Bosch cctx->set.socket_recv_buffer_size = set->socket_recv_buffer_size;
9fe6a55877bee691b32c12c7be56242054841670Stephan Bosch cctx->conn_list = http_client_connection_list_init();
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hash_table_create(&cctx->hosts, default_pool, 0, str_hash, strcmp);
27a2e59eaa648fef2acb2c4b852567d22e016a2dStephan Bosch hash_table_create(&cctx->peers, default_pool, 0,
27a2e59eaa648fef2acb2c4b852567d22e016a2dStephan Bosch http_client_peer_addr_hash, http_client_peer_addr_cmp);
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Boschvoid http_client_context_ref(struct http_client_context *cctx)
fab1a1c57f467c19c728d2391ff5e5025bb832f7Stephan Boschvoid http_client_context_unref(struct http_client_context **_cctx)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch /* free hosts */
27a2e59eaa648fef2acb2c4b852567d22e016a2dStephan Bosch /* close all idle connections */
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Boschstatic unsigned int
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Boschhttp_client_get_dns_lookup_timeout_msecs(const struct http_client_settings *set)
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch return HTTP_CLIENT_DEFAULT_DNS_LOOKUP_TIMEOUT_MSECS;
473f30e2d1ce3a2320aeae03b32b766437ef0a13Stephan Boschhttp_client_context_update_settings(struct http_client_context *cctx)
473f30e2d1ce3a2320aeae03b32b766437ef0a13Stephan Bosch /* revert back to context settings */
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch cctx->dns_client_socket_path = cctx->set.dns_client_socket_path;
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch cctx->dns_ttl_msecs = cctx->set.dns_ttl_msecs;
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch http_client_get_dns_lookup_timeout_msecs(&cctx->set);
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch /* override with available client settings */
473f30e2d1ce3a2320aeae03b32b766437ef0a13Stephan Bosch for (client = cctx->clients_list; client != NULL;
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch http_client_get_dns_lookup_timeout_msecs(&client->set);
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch cctx->dns_ttl_msecs > client->set.dns_ttl_msecs)
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch cctx->dns_ttl_msecs = client->set.dns_ttl_msecs;
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch cctx->dns_lookup_timeout_msecs > dns_lookup_timeout_msecs) {
4977156a495d44a5876be598b561bf1d9579e52eStephan Boschhttp_client_context_add_client(struct http_client_context *cctx,
4977156a495d44a5876be598b561bf1d9579e52eStephan Boschhttp_client_context_remove_client(struct http_client_context *cctx,
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Bosch io_loop_set_current(cctx->clients_list->ioloop);
e0990933b4c3428f3de18cbeb5844217cb029611Stephan Boschstatic void http_client_context_close(struct http_client_context *cctx)
e0990933b4c3428f3de18cbeb5844217cb029611Stephan Bosch /* Switching to NULL ioloop;
e0990933b4c3428f3de18cbeb5844217cb029611Stephan Bosch close all hosts, peers, and connections */
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Boschhttp_client_context_do_switch_ioloop(struct http_client_context *cctx)
9fe6a55877bee691b32c12c7be56242054841670Stephan Bosch struct connection *_conn = cctx->conn_list->connections;
9fe6a55877bee691b32c12c7be56242054841670Stephan Bosch /* move connections */
9fe6a55877bee691b32c12c7be56242054841670Stephan Bosch /* FIXME: we wouldn't necessarily need to switch all of them
9fe6a55877bee691b32c12c7be56242054841670Stephan Bosch immediately, only those that have requests now. but also connections
9fe6a55877bee691b32c12c7be56242054841670Stephan Bosch that get new requests before ioloop is switched again.. */
ac58ae8fb539021189941651b33246b749c35297Stephan Bosch /* move backoff timeouts */
ac58ae8fb539021189941651b33246b749c35297Stephan Bosch for (pshared = cctx->peers_list; pshared != NULL;
ac58ae8fb539021189941651b33246b749c35297Stephan Bosch http_client_peer_shared_switch_ioloop(pshared);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch /* move dns lookups and delayed requests */
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch for (hshared = cctx->hosts_list; hshared != NULL;
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_host_shared_switch_ioloop(hshared);
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Boschvoid http_client_context_switch_ioloop(struct http_client_context *cctx)
788e61d347adbdb7c9a4d767e381f4bd8a3526b2Timo Sirainenstatic void http_client_global_context_free(void)
788e61d347adbdb7c9a4d767e381f4bd8a3526b2Timo Sirainen http_client_context_unref(&http_client_global_context);
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Bosch struct http_client_context *cctx = http_client_global_context;
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Bosch /* follow the current ioloop if there is no client */
788e61d347adbdb7c9a4d767e381f4bd8a3526b2Timo Sirainenstruct http_client_context *http_client_get_global_context(void)
788e61d347adbdb7c9a4d767e381f4bd8a3526b2Timo Sirainen http_client_global_context = http_client_context_create(&set);
788e61d347adbdb7c9a4d767e381f4bd8a3526b2Timo Sirainen /* keep this a bit higher than lib-ssl-iostream */
788e61d347adbdb7c9a4d767e381f4bd8a3526b2Timo Sirainen lib_atexit_priority(http_client_global_context_free, LIB_ATEXIT_PRIORITY_LOW-1);