]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dns: Use connection.c
authorAki Tuomi <aki.tuomi@dovecot.fi>
Thu, 16 Aug 2018 07:32:38 +0000 (10:32 +0300)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 13 Nov 2018 13:09:32 +0000 (15:09 +0200)
This enables processing multiple requests at a time.

src/dns/dns-client.c

index 53a41be7ff02623e9e901e68340aa8499fad81de..8c3a6bd47abeb7082f1c28146ff94df9a90e49fc 100644 (file)
@@ -1,38 +1,34 @@
 /* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "ioloop.h"
 #include "istream.h"
 #include "ostream.h"
+#include "array.h"
+#include "strfuncs.h"
+#include "connection.h"
 #include "restrict-access.h"
 #include "master-service.h"
 
 #include <unistd.h>
 
-struct dns_client {
-       int fd;
-       struct istream *input;
-       struct ostream *output;
-       struct io *io;
-};
-
-#define MAX_INBUF_SIZE 1024
-#define MAX_OUTBUF_SIZE (1024*64)
-#define INPUT_TIMEOUT_MSECS (1000*10)
-
-static struct dns_client *dns_client = NULL;
-
-static void dns_client_destroy(struct dns_client **client);
+static struct connection_list *dns_clients = NULL;
 
-static int dns_client_input_line(struct dns_client *client, const char *line)
+static int dns_client_input_args(struct connection *client, const char *const *args)
 {
        struct ip_addr *ips, ip;
        const char *name;
        unsigned int i, ips_count;
        int ret;
 
-       if (str_begins(line, "IP\t")) {
-               ret = net_gethostbyname(line + 3, &ips, &ips_count);
+       if (strcmp(args[0], "QUIT") == 0) {
+               return -1;
+       } else if (args[1] == NULL) {
+               i_error("Got empty request");
+               return -1;
+       }
+
+       if (strcmp(args[0], "IP") == 0) {
+               ret = net_gethostbyname(args[1], &ips, &ips_count);
                if (ret == 0 && ips_count == 0) {
                        /* shouldn't happen, but fix it anyway.. */
                        ret = EAI_NONAME;
@@ -44,12 +40,13 @@ static int dns_client_input_line(struct dns_client *client, const char *line)
                        o_stream_nsend_str(client->output,
                                t_strdup_printf("0 %u\n", ips_count));
                        for (i = 0; i < ips_count; i++) {
+                               const char *ip = net_ip2addr(&ips[i]);
                                o_stream_nsend_str(client->output, t_strconcat(
                                        net_ip2addr(&ips[i]), "\n", NULL));
                        }
                }
-       } else if (str_begins(line, "NAME\t")) {
-               if (net_addr2ip(line+5, &ip) < 0)
+       } else if (strcmp(args[0], "NAME") == 0) {
+               if (net_addr2ip(args[1], &ip) < 0)
                        o_stream_nsend_str(client->output, "-1\n");
                else if ((ret = net_gethostbyaddr(&ip, &name)) != 0) {
                        o_stream_nsend_str(client->output,
@@ -58,74 +55,37 @@ static int dns_client_input_line(struct dns_client *client, const char *line)
                        o_stream_nsend_str(client->output,
                                t_strdup_printf("0 %s\n", name));
                }
-       } else if (strcmp(line, "QUIT") == 0) {
-               return -1;
        } else {
                o_stream_nsend_str(client->output, "Unknown command\n");
        }
 
-       if (client->output->overflow)
-               return -1;
-       return 0;
-}
-
-static void dns_client_input(struct dns_client *client)
-{
-       const char *line;
-       int ret = 0;
-
-       o_stream_cork(client->output);
-       while ((line = i_stream_read_next_line(client->input)) != NULL) {
-               if (dns_client_input_line(client, line) < 0) {
-                       ret = -1;
-                       break;
-               }
-       }
-       o_stream_uncork(client->output);
-
-       if (client->input->eof || client->input->stream_errno != 0 || ret < 0)
-               dns_client_destroy(&client);
-}
-
-static struct dns_client *dns_client_create(int fd)
-{
-       struct dns_client *client;
-
-       client = i_new(struct dns_client, 1);
-       client->fd = fd;
-       client->input = i_stream_create_fd(fd, MAX_INBUF_SIZE);
-       client->output = o_stream_create_fd(fd, MAX_OUTBUF_SIZE);
-       o_stream_set_no_error_handling(client->output, TRUE);
-       client->io = io_add(fd, IO_READ, dns_client_input, client);
-       return client;
+       return 1;
 }
 
-static void dns_client_destroy(struct dns_client **_client)
+static void dns_client_destroy(struct connection *client)
 {
-       struct dns_client *client = *_client;
-
-       *_client = NULL;
-
-       io_remove(&client->io);
-       i_stream_destroy(&client->input);
-       o_stream_destroy(&client->output);
-       if (close(client->fd) < 0)
-               i_error("close() failed: %m");
+       connection_deinit(client);
        i_free(client);
-
-       dns_client = NULL;
        master_service_client_connection_destroyed(master_service);
 }
 
-static void client_connected(struct master_service_connection *conn)
-{
-       if (dns_client != NULL) {
-               i_error("dns-client must be configured with client_limit=1");
-               return;
-       }
+static const struct connection_vfuncs dns_client_vfuncs = {
+       .input_args = dns_client_input_args,
+       .destroy = dns_client_destroy
+};
+
+static const struct connection_settings dns_client_set = {
+       .dont_send_version = TRUE,
+       .input_max_size = (size_t)-1,
+       .output_max_size = (size_t)-1
+};
 
-       master_service_client_connection_accept(conn);
-       dns_client = dns_client_create(conn->fd);
+static void client_connected(struct master_service_connection *master_conn)
+{
+       struct connection *conn = i_new(struct connection, 1);
+       master_service_client_connection_accept(master_conn);
+       connection_init_server(dns_clients, conn, master_conn->name,
+                              master_conn->fd, master_conn->fd);
 }
 
 int main(int argc, char *argv[])
@@ -140,9 +100,13 @@ int main(int argc, char *argv[])
 
        master_service_init_finish(master_service);
 
+       /* setup connection list */
+       dns_clients = connection_list_init(&dns_client_set, &dns_client_vfuncs);
+
        master_service_run(master_service, client_connected);
-       if (dns_client != NULL)
-               dns_client_destroy(&dns_client);
+
+       /* disconnect all clients */
+       connection_list_deinit(&dns_clients);
 
        master_service_deinit(&master_service);
         return 0;