diff --git a/src/mux_quic.c b/src/mux_quic.c index 2e5ebdc9f..db32de146 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -345,7 +345,7 @@ struct qcs *qcc_get_qcs(struct qcc *qcc, uint64_t id) * to process the frame content. * * Returns a code indicating how the frame was handled. - * - 0: frame received completly and can be dropped. + * - 0: frame received completely and can be dropped. * - 1: frame not received but can be dropped. * - 2: frame cannot be handled, either partially or not at all. * indicated the number of bytes handled. The rest should be buffered. @@ -374,7 +374,7 @@ int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset, if (offset + len <= qcs->rx.offset) { TRACE_DEVEL("leaving on already received offset", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV, qcc->conn, qcs); - return 1; + return 0; } /* Last frame already handled for this stream. */ diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 844aa13ea..3a069df93 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -2255,14 +2255,16 @@ static int qc_handle_bidi_strm_frm(struct quic_rx_packet *pkt, strm_frm->offset.key, strm_frm->fin, (char *)strm_frm->data, &qcs, &done); - /* invalid or already received frame */ + /* invalid frame */ if (ret == 1) + return 0; + + /* already fully received offset */ + if (ret == 0 && done == 0) return 1; + /* frame not handled (partially or completely) must be buffered */ if (ret == 2) { - /* frame cannot be parsed at the moment and should be - * buffered. - */ frm = new_quic_rx_strm_frm(strm_frm, pkt); if (!frm) { TRACE_PROTO("Could not alloc RX STREAM frame", @@ -2270,6 +2272,7 @@ static int qc_handle_bidi_strm_frm(struct quic_rx_packet *pkt, return 0; } + /* frame partially handled by the MUX */ if (done) { BUG_ON(done >= frm->len); /* must never happen */ frm->len -= done; @@ -2305,6 +2308,8 @@ static int qc_handle_bidi_strm_frm(struct quic_rx_packet *pkt, frm->offset_node.key, frm->fin, (char *)frm->data, &qcs, &done); + BUG_ON(ret == 1); /* must never happen for buffered frames */ + /* interrupt the parsing if the frame cannot be handled * entirely for the moment only. */ @@ -2423,10 +2428,22 @@ static int qc_handle_uni_strm_frm(struct quic_rx_packet *pkt, return 1; } +/* Returns 1 on success or 0 on error. On error, the packet containing the + * frame must not be acknowledged. + */ static inline int qc_handle_strm_frm(struct quic_rx_packet *pkt, struct quic_stream *strm_frm, struct quic_conn *qc) { + /* RFC9000 13.1. Packet Processing + * + * A packet MUST NOT be acknowledged until packet protection has been + * successfully removed and all frames contained in the packet have + * been processed. For STREAM frames, this means the data has been + * enqueued in preparation to be received by the application protocol, + * but it does not require that data be delivered and consumed. + */ + if (strm_frm->id & QCS_ID_DIR_BIT) return qc_handle_uni_strm_frm(pkt, strm_frm, qc); else