QUIC CHANNEL: Handle any number of streams
authorHugo Landau <hlandau@openssl.org>
Tue, 18 Apr 2023 18:30:54 +0000 (19:30 +0100)
committerHugo Landau <hlandau@openssl.org>
Fri, 12 May 2023 13:47:11 +0000 (14:47 +0100)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20765)

include/internal/quic_stream_map.h
ssl/quic/quic_channel.c
ssl/quic/quic_rx_depack.c

index b4e0993eb584805175dfca9942e6349b40ebe7a8..f9a04723c1e2f733568748145965f63007ad20f3 100644 (file)
@@ -166,6 +166,16 @@ void ossl_quic_stream_map_cleanup(QUIC_STREAM_MAP *qsm);
 #define QUIC_STREAM_DIR_UNI                 2
 #define QUIC_STREAM_DIR_MASK                2
 
+static ossl_inline ossl_unused int ossl_quic_stream_is_server_init(QUIC_STREAM *s)
+{
+    return (s->type & QUIC_STREAM_INITIATOR_MASK) == QUIC_STREAM_INITIATOR_SERVER;
+}
+
+static ossl_inline ossl_unused int ossl_quic_stream_is_bidi(QUIC_STREAM *s)
+{
+    return (s->type & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_BIDI;
+}
+
 /*
  * Allocate a new stream. type is a combination of one QUIC_STREAM_INITIATOR_*
  * value and one QUIC_STREAM_DIR_* value. Note that clients can e.g. allocate
index 79e015d123b858cb3fb5fa465de86f25542ee9be..7ef66b234d8113f6f1ff7a8f6d88ab5a7657d368 100644 (file)
@@ -714,6 +714,31 @@ static int ch_on_handshake_alert(void *arg, unsigned char alert_code)
 #define TP_REASON_REQUIRED(x) \
     x " was not sent but is required"
 
+static void txfc_bump_cwm_bidi(QUIC_STREAM *s, void *arg)
+{
+    if (!ossl_quic_stream_is_bidi(s)
+        || ossl_quic_stream_is_server_init(s))
+        return;
+
+    ossl_quic_txfc_bump_cwm(&s->txfc, *(uint64_t *)arg);
+}
+
+static void txfc_bump_cwm_uni(QUIC_STREAM *s, void *arg)
+{
+    if (ossl_quic_stream_is_bidi(s)
+        || ossl_quic_stream_is_server_init(s))
+        return;
+
+    ossl_quic_txfc_bump_cwm(&s->txfc, *(uint64_t *)arg);
+}
+
+static void do_update(QUIC_STREAM *s, void *arg)
+{
+    QUIC_CHANNEL *ch = arg;
+
+    ossl_quic_stream_map_update_state(&ch->qsm, s);
+}
+
 static int ch_on_transport_params(const unsigned char *params,
                                   size_t params_len,
                                   void *arg)
@@ -881,8 +906,8 @@ static int ch_on_transport_params(const unsigned char *params,
              */
             ch->rx_init_max_stream_data_bidi_local = v;
 
-            /* Apply to stream 0. */
-            ossl_quic_txfc_bump_cwm(&ch->stream0->txfc, v);
+            /* Apply to all existing streams. */
+            ossl_quic_stream_map_visit(&ch->qsm, txfc_bump_cwm_bidi, &v);
             got_initial_max_stream_data_bidi_remote = 1;
             break;
 
@@ -899,6 +924,9 @@ static int ch_on_transport_params(const unsigned char *params,
             }
 
             ch->rx_init_max_stream_data_uni_remote = v;
+
+            /* Apply to all existing streams. */
+            ossl_quic_stream_map_visit(&ch->qsm, txfc_bump_cwm_uni, &v);
             got_initial_max_stream_data_uni = 1;
             break;
 
@@ -1093,8 +1121,11 @@ static int ch_on_transport_params(const unsigned char *params,
 
     if (got_initial_max_data || got_initial_max_stream_data_bidi_remote
         || got_initial_max_streams_bidi || got_initial_max_streams_uni)
-        /* If FC credit was bumped, we may now be able to send. */
-        ossl_quic_stream_map_update_state(&ch->qsm, ch->stream0);
+        /*
+         * If FC credit was bumped, we may now be able to send. Update all
+         * streams.
+         */
+        ossl_quic_stream_map_visit(&ch->qsm, do_update, ch);
 
     /* If we are a server, we now generate our own transport parameters. */
     if (ch->is_server && !ch_generate_transport_params(ch)) {
index 7af86c8841066627c3e08c4230c6d2af3db51fff..ea54bc3c08d04e83f8ae9aebb5c02131706c1991 100644 (file)
@@ -308,6 +308,33 @@ static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
     return 1;
 }
 
+static void update_streams(QUIC_STREAM *s, void *arg)
+{
+    QUIC_CHANNEL *ch = arg;
+
+    ossl_quic_stream_map_update_state(&ch->qsm, s);
+}
+
+static void update_streams_bidi(QUIC_STREAM *s, void *arg)
+{
+    QUIC_CHANNEL *ch = arg;
+
+    if (!ossl_quic_stream_is_bidi(s))
+        return;
+
+    ossl_quic_stream_map_update_state(&ch->qsm, s);
+}
+
+static void update_streams_uni(QUIC_STREAM *s, void *arg)
+{
+    QUIC_CHANNEL *ch = arg;
+
+    if (ossl_quic_stream_is_bidi(s))
+        return;
+
+    ossl_quic_stream_map_update_state(&ch->qsm, s);
+}
+
 static int depack_do_frame_max_data(PACKET *pkt, QUIC_CHANNEL *ch,
                                     OSSL_ACKM_RX_PKT *ackm_data)
 {
@@ -325,7 +352,7 @@ static int depack_do_frame_max_data(PACKET *pkt, QUIC_CHANNEL *ch,
     ackm_data->is_ack_eliciting = 1;
 
     ossl_quic_txfc_bump_cwm(&ch->conn_txfc, max_data);
-    ossl_quic_stream_map_update_state(&ch->qsm, ch->stream0);
+    ossl_quic_stream_map_visit(&ch->qsm, update_streams, ch);
     return 1;
 }
 
@@ -404,17 +431,15 @@ static int depack_do_frame_max_streams(PACKET *pkt,
         if (max_streams > ch->max_local_streams_bidi)
             ch->max_local_streams_bidi = max_streams;
 
-        /* Stream may now be able to send */
-        ossl_quic_stream_map_update_state(&ch->qsm,
-                                          ch->stream0);
+        /* Some streams may now be able to send. */
+        ossl_quic_stream_map_visit(&ch->qsm, update_streams_bidi, ch);
         break;
     case OSSL_QUIC_FRAME_TYPE_MAX_STREAMS_UNI:
         if (max_streams > ch->max_local_streams_uni)
             ch->max_local_streams_uni = max_streams;
 
-        /* Stream may now be able to send */
-        ossl_quic_stream_map_update_state(&ch->qsm,
-                                          ch->stream0);
+        /* Some streams may now be able to send. */
+        ossl_quic_stream_map_visit(&ch->qsm, update_streams_uni, ch);
         break;
     default:
         ossl_quic_channel_raise_protocol_error(ch,