]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: mux-h1: Don't expect data from server as long as request is unfinished
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 23 Feb 2023 12:58:13 +0000 (13:58 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 27 Feb 2023 16:45:45 +0000 (17:45 +0100)
On client side, as long as the request is unfinished, the H1 stream states
it does not expect data from the server. It does not mean the server must
not send its response but only it may wait to receive the whole request with
no risk to trigger a read timeout.

When the request is finished, the H1 stream reports it expects to receive
data from the opposite endpoint.

The purpose of this patch is to never report a server timeout on receive if
the client is still uploading data. This way, it is possible to have a
smaller server timeout than the client one.

src/mux_h1.c

index adf4569f7d3d2138920996065b8c9c75821bfacc..f9bd1d88b9a180fb67e400c427c62f375bf76ea4 100644 (file)
@@ -782,7 +782,12 @@ static struct h1s *h1c_frt_stream_new(struct h1c *h1c, struct stconn *sc, struct
                h1s->sd->conn   = h1c->conn;
                se_fl_set(h1s->sd, SE_FL_T_MUX | SE_FL_ORPHAN);
        }
-
+       /* When a request starts, the H1S does not expect data while the request
+        * is not finished. It does not mean the response must not be received,
+        * especially if headers were already forwarded. But it is not
+        * mandatory.
+        */
+       se_expect_no_data(h1s->sd);
        h1s->sess = sess;
 
        if (h1c->px->options2 & PR_O2_REQBUG_OK)
@@ -1774,6 +1779,13 @@ static size_t h1_process_demux(struct h1c *h1c, struct buffer *buf, size_t count
                        TRACE_USER((!(h1m->flags & H1_MF_RESP) ? "H1 request fully rcvd" : "H1 response fully rcvd"),
                                   H1_EV_RX_DATA|H1_EV_RX_EOI, h1c->conn, h1s, htx);
 
+                       if (!(h1c->flags & H1C_F_IS_BACK)) {
+                               /* The request was fully received. It means the H1S now
+                                * expect data from the opposite side
+                                */
+                               se_expect_data(h1s->sd);
+                       }
+
                        if ((h1m->flags & H1_MF_RESP) &&
                            ((h1s->meth == HTTP_METH_CONNECT && h1s->status >= 200 && h1s->status < 300) || h1s->status == 101))
                                h1_set_tunnel_mode(h1s);
@@ -3783,6 +3795,14 @@ static int h1_rcv_pipe(struct stconn *sc, struct pipe *pipe, unsigned int count)
                        if (!h1m->curr_len) {
                                h1m->state = H1_MSG_DONE;
                                h1c->flags &= ~H1C_F_WANT_SPLICE;
+
+                               if (!(h1c->flags & H1C_F_IS_BACK)) {
+                                       /* The request was fully received. It means the H1S now
+                                        * expect data from the opposite side
+                                        */
+                                       se_expect_data(h1s->sd);
+                               }
+
                                TRACE_STATE("payload fully received", H1_EV_STRM_RECV, h1c->conn, h1s);
                        }
                }