]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
submission: Record backend used for each recipient.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 15 Sep 2018 16:04:33 +0000 (18:04 +0200)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 12 Feb 2019 13:40:41 +0000 (15:40 +0200)
This is a preparation for plugins overriding the default backend for a recipient.

src/submission/submission-backend.c
src/submission/submission-backend.h
src/submission/submission-client.c
src/submission/submission-client.h
src/submission/submission-commands.c
src/submission/submission-recipient.c
src/submission/submission-recipient.h

index d21b4d1ff038d499a16dc4da13d9649fd33e0206..c92e15724f5fe55b6e3e1519c547596410da5c9c 100644 (file)
@@ -2,6 +2,8 @@
 
 #include "submission-common.h"
 #include "llist.h"
+#include "istream.h"
+#include "istream-sized.h"
 
 #include "submission-client.h"
 #include "submission-commands.h"
@@ -22,6 +24,8 @@ static void submission_backend_destroy(struct submission_backend *backend)
 {
        struct client *client = backend->client;
 
+       i_stream_unref(&backend->data_input);
+
        DLLIST_REMOVE(&client->backends, backend);
        backend->v.destroy(backend);
 }
@@ -30,6 +34,7 @@ void submission_backends_destroy_all(struct client *client)
 {
        while (client->backends != NULL)
                submission_backend_destroy(client->backends);
+       array_clear(&client->rcpt_backends);
        client->state.backend = NULL;
 }
 
@@ -84,6 +89,22 @@ uoff_t submission_backend_get_max_mail_size(struct submission_backend *backend)
        return UOFF_T_MAX;
 }
 
+void submission_backends_trans_free(struct client *client)
+{
+       struct submission_backend *const *bkp;
+
+       i_assert(client->state.backend != NULL ||
+                array_count(&client->rcpt_backends) == 0);
+
+       array_foreach(&client->rcpt_backends, bkp) {
+               struct submission_backend *backend = *bkp;
+
+               i_stream_unref(&backend->data_input);
+       }
+       array_clear(&client->rcpt_backends);
+       client->state.backend = NULL;
+}
+
 int submission_backend_cmd_helo(struct submission_backend *backend,
                                struct smtp_server_cmd_ctx *cmd,
                                struct smtp_server_cmd_helo *data)
@@ -140,12 +161,46 @@ int submission_backend_cmd_rset(struct submission_backend *backend,
        return backend->v.cmd_rset(backend, cmd);
 }
 
