]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
submission: relay backend: Use SMTP client transaction API, rather than relaying...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 29 Sep 2018 02:42:27 +0000 (04:42 +0200)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Wed, 10 Oct 2018 09:49:07 +0000 (09:49 +0000)
src/submission/submission-backend-relay.c

index cb5c4b0e1db49d8e8d9ad4a142ca57e7825cff94..734df10e29dceca6743aab52c4dec72a242bb806 100644 (file)
@@ -7,6 +7,7 @@
 #include "iostream-ssl.h"
 #include "smtp-client.h"
 #include "smtp-client-connection.h"
+#include "smtp-client-transaction.h"
 #include "smtp-client-command.h"
 
 #include "submission-backend-relay.h"
@@ -15,8 +16,10 @@ struct submission_backend_relay {
        struct submission_backend backend;
 
        struct smtp_client_connection *conn;
+       struct smtp_client_transaction *trans;
 
        bool xclient_sent:1;
+       bool trans_started:1;
        bool trusted:1;
 };
 
@@ -87,6 +90,58 @@ backend_relay_handle_relay_reply(struct submission_backend_relay *backend,
        return TRUE;
 }
 
+/*
+ * Mail transaction
+ */
+
+static void
+backend_relay_trans_finished(struct submission_backend_relay *backend)
+{
+       backend->trans = NULL;
+}
+
+static void
+backend_relay_trans_start_callback(
+       const struct smtp_reply *relay_reply ATTR_UNUSED,
+       struct submission_backend_relay *backend ATTR_UNUSED)
+{
+       /* nothing to do */
+}
+
+static void
+backend_relay_trans_start(struct submission_backend *_backend,
+                         struct smtp_server_transaction *trans)
+{
+       struct submission_backend_relay *backend =
+               (struct submission_backend_relay *)_backend;
+
+       if (backend->trans == NULL) {
+               backend->trans = smtp_client_transaction_create(
+                       backend->conn, trans->mail_from, &trans->params,
+                       backend_relay_trans_finished, backend);
+               smtp_client_transaction_start(
+                       backend->trans, backend_relay_trans_start_callback,
+                       backend);
+       } else if (!backend->trans_started) {
+               smtp_client_transaction_start_empty(
+                       backend->trans, trans->mail_from, &trans->params,
+                       backend_relay_trans_start_callback, backend);
+       }
+}
+
+static void
+backend_relay_trans_free(struct submission_backend *_backend,
+                        struct smtp_server_transaction *trans ATTR_UNUSED)
+{
+       struct submission_backend_relay *backend =
+               (struct submission_backend_relay *)_backend;
+
+       if (backend->trans == NULL)
+               return;
+
+       smtp_client_transaction_destroy(&backend->trans);
+}
+
 /*
  * EHLO, HELO commands
  */
@@ -203,7 +258,7 @@ struct relay_cmd_mail_context {
        struct smtp_server_cmd_ctx *cmd;
        struct smtp_server_cmd_mail *data;
 
-       struct smtp_client_command *cmd_relayed;
+       struct smtp_client_transaction_mail *relay_mail;
 };
 
 static void
@@ -229,12 +284,13 @@ relay_cmd_mail_update_xclient(struct submission_backend_relay *backend)
        backend->xclient_sent = TRUE;
 }
 
+
 static void
 relay_cmd_mail_replied(struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
                       struct relay_cmd_mail_context *mail_cmd)
 {
-       if (mail_cmd->cmd_relayed != NULL)
-               smtp_client_command_abort(&mail_cmd->cmd_relayed);
+       if (mail_cmd->relay_mail != NULL)
+               smtp_client_transaction_mail_abort(&mail_cmd->relay_mail);
 }
 
 static void
