From: Stephan Bosch Date: Sat, 7 Oct 2017 11:39:44 +0000 (+0200) Subject: doveadm-server: Restructured client-connection code so that TCP and HTTP connection... X-Git-Tag: 2.3.0.rc1~750 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=80a225c0b1f4bf322a562cc7c21d5891fb6895ee;p=thirdparty%2Fdovecot%2Fcore.git doveadm-server: Restructured client-connection code so that TCP and HTTP connection types are properly separated. --- diff --git a/src/doveadm/client-connection-http.c b/src/doveadm/client-connection-http.c index aac00c3c91..67c4c8a9f4 100644 --- a/src/doveadm/client-connection-http.c +++ b/src/doveadm/client-connection-http.c @@ -34,12 +34,17 @@ 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); } diff --git a/src/doveadm/client-connection-private.h b/src/doveadm/client-connection-private.h index 4effdf806d..5b6b698ce5 100644 --- a/src/doveadm/client-connection-private.h +++ b/src/doveadm/client-connection-private.h @@ -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 diff --git a/src/doveadm/client-connection-tcp.c b/src/doveadm/client-connection-tcp.c index b045fca68c..3fcbcf439e 100644 --- a/src/doveadm/client-connection-tcp.c +++ b/src/doveadm/client-connection-tcp.c @@ -14,16 +14,35 @@ #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 #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 ? "" : - 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); } diff --git a/src/doveadm/client-connection.c b/src/doveadm/client-connection.c index 2c560227cd..92a8cfbda3 100644 --- a/src/doveadm/client-connection.c +++ b/src/doveadm/client-connection.c @@ -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 ? "" : + 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(); +} diff --git a/src/doveadm/client-connection.h b/src/doveadm/client-connection.h index b8eaa2db38..b33b82e304 100644 --- a/src/doveadm/client-connection.h +++ b/src/doveadm/client-connection.h @@ -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 diff --git a/src/doveadm/main.c b/src/doveadm/main.c index 742d5b0968..a6daa0915d 100644 --- a/src/doveadm/main.c +++ b/src/doveadm/main.c @@ -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); }