From: Christopher Faulet Date: Tue, 16 Apr 2019 14:46:36 +0000 (+0200) Subject: BUG/MEDIUM: mux-h1: Enable TCP splicing to exchange data only X-Git-Tag: v2.0-dev3~248 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e18777b79d7ac5a8e01e51a84addd453939f7ede;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: mux-h1: Enable TCP splicing to exchange data only Use the TCP splicing only when the input parser is in the state H1_MSG_DATA or H1_MSG_TUNNEL and don't transfer more than then known expected length for these data (unlimited for the tunnel mode). In other states or when all data are transferred, the TCP splicing is disabled. This patch must be backported to 1.9. --- diff --git a/src/mux_h1.c b/src/mux_h1.c index b5e47c680d..c820ebe3cc 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -2242,8 +2242,12 @@ static size_t h1_rcv_buf(struct conn_stream *cs, struct buffer *buf, size_t coun if (!(h1c->flags & H1C_F_IN_ALLOC)) ret = h1_process_input(h1c, buf, flags); - if (flags & CO_RFL_BUF_FLUSH) - h1s->flags |= H1S_F_BUF_FLUSH; + if (flags & CO_RFL_BUF_FLUSH) { + struct h1m *h1m = (!conn_is_back(cs->conn) ? &h1s->req : &h1s->res); + + if (h1m->state != H1_MSG_TUNNEL || (h1m->state == H1_MSG_DATA && h1m->curr_len)) + h1s->flags |= H1S_F_BUF_FLUSH; + } else if (ret > 0 || (h1s->flags & H1S_F_SPLICED_DATA)) { h1s->flags &= ~H1S_F_SPLICED_DATA; if (!(h1c->wait_event.events & SUB_RETRY_RECV)) @@ -2290,6 +2294,13 @@ static int h1_rcv_pipe(struct conn_stream *cs, struct pipe *pipe, unsigned int c struct h1m *h1m = (!conn_is_back(cs->conn) ? &h1s->req : &h1s->res); int ret = 0; + if ((h1m->state != H1_MSG_DATA && h1m->state != H1_MSG_TUNNEL) || + (h1m->state == H1_MSG_DATA && !h1m->curr_len)) { + h1s->flags &= ~(H1S_F_BUF_FLUSH|H1S_F_SPLICED_DATA); + cs->conn->xprt->subscribe(cs->conn, SUB_RETRY_RECV, &h1s->h1c->wait_event); + goto end; + } + if (b_data(&h1s->h1c->ibuf)) { h1s->flags |= H1S_F_BUF_FLUSH; goto end; @@ -2300,11 +2311,14 @@ static int h1_rcv_pipe(struct conn_stream *cs, struct pipe *pipe, unsigned int c if (h1m->state == H1_MSG_DATA && count > h1m->curr_len) count = h1m->curr_len; ret = cs->conn->xprt->rcv_pipe(cs->conn, pipe, count); - if (h1m->state == H1_MSG_DATA && ret > 0) + if (h1m->state == H1_MSG_DATA && ret > 0) { h1m->curr_len -= ret; + if (!h1m->curr_len) + h1s->flags &= ~(H1S_F_BUF_FLUSH|H1S_F_SPLICED_DATA); + } + end: return ret; - } static int h1_snd_pipe(struct conn_stream *cs, struct pipe *pipe)