]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
quic conformance: section 10.2.2 requirements
authorPauli <pauli@openssl.org>
Mon, 17 Jul 2023 01:32:58 +0000 (11:32 +1000)
committerPauli <pauli@openssl.org>
Fri, 4 Aug 2023 01:55:34 +0000 (11:55 +1000)
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21429)

include/internal/quic_channel.h
ssl/quic/quic_channel.c

index 03aeab949b70189adefc974f1f09cd177ee8cb39..abeeb05b9643fef25ea2b31c7aab20c608bd8435 100644 (file)
@@ -269,7 +269,6 @@ QUIC_STREAM *ossl_quic_channel_get_stream_by_id(QUIC_CHANNEL *ch,
 int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch);
 const QUIC_TERMINATE_CAUSE *
 ossl_quic_channel_get_terminate_cause(const QUIC_CHANNEL *ch);
-int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch);
 int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch);
 int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch);
 int ossl_quic_channel_is_handshake_complete(const QUIC_CHANNEL *ch);
index 91c125ee9a3c461cc2985d11ec82303799326cc0..29ee89ac58fe6f91373f2cf52f8e24f5a89f35c0 100644 (file)
@@ -451,21 +451,25 @@ int ossl_quic_channel_is_active(const QUIC_CHANNEL *ch)
     return ch != NULL && ch->state == QUIC_CHANNEL_STATE_ACTIVE;
 }
 
-int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch)
+static int ossl_quic_channel_is_closing(const QUIC_CHANNEL *ch)
 {
-    if (ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING
-            || ch->state == QUIC_CHANNEL_STATE_TERMINATING_DRAINING)
-        return 1;
+    return ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING;
+}
 
-    return 0;
+static int ossl_quic_channel_is_draining(const QUIC_CHANNEL *ch)
+{
+    return ch->state == QUIC_CHANNEL_STATE_TERMINATING_DRAINING;
 }
 
-int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch)
+static int ossl_quic_channel_is_terminating(const QUIC_CHANNEL *ch)
 {
-    if (ch->state == QUIC_CHANNEL_STATE_TERMINATED)
-        return 1;
+    return ossl_quic_channel_is_closing(ch)
+        || ossl_quic_channel_is_draining(ch);
+}
 
-    return 0;
+int ossl_quic_channel_is_terminated(const QUIC_CHANNEL *ch)
+{
+    return ch->state == QUIC_CHANNEL_STATE_TERMINATED;
 }
 
 int ossl_quic_channel_is_term_any(const QUIC_CHANNEL *ch)
@@ -1816,7 +1820,7 @@ static int ch_rx(QUIC_CHANNEL *ch)
      * When in TERMINATING - CLOSING, generate a CONN_CLOSE frame whenever we
      * process one or more incoming packets.
      */
-    if (handled_any && ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING)
+    if (handled_any && ossl_quic_channel_is_closing(ch))
         ch->conn_close_queued = 1;
 
     return 1;
@@ -2114,16 +2118,26 @@ static int ch_tx(QUIC_CHANNEL *ch)
 {
     QUIC_TXP_STATUS status;
 
-    if (ch->state == QUIC_CHANNEL_STATE_TERMINATING_CLOSING) {
+    /*
+     * RFC 9000 s. 10.2.2: Draining Connection State:
+     *      While otherwise identical to the closing state, an endpoint
+     *      in the draining state MUST NOT send any packets.
+     * and:
+     *      An endpoint MUST NOT send further packets.
+     */
+    if (ossl_quic_channel_is_draining(ch))
+        return 0;
+
+    if (ossl_quic_channel_is_closing(ch)) {
         /*
          * While closing, only send CONN_CLOSE if we've received more traffic
          * from the peer. Once we tell the TXP to generate CONN_CLOSE, all
          * future calls to it generate CONN_CLOSE frames, so otherwise we would
          * just constantly generate CONN_CLOSE frames.
          *
-         * Conforming to RFC 9000 s. 10.2.1 Closing Connection State:
+         * Confirming to RFC 9000 s. 10.2.1 Closing Connection State:
          *      An endpoint SHOULD limit the rate at which it generates
-         *      packets in the closing state. TODO(QUIC)
+         *      packets in the closing state.
          */
         if (!ch->conn_close_queued)
             return 0;
@@ -2589,6 +2603,13 @@ static void ch_start_terminating(QUIC_CHANNEL *ch,
                 f.frame_type = ch->terminate_cause.frame_type;
                 f.is_app     = ch->terminate_cause.app;
                 ossl_quic_tx_packetiser_schedule_conn_close(ch->txp, &f);
+                /*
+                 * RFC 9000 s. 10.2.2 Draining Connection State:
+                 *  An endpoint that receives a CONNECTION_CLOSE frame MAY
+                 *  send a single packet containing a CONNECTION_CLOSE
+                 *  frame before entering the draining state, using a
+                 *  NO_ERROR code if appropriate
+                 */
                 ch->conn_close_queued = 1;
             }
         } else {
@@ -2600,6 +2621,12 @@ static void ch_start_terminating(QUIC_CHANNEL *ch,
         if (force_immediate)
             ch_on_terminating_timeout(ch);
         else if (tcause->remote)
+            /*
+             * RFC 9000 s. 10.2.2 Draining Connection State:
+             *  An endpoint MAY enter the draining state from the
+             *  closing state if it receives a CONNECTION_CLOSE frame,
+             *  which indicates that the peer is also closing or draining.
+             */
             ch->state = QUIC_CHANNEL_STATE_TERMINATING_DRAINING;
 
         break;