istream-timeout.c revision 25fb397382c6f7d39bfeee85774e7675f02bfb3c
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2014-2015 Dovecot authors, see the included COPYING file */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void i_stream_timeout_close(struct iostream_private *stream,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct timeout_istream *tstream = (struct timeout_istream *)stream;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void i_stream_timeout_switch_ioloop(struct istream_private *stream)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct timeout_istream *tstream = (struct timeout_istream *)stream;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen tstream->to = io_loop_move_timeout(&tstream->to);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainenstatic void i_stream_timeout(struct timeout_istream *tstream)
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen unsigned int msecs;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* we came here after a long-running code. timeouts are handled
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen before IOs, so wait for i_stream_read() to be called again
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen before assuming that we've timed out. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen diff = timeval_diff_msecs(&ioloop_timeval, &tstream->last_read_timestamp);
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen /* we haven't reached the read timeout yet, update it */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tstream->to = timeout_add(tstream->timeout_msecs - diff,
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen io_stream_set_error(&tstream->istream.iostream,
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen "Read timeout in %u%s s after %"PRIuUOFF_T" bytes",
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen msecs == 0 ? "" : t_strdup_printf(".%u", msecs),
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tstream->istream.istream.stream_errno = ETIMEDOUT;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_set_input_pending(tstream->istream.parent, TRUE);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic void i_stream_timeout_set_pending(struct timeout_istream *tstream)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* make sure we get called again on the next ioloop run. this updates
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen the timeout to the timestamp where we actually would have wanted to
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen start waiting for more data (so if there is long-running code
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen outside the ioloop it's not counted) */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tstream->last_read_timestamp = ioloop_timeval;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_set_input_pending(&tstream->istream.istream, TRUE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Siraineni_stream_timeout_read(struct istream_private *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct timeout_istream *tstream = (struct timeout_istream *)stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_seek(stream->parent, stream->parent_start_offset +
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = i_stream_read_copy_from_parent(&stream->istream);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen io_stream_set_error(&tstream->istream.iostream,
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen "%s (opened %d secs ago)",
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen /* first read. add the timeout here instead of in init
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen in case the stream is created long before it's actually
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen read from. */
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen tstream->to = tstream->timeout_msecs == 0 ? NULL :
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen /* we read something, reset the timeout */
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen tstream->last_read_timestamp = ioloop_timeval;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Siraineni_stream_create_timeout(struct istream *input, unsigned int timeout_msecs)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen tstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tstream->istream.stream_size_passthrough = TRUE;
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen tstream->istream.read = i_stream_timeout_read;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tstream->istream.switch_ioloop = i_stream_timeout_switch_ioloop;
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen tstream->istream.iostream.close = i_stream_timeout_close;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen tstream->istream.istream.readable_fd = input->readable_fd;
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen tstream->istream.istream.blocking = input->blocking;
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen tstream->istream.istream.seekable = input->seekable;