]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] Do not replan retransmits if merely one server is defined
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 26 Sep 2016 16:08:43 +0000 (17:08 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 26 Sep 2016 16:15:51 +0000 (17:15 +0100)
contrib/librdns/rdns.h
contrib/librdns/resolver.c
src/libserver/dns.c

index 7e5843183e1d63ecac02e7abf34216c072b92f60..e5fc82fe40a362562252dc7c02fce4dd5f813f01 100644 (file)
@@ -164,6 +164,7 @@ struct rdns_upstream_context {
                        size_t len, void *ups_data);
        struct rdns_upstream_elt* (*select_retransmit)(const char *name,
                        size_t len, void *ups_data);
+       unsigned int (*count)(void *ups_data);
        void (*ok)(struct rdns_upstream_elt *elt, void *ups_data);
        void (*fail)(struct rdns_upstream_elt *elt, void *ups_data);
 };
index 329caa6206eccad57ae199863329862ab753619b..8c5df913f05da8b5ba0b882f06abd5f1c1bd5835 100644 (file)
@@ -295,6 +295,7 @@ rdns_process_timer (void *arg)
        bool renew = false;
        struct rdns_resolver *resolver;
        struct rdns_server *serv = NULL;
+       unsigned cnt;
 
        req->retransmits --;
        resolver = req->resolver;
@@ -318,44 +319,57 @@ rdns_process_timer (void *arg)
        }
 
        if (!req->io->active || req->retransmits == 1) {
-               /* Do not reschedule IO requests on inactive sockets */
-               rdns_debug ("reschedule request with id: %d", (int)req->id);
-               rdns_request_unschedule (req);
-               REF_RELEASE (req->io);
 
                if (resolver->ups) {
-                       struct rdns_upstream_elt *elt;
+                       cnt = resolver->ups->count (resolver->ups->data);
+               }
+               else {
+                       cnt = 0;
+                       UPSTREAM_FOREACH (resolver->servers, serv) {
+                               cnt ++;
+                       }
+               }
 
-                       elt = resolver->ups->select_retransmit (req->requested_names[0].name,
-                                       req->requested_names[0].len, resolver->ups->data);
+               if (!req->io->active || cnt > 1) {
+                       /* Do not reschedule IO requests on inactive sockets */
+                       rdns_debug ("reschedule request with id: %d", (int)req->id);
+                       rdns_request_unschedule (req);
+                       REF_RELEASE (req->io);
 
-                       if (elt) {
-                               serv = elt->server;
-                               serv->ups_elt = elt;
+                       if (resolver->ups) {
+                               struct rdns_upstream_elt *elt;
+
+                               elt = resolver->ups->select_retransmit (req->requested_names[0].name,
+                                               req->requested_names[0].len, resolver->ups->data);
+
+                               if (elt) {
+                                       serv = elt->server;
+                                       serv->ups_elt = elt;
+                               }
+                               else {
+                                       UPSTREAM_SELECT_ROUND_ROBIN (resolver->servers, serv);
+                               }
                        }
                        else {
                                UPSTREAM_SELECT_ROUND_ROBIN (resolver->servers, serv);
                        }
-               }
-               else {
-                       UPSTREAM_SELECT_ROUND_ROBIN (resolver->servers, serv);
-               }
 
-               if (serv == NULL) {
-                       rdns_warn ("cannot find suitable server for request");
-                       rep = rdns_make_reply (req, RDNS_RC_SERVFAIL);
-                       req->state = RDNS_REQUEST_REPLIED;
-                       req->func (rep, req->arg);
-                       REF_RELEASE (req);
+                       if (serv == NULL) {
+                               rdns_warn ("cannot find suitable server for request");
+                               rep = rdns_make_reply (req, RDNS_RC_SERVFAIL);
+                               req->state = RDNS_REQUEST_REPLIED;
+                               req->func (rep, req->arg);
+                               REF_RELEASE (req);
 
-                       return;
-               }
+                               return;
+                       }
 
-               /* Select random IO channel */
-               req->io = serv->io_channels[ottery_rand_uint32 () % serv->io_cnt];
-               req->io->uses ++;
-               REF_RETAIN (req->io);
-               renew = true;
+                       /* Select random IO channel */
+                       req->io = serv->io_channels[ottery_rand_uint32 () % serv->io_cnt];
+                       req->io->uses ++;
+                       REF_RETAIN (req->io);
+                       renew = true;
+               }
        }
 
        /*
index 13d1b8309d444ebb8348d1a4a82583218b369deb..34b6852608b1e31ee5bc91b9a5345c19fde551fd 100644 (file)
@@ -30,12 +30,14 @@ static void rspamd_dns_upstream_ok (struct rdns_upstream_elt *elt,
                void *ups_data);
 static void rspamd_dns_upstream_fail (struct rdns_upstream_elt *elt,
                void *ups_data);
+static unsigned int rspamd_dns_upstream_count (void *ups_data);
 
 static struct rdns_upstream_context rspamd_ups_ctx = {
                .select = rspamd_dns_select_upstream,
                .select_retransmit = rspamd_dns_select_upstream_retransmit,
                .ok = rspamd_dns_upstream_ok,
                .fail = rspamd_dns_upstream_fail,
+               .count = rspamd_dns_upstream_count,
                .data = NULL
 };
 
@@ -340,3 +342,11 @@ rspamd_dns_upstream_fail (struct rdns_upstream_elt *elt,
 
        rspamd_upstream_fail (up);
 }
+
+static unsigned int
+rspamd_dns_upstream_count (void *ups_data)
+{
+       struct upstream_list *ups = ups_data;
+
+       return rspamd_upstreams_alive (ups);
+}