From f9cb3a9b0e89074537878fc5dc93d2317a8095a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Thu, 2 Dec 2021 11:25:58 +0100 Subject: [PATCH] MINOR: quic: RX buffer full due to wrong CRYPTO data handling Do not leave in the RX buffer packets with CRYPTO data which were already received. We do this when parsing CRYPTO frame. If already received we must not consider such frames as if they were not received in order! This had as side effect to interrupt the transfer of long streams (ACK frames not parsed). --- src/xprt_quic.c | 69 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/src/xprt_quic.c b/src/xprt_quic.c index d70be2cc5..2809de92d 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -2230,35 +2230,66 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct break; } case QUIC_FT_CRYPTO: - if (frm.crypto.offset != qel->rx.crypto.offset) { - struct quic_rx_crypto_frm *cf; + { + struct quic_rx_crypto_frm *cf; - cf = pool_alloc(pool_head_quic_rx_crypto_frm); - if (!cf) { - TRACE_DEVEL("CRYPTO frame allocation failed", - QUIC_EV_CONN_PRSHPKT, ctx->conn); - goto err; + if (unlikely(frm.crypto.offset < qel->rx.crypto.offset)) { + if (frm.crypto.offset + frm.crypto.len <= qel->rx.crypto.offset) { + /* XXX TO DO: is used only for the traces. */ + struct quic_rx_crypto_frm cfdebug = { }; + + cfdebug.offset_node.key = frm.crypto.offset; + cfdebug.len = frm.crypto.len; + /* Nothing to do */ + TRACE_PROTO("Already received CRYPTO data", + QUIC_EV_CONN_ELRXPKTS, ctx->conn, pkt, &cfdebug); + break; } + else { + size_t diff = qel->rx.crypto.offset - frm.crypto.offset; + /* XXX TO DO: is used only for the traces. */ + struct quic_rx_crypto_frm cfdebug = { }; - cf->offset_node.key = frm.crypto.offset; - cf->len = frm.crypto.len; - cf->data = frm.crypto.data; - cf->pkt = pkt; - eb64_insert(&qel->rx.crypto.frms, &cf->offset_node); - quic_rx_packet_refinc(pkt); + cfdebug.offset_node.key = frm.crypto.offset; + cfdebug.len = frm.crypto.len; + TRACE_PROTO("Partially already received CRYPTO data", + QUIC_EV_CONN_ELRXPKTS, ctx->conn, pkt, &cfdebug); + frm.crypto.len -= diff; + frm.crypto.data += diff; + frm.crypto.offset = qel->rx.crypto.offset; + } } - else { - /* XXX TO DO: is used only for the traces. */ - struct quic_rx_crypto_frm cf = { }; - cf.offset_node.key = frm.crypto.offset; - cf.len = frm.crypto.len; + if (frm.crypto.offset == qel->rx.crypto.offset) { + /* XXX TO DO: is used only for the traces. */ + struct quic_rx_crypto_frm cfdebug = { }; + + cfdebug.offset_node.key = frm.crypto.offset; + cfdebug.len = frm.crypto.len; if (!qc_provide_cdata(qel, ctx, frm.crypto.data, frm.crypto.len, - pkt, &cf)) + pkt, &cfdebug)) goto err; + + break; } + + /* frm.crypto.offset > qel->rx.crypto.offset */ + cf = pool_alloc(pool_head_quic_rx_crypto_frm); + if (!cf) { + TRACE_DEVEL("CRYPTO frame allocation failed", + QUIC_EV_CONN_PRSHPKT, ctx->conn); + goto err; + } + + cf->offset_node.key = frm.crypto.offset; + cf->len = frm.crypto.len; + cf->data = frm.crypto.data; + cf->pkt = pkt; + eb64_insert(&qel->rx.crypto.frms, &cf->offset_node); + quic_rx_packet_refinc(pkt); break; + } case QUIC_FT_STREAM_8: case QUIC_FT_STREAM_9: case QUIC_FT_STREAM_A: