]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: mux-quic: support stream opening via MAX_STREAM_DATA
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 6 Jul 2022 13:45:20 +0000 (15:45 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 11 Jul 2022 14:24:03 +0000 (16:24 +0200)
MAX_STREAM_DATA can be used as the first frame of a stream. In this
case, the stream should be opened, if it respects flow-control limit. To
implement this, simply replace plain lookup in stream tree by
qcc_get_qcs() at the start of the parsing function. This automatically
takes care of opening the stream if not already done.

As specified by RFC 9000, if MAX_STREAM_DATA is receive for a
receive-only stream, a STREAM_STATE_ERROR connection error is emitted.

src/mux_quic.c
src/xprt_quic.c

index 6cf2504f6fddbe79152a97cd6d82d196a6a866a1..f03a58170e6105a8b324187214c9ba5cf35f7244 100644 (file)
@@ -762,18 +762,29 @@ int qcc_recv_max_data(struct qcc *qcc, uint64_t max)
 /* Handle a new MAX_STREAM_DATA frame. <max> must contains the maximum data
  * field of the frame and <id> is the identifier of the QUIC stream.
  *
- * Returns 0 on success else non-zero.
+ * Returns 0 on success else non-zero. On error, the received frame should not
+ * be acknowledged.
  */
 int qcc_recv_max_stream_data(struct qcc *qcc, uint64_t id, uint64_t max)
 {
        struct qcs *qcs;
-       struct eb64_node *node;
 
        TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn);
 
-       node = eb64_lookup(&qcc->streams_by_id, id);
-       if (node) {
-               qcs = eb64_entry(node, struct qcs, by_id);
+       /* RFC 9000 19.10. MAX_STREAM_DATA Frames
+        *
+        * Receiving a MAX_STREAM_DATA frame for a locally
+        * initiated stream that has not yet been created MUST be treated as a
+        * connection error of type STREAM_STATE_ERROR.  An endpoint that
+        * receives a MAX_STREAM_DATA frame for a receive-only stream MUST
+        * terminate the connection with error STREAM_STATE_ERROR.
+        */
+       if (qcc_get_qcs(qcc, id, 0, 1, &qcs)) {
+               TRACE_LEAVE(QMUX_EV_QCC_RECV, qcc->conn);
+               return 1;
+       }
+
+       if (qcs) {
                if (max > qcs->tx.msd) {
                        qcs->tx.msd = max;
                        TRACE_DEVEL("increase remote max-stream-data", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV, qcc->conn, qcs);
index ce4a2f9704e7451ff140fbf257ac3c42f5c8a80e..728aaf5c2ed5a58a8a1f46b3f78bc4e7c2de6f8b 100644 (file)
@@ -2523,8 +2523,10 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct
                case QUIC_FT_MAX_STREAM_DATA:
                        if (qc->mux_state == QC_MUX_READY) {
                                struct quic_max_stream_data *data = &frm.max_stream_data;
-                               qcc_recv_max_stream_data(qc->qcc, data->id,
-                                                        data->max_stream_data);
+                               if (qcc_recv_max_stream_data(qc->qcc, data->id,
+                                                             data->max_stream_data)) {
+                                       goto err;
+                               }
                        }
                        break;
                case QUIC_FT_MAX_STREAMS_BIDI: