From: Karl Fleischmann Date: Wed, 3 Aug 2022 12:53:36 +0000 (+0200) Subject: imap: Handle rawlogs when starting a compressed communication X-Git-Tag: 2.4.0~3656 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5c76bdcdfe0dab2126df6af3409e9cec773dc93a;p=thirdparty%2Fdovecot%2Fcore.git imap: Handle rawlogs when starting a compressed communication The rawlogs should not contain compressed data when starting a compressed communication channel. This commit amends rawlog management data on the imap client to keep track of rawlog streams, and appropriately handle rawlogs when imap compression is enabled. --- diff --git a/src/imap/cmd-compress.c b/src/imap/cmd-compress.c index 1df526e3f9..7254d40110 100644 --- a/src/imap/cmd-compress.c +++ b/src/imap/cmd-compress.c @@ -4,6 +4,7 @@ #include "imap-commands.h" #include "istream.h" #include "ostream.h" +#include "iostream-rawlog.h" #include "str.h" #include "compression.h" @@ -70,6 +71,32 @@ bool cmd_compress(struct client_command_context *cmd) client_skip_line(client); client_send_tagline(cmd, "OK Begin compression."); + if (client->pre_rawlog_input != NULL) { + /* Rawlogging is currently enabled. Stop it. */ + i_assert(client->pre_rawlog_output != NULL); + i_assert(client->pre_rawlog_input != client->post_rawlog_input); + i_assert(client->pre_rawlog_output != client->post_rawlog_output); + uoff_t prev_in_offset = client->input->v_offset; + /* Make sure the rawlog is the outermost stream, since we + can't remove it from the middle */ + i_assert(client->post_rawlog_input == client->input); + i_assert(client->post_rawlog_output == client->output); + /* Pre-rawlog streams are referenced only by the outermost + stream, so make sure they don't get destroyed */ + client->input = client->pre_rawlog_input; + client->output = client->pre_rawlog_output; + i_stream_ref(client->input); + o_stream_ref(client->output); + /* Destroy the rawlog streams. This closes the rawlogs, but + not the parent streams. */ + i_stream_destroy(&client->post_rawlog_input); + o_stream_destroy(&client->post_rawlog_output); + io_remove(&client->io); + /* Make sure istream-rawlog updated the parent stream's seek + offset. */ + i_assert(client->input->v_offset == prev_in_offset); + } + level = handler->get_default_level(); old_input = client->input; old_output = client->output; @@ -81,6 +108,14 @@ bool cmd_compress(struct client_command_context *cmd) i_stream_unref(&old_input); o_stream_unref(&old_output); + if (client->pre_rawlog_input != NULL) { + (void)iostream_rawlog_create(client->set->rawlog_dir, + &client->input, &client->output); + client->post_rawlog_input = client->input; + client->post_rawlog_output = client->output; + client_add_missing_io(client); + } + client_update_imap_parser_streams(client); return TRUE; } diff --git a/src/imap/imap-client.c b/src/imap/imap-client.c index 3c445b0f7f..2b0fcb07db 100644 --- a/src/imap/imap-client.c +++ b/src/imap/imap-client.c @@ -221,8 +221,20 @@ struct client *client_create(int fd_in, int fd_out, bool unhibernated, void client_create_finish_io(struct client *client) { if (client->set->rawlog_dir[0] != '\0') { + client->pre_rawlog_input = client->input; + client->pre_rawlog_output = client->output; (void)iostream_rawlog_create(client->set->rawlog_dir, &client->input, &client->output); + if (client->input != client->pre_rawlog_input) { + /* rawlog enabled */ + client->post_rawlog_input = client->input; + client->post_rawlog_output = client->output; + } else { + /* rawlog setting is set, but rawlog wasn't actually + started. */ + client->pre_rawlog_input = NULL; + client->pre_rawlog_output = NULL; + } } client->io = io_add_istream(client->input, client_input, client); } diff --git a/src/imap/imap-client.h b/src/imap/imap-client.h index af8af980c7..433d850117 100644 --- a/src/imap/imap-client.h +++ b/src/imap/imap-client.h @@ -161,8 +161,8 @@ struct client { int fd_in, fd_out; struct io *io; - struct istream *input; - struct ostream *output; + struct istream *input, *pre_rawlog_input, *post_rawlog_input; + struct ostream *output, *pre_rawlog_output, *post_rawlog_output; struct timeout *to_idle, *to_idle_output, *to_delayed_input; guid_128_t anvil_conn_guid;