http-client-host.c revision 2300bdf148ee501082947c2ec79d12c175489897
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2013-2017 Dovecot authors, see the included COPYING file */
c4b2dba355010a38f17b3cd84feb01ecb8b05a55Stephan Bosch#define HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS 100
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic inline void
7384b4e78eaab44693c985192276e31322155e32Stephan Boschhttp_client_host_debug(struct http_client_host *host,
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic inline void
7384b4e78eaab44693c985192276e31322155e32Stephan Boschhttp_client_host_debug(struct http_client_host *host,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *format, ...)
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Boschhttp_client_host_idle_timeout(struct http_client_host *host)
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch http_client_host_debug(host, "Idle host timed out");
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Boschvoid http_client_host_check_idle(struct http_client_host *host)
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch unsigned int requests = 0;
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch requests += http_client_queue_requests_active(*queue_idx);
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch if (!host->unix_local && !host->explicit_ip &&
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch if (timeout <= HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS)
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch timeout = HTTP_CLIENT_HOST_MINIMUM_IDLE_TIMEOUT_MSECS;
fbe111ce65bb5af03314adbfa8bcde3f08c08641Stephan Bosch "Host is idle (timeout = %u msecs)", timeout);
de96afeeaa5242cffe89f1966457e935806b5746Stephan Boschhttp_client_host_lookup_failure(struct http_client_host *host,
18d2775f815cdeed9bc1a2da078e682f5d354cf9Timo Sirainen error = t_strdup_printf("Failed to lookup host %s: %s",
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch array_foreach_modifiable(&host->queues, queue_idx) {
5791d02c3672f6a525f1fcf0f4f375b4be0ccf4bStephan Bosch http_client_queue_host_lookup_failure(*queue_idx, error);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschhttp_client_host_dns_callback(const struct dns_lookup_result *result,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch unsigned int requests = 0;
1e63e30812158e6446d81cdbb2f45954794d4f8aStephan Bosch /* lookup failed */
18d2775f815cdeed9bc1a2da078e682f5d354cf9Timo Sirainen http_client_host_lookup_failure(host, result->error);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "DNS lookup successful; got %d IPs", result->ips_count);
7fc4f555a9a12630932f73659bd575a4a94386ecTimo Sirainen host->ips = i_realloc_type(host->ips, struct ip_addr,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch memcpy(host->ips, result->ips, sizeof(*host->ips) * host->ips_count);
1e63e30812158e6446d81cdbb2f45954794d4f8aStephan Bosch timeval_add_msecs(&host->ips_timeout, client->set.dns_ttl_msecs);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* make connections to requested ports */
de96afeeaa5242cffe89f1966457e935806b5746Stephan Bosch array_foreach_modifiable(&host->queues, queue_idx) {
1e63e30812158e6446d81cdbb2f45954794d4f8aStephan Bosch requests += http_client_queue_host_lookup_done(*queue_idx);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (requests == 0 && host->client->ioloop != NULL)
7944646fad6aa1e7c649c3d33e454c516b0220b6Timo Sirainen "Performing asynchronous DNS lookup");
7944646fad6aa1e7c649c3d33e454c516b0220b6Timo Sirainen (void)dns_client_lookup(client->set.dns_client, host->name,
7944646fad6aa1e7c649c3d33e454c516b0220b6Timo Sirainen http_client_host_dns_callback, host, &host->dns_lookup);
81558ac5d0b1a23861870e084fa52cbc951ceda6Timo Sirainen } else if (client->set.dns_client_socket_path != NULL) {
7944646fad6aa1e7c649c3d33e454c516b0220b6Timo Sirainen "Performing asynchronous DNS lookup");
5257840e8d31a6cb7051703b4cb0931c82aba638Stephan Bosch dns_set.timeout_msecs = client->set.connect_timeout_msecs;
5257840e8d31a6cb7051703b4cb0931c82aba638Stephan Bosch else if (client->set.request_timeout_msecs > 0)
5257840e8d31a6cb7051703b4cb0931c82aba638Stephan Bosch dns_set.timeout_msecs = client->set.request_timeout_msecs;
7944646fad6aa1e7c649c3d33e454c516b0220b6Timo Sirainen http_client_host_dns_callback, host, &host->dns_lookup);
7944646fad6aa1e7c649c3d33e454c516b0220b6Timo Sirainen ret = net_gethostbyname(host->name, &ips, &ips_count);
18d2775f815cdeed9bc1a2da078e682f5d354cf9Timo Sirainen http_client_host_lookup_failure(host, net_gethosterror(ret));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "DNS lookup successful; got %d IPs", ips_count);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch memcpy(host->ips, ips, ips_count * sizeof(*ips));
1e63e30812158e6446d81cdbb2f45954794d4f8aStephan Bosch timeval_add_msecs(&host->ips_timeout, client->set.dns_ttl_msecs);
1e63e30812158e6446d81cdbb2f45954794d4f8aStephan Boschint http_client_host_refresh(struct http_client_host *host)
1e63e30812158e6446d81cdbb2f45954794d4f8aStephan Bosch timeval_cmp(&host->ips_timeout, &ioloop_timeval) > 0)
1e63e30812158e6446d81cdbb2f45954794d4f8aStephan Bosch "IPs have expired; need to refresh DNS lookup");
ede750711f27ca9d9037a7ab9f016411b57f1ad9Stephan Boschstatic struct http_client_host *http_client_host_create
ede750711f27ca9d9037a7ab9f016411b57f1ad9Stephan Bosch // FIXME: limit the maximum number of inactive cached hosts
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch(struct http_client *client, const struct http_url *host_url)
ede750711f27ca9d9037a7ab9f016411b57f1ad9Stephan Bosch http_client_host_debug(host, "Unix host created");
ede750711f27ca9d9037a7ab9f016411b57f1ad9Stephan Bosch host = hash_table_lookup(client->hosts, hostname);
ede750711f27ca9d9037a7ab9f016411b57f1ad9Stephan Bosch hash_table_insert(client->hosts, hostname, host);
c936df07cf490f090f2f336f40ca386cc953b055Stephan Bosch if (ip.family != 0 || net_addr2ip(host->name, &ip) == 0) {
ede750711f27ca9d9037a7ab9f016411b57f1ad9Stephan Bosch host->ips = i_new(struct ip_addr, host->ips_count);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid http_client_host_free(struct http_client_host **_host)
aacf2a69acc59e9382578d6f4e030788abc79706Timo Sirainen DLLIST_REMOVE(&host->client->hosts_list, host);
ede750711f27ca9d9037a7ab9f016411b57f1ad9Stephan Bosch hash_table_remove(host->client->hosts, hostname);
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));
2300bdf148ee501082947c2ec79d12c175489897Stephan Boschvoid http_client_host_submit_request(struct http_client_host *host,
2300bdf148ee501082947c2ec79d12c175489897Stephan Bosch http_client_request_get_peer_addr(req, &addr);
2300bdf148ee501082947c2ec79d12c175489897Stephan Bosch if (http_client_init_ssl_ctx(host->client, &error) < 0) {
2300bdf148ee501082947c2ec79d12c175489897Stephan Bosch HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, error);
2300bdf148ee501082947c2ec79d12c175489897Stephan Bosch /* add request to queue (grouped by tcp port) */
2300bdf148ee501082947c2ec79d12c175489897Stephan Bosch /* cancel host idle timeout */
23fe024e1dfc8eb5eaefc4e57a16b4257568f510Stephan Boschbool http_client_host_get_ip_idx(struct http_client_host *host,
23fe024e1dfc8eb5eaefc4e57a16b4257568f510Stephan Bosch const struct ip_addr *ip, unsigned int *idx_r)
23fe024e1dfc8eb5eaefc4e57a16b4257568f510Stephan Bosch unsigned int i;
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid http_client_host_switch_ioloop(struct http_client_host *host)
856ae2ad98cee79b2719911a3cc131d7f4ec8a90Timo Sirainen if (host->dns_lookup != NULL && host->client->set.dns_client == NULL)