]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-h1: Enable TCP splicing to exchange data only
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 16 Apr 2019 14:46:36 +0000 (16:46 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 17 Apr 2019 12:52:31 +0000 (14:52 +0200)
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.

src/mux_h1.c

index b5e47c680dfb0c3020fd32172b8216fe604f2cad..c820ebe3cc7e9f562ef12db26f7f0bdcd154553a 100644 (file)
@@ -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)