From 7fc7e66e951211b472cd58d098c9b6a251070fe0 Mon Sep 17 00:00:00 2001 From: Stephan Bosch Date: Sat, 15 Sep 2018 18:04:33 +0200 Subject: [PATCH] submission: Record backend used for each recipient. This is a preparation for plugins overriding the default backend for a recipient. --- src/submission/submission-backend.c | 65 ++++++++++++++++++++++++--- src/submission/submission-backend.h | 13 ++++-- src/submission/submission-client.c | 3 ++ src/submission/submission-client.h | 1 + src/submission/submission-commands.c | 6 +-- src/submission/submission-recipient.c | 17 ++++++- src/submission/submission-recipient.h | 3 +- 7 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/submission/submission-backend.c b/src/submission/submission-backend.c index d21b4d1ff0..c92e15724f 100644 --- a/src/submission/submission-backend.c +++ b/src/submission/submission-backend.c @@ -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, diff --git a/src/submission/submission-backend.h b/src/submission/submission-backend.h index a13c592948..54c7aa7ce7 100644 --- a/src/submission/submission-backend.h +++ b/src/submission/submission-backend.h @@ -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, diff --git a/src/submission/submission-client.c b/src/submission/submission-client.c index b6ee4403fb..bb0a353d13 100644 --- a/src/submission/submission-client.c +++ b/src/submission/submission-client.c @@ -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); } diff --git a/src/submission/submission-client.h b/src/submission/submission-client.h index bc0c9bdd52..71be61393b 100644 --- a/src/submission/submission-client.h +++ b/src/submission/submission-client.h @@ -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; diff --git a/src/submission/submission-commands.c b/src/submission/submission-commands.c index b472cb594b..c6ef4ec33a 100644 --- a/src/submission/submission-commands.c +++ b/src/submission/submission-commands.c @@ -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; diff --git a/src/submission/submission-recipient.c b/src/submission/submission-recipient.c index b53e7b8b2b..bb48c20ff6 100644 --- a/src/submission/submission-recipient.c +++ b/src/submission/submission-recipient.c @@ -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); } diff --git a/src/submission/submission-recipient.h b/src/submission/submission-recipient.h index 3006a6582c..1ce9e42423 100644 --- a/src/submission/submission-recipient.h +++ b/src/submission/submission-recipient.h @@ -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; -- 2.47.3