]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-quic: simplify sending of empty STREAM FIN
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 21 Oct 2024 08:28:18 +0000 (10:28 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 21 Oct 2024 09:21:07 +0000 (11:21 +0200)
An empty STREAM frame can be emitted by QUIC MUX to notify about a
delayed FIN when there is no data left to transmit. This requires a
tedious comparison on stream offset in qmux_ctrl_send() to ensure an
empty stream frame is not always considered as retransmitted, which is
necessary to locally close the QCS instance.

Simplify this by unsubscribe from streamdesc layer when the QCS is
locally closed on FIN transmission notification. This prevents all
future retransmitted frames to be reported to the QCS instance,
especially any potentially retransmitted empty FIN.

src/mux_quic.c

index ac2c491e3d9b28582eac0be7a67cf5987eaeb3c1..ea8c38b5f7679cb1717a8e45be4920b8acb16d6f 100644 (file)
@@ -563,15 +563,19 @@ static void qmux_ctrl_send(struct qc_stream_desc *stream, uint64_t data, uint64_
        /* Real off MUST always be the greatest offset sent. */
        BUG_ON(offset > qcs->tx.fc.off_real);
 
-       /* check if the STREAM frame has already been notified. It can happen
-        * for retransmission. Special care must be taken to ensure an empty
-        * STREAM frame with FIN set is not considered as retransmitted
+       /* Check if the STREAM frame has already been notified. An empty FIN
+        * frame must not be considered retransmitted.
         */
-       if (offset + data < qcs->tx.fc.off_real || (!data && !(qcs->flags & QC_SF_FIN_STREAM))) {
+       if (data && offset + data <= qcs->tx.fc.off_real) {
                TRACE_DEVEL("offset already notified", QMUX_EV_QCS_SEND, qcc->conn, qcs);
                goto out;
        }
 
+       /* An empty STREAM frame is only used to notify FIN. A retransmitted
+        * empty FIN cannot be notified as QCS will be unsubscribed first.
+        */
+       BUG_ON(!data && !(qcs->flags & QC_SF_FIN_STREAM));
+
        qcs_idle_open(qcs);
 
        diff = offset + data - qcs->tx.fc.off_real;
@@ -622,6 +626,9 @@ static void qmux_ctrl_send(struct qc_stream_desc *stream, uint64_t data, uint64_
                                /* Reset flag to not emit multiple FIN STREAM frames. */
                                qcs->flags &= ~QC_SF_FIN_STREAM;
                        }
+
+                       /* Unsubscribe from streamdesc when everything sent. */
+                       qc_stream_desc_sub_send(qcs->stream, NULL);
                }
        }