From: Timo Sirainen Date: Wed, 4 Jun 2025 06:56:26 +0000 (+0300) Subject: lib, lib-ssl-iostream: Split off o_stream_init_buffering_flush() X-Git-Tag: 2.4.2~671 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16f9d8128a0181aa185e1b492429d388f38a869e;p=thirdparty%2Fdovecot%2Fcore.git lib, lib-ssl-iostream: Split off o_stream_init_buffering_flush() --- diff --git a/src/lib-ssl-iostream/ostream-openssl.c b/src/lib-ssl-iostream/ostream-openssl.c index fe50535376..530aa29bb2 100644 --- a/src/lib-ssl-iostream/ostream-openssl.c +++ b/src/lib-ssl-iostream/ostream-openssl.c @@ -217,29 +217,6 @@ static void o_stream_ssl_switch_ioloop_to(struct ostream_private *stream, o_stream_switch_ioloop_to(sstream->ssl_io->plain_output, ioloop); } -static int plain_flush_callback(struct ssl_ostream *sstream) -{ - struct ostream *ostream = &sstream->ostream.ostream; - int ret, ret2; - - /* try to actually flush the pending data */ - if ((ret = o_stream_flush(sstream->ssl_io->plain_output)) < 0) - return -1; - - /* we may be able to copy more data, try it */ - o_stream_ref(ostream); - if (sstream->ostream.callback != NULL) - ret2 = sstream->ostream.callback(sstream->ostream.context); - else - ret2 = o_stream_flush(&sstream->ostream.ostream); - if (ret2 == 0) - o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE); - o_stream_unref(&ostream); - if (ret2 < 0) - return -1; - return ret > 0 && ret2 > 0 ? 1 : 0; -} - static size_t o_stream_ssl_get_buffer_used_size(const struct ostream_private *stream) { @@ -310,10 +287,7 @@ struct ostream *openssl_o_stream_create_ssl(struct ssl_iostream *ssl_io) sstream->ostream.iostream.set_max_buffer_size = o_stream_ssl_set_max_buffer_size; - sstream->ostream.callback = ssl_io->plain_output->real_stream->callback; - sstream->ostream.context = ssl_io->plain_output->real_stream->context; - o_stream_set_flush_callback(ssl_io->plain_output, - plain_flush_callback, sstream); + o_stream_init_buffering_flush(&sstream->ostream, ssl_io->plain_output); return o_stream_create(&sstream->ostream, NULL, o_stream_get_fd(ssl_io->plain_output)); diff --git a/src/lib/ostream-private.h b/src/lib/ostream-private.h index 6222aa08d3..b4d08f5b47 100644 --- a/src/lib/ostream-private.h +++ b/src/lib/ostream-private.h @@ -34,6 +34,7 @@ struct ostream_private { size_t max_buffer_size; struct ostream *parent; /* for filter streams */ + struct ostream *buffering_parent; int fd; struct timeval last_write_timeval; @@ -70,4 +71,12 @@ int o_stream_flush_parent_if_needed(struct ostream_private *_stream); copied to this stream. */ int o_stream_flush_parent(struct ostream_private *_stream); +/* ostreams that buffer data internally need to be able to continue the flush + after parent ostream has more space available. This function registers a + flush callback to the parent ostream, which triggers flushing on this + ostream. If the parent already had a flush callback, it gets first copied to + this ostream. */ +void o_stream_init_buffering_flush(struct ostream_private *_stream, + struct ostream *parent); + #endif diff --git a/src/lib/ostream.c b/src/lib/ostream.c index 11b358ff1d..55ecb8b826 100644 --- a/src/lib/ostream.c +++ b/src/lib/ostream.c @@ -139,6 +139,40 @@ void o_stream_close(struct ostream *stream) o_stream_close_full(stream, TRUE); } +static int o_stream_default_buffering_flush(struct ostream_private *_stream) +{ + struct ostream *ostream = &_stream->ostream; + int ret, ret2; + + /* try to actually flush the pending data */ + if ((ret = o_stream_flush(_stream->buffering_parent)) < 0) + return -1; + + /* we may be able to copy more data, try it */ + o_stream_ref(ostream); + if (_stream->callback != NULL) + ret2 = _stream->callback(_stream->context); + else + ret2 = o_stream_flush(ostream); + if (ret2 == 0) + o_stream_set_flush_pending(_stream->buffering_parent, TRUE); + o_stream_unref(&ostream); + if (ret2 < 0) + return -1; + return ret > 0 && ret2 > 0 ? 1 : 0; +} + +void o_stream_init_buffering_flush(struct ostream_private *_stream, + struct ostream *parent) +{ + _stream->buffering_parent = parent; + _stream->callback = parent->real_stream->callback; + _stream->context = parent->real_stream->context; + + o_stream_set_flush_callback(parent, o_stream_default_buffering_flush, + _stream); +} + #undef o_stream_set_flush_callback void o_stream_set_flush_callback(struct ostream *stream, stream_flush_callback_t *callback, @@ -641,7 +675,7 @@ o_stream_default_set_flush_callback(struct ostream_private *_stream, stream_flush_callback_t *callback, void *context) { - if (_stream->parent != NULL) + if (_stream->parent != NULL && _stream->buffering_parent == NULL) o_stream_set_flush_callback(_stream->parent, callback, context); _stream->callback = callback; @@ -734,8 +768,10 @@ o_stream_create(struct ostream_private *_stream, struct ostream *parent, int fd) _stream->parent = parent; o_stream_ref(parent); - _stream->callback = parent->real_stream->callback; - _stream->context = parent->real_stream->context; + if (_stream->buffering_parent == NULL) { + _stream->callback = parent->real_stream->callback; + _stream->context = parent->real_stream->context; + } _stream->max_buffer_size = parent->real_stream->max_buffer_size; _stream->error_handling_disabled = parent->real_stream->error_handling_disabled;