QUIC CHANNEL: Allow ticking to be inhibited for testing purposes
authorHugo Landau <hlandau@openssl.org>
Tue, 18 Jul 2023 15:12:04 +0000 (16:12 +0100)
committerMatt Caswell <matt@openssl.org>
Mon, 31 Jul 2023 13:03:25 +0000 (14:03 +0100)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21484)

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

index bd9f45c68a98cad5424ed41ec678b39226e0e2d2..03aeab949b70189adefc974f1f09cd177ee8cb39 100644 (file)
@@ -353,6 +353,9 @@ int ossl_quic_channel_has_pending(const QUIC_CHANNEL *ch);
 /* Force transmission of an ACK-eliciting packet. */
 int ossl_quic_channel_ping(QUIC_CHANNEL *ch);
 
+/* For testing use. While enabled, ticking is not performed. */
+void ossl_quic_channel_set_inhibit_tick(QUIC_CHANNEL *ch, int inhibit);
+
 # endif
 
 #endif
index 1e6a29a706c9aeb37e6f970a3a3d0a42ffab8460..b516746b586949e9cd3165a510a839a0e3ddae6b 100644 (file)
@@ -1631,69 +1631,76 @@ static void ch_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
         }
     }
 
-    /* Handle RXKU timeouts. */
-    ch_rxku_tick(ch);
+    if (!ch->inhibit_tick) {
+        /* Handle RXKU timeouts. */
+        ch_rxku_tick(ch);
 
-    /* Handle any incoming data from network. */
-    ch_rx_pre(ch);
+        /* Handle any incoming data from network. */
+        ch_rx_pre(ch);
 
-    do {
-        /* Process queued incoming packets. */
-        ch_rx(ch);
+        do {
+            /* Process queued incoming packets. */
+            ch_rx(ch);
 
-        /*
-         * Allow the handshake layer to check for any new incoming data and generate
-         * new outgoing data.
-         */
-        ch->have_new_rx_secret = 0;
-        if (!channel_only)
-            ossl_quic_tls_tick(ch->qtls);
+            /*
+             * Allow the handshake layer to check for any new incoming data and
+             * generate new outgoing data.
+             */
+            ch->have_new_rx_secret = 0;
+            if (!channel_only)
+                ossl_quic_tls_tick(ch->qtls);
 
-        /*
-         * If the handshake layer gave us a new secret, we need to do RX again
-         * because packets that were not previously processable and were
-         * deferred might now be processable.
-         *
-         * TODO(QUIC): Consider handling this in the yield_secret callback.
-         */
-    } while (ch->have_new_rx_secret);
+            /*
+             * If the handshake layer gave us a new secret, we need to do RX
+             * again because packets that were not previously processable and
+             * were deferred might now be processable.
+             *
+             * TODO(QUIC): Consider handling this in the yield_secret callback.
+             */
+        } while (ch->have_new_rx_secret);
+    }
 
     /*
-     * Handle any timer events which are due to fire; namely, the loss detection
-     * deadline and the idle timeout.
+     * Handle any timer events which are due to fire; namely, the loss
+     * detection deadline and the idle timeout.
      *
-     * ACKM ACK generation deadline is polled by TXP, so we don't need to handle
-     * it here.
+     * ACKM ACK generation deadline is polled by TXP, so we don't need to
+     * handle it here.
      */
     now = get_time(ch);
     if (ossl_time_compare(now, ch->idle_deadline) >= 0) {
         /*
-         * Idle timeout differs from normal protocol violation because we do not
-         * send a CONN_CLOSE frame; go straight to TERMINATED.
+         * Idle timeout differs from normal protocol violation because we do
+         * not send a CONN_CLOSE frame; go straight to TERMINATED.
          */
-        ch_on_idle_timeout(ch);
+        if (!ch->inhibit_tick)
+            ch_on_idle_timeout(ch);
+
         res->net_read_desired   = 0;
         res->net_write_desired  = 0;
         res->tick_deadline      = ossl_time_infinite();
         return;
     }
 
-    deadline = ossl_ackm_get_loss_detection_deadline(ch->ackm);
-    if (!ossl_time_is_zero(deadline) && ossl_time_compare(now, deadline) >= 0)
-        ossl_ackm_on_timeout(ch->ackm);
+    if (!ch->inhibit_tick) {
+        deadline = ossl_ackm_get_loss_detection_deadline(ch->ackm);
+        if (!ossl_time_is_zero(deadline)
+            && ossl_time_compare(now, deadline) >= 0)
+            ossl_ackm_on_timeout(ch->ackm);
 
-    /* If a ping is due, inform TXP. */
-    if (ossl_time_compare(now, ch->ping_deadline) >= 0) {
-        int pn_space = ossl_quic_enc_level_to_pn_space(ch->tx_enc_level);
+        /* If a ping is due, inform TXP. */
+        if (ossl_time_compare(now, ch->ping_deadline) >= 0) {
+            int pn_space = ossl_quic_enc_level_to_pn_space(ch->tx_enc_level);
 
-        ossl_quic_tx_packetiser_schedule_ack_eliciting(ch->txp, pn_space);
-    }
+            ossl_quic_tx_packetiser_schedule_ack_eliciting(ch->txp, pn_space);
+        }
 
-    /* Write any data to the network due to be sent. */
-    ch_tx(ch);
+        /* Write any data to the network due to be sent. */
+        ch_tx(ch);
 
-    /* Do stream GC. */
-    ossl_quic_stream_map_gc(&ch->qsm);
+        /* Do stream GC. */
+        ossl_quic_stream_map_gc(&ch->qsm);
+    }
 
     /* Determine the time at which we should next be ticked. */
     res->tick_deadline = ch_determine_next_tick_deadline(ch);
@@ -3152,3 +3159,8 @@ int ossl_quic_channel_ping(QUIC_CHANNEL *ch)
 
     return 1;
 }
+
+void ossl_quic_channel_set_inhibit_tick(QUIC_CHANNEL *ch, int inhibit)
+{
+    ch->inhibit_tick = (inhibit != 0);
+}
index 8cc903506d9e1dd3a71fe07bf34b48cd0e0a5bfd..8e7d78855edf000988a930356787284822382f69 100644 (file)
@@ -404,6 +404,9 @@ struct quic_channel_st {
     /* Permanent net error encountered */
     unsigned int                    net_error                           : 1;
 
+    /* Inhibit tick for testing purposes? */
+    unsigned int                    inhibit_tick                        : 1;
+
     /* Saved error stack in case permanent error was encountered */
     ERR_STATE                       *err_state;
 };