]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mux-h1: Fix condition to set EOI on SE during zero-copy forwarding
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 2 Oct 2024 07:25:28 +0000 (09:25 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 2 Oct 2024 08:22:51 +0000 (10:22 +0200)
During zero-copy data forwarding, the producer must set the EOI flag on the SE
when end of the message is reached. It is already done but there is a case where
this flag is set while it should not. When a request wants to perform a protocol
upgrade and it is waiting for the server response, the flag must not be set
because the HTTP message is finished but some data are possibly still expected,
depending on the server response. On a 101-switching-protocol, more data will be
sent because the producer is switch to TUNNEL state.

So, now, the right condition is used. In DONE state, SE_FL_EOI flag is set on the sedesc iff:

  - it is the response
  - it is the request and the response is also in DONNE state
  - it is a request but no a protocol upgrade nor a CONNECT

This patch must be backported as far as 2.9.

src/mux_h1.c

index 6535d703c32882261f10fcccb6d7731131d26a4a..8fc33a9d899b2a193bd628958f2777c1c50f81e9 100644 (file)
@@ -5004,11 +5004,18 @@ static int h1_fastfwd(struct stconn *sc, unsigned int count, unsigned int flags)
                h1m->curr_len -= total;
                if (!h1m->curr_len) {
                        if (h1m->flags & H1_MF_CLEN) {
+                               /* Set EOI on stream connector in DONE state iff:
+                                *  - it is a response
+                                *  - it is a request and the response is DONE too
+                                *  - it is a request but no a protocol upgrade nor a CONNECT
+                                *
+                                * If not set, Wait the response to do so or not depending on the status
+                                * code.
+                                */
                                h1m->state = H1_MSG_DONE;
-                               se_fl_set(h1s->sd, SE_FL_EOI); /* TODO: this line is tricky and must be evaluated first
-                                                               *       Its purpose is to avoid to set CO_SFL_MSG_MORE on the
-                                                               *       next calls to ->complete_fastfwd().
-                                                               */
+                               if ((h1m->flags & H1_MF_RESP) || (h1s->res.state == H1_MSG_DONE) ||
+                                   ((h1s->meth != HTTP_METH_CONNECT) && !(h1m->flags & H1_MF_CONN_UPG)))
+                                       se_fl_set(h1s->sd, SE_FL_EOI);
                        }
                        else
                                h1m->state = H1_MSG_CHUNK_CRLF;