bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen#include "lib.h"
fbae84cc7a76555ab38cf1b5b90682fa8deee2f3Timo Sirainen#include "istream.h"
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen#include "ostream-private.h"
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen#include "ostream-metawrap.h"
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainenstruct metawrap_ostream {
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen struct ostream_private ostream;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen void (*write_callback)(void *);
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen void *context;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen};
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainenstatic void o_stream_metawrap_call_callback(struct metawrap_ostream *mstream)
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen{
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen void (*write_callback)(void *) = mstream->write_callback;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen if (write_callback != NULL) {
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen mstream->write_callback = NULL;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen write_callback(mstream->context);
c449e0b0843381306cc196affcd5a38a40804178Timo Sirainen /* metadata headers aren't counted as part of the offset */
c449e0b0843381306cc196affcd5a38a40804178Timo Sirainen mstream->ostream.ostream.offset = 0;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen }
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen}
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainenstatic ssize_t
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Siraineno_stream_metawrap_sendv(struct ostream_private *stream,
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen const struct const_iovec *iov, unsigned int iov_count)
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen{
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen struct metawrap_ostream *mstream = (struct metawrap_ostream *)stream;
6759ba36f2bac9e83547cfdcf233382a139f1283Timo Sirainen ssize_t ret;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen o_stream_metawrap_call_callback(mstream);
6759ba36f2bac9e83547cfdcf233382a139f1283Timo Sirainen if ((ret = o_stream_sendv(stream->parent, iov, iov_count)) < 0)
6759ba36f2bac9e83547cfdcf233382a139f1283Timo Sirainen o_stream_copy_error_from_parent(stream);
ec13aa1185c1722b3ac5deb1a000234effc93c42Timo Sirainen else
ec13aa1185c1722b3ac5deb1a000234effc93c42Timo Sirainen stream->ostream.offset += ret;
6759ba36f2bac9e83547cfdcf233382a139f1283Timo Sirainen return ret;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen}
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainenstatic enum ostream_send_istream_result
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Siraineno_stream_metawrap_send_istream(struct ostream_private *_outstream,
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen struct istream *instream)
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen{
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen struct metawrap_ostream *outstream =
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen (struct metawrap_ostream *)_outstream;
fbae84cc7a76555ab38cf1b5b90682fa8deee2f3Timo Sirainen uoff_t orig_instream_offset = instream->v_offset;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen enum ostream_send_istream_result res;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen o_stream_metawrap_call_callback(outstream);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if ((res = o_stream_send_istream(_outstream->parent, instream)) == OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT)
b60ba688ee49df2c2efba9071b717c8d2363cdc3Timo Sirainen o_stream_copy_error_from_parent(_outstream);
fbae84cc7a76555ab38cf1b5b90682fa8deee2f3Timo Sirainen _outstream->ostream.offset += instream->v_offset - orig_instream_offset;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return res;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen}
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainenstruct ostream *
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Siraineno_stream_create_metawrap(struct ostream *output,
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen void (*write_callback)(void *), void *context)
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen{
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen struct metawrap_ostream *mstream;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen mstream = i_new(struct metawrap_ostream, 1);
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen mstream->ostream.sendv = o_stream_metawrap_sendv;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen mstream->ostream.send_istream = o_stream_metawrap_send_istream;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen mstream->write_callback = write_callback;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen mstream->context = context;
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen return o_stream_create(&mstream->ostream, output,
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen o_stream_get_fd(output));
deed0441882796b3d985ab867e96b9c56d9fc0d9Timo Sirainen}