-int submission_backend_cmd_data(struct submission_backend *backend,
-                               struct smtp_server_cmd_ctx *cmd,
-                               struct smtp_server_transaction *trans,
-                               struct istream *data_input, uoff_t data_size)
+static int
+submission_backend_cmd_data(struct submission_backend *backend,
+                           struct smtp_server_cmd_ctx *cmd,
+                           struct smtp_server_transaction *trans)
 {
-       return backend->v.cmd_data(backend, cmd, trans, data_input, data_size);
+       return backend->v.cmd_data(backend, cmd, trans,
+                                  backend->data_input, backend->data_size);
+}
+
+int submission_backends_cmd_data(struct client *client,
+                                struct smtp_server_cmd_ctx *cmd,
+                                struct smtp_server_transaction *trans,
+                                struct istream *data_input, uoff_t data_size)
+{
+       struct submission_backend *const *bkp;
+       int ret = 0;
+
+       i_assert(array_count(&client->rcpt_backends) > 0);
+
+       /* create the data_input streams first */
+       array_foreach_modifiable(&client->rcpt_backends, bkp) {
+               struct submission_backend *backend = *bkp;
+
+               backend->data_input =
+                       i_stream_create_sized(data_input, data_size);
+               backend->data_size = data_size;
+       }
+
+       /* now that all the streams are created, start reading them
+          (reading them earlier could have caused the data_input parent's
+          offset to change) */
+       array_foreach_modifiable(&client->rcpt_backends, bkp) {
+               struct submission_backend *backend = *bkp;
+
+               ret = submission_backend_cmd_data(backend, cmd, trans);
+               if (ret < 0)
+                       break;
+       }
+
+       return ret;
 }
 
 int submission_backend_cmd_vrfy(struct submission_backend *backend,
index a13c592948f75f8d0ff853612af6ca443fbd9b7e..54c7aa7ce774ac1c57e28feebd42aca88f53d4c1 100644 (file)
@@ -47,6 +47,9 @@ struct submission_backend {
 
        struct submission_backend_vfuncs v;
 
+       struct istream *data_input;
+       uoff_t data_size;
+
        bool started:1;
 };
 
@@ -64,6 +67,8 @@ void submission_backends_client_input_post(struct client *client);
 
 uoff_t submission_backend_get_max_mail_size(struct submission_backend *backend);
 
+void submission_backends_trans_free(struct client *client);
+
 void submission_backend_helo_reply_submit(struct submission_backend *backend,
                                          struct smtp_server_cmd_ctx *cmd,
                                          struct smtp_server_cmd_helo *data);
@@ -79,10 +84,10 @@ int submission_backend_cmd_rcpt(struct submission_backend *backend,
                                struct smtp_server_cmd_rcpt *data);
 int submission_backend_cmd_rset(struct submission_backend *backend,
                                struct smtp_server_cmd_ctx *cmd);
-int submission_backend_cmd_data(struct submission_backend *backend,
-                               struct smtp_server_cmd_ctx *cmd,
-                               struct smtp_server_transaction *trans,
-                               struct istream *data_input, uoff_t data_size);
+int submission_backends_cmd_data(struct client *client,
+                                struct smtp_server_cmd_ctx *cmd,
+                                struct smtp_server_transaction *trans,
+                                struct istream *data_input, uoff_t data_size);
 
 int submission_backend_cmd_vrfy(struct submission_backend *backend,
                                struct smtp_server_cmd_ctx *cmd,
index b6ee4403fbf04aeac0a785fde9c9e8ebd6350802..bb0a353d13067ba7f7b4bbcb8a8f0ff493745ef5 100644 (file)
@@ -198,6 +198,7 @@ struct client *client_create(int fd_in, int fd_out,
        client->session_id = i_strdup(session_id);
 
        i_array_init(&client->rcpt_to, 8);
+       i_array_init(&client->rcpt_backends, 8);
 
        i_zero(&smtp_set);
        smtp_set.hostname = set->hostname;
@@ -281,6 +282,7 @@ void client_destroy(struct client *client, const char *prefix,
 
        submission_backends_destroy_all(client);
        array_free(&client->rcpt_to);
+       array_free(&client->rcpt_backends);
 
        submission_client_count--;
        DLLIST_REMOVE(&submission_clients, client);
@@ -318,6 +320,7 @@ client_connection_trans_free(void *context,
                submission_recipient_destroy(rcptp);
        array_clear(&client->rcpt_to);
 
+       submission_backends_trans_free(client);
        client_state_reset(client);
 }
 
index bc0c9bdd529dbfe4ad0c450b47bf2774a3958516..71be61393b1c6643cb835661b161b20be9c6896d 100644 (file)
@@ -26,6 +26,7 @@ struct client {
        enum smtp_server_state last_state;
        struct client_state state;
        ARRAY(struct submission_recipient *) rcpt_to;
+       ARRAY(struct submission_backend *) rcpt_backends;
 
        struct mail_storage_service_user *service_user;
        struct mail_user *user;
index b472cb594b9eb5cac129d3e497ca366fc90cc629..c6ef4ec33a1d9405aca56ce53ef50ac3a43396e9 100644 (file)
@@ -146,7 +146,7 @@ int cmd_rcpt(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
        data->trans_context = rcpt;
        data->hook_finished = submission_rcpt_finished;
 
-       return submission_backend_cmd_rcpt(client->state.backend, cmd, data);
+       return submission_backend_cmd_rcpt(rcpt->backend, cmd, data);
 }
 
 /*
@@ -214,8 +214,8 @@ int cmd_data_continue(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
        i_stream_unref(&inputs[0]);
        i_stream_unref(&inputs[1]);
 
-       ret = submission_backend_cmd_data(client->state.backend, cmd,
-                                         trans, data_input, data_size);
+       ret = submission_backends_cmd_data(client, cmd, trans,
+                                          data_input, data_size);
 
        i_stream_unref(&data_input);
        return ret;
index b53e7b8b2b37952307e76d0228472c5993f2924a..bb48c20ff61674bf273078bcbda32dfceeaaa57c 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "submission-common.h"
 
+#include "submission-backend.h"
 #include "submission-recipient.h"
 
 struct submission_recipient *
@@ -10,7 +11,7 @@ submission_recipient_create(struct client *client, struct smtp_address *path)
        struct submission_recipient *rcpt;
 
        rcpt = i_new(struct submission_recipient, 1);
-       rcpt->client = client;
+       rcpt->backend = client->state.backend;
        rcpt->path = path;
 
        return rcpt;
@@ -29,10 +30,22 @@ void submission_recipient_finished(struct submission_recipient *rcpt,
                                   struct smtp_server_recipient *trcpt,
                                   unsigned int index)
 {
-       struct client *client = rcpt->client;
+       struct submission_backend *backend = rcpt->backend;
+       struct client *client = backend->client;
+       struct submission_backend *const *bknd_idx;
+       bool backend_found = FALSE;
 
        rcpt->path = trcpt->path;
        rcpt->index = index;
 
        array_append(&client->rcpt_to, &rcpt, 1);
+
+       array_foreach(&client->rcpt_backends, bknd_idx) {
+               if (*bknd_idx == backend) {
+                       backend_found = TRUE;
+                       break;
+               }
+       }
+       if (!backend_found)
+               array_append(&client->rcpt_backends, &backend, 1);
 }
index 3006a6582c6f03b734c1e8339a157e2641f78da2..1ce9e424232f3f399494599d4587892374d1637a 100644 (file)
@@ -1,10 +1,11 @@
 #ifndef SUBMISSION_RECIPIENT_H
 #define SUBMISSION_RECIPIENT_H
 
+struct submission_backend;
 struct client;
 
 struct submission_recipient {
-       struct client *client;
+       struct submission_backend *backend;
 
        struct smtp_address *path;
        unsigned int index;