]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
submission: Define generic backend API.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 15 Sep 2018 11:02:50 +0000 (13:02 +0200)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 12 Feb 2019 13:40:41 +0000 (15:40 +0200)
src/submission/Makefile.am
src/submission/submission-backend.c [new file with mode: 0644]
src/submission/submission-backend.h
src/submission/submission-client.c
src/submission/submission-client.h

index 08635bee34ca2e151b7fa90489d02be5d69787b3..2ccb1e16d9014b22537c93b8628dbd80306d8e5a 100644 (file)
@@ -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 (file)
index 0000000..6588e0c
--- /dev/null
@@ -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);
+}
index 0a3e6ea9e67a2efe05af935057f603a2735480cc..12ad93bbeec4f405bb1a4111331cc424e8b3e9e3 100644 (file)
@@ -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
index 976c8180a483730d245f886c9d3e91fb97a56a6d..99a68d6c563812f27d1646e207ce761ef1bad3dc 100644 (file)
@@ -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;
 }
index 71d73b4d1754271062c83f970dfd4510babc908b..9c219f5fa8d009ede7f4c686c39c9b745a28ae58 100644 (file)
@@ -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;