aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil/upstream.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2017-11-26 22:07:57 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2017-11-26 22:07:57 +0000
commit758c39a8b70ae85f5111e981ddc931f5e2b61198 (patch)
treeb0f37b5089eade01f11429cd0a58cfcb74983e27 /src/libutil/upstream.c
parent9478d16620a675f87541316eb9977c2c9fb15a8f (diff)
downloadrspamd-758c39a8b70ae85f5111e981ddc931f5e2b61198.tar.gz
rspamd-758c39a8b70ae85f5111e981ddc931f5e2b61198.zip
[Fix] Do not constantly re-resolve failed upstreams with a single
element
Diffstat (limited to 'src/libutil/upstream.c')
-rw-r--r--src/libutil/upstream.c48
1 files changed, 35 insertions, 13 deletions
diff --git a/src/libutil/upstream.c b/src/libutil/upstream.c
index 2f2772f92..299ea37cb 100644
--- a/src/libutil/upstream.c
+++ b/src/libutil/upstream.c
@@ -226,18 +226,20 @@ rspamd_upstream_addr_elt_dtor (gpointer a)
{
struct upstream_addr_elt *elt = a;
- rspamd_inet_address_free (elt->addr);
- g_free (elt);
+ if (elt) {
+ rspamd_inet_address_free (elt->addr);
+ g_free (elt);
+ }
}
static void
rspamd_upstream_update_addrs (struct upstream *up)
{
- guint16 port;
- guint addr_cnt;
+ guint addr_cnt, i, port;
+ gboolean seen_addr;
struct upstream_inet_addr_entry *cur, *tmp;
GPtrArray *new_addrs;
- struct upstream_addr_elt *addr_elt;
+ struct upstream_addr_elt *addr_elt, *naddr;
/*
* We need first of all get the saved port, since DNS gives us no
@@ -249,25 +251,44 @@ rspamd_upstream_update_addrs (struct upstream *up)
addr_elt = g_ptr_array_index (up->addrs.addr, 0);
port = rspamd_inet_address_get_port (addr_elt->addr);
- /* Free old addresses */
- g_ptr_array_free (up->addrs.addr, TRUE);
-
/* Now calculate new addrs count */
addr_cnt = 0;
LL_FOREACH (up->new_addrs, cur) {
addr_cnt++;
}
+
new_addrs = g_ptr_array_new_full (addr_cnt, rspamd_upstream_addr_elt_dtor);
/* Copy addrs back */
LL_FOREACH (up->new_addrs, cur) {
+ seen_addr = FALSE;
+ naddr = NULL;
+ /* Ports are problematic, set to compare in the next block */
rspamd_inet_address_set_port (cur->addr, port);
- addr_elt = g_malloc0 (sizeof (*addr_elt));
- addr_elt->addr = cur->addr;
- addr_elt->errors = 0;
- g_ptr_array_add (new_addrs, addr_elt);
+
+ PTR_ARRAY_FOREACH (up->addrs.addr, i, addr_elt) {
+ if (rspamd_inet_address_compare (addr_elt->addr, cur->addr) == 0) {
+ naddr = g_malloc0 (sizeof (*addr_elt));
+ naddr->addr = cur->addr;
+ naddr->errors = addr_elt->errors; /* Preserve errors */
+ seen_addr = TRUE;
+
+ break;
+ }
+ }
+
+ if (!seen_addr) {
+ addr_elt = g_malloc0 (sizeof (*addr_elt));
+ addr_elt->addr = cur->addr;
+ addr_elt->errors = 0;
+ }
+
+ g_ptr_array_add (new_addrs, naddr);
}
+ /* Free old addresses */
+ g_ptr_array_free (up->addrs.addr, TRUE);
+
up->addrs.cur = 0;
up->addrs.addr = new_addrs;
g_ptr_array_sort (up->addrs.addr, rspamd_upstream_addr_sort_func);
@@ -277,8 +298,8 @@ rspamd_upstream_update_addrs (struct upstream *up)
/* Do not free inet address pointer since it has been transferred to up */
g_free (cur);
}
- up->new_addrs = NULL;
+ up->new_addrs = NULL;
RSPAMD_UPSTREAM_UNLOCK (up->lock);
}
@@ -438,6 +459,7 @@ rspamd_upstream_fail (struct upstream *up)
}
else {
/* Just re-resolve addresses */
+ up->errors = 0;
rspamd_upstream_resolve_addrs (up->ls, up);
}
}