From: Timo Sirainen Date: Thu, 29 Jul 2021 12:07:21 +0000 (+0300) Subject: doveadm: server-connection - Convert to connection API X-Git-Tag: 2.4.0~4775 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b4d747777db78dce07bd638a3630fa0a24653588;p=thirdparty%2Fdovecot%2Fcore.git doveadm: server-connection - Convert to connection API --- diff --git a/src/doveadm/doveadm-dsync.c b/src/doveadm/doveadm-dsync.c index 1078a59980..1155347461 100644 --- a/src/doveadm/doveadm-dsync.c +++ b/src/doveadm/doveadm-dsync.c @@ -5,6 +5,7 @@ #include "array.h" #include "execv-const.h" #include "child-wait.h" +#include "connection.h" #include "istream.h" #include "ostream.h" #include "iostream-ssl.h" @@ -918,7 +919,6 @@ dsync_connect_tcp(struct dsync_cmd_context *ctx, ctx->ctx.set->doveadm_username); server->password = p_strdup(ctx->ctx.pool, ctx->ctx.set->doveadm_password); - p_array_init(&server->connections, ctx->ctx.pool, 1); p_array_init(&server->queue, ctx->ctx.pool, 1); prev_ioloop = current_ioloop; @@ -941,8 +941,7 @@ dsync_connect_tcp(struct dsync_cmd_context *ctx, dsync_server_run_command(ctx, conn); } - if (array_count(&server->connections) > 0) - server_connection_destroy(&conn); + connection_list_deinit(&server->connections); dsync_cmd_switch_ioloop_to(ctx, prev_ioloop); io_loop_destroy(&ioloop); diff --git a/src/doveadm/doveadm-mail-server.c b/src/doveadm/doveadm-mail-server.c index 8c535afc37..348912de0f 100644 --- a/src/doveadm/doveadm-mail-server.c +++ b/src/doveadm/doveadm-mail-server.c @@ -5,6 +5,7 @@ #include "hash.h" #include "str.h" #include "strescape.h" +#include "connection.h" #include "ioloop.h" #include "istream.h" #include "master-service.h" @@ -75,8 +76,6 @@ static struct doveadm_server *doveadm_server_get(const char *name) server->hostname = p == NULL ? server->name : p_strdup_until(server_pool, server->name, p); - p_array_init(&server->connections, server_pool, - doveadm_settings->doveadm_worker_count); p_array_init(&server->queue, server_pool, DOVEADM_SERVER_QUEUE_MAX); hash_table_insert(servers, dup_name, server); @@ -86,7 +85,8 @@ static struct doveadm_server *doveadm_server_get(const char *name) static bool doveadm_server_have_used_connections(struct doveadm_server *server) { - return array_count(&server->connections) > 0; + return server->connections != NULL && + server->connections->connections != NULL; } static void doveadm_mail_server_cmd_free(struct doveadm_mail_server_cmd **_cmd) @@ -620,8 +620,9 @@ int doveadm_mail_server_user(struct doveadm_mail_cmd_context *ctx, server->ip = proxy_set.host_ip; server->ssl_flags = proxy_set.ssl_flags; server->port = proxy_set.port; - if (array_count(&server->connections) < - I_MAX(ctx->set->doveadm_worker_count, 1)) { + if (server->connections == NULL || + server->connections->connections_count < + I_MAX(ctx->set->doveadm_worker_count, 1)) { if (server_connection_create(server, &conn, error_r) < 0) { internal_failure = TRUE; return -1; @@ -666,13 +667,7 @@ static void doveadm_servers_destroy_all_connections(void) iter = hash_table_iterate_init(servers); while (hash_table_iterate(iter, servers, &key, &server)) { - while (array_count(&server->connections) > 0) { - struct server_connection *const *connp, *conn; - - connp = array_front(&server->connections); - conn = *connp; - server_connection_destroy(&conn); - } + connection_list_deinit(&server->connections); ssl_iostream_context_unref(&server->ssl_ctx); } hash_table_iterate_deinit(&iter); diff --git a/src/doveadm/doveadm-server.h b/src/doveadm/doveadm-server.h index f22603c1d1..8aa4d8146f 100644 --- a/src/doveadm/doveadm-server.h +++ b/src/doveadm/doveadm-server.h @@ -22,7 +22,7 @@ struct doveadm_server { enum auth_proxy_ssl_flags ssl_flags; struct ssl_iostream_context *ssl_ctx; - ARRAY(struct server_connection *) connections; + struct connection_list *connections; ARRAY_TYPE(string) queue; }; diff --git a/src/doveadm/server-connection.c b/src/doveadm/server-connection.c index afdb632e6b..0c8a709984 100644 --- a/src/doveadm/server-connection.c +++ b/src/doveadm/server-connection.c @@ -4,8 +4,6 @@ #include "array.h" #include "base64.h" #include "connection.h" -#include "ioloop.h" -#include "net.h" #include "istream.h" #include "istream-multiplex.h" #include "ostream.h" @@ -14,16 +12,12 @@ #include "strescape.h" #include "iostream-ssl.h" #include "master-service.h" -#include "master-service-settings.h" -#include "settings-parser.h" #include "doveadm.h" #include "doveadm-print.h" #include "doveadm-util.h" #include "doveadm-server.h" #include "server-connection.h" -#include - #define DOVEADM_LOG_CHANNEL_ID 'L' #define MAX_INBUF_SIZE (1024*32) @@ -65,10 +59,10 @@ struct server_connection { static struct server_connection *printing_conn = NULL; static ARRAY(struct doveadm_server *) print_pending_servers = ARRAY_INIT; -static void server_connection_input(struct server_connection *conn); static bool server_connection_input_one(struct server_connection *conn); static int server_connection_init_ssl(struct server_connection *conn, const char **error_r); +static void server_connection_destroy(struct server_connection **_conn); static void server_set_print_pending(struct doveadm_server *server) { @@ -85,18 +79,11 @@ static void server_set_print_pending(struct doveadm_server *server) static void server_print_connection_released(struct doveadm_server *server) { - struct server_connection *const *conns; - unsigned int i, count; - - conns = array_get(&server->connections, &count); - for (i = 0; i < count; i++) { - if (conns[i]->conn.io != NULL) - continue; + struct connection *conn; - conns[i]->conn.io = io_add(conns[i]->conn.fd_in, IO_READ, - server_connection_input, conns[i]); - io_set_pending(conns[i]->conn.io); - } + conn = server->connections->connections; + for (; conn != NULL; conn = conn->next) + connection_input_resume(conn); } static void print_connection_released(void) @@ -335,10 +322,8 @@ static void server_log_disconnect_error(struct server_connection *conn) error = conn->ssl_iostream == NULL ? NULL : ssl_iostream_get_last_error(conn->ssl_iostream); - if (error == NULL) { - error = conn->conn.input->stream_errno == 0 ? "EOF" : - strerror(conn->conn.input->stream_errno); - } + if (error == NULL) + error = connection_disconnect_reason(&conn->conn); i_error("doveadm server disconnected before handshake: %s", error); } @@ -365,17 +350,20 @@ static void server_connection_start_multiplex(struct server_connection *conn) struct istream *is = conn->conn.input; conn->conn.input = i_stream_create_multiplex(is, MAX_INBUF_SIZE); i_stream_unref(&is); - io_remove(&conn->conn.io); - conn->conn.io = io_add_istream(conn->conn.input, - server_connection_input, conn); + conn->log_input = i_stream_multiplex_add_channel(conn->conn.input, DOVEADM_LOG_CHANNEL_ID); conn->io_log = io_add_istream(conn->log_input, server_connection_print_log, conn); i_stream_set_return_partial_line(conn->log_input, TRUE); + + /* recreate IO using multiplex istream */ + connection_streams_changed(&conn->conn); } -static void server_connection_input(struct server_connection *conn) +static void server_connection_input(struct connection *_conn) { + struct server_connection *conn = + container_of(_conn, struct server_connection, conn); const char *line; const char *error; @@ -422,7 +410,7 @@ static void server_connection_input(struct server_connection *conn) } if (!conn->ssl_done && (conn->server->ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) != 0) { - io_remove(&conn->conn.io); + connection_input_halt(&conn->conn); if (conn->conn.minor_version < DOVEADM_PROTO_MINOR_MIN_STARTTLS) { i_error("doveadm STARTTLS failed: Server does not support it"); server_connection_destroy(&conn); @@ -436,8 +424,7 @@ static void server_connection_input(struct server_connection *conn) return; } conn->ssl_done = TRUE; - conn->conn.io = io_add_istream(conn->conn.input, - server_connection_input, conn); + connection_input_resume(&conn->conn); } if (server_connection_authenticate(conn) < 0) { server_connection_destroy(&conn); @@ -555,6 +542,7 @@ static int server_connection_init_ssl(struct server_connection *conn, return -1; } + connection_input_halt(&conn->conn); if (io_stream_create_ssl_client(conn->server->ssl_ctx, conn->server->hostname, &ssl_set, &conn->conn.input, &conn->conn.output, @@ -569,9 +557,35 @@ static int server_connection_init_ssl(struct server_connection *conn, ssl_iostream_get_last_error(conn->ssl_iostream)); return -1; } + connection_input_resume(&conn->conn); return 0; } +static void server_connection_destroy_conn(struct connection *_conn) +{ + struct server_connection *conn = + container_of(_conn, struct server_connection, conn); + server_connection_destroy(&conn); +} + +static const struct connection_vfuncs doveadm_client_vfuncs = { + .input = server_connection_input, + .destroy = server_connection_destroy_conn, +}; + +static struct connection_settings doveadm_client_set = { + /* Note: These service names are reversed compared to how they usually + work. Too late to change now without breaking the protocol. */ + .service_name_in = "doveadm-client", + .service_name_out = "doveadm-server", + .major_version = DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR, + .minor_version = DOVEADM_SERVER_PROTOCOL_VERSION_MINOR, + .dont_send_version = TRUE, /* doesn't work with SSL */ + .input_max_size = MAX_INBUF_SIZE, + .output_max_size = SIZE_MAX, + .client = TRUE, +}; + int server_connection_create(struct doveadm_server *server, struct server_connection **conn_r, const char **error_r) @@ -583,6 +597,12 @@ int server_connection_create(struct doveadm_server *server, i_assert(server->username != NULL); i_assert(server->password != NULL); + if (server->connections == NULL) { + server->connections = + connection_list_init(&doveadm_client_set, + &doveadm_client_vfuncs); + } + pool = pool_alloconly_create("doveadm server connection", 1024*16); conn = p_new(pool, struct server_connection, 1); conn->pool = pool; @@ -592,29 +612,20 @@ int server_connection_create(struct doveadm_server *server, } else { target = server->name; } - conn->conn.fd_in = doveadm_connect_with_default_port(target, - doveadm_settings->doveadm_port); - conn->conn.fd_out = conn->conn.fd_out; + int fd = doveadm_connect_with_default_port(target, + doveadm_settings->doveadm_port); + net_set_nonblock(fd, TRUE); + connection_init_client_fd(server->connections, &conn->conn, + server->hostname, fd, fd); - net_set_nonblock(conn->conn.fd_in, TRUE); - conn->conn.input = i_stream_create_fd(conn->conn.fd_in, MAX_INBUF_SIZE); - conn->conn.output = o_stream_create_fd(conn->conn.fd_in, SIZE_MAX); o_stream_set_flush_callback(conn->conn.output, server_connection_output, conn); - o_stream_set_no_error_handling(conn->conn.output, TRUE); - - i_stream_set_name(conn->conn.input, server->name); - o_stream_set_name(conn->conn.output, server->name); - - array_push_back(&conn->server->connections, &conn); if (((server->ssl_flags & AUTH_PROXY_SSL_FLAG_STARTTLS) == 0 && server_connection_init_ssl(conn, error_r) < 0)) { server_connection_destroy(&conn); return -1; } - conn->conn.io = io_add_istream(conn->conn.input, - server_connection_input, conn); conn->state = SERVER_REPLY_STATE_DONE; o_stream_nsend_str(conn->conn.output, @@ -624,30 +635,18 @@ int server_connection_create(struct doveadm_server *server, return 0; } -void server_connection_destroy(struct server_connection **_conn) +static void server_connection_destroy(struct server_connection **_conn) { struct server_connection *conn = *_conn; - struct server_connection *const *conns; const char *error; - unsigned int i, count; *_conn = NULL; - conns = array_get(&conn->server->connections, &count); - for (i = 0; i < count; i++) { - if (conns[i] == conn) { - array_delete(&conn->server->connections, i, 1); - break; - } - } - if (conn->callback != NULL) { error = conn->ssl_iostream == NULL ? NULL : ssl_iostream_get_last_error(conn->ssl_iostream); - if (error == NULL) { - error = conn->conn.input->stream_errno == 0 ? "EOF" : - strerror(conn->conn.input->stream_errno); - } + if (error == NULL) + error = connection_disconnect_reason(&conn->conn); struct doveadm_server_reply reply = { .exit_code = SERVER_EXIT_CODE_DISCONNECTED, .error = error, @@ -657,19 +656,19 @@ void server_connection_destroy(struct server_connection **_conn) if (printing_conn == conn) print_connection_released(); - i_stream_destroy(&conn->conn.input); - o_stream_destroy(&conn->conn.output); - i_stream_unref(&conn->cmd_input); /* close cmd_output after its parent, so the "." isn't sent */ + o_stream_close(conn->conn.output); o_stream_destroy(&conn->cmd_output); + + i_stream_unref(&conn->cmd_input); ssl_iostream_destroy(&conn->ssl_iostream); io_remove(&conn->io_log); - /* make sure all logs got consumed */ + /* make sure all logs got consumed before closing the fd */ if (conn->log_input != NULL) server_connection_print_log(conn); i_stream_unref(&conn->log_input); - io_remove(&conn->conn.io); - i_close_fd(&conn->conn.fd_in); + + connection_deinit(&conn->conn); pool_unref(&conn->pool); } diff --git a/src/doveadm/server-connection.h b/src/doveadm/server-connection.h index b119256da2..c6028eac3c 100644 --- a/src/doveadm/server-connection.h +++ b/src/doveadm/server-connection.h @@ -18,7 +18,6 @@ typedef void server_cmd_callback_t(const struct doveadm_server_reply *reply, int server_connection_create(struct doveadm_server *server, struct server_connection **conn_r, const char **error_r); -void server_connection_destroy(struct server_connection **conn); void server_connection_get_dest(struct server_connection *conn, struct ip_addr *ip_r, in_port_t *port_r);