QLOG: Events: Implement connectivity:connection_state_updated
authorHugo Landau <hlandau@openssl.org>
Fri, 8 Sep 2023 11:43:04 +0000 (12:43 +0100)
committerHugo Landau <hlandau@openssl.org>
Fri, 2 Feb 2024 11:49:34 +0000 (11:49 +0000)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22037)

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

index e26f4205613e770fca3802efcecc5901145f8875..de9022659ee9064ac614888c175b23405c7ee597 100644 (file)
 void ossl_qlog_event_connectivity_connection_started(QLOG *qlog,
                                                      const QUIC_CONN_ID *init_dcid);
 
+/* connectivity:connection_state_updated */
+void ossl_qlog_event_connectivity_connection_state_updated(QLOG *qlog,
+                                                           uint32_t old_state,
+                                                           uint32_t new_state,
+                                                           int handshake_complete,
+                                                           int handshake_confirmed);
+
 #endif
index d9542d9f5adcb8a1f3251d2e9e9cbe818bf489e3..82d0254c39cad4ece6baafd6a66d28c48318bff4 100644 (file)
@@ -7,3 +7,4 @@
  * https://www.openssl.org/source/license.html
  */
 QLOG_EVENT(connectivity, connection_started)
+QLOG_EVENT(connectivity, connection_state_updated)
index 0cbd616096a3d9f0974fd0c7cd2a075edf186e43..66157fe444eb2a6cad5412909e7526ee0d5e12c7 100644 (file)
@@ -21,3 +21,53 @@ void ossl_qlog_event_connectivity_connection_started(QLOG *qlog,
     QLOG_EVENT_END()
 #endif
 }
+
+#ifndef OPENSSL_NO_QLOG
+static const char *map_state_to_qlog(uint32_t state,
+                                     int handshake_complete,
+                                     int handshake_confirmed)
+{
+    switch (state) {
+    default:
+    case QUIC_CHANNEL_STATE_IDLE:
+        return NULL;
+
+    case QUIC_CHANNEL_STATE_ACTIVE:
+        if (handshake_confirmed)
+            return "handshake_confirmed";
+        else if (handshake_complete)
+            return "handshake_complete";
+        else
+            return "attempted";
+
+    case QUIC_CHANNEL_STATE_TERMINATING_CLOSING:
+        return "closing";
+
+    case QUIC_CHANNEL_STATE_TERMINATING_DRAINING:
+        return "draining";
+
+    case QUIC_CHANNEL_STATE_TERMINATED:
+        return "closed";
+    }
+}
+#endif
+
+void ossl_qlog_event_connectivity_connection_state_updated(QLOG *qlog,
+                                                           uint32_t old_state,
+                                                           uint32_t new_state,
+                                                           int handshake_complete,
+                                                           int handshake_confirmed)
+{
+#ifndef OPENSSL_NO_QLOG
+    const char *state_s;
+
+    QLOG_EVENT_BEGIN(qlog, connectivity, connection_state_updated)
+        state_s = map_state_to_qlog(new_state,
+                                    handshake_complete,
+                                    handshake_confirmed);
+
+        if (state_s != NULL)
+            QLOG_STR("state", state_s);
+    QLOG_EVENT_END()
+#endif
+}
index 5b1610ee40857151ce42b06bcb510a290c50f25f..b11cfe8c69a4e4d2a427a6fcaee8ef9a6bc82078 100644 (file)
@@ -101,6 +101,7 @@ static void ch_on_txp_ack_tx(const OSSL_QUIC_FRAME_ACK *ack, uint32_t pn_space,
                              void *arg);
 static void ch_rx_handle_version_neg(QUIC_CHANNEL *ch, OSSL_QRX_PKT *pkt);
 static void ch_raise_version_neg_failure(QUIC_CHANNEL *ch);
+static void ch_record_state_transition(QUIC_CHANNEL *ch, uint32_t new_state);
 
 DEFINE_LHASH_OF_EX(QUIC_SRT_ELEM);
 
@@ -1032,6 +1033,7 @@ static int ch_on_handshake_complete(void *arg)
         ossl_quic_tx_packetiser_schedule_handshake_done(ch->txp);
     }
 
+    ch_record_state_transition(ch, ch->state);
     return 1;
 }
 
