From: Amaury Denoyelle Date: Mon, 28 Feb 2022 10:38:36 +0000 (+0100) Subject: BUG/MINOR: quic: support FIN on Rx-buffered STREAM frames X-Git-Tag: v2.6-dev3~92 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3c4303998fd1b59f1f404ba166bde43fbfa24b7b;p=thirdparty%2Fhaproxy.git BUG/MINOR: quic: support FIN on Rx-buffered STREAM frames FIN flag on a STREAM frame was not detected if the frame was previously buffered on qcs.rx.frms before being handled. To fix this, copy the fin field from the quic_stream instance to quic_rx_strm_frm. This is required to properly notify the FIN flag on qc_treat_rx_strm_frms for the MUX layer. Without this fix, the request channel might be left opened after the last STREAM frame reception if there is out-of-order frames on the Rx path. --- diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index ace547634e..773c2fe966 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -496,6 +496,7 @@ struct quic_rx_strm_frm { struct eb64_node offset_node; uint64_t len; const unsigned char *data; + int fin; struct quic_rx_packet *pkt; }; diff --git a/src/xprt_quic.c b/src/xprt_quic.c index aaace9c124..d69bbf54f8 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -1964,6 +1964,7 @@ struct quic_rx_strm_frm *new_quic_rx_strm_frm(struct quic_stream *stream_frm, frm->len = stream_frm->len; frm->data = stream_frm->data; frm->pkt = pkt; + frm->fin = stream_frm->fin; } return frm; @@ -2026,14 +2027,15 @@ static size_t qc_treat_rx_strm_frms(struct qcs *qcs) size_t diff; frm = eb64_entry(&frm_node->node, struct quic_rx_strm_frm, offset_node); - if (frm->offset_node.key > qcs->rx.offset) - break; - if (frm->offset_node.key + frm->len < qcs->rx.offset) { /* fully already received STREAM offset */ goto next; } + BUG_ON(qcs->flags & QC_SF_FIN_RECV); + if (frm->offset_node.key > qcs->rx.offset) + break; + diff = qcs->rx.offset - frm->offset_node.key; frm->data += diff; frm->len -= diff; @@ -2055,6 +2057,9 @@ static size_t qc_treat_rx_strm_frms(struct qcs *qcs) break; } + if (frm->fin) + qcs->flags |= QC_SF_FIN_RECV; + next: frm_node = eb64_next(frm_node); quic_rx_packet_refdec(frm->pkt); @@ -2117,11 +2122,12 @@ static int qc_handle_bidi_strm_frm(struct quic_rx_packet *pkt, strm->rx.offset += ret; } - total += qc_treat_rx_strm_frms(strm); /* FIN is set only if all data were copied. */ if (strm_frm->fin && !strm_frm->len) strm->flags |= QC_SF_FIN_RECV; + total += qc_treat_rx_strm_frms(strm); + if (total && qc->qcc->app_ops->decode_qcs(strm, strm->flags & QC_SF_FIN_RECV, qc->qcc->ctx) < 0) { TRACE_PROTO("Decoding error", QUIC_EV_CONN_PSTRM, qc); return 0;