From: Timo Sirainen Date: Tue, 25 Jan 2022 17:16:32 +0000 (+0100) Subject: doveadm: Add doveadm_blocking_connect() X-Git-Tag: 2.4.0~4441 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a58e9a7bc4bc86922e420ab0ea30e22cafec4dd9;p=thirdparty%2Fdovecot%2Fcore.git doveadm: Add doveadm_blocking_connect() This makes it easier for doveadm to connect to various connection API compatible sockets. --- diff --git a/src/doveadm/doveadm-util.c b/src/doveadm/doveadm-util.c index 8d1ba418f5..5a10692312 100644 --- a/src/doveadm/doveadm-util.c +++ b/src/doveadm/doveadm-util.c @@ -2,6 +2,9 @@ #include "lib.h" #include "array.h" +#include "connection.h" +#include "istream.h" +#include "ostream.h" #include "net.h" #include "time-util.h" #include "master-service.h" @@ -153,6 +156,57 @@ int doveadm_connect(const char *path) return doveadm_connect_with_default_port(path, 0); } +int doveadm_blocking_connect(const char *path, + const struct connection_settings *set, + struct istream **input_r, + struct ostream **output_r, const char **error_r) +{ + const char *line; + int ret = 0; + + int fd = net_connect_unix(path); + if (fd == -1) { + *error_r = t_strdup_printf( + "net_connect_unix(%s) failed: %m", path); + return -1; + } + net_set_nonblock(fd, FALSE); + *output_r = o_stream_create_fd_blocking(fd); + o_stream_set_name(*output_r, path); + + if (!set->dont_send_version && set->service_name_out != NULL && + set->major_version != 0) { + const char *str = t_strdup_printf("VERSION\t%s\t%u\t%u\n", + set->service_name_out, + set->major_version, set->minor_version); + o_stream_nsend_str(*output_r, str); + } + + *input_r = i_stream_create_fd_autoclose(&fd, SIZE_MAX); + i_stream_set_name(*input_r, path); + if (set->service_name_in != NULL) { + alarm(DOVEADM_HANDSHAKE_TIMEOUT_SECS); + if ((line = i_stream_read_next_line(*input_r)) == NULL) { + *error_r = t_strdup_printf("read(%s) failed: %s", + path, i_stream_get_error(*input_r)); + ret = -1; + } else if (!version_string_verify(line, set->service_name_in, + set->major_version)) { + *error_r = t_strdup_printf( + "%s is not a compatible socket " + "(wanted %s v%u, received: %s)", path, + set->service_name_in, set->major_version, line); + ret = -1; + } + alarm(0); + } + if (ret < 0) { + o_stream_destroy(output_r); + i_stream_destroy(input_r); + } + return ret; +} + int i_strccdascmp(const char *a, const char *b) { while(*a != '\0' && *b != '\0') { diff --git a/src/doveadm/doveadm-util.h b/src/doveadm/doveadm-util.h index bfb882f98a..3bd6a35da0 100644 --- a/src/doveadm/doveadm-util.h +++ b/src/doveadm/doveadm-util.h @@ -3,6 +3,8 @@ #include "net.h" +struct connection_settings; + extern bool doveadm_verbose, doveadm_debug, doveadm_server; const char *unixdate2str(time_t timestamp); @@ -12,6 +14,12 @@ int doveadm_tcp_connect(const char *target, in_port_t default_port); int doveadm_connect_with_default_port(const char *path, in_port_t default_port); +/* Connect to a connection API compatible UNIX socket. */ +int doveadm_blocking_connect(const char *path, + const struct connection_settings *set, + struct istream **input_r, + struct ostream **output_r, const char **error_r); + void doveadm_load_modules(void); void doveadm_unload_modules(void); bool doveadm_has_unloaded_plugin(const char *name); diff --git a/src/doveadm/test-doveadm-util.c b/src/doveadm/test-doveadm-util.c index aec1b39ae1..8756f8ad5d 100644 --- a/src/doveadm/test-doveadm-util.c +++ b/src/doveadm/test-doveadm-util.c @@ -2,11 +2,19 @@ #include "lib.h" #include "test-common.h" +#include "master-service.h" #include "doveadm-settings.h" #include "doveadm-util.h" struct doveadm_settings *doveadm_settings; /* just to avoid linker error */ +bool version_string_verify(const char *line ATTR_UNUSED, + const char *service_name ATTR_UNUSED, + unsigned major_version ATTR_UNUSED) +{ + return FALSE; +} + static void test_i_strccdascmp(void) { test_begin("i_strccdascmp()"); diff --git a/src/lib-doveadm/doveadm-protocol.h b/src/lib-doveadm/doveadm-protocol.h index 4f2760bd60..978dacaac5 100644 --- a/src/lib-doveadm/doveadm-protocol.h +++ b/src/lib-doveadm/doveadm-protocol.h @@ -6,6 +6,7 @@ #define DOVEADM_SERVER_PROTOCOL_VERSION_LINE "VERSION\tdoveadm-server\t1\t3" #define DOVEADM_CLIENT_PROTOCOL_VERSION_LINE "VERSION\tdoveadm-client\t1\t3" #define DOVEADM_TCP_CONNECT_TIMEOUT_SECS 30 +#define DOVEADM_HANDSHAKE_TIMEOUT_SECS 5 #define DOVEADM_PROTOCOL_MIN_VERSION_MULTIPLEX 1 #define DOVEADM_PROTOCOL_MIN_VERSION_STARTTLS 2