summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Landau <hlandau@openssl.org>2023-04-18 19:30:55 +0100
committerHugo Landau <hlandau@openssl.org>2023-05-12 14:47:12 +0100
commit999e13f40eda5a2ca39d1efb407b96f81d2b9535 (patch)
treed34c48091e5d317251e22a786e28479106acc004
parent9caf981237c3e655c18ebef7193153238f2855db (diff)
downloadopenssl-new-999e13f40eda5a2ca39d1efb407b96f81d2b9535.tar.gz
QUIC CHANNEL: Incoming streams implicitly create lower-numbered streams
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_local.h9
-rw-r--r--ssl/quic/quic_rx_depack.c42
2 files changed, 40 insertions, 11 deletions
diff --git a/ssl/quic/quic_channel_local.h b/ssl/quic/quic_channel_local.h
index a1ce833f56..f13d0118ee 100644
--- a/ssl/quic/quic_channel_local.h
+++ b/ssl/quic/quic_channel_local.h
@@ -168,6 +168,15 @@ struct quic_channel_st {
uint64_t next_local_stream_ordinal_uni;
/*
+ * Used to track which stream ordinals within a given stream type have been
+ * used by the remote peer. This is an optimisation used to determine
+ * which streams should be implicitly created due to usage of a higher
+ * stream ordinal.
+ */
+ uint64_t next_remote_stream_ordinal_bidi;
+ uint64_t next_remote_stream_ordinal_uni;
+
+ /*
* Application error code to be used for STOP_SENDING/RESET_STREAM frames
* used to autoreject incoming streams.
*/
diff --git a/ssl/quic/quic_rx_depack.c b/ssl/quic/quic_rx_depack.c
index 7adec6d7b0..c49a13fe89 100644
--- a/ssl/quic/quic_rx_depack.c
+++ b/ssl/quic/quic_rx_depack.c
@@ -254,7 +254,8 @@ static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
stream = ossl_quic_stream_map_get_by_id(&ch->qsm, frame_data.stream_id);
if (stream == NULL) {
- uint64_t peer_role, stream_ordinal, *p_next_ordinal;
+ uint64_t peer_role, stream_ordinal;
+ uint64_t *p_next_ordinal_local, *p_next_ordinal_remote;
int is_uni;
/*
@@ -286,14 +287,33 @@ static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
stream_ordinal = frame_data.stream_id >> 2;
if ((frame_data.stream_id & QUIC_STREAM_INITIATOR_MASK) == peer_role) {
- /* Peer-created stream which does not yet exist. Create it. */
- stream = ossl_quic_channel_new_stream_remote(ch, frame_data.stream_id);
- if (stream == NULL) {
- ossl_quic_channel_raise_protocol_error(ch,
- QUIC_ERR_INTERNAL_ERROR,
- frame_type,
- "internal error (stream allocation)");
- return 0;
+ /*
+ * Peer-created stream which does not yet exist. Create it. QUIC
+ * stream ordinals within a given stream type MUST be used in
+ * sequence and receiving a STREAM frame for ordinal n must
+ * implicitly create streams with ordinals [0, n) within that stream
+ * type even if no explicit STREAM frames are received for those
+ * ordinals.
+ */
+ p_next_ordinal_remote = is_uni
+ ? &ch->next_remote_stream_ordinal_uni
+ : &ch->next_remote_stream_ordinal_bidi;
+
+ while (*p_next_ordinal_remote <= stream_ordinal) {
+ uint64_t stream_id = (*p_next_ordinal_remote << 2) |
+ (frame_data.stream_id
+ & (QUIC_STREAM_DIR_MASK | QUIC_STREAM_INITIATOR_MASK));
+
+ stream = ossl_quic_channel_new_stream_remote(ch, stream_id);
+ if (stream == NULL) {
+ ossl_quic_channel_raise_protocol_error(ch,
+ QUIC_ERR_INTERNAL_ERROR,
+ frame_type,
+ "internal error (stream allocation)");
+ return 0;
+ }
+
+ ++*p_next_ordinal_remote;
}
/*
@@ -303,11 +323,11 @@ static int depack_do_frame_stream(PACKET *pkt, QUIC_CHANNEL *ch,
} else {
/* Locally-created stream which does not yet exist. */
- p_next_ordinal = is_uni
+ p_next_ordinal_local = is_uni
? &ch->next_local_stream_ordinal_uni
: &ch->next_local_stream_ordinal_bidi;
- if (stream_ordinal >= *p_next_ordinal) {
+ if (stream_ordinal >= *p_next_ordinal_local) {
/*
* We never created this stream yet, this is a protocol
* violation.