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