]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: Add doveadm_blocking_connect()
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 25 Jan 2022 17:16:32 +0000 (18:16 +0100)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Sun, 13 Feb 2022 10:23:26 +0000 (10:23 +0000)
This makes it easier for doveadm to connect to various connection API
compatible sockets.

src/doveadm/doveadm-util.c
src/doveadm/doveadm-util.h
src/doveadm/test-doveadm-util.c
src/lib-doveadm/doveadm-protocol.h

index 8d1ba418f5a3f38f741d1fd6f315744eaf4bda2c..5a1069231261ede393c5206e6f7ae63bb354497d 100644 (file)
@@ -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') {
index bfb882f98aad8b01f877e4153249dddf336a6aa5..3bd6a35da0bd72dc50d328472007614fe63effcb 100644 (file)
@@ -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);
index aec1b39ae192e4ae33641f8d17cc5e729bbdea6e..8756f8ad5dc89dfa1e051cd4c94116656bc040e9 100644 (file)
@@ -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()");
index 4f2760bd6031cc46602399932aefa1716a7e10d3..978dacaac506c1da9683acdf22b74434a2179bf6 100644 (file)
@@ -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