]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3: abort read on unknown uni stream
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 24 May 2022 15:22:07 +0000 (17:22 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 25 May 2022 13:41:25 +0000 (15:41 +0200)
As specified by HTTP/3 draft, an unknown unidirectional stream can be
aborted. To do this, use a new flag QC_SF_READ_ABORTED. When the MUX
detects this flag, QCS instance is automatically freed.

Previously, such streams were instead automatically drained. By aborting
them, we economize some useless memcpy instruction. On future data
reception, QCS instance is not found in the tree and considered as
already closed. The frame payload is thus deleted without copying it.

include/haproxy/mux_quic-t.h
src/h3.c
src/mux_quic.c

index fca28f7faf49b62c270d593350c4cf827417bf25..40f784c3192f66dba2fd3b829334edd379543b12 100644 (file)
@@ -100,6 +100,7 @@ struct qcc {
 #define QC_SF_DETACH            0x00000008  /* cs is detached but there is remaining data to send */
 #define QC_SF_BLK_SFCTL         0x00000010  /* stream blocked due to stream flow control limit */
 #define QC_SF_DEM_FULL          0x00000020  /* demux blocked on request channel buffer full */
+#define QC_SF_READ_ABORTED      0x00000040  /* stream rejected by app layer */
 
 struct qcs {
        struct qcc *qcc;
index a792851abb6e4ccc84e3ee69bf87c65af1a2d0c9..3fb6942b8e836b443961836cab7968526c85ff74 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -144,8 +144,13 @@ static int h3_init_uni_stream(struct h3c *h3c, struct qcs *qcs,
                break;
 
        default:
-               h3s->flags |= H3_SF_UNI_NO_H3;
-               break;
+               /* draft-ietf-quic-http34 9. Extensions to HTTP/3
+                *
+                * Implementations MUST [...] abort reading on unidirectional
+                * streams that have unknown or unsupported types.
+                */
+               qcs->flags |= QC_SF_READ_ABORTED;
+               return 1;
        };
 
        h3s->flags |= H3_SF_UNI_INIT;
@@ -175,10 +180,10 @@ static int h3_parse_uni_stream_no_h3(struct qcs *qcs, struct ncbuf *rxbuf)
                if (!qpack_decode_enc(qcs, NULL))
                        return 1;
                break;
+       case H3S_T_UNKNOWN:
        default:
-               /* unknown uni stream : just consume it. */
-               qcs_consume(qcs, ncb_data(rxbuf, 0));
-               break;
+               /* Unknown stream should be flagged with QC_SF_READ_ABORTED. */
+               ABORT_NOW();
        }
 
        return 0;
index c47e83a2c2da602b858a6dc2f75f2a8bb60356db..b7d1e17f43261681c56e1323230905beaefd1ac2 100644 (file)
@@ -584,6 +584,11 @@ int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
        if (ncb_data(&qcs->rx.ncbuf, 0) && !(qcs->flags & QC_SF_DEM_FULL))
                qcc_decode_qcs(qcc, qcs);
 
+       if (qcs->flags & QC_SF_READ_ABORTED) {
+               /* TODO should send a STOP_SENDING */
+               qcs_free(qcs);
+       }
+
        TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn);
        return 0;
 }
@@ -1192,6 +1197,11 @@ static int qc_recv(struct qcc *qcc)
 
                qcc_decode_qcs(qcc, qcs);
                node = eb64_next(node);
+
+               if (qcs->flags & QC_SF_READ_ABORTED) {
+                       /* TODO should send a STOP_SENDING */
+                       qcs_free(qcs);
+               }
        }
 
        TRACE_LEAVE(QMUX_EV_QCC_RECV);