@@ -247,7 +303,7 @@ relay_cmd_mail_callback(const struct smtp_reply *relay_reply,
 
        /* finished relaying MAIL command to relay server */
        i_assert(mail_cmd != NULL);
-       mail_cmd->cmd_relayed = NULL;
+       mail_cmd->relay_mail = NULL;
 
        if (!backend_relay_handle_relay_reply(backend, relay_reply, &reply))
                return;
@@ -344,9 +400,22 @@ backend_relay_cmd_mail(struct submission_backend *_backend,
        smtp_server_command_add_hook(cmd->cmd, SMTP_SERVER_COMMAND_HOOK_REPLIED,
                                     relay_cmd_mail_replied, mail_cmd);
 
-       mail_cmd->cmd_relayed = smtp_client_command_mail_submit(
-               backend->conn, 0, data->path, &data->params,
-               relay_cmd_mail_callback, mail_cmd);
+       if (backend->trans == NULL) {
+               /* start client transaction */
+               backend->trans = smtp_client_transaction_create(
+                       backend->conn, data->path, &data->params,
+                       backend_relay_trans_finished, backend);
+               smtp_client_transaction_set_immediate(backend->trans, TRUE);
+               smtp_client_transaction_start(backend->trans,
+                                             relay_cmd_mail_callback, mail_cmd);
+               backend->trans_started = TRUE;
+       } else {
+               /* forward pipelined MAIL command */
+               i_assert(backend->trans_started);
+               mail_cmd->relay_mail = smtp_client_transaction_add_mail(
+                       backend->trans, data->path, &data->params,
+                       relay_cmd_mail_callback, mail_cmd);
+       }
        return 0;
 }
 
@@ -360,15 +429,23 @@ struct relay_cmd_rcpt_context {
        struct smtp_server_cmd_ctx *cmd;
        struct smtp_server_cmd_rcpt *data;
 
-       struct smtp_client_command *cmd_relayed;
+       struct smtp_client_transaction_rcpt *relay_rcpt;
 };
 
 static void
 relay_cmd_rcpt_replied(struct smtp_server_cmd_ctx *cmd ATTR_UNUSED,
                       struct relay_cmd_rcpt_context *rcpt_cmd)
 {
-       if (rcpt_cmd->cmd_relayed != NULL)
-               smtp_client_command_abort(&rcpt_cmd->cmd_relayed);
+       if (rcpt_cmd->relay_rcpt != NULL)
+               smtp_client_transaction_rcpt_abort(&rcpt_cmd->relay_rcpt);
+}
+
+static void
+relay_cmd_rcpt_data_callback(
+       const struct smtp_reply *relay_reply ATTR_UNUSED,
+       struct relay_cmd_rcpt_context *rcpt_cmd ATTR_UNUSED)
+{
+       /* nothing to do here for normal submission */
 }
 
 static void
@@ -381,7 +458,7 @@ relay_cmd_rcpt_callback(const struct smtp_reply *relay_reply,
 
        /* finished relaying MAIL command to relay server */
        i_assert(rcpt_cmd != NULL);
-       rcpt_cmd->cmd_relayed = NULL;
+       rcpt_cmd->relay_rcpt = NULL;
 
        if (!backend_relay_handle_relay_reply(backend, relay_reply, &reply))
                return;
@@ -414,9 +491,14 @@ backend_relay_cmd_rcpt(struct submission_backend *_backend,
        smtp_server_command_add_hook(cmd->cmd, SMTP_SERVER_COMMAND_HOOK_REPLIED,
                                     relay_cmd_rcpt_replied, rcpt_cmd);
 
-       rcpt_cmd->cmd_relayed = smtp_client_command_rcpt_submit(
-               backend->conn, 0, data->path, &data->params,
-               relay_cmd_rcpt_callback, rcpt_cmd);
+       if (backend->trans == NULL) {
+               backend->trans = smtp_client_transaction_create_empty(
+                       backend->conn, backend_relay_trans_finished, backend);
+       }
+       rcpt_cmd->relay_rcpt = smtp_client_transaction_add_rcpt(
+               backend->trans, data->path,  &data->params,
+               relay_cmd_rcpt_callback, relay_cmd_rcpt_data_callback,
+               rcpt_cmd);
        return 0;
 }
 
@@ -463,8 +545,16 @@ backend_relay_cmd_rset(struct submission_backend *_backend,
        rset_cmd->backend = backend;
        rset_cmd->cmd = cmd;
 
-       rset_cmd->cmd_relayed = smtp_client_command_rset_submit(
-               backend->conn, 0, relay_cmd_rset_callback, rset_cmd);
+       if (backend->trans != NULL) {
+               /* RSET pipelined after MAIL */
+               smtp_client_transaction_reset(backend->trans,
+                                             relay_cmd_rset_callback,
+                                             rset_cmd);
+       } else {
+               /* RSET alone */
+               rset_cmd->cmd_relayed = smtp_client_command_rset_submit(
+                       backend->conn, 0, relay_cmd_rset_callback, rset_cmd);
+       }
        return 0;
 }
 
@@ -477,8 +567,6 @@ struct relay_cmd_data_context {
 
        struct smtp_server_cmd_ctx *cmd;
        struct smtp_server_transaction *trans;
-
-       struct smtp_client_command *cmd_relayed;
 };
 
 static void
@@ -534,9 +622,9 @@ backend_relay_cmd_data(struct submission_backend *_backend,
        data_ctx->trans = trans;
        trans->context = (void*)data_ctx;
 
-       data_ctx->cmd_relayed = smtp_client_command_data_submit(
-               backend->conn, 0, data_input, relay_cmd_data_callback,
-               data_ctx);
+       i_assert(backend->trans != NULL);
+       smtp_client_transaction_send(backend->trans, data_input,
+                                    relay_cmd_data_callback, data_ctx);
        return 0;
 }
 
@@ -816,6 +904,8 @@ static void backend_relay_destroy(struct submission_backend *_backend)
        struct submission_backend_relay *backend =
                (struct submission_backend_relay *)_backend;
 
+       if (backend->trans != NULL)
+               smtp_client_transaction_destroy(&backend->trans);
        if (backend->conn != NULL)
                smtp_client_connection_close(&backend->conn);
        i_free(backend);
@@ -890,6 +980,9 @@ static struct submission_backend_vfuncs backend_relay_vfuncs = {
 
        .get_max_mail_size = backend_relay_get_max_mail_size,
 
+       .trans_start = backend_relay_trans_start,
+       .trans_free = backend_relay_trans_free,
+
        .cmd_helo = backend_relay_cmd_helo,
 
        .cmd_mail = backend_relay_cmd_mail,