bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2014-2018 Dovecot authors, see the included COPYING file */
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainenstatic void i_stream_timeout_close(struct iostream_private *stream,
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen struct timeout_istream *tstream = (struct timeout_istream *)stream;
038c2831447440bf0bef89b43dd0968afc298abcStephan Boschstatic void i_stream_timeout_switch_ioloop_to(struct istream_private *stream,
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen struct timeout_istream *tstream = (struct timeout_istream *)stream;
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch tstream->to = io_loop_move_timeout_to(ioloop, &tstream->to);
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainenstatic void i_stream_timeout(struct timeout_istream *tstream)
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch struct iostream_private *iostream = &tstream->istream.iostream;
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen /* we came here after a long-running code. timeouts are handled
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen before IOs, so wait for i_stream_read() to be called again
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen before assuming that we've timed out. */
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen diff = timeval_diff_msecs(&ioloop_timeval, &tstream->last_read_timestamp);
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen /* we haven't reached the read timeout yet, update it */
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch tstream->to = timeout_add_to(io_stream_get_ioloop(iostream),
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen io_stream_set_error(&tstream->istream.iostream,
9766afd8dc3976d238e1c71712d6bafa316f2e06Timo Sirainen "Read timeout in %u.%03u s after %"PRIuUOFF_T" bytes%s",
a77d7cc71b6a1d66fa33516582890c2256516c26Timo Sirainen " (requested timeout in %u ms)", tstream->timeout_msecs));
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen tstream->istream.istream.stream_errno = ETIMEDOUT;
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen i_stream_set_input_pending(tstream->istream.parent, TRUE);
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainenstatic void i_stream_timeout_set_pending(struct timeout_istream *tstream)
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen /* make sure we get called again on the next ioloop run. this updates
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen the timeout to the timestamp where we actually would have wanted to
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen start waiting for more data (so if there is long-running code
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen outside the ioloop it's not counted) */
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen tstream->last_read_timestamp = ioloop_timeval;
29cda2d6eb57b7fb65a55115ea8bcb6ab6938477Timo Sirainen i_stream_set_input_pending(&tstream->istream.istream, TRUE);
854b4074ac77a138b3983d72510b4d8779d15040Timo Siraineni_stream_timeout_read(struct istream_private *stream)
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen struct timeout_istream *tstream = (struct timeout_istream *)stream;
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch struct iostream_private *iostream = &tstream->istream.iostream;
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen i_stream_seek(stream->parent, stream->parent_start_offset +
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen ret = i_stream_read_copy_from_parent(&stream->istream);
decdff03c32cb5d0e99d71c5678fd008714de70bTimo Sirainen io_stream_set_error(&tstream->istream.iostream,
decdff03c32cb5d0e99d71c5678fd008714de70bTimo Sirainen "%s (opened %d secs ago)",
8e0eb6a0cfc2cb66385bdf05a70a38d753bc1e24Timo Sirainen } else if (tstream->to == NULL && tstream->timeout_msecs > 0) {
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen /* first read. add the timeout here instead of in init
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen in case the stream is created long before it's actually
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen read from. */
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch tstream->to = timeout_add_to(io_stream_get_ioloop(iostream),
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen /* we read something, reset the timeout */
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen tstream->last_read_timestamp = ioloop_timeval;
854b4074ac77a138b3983d72510b4d8779d15040Timo Siraineni_stream_create_timeout(struct istream *input, unsigned int timeout_msecs)
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen tstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen tstream->istream.stream_size_passthrough = TRUE;
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen tstream->istream.read = i_stream_timeout_read;
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch tstream->istream.switch_ioloop_to = i_stream_timeout_switch_ioloop_to;
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen tstream->istream.iostream.close = i_stream_timeout_close;
25fb397382c6f7d39bfeee85774e7675f02bfb3cTimo Sirainen tstream->istream.istream.readable_fd = input->readable_fd;
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen tstream->istream.istream.blocking = input->blocking;
854b4074ac77a138b3983d72510b4d8779d15040Timo Sirainen tstream->istream.istream.seekable = input->seekable;