From: Stephan Bosch Date: Wed, 30 Nov 2016 01:04:11 +0000 (+0100) Subject: lib-http: client: Avoid direct access to host object members from queue. X-Git-Tag: 2.3.0.rc1~266 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=23fe024e1dfc8eb5eaefc4e57a16b4257568f510;p=thirdparty%2Fdovecot%2Fcore.git lib-http: client: Avoid direct access to host object members from queue. --- diff --git a/src/lib-http/http-client-host.c b/src/lib-http/http-client-host.c index 1350f5c8ff..eb7e1f0eb9 100644 --- a/src/lib-http/http-client-host.c +++ b/src/lib-http/http-client-host.c @@ -333,6 +333,20 @@ void http_client_host_check_idle(struct http_client_host *host) "Host is idle (timeout = %u msecs)", timeout); } +bool http_client_host_get_ip_idx(struct http_client_host *host, + const struct ip_addr *ip, unsigned int *idx_r) +{ + unsigned int i; + + for (i = 0; i < host->ips_count; i++) { + if (net_ip_compare(&host->ips[i], ip)) { + *idx_r = i; + return TRUE; + } + } + return FALSE; +} + void http_client_host_switch_ioloop(struct http_client_host *host) { struct http_client_queue *const *queue_idx; diff --git a/src/lib-http/http-client-private.h b/src/lib-http/http-client-private.h index 8eec07fb09..d3320e2469 100644 --- a/src/lib-http/http-client-private.h +++ b/src/lib-http/http-client-private.h @@ -560,19 +560,24 @@ void http_client_queue_switch_ioloop(struct http_client_queue *queue); * Host */ -static inline bool -http_client_host_get_ip_idx(struct http_client_host *host, - const struct ip_addr *ip, unsigned int *idx_r) +static inline unsigned int +http_client_host_get_ips_count(struct http_client_host *host) { - unsigned int i; + return host->ips_count; +} - for (i = 0; i < host->ips_count; i++) { - if (net_ip_compare(&host->ips[i], ip)) { - *idx_r = i; - return TRUE; - } - } - return FALSE; +static inline const struct ip_addr * +http_client_host_get_ip(struct http_client_host *host, + unsigned int idx) +{ + i_assert(idx < host->ips_count); + return &host->ips[idx]; +} + +static inline bool +http_client_host_ready(struct http_client_host *host) +{ + return host->dns_lookup == NULL; } struct http_client_host * @@ -584,6 +589,8 @@ void http_client_host_submit_request(struct http_client_host *host, void http_client_host_switch_ioloop(struct http_client_host *host); void http_client_host_check_idle(struct http_client_host *host); int http_client_host_refresh(struct http_client_host *host); +bool http_client_host_get_ip_idx(struct http_client_host *host, + const struct ip_addr *ip, unsigned int *idx_r); /* * Client diff --git a/src/lib-http/http-client-queue.c b/src/lib-http/http-client-queue.c index 743a710b90..7928451e42 100644 --- a/src/lib-http/http-client-queue.c +++ b/src/lib-http/http-client-queue.c @@ -227,10 +227,11 @@ http_client_queue_is_last_connect_ip(struct http_client_queue *queue) const struct http_client_settings *set = &queue->client->set; struct http_client_host *host = queue->host; + unsigned int ips_count = http_client_host_get_ips_count(host); i_assert(queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX); - i_assert(queue->ips_connect_idx < host->ips_count); - i_assert(queue->ips_connect_start_idx < host->ips_count); + i_assert(queue->ips_connect_idx < ips_count); + i_assert(queue->ips_connect_start_idx < ips_count); /* if a maximum connect attempts > 1 is set, enforce it directly */ if (set->max_connect_attempts > 1 && @@ -241,7 +242,7 @@ http_client_queue_is_last_connect_ip(struct http_client_queue *queue) start connecting from the first IP, so we'll need to treat the IPs as a ring buffer where we automatically wrap back to the first IP when necessary. */ - return (queue->ips_connect_idx + 1) % host->ips_count == + return (queue->ips_connect_idx + 1) % ips_count == queue->ips_connect_start_idx; } @@ -249,8 +250,7 @@ static void http_client_queue_recover_from_lookup(struct http_client_queue *queue) { struct http_client_host *host = queue->host; - struct http_client_peer_addr new_addr = queue->addr; - unsigned int i; + unsigned int ip_idx; i_assert(queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX); @@ -259,17 +259,10 @@ http_client_queue_recover_from_lookup(struct http_client_queue *queue) return; } - /* try to find current peer amongst new IPs */ - for (i = 0; i < host->ips_count; i++) { - new_addr.a.tcp.ip = host->ips[i]; - if (http_client_peer_addr_cmp - (&new_addr, &queue->cur_peer->addr) == 0) - break; - } - - if (i < host->ips_count) { + if (http_client_host_get_ip_idx(host, + &queue->cur_peer->addr.a.tcp.ip, &ip_idx)) { /* continue with current peer */ - queue->ips_connect_idx = queue->ips_connect_start_idx = i; + queue->ips_connect_idx = queue->ips_connect_start_idx = ip_idx; } else { /* reset connect attempts */ queue->ips_connect_idx = queue->ips_connect_start_idx = 0; @@ -281,6 +274,7 @@ http_client_queue_soft_connect_timeout(struct http_client_queue *queue) { struct http_client_host *host = queue->host; const struct http_client_peer_addr *addr = &queue->addr; + unsigned int ips_count = http_client_host_get_ips_count(host); const char *https_name; i_assert(queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX); @@ -302,7 +296,7 @@ http_client_queue_soft_connect_timeout(struct http_client_queue *queue) t_strdup_printf(" (SSL=%s)", https_name))); /* next IP */ - queue->ips_connect_idx = (queue->ips_connect_idx + 1) % host->ips_count; + queue->ips_connect_idx = (queue->ips_connect_idx + 1) % ips_count; /* setup connection to new peer (can start new soft timeout) */ http_client_queue_connection_setup(queue); @@ -336,8 +330,9 @@ http_client_queue_connection_attempt(struct http_client_queue *queue) /* update our peer address */ if (queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX) { - i_assert(queue->ips_connect_idx < host->ips_count); - queue->addr.a.tcp.ip = host->ips[queue->ips_connect_idx]; + const struct ip_addr *ip = http_client_host_get_ip(host, + queue->ips_connect_idx); + queue->addr.a.tcp.ip = *ip; ssl = http_client_peer_addr_get_https_name(addr); ssl = (ssl == NULL ? "" : t_strdup_printf(" (SSL=%s)", ssl)); } @@ -463,10 +458,12 @@ void http_client_queue_connection_success(struct http_client_queue *queue, const struct http_client_peer_addr *addr) { - if (queue->host->dns_lookup == NULL && + struct http_client_host *host = queue->host; + + if (http_client_host_ready(host) && queue->addr.type != HTTP_CLIENT_PEER_ADDR_UNIX) { /* we achieved at least one connection the the addr->ip */ - if (!http_client_host_get_ip_idx(queue->host, + if (!http_client_host_get_ip_idx(host, &addr->a.tcp.ip, &queue->ips_connect_start_idx)) { /* list of IPs changed during connect */ queue->ips_connect_start_idx = 0; @@ -513,6 +510,7 @@ http_client_queue_connection_failure(struct http_client_queue *queue, &queue->client->set; const char *https_name = http_client_peer_addr_get_https_name(addr); struct http_client_host *host = queue->host; + unsigned int ips_count = http_client_host_get_ips_count(host); struct http_client_peer *failed_peer; struct http_client_peer *const *peer_idx; @@ -580,7 +578,7 @@ http_client_queue_connection_failure(struct http_client_queue *queue, /* all IPs failed, but retry all of them again if we have more connect attempts left or on the next request. */ queue->ips_connect_idx = queue->ips_connect_start_idx = - (queue->ips_connect_idx + 1) % host->ips_count; + (queue->ips_connect_idx + 1) % ips_count; if (set->max_connect_attempts == 0 || queue->connect_attempts >= set->max_connect_attempts) { @@ -600,7 +598,7 @@ http_client_queue_connection_failure(struct http_client_queue *queue, return; } } else { - queue->ips_connect_idx = (queue->ips_connect_idx + 1) % host->ips_count; + queue->ips_connect_idx = (queue->ips_connect_idx + 1) % ips_count; } if (http_client_queue_connection_attempt(queue) != failed_peer)