]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Rdns: Initial support of TCP IO channels
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 1 Jan 2022 17:49:27 +0000 (17:49 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 1 Jan 2022 17:49:27 +0000 (17:49 +0000)
contrib/librdns/dns_private.h
contrib/librdns/resolver.c
contrib/librdns/util.c

index f59fa2719f11f8e1be93d2e5b67dbd579b6d2fe2..4429552bce17f85a2dff14086ed019f28da2954f 100644 (file)
@@ -34,6 +34,7 @@
 
 static const int dns_port = 53;
 static const int default_io_cnt = 8;
+static const int default_tcp_io_cnt = 2;
 
 #define UDP_PACKET_SIZE (4096 * 2)
 
@@ -51,8 +52,10 @@ struct rdns_server {
        char *name;
        unsigned int port;
        unsigned int io_cnt;
+       unsigned int tcp_io_cnt;
 
        struct rdns_io_channel **io_channels;
+       struct rdns_io_channel **tcp_io_channels;
        void *ups_elt;
        upstream_entry_t up;
 };
index 6b1ed8211ae3503d103bcabd8414fe38bc883ccd..d7d41915f0f8bb83ee89da6c230424e5a8106533 100644 (file)
@@ -893,6 +893,18 @@ rdns_resolver_init (struct rdns_resolver *resolver)
 
                        serv->io_channels[i] = ioc;
                }
+
+               serv->tcp_io_channels = calloc (serv->tcp_io_cnt, sizeof (struct rdns_io_channel *));
+               for (i = 0; i < serv->tcp_io_cnt; i ++) {
+                       ioc = rdns_ioc_new (serv, resolver, true);
+
+                       if (ioc == NULL) {
+                               rdns_err ("cannot allocate memory for the resolver IO channels");
+                               return false;
+                       }
+
+                       serv->tcp_io_channels[i] = ioc;
+               }
        }
 
        if (resolver->async->add_periodic) {
@@ -952,6 +964,8 @@ rdns_resolver_add_server (struct rdns_resolver *resolver,
        }
 
        serv->io_cnt = io_cnt;
+       /* TODO: make it configurable maybe? */
+       serv->tcp_io_cnt = default_tcp_io_cnt;
        serv->port = port;
 
        UPSTREAM_ADD (resolver->servers, serv, priority);
@@ -1026,7 +1040,10 @@ rdns_resolver_free (struct rdns_resolver *resolver)
                                ioc = serv->io_channels[i];
                                REF_RELEASE (ioc);
                        }
-                       serv->io_cnt = 0;
+                       for (i = 0; i < serv->tcp_io_cnt; i ++) {
+                               ioc = serv->tcp_io_channels[i];
+                               REF_RELEASE (ioc);
+                       }
                        UPSTREAM_DEL (resolver->servers, serv);
                        free (serv->io_channels);
                        free (serv->name);
index d69ef6cd04b960d159e0e6c4180a2ac88100fdb5..3cdb88fd032ccdb0ba321c3d6589597d3d563c3f 100644 (file)
@@ -530,11 +530,42 @@ rdns_ioc_new (struct rdns_server *serv,
                return NULL;
        }
 
+       if (is_tcp) {
+               /* We also need to connect a TCP channel */
+               int r = connect (nioc->sock, nioc->saddr, nioc->slen);
+
+               if (r == -1) {
+                       if (errno != EAGAIN && errno != EINTR && errno != EINPROGRESS) {
+                               rdns_err ("cannot connect a TCP socket: %s for server %s",
+                                               strerror(errno), serv->name);
+                               close(nioc->sock);
+                               free(nioc);
+
+                               return NULL;
+                       }
+                       else {
+                               /* We need to wait for write readiness here */
+                               nioc->async_io = resolver->async->add_write (resolver->async->data,
+                                               nioc->sock, nioc);
+                       }
+               }
+               else {
+                       nioc->flags |= RDNS_CHANNEL_CONNECTED|RDNS_CHANNEL_ACTIVE;
+               }
+
+               nioc->flags |= RDNS_CHANNEL_TCP;
+       }
+
        nioc->srv = serv;
-       nioc->flags = RDNS_CHANNEL_ACTIVE;
        nioc->resolver = resolver;
-       nioc->async_io = resolver->async->add_read (resolver->async->data,
-                       nioc->sock, nioc);
+
+       /* If it is not NULL then we are in a delayed connection state */
+       if (nioc->async_io == NULL) {
+               nioc->flags |= RDNS_CHANNEL_ACTIVE;
+               nioc->async_io = resolver->async->add_read(resolver->async->data,
+                               nioc->sock, nioc);
+       }
+
        nioc->requests = kh_init(rdns_requests_hash);
        REF_INIT_RETAIN (nioc, rdns_ioc_free);