From: Stephan Bosch Date: Sat, 15 Sep 2018 11:02:50 +0000 (+0200) Subject: submission: Define generic backend API. X-Git-Tag: 2.3.5~214 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=543b5df06e8c02702316e80020e30f0683def6b6;p=thirdparty%2Fdovecot%2Fcore.git submission: Define generic backend API. --- diff --git a/src/submission/Makefile.am b/src/submission/Makefile.am index 08635bee34..2ccb1e16d9 100644 --- a/src/submission/Makefile.am +++ b/src/submission/Makefile.am @@ -35,6 +35,7 @@ submission_DEPENDENCIES = \ submission_SOURCES = \ main.c \ + submission-backend.c \ submission-backend-relay.c \ submission-recipient.c \ submission-client.c \ diff --git a/src/submission/submission-backend.c b/src/submission/submission-backend.c new file mode 100644 index 0000000000..6588e0cb91 --- /dev/null +++ b/src/submission/submission-backend.c @@ -0,0 +1,178 @@ +/* Copyright (c) 2018 Dovecot authors, see the included COPYING file */ + +#include "submission-common.h" +#include "llist.h" + +#include "submission-client.h" +#include "submission-commands.h" +#include "submission-backend.h" + +void submission_backend_init(struct submission_backend *backend, + struct client *client, + const struct submission_backend_vfuncs *vfunc) +{ + backend->client = client; + backend->v = *vfunc; + + client->backends_count++; + DLLIST_PREPEND(&client->backends, backend); +} + +static void submission_backend_destroy(struct submission_backend *backend) +{ + struct client *client = backend->client; + + DLLIST_REMOVE(&client->backends, backend); + backend->v.destroy(backend); +} + +void submission_backends_destroy_all(struct client *client) +{ + while (client->backends != NULL) + submission_backend_destroy(client->backends); +} + +void submission_backend_start(struct submission_backend *backend) +{ + if (backend->started) + return; + backend->v.start(backend); + backend->started = TRUE; +} + +void submission_backend_started(struct submission_backend *backend, + enum smtp_capability caps) +{ + struct client *client = backend->client; + + client_default_backend_started(client, caps); +} + +void submission_backends_client_input_pre(struct client *client) +{ + struct submission_backend *backend; + + for (backend = client->backends; backend != NULL; + backend = backend->next) { + if (!backend->started) + continue; + if (backend->v.client_input_pre != NULL) + backend->v.client_input_pre(backend); + + } +} + +void submission_backends_client_input_post(struct client *client) +{ + struct submission_backend *backend; + + for (backend = client->backends; backend != NULL; + backend = backend->next) { + if (!backend->started) + continue; + if (backend->v.client_input_post != NULL) + backend->v.client_input_post(backend); + } +} + +uoff_t submission_backend_get_max_mail_size(struct submission_backend *backend) +{ + if (backend->v.get_max_mail_size != NULL) + return backend->v.get_max_mail_size(backend); + return UOFF_T_MAX; +} + +int submission_backend_cmd_helo(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_helo *data) +{ + if (!backend->started || backend->v.cmd_helo == NULL) { + /* default backend is not interested, respond right away */ + submission_helo_reply_submit(cmd, data); + return 1; + } + + return backend->v.cmd_helo(backend, cmd, data); +} + +void submission_backend_helo_reply_submit( + struct submission_backend *backend ATTR_UNUSED, + struct smtp_server_cmd_ctx *cmd, struct smtp_server_cmd_helo *data) +{ + submission_helo_reply_submit(cmd, data); +} + +int submission_backend_cmd_mail(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_mail *data) +{ + submission_backend_start(backend); + + if (backend->v.cmd_mail == NULL) { + /* mail backend is not interested, respond right away */ + return 1; + } + + return backend->v.cmd_mail(backend, cmd, data); +} + +int submission_backend_cmd_rcpt(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_rcpt *data) +{ + if (backend->v.cmd_rcpt == NULL) { + /* backend is not interested, respond right away */ + return 1; + } + + return backend->v.cmd_rcpt(backend, cmd, data); +} + +int submission_backend_cmd_rset(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd) +{ + if (backend->v.cmd_rset == NULL) { + /* backend is not interested, respond right away */ + return 1; + } + 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) +{ + return backend->v.cmd_data(backend, cmd, trans, data_input); +} + +int submission_backend_cmd_vrfy(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + const char *param) +{ + if (backend->v.cmd_vrfy == NULL) { + /* backend is not interested, respond right away */ + return 1; + } + return backend->v.cmd_vrfy(backend, cmd, param); +} + +int submission_backend_cmd_noop(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd) +{ + if (backend->v.cmd_noop == NULL) { + /* backend is not interested, respond right away */ + return 1; + } + return backend->v.cmd_noop(backend, cmd); +} + +int submission_backend_cmd_quit(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd) +{ + if (backend->v.cmd_quit == NULL) { + /* backend is not interested, respond right away */ + return 1; + } + return backend->v.cmd_quit(backend, cmd); +} diff --git a/src/submission/submission-backend.h b/src/submission/submission-backend.h index 0a3e6ea9e6..12ad93bbee 100644 --- a/src/submission/submission-backend.h +++ b/src/submission/submission-backend.h @@ -1,8 +1,96 @@ #ifndef SUBMISSION_BACKEND_H #define SUBMISSION_BACKEND_H +struct submission_backend; + +struct submission_backend_vfuncs { + void (*destroy)(struct submission_backend *backend); + + void (*start)(struct submission_backend *backend); + + void (*client_input_pre)(struct submission_backend *backend); + void (*client_input_post)(struct submission_backend *backend); + + uoff_t (*get_max_mail_size)(struct submission_backend *backend); + + int (*cmd_helo)(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_helo *data); + + int (*cmd_mail)(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_mail *data); + int (*cmd_rcpt)(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_rcpt *data); + int (*cmd_rset)(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd); + int (*cmd_data)(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_transaction *trans, + struct istream *data_input); + + int (*cmd_vrfy)(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + const char *param); + int (*cmd_noop)(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd); + + int (*cmd_quit)(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd); +}; + struct submission_backend { struct client *client; + + struct submission_backend *prev, *next; + + struct submission_backend_vfuncs v; + + bool started:1; }; +void submission_backend_init(struct submission_backend *backend, + struct client *client, + const struct submission_backend_vfuncs *vfunc); +void submission_backends_destroy_all(struct client *client); + +void submission_backend_start(struct submission_backend *backend); +void submission_backend_started(struct submission_backend *backend, + enum smtp_capability caps); + +void submission_backends_client_input_pre(struct client *client); +void submission_backends_client_input_post(struct client *client); + +uoff_t submission_backend_get_max_mail_size(struct submission_backend *backend); + +void submission_backend_helo_reply_submit(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_helo *data); +int submission_backend_cmd_helo(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_helo *data); + +int submission_backend_cmd_mail(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + struct smtp_server_cmd_mail *data); +int submission_backend_cmd_rcpt(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + 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); + +int submission_backend_cmd_vrfy(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd, + const char *param); +int submission_backend_cmd_noop(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd); + +int submission_backend_cmd_quit(struct submission_backend *backend, + struct smtp_server_cmd_ctx *cmd); + #endif diff --git a/src/submission/submission-client.c b/src/submission/submission-client.c index 976c8180a4..99a68d6c56 100644 --- a/src/submission/submission-client.c +++ b/src/submission/submission-client.c @@ -50,12 +50,14 @@ static void client_input_pre(void *context) struct client *client = context; client_proxy_input_pre(client); + submission_backends_client_input_pre(client); } static void client_input_post(void *context) { struct client *client = context; client_proxy_input_post(client); + submission_backends_client_input_post(client); } static const char *client_remote_id(struct client *client) @@ -246,6 +248,7 @@ void client_destroy(struct client *client, const char *prefix, client_disconnect(client, prefix, reason); + submission_backends_destroy_all(client); array_free(&client->rcpt_to); submission_client_count--; @@ -371,6 +374,7 @@ void client_disconnect(struct client *client, const char *enh_code, timeout_remove(&client->to_quit); client_proxy_destroy(client); + submission_backends_destroy_all(client); if (array_is_created(&client->rcpt_to)) { array_foreach_modifiable(&client->rcpt_to, rcptp) @@ -402,10 +406,11 @@ void client_disconnect(struct client *client, const char *enh_code, uoff_t client_get_max_mail_size(struct client *client) { + struct submission_backend *backend; uoff_t max_size, limit; - /* Account for the backend server's SIZE limit and calculate our own - relative to it. */ + /* Account for backend SIZE limits and calculate our own relative to + those. */ max_size = client->set->submission_max_mail_size; if (max_size == 0) max_size = UOFF_T_MAX; @@ -415,6 +420,16 @@ uoff_t client_get_max_mail_size(struct client *client) if (limit < max_size) max_size = limit; } + for (backend = client->backends; backend != NULL; + backend = backend->next) { + limit = submission_backend_get_max_mail_size(backend); + + if (limit <= SUBMISSION_MAX_ADDITIONAL_MAIL_SIZE) + continue; + limit -= SUBMISSION_MAX_ADDITIONAL_MAIL_SIZE; + if (limit < max_size) + max_size = limit; + } return max_size; } diff --git a/src/submission/submission-client.h b/src/submission/submission-client.h index 71d73b4d17..9c219f5fa8 100644 --- a/src/submission/submission-client.h +++ b/src/submission/submission-client.h @@ -7,6 +7,7 @@ struct smtp_reply; struct submission_recipient; +struct submission_backend; struct client; struct client_state { @@ -38,6 +39,8 @@ struct client { enum smtp_capability backend_capabilities; struct submission_backend_relay backend; + struct submission_backend *backends; + unsigned int backends_count; bool standalone:1; bool disconnected:1;