]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
QUIC QSM: Handle STOP_SENDING correctly
authorHugo Landau <hlandau@openssl.org>
Tue, 18 Apr 2023 18:30:55 +0000 (19:30 +0100)
committerHugo Landau <hlandau@openssl.org>
Fri, 12 May 2023 13:47:12 +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_rx_depack.c
ssl/quic/quic_stream_map.c

index 81312e8b4ad9a8238d62ef79d4feae0eaec1cfb6..2be73286ea286ba9998e4781fe0c403ddf688586 100644 (file)
@@ -237,6 +237,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.
  */
index a81f47d6d924128bd612e11f0a6b4ce0235be0a1..2bc4e146e8086c20dc71d244730264fd19888023 100644 (file)
@@ -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;
 }
 
index a9c616ea9f2d446980edb3202b69911be8cf590b..2f58b2a51a99c5fbcd80a3eba4a463eb80f74118 100644 (file)
@@ -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);