]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
doveadm: server-connection - Move reply printing to caller
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 29 Jul 2021 16:21:01 +0000 (19:21 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Mon, 17 Jan 2022 11:52:09 +0000 (13:52 +0200)
src/doveadm/doveadm-mail-server.c
src/doveadm/server-connection.c
src/doveadm/server-connection.h

index 348912de0faf2ff31a8986e85d9f4464db20a356..ecfcb96d647a85f657efbcd9d84e8cb7394174d6 100644 (file)
@@ -41,6 +41,7 @@ struct doveadm_mail_server_cmd {
 
        char *cmdline;
        struct istream *input;
+       bool streaming;
 };
 
 static HASH_TABLE(char *, struct doveadm_server *) servers;
@@ -395,6 +396,29 @@ static int doveadm_cmd_redirect(struct doveadm_mail_server_cmd *servercmd,
        return 0;
 }
 
+static void
+doveadm_cmd_print_callback(const unsigned char *data,
+                          size_t size, bool finished,
+                          struct doveadm_mail_server_cmd *servercmd)
+{
+       string_t *str = t_str_new(size);
+       if (!finished) {
+               servercmd->streaming = TRUE;
+               str_append_tabunescaped(str, data, size);
+               doveadm_print_stream(str->data, str->used);
+       } else if (servercmd->streaming) {
+               servercmd->streaming = FALSE;
+               if (size > 0) {
+                       str_append_tabunescaped(str, data, size);
+                       doveadm_print_stream(str->data, str->used);
+               }
+               doveadm_print_stream("", 0);
+       } else {
+               str_append_tabunescaped(str, data, size);
+               doveadm_print(str_c(str));
+       }
+}
+
 static void doveadm_cmd_callback(const struct doveadm_server_reply *reply,
                                 void *context)
 {
@@ -479,6 +503,8 @@ static void doveadm_mail_server_handle(struct doveadm_server *server,
        servercmd->input = cmd_ctx->cmd_input;
        if (servercmd->input != NULL)
                i_stream_ref(servercmd->input);
+       server_connection_set_print(conn, doveadm_cmd_print_callback,
+                                   servercmd);
        server_connection_cmd(conn, cmd_ctx->proxy_ttl,
                              str_c(cmd), cmd_ctx->cmd_input,
                              doveadm_cmd_callback, servercmd);
index 2b7b763dea423fb79d92819445895dc86ba21f2f..db894481ac8edf9176bf03b2f0a0dc6bca80ed89 100644 (file)
@@ -9,11 +9,9 @@
 #include "ostream.h"
 #include "ostream-dot.h"
 #include "str.h"
-#include "strescape.h"
 #include "iostream-ssl.h"
 #include "master-service.h"
 #include "doveadm.h"
-#include "doveadm-print.h"
 #include "doveadm-util.h"
 #include "doveadm-server.h"
 #include "server-connection.h"
@@ -49,11 +47,13 @@ struct server_connection {
        server_cmd_callback_t *callback;
        void *context;
 
+       server_connection_print_t *print_callback;
+       void *print_context;
+
        enum server_reply_state state;
 
        bool authenticate_sent:1;
        bool authenticated:1;
-       bool streaming:1;
        bool ssl_done:1;
 };
 
@@ -158,33 +158,10 @@ server_connection_callback(struct server_connection *conn,
        callback(reply, conn->context);
 }
 
-static void stream_data(string_t *str, const unsigned char *data, size_t size)
-{
-       str_truncate(str, 0);
-       str_append_tabunescaped(str, data, size);
-       doveadm_print_stream(str->data, str->used);
-}
-
-static void server_flush_field(struct server_connection *conn, string_t *str,
-                              const unsigned char *data, size_t size)
-{
-       if (conn->streaming) {
-               conn->streaming = FALSE;
-               if (size > 0)
-                       stream_data(str, data, size);
-               doveadm_print_stream("", 0);
-       } else {
-               str_truncate(str, 0);
-               str_append_tabunescaped(str, data, size);
-               doveadm_print(str_c(str));
-       }
-}
-
 static void
 server_handle_input(struct server_connection *conn,
                    const unsigned char *data, size_t size)
 {
-       string_t *str;
        size_t i, start;
 
        if (printing_conn == conn) {
@@ -204,7 +181,6 @@ server_handle_input(struct server_connection *conn,
                size--;
        }
 
-       str = t_str_new(128);
        for (i = start = 0; i < size; i++) {
                if (data[i] == '\n') {
                        if (i != start) {
@@ -220,14 +196,17 @@ server_handle_input(struct server_connection *conn,
                        return;
                }
                if (data[i] == '\t') {
-                       server_flush_field(conn, str, data + start, i - start);
+                       if (conn->print_callback != NULL) T_BEGIN {
+                               conn->print_callback(data + start, i - start,
+                                                    TRUE, conn->print_context);
+                       } T_END;
                        start = i + 1;
                }
        }
-       if (start != size) {
-               conn->streaming = TRUE;
-               stream_data(str, data + start, size - start);
-       }
+       if (start != size && conn->print_callback != NULL) T_BEGIN {
+               conn->print_callback(data + start, size - start, FALSE,
+                                    conn->print_context);
+       } T_END;
        i_stream_skip(conn->conn.input, size);
 }
 
@@ -665,6 +644,15 @@ int server_connection_create(struct doveadm_server *server,
        return 0;
 }
 
+#undef server_connection_set_print
+void server_connection_set_print(struct server_connection *conn,
+                                server_connection_print_t *callback,
+                                void *context)
+{
+       conn->print_callback = callback;
+       conn->print_context = context;
+}
+
 static void server_connection_destroy(struct server_connection **_conn)
 {
        struct server_connection *conn = *_conn;
index c6028eac3c635c96d5f2cd304e1f94b0f168ddb7..993a56a4faa6d0e1ac86e4922df9e7eb68e6a5d5 100644 (file)
@@ -15,6 +15,12 @@ struct doveadm_server_reply {
 typedef void server_cmd_callback_t(const struct doveadm_server_reply *reply,
                                   void *context);
 
+/* Called when a field needs to be printed. If finished=FALSE, the next
+   call will continue printing this same field. */
+typedef void server_connection_print_t(const unsigned char *data,
+                                      size_t size, bool finished,
+                                      void *context);
+
 int server_connection_create(struct doveadm_server *server,
                             struct server_connection **conn_r,
                             const char **error_r);
@@ -22,6 +28,15 @@ int server_connection_create(struct doveadm_server *server,
 void server_connection_get_dest(struct server_connection *conn,
                                struct ip_addr *ip_r, in_port_t *port_r);
 
+void server_connection_set_print(struct server_connection *conn,
+                                server_connection_print_t *callback,
+                                void *context);
+#define server_connection_set_print(conn, callback, context) \
+       server_connection_set_print(conn, \
+               (server_connection_print_t *)callback, \
+               TRUE ? context : CALLBACK_TYPECHECK(callback, \
+                       void (*)(const unsigned char *, size_t, bool, typeof(context))))
+
 void server_connection_cmd(struct server_connection *conn, int proxy_ttl,
                           const char *line, struct istream *cmd_input,
                           server_cmd_callback_t *callback, void *context);