diff options
author | Hugo Landau <hlandau@openssl.org> | 2023-04-18 19:30:54 +0100 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-05-12 14:47:11 +0100 |
commit | e8fe7a21ea253408930d570ce00e6d3a78652162 (patch) | |
tree | 708e7ef83a5670c7791e543244d5fe018d41b2fc | |
parent | f20fdd16d817a095f58f9c016044abef24e50e58 (diff) | |
download | openssl-new-e8fe7a21ea253408930d570ce00e6d3a78652162.tar.gz |
QUIC CHANNEL: Initialise state, FC credit for new streams correctly
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20765)
-rw-r--r-- | ssl/quic/quic_channel.c | 96 | ||||
-rw-r--r-- | ssl/quic/quic_channel_local.h | 2 |
2 files changed, 91 insertions, 7 deletions
diff --git a/ssl/quic/quic_channel.c b/ssl/quic/quic_channel.c index b11393955d..f11139132f 100644 --- a/ssl/quic/quic_channel.c +++ b/ssl/quic/quic_channel.c @@ -105,11 +105,11 @@ static int gen_rand_conn_id(OSSL_LIB_CTX *libctx, size_t len, QUIC_CONN_ID *cid) * QUIC Channel Initialization and Teardown * ======================================== */ -#define DEFAULT_INIT_CONN_RXFC_WND ( 2 * 1024 * 1024) -#define DEFAULT_MAX_CONN_RXFC_WND (10 * 1024 * 1024) +#define DEFAULT_INIT_CONN_RXFC_WND (2 * 1024 * 1024) +#define DEFAULT_CONN_RXFC_MAX_WND_MUL 5 -#define DEFAULT_INIT_STREAM_RXFC_WND ( 2 * 1024 * 1024) -#define DEFAULT_MAX_STREAM_RXFC_WND (10 * 1024 * 1024) +#define DEFAULT_INIT_STREAM_RXFC_WND (2 * 1024 * 1024) +#define DEFAULT_STREAM_RXFC_MAX_WND_MUL 5 static int ch_init(QUIC_CHANNEL *ch) { @@ -155,7 +155,8 @@ static int ch_init(QUIC_CHANNEL *ch) if (!ossl_quic_rxfc_init(&ch->conn_rxfc, NULL, DEFAULT_INIT_CONN_RXFC_WND, - DEFAULT_MAX_CONN_RXFC_WND, + DEFAULT_CONN_RXFC_MAX_WND_MUL * + DEFAULT_INIT_CONN_RXFC_WND, get_time, ch)) goto err; @@ -923,7 +924,7 @@ static int ch_on_transport_params(const unsigned char *params, goto malformed; } - ch->rx_init_max_stream_data_uni_remote = v; + ch->rx_init_max_stream_data_uni = v; /* Apply to all existing streams. */ ossl_quic_stream_map_visit(&ch->qsm, txfc_bump_cwm_uni, &v); @@ -2214,6 +2215,70 @@ SSL *ossl_quic_channel_get0_ssl(QUIC_CHANNEL *ch) return ch->tls; } +static int ch_init_new_stream(QUIC_CHANNEL *ch, QUIC_STREAM *qs, + int can_send, int can_recv) +{ + uint64_t rxfc_wnd; + int server_init = ossl_quic_stream_is_server_init(qs); + int local_init = (ch->is_server == server_init); + int is_uni = !ossl_quic_stream_is_bidi(qs); + + if (can_send && (qs->sstream = ossl_quic_sstream_new(INIT_APP_BUF_LEN)) == NULL) + goto err; + + if (can_recv && (qs->rstream = ossl_quic_rstream_new(NULL, NULL, 0)) == NULL) + goto err; + + /* TXFC */ + if (!ossl_quic_txfc_init(&qs->txfc, &ch->conn_txfc)) + goto err; + + if (ch->got_remote_transport_params) { + /* + * If we already got peer TPs we need to apply the initial CWM credit + * now. If we didn't already get peer TPs this will be done + * automatically for all extant streams when we do. + */ + if (can_send) { + uint64_t cwm; + + if (is_uni) + cwm = ch->rx_init_max_stream_data_uni; + else if (local_init) + cwm = ch->rx_init_max_stream_data_bidi_local; + else + cwm = ch->rx_init_max_stream_data_bidi_remote; + + ossl_quic_txfc_bump_cwm(&qs->txfc, cwm); + } + } + + /* RXFC */ + if (!can_recv) + rxfc_wnd = 0; + else if (is_uni) + rxfc_wnd = ch->tx_init_max_stream_data_uni; + else if (local_init) + rxfc_wnd = ch->tx_init_max_stream_data_bidi_local; + else + rxfc_wnd = ch->tx_init_max_stream_data_bidi_remote; + + if (!ossl_quic_rxfc_init(&qs->rxfc, &ch->conn_rxfc, + rxfc_wnd, + DEFAULT_STREAM_RXFC_MAX_WND_MUL * rxfc_wnd, + get_time, ch)) + goto err; + + return 1; + +err: + ossl_quic_sstream_free(qs->sstream); + qs->sstream = NULL; + ossl_quic_rstream_free(qs->rstream); + qs->rstream = NULL; + return 0; +} + QUIC_STREAM *ossl_quic_channel_new_stream_local(QUIC_CHANNEL *ch, int is_uni) { QUIC_STREAM *qs; @@ -2239,14 +2304,24 @@ QUIC_STREAM *ossl_quic_channel_new_stream_local(QUIC_CHANNEL *ch, int is_uni) if ((qs = ossl_quic_stream_map_alloc(&ch->qsm, stream_id, type)) == NULL) return NULL; + /* Locally-initiated stream, so we always want a send buffer. */ + if (!ch_init_new_stream(ch, qs, /*can_send=*/1, /*can_recv=*/!is_uni)) + goto err; + + ++*p_next_ordinal; return qs; + +err: + ossl_quic_stream_map_release(&ch->qsm, qs); + return NULL; } QUIC_STREAM *ossl_quic_channel_new_stream_remote(QUIC_CHANNEL *ch, uint64_t stream_id) { uint64_t peer_role; + int is_uni; QUIC_STREAM *qs; peer_role = ch->is_server @@ -2256,12 +2331,21 @@ QUIC_STREAM *ossl_quic_channel_new_stream_remote(QUIC_CHANNEL *ch, if ((stream_id & QUIC_STREAM_INITIATOR_MASK) != peer_role) return NULL; + is_uni = ((stream_id & QUIC_STREAM_DIR_MASK) == QUIC_STREAM_DIR_UNI); + qs = ossl_quic_stream_map_alloc(&ch->qsm, stream_id, stream_id & (QUIC_STREAM_INITIATOR_MASK | QUIC_STREAM_DIR_MASK)); if (qs == NULL) return NULL; + if (!ch_init_new_stream(ch, qs, /*can_send=*/!is_uni, /*can_recv=*/1)) + goto err; + ossl_quic_stream_map_push_accept_queue(&ch->qsm, qs); return qs; + +err: + ossl_quic_stream_map_release(&ch->qsm, qs); + return NULL; } diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h index 8534ae9835..3645c277dd 100644 --- a/ssl/quic/quic_channel_local.h +++ b/ssl/quic/quic_channel_local.h @@ -131,7 +131,7 @@ struct quic_channel_st { /* Transport parameter values received from server. */ uint64_t rx_init_max_stream_data_bidi_local; uint64_t rx_init_max_stream_data_bidi_remote; - uint64_t rx_init_max_stream_data_uni_remote; + uint64_t rx_init_max_stream_data_uni; uint64_t rx_max_ack_delay; /* ms */ unsigned char rx_ack_delay_exp; |