diff options
author | Hugo Landau <hlandau@openssl.org> | 2022-11-17 15:29:44 +0000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-01-13 13:20:15 +0000 |
commit | cbe7f586ad42b7cf6d16b11a6d614798df0a5d29 (patch) | |
tree | 85619475d9e2368a3275aff470e54f08c8a2abb4 | |
parent | 3a37c9235de465fe8d557b32f0178bfad0c09908 (diff) |
QUIC Stream Mapper: CSM-related changes, stream limits handling
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19703)
-rw-r--r-- | include/internal/quic_stream_map.h | 51 | ||||
-rw-r--r-- | ssl/quic/quic_stream_map.c | 37 | ||||
-rw-r--r-- | test/quic_txp_test.c | 2 |
3 files changed, 70 insertions, 20 deletions
diff --git a/include/internal/quic_stream_map.h b/include/internal/quic_stream_map.h index 5f0e0347e4..b4e0993eb5 100644 --- a/include/internal/quic_stream_map.h +++ b/include/internal/quic_stream_map.h @@ -11,12 +11,14 @@ # define OSSL_INTERNAL_QUIC_STREAM_MAP_H # pragma once -#include "internal/e_os.h" -#include "internal/time.h" -#include "internal/quic_types.h" -#include "internal/quic_stream.h" -#include "internal/quic_fc.h" -#include <openssl/lhash.h> +# include "internal/e_os.h" +# include "internal/time.h" +# include "internal/quic_types.h" +# include "internal/quic_stream.h" +# include "internal/quic_fc.h" +# include <openssl/lhash.h> + +# ifndef OPENSSL_NO_QUIC /* * QUIC Stream @@ -68,18 +70,23 @@ struct quic_stream_st { unsigned int active : 1; /* - * Has STOP_SENDING been requested? Note that this is not the same as - * want_stop_sending below, as a STOP_SENDING frame may already have been + * Has STOP_SENDING been requested (by us)? Note that this is not the same + * as want_stop_sending below, as a STOP_SENDING frame may already have been * sent and fully acknowledged. */ unsigned int stop_sending : 1; /* - * Has RESET_STREAM been requested? Works identically to STOP_SENDING for - * transmission purposes. + * Has RESET_STREAM been requested (by us)? Works identically to + * STOP_SENDING for transmission purposes. */ unsigned int reset_stream : 1; + /* Has our peer sent a STOP_SENDING frame? */ + unsigned int peer_stop_sending : 1; + /* Has our peer sent a RESET_STREAM frame? */ + unsigned int peer_reset_stream : 1; + /* Temporary flags used by TXP. */ unsigned int txp_sent_fc : 1; unsigned int txp_sent_stop_sending : 1; @@ -91,6 +98,9 @@ struct quic_stream_st { unsigned int want_max_stream_data : 1; /* used for regen only */ unsigned int want_stop_sending : 1; /* used for gen or regen */ unsigned int want_reset_stream : 1; /* used for gen or regen */ + + /* A FIN has been retired from the rstream buffer. */ + unsigned int recv_fin_retired : 1; }; /* @@ -121,9 +131,26 @@ typedef struct quic_stream_map_st { QUIC_STREAM_LIST_NODE active_list; size_t rr_stepping, rr_counter; QUIC_STREAM *rr_cur; + uint64_t (*get_stream_limit_cb)(int uni, void *arg); + void *get_stream_limit_cb_arg; } QUIC_STREAM_MAP; -int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm); +/* + * get_stream_limit is a callback which is called to retrieve the current stream + * limit for streams created by us. This mechanism is not used for + * peer-initiated streams. If a stream's stream ID is x, a stream is allowed if + * (x >> 2) < returned limit value; i.e., the returned value is exclusive. + * + * If uni is 1, get the limit for locally-initiated unidirectional streams, else + * get the limit for locally-initiated bidirectional streams. + * + * If the callback is NULL, stream limiting is not applied. + * Stream limiting is used to determine if frames can currently be produced for + * a stream. + */ +int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm, + uint64_t (*get_stream_limit_cb)(int uni, void *arg), + void *get_stream_limit_cb_arg); /* * Any streams still in the map will be released as though @@ -229,4 +256,6 @@ void ossl_quic_stream_iter_init(QUIC_STREAM_ITER *it, QUIC_STREAM_MAP *qsm, */ void ossl_quic_stream_iter_next(QUIC_STREAM_ITER *it); +# endif + #endif diff --git a/ssl/quic/quic_stream_map.c b/ssl/quic/quic_stream_map.c index d080bac233..52e8e14bf8 100644 --- a/ssl/quic/quic_stream_map.c +++ b/ssl/quic/quic_stream_map.c @@ -91,13 +91,18 @@ static int cmp_stream(const QUIC_STREAM *a, const QUIC_STREAM *b) return 0; } -int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm) +int ossl_quic_stream_map_init(QUIC_STREAM_MAP *qsm, + uint64_t (*get_stream_limit_cb)(int uni, void *arg), + void *get_stream_limit_cb_arg) { qsm->map = lh_QUIC_STREAM_new(hash_stream, cmp_stream); qsm->active_list.prev = qsm->active_list.next = &qsm->active_list; qsm->rr_stepping = 1; qsm->rr_counter = 0; qsm->rr_cur = NULL; + + qsm->get_stream_limit_cb = get_stream_limit_cb; + qsm->get_stream_limit_cb_arg = get_stream_limit_cb_arg; return 1; } @@ -236,13 +241,29 @@ static int stream_has_data_to_send(QUIC_STREAM *s) void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s) { - int should_be_active - = (s->rstream != NULL - && (s->want_max_stream_data - || ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0))) - || s->want_stop_sending - || s->want_reset_stream - || stream_has_data_to_send(s); + int should_be_active, allowed_by_stream_limit = 1; + + if (qsm->get_stream_limit_cb != NULL + && (s->type & QUIC_STREAM_INITIATOR_CLIENT) != 0) { + int uni = ((s->type & QUIC_STREAM_DIR_UNI) != 0); + uint64_t stream_limit, stream_ordinal = s->id >> 2; + + stream_limit + = qsm->get_stream_limit_cb(uni, qsm->get_stream_limit_cb_arg); + + allowed_by_stream_limit = (stream_ordinal < stream_limit); + } + + should_be_active + = allowed_by_stream_limit + && !s->peer_stop_sending + && !s->peer_reset_stream + && ((s->rstream != NULL + && (s->want_max_stream_data + || ossl_quic_rxfc_has_cwm_changed(&s->rxfc, 0))) + || s->want_stop_sending + || s->want_reset_stream + || stream_has_data_to_send(s)); if (should_be_active) stream_map_mark_active(qsm, s); diff --git a/test/quic_txp_test.c b/test/quic_txp_test.c index ab9b943c7e..8d2361af18 100644 --- a/test/quic_txp_test.c +++ b/test/quic_txp_test.c @@ -162,7 +162,7 @@ static int helper_init(struct helper *h) h->cc_data))) goto err; - if (!TEST_true(ossl_quic_stream_map_init(&h->qsm))) + if (!TEST_true(ossl_quic_stream_map_init(&h->qsm, NULL, NULL))) goto err; h->have_qsm = 1; |