diff --git a/include/haproxy/channel.h b/include/haproxy/channel.h index 17dd75fba..1b5c8a06f 100644 --- a/include/haproxy/channel.h +++ b/include/haproxy/channel.h @@ -818,6 +818,69 @@ static inline size_t channel_empty(const struct channel *chn) return (IS_HTX_STRM(chn) ? htx_is_empty(htxbuf(&chn->buf)) : c_empty(chn)); } +/* Check channel's last_read date against the idle timeer to verify the producer + * is still streaming data or not + */ +static inline void channel_check_idletimer(struct channel *chn) +{ + if ((chn->flags & (CF_STREAMER | CF_STREAMER_FAST)) && !co_data(chn) && + global.tune.idle_timer && + (unsigned short)(now_ms - chn->last_read) >= global.tune.idle_timer) { + /* The buffer was empty and nothing was transferred for more + * than one second. This was caused by a pause and not by + * congestion. Reset any streaming mode to reduce latency. + */ + chn->xfer_small = 0; + chn->xfer_large = 0; + chn->flags &= ~(CF_STREAMER | CF_STREAMER_FAST); + } +} + +/* Check amount of transferred data after a receive. If is greater + * than 0, the date is updated and STREAMER flags for the channels + * are verified. + */ +static inline void channel_check_xfer(struct channel *chn, size_t xferred) +{ + if (!xferred) + return; + + if ((chn->flags & (CF_STREAMER | CF_STREAMER_FAST)) && + (xferred <= c_size(chn) / 2)) { + chn->xfer_large = 0; + chn->xfer_small++; + if (chn->xfer_small >= 3) { + /* we have read less than half of the buffer in + * one pass, and this happened at least 3 times. + * This is definitely not a streamer. + */ + chn->flags &= ~(CF_STREAMER | CF_STREAMER_FAST); + } + else if (chn->xfer_small >= 2) { + /* if the buffer has been at least half full twchne, + * we receive faster than we send, so at least it + * is not a "fast streamer". + */ + chn->flags &= ~CF_STREAMER_FAST; + } + } + else if (!(chn->flags & CF_STREAMER_FAST) && (xferred >= channel_data_limit(chn))) { + /* we read a full buffer at once */ + chn->xfer_small = 0; + chn->xfer_large++; + if (chn->xfer_large >= 3) { + /* we call this buffer a fast streamer if it manages + * to be filled in one call 3 consecutive times. + */ + chn->flags |= (CF_STREAMER | CF_STREAMER_FAST); + } + } + else { + chn->xfer_small = 0; + chn->xfer_large = 0; + } + chn->last_read = now_ms; +} /* Returns the amount of bytes that can be written over the input data at once, * including reserved space which may be overwritten. This is used by Lua to diff --git a/src/stconn.c b/src/stconn.c index 63dd9bf1f..b3aed9521 100644 --- a/src/stconn.c +++ b/src/stconn.c @@ -1251,17 +1251,7 @@ int sc_conn_recv(struct stconn *sc) /* prepare to detect if the mux needs more room */ sc_ep_clr(sc, SE_FL_WANT_ROOM); - if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) && !co_data(ic) && - global.tune.idle_timer && - (unsigned short)(now_ms - ic->last_read) >= global.tune.idle_timer) { - /* The buffer was empty and nothing was transferred for more - * than one second. This was caused by a pause and not by - * congestion. Reset any streaming mode to reduce latency. - */ - ic->xfer_small = 0; - ic->xfer_large = 0; - ic->flags &= ~(CF_STREAMER | CF_STREAMER_FAST); - } + channel_check_idletimer(ic); #if defined(USE_LINUX_SPLICE) /* Detect if the splicing is possible depending on the stream policy */ @@ -1447,41 +1437,7 @@ int sc_conn_recv(struct stconn *sc) if (!cur_read) se_have_no_more_data(sc->sedesc); else { - if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) && - (cur_read <= ic->buf.size / 2)) { - ic->xfer_large = 0; - ic->xfer_small++; - if (ic->xfer_small >= 3) { - /* we have read less than half of the buffer in - * one pass, and this happened at least 3 times. - * This is definitely not a streamer. - */ - ic->flags &= ~(CF_STREAMER | CF_STREAMER_FAST); - } - else if (ic->xfer_small >= 2) { - /* if the buffer has been at least half full twice, - * we receive faster than we send, so at least it - * is not a "fast streamer". - */ - ic->flags &= ~CF_STREAMER_FAST; - } - } - else if (!(ic->flags & CF_STREAMER_FAST) && (cur_read >= channel_data_limit(ic))) { - /* we read a full buffer at once */ - ic->xfer_small = 0; - ic->xfer_large++; - if (ic->xfer_large >= 3) { - /* we call this buffer a fast streamer if it manages - * to be filled in one call 3 consecutive times. - */ - ic->flags |= (CF_STREAMER | CF_STREAMER_FAST); - } - } - else { - ic->xfer_small = 0; - ic->xfer_large = 0; - } - ic->last_read = now_ms; + channel_check_xfer(ic, cur_read); sc_ep_report_read_activity(sc); }