]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm-server: Restructured client-connection code so that TCP and HTTP connection...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 7 Oct 2017 11:39:44 +0000 (13:39 +0200)
committerStephan Bosch <stephan.bosch@dovecot.fi>
Tue, 24 Oct 2017 20:29:19 +0000 (22:29 +0200)
src/doveadm/client-connection-http.c
src/doveadm/client-connection-private.h
src/doveadm/client-connection-tcp.c
src/doveadm/client-connection.c
src/doveadm/client-connection.h
src/doveadm/main.c

index aac00c3c91555d1f23a52255c63a3879df3b5c7e..67c4c8a9f4c02a23fd12d113325574fa27be7e15 100644 (file)
 
 struct client_connection_http {
        struct client_connection conn;
+
        struct http_server_connection *http_client;
 
        struct http_server_request *http_server_request;
        const struct http_request *http_request;
        struct http_server_response *http_response;
 
+       struct io *io;
+       struct istream *input;
+       struct ostream *output;
+
        struct json_parser *json_parser;
 
        const struct doveadm_cmd_ver2 *cmd;
@@ -116,14 +121,19 @@ static struct doveadm_http_server_mount doveadm_http_server_mounts[] = {
 
 static void doveadm_http_server_send_response(void *context);
 
-void client_connection_destroy_http(struct client_connection *conn)
+static void
+client_connection_http_free(struct client_connection *_conn)
 {
-       struct client_connection_http *hconn =
-               (struct client_connection_http *)conn;
+       struct client_connection_http *conn =
+               (struct client_connection_http *)_conn;
 
-       if (hconn->http_client != NULL) {
+       io_remove(&conn->io);
+       o_stream_destroy(&conn->output);
+       i_stream_destroy(&conn->input);
+
+       if (conn->http_client != NULL) {
                /* We're not in the lib-http/server's connection destroy callback. */
-               http_server_connection_close(&hconn->http_client,
+               http_server_connection_close(&conn->http_client,
                        "Server shutting down");
        }
 }
@@ -136,16 +146,16 @@ client_connection_http_create(int fd, bool ssl)
 
        pool = pool_alloconly_create("doveadm client", 1024*16);
        conn = p_new(pool, struct client_connection_http, 1);
-       conn->conn.pool = pool;
-       conn->conn.http = TRUE;
 
        if (client_connection_init(&conn->conn,
-               CLIENT_CONNECTION_TYPE_HTTP, fd) < 0)
+               CLIENT_CONNECTION_TYPE_HTTP, pool, fd) < 0) {
+               pool_unref(&conn->conn.pool);
                return NULL;
+       }
+       conn->conn.free = client_connection_http_free;
 
        conn->http_client = http_server_connection_create(doveadm_http_server,
                        fd, fd, ssl, &doveadm_http_callbacks, conn);
-       conn->conn.fd = -1;
        return &conn->conn;
 }
 
@@ -153,20 +163,20 @@ static void
 doveadm_http_server_connection_destroy(void *context,
        const char *reason ATTR_UNUSED)
 {
-       struct client_connection_http *hconn =
+       struct client_connection_http *conn =
                (struct client_connection_http *)context;
-       struct client_connection *conn = &hconn->conn;
+       struct client_connection *bconn = &conn->conn;
 
-       if (hconn->http_client == NULL) {
+       if (conn->http_client == NULL) {
                /* already destroying client directly */
                return;
        }
 
        /* HTTP connection is destroyed already now */
-       hconn->http_client = NULL;
+       conn->http_client = NULL;
 
        /* destroy the connection itself */
-       client_connection_destroy(&conn);
+       client_connection_destroy(&bconn);
 }
 
 static void
@@ -200,8 +210,8 @@ doveadm_http_server_request_destroy(struct client_connection_http *conn)
                (void)json_parser_deinit(&conn->json_parser, &error);
                // we've already failed, ignore error
        }
-       if (conn->conn.output != NULL)
-               o_stream_set_no_error_handling(conn->conn.output, TRUE);
+       if (conn->output != NULL)
+               o_stream_set_no_error_handling(conn->output, TRUE);
 
        http_server_request_unref(&(conn->http_server_request));
        http_server_switch_ioloop(doveadm_http_server);
@@ -210,7 +220,7 @@ doveadm_http_server_request_destroy(struct client_connection_http *conn)
 static void doveadm_http_server_json_error(void *context, const char *error)
 {
        struct client_connection_http *conn = context;
-       struct ostream *output = conn->conn.output;
+       struct ostream *output = conn->output;
        string_t *escaped;
 
        escaped = str_new(conn->conn.pool, 10);
@@ -234,7 +244,7 @@ static void doveadm_http_server_json_error(void *context, const char *error)
 static void doveadm_http_server_json_success(void *context, struct istream *result)
 {
        struct client_connection_http *conn = context;
-       struct ostream *output = conn->conn.output;
+       struct ostream *output = conn->output;
        string_t *escaped;
 
        escaped = str_new(conn->conn.pool, 10);
@@ -390,8 +400,8 @@ doveadm_http_server_command_execute(struct client_connection_http *conn)
        prev_ioloop = current_ioloop;
        i_zero(&cctx);
        cctx.conn_type = conn->conn.type;
-       cctx.input = conn->conn.input;
-       cctx.output = conn->conn.output;
+       cctx.input = conn->input;
+       cctx.output = conn->output;
 
        // create iostream
        doveadm_print_ostream = iostream_temp_create("/tmp/doveadm.", 0);
@@ -420,7 +430,7 @@ doveadm_http_server_command_execute(struct client_connection_http *conn)
        client_connection_set_proctitle(&conn->conn, "");
 
        io_loop_set_current(prev_ioloop);
-       o_stream_switch_ioloop(conn->conn.output);
+       o_stream_switch_ioloop(conn->output);
        io_loop_set_current(ioloop);
        io_loop_destroy(&ioloop);
 
@@ -429,7 +439,7 @@ doveadm_http_server_command_execute(struct client_connection_http *conn)
        if (o_stream_nfinish(doveadm_print_ostream) < 0) {
                i_info("Error writing output in command %s: %s",
                       conn->cmd->name,
-                      o_stream_get_error(conn->conn.output));
+                      o_stream_get_error(conn->output));
                doveadm_exit_code = EX_TEMPFAIL;
        }
 
@@ -438,7 +448,7 @@ doveadm_http_server_command_execute(struct client_connection_http *conn)
        if (conn->first_row == TRUE)
                conn->first_row = FALSE;
        else
-               o_stream_nsend_str(conn->conn.output,",");
+               o_stream_nsend_str(conn->output,",");
 
        if (doveadm_exit_code != 0) {
                if (doveadm_exit_code == 0 || doveadm_exit_code == EX_TEMPFAIL)
@@ -464,7 +474,7 @@ doveadm_http_handle_json_v1(struct client_connection_http *conn,
                        return FALSE;
                conn->json_state = JSON_STATE_COMMAND;
                conn->first_row = TRUE;
-               o_stream_nsend_str(conn->conn.output,"[");
+               o_stream_nsend_str(conn->output,"[");
                return TRUE;
        case JSON_STATE_COMMAND:
                if (type == JSON_TYPE_ARRAY_END) {
@@ -585,7 +595,7 @@ doveadm_http_server_read_request_v1(struct client_connection_http *conn)
        int ret;
 
        if (conn->json_parser == NULL) {
-               conn->json_parser = json_parser_init_flags(conn->conn.input, JSON_PARSER_NO_ROOT_OBJECT);
+               conn->json_parser = json_parser_init_flags(conn->input, JSON_PARSER_NO_ROOT_OBJECT);
        }
 
        while ((ret = doveadm_http_server_json_parse_next(conn, &type, &value)) == 1) {
@@ -593,9 +603,9 @@ doveadm_http_server_read_request_v1(struct client_connection_http *conn)
                        break;
        }
 
-       if (!conn->conn.input->eof && ret == 0)
+       if (!conn->input->eof && ret == 0)
                return;
-       io_remove(&conn->conn.io);
+       io_remove(&conn->io);
 
        doveadm_cmd_params_clean(&conn->pargv);
 
@@ -607,10 +617,10 @@ doveadm_http_server_read_request_v1(struct client_connection_http *conn)
                return;
        }
 
-       if (conn->conn.input->stream_errno != 0) {
+       if (conn->input->stream_errno != 0) {
                http_server_request_fail_close(http_sreq, 400, "Client disconnected");
                i_info("read(client) failed: %s",
-                      i_stream_get_error(conn->conn.input));
+                      i_stream_get_error(conn->input));
                return;
        }
 
@@ -621,7 +631,7 @@ doveadm_http_server_read_request_v1(struct client_connection_http *conn)
                i_info("JSON parse error: %s", error);
                return;
        }
-       o_stream_nsend_str(conn->conn.output,"]");
+       o_stream_nsend_str(conn->output,"]");
 
        doveadm_http_server_send_response(conn);
 }
@@ -645,7 +655,7 @@ static void doveadm_http_server_camelcase_value(string_t *value)
 static void
 doveadm_http_server_send_api_v1(struct client_connection_http *conn)
 {
-       struct ostream *output = conn->conn.output;
+       struct ostream *output = conn->output;
        const struct doveadm_cmd_ver2 *cmd;
        const struct doveadm_cmd_param *par;
        unsigned int i, k;
@@ -728,7 +738,7 @@ doveadm_http_server_options_handler(struct client_connection_http *conn)
 static void
 doveadm_http_server_print_mounts(struct client_connection_http *conn)
 {
-       struct ostream *output = conn->conn.output;
+       struct ostream *output = conn->output;
        unsigned int i;
 
        o_stream_nsend_str(output, "[\n");
@@ -847,16 +857,16 @@ doveadm_http_server_handle_request(void *context, struct http_server_request *ht
 
        if (strcmp(http_req->method, "POST") == 0) {
                /* handle request */
-               conn->conn.input = http_req->payload;
-               i_stream_set_name(conn->conn.input, net_ip2addr(&conn->conn.remote_ip));
-               i_stream_ref(conn->conn.input);
-               conn->conn.io = io_add_istream(conn->conn.input, *ep->handler, conn);
-               conn->conn.output = iostream_temp_create_named
+               conn->input = http_req->payload;
+               i_stream_set_name(conn->input, net_ip2addr(&conn->conn.remote_ip));
+               i_stream_ref(conn->input);
+               conn->io = io_add_istream(conn->input, *ep->handler, conn);
+               conn->output = iostream_temp_create_named
                        ("/tmp/doveadm.", 0, net_ip2addr(&conn->conn.remote_ip));
                p_array_init(&conn->pargv, conn->conn.pool, 5);
                ep->handler(conn);
        } else {
-               conn->conn.output = iostream_temp_create_named
+               conn->output = iostream_temp_create_named
                        ("/tmp/doveadm.", 0, net_ip2addr(&conn->conn.remote_ip));
                ep->handler(conn);
        }
@@ -867,17 +877,17 @@ static void doveadm_http_server_send_response(void *context)
        struct client_connection_http *conn = context;
        struct http_server_response *http_resp = conn->http_response;
 
-       if (conn->conn.output != NULL) {
-               if (o_stream_nfinish(conn->conn.output) == -1) {
+       if (conn->output != NULL) {
+               if (o_stream_nfinish(conn->output) == -1) {
                        i_info("error writing output: %s",
-                              o_stream_get_error(conn->conn.output));
-                       o_stream_destroy(&conn->conn.output);
+                              o_stream_get_error(conn->output));
+                       o_stream_destroy(&conn->output);
                        http_server_response_update_status(http_resp, 500, "Internal server error");
                } else {
                        // send the payload response
                        struct istream *is;
 
-                       is = iostream_temp_finish(&conn->conn.output, IO_BLOCK_SIZE);
+                       is = iostream_temp_finish(&conn->output, IO_BLOCK_SIZE);
                        http_server_response_set_payload(http_resp, is);
                        i_stream_unref(&is);
                }
index 4effdf806d1d5dd1ea5dfba98adc614e8bed5edc..5b6b698ce58a26cbbedd574029b68527d9f784b5 100644 (file)
@@ -7,15 +7,16 @@ bool doveadm_client_is_allowed_command(const struct doveadm_settings *set,
        const char *cmd_name);
 
 int client_connection_init(struct client_connection *conn,
-       enum client_connection_type type, int fd);
-void client_connection_deinit(struct client_connection *conn ATTR_UNUSED);
+       enum client_connection_type type, pool_t pool, int fd);
+void client_connection_destroy(struct client_connection **_conn);
 
 void client_connection_set_proctitle(struct client_connection *conn,
                                     const char *text);
 
-void client_connection_destroy_http(struct client_connection *conn);
-
 void doveadm_http_server_init(void);
 void doveadm_http_server_deinit(void);
 
+void doveadm_server_init(void);
+void doveadm_server_deinit(void);
+
 #endif
index b045fca68c882fac3b6b90117b4bc2f0c78b7928..3fcbcf439ef58872b1d2f50062e275a6290f1558 100644 (file)
 #include "master-service-ssl.h"
 #include "mail-storage-service.h"
 #include "doveadm-util.h"
-#include "doveadm-server.h"
 #include "doveadm-mail.h"
 #include "doveadm-print.h"
+#include "doveadm-server.h"
 #include "client-connection-private.h"
 
 #include <unistd.h>
 
 #define MAX_INBUF_SIZE (1024*1024)
 
-static void client_connection_input(struct client_connection *conn);
+struct client_connection_tcp {
+       struct client_connection conn;
+
+       int fd;
+       struct io *io;
+       struct istream *input;
+       struct ostream *output;
+       struct ostream *log_out;
+       struct ssl_iostream *ssl_iostream;
+
+       bool handshaked:1;
+       bool authenticated:1;
+       bool io_setup:1;
+       bool use_multiplex:1;
+};
+
+static void
+client_connection_tcp_input(struct client_connection_tcp *conn);
+static void
+client_connection_tcp_destroy(struct client_connection_tcp **_conn);
 
 static failure_callback_t *orig_error_callback, *orig_fatal_callback;
 static failure_callback_t *orig_info_callback, *orig_debug_callback = NULL;
@@ -34,9 +53,15 @@ static void ATTR_FORMAT(2, 0)
 doveadm_server_log_handler(const struct failure_context *ctx,
                           const char *format, va_list args)
 {
-       if (!log_recursing && doveadm_client != NULL &&
-           doveadm_client->log_out != NULL) T_BEGIN {
-               struct ostream *log_out = doveadm_client->log_out;
+       struct client_connection_tcp *conn = NULL;
+
+       if (doveadm_client != NULL &&
+               doveadm_client->type == CLIENT_CONNECTION_TYPE_TCP)
+               conn = (struct client_connection_tcp *)doveadm_client;
+
+       if (!log_recursing && conn != NULL &&
+           conn->log_out != NULL) T_BEGIN {
+               struct ostream *log_out = conn->log_out;
                char c;
                const char *ptr, *start;
                bool corked;
@@ -113,7 +138,7 @@ static void doveadm_server_restore_logs(void)
 }
 
 static void
-doveadm_cmd_server_post(struct client_connection *conn, const char *cmd_name)
+doveadm_cmd_server_post(struct client_connection_tcp *conn, const char *cmd_name)
 {
        const char *str = NULL;
 
@@ -135,7 +160,7 @@ doveadm_cmd_server_post(struct client_connection *conn, const char *cmd_name)
 }
 
 static void
-doveadm_cmd_server_run_ver2(struct client_connection *conn,
+doveadm_cmd_server_run_ver2(struct client_connection_tcp *conn,
                            int argc, const char *const argv[],
                            struct doveadm_cmd_context *cctx)
 {
@@ -146,7 +171,7 @@ doveadm_cmd_server_run_ver2(struct client_connection *conn,
 }
 
 static void
-doveadm_cmd_server_run(struct client_connection *conn,
+doveadm_cmd_server_run(struct client_connection_tcp *conn,
                       int argc, const char *const argv[],
                       const struct doveadm_cmd *cmd)
 {
@@ -233,7 +258,7 @@ doveadm_mail_cmd_server_parse(const struct doveadm_mail_cmd *cmd,
 }
 
 static void
-doveadm_mail_cmd_server_run(struct client_connection *conn,
+doveadm_mail_cmd_server_run(struct client_connection_tcp *conn,
                            struct doveadm_mail_cmd_context *mctx)
 {
        const char *error;
@@ -266,7 +291,7 @@ doveadm_mail_cmd_server_run(struct client_connection *conn,
        pool_unref(&mctx->pool);
 }
 
-static int doveadm_cmd_handle(struct client_connection *conn,
+static int doveadm_cmd_handle(struct client_connection_tcp *conn,
                              const char *cmd_name,
                              int argc, const char *const argv[],
                              struct doveadm_cmd_context *cctx)
@@ -286,7 +311,7 @@ static int doveadm_cmd_handle(struct client_connection *conn,
                                return -1;
                        }
                } else {
-                       if (doveadm_mail_cmd_server_parse(mail_cmd, conn->set,
+                       if (doveadm_mail_cmd_server_parse(mail_cmd, conn->conn.set,
                                                          argc, argv,
                                                          cctx, &mctx) < 0)
                                return -1;
@@ -320,7 +345,7 @@ static int doveadm_cmd_handle(struct client_connection *conn,
        return doveadm_exit_code == 0 ? 0 : -1;
 }
 
-static bool client_handle_command(struct client_connection *conn,
+static bool client_handle_command(struct client_connection_tcp *conn,
                                  const char *const *args)
 {
        struct doveadm_cmd_context cctx;
@@ -332,13 +357,13 @@ static bool client_handle_command(struct client_connection *conn,
                return FALSE;
        }
        i_zero(&cctx);
-       cctx.conn_type = conn->type;
+       cctx.conn_type = conn->conn.type;
        cctx.input = conn->input;
        cctx.output = conn->output;
-       cctx.local_ip = conn->local_ip;
-       cctx.remote_ip = conn->remote_ip;
-       cctx.local_port = conn->local_port;
-       cctx.remote_port = conn->remote_port;
+       cctx.local_ip = conn->conn.local_ip;
+       cctx.remote_ip = conn->conn.remote_ip;
+       cctx.local_port = conn->conn.local_port;
+       cctx.remote_port = conn->conn.remote_port;
        doveadm_exit_code = 0;
 
        flags = args[0];
@@ -363,18 +388,18 @@ static bool client_handle_command(struct client_connection *conn,
                }
        }
 
-       if (!doveadm_client_is_allowed_command(conn->set, cmd_name)) {
+       if (!doveadm_client_is_allowed_command(conn->conn.set, cmd_name)) {
                i_error("doveadm client isn't allowed to use command: %s",
                        cmd_name);
                return FALSE;
        }
 
-       client_connection_set_proctitle(conn, cmd_name);
+       client_connection_set_proctitle(&conn->conn, cmd_name);
        o_stream_cork(conn->output);
        if (doveadm_cmd_handle(conn, cmd_name, argc-2, args+2, &cctx) < 0)
                o_stream_nsend(conn->output, "\n-\n", 3);
        o_stream_uncork(conn->output);
-       client_connection_set_proctitle(conn, "");
+       client_connection_set_proctitle(&conn->conn, "");
 
        /* flush the output and possibly run next command */
        net_set_nonblock(conn->fd, FALSE);
@@ -384,8 +409,9 @@ static bool client_handle_command(struct client_connection *conn,
 }
 
 static int
-client_connection_authenticate(struct client_connection *conn)
+client_connection_tcp_authenticate(struct client_connection_tcp *conn)
 {
+       const struct doveadm_settings *set = conn->conn.set;
        const char *line, *pass;
        buffer_t *plain;
        const unsigned char *data;
@@ -397,7 +423,7 @@ client_connection_authenticate(struct client_connection *conn)
                return 0;
        }
 
-       if (*conn->set->doveadm_password == '\0') {
+       if (*set->doveadm_password == '\0') {
                i_error("doveadm_password not set, "
                        "remote authentication disabled");
                return -1;
@@ -424,8 +450,8 @@ client_connection_authenticate(struct client_connection *conn)
                return -1;
        }
        pass = t_strndup(data + 9, size - 9);
-       if (strlen(pass) != strlen(conn->set->doveadm_password) ||
-           !mem_equals_timing_safe(pass, conn->set->doveadm_password,
+       if (strlen(pass) != strlen(set->doveadm_password) ||
+           !mem_equals_timing_safe(pass, set->doveadm_password,
                                    strlen(pass))) {
                i_error("doveadm client authenticated with wrong password");
                return -1;
@@ -433,7 +459,7 @@ client_connection_authenticate(struct client_connection *conn)
        return 1;
 }
 
-static void client_log_disconnect_error(struct client_connection *conn)
+static void client_log_disconnect_error(struct client_connection_tcp *conn)
 {
        const char *error;
 
@@ -446,7 +472,8 @@ static void client_log_disconnect_error(struct client_connection *conn)
        i_error("doveadm client disconnected before handshake: %s", error);
 }
 
-static void client_connection_input(struct client_connection *conn)
+static void
+client_connection_tcp_input(struct client_connection_tcp *conn)
 {
        const char *line;
        bool ok = TRUE;
@@ -457,7 +484,7 @@ static void client_connection_input(struct client_connection *conn)
                if ((line = i_stream_read_next_line(conn->input)) == NULL) {
                        if (conn->input->eof || conn->input->stream_errno != 0) {
                                client_log_disconnect_error(conn);
-                               client_connection_destroy(&conn);
+                               client_connection_tcp_destroy(&conn);
                        }
                        return;
                }
@@ -465,7 +492,7 @@ static void client_connection_input(struct client_connection *conn)
                                DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR, &minor)) {
                        i_error("doveadm client not compatible with this server "
                                "(mixed old and new binaries?)");
-                       client_connection_destroy(&conn);
+                       client_connection_tcp_destroy(&conn);
                        return;
                }
                if (minor > 0) {
@@ -477,10 +504,10 @@ static void client_connection_input(struct client_connection *conn)
                conn->handshaked = TRUE;
        }
        if (!conn->authenticated) {
-               if ((ret = client_connection_authenticate(conn)) <= 0) {
+               if ((ret = client_connection_tcp_authenticate(conn)) <= 0) {
                        if (ret < 0) {
                                o_stream_nsend(conn->output, "-\n", 2);
-                               client_connection_destroy(&conn);
+                               client_connection_tcp_destroy(&conn);
                        }
                        return;
                }
@@ -517,10 +544,11 @@ static void client_connection_input(struct client_connection *conn)
                } T_END;
        }
        if (conn->input->eof || conn->input->stream_errno != 0 || !ok)
-               client_connection_destroy(&conn);
+               client_connection_tcp_destroy(&conn);
 }
 
-static int client_connection_init_ssl(struct client_connection *conn)
+static int
+client_connection_tcp_init_ssl(struct client_connection_tcp *conn)
 {
        const char *error;
 
@@ -539,7 +567,7 @@ static int client_connection_init_ssl(struct client_connection *conn)
 }
 
 static void
-client_connection_send_auth_handshake(struct client_connection *
+client_connection_tcp_send_auth_handshake(struct client_connection_tcp *
                                      conn, int listen_fd)
 {
        const char *listen_path;
@@ -558,71 +586,75 @@ client_connection_send_auth_handshake(struct client_connection *
        }
 }
 
-void client_connection_destroy(struct client_connection **_conn)
+static void
+client_connection_tcp_free(struct client_connection *_conn)
 {
-       struct client_connection *conn = *_conn;
+       struct client_connection_tcp *conn =
+               (struct client_connection_tcp *)_conn;
 
-       *_conn = NULL;
+       i_assert(_conn->type == CLIENT_CONNECTION_TYPE_TCP);
 
        doveadm_print_deinit();
-
-       if (conn->http)
-               client_connection_destroy_http(conn);
+       doveadm_print_ostream = NULL;
 
        if (conn->ssl_iostream != NULL)
                ssl_iostream_destroy(&conn->ssl_iostream);
 
-       o_stream_destroy(&conn->output);
-
-       io_remove(&conn->io);
-
        if (conn->log_out != NULL) {
                doveadm_server_restore_logs();
                o_stream_unref(&conn->log_out);
        }
 
+       io_remove(&conn->io);
+       o_stream_destroy(&conn->output);
        i_stream_destroy(&conn->input);
-
        i_close_fd(&conn->fd);
-       pool_unref(&conn->pool);
-
-       doveadm_print_ostream = NULL;
-
-       client_connection_deinit(conn);
 }
 
 struct client_connection *
 client_connection_tcp_create(int fd, int listen_fd, bool ssl)
 {
-       struct client_connection *conn;
+       struct client_connection_tcp *conn;
        pool_t pool;
 
        pool = pool_alloconly_create("doveadm client", 1024*16);
-       conn = p_new(pool, struct client_connection, 1);
-       conn->pool = pool;
+       conn = p_new(pool, struct client_connection_tcp, 1);
+       conn->fd = fd;
 
-       if (client_connection_init(conn,
-               CLIENT_CONNECTION_TYPE_TCP, fd) < 0)
+       if (client_connection_init(&conn->conn,
+               CLIENT_CONNECTION_TYPE_TCP, pool, fd) < 0) {
+               client_connection_tcp_destroy(&conn);
                return NULL;
-        doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
+       }
+       conn->conn.free = client_connection_tcp_free;
 
-       conn->name = conn->remote_ip.family == 0 ? "<local>" :
-               p_strdup(pool, net_ip2addr(&conn->remote_ip));
-       conn->io = io_add(fd, IO_READ, client_connection_input, conn);
+       doveadm_print_init(DOVEADM_PRINT_TYPE_SERVER);
+
+       conn->io = io_add(fd, IO_READ, client_connection_tcp_input, conn);
        conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE);
        conn->output = o_stream_create_fd(fd, (size_t)-1);
-       i_stream_set_name(conn->input, conn->name);
-       o_stream_set_name(conn->output, conn->name);
+       i_stream_set_name(conn->input, conn->conn.name);
+       o_stream_set_name(conn->output, conn->conn.name);
        o_stream_set_no_error_handling(conn->output, TRUE);
 
        if (ssl) {
-               if (client_connection_init_ssl(conn) < 0) {
-                       client_connection_destroy(&conn);
+               if (client_connection_tcp_init_ssl(conn) < 0) {
+                       client_connection_tcp_destroy(&conn);
                        return NULL;
                }
        }
-       client_connection_send_auth_handshake(conn, listen_fd);
-       client_connection_set_proctitle(conn, "");
+       client_connection_tcp_send_auth_handshake(conn, listen_fd);
+       client_connection_set_proctitle(&conn->conn, "");
+
+       return &conn->conn;
+}
 
-       return conn;
+static void
+client_connection_tcp_destroy(struct client_connection_tcp **_conn)
+{
+       struct client_connection_tcp *conn = *_conn;
+       struct client_connection *bconn = &conn->conn;
+
+       *_conn = NULL;
+       client_connection_destroy(&bconn);
 }
index 2c560227cd751cfe6680c6416d00994fa2ef9d7e..92a8cfbda333d33790eec80425932f74397a60a8 100644 (file)
@@ -59,14 +59,14 @@ static int client_connection_read_settings(struct client_connection *conn)
 }
 
 int client_connection_init(struct client_connection *conn,
-       enum client_connection_type type, int fd)
+       enum client_connection_type type, pool_t pool, int fd)
 {
        const char *ip;
 
        i_assert(type != CLIENT_CONNECTION_TYPE_CLI);
 
-       conn->fd = fd;
        conn->type = type;
+       conn->pool = pool;
 
        (void)net_getsockname(fd, &conn->local_ip, &conn->local_port);
        (void)net_getpeername(fd, &conn->remote_ip, &conn->remote_port);
@@ -75,20 +75,28 @@ int client_connection_init(struct client_connection *conn,
        if (ip[0] != '\0')
                i_set_failure_prefix("doveadm(%s): ", ip);
 
-       if (client_connection_read_settings(conn) < 0) {
-               client_connection_destroy(&conn);
-               return -1;
-       }
-       return 0;
+       conn->name = conn->remote_ip.family == 0 ? "<local>" :
+               p_strdup(pool, net_ip2addr(&conn->remote_ip));
+
+       return client_connection_read_settings(conn);
 }
 
-void client_connection_deinit(struct client_connection *conn ATTR_UNUSED)
+void client_connection_destroy(struct client_connection **_conn)
 {
+       struct client_connection *conn = *_conn;
+
+       *_conn = NULL;
+
+       if (conn->free != NULL)
+               conn->free(conn);
+
        doveadm_client = NULL;
        master_service_client_connection_destroyed(master_service);
 
        if (doveadm_verbose_proctitle)
                process_title_set("[idling]");
+       
+       pool_unref(&conn->pool);
 }
 
 void client_connection_set_proctitle(struct client_connection *conn,
@@ -106,4 +114,14 @@ void client_connection_set_proctitle(struct client_connection *conn,
        process_title_set(str);
 }
 
+void doveadm_server_init(void)
+{
+       doveadm_http_server_init();
+}
 
+void doveadm_server_deinit(void)
+{
+       if (doveadm_client != NULL)
+               client_connection_destroy(&doveadm_client);
+       doveadm_http_server_deinit();
+}
index b8eaa2db38a704ce20aafa5f42c200a953f424a1..b33b82e30472b47db23ace9b99b047ec2dd7fae6 100644 (file)
@@ -14,29 +14,19 @@ enum client_connection_type {
 struct client_connection {
        pool_t pool;
        enum client_connection_type type;
-
-       int fd;
        const char *name;
-       struct io *io;
-       struct istream *input;
-       struct ostream *output;
-       struct ostream *log_out;
-       struct ssl_iostream *ssl_iostream;
+
        struct ip_addr local_ip, remote_ip;
        in_port_t local_port, remote_port;
+
        const struct doveadm_settings *set;
 
-       bool handshaked:1;
-       bool authenticated:1;
-       bool http:1;
-       bool io_setup:1;
-       bool use_multiplex:1;
+       void (*free)(struct client_connection *conn);
 };
 
 struct client_connection *
 client_connection_tcp_create(int fd, int listen_fd, bool ssl);
 struct client_connection *
 client_connection_http_create(int fd, bool ssl);
-void client_connection_destroy(struct client_connection **conn);
 
 #endif
index 742d5b096880693336614b9dbac9986adcba7c30..a6daa0915d11be52e907a2c133d543a727b37c49 100644 (file)
@@ -79,26 +79,24 @@ static void main_init(void)
        if (doveadm_verbose_proctitle)
                process_title_set("[idling]");
 
-       doveadm_http_server_init();
        doveadm_cmds_init();
        doveadm_register_auth_server_commands();
        doveadm_dump_init();
        doveadm_mail_init();
+       doveadm_server_init();
        dict_drivers_register_builtin();
        doveadm_load_modules();
 }
 
 static void main_deinit(void)
 {
-       if (doveadm_client != NULL)
-               client_connection_destroy(&doveadm_client);
+       doveadm_server_deinit();
        doveadm_mail_deinit();
        doveadm_dump_deinit();
        doveadm_unload_modules();
        dict_drivers_unregister_builtin();
        doveadm_print_deinit();
        doveadm_cmds_deinit();
-       doveadm_http_server_deinit();
        pool_unref(&doveadm_settings_pool);
 }