From 8dedeb62b7fb086bb20e8ccc622cbf294eceae6b Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 26 Sep 2024 18:24:39 +0200 Subject: [PATCH] TMP --- src/quic_rx.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/src/quic_rx.c b/src/quic_rx.c index 4562e822b..d74764977 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -324,13 +324,81 @@ static void qc_handle_newly_acked_frm(struct quic_conn *qc, struct quic_frame *f qc_release_frm(qc, frm); } else { - //eb64_insert(&stream->acked_frms, &strm_frm->offset); + struct eb64_node *less, *more; + struct qf_stream *less_strm = NULL, *more_strm = NULL; struct qc_stream_buf *stream_buf; struct eb64_node *buf_node; buf_node = eb64_lookup_le(&stream->buf_tree, offset); stream_buf = eb64_entry(buf_node, struct qc_stream_buf, offset_node); - eb64_insert(&stream_buf->acked_frms, &strm_frm->offset); + + more = eb64_lookup_ge(&stream_buf->acked_frms, strm_frm->offset.key); + if (more) + more_strm = eb64_entry(more, struct qf_stream, offset); + + less = eb64_lookup_le(&stream_buf->acked_frms, strm_frm->offset.key); + if (less && more != less) + less_strm = eb64_entry(less, struct qf_stream, offset); + + if ((more_strm && + strm_frm->offset.key == more_strm->offset.key && + strm_frm->offset.key + strm_frm->len <= more_strm->offset.key + more_strm->len) || + (less_strm && + strm_frm->offset.key + strm_frm->len <= less_strm->offset.key + less_strm->len)) { + /* A frame was already buffered which covered + * the same range or more. Discard the current + * frame. + */ + TRACE_DEVEL("already covered stream range", QUIC_EV_CONN_ACKSTRM, qc); + qc_release_frm(qc, frm); + } + else { + /* Loop until there is no overlap between current frame and a next entry. */ + while (more_strm && + strm_frm->offset.key + strm_frm->len >= more_strm->offset.key) { + struct quic_frame *more_frm; + struct eb64_node *next; + + more_frm = container_of(more_strm, struct quic_frame, stream); + if (strm_frm->offset.key + strm_frm->len < more_strm->offset.key + more_strm->len) { + /* Extend current frame to cover next entry. */ + strm_frm->len += (more_strm->offset.key + more_strm->len) - + (strm_frm->offset.key + strm_frm->len); + if (more_frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT) + frm->type |= QUIC_STREAM_FRAME_TYPE_FIN_BIT; + } + + /* Remove next entry as it is covered by current frame. */ + TRACE_DEVEL("removing overlapping stream range", QUIC_EV_CONN_ACKSTRM, qc); + next = eb64_next(more); + eb64_delete(more); + qc_release_frm(qc, more_frm); + + more = next; + more_strm = more ? eb64_entry(more, struct qf_stream, offset) : NULL; + } + + /* Check if there is overlap between current frame and a previous entry. */ + if (less_strm && + less_strm->offset.key + less_strm->len >= strm_frm->offset.key) { + struct quic_frame *less_frm; + + /* Extend previous entry to cover fully the current frame. */ + less_strm->len += (strm_frm->offset.key + strm_frm->len) - + (less_strm->offset.key + less_strm->len); + + less_frm = container_of(less_strm, struct quic_frame, stream); + if (frm->type & QUIC_STREAM_FRAME_TYPE_FIN_BIT) + less_frm->type |= QUIC_STREAM_FRAME_TYPE_FIN_BIT; + + /* Discard current frame. */ + TRACE_DEVEL("using smaller overlapping stream range, discard current frame", QUIC_EV_CONN_ACKSTRM, qc); + qc_release_frm(qc, frm); + } + else { + eb64_insert(&stream_buf->acked_frms, &strm_frm->offset); + } + } } } break;