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
commitb89c81e43b88c48d7cb5ce48665bab6c36ae02ac (patch)
tree8e05251eac8cce369d6daf6d1197037940b8a945
parent90cecc406f58b229ffa9c8e8473eaa6924c4a5d5 (diff)
downloadopenssl-new-b89c81e43b88c48d7cb5ce48665bab6c36ae02ac.tar.gz
QUIC QSM: Handle STOP_SENDING 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--include/internal/quic_stream_map.h7
-rw-r--r--ssl/quic/quic_rx_depack.c9
-rw-r--r--ssl/quic/quic_stream_map.c24
3 files changed, 33 insertions, 7 deletions
diff --git a/include/internal/quic_stream_map.h b/include/internal/quic_stream_map.h
index 81312e8b4a..2be73286ea 100644
--- a/include/internal/quic_stream_map.h
+++ b/include/internal/quic_stream_map.h
@@ -238,6 +238,13 @@ void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s);
void ossl_quic_stream_map_set_rr_stepping(QUIC_STREAM_MAP *qsm, size_t stepping);
/*
+ * Resets the sending part of a stream.
+ */
+void ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,
+ QUIC_STREAM *qs,
+ uint64_t aec);
+
+/*
* Adds a stream to the accept queue.
*/
void ossl_quic_stream_map_push_accept_queue(QUIC_STREAM_MAP *qsm,
diff --git a/ssl/quic/quic_rx_depack.c b/ssl/quic/quic_rx_depack.c
index a81f47d6d9..2bc4e146e8 100644
--- a/ssl/quic/quic_rx_depack.c
+++ b/ssl/quic/quic_rx_depack.c
@@ -172,7 +172,14 @@ static int depack_do_frame_stop_sending(PACKET *pkt,
}
stream->peer_stop_sending = 1;
- ossl_quic_stream_map_update_state(&ch->qsm, stream);
+
+ /*
+ * RFC 9000 s. 3.5: Receiving a STOP_SENDING frame means we must respond in
+ * turn with a RESET_STREAM frame for the same part of the stream. The other
+ * part is unaffected.
+ */
+ ossl_quic_stream_map_reset_stream_send_part(&ch->qsm, stream,
+ frame_data.app_error_code);
return 1;
}
diff --git a/ssl/quic/quic_stream_map.c b/ssl/quic/quic_stream_map.c
index a9c616ea9f..2f58b2a51a 100644
--- a/ssl/quic/quic_stream_map.c
+++ b/ssl/quic/quic_stream_map.c
@@ -271,14 +271,12 @@ void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
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->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));
+ || (!s->peer_stop_sending && stream_has_data_to_send(s)));
if (should_be_active)
stream_map_mark_active(qsm, s);
@@ -286,6 +284,20 @@ void ossl_quic_stream_map_update_state(QUIC_STREAM_MAP *qsm, QUIC_STREAM *s)
stream_map_mark_inactive(qsm, s);
}
+void ossl_quic_stream_map_reset_stream_send_part(QUIC_STREAM_MAP *qsm,
+ QUIC_STREAM *qs,
+ uint64_t aec)
+{
+ if (qs->reset_stream)
+ return;
+
+ qs->reset_stream = 1;
+ qs->reset_stream_aec = aec;
+ qs->want_reset_stream = 1;
+
+ ossl_quic_stream_map_update_state(qsm, qs);
+}
+
QUIC_STREAM *ossl_quic_stream_map_peek_accept_queue(QUIC_STREAM_MAP *qsm)
{
return accept_head(&qsm->accept_list);