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
+}
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);
ossl_quic_tx_packetiser_schedule_handshake_done(ch->txp);
}
+ ch_record_state_transition(ch, ch->state);
return 1;
}
* 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)
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),
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;
}
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
* 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;
*/
static void ch_on_terminating_timeout(QUIC_CHANNEL *ch)
{
- ch->state = QUIC_CHANNEL_STATE_TERMINATED;
+ ch_record_state_transition(ch, QUIC_CHANNEL_STATE_TERMINATED);
}
/*
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. */
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;
}