From: Aki Tuomi Date: Thu, 24 Aug 2017 11:45:22 +0000 (+0300) Subject: doveadm: Refactor server/client code to support versioning properly X-Git-Tag: 2.3.0.rc1~907 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce700412721a0526fd69a93d99013d19487e4029;p=thirdparty%2Fdovecot%2Fcore.git doveadm: Refactor server/client code to support versioning properly This way we can distinguish between old and new server side --- diff --git a/src/doveadm/client-connection.c b/src/doveadm/client-connection.c index 0692bed268..187695a78e 100644 --- a/src/doveadm/client-connection.c +++ b/src/doveadm/client-connection.c @@ -388,6 +388,7 @@ static void client_connection_input(struct client_connection *conn) const char *line; bool ok = TRUE; int ret; + unsigned int minor; if (!conn->handshaked) { if ((line = i_stream_read_next_line(conn->input)) == NULL) { @@ -397,14 +398,19 @@ static void client_connection_input(struct client_connection *conn) } return; } - - if (!version_string_verify(line, "doveadm-server", - DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR)) { + if (!version_string_verify_full(line, "doveadm-server", + DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR, &minor)) { i_error("doveadm client not compatible with this server " "(mixed old and new binaries?)"); client_connection_destroy(&conn); return; } + if (minor > 0) { + /* send version reply */ + o_stream_nsend_str(conn->output, + DOVEADM_CLIENT_PROTOCOL_VERSION_LINE"\n"); + conn->use_multiplex = TRUE; + } conn->handshaked = TRUE; } if (!conn->authenticated) { @@ -417,6 +423,7 @@ static void client_connection_input(struct client_connection *conn) } o_stream_nsend(conn->output, "+\n", 2); conn->authenticated = TRUE; + doveadm_print_ostream = conn->output; } if (!conn->io_setup) { @@ -554,7 +561,6 @@ client_connection_create(int fd, int listen_fd, bool ssl) client_connection_send_auth_handshake(conn, listen_fd); client_connection_set_proctitle(conn, ""); - doveadm_print_ostream = conn->output; return conn; } diff --git a/src/doveadm/doveadm-util.h b/src/doveadm/doveadm-util.h index 54fdf60d7c..62a5630f0b 100644 --- a/src/doveadm/doveadm-util.h +++ b/src/doveadm/doveadm-util.h @@ -6,6 +6,7 @@ #define DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR 1 #define DOVEADM_SERVER_PROTOCOL_VERSION_MINOR 0 #define DOVEADM_SERVER_PROTOCOL_VERSION_LINE "VERSION\tdoveadm-server\t1\t0" +#define DOVEADM_CLIENT_PROTOCOL_VERSION_LINE "VERSION\tdoveadm-client\t1\t0" extern bool doveadm_verbose, doveadm_debug, doveadm_server; diff --git a/src/doveadm/server-connection.c b/src/doveadm/server-connection.c index a0a6de7408..ab76e8dcbc 100644 --- a/src/doveadm/server-connection.c +++ b/src/doveadm/server-connection.c @@ -39,6 +39,8 @@ struct server_connection { struct doveadm_settings *set; int fd; + unsigned int minor; + struct io *io; struct istream *input; struct ostream *output; @@ -309,6 +311,16 @@ static void server_connection_input(struct server_connection *conn) if (!conn->handshaked || !conn->authenticated) { while((line = i_stream_read_next_line(conn->input)) != NULL) { + if (strncmp(line, "VERSION\t", 8) == 0) { + if (!version_string_verify_full(line, "doveadm-client", + DOVEADM_SERVER_PROTOCOL_VERSION_MAJOR, + &conn->minor)) { + i_error("doveadm server not compatible with this client" + "(mixed old and new binaries?)"); + server_connection_destroy(&conn); + } + continue; + } if (strcmp(line, "+") == 0) { server_connection_authenticated(conn); break; @@ -481,7 +493,6 @@ static int server_connection_init_ssl(struct server_connection *conn) int server_connection_create(struct doveadm_server *server, struct server_connection **conn_r) { -#define DOVEADM_SERVER_HANDSHAKE "VERSION\tdoveadm-server\t1\t0\n" struct server_connection *conn; pool_t pool; @@ -492,8 +503,8 @@ int server_connection_create(struct doveadm_server *server, conn->fd = doveadm_connect_with_default_port(server->name, doveadm_settings->doveadm_port); net_set_nonblock(conn->fd, TRUE); - conn->io = io_add(conn->fd, IO_READ, server_connection_input, conn); conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE); + conn->io = io_add_istream(conn->input, server_connection_input, conn); conn->output = o_stream_create_fd(conn->fd, (size_t)-1); o_stream_set_flush_callback(conn->output, server_connection_output, conn); @@ -510,7 +521,7 @@ int server_connection_create(struct doveadm_server *server, o_stream_set_no_error_handling(conn->output, TRUE); conn->state = SERVER_REPLY_STATE_DONE; - o_stream_nsend_str(conn->output, DOVEADM_SERVER_HANDSHAKE); + o_stream_nsend_str(conn->output, DOVEADM_SERVER_PROTOCOL_VERSION_LINE"\n"); *conn_r = conn; return 0;