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.
This commit is contained in:
Christopher Faulet 2023-02-23 13:58:13 +01:00
parent 59b240c30c
commit f4b89f162a

View File

@ -782,7 +782,12 @@ static struct h1s *h1c_frt_stream_new(struct h1c *h1c, struct stconn *sc, struct
h1s->sd->conn = h1c->conn; h1s->sd->conn = h1c->conn;
se_fl_set(h1s->sd, SE_FL_T_MUX | SE_FL_ORPHAN); 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; h1s->sess = sess;
if (h1c->px->options2 & PR_O2_REQBUG_OK) 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"), 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); 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) && if ((h1m->flags & H1_MF_RESP) &&
((h1s->meth == HTTP_METH_CONNECT && h1s->status >= 200 && h1s->status < 300) || h1s->status == 101)) ((h1s->meth == HTTP_METH_CONNECT && h1s->status >= 200 && h1s->status < 300) || h1s->status == 101))
h1_set_tunnel_mode(h1s); 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) { if (!h1m->curr_len) {
h1m->state = H1_MSG_DONE; h1m->state = H1_MSG_DONE;
h1c->flags &= ~H1C_F_WANT_SPLICE; 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); TRACE_STATE("payload fully received", H1_EV_STRM_RECV, h1c->conn, h1s);
} }
} }