BUG/MINOR: quic: Dropped retransmitted STREAM frames
It is possible that we continue to receive retransmitted STREAM frames after
the mux have been released. We rely on the ->rx.streams[].nb_streams counter
to check the stream was closed. If not, at this time we drop the packet.
diff --git a/src/xprt_quic.c b/src/xprt_quic.c
index a83fb0c..524c42d 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -2689,6 +2689,7 @@
case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
{
struct quic_stream *stream = &frm.stream;
+ unsigned nb_streams = qc->rx.strms[qcs_id_type(stream->id)].nb_streams;
if (qc_is_listener(ctx->qc)) {
if (stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT)
@@ -2696,12 +2697,17 @@
} else if (!(stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT))
goto err;
- /* The upper layer may not be allocated.
- *
- * TODO emit a CONNECTION_CLOSE if mux already freed.
- */
- if (qc->mux_state != QC_MUX_READY)
- goto err;
+ /* The upper layer may not be allocated. */
+ if (qc->mux_state != QC_MUX_READY) {
+ if ((stream->id >> QCS_ID_TYPE_SHIFT) < nb_streams) {
+ TRACE_PROTO("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
+ break;
+ }
+ else {
+ TRACE_PROTO("Stream not found", QUIC_EV_CONN_PRSHPKT, qc);
+ goto err;
+ }
+ }
if (!qc_handle_strm_frm(pkt, stream, qc))
goto err;