From: Stephan Bosch Date: Sat, 13 Jan 2018 11:43:08 +0000 (+0100) Subject: lib-smtp: server: Put reply content in a separate struct. X-Git-Tag: 2.3.1~215 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=06d4b7aac2f175619d00c8b5d8a7fa87571f625d;p=thirdparty%2Fdovecot%2Fcore.git lib-smtp: server: Put reply content in a separate struct. This allows duplicate replies to share content for a multi-reply command. --- diff --git a/src/lib-smtp/smtp-server-command.c b/src/lib-smtp/smtp-server-command.c index 8012ada1e2..915dc0787c 100644 --- a/src/lib-smtp/smtp-server-command.c +++ b/src/lib-smtp/smtp-server-command.c @@ -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))); diff --git a/src/lib-smtp/smtp-server-private.h b/src/lib-smtp/smtp-server-private.h index a1df0886db..bd41896825 100644 --- a/src/lib-smtp/smtp-server-private.h +++ b/src/lib-smtp/smtp-server-private.h @@ -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; diff --git a/src/lib-smtp/smtp-server-reply.c b/src/lib-smtp/smtp-server-reply.c index 3840125a9c..9731714936 100644 --- a/src/lib-smtp/smtp-server-reply.c +++ b/src/lib-smtp/smtp-server-reply.c @@ -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)