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 ace5476..773c2fe 100644
--- a/include/haproxy/xprt_quic-t.h
+++ b/include/haproxy/xprt_quic-t.h
@@ -496,6 +496,7 @@
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 aaace9c..d69bbf5 100644
--- a/src/xprt_quic.c
+++ b/src/xprt_quic.c
@@ -1964,6 +1964,7 @@
frm->len = stream_frm->len;
frm->data = stream_frm->data;
frm->pkt = pkt;
+ frm->fin = stream_frm->fin;
}
return frm;
@@ -2026,14 +2027,15 @@
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 @@
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 @@
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;