MEDIUM: quic: do not ack packet with invalid STREAM

If the MUX cannot handle immediately nor buffer a STREAM frame, the
packet containing it must not be acknowledge. This is in conformance
with the RFC9000.

qcc_recv() return codes have been adjusted to differentiate an invalid
frame with an already fully received offset which must be acknowledged.
This commit is contained in:
Amaury Denoyelle 2022-04-29 15:58:22 +02:00
parent d46e335683
commit 74cf237ecd
2 changed files with 23 additions and 6 deletions

View File

@ -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. <done>
* 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. */

View File

@ -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