@@ -2423,6 +2425,24 @@ static OSSL_TIME ch_determine_next_tick_deadline(QUIC_CHANNEL *ch)
  * QUIC Channel: Lifecycle Events
  * ==============================
  */
+
+/*
+ * Record a state transition. This is not necessarily a change to ch->state but
+ * also includes the handshake becoming complete or confirmed, etc.
+ */
+static void ch_record_state_transition(QUIC_CHANNEL *ch, uint32_t new_state)
+{
+    uint32_t old_state = ch->state;
+
+    ch->state = new_state;
+
+    ossl_qlog_event_connectivity_connection_state_updated(ch_get_qlog(ch),
+                                                          old_state,
+                                                          new_state,
+                                                          ch->handshake_complete,
+                                                          ch->handshake_confirmed);
+}
+
 int ossl_quic_channel_start(QUIC_CHANNEL *ch)
 {
     if (ch->is_server)
@@ -2449,7 +2469,7 @@ int ossl_quic_channel_start(QUIC_CHANNEL *ch)
         return 0;
 
     /* Change state. */
-    ch->state                   = QUIC_CHANNEL_STATE_ACTIVE;
+    ch_record_state_transition(ch, QUIC_CHANNEL_STATE_ACTIVE);
     ch->doing_proactive_ver_neg = 0; /* not currently supported */
 
     ossl_qlog_event_connectivity_connection_started(ch_get_qlog(ch),
@@ -2612,6 +2632,7 @@ int ossl_quic_channel_on_handshake_confirmed(QUIC_CHANNEL *ch)
 
     ch_discard_el(ch, QUIC_ENC_LEVEL_HANDSHAKE);
     ch->handshake_confirmed = 1;
+    ch_record_state_transition(ch, ch->state);
     ossl_ackm_on_handshake_confirmed(ch->ackm);
     return 1;
 }
@@ -2711,8 +2732,9 @@ static void ch_start_terminating(QUIC_CHANNEL *ch,
         copy_tcause(&ch->terminate_cause, tcause);
 
         if (!force_immediate) {
-            ch->state = tcause->remote ? QUIC_CHANNEL_STATE_TERMINATING_DRAINING
-                                       : QUIC_CHANNEL_STATE_TERMINATING_CLOSING;
+            ch_record_state_transition(ch, tcause->remote
+                                           ? QUIC_CHANNEL_STATE_TERMINATING_DRAINING
+                                           : QUIC_CHANNEL_STATE_TERMINATING_CLOSING);
             /*
              * RFC 9000 s. 10.2 Immediate Close
              *  These states SHOULD persist for at least three times
@@ -2757,7 +2779,7 @@ static void ch_start_terminating(QUIC_CHANNEL *ch,
              *  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;
+            ch_record_state_transition(ch, QUIC_CHANNEL_STATE_TERMINATING_DRAINING);
 
         break;
 
@@ -3091,7 +3113,7 @@ void ossl_quic_channel_raise_protocol_error_loc(QUIC_CHANNEL *ch,
  */
 static void ch_on_terminating_timeout(QUIC_CHANNEL *ch)
 {
-    ch->state = QUIC_CHANNEL_STATE_TERMINATED;
+    ch_record_state_transition(ch, QUIC_CHANNEL_STATE_TERMINATED);
 }
 
 /*
@@ -3166,7 +3188,7 @@ static void ch_on_idle_timeout(QUIC_CHANNEL *ch)
     ch->terminate_cause.error_code  = UINT64_MAX;
     ch->terminate_cause.frame_type  = 0;
 
-    ch->state = QUIC_CHANNEL_STATE_TERMINATED;
+    ch_record_state_transition(ch, QUIC_CHANNEL_STATE_TERMINATED);
 }
 
 /* Called when we, as a server, get a new incoming connection. */
@@ -3210,7 +3232,7 @@ int ossl_quic_channel_on_new_conn(QUIC_CHANNEL *ch, const BIO_ADDR *peer,
         return 0;
 
     /* Change state. */
-    ch->state                   = QUIC_CHANNEL_STATE_ACTIVE;
+    ch_record_state_transition(ch, QUIC_CHANNEL_STATE_ACTIVE);
     ch->doing_proactive_ver_neg = 0; /* not currently supported */
     return 1;
 }