bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
c4b2dba355010a38f17b3cd84feb01ecb8b05a55Stephan Bosch#define HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS 100
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_lookup_done(struct http_client_host *host);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_lookup_failure(struct http_client_host *host,
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch const char *error);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_is_idle(struct http_client_host *host);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch * Host (shared)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_shared_idle_timeout(struct http_client_host_shared *hshared)
36409af77b42dc1c18c0691970b2eb07785fbba4Timo Sirainen e_debug(hshared->event, "Idle host timed out");
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch if (!hshared->unix_local && !hshared->explicit_ip &&
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch if (timeout <= HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS)
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch timeout = HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS;
a68aaff537e2e30d782bb8b9d8782e1a10a17d1aStephan Bosch hshared->to_idle = timeout_add_to(hshared->cctx->ioloop, timeout,
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_host_shared_idle_timeout, hshared);
36409af77b42dc1c18c0691970b2eb07785fbba4Timo Sirainen e_debug(hshared->event, "Host is idle (timeout = %u msecs)", timeout);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_shared_lookup_failure(struct http_client_host_shared *hshared,
18d2775f815cdeed9bc1a2da078e682f5d354cf9Timo Sirainen error = t_strdup_printf("Failed to lookup host %s: %s",
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_shared_dns_callback(const struct dns_lookup_result *result,
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch struct http_client_context *cctx = hshared->cctx;
1e63e30812158e6446d81cdbb2f45954794d4f8aStephan Bosch /* lookup failed */
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_host_shared_lookup_failure(hshared, result->error);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "DNS lookup successful; got %d IPs", result->ips_count);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hshared->ips = i_realloc_type(hshared->ips, struct ip_addr,
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch memcpy(hshared->ips, result->ips, sizeof(*hshared->ips) * hshared->ips_count);
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch timeval_add_msecs(&hshared->ips_timeout, cctx->dns_ttl_msecs);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch /* notify all sessions */
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch struct http_client_context *cctx = hshared->cctx;
36409af77b42dc1c18c0691970b2eb07785fbba4Timo Sirainen e_debug(hshared->event, "Performing asynchronous DNS lookup");
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch (void)dns_client_lookup(cctx->dns_client, hshared->name,
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_host_shared_dns_callback, hshared, &hshared->dns_lookup);
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch } else if (cctx->dns_client_socket_path != NULL) {
36409af77b42dc1c18c0691970b2eb07785fbba4Timo Sirainen e_debug(hshared->event, "Performing asynchronous DNS lookup");
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch dns_set.dns_client_socket_path = cctx->dns_client_socket_path;
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch dns_set.timeout_msecs = cctx->dns_lookup_timeout_msecs;
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_host_shared_dns_callback, hshared, &hshared->dns_lookup);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch ret = net_gethostbyname(hshared->name, &ips, &ips_count);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_host_shared_lookup_failure(hshared, net_gethosterror(ret));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "DNS lookup successful; got %d IPs", ips_count);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hshared->ips = i_new(struct ip_addr, ips_count);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch memcpy(hshared->ips, ips, ips_count * sizeof(*ips));
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch timeval_add_msecs(&hshared->ips_timeout, cctx->dns_ttl_msecs);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_shared_refresh(struct http_client_host_shared *hshared)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch timeval_cmp(&hshared->ips_timeout, &ioloop_timeval) > 0)
36409af77b42dc1c18c0691970b2eb07785fbba4Timo Sirainen e_debug(hshared->event, "IPs have expired; need to refresh DNS lookup");
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschstatic struct http_client_host_shared *http_client_host_shared_create
a79ae29fa95877ab857b1b25268c75327717ae8dTimo Sirainen(struct http_client_context *cctx, const char *name)
ede750711f27ca9d9037a7ab9f016411b57f1ad9Stephan Bosch // FIXME: limit the maximum number of inactive cached hosts
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hshared = i_new(struct http_client_host_shared, 1);
a79ae29fa95877ab857b1b25268c75327717ae8dTimo Sirainen hshared = http_client_host_shared_create(cctx, "[unix]");
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hshared = hash_table_lookup(cctx->hosts, hostname);
a79ae29fa95877ab857b1b25268c75327717ae8dTimo Sirainen hshared = http_client_host_shared_create(cctx, hostname);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hash_table_insert(cctx->hosts, hostname, hshared);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch if (ip.family != 0 || net_addr2ip(hshared->name, &ip) == 0) {
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hshared->ips = i_new(struct ip_addr, hshared->ips_count);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschvoid http_client_host_shared_free(struct http_client_host_shared **_hshared)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch struct http_client_host_shared *hshared = *_hshared;
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch struct http_client_context *cctx = hshared->cctx;
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch /* drop client sessions */
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch /* cancel host idle timeout */
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch struct http_client_context *cctx = hshared->cctx;
ee90a96c4f47ff9c1e56451201386ca8a0b48124Stephan Bosch if (hshared->dns_lookup != NULL && cctx->dns_client == NULL)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch dns_lookup_switch_ioloop(hshared->dns_lookup);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hshared->to_idle = io_loop_move_timeout(&hshared->to_idle);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_get(struct http_client *client,
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch hshared = http_client_host_shared_get(client->cctx, host_url);
36409af77b42dc1c18c0691970b2eb07785fbba4Timo Sirainen e_debug(hshared->event, "Host session created");
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch struct http_client_host_shared *hshared = host->shared;
36409af77b42dc1c18c0691970b2eb07785fbba4Timo Sirainen e_debug(hshared->event, "Host session destroy");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* drop request queues */
c4b2dba355010a38f17b3cd84feb01ecb8b05a55Stephan Bosch t_array_init(&queues, array_count(&host->queues));
c4b2dba355010a38f17b3cd84feb01ecb8b05a55Stephan Bosch &host->queues.arr, 0, array_count(&host->queues));
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch /* notify all queues */
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch array_foreach_modifiable(&host->queues, queue_idx) {
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch requests += http_client_queue_host_lookup_done(*queue_idx);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_lookup_failure(struct http_client_host *host,
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch array_foreach_modifiable(&host->queues, queue_idx)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_queue_host_lookup_failure(*queue_idx, error);
2300bdf148ee501082947c2ec79d12c175489897Stephan Boschvoid http_client_host_submit_request(struct http_client_host *host,
2300bdf148ee501082947c2ec79d12c175489897Stephan Bosch http_client_request_get_peer_addr(req, &addr);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch if (http_client_init_ssl_ctx(client, &error) < 0) {
2300bdf148ee501082947c2ec79d12c175489897Stephan Bosch HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, error);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch /* add request to queue */
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_host_shared_request_submitted(host->shared);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch /* queue will trigger host lookup once the request is activated
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch (may be delayed) */
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschhttp_client_host_is_idle(struct http_client_host *host)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch requests += http_client_queue_requests_active(*queue_idx);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschvoid http_client_host_check_idle(struct http_client_host *host)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch http_client_host_shared_check_idle(host->shared);
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Boschint http_client_host_refresh(struct http_client_host *host)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch return http_client_host_shared_refresh(host->shared);
23fe024e1dfc8eb5eaefc4e57a16b4257568f510Stephan Boschbool http_client_host_get_ip_idx(struct http_client_host *host,
23fe024e1dfc8eb5eaefc4e57a16b4257568f510Stephan Bosch const struct ip_addr *ip, unsigned int *idx_r)
e48102389fb49deadfc685600dc2e56177fd0d7cStephan Bosch struct http_client_host_shared *hshared = host->shared;
23fe024e1dfc8eb5eaefc4e57a16b4257568f510Stephan Bosch unsigned int i;