]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: server: Put reply content in a separate struct.
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sat, 13 Jan 2018 11:43:08 +0000 (12:43 +0100)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Tue, 6 Mar 2018 04:44:46 +0000 (06:44 +0200)
This allows duplicate replies to share content for a multi-reply command.

src/lib-smtp/smtp-server-command.c
src/lib-smtp/smtp-server-private.h
src/lib-smtp/smtp-server-reply.c

index 8012ada1e252c66ac07325d162f6e3ca2c6501e1..915dc0787c1b997ef7211cfdf19cb09901eacbdb 100644 (file)
@@ -403,10 +403,12 @@ void smtp_server_command_submit_reply(struct smtp_server_command *cmd)
        for (i = 0; i < cmd->replies_expected; i++) {
                const struct smtp_server_reply *reply =
                        array_idx(&cmd->replies, i);
-               if (reply->submitted)
-                       submitted++;
+               if (!reply->submitted)
+                       continue;
+               submitted++;
 
-               switch (reply->status) {
+               i_assert(reply->content != NULL);
+               switch (reply->content->status) {
                case 500:
                case 501:
                case 503:
@@ -497,7 +499,7 @@ bool smtp_server_command_reply_status_equals(struct smtp_server_command *cmd,
        i_assert(cmd->replies_expected == 1);
        reply = smtp_server_command_get_reply(cmd, 0);
 
-       return (reply->status == status);
+       return (reply->content != NULL && reply->content->status == status);
 }
 
 bool smtp_server_command_replied_success(struct smtp_server_command *cmd)
@@ -513,7 +515,8 @@ bool smtp_server_command_replied_success(struct smtp_server_command *cmd)
                        array_idx(&cmd->replies, i);
                if (!reply->submitted)
                        return FALSE;
-               if (reply->status / 100 == 2)
+               i_assert(reply->content != NULL);
+               if (reply->content->status / 100 == 2)
                        success = TRUE;
        }
 
@@ -535,10 +538,11 @@ void smtp_server_command_finished(struct smtp_server_command *cmd)
 
        i_assert(array_is_created(&cmd->replies));
        reply = array_idx_modifiable(&cmd->replies, 0);
+       i_assert(reply->content != NULL);
 
-       if (reply->status == 221 || reply->status == 421) {
+       if (reply->content->status == 221 || reply->content->status == 421) {
                i_assert(cmd->replies_expected == 1);
-               if (reply->status == 421) {
+               if (reply->content->status == 421) {
                        smtp_server_connection_close(&conn, t_strdup_printf(
                                "Server closed the connection: %s",
                                smtp_server_reply_get_one_line(reply)));
index a1df0886db85f483b036b675d8eb4ffcee596180..bd41896825b8624fe2d161b795a234c3e5208678 100644 (file)
@@ -43,15 +43,20 @@ enum smtp_server_command_state {
        SMTP_SERVER_COMMAND_STATE_ABORTED
 };
 
-struct smtp_server_reply {
-       struct smtp_server_command *command;
-       unsigned int index;
-
+struct smtp_server_reply_content {
        unsigned int status;
        const char *status_prefix;
 
        string_t *text;
        size_t last_line;
+};
+
+struct smtp_server_reply {
+       struct smtp_server_command *command;
+       unsigned int index;
+
+       /* replies may share content */
+       struct smtp_server_reply_content *content;
 
        bool submitted:1;
        bool sent:1;
index 3840125a9c764dc2cfd111980ae99d68367f38c1..9731714936eb75b9a8d980ab8ff03c5088c84699 100644 (file)
@@ -30,7 +30,8 @@ smtp_server_reply_debug(struct smtp_server_reply *reply,
                                smtp_protocol_name(set->protocol),
                                smtp_server_connection_label(conn),
                                smtp_server_command_label(command),
-                               reply->status, reply->index+1, command->replies_expected,
+                               reply->content->status,
+                               reply->index+1, command->replies_expected,
                                t_strdup_vprintf(format, args));
                } else {
                        i_debug("%s-server: conn %s: "
@@ -38,7 +39,8 @@ smtp_server_reply_debug(struct smtp_server_reply *reply,
                                smtp_protocol_name(set->protocol),
                                smtp_server_connection_label(conn),
                                smtp_server_command_label(command),
-                               reply->status, t_strdup_vprintf(format, args));
+                               reply->content->status,
+                               t_strdup_vprintf(format, args));
                }
                va_end(args);
        }
@@ -55,8 +57,10 @@ static void smtp_server_reply_clear(struct smtp_server_reply *reply)
 
        smtp_server_reply_debug(reply, "Destroy");
 
-       if (reply->text != NULL)
-               str_free(&reply->text);
+       if (reply->content == NULL)
+               return;
+       str_free(&reply->content->text);
+
 }
 
 struct smtp_server_reply *
@@ -103,15 +107,18 @@ smtp_server_reply_create_index(struct smtp_server_command *cmd,
 
        reply->index = index;
        reply->command = cmd;
-       reply->status = status;
+
+       if (reply->content == NULL)
+               reply->content = p_new(pool, struct smtp_server_reply_content, 1);
+       reply->content->status = status;
        if (enh_code == NULL || *enh_code == '\0') {
-               reply->status_prefix =
+               reply->content->status_prefix =
                        p_strdup_printf(pool, "%03u-", status);
        } else {
-               reply->status_prefix =
+               reply->content->status_prefix =
                        p_strdup_printf(pool, "%03u-%s ", status, enh_code);
        }
-       reply->text = str_new(default_pool, 256);
+       reply->content->text = str_new(default_pool, 256);
        return reply;
 }
 
@@ -130,7 +137,7 @@ smtp_server_reply_create_forward(struct smtp_server_command *cmd,
 
        reply = smtp_server_reply_create_index(cmd, index,
                from->status, smtp_reply_get_enh_code(from));
-       smtp_reply_write(reply->text, from);
+       smtp_reply_write(reply->content->text, from);
 
        return reply;
 }
@@ -152,6 +159,8 @@ void smtp_server_reply_free(struct smtp_server_command *cmd)
 void smtp_server_reply_add_text(struct smtp_server_reply *reply,
                                const char *text)
 {
+       string_t *textbuf = reply->content->text;
+
        i_assert(!reply->submitted);
 
        if (*text == '\0')
@@ -160,28 +169,29 @@ void smtp_server_reply_add_text(struct smtp_server_reply *reply,
        do {
                const char *p;
 
-               reply->last_line = str_len(reply->text);
+               reply->content->last_line = str_len(textbuf);
 
                p = strchr(text, '\n');
-               str_append(reply->text, reply->status_prefix);
+               str_append(textbuf, reply->content->status_prefix);
                if (p == NULL) {
-                       str_append(reply->text, text);
+                       str_append(textbuf, text);
                        text = NULL;
                } else {
                        if (p > text && *(p-1) == '\r')
-                               str_append_n(reply->text, text, p - text - 1);
+                               str_append_n(textbuf, text, p - text - 1);
                        else
-                               str_append_n(reply->text, text, p - text);
+                               str_append_n(textbuf, text, p - text);
                        text = p + 1;
                }
-               str_append(reply->text, "\r\n");
+               str_append(textbuf, "\r\n");
        } while (text != NULL && *text != '\0');
 }
 
 void smtp_server_reply_submit(struct smtp_server_reply *reply)
 {
        i_assert(!reply->submitted);
-       i_assert(str_len(reply->text) >= 5);
+       i_assert(reply->content != NULL);
+       i_assert(str_len(reply->content->text) >= 5);
        smtp_server_reply_debug(reply, "Submitted");
 
        reply->command->replies_submitted++;
@@ -312,16 +322,18 @@ void smtp_server_reply_quit(struct smtp_server_cmd_ctx *_cmd)
 
 const char *smtp_server_reply_get_one_line(struct smtp_server_reply *reply)
 {
-       string_t *str;
+       string_t *textbuf, *str;
        const char *text, *p;
        size_t text_len, prefix_len, line_len;
 
-       i_assert(str_len(reply->text) > 0);
+       i_assert(reply->content != NULL);
+       textbuf = reply->content->text;
+       i_assert(str_len(textbuf) > 0);
 
-       prefix_len = strlen(reply->status_prefix);
+       prefix_len = strlen(reply->content->status_prefix);
        str = t_str_new(256);
-       text = str_c(reply->text);
-       text_len = str_len(reply->text);
+       text = str_c(textbuf);
+       text_len = str_len(textbuf);
 
        for (;;) {
                p = strchr(text, '\n');
@@ -350,23 +362,25 @@ static int smtp_server_reply_send_real(struct smtp_server_reply *reply,
        struct smtp_server_connection *conn = cmd->context.conn;
        const struct smtp_server_settings *set = &conn->set;
        struct ostream *output = conn->conn.output;
+       string_t *textbuf;
        char *text;
        int ret = 0;
 
        *error_r = NULL;
 
-       i_assert(str_len(reply->text) > 0);
+       i_assert(reply->content != NULL);
+       textbuf = reply->content->text;
+       i_assert(str_len(textbuf) > 0);
 
        /* substitute '-' with ' ' in last line */
-       text = str_c_modifiable(reply->text);
-       text = text + reply->last_line + 3;
+       text = str_c_modifiable(textbuf);
+       text = text + reply->content->last_line + 3;
        if (text[0] != ' ') {
                i_assert(text[0] == '-');
                text[0] = ' ';
        }
 
-       if (o_stream_send(output,
-               str_data(reply->text), str_len(reply->text)) < 0) {
+       if (o_stream_send(output, str_data(textbuf), str_len(textbuf)) < 0) {
                if (errno != EPIPE && errno != ECONNRESET) {
                        *error_r = t_strdup_printf("write(%s) failed: %s",
                                                   o_stream_get_name(output),
@@ -407,11 +421,13 @@ smtp_server_reply_create_ehlo(struct smtp_server_command *cmd)
 {
        struct smtp_server_connection *conn = cmd->context.conn;
        struct smtp_server_reply *reply;
+       string_t *textbuf;
 
        reply = smtp_server_reply_create(cmd, 250, "");
-       str_append(reply->text, reply->status_prefix);
-       str_append(reply->text, conn->set.hostname);
-       str_append(reply->text, "\r\n");
+       textbuf = reply->content->text;
+       str_append(textbuf, reply->content->status_prefix);
+       str_append(textbuf, conn->set.hostname);
+       str_append(textbuf, "\r\n");
 
        return reply;
 }
@@ -419,31 +435,38 @@ smtp_server_reply_create_ehlo(struct smtp_server_command *cmd)
 void smtp_server_reply_ehlo_add(struct smtp_server_reply *reply,
                                const char *keyword)
 {
+       string_t *textbuf;
+
        i_assert(!reply->submitted);
+       i_assert(reply->content != NULL);
+       textbuf = reply->content->text;
 
-       reply->last_line = str_len(reply->text);
-       str_append(reply->text, reply->status_prefix);
-       str_append(reply->text, keyword);
-       str_append(reply->text, "\r\n");
+       reply->content->last_line = str_len(textbuf);
+       str_append(textbuf, reply->content->status_prefix);
+       str_append(textbuf, keyword);
+       str_append(textbuf, "\r\n");
 }
 
 void smtp_server_reply_ehlo_add_param(struct smtp_server_reply *reply,
        const char *keyword, const char *param_fmt, ...)
 {
        va_list args;
+       string_t *textbuf;
 
        i_assert(!reply->submitted);
+       i_assert(reply->content != NULL);
+       textbuf = reply->content->text;
 
-       reply->last_line = str_len(reply->text);
-       str_append(reply->text, reply->status_prefix);
-       str_append(reply->text, keyword);
+       reply->content->last_line = str_len(textbuf);
+       str_append(textbuf, reply->content->status_prefix);
+       str_append(textbuf, keyword);
        if (*param_fmt != '\0') {
                va_start(args, param_fmt);
-               str_append_c(reply->text, ' ');
-               str_vprintfa(reply->text, param_fmt, args);
+               str_append_c(textbuf, ' ');
+               str_vprintfa(textbuf, param_fmt, args);
                va_end(args);
        }
-       str_append(reply->text, "\r\n");
+       str_append(textbuf, "\r\n");
 }
 
 void smtp_server_reply_ehlo_add_xclient(struct smtp_server_reply *reply)