From fe2d5b11f4aec0c8effd4ec4a2c9c1f07a9dc919 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 7 Dec 2020 18:21:27 +0100 Subject: [PATCH] BUG/MINOR: mux-h1: Don't set CS_FL_EOI too early for protocol upgrade requests When a protocol upgrade request is received, once parsed, it is waiting for the response in the DONE state. But we must not set the flag CS_FL_EOI because we don't know if a protocol upgrade will be performed or not. Now, it is set on the response path, if both sides reached the DONE state. If a protocol upgrade is finally performed, both side are switched in TUNNEL state. Thus the CS_FL_EOI flag is not set. If backported, this patch must be adapted because for now it relies on last 2.4-dev changes. It may be backported as far as 2.0. (cherry picked from commit 3e1748bbf30bc06407bda36517c00c0b97bfeb50) [cf: context adjustment] Signed-off-by: Christopher Faulet --- src/mux_h1.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/mux_h1.c b/src/mux_h1.c index cc34bba..c6c15c2 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -1410,7 +1410,11 @@ static size_t h1_process_eom(struct h1s *h1s, struct h1m *h1m, struct htx *htx, } h1s->flags |= H1S_F_PARSING_DONE; - h1s->cs->flags |= CS_FL_EOI; + /* Don't set EOI on the conn-stream for protocol upgrade requests, wait + * the response to do so or not depending on the status code. + */ + if (!(h1m->flags & H1_MF_CONN_UPG)) + h1s->cs->flags |= CS_FL_EOI; end: TRACE_LEAVE(H1_EV_RX_DATA|H1_EV_RX_EOI, h1s->h1c->conn, h1s, 0, (size_t[]){ret}); return ret; @@ -1543,7 +1547,7 @@ static size_t h1_process_input(struct h1c *h1c, struct buffer *buf, size_t count h1s->cs->flags |= CS_FL_RCV_MORE | CS_FL_WANT_ROOM; else if (h1s->flags & H1S_F_REOS) { h1s->cs->flags |= CS_FL_EOS; - if (h1m->state == H1_MSG_TUNNEL) + if (h1m->state >= H1_MSG_DONE) h1s->cs->flags |= CS_FL_EOI; else if (h1m->state > H1_MSG_LAST_LF && h1m->state < H1_MSG_DONE) h1s->cs->flags |= CS_FL_ERROR; @@ -1989,6 +1993,13 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun htx_to_buf(chn_htx, buf); out: + /* Both the request and the response reached the DONE state. So set EOI + * flag on the conn-stream. Most of time, the flag will already be set, + * except for protocol upgrades. + */ + if (h1s->cs && h1s->req.state == H1_MSG_DONE && h1s->res.state == H1_MSG_DONE) + h1s->cs->flags |= CS_FL_EOI; + if (!buf_room_for_htx_data(&h1c->obuf)) { TRACE_STATE("h1c obuf full", H1_EV_TX_DATA|H1_EV_H1S_BLK, h1c->conn, h1s); h1c->flags |= H1C_F_OUT_FULL; -- 1.7.10.4