]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: handle partially received buffered stream frame
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 25 Feb 2022 16:36:31 +0000 (17:36 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 1 Mar 2022 09:52:31 +0000 (10:52 +0100)
Adjust the function to handle buffered STREAM frames. If the offset of
the frame was already fully received, discard the frame. If only
partially received, compute the difference and copy only the newly
offset.

Before this change, a buffered frame representing a fully or partially
received offset caused the loop to be interrupted. The frame was
preserved, thus preventing frames with greater offset to be handled.

This may fix some occurences of stalled transfer on the request channel
if there is out-of-order STREAM frames on the Rx path.

src/xprt_quic.c

index a1b89c771f96830cfd730dd5656a1dab97315e73..06bcbf6830f414511a27b2d247a9bf17c964a22e 100644 (file)
@@ -2023,11 +2023,21 @@ static size_t qc_treat_rx_strm_frms(struct qcs *qcs)
        while (frm_node) {
                int ret;
                struct quic_rx_strm_frm *frm;
+               size_t diff;
 
                frm = eb64_entry(&frm_node->node, struct quic_rx_strm_frm, offset_node);
-               if (frm->offset_node.key != qcs->rx.offset)
+               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;
+               }
+
+               diff = qcs->rx.offset - frm->offset_node.key;
+               frm->data += diff;
+               frm->len -= diff;
+
                ret = qc_rx_strm_frm_cpy(&qcs->rx.buf, frm);
                qcs->rx.offset += ret;
                total += ret;
@@ -2038,13 +2048,14 @@ static size_t qc_treat_rx_strm_frms(struct qcs *qcs)
                         * offset field.
                         */
                        eb64_delete(&frm->offset_node);
-                       frm->offset_node.key += ret;
+                       frm->offset_node.key += (diff + ret);
                        frm->data += ret;
                        frm->len -= ret;
                        eb64_insert(&qcs->rx.frms, &frm->offset_node);
                        break;
                }
 
+ next:
                frm_node = eb64_next(frm_node);
                quic_rx_packet_refdec(frm->pkt);
                eb64_delete(&frm->offset_node);