]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-quic: filter send/receive-only streams on frame parsing
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 6 Jul 2022 13:43:21 +0000 (15:43 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 11 Jul 2022 14:24:03 +0000 (16:24 +0200)
Extend the function qcc_get_qcs() to be able to filter send/receive-only
unidirectional streams. A connection error STREAM_STATE_ERROR is emitted
if this new filter does not match.

This will be useful when various frames handlers are converted with
qcc_get_qcs(). Depending on the frame type, it will be easy to filter on
the forbidden stream types as specified in RFC 9000.

src/mux_quic.c

index 0263c07a6383091f579249cbc41971af06144c86..90d7945c530feddc5b1c73cbc3a8082ab0e4880c 100644 (file)
@@ -430,17 +430,31 @@ static int qcc_stream_id_is_closed(struct qcc *qcc, uint64_t id)
 
 /* Retrieve the stream instance from <id> ID. This can be used when receiving
  * STREAM, STREAM_DATA_BLOCKED, RESET_STREAM, MAX_STREAM_DATA or STOP_SENDING
- * frames.
+ * frames. Set to false <receive_only> or <send_only> if these particular types
+ * of streams are not allowed.
  *
  * Return the stream instance or NULL if not found.
  */
-static struct qcs *qcc_get_qcs(struct qcc *qcc, uint64_t id)
+static struct qcs *qcc_get_qcs(struct qcc *qcc, uint64_t id,
+                               int receive_only, int send_only)
 {
        struct eb64_node *node;
        struct qcs *qcs = NULL;
 
        TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn);
 
+       if (!receive_only && quic_stream_is_uni(id) && quic_stream_is_remote(qcc, id)) {
+               TRACE_DEVEL("leaving on receive-only stream not allowed", QMUX_EV_QCC_RECV|QMUX_EV_QCC_NQCS, qcc->conn, NULL, &id);
+               qcc_emit_cc(qcc, QC_ERR_STREAM_STATE_ERROR);
+               return NULL;
+       }
+
+       if (!send_only && quic_stream_is_uni(id) && quic_stream_is_local(qcc, id)) {
+               TRACE_DEVEL("leaving on send-only stream not allowed", QMUX_EV_QCC_RECV|QMUX_EV_QCC_NQCS, qcc->conn, NULL, &id);
+               qcc_emit_cc(qcc, QC_ERR_STREAM_STATE_ERROR);
+               return NULL;
+       }
+
        /* Search the stream in the connection tree. */
        node = eb64_lookup(&qcc->streams_by_id, id);
        if (node) {
@@ -610,13 +624,7 @@ int qcc_recv(struct qcc *qcc, uint64_t id, uint64_t len, uint64_t offset,
         * initiated stream that has not yet been created, or for a send-only
         * stream.
         */
-       if (quic_stream_is_local(qcc, id) && quic_stream_is_uni(id)) {
-               qcc_emit_cc(qcc, QC_ERR_STREAM_STATE_ERROR);
-               TRACE_DEVEL("leaving on invalid reception for a send-only stream", QMUX_EV_QCC_RECV|QMUX_EV_QCC_NQCS, qcc->conn, NULL, &id);
-               return 1;
-       }
-
-       qcs = qcc_get_qcs(qcc, id);
+       qcs = qcc_get_qcs(qcc, id, 1, 0);
        if (!qcs)
                return 0;