From: Christopher Faulet Date: Thu, 23 Feb 2023 12:58:13 +0000 (+0100) Subject: MEDIUM: mux-h1: Don't expect data from server as long as request is unfinished X-Git-Tag: v2.8-dev5~89 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f4b89f162a6c2917050b0ca3ae5e40621874a626;p=thirdparty%2Fhaproxy.git MEDIUM: mux-h1: Don't expect data from server as long as request is unfinished 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. --- diff --git a/src/mux_h1.c b/src/mux_h1.c index adf4569f7d..f9bd1d88b9 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -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); } }