From a82ed926bea675961960e8be969048e8eea4b924 Mon Sep 17 00:00:00 2001 From: Cameron Bytheway Date: Tue, 29 Oct 2024 21:50:00 -0600 Subject: [PATCH 1/2] feat(s2n-quic-dc): add map events --- dc/s2n-quic-dc/events/common.rs | 10 + dc/s2n-quic-dc/events/connection.rs | 12 +- dc/s2n-quic-dc/events/map.rs | 176 ++ dc/s2n-quic-dc/src/event.rs | 22 +- dc/s2n-quic-dc/src/event/generated.rs | 2504 ++++++++++++++++- dc/s2n-quic-dc/src/path/secret/map.rs | 26 +- dc/s2n-quic-dc/src/path/secret/map/cleaner.rs | 5 +- .../src/path/secret/map/handshake.rs | 4 +- dc/s2n-quic-dc/src/path/secret/map/state.rs | 350 ++- .../src/path/secret/map/state/tests.rs | 21 +- dc/s2n-quic-dc/src/path/secret/map/status.rs | 32 +- dc/s2n-quic-dc/src/path/secret/map/store.rs | 15 +- dc/s2n-quic-dc/src/stream/recv/shared.rs | 10 +- dc/s2n-quic-dc/src/stream/send/worker.rs | 6 +- quic/s2n-quic-core/src/event/generated.rs | 88 +- quic/s2n-quic-events/src/main.rs | 126 +- quic/s2n-quic-events/src/parser.rs | 9 +- 17 files changed, 3032 insertions(+), 384 deletions(-) create mode 100644 dc/s2n-quic-dc/events/common.rs create mode 100644 dc/s2n-quic-dc/events/map.rs diff --git a/dc/s2n-quic-dc/events/common.rs b/dc/s2n-quic-dc/events/common.rs new file mode 100644 index 000000000..29ce73ff6 --- /dev/null +++ b/dc/s2n-quic-dc/events/common.rs @@ -0,0 +1,10 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +struct ConnectionMeta { + id: u64, +} + +struct EndpointMeta {} + +struct ConnectionInfo {} diff --git a/dc/s2n-quic-dc/events/connection.rs b/dc/s2n-quic-dc/events/connection.rs index 10fd951ba..b5e150e97 100644 --- a/dc/s2n-quic-dc/events/connection.rs +++ b/dc/s2n-quic-dc/events/connection.rs @@ -4,11 +4,17 @@ #[event("application:write")] pub struct ApplicationWrite { /// The number of bytes that the application tried to write - len: usize, + total_len: usize, + + /// The amount that was written + write_len: usize, } -#[event("application:write")] +#[event("application:read")] pub struct ApplicationRead { /// The number of bytes that the application tried to read - len: usize, + capacity: usize, + + /// The amount that was read + read_len: usize, } diff --git a/dc/s2n-quic-dc/events/map.rs b/dc/s2n-quic-dc/events/map.rs new file mode 100644 index 000000000..245273848 --- /dev/null +++ b/dc/s2n-quic-dc/events/map.rs @@ -0,0 +1,176 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +#[event("path_secret_map:initialized")] +#[subject(endpoint)] +struct PathSecretMapInitialized { + /// The capacity of the path secret map + capacity: usize, + + /// The port that the path secret is listening on + control_socket_port: u16, +} + +#[event("path_secret_map:uninitialized")] +#[subject(endpoint)] +struct PathSecretMapUninitialized { + /// The capacity of the path secret map + capacity: usize, + + /// The port that the path secret is listening on + control_socket_port: u16, + + /// The number of entries in the map + entries: usize, +} + +#[event("path_secret_map:background_handshake_requested")] +#[subject(endpoint)] +/// Emitted when a background handshake is requested +struct PathSecretMapBackgroundHandshakeRequested<'a> { + peer_address: SocketAddress<'a>, +} + +#[event("path_secret_map:entry_replaced")] +#[subject(endpoint)] +/// Emitted when the entry is inserted into the path secret map +struct PathSecretMapEntryInserted<'a> { + peer_address: SocketAddress<'a>, + + credential_id: &'a [u8], +} + +#[event("path_secret_map:entry_replaced")] +#[subject(endpoint)] +/// Emitted when the entry is considered ready for use +struct PathSecretMapEntryReady<'a> { + peer_address: SocketAddress<'a>, + + credential_id: &'a [u8], +} + +#[event("path_secret_map:entry_replaced")] +#[subject(endpoint)] +/// Emitted when an entry is replaced by a new one for the same `peer_address` +struct PathSecretMapEntryReplaced<'a> { + peer_address: SocketAddress<'a>, + + new_credential_id: &'a [u8], + + previous_credential_id: &'a [u8], +} + +#[event("path_secret_map:unknown_path_secret_packet_sent")] +#[subject(endpoint)] +/// Emitted when an UnknownPathSecret packet was sent +struct UnknownPathSecretPacketSent<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:unknown_path_secret_packet_received")] +#[subject(endpoint)] +/// Emitted when an UnknownPathSecret packet was received +struct UnknownPathSecretPacketReceived<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:unknown_path_secret_packet_accepted")] +#[subject(endpoint)] +/// Emitted when an UnknownPathSecret packet was authentic and processed +struct UnknownPathSecretPacketAccepted<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:unknown_path_secret_packet_rejected")] +#[subject(endpoint)] +/// Emitted when an UnknownPathSecret packet was rejected as invalid +struct UnknownPathSecretPacketRejected<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:replay_definitely_detected")] +#[subject(endpoint)] +/// Emitted when credential replay was definitely detected +struct ReplayDefinitelyDetected<'a> { + credential_id: &'a [u8], + key_id: u64, +} + +#[event("path_secret_map:replay_potentially_detected")] +#[subject(endpoint)] +/// Emitted when credential replay was potentially detected, but could not be verified +/// due to a limiting tracking window +struct ReplayPotentiallyDetected<'a> { + credential_id: &'a [u8], + key_id: u64, + gap: u64, +} + +#[event("path_secret_map:replay_detected_packet_sent")] +#[subject(endpoint)] +/// Emitted when an ReplayDetected packet was sent +struct ReplayDetectedPacketSent<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:replay_detected_packet_received")] +#[subject(endpoint)] +/// Emitted when an ReplayDetected packet was received +struct ReplayDetectedPacketReceived<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:replay_detected_packet_accepted")] +#[subject(endpoint)] +/// Emitted when an StaleKey packet was authentic and processed +struct ReplayDetectedPacketAccepted<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], + key_id: u64, +} + +#[event("path_secret_map:replay_detected_packet_rejected")] +#[subject(endpoint)] +/// Emitted when an ReplayDetected packet was rejected as invalid +struct ReplayDetectedPacketRejected<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:stale_key_packet_sent")] +#[subject(endpoint)] +/// Emitted when an StaleKey packet was sent +struct StaleKeyPacketSent<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:stale_key_packet_received")] +#[subject(endpoint)] +/// Emitted when an StaleKey packet was received +struct StaleKeyPacketReceived<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:stale_key_packet_accepted")] +#[subject(endpoint)] +/// Emitted when an StaleKey packet was authentic and processed +struct StaleKeyPacketAccepted<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + +#[event("path_secret_map:stale_key_packet_rejected")] +#[subject(endpoint)] +/// Emitted when an StaleKey packet was rejected as invalid +struct StaleKeyPacketRejected<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} diff --git a/dc/s2n-quic-dc/src/event.rs b/dc/s2n-quic-dc/src/event.rs index b4ca61d92..8445158d5 100644 --- a/dc/s2n-quic-dc/src/event.rs +++ b/dc/s2n-quic-dc/src/event.rs @@ -4,7 +4,27 @@ #[cfg(any(test, feature = "testing"))] use s2n_quic_core::event::snapshot; -pub use s2n_quic_core::event::{Event, IntoEvent, Timestamp}; +pub use s2n_quic_core::event::{Event, IntoEvent}; + +/// Provides metadata related to an event +pub trait Meta: core::fmt::Debug { + /// A context from which the event is being emitted + /// + /// An event can occur in the context of an Endpoint or Connection + fn subject(&self) -> api::Subject; +} + +impl Meta for api::ConnectionMeta { + fn subject(&self) -> api::Subject { + builder::Subject::Connection { id: self.id }.into_event() + } +} + +impl Meta for api::EndpointMeta { + fn subject(&self) -> api::Subject { + builder::Subject::Endpoint {}.into_event() + } +} mod generated; pub use generated::*; diff --git a/dc/s2n-quic-dc/src/event/generated.rs b/dc/s2n-quic-dc/src/event/generated.rs index bd55f188a..c1f461e20 100644 --- a/dc/s2n-quic-dc/src/event/generated.rs +++ b/dc/s2n-quic-dc/src/event/generated.rs @@ -9,12 +9,21 @@ use super::*; pub mod api { #![doc = r" This module contains events that are emitted to the [`Subscriber`](crate::event::Subscriber)"] use super::*; - pub use s2n_quic_core::event::api::{ - ConnectionInfo, ConnectionMeta, EndpointMeta, EndpointType, SocketAddress, Subject, - }; + pub use s2n_quic_core::event::api::{EndpointType, SocketAddress, Subject}; pub use traits::Subscriber; #[derive(Clone, Debug)] #[non_exhaustive] + pub struct ConnectionMeta { + pub id: u64, + } + #[derive(Clone, Debug)] + #[non_exhaustive] + pub struct EndpointMeta {} + #[derive(Clone, Debug)] + #[non_exhaustive] + pub struct ConnectionInfo {} + #[derive(Clone, Debug)] + #[non_exhaustive] pub struct ApplicationWrite { #[doc = " The number of bytes that the application tried to write"] pub len: usize, @@ -42,6 +51,213 @@ pub mod api { impl<'a> Event for EndpointInitialized<'a> { const NAME: &'static str = "endpoint:initialized"; } + #[derive(Clone, Debug)] + #[non_exhaustive] + pub struct PathSecretMapInitialized { + #[doc = " The capacity of the path secret map"] + pub capacity: usize, + #[doc = " The port that the path secret is listening on"] + pub control_socket_port: u16, + } + impl Event for PathSecretMapInitialized { + const NAME: &'static str = "path_secret_map:initialized"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + pub struct PathSecretMapUninitialized { + #[doc = " The capacity of the path secret map"] + pub capacity: usize, + #[doc = " The port that the path secret is listening on"] + pub control_socket_port: u16, + #[doc = " The number of entries in the map"] + pub entries: usize, + } + impl Event for PathSecretMapUninitialized { + const NAME: &'static str = "path_secret_map:uninitialized"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when a background handshake is requested"] + pub struct PathSecretMapBackgroundHandshakeRequested<'a> { + pub peer_address: SocketAddress<'a>, + } + impl<'a> Event for PathSecretMapBackgroundHandshakeRequested<'a> { + const NAME: &'static str = "path_secret_map:background_handshake_requested"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when the entry is inserted into the path secret map"] + pub struct PathSecretMapEntryInserted<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for PathSecretMapEntryInserted<'a> { + const NAME: &'static str = "path_secret_map:entry_replaced"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when the entry is considered ready for use"] + pub struct PathSecretMapEntryReady<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for PathSecretMapEntryReady<'a> { + const NAME: &'static str = "path_secret_map:entry_replaced"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an entry is replaced by a new one for the same `peer_address`"] + pub struct PathSecretMapEntryReplaced<'a> { + pub peer_address: SocketAddress<'a>, + pub new_credential_id: &'a [u8], + pub previous_credential_id: &'a [u8], + } + impl<'a> Event for PathSecretMapEntryReplaced<'a> { + const NAME: &'static str = "path_secret_map:entry_replaced"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an UnknownPathSecret packet was sent"] + pub struct UnknownPathSecretPacketSent<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for UnknownPathSecretPacketSent<'a> { + const NAME: &'static str = "path_secret_map:unknown_path_secret_packet_sent"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an UnknownPathSecret packet was received"] + pub struct UnknownPathSecretPacketReceived<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for UnknownPathSecretPacketReceived<'a> { + const NAME: &'static str = "path_secret_map:unknown_path_secret_packet_received"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an UnknownPathSecret packet was authentic and processed"] + pub struct UnknownPathSecretPacketAccepted<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for UnknownPathSecretPacketAccepted<'a> { + const NAME: &'static str = "path_secret_map:unknown_path_secret_packet_accepted"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an UnknownPathSecret packet was rejected as invalid"] + pub struct UnknownPathSecretPacketRejected<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for UnknownPathSecretPacketRejected<'a> { + const NAME: &'static str = "path_secret_map:unknown_path_secret_packet_rejected"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when credential replay was definitely detected"] + pub struct ReplayDefinitelyDetected<'a> { + pub credential_id: &'a [u8], + pub key_id: u64, + } + impl<'a> Event for ReplayDefinitelyDetected<'a> { + const NAME: &'static str = "path_secret_map:replay_definitely_detected"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when credential replay was potentially detected, but could not be verified"] + #[doc = " due to a limiting tracking window"] + pub struct ReplayPotentiallyDetected<'a> { + pub credential_id: &'a [u8], + pub key_id: u64, + pub gap: u64, + } + impl<'a> Event for ReplayPotentiallyDetected<'a> { + const NAME: &'static str = "path_secret_map:replay_potentially_detected"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an ReplayDetected packet was sent"] + pub struct ReplayDetectedPacketSent<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for ReplayDetectedPacketSent<'a> { + const NAME: &'static str = "path_secret_map:replay_detected_packet_sent"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an ReplayDetected packet was received"] + pub struct ReplayDetectedPacketReceived<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for ReplayDetectedPacketReceived<'a> { + const NAME: &'static str = "path_secret_map:replay_detected_packet_received"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an StaleKey packet was authentic and processed"] + pub struct ReplayDetectedPacketAccepted<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + pub key_id: u64, + } + impl<'a> Event for ReplayDetectedPacketAccepted<'a> { + const NAME: &'static str = "path_secret_map:replay_detected_packet_accepted"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an ReplayDetected packet was rejected as invalid"] + pub struct ReplayDetectedPacketRejected<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for ReplayDetectedPacketRejected<'a> { + const NAME: &'static str = "path_secret_map:replay_detected_packet_rejected"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an StaleKey packet was sent"] + pub struct StaleKeyPacketSent<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for StaleKeyPacketSent<'a> { + const NAME: &'static str = "path_secret_map:stale_key_packet_sent"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an StaleKey packet was received"] + pub struct StaleKeyPacketReceived<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for StaleKeyPacketReceived<'a> { + const NAME: &'static str = "path_secret_map:stale_key_packet_received"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an StaleKey packet was authentic and processed"] + pub struct StaleKeyPacketAccepted<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for StaleKeyPacketAccepted<'a> { + const NAME: &'static str = "path_secret_map:stale_key_packet_accepted"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an StaleKey packet was rejected as invalid"] + pub struct StaleKeyPacketRejected<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for StaleKeyPacketRejected<'a> { + const NAME: &'static str = "path_secret_map:stale_key_packet_rejected"; + } } pub mod tracing { #![doc = r" This module contains event integration with [`tracing`](https://docs.rs/tracing)"] @@ -49,17 +265,17 @@ pub mod tracing { #[doc = r" Emits events with [`tracing`](https://docs.rs/tracing)"] #[derive(Clone, Debug)] pub struct Subscriber { - client: tracing::Span, - server: tracing::Span, + root: tracing::Span, } impl Default for Subscriber { fn default() -> Self { let root = tracing :: span ! (target : "s2n_quic_dc" , tracing :: Level :: DEBUG , "s2n_quic_dc"); - let client = - tracing :: span ! (parent : root . id () , tracing :: Level :: DEBUG , "client"); - let server = - tracing :: span ! (parent : root . id () , tracing :: Level :: DEBUG , "server"); - Self { client, server } + Self { root } + } + } + impl Subscriber { + fn parent(&self, _meta: &M) -> Option { + self.root.id() } } impl super::Subscriber for Subscriber { @@ -69,10 +285,7 @@ pub mod tracing { meta: &api::ConnectionMeta, _info: &api::ConnectionInfo, ) -> Self::ConnectionContext { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); tracing :: span ! (target : "s2n_quic_dc" , parent : parent , tracing :: Level :: DEBUG , "conn" , id = meta . id) } #[inline] @@ -103,10 +316,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::EndpointInitialized, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::EndpointInitialized { acceptor_addr, handshake_addr, @@ -115,13 +325,303 @@ pub mod tracing { } = event; tracing :: event ! (target : "endpoint_initialized" , parent : parent , tracing :: Level :: DEBUG , acceptor_addr = tracing :: field :: debug (acceptor_addr) , handshake_addr = tracing :: field :: debug (handshake_addr) , tcp = tracing :: field :: debug (tcp) , udp = tracing :: field :: debug (udp)); } + #[inline] + fn on_path_secret_map_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapInitialized, + ) { + let parent = self.parent(meta); + let api::PathSecretMapInitialized { + capacity, + control_socket_port, + } = event; + tracing :: event ! (target : "path_secret_map_initialized" , parent : parent , tracing :: Level :: DEBUG , capacity = tracing :: field :: debug (capacity) , control_socket_port = tracing :: field :: debug (control_socket_port)); + } + #[inline] + fn on_path_secret_map_uninitialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapUninitialized, + ) { + let parent = self.parent(meta); + let api::PathSecretMapUninitialized { + capacity, + control_socket_port, + entries, + } = event; + tracing :: event ! (target : "path_secret_map_uninitialized" , parent : parent , tracing :: Level :: DEBUG , capacity = tracing :: field :: debug (capacity) , control_socket_port = tracing :: field :: debug (control_socket_port) , entries = tracing :: field :: debug (entries)); + } + #[inline] + fn on_path_secret_map_background_handshake_requested( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapBackgroundHandshakeRequested, + ) { + let parent = self.parent(meta); + let api::PathSecretMapBackgroundHandshakeRequested { peer_address } = event; + tracing :: event ! (target : "path_secret_map_background_handshake_requested" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address)); + } + #[inline] + fn on_path_secret_map_entry_inserted( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryInserted, + ) { + let parent = self.parent(meta); + let api::PathSecretMapEntryInserted { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "path_secret_map_entry_inserted" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_path_secret_map_entry_ready( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReady, + ) { + let parent = self.parent(meta); + let api::PathSecretMapEntryReady { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "path_secret_map_entry_ready" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_path_secret_map_entry_replaced( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReplaced, + ) { + let parent = self.parent(meta); + let api::PathSecretMapEntryReplaced { + peer_address, + new_credential_id, + previous_credential_id, + } = event; + tracing :: event ! (target : "path_secret_map_entry_replaced" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , new_credential_id = tracing :: field :: debug (new_credential_id) , previous_credential_id = tracing :: field :: debug (previous_credential_id)); + } + #[inline] + fn on_unknown_path_secret_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketSent, + ) { + let parent = self.parent(meta); + let api::UnknownPathSecretPacketSent { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "unknown_path_secret_packet_sent" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_unknown_path_secret_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketReceived, + ) { + let parent = self.parent(meta); + let api::UnknownPathSecretPacketReceived { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "unknown_path_secret_packet_received" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_unknown_path_secret_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketAccepted, + ) { + let parent = self.parent(meta); + let api::UnknownPathSecretPacketAccepted { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "unknown_path_secret_packet_accepted" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_unknown_path_secret_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketRejected, + ) { + let parent = self.parent(meta); + let api::UnknownPathSecretPacketRejected { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "unknown_path_secret_packet_rejected" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_replay_definitely_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDefinitelyDetected, + ) { + let parent = self.parent(meta); + let api::ReplayDefinitelyDetected { + credential_id, + key_id, + } = event; + tracing :: event ! (target : "replay_definitely_detected" , parent : parent , tracing :: Level :: DEBUG , credential_id = tracing :: field :: debug (credential_id) , key_id = tracing :: field :: debug (key_id)); + } + #[inline] + fn on_replay_potentially_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayPotentiallyDetected, + ) { + let parent = self.parent(meta); + let api::ReplayPotentiallyDetected { + credential_id, + key_id, + gap, + } = event; + tracing :: event ! (target : "replay_potentially_detected" , parent : parent , tracing :: Level :: DEBUG , credential_id = tracing :: field :: debug (credential_id) , key_id = tracing :: field :: debug (key_id) , gap = tracing :: field :: debug (gap)); + } + #[inline] + fn on_replay_detected_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketSent, + ) { + let parent = self.parent(meta); + let api::ReplayDetectedPacketSent { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "replay_detected_packet_sent" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_replay_detected_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketReceived, + ) { + let parent = self.parent(meta); + let api::ReplayDetectedPacketReceived { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "replay_detected_packet_received" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_replay_detected_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketAccepted, + ) { + let parent = self.parent(meta); + let api::ReplayDetectedPacketAccepted { + peer_address, + credential_id, + key_id, + } = event; + tracing :: event ! (target : "replay_detected_packet_accepted" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id) , key_id = tracing :: field :: debug (key_id)); + } + #[inline] + fn on_replay_detected_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketRejected, + ) { + let parent = self.parent(meta); + let api::ReplayDetectedPacketRejected { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "replay_detected_packet_rejected" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_stale_key_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketSent, + ) { + let parent = self.parent(meta); + let api::StaleKeyPacketSent { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "stale_key_packet_sent" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_stale_key_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketReceived, + ) { + let parent = self.parent(meta); + let api::StaleKeyPacketReceived { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "stale_key_packet_received" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_stale_key_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketAccepted, + ) { + let parent = self.parent(meta); + let api::StaleKeyPacketAccepted { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "stale_key_packet_accepted" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] + fn on_stale_key_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketRejected, + ) { + let parent = self.parent(meta); + let api::StaleKeyPacketRejected { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "stale_key_packet_rejected" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } } } pub mod builder { use super::*; - pub use s2n_quic_core::event::builder::{ - ConnectionInfo, ConnectionMeta, EndpointMeta, EndpointType, SocketAddress, Subject, - }; + pub use s2n_quic_core::event::builder::{EndpointType, SocketAddress, Subject}; + #[derive(Clone, Debug)] + pub struct ConnectionMeta { + pub id: u64, + } + impl IntoEvent for ConnectionMeta { + #[inline] + fn into_event(self) -> api::ConnectionMeta { + let ConnectionMeta { id } = self; + api::ConnectionMeta { + id: id.into_event(), + } + } + } + #[derive(Clone, Debug)] + pub struct EndpointMeta {} + impl IntoEvent for EndpointMeta { + #[inline] + fn into_event(self) -> api::EndpointMeta { + let EndpointMeta {} = self; + api::EndpointMeta {} + } + } + #[derive(Clone, Debug)] + pub struct ConnectionInfo {} + impl IntoEvent for ConnectionInfo { + #[inline] + fn into_event(self) -> api::ConnectionInfo { + let ConnectionInfo {} = self; + api::ConnectionInfo {} + } + } #[derive(Clone, Debug)] pub struct ApplicationWrite { #[doc = " The number of bytes that the application tried to write"] @@ -174,41 +674,441 @@ pub mod builder { } } } -} -pub use traits::*; -mod traits { - use super::*; - use core::fmt; - use s2n_quic_core::{event::Meta, query}; - #[doc = r" Allows for events to be subscribed to"] - pub trait Subscriber: 'static + Send { - #[doc = r" An application provided type associated with each connection."] - #[doc = r""] - #[doc = r" The context provides a mechanism for applications to provide a custom type"] - #[doc = r" and update it on each event, e.g. computing statistics. Each event"] - #[doc = r" invocation (e.g. [`Subscriber::on_packet_sent`]) also provides mutable"] - #[doc = r" access to the context `&mut ConnectionContext` and allows for updating the"] - #[doc = r" context."] - #[doc = r""] - #[doc = r" ```no_run"] - #[doc = r" # mod s2n_quic { pub mod provider { pub mod event {"] - #[doc = r" # pub use s2n_quic_core::event::{api as events, api::ConnectionInfo, api::ConnectionMeta, Subscriber};"] - #[doc = r" # }}}"] - #[doc = r" use s2n_quic::provider::event::{"] - #[doc = r" ConnectionInfo, ConnectionMeta, Subscriber, events::PacketSent"] - #[doc = r" };"] - #[doc = r""] - #[doc = r" pub struct MyEventSubscriber;"] - #[doc = r""] - #[doc = r" pub struct MyEventContext {"] - #[doc = r" packet_sent: u64,"] - #[doc = r" }"] - #[doc = r""] - #[doc = r" impl Subscriber for MyEventSubscriber {"] - #[doc = r" type ConnectionContext = MyEventContext;"] - #[doc = r""] - #[doc = r" fn create_connection_context("] - #[doc = r" &mut self, _meta: &ConnectionMeta,"] + #[derive(Clone, Debug)] + pub struct PathSecretMapInitialized { + #[doc = " The capacity of the path secret map"] + pub capacity: usize, + #[doc = " The port that the path secret is listening on"] + pub control_socket_port: u16, + } + impl IntoEvent for PathSecretMapInitialized { + #[inline] + fn into_event(self) -> api::PathSecretMapInitialized { + let PathSecretMapInitialized { + capacity, + control_socket_port, + } = self; + api::PathSecretMapInitialized { + capacity: capacity.into_event(), + control_socket_port: control_socket_port.into_event(), + } + } + } + #[derive(Clone, Debug)] + pub struct PathSecretMapUninitialized { + #[doc = " The capacity of the path secret map"] + pub capacity: usize, + #[doc = " The port that the path secret is listening on"] + pub control_socket_port: u16, + #[doc = " The number of entries in the map"] + pub entries: usize, + } + impl IntoEvent for PathSecretMapUninitialized { + #[inline] + fn into_event(self) -> api::PathSecretMapUninitialized { + let PathSecretMapUninitialized { + capacity, + control_socket_port, + entries, + } = self; + api::PathSecretMapUninitialized { + capacity: capacity.into_event(), + control_socket_port: control_socket_port.into_event(), + entries: entries.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when a background handshake is requested"] + pub struct PathSecretMapBackgroundHandshakeRequested<'a> { + pub peer_address: SocketAddress<'a>, + } + impl<'a> IntoEvent> + for PathSecretMapBackgroundHandshakeRequested<'a> + { + #[inline] + fn into_event(self) -> api::PathSecretMapBackgroundHandshakeRequested<'a> { + let PathSecretMapBackgroundHandshakeRequested { peer_address } = self; + api::PathSecretMapBackgroundHandshakeRequested { + peer_address: peer_address.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when the entry is inserted into the path secret map"] + pub struct PathSecretMapEntryInserted<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for PathSecretMapEntryInserted<'a> { + #[inline] + fn into_event(self) -> api::PathSecretMapEntryInserted<'a> { + let PathSecretMapEntryInserted { + peer_address, + credential_id, + } = self; + api::PathSecretMapEntryInserted { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when the entry is considered ready for use"] + pub struct PathSecretMapEntryReady<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for PathSecretMapEntryReady<'a> { + #[inline] + fn into_event(self) -> api::PathSecretMapEntryReady<'a> { + let PathSecretMapEntryReady { + peer_address, + credential_id, + } = self; + api::PathSecretMapEntryReady { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an entry is replaced by a new one for the same `peer_address`"] + pub struct PathSecretMapEntryReplaced<'a> { + pub peer_address: SocketAddress<'a>, + pub new_credential_id: &'a [u8], + pub previous_credential_id: &'a [u8], + } + impl<'a> IntoEvent> for PathSecretMapEntryReplaced<'a> { + #[inline] + fn into_event(self) -> api::PathSecretMapEntryReplaced<'a> { + let PathSecretMapEntryReplaced { + peer_address, + new_credential_id, + previous_credential_id, + } = self; + api::PathSecretMapEntryReplaced { + peer_address: peer_address.into_event(), + new_credential_id: new_credential_id.into_event(), + previous_credential_id: previous_credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an UnknownPathSecret packet was sent"] + pub struct UnknownPathSecretPacketSent<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for UnknownPathSecretPacketSent<'a> { + #[inline] + fn into_event(self) -> api::UnknownPathSecretPacketSent<'a> { + let UnknownPathSecretPacketSent { + peer_address, + credential_id, + } = self; + api::UnknownPathSecretPacketSent { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an UnknownPathSecret packet was received"] + pub struct UnknownPathSecretPacketReceived<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> + for UnknownPathSecretPacketReceived<'a> + { + #[inline] + fn into_event(self) -> api::UnknownPathSecretPacketReceived<'a> { + let UnknownPathSecretPacketReceived { + peer_address, + credential_id, + } = self; + api::UnknownPathSecretPacketReceived { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an UnknownPathSecret packet was authentic and processed"] + pub struct UnknownPathSecretPacketAccepted<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> + for UnknownPathSecretPacketAccepted<'a> + { + #[inline] + fn into_event(self) -> api::UnknownPathSecretPacketAccepted<'a> { + let UnknownPathSecretPacketAccepted { + peer_address, + credential_id, + } = self; + api::UnknownPathSecretPacketAccepted { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an UnknownPathSecret packet was rejected as invalid"] + pub struct UnknownPathSecretPacketRejected<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> + for UnknownPathSecretPacketRejected<'a> + { + #[inline] + fn into_event(self) -> api::UnknownPathSecretPacketRejected<'a> { + let UnknownPathSecretPacketRejected { + peer_address, + credential_id, + } = self; + api::UnknownPathSecretPacketRejected { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when credential replay was definitely detected"] + pub struct ReplayDefinitelyDetected<'a> { + pub credential_id: &'a [u8], + pub key_id: u64, + } + impl<'a> IntoEvent> for ReplayDefinitelyDetected<'a> { + #[inline] + fn into_event(self) -> api::ReplayDefinitelyDetected<'a> { + let ReplayDefinitelyDetected { + credential_id, + key_id, + } = self; + api::ReplayDefinitelyDetected { + credential_id: credential_id.into_event(), + key_id: key_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when credential replay was potentially detected, but could not be verified"] + #[doc = " due to a limiting tracking window"] + pub struct ReplayPotentiallyDetected<'a> { + pub credential_id: &'a [u8], + pub key_id: u64, + pub gap: u64, + } + impl<'a> IntoEvent> for ReplayPotentiallyDetected<'a> { + #[inline] + fn into_event(self) -> api::ReplayPotentiallyDetected<'a> { + let ReplayPotentiallyDetected { + credential_id, + key_id, + gap, + } = self; + api::ReplayPotentiallyDetected { + credential_id: credential_id.into_event(), + key_id: key_id.into_event(), + gap: gap.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an ReplayDetected packet was sent"] + pub struct ReplayDetectedPacketSent<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for ReplayDetectedPacketSent<'a> { + #[inline] + fn into_event(self) -> api::ReplayDetectedPacketSent<'a> { + let ReplayDetectedPacketSent { + peer_address, + credential_id, + } = self; + api::ReplayDetectedPacketSent { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an ReplayDetected packet was received"] + pub struct ReplayDetectedPacketReceived<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for ReplayDetectedPacketReceived<'a> { + #[inline] + fn into_event(self) -> api::ReplayDetectedPacketReceived<'a> { + let ReplayDetectedPacketReceived { + peer_address, + credential_id, + } = self; + api::ReplayDetectedPacketReceived { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an StaleKey packet was authentic and processed"] + pub struct ReplayDetectedPacketAccepted<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + pub key_id: u64, + } + impl<'a> IntoEvent> for ReplayDetectedPacketAccepted<'a> { + #[inline] + fn into_event(self) -> api::ReplayDetectedPacketAccepted<'a> { + let ReplayDetectedPacketAccepted { + peer_address, + credential_id, + key_id, + } = self; + api::ReplayDetectedPacketAccepted { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + key_id: key_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an ReplayDetected packet was rejected as invalid"] + pub struct ReplayDetectedPacketRejected<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for ReplayDetectedPacketRejected<'a> { + #[inline] + fn into_event(self) -> api::ReplayDetectedPacketRejected<'a> { + let ReplayDetectedPacketRejected { + peer_address, + credential_id, + } = self; + api::ReplayDetectedPacketRejected { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an StaleKey packet was sent"] + pub struct StaleKeyPacketSent<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for StaleKeyPacketSent<'a> { + #[inline] + fn into_event(self) -> api::StaleKeyPacketSent<'a> { + let StaleKeyPacketSent { + peer_address, + credential_id, + } = self; + api::StaleKeyPacketSent { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an StaleKey packet was received"] + pub struct StaleKeyPacketReceived<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for StaleKeyPacketReceived<'a> { + #[inline] + fn into_event(self) -> api::StaleKeyPacketReceived<'a> { + let StaleKeyPacketReceived { + peer_address, + credential_id, + } = self; + api::StaleKeyPacketReceived { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an StaleKey packet was authentic and processed"] + pub struct StaleKeyPacketAccepted<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for StaleKeyPacketAccepted<'a> { + #[inline] + fn into_event(self) -> api::StaleKeyPacketAccepted<'a> { + let StaleKeyPacketAccepted { + peer_address, + credential_id, + } = self; + api::StaleKeyPacketAccepted { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] + #[doc = " Emitted when an StaleKey packet was rejected as invalid"] + pub struct StaleKeyPacketRejected<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for StaleKeyPacketRejected<'a> { + #[inline] + fn into_event(self) -> api::StaleKeyPacketRejected<'a> { + let StaleKeyPacketRejected { + peer_address, + credential_id, + } = self; + api::StaleKeyPacketRejected { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } +} +pub use traits::*; +mod traits { + use super::*; + use crate::event::Meta; + use core::fmt; + use s2n_quic_core::query; + #[doc = r" Allows for events to be subscribed to"] + pub trait Subscriber: 'static + Send + Sync { + #[doc = r" An application provided type associated with each connection."] + #[doc = r""] + #[doc = r" The context provides a mechanism for applications to provide a custom type"] + #[doc = r" and update it on each event, e.g. computing statistics. Each event"] + #[doc = r" invocation (e.g. [`Subscriber::on_packet_sent`]) also provides mutable"] + #[doc = r" access to the context `&mut ConnectionContext` and allows for updating the"] + #[doc = r" context."] + #[doc = r""] + #[doc = r" ```no_run"] + #[doc = r" # mod s2n_quic { pub mod provider { pub mod event {"] + #[doc = r" # pub use s2n_quic_core::event::{api as events, api::ConnectionInfo, api::ConnectionMeta, Subscriber};"] + #[doc = r" # }}}"] + #[doc = r" use s2n_quic::provider::event::{"] + #[doc = r" ConnectionInfo, ConnectionMeta, Subscriber, events::PacketSent"] + #[doc = r" };"] + #[doc = r""] + #[doc = r" pub struct MyEventSubscriber;"] + #[doc = r""] + #[doc = r" pub struct MyEventContext {"] + #[doc = r" packet_sent: u64,"] + #[doc = r" }"] + #[doc = r""] + #[doc = r" impl Subscriber for MyEventSubscriber {"] + #[doc = r" type ConnectionContext = MyEventContext;"] + #[doc = r""] + #[doc = r" fn create_connection_context("] + #[doc = r" &mut self, _meta: &ConnectionMeta,"] #[doc = r" _info: &ConnectionInfo,"] #[doc = r" ) -> Self::ConnectionContext {"] #[doc = r" MyEventContext { packet_sent: 0 }"] @@ -233,34 +1133,234 @@ mod traits { ) -> Self::ConnectionContext; #[doc = "Called when the `ApplicationWrite` event is triggered"] #[inline] - fn on_application_write( + fn on_application_write( + &self, + context: &Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationWrite, + ) { + let _ = context; + let _ = meta; + let _ = event; + } + #[doc = "Called when the `ApplicationRead` event is triggered"] + #[inline] + fn on_application_read( + &self, + context: &Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationRead, + ) { + let _ = context; + let _ = meta; + let _ = event; + } + #[doc = "Called when the `EndpointInitialized` event is triggered"] + #[inline] + fn on_endpoint_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::EndpointInitialized, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `PathSecretMapInitialized` event is triggered"] + #[inline] + fn on_path_secret_map_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapInitialized, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `PathSecretMapUninitialized` event is triggered"] + #[inline] + fn on_path_secret_map_uninitialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapUninitialized, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `PathSecretMapBackgroundHandshakeRequested` event is triggered"] + #[inline] + fn on_path_secret_map_background_handshake_requested( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapBackgroundHandshakeRequested, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `PathSecretMapEntryInserted` event is triggered"] + #[inline] + fn on_path_secret_map_entry_inserted( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryInserted, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `PathSecretMapEntryReady` event is triggered"] + #[inline] + fn on_path_secret_map_entry_ready( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReady, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `PathSecretMapEntryReplaced` event is triggered"] + #[inline] + fn on_path_secret_map_entry_replaced( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReplaced, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `UnknownPathSecretPacketSent` event is triggered"] + #[inline] + fn on_unknown_path_secret_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketSent, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `UnknownPathSecretPacketReceived` event is triggered"] + #[inline] + fn on_unknown_path_secret_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketReceived, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `UnknownPathSecretPacketAccepted` event is triggered"] + #[inline] + fn on_unknown_path_secret_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketAccepted, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `UnknownPathSecretPacketRejected` event is triggered"] + #[inline] + fn on_unknown_path_secret_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketRejected, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `ReplayDefinitelyDetected` event is triggered"] + #[inline] + fn on_replay_definitely_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDefinitelyDetected, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `ReplayPotentiallyDetected` event is triggered"] + #[inline] + fn on_replay_potentially_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayPotentiallyDetected, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `ReplayDetectedPacketSent` event is triggered"] + #[inline] + fn on_replay_detected_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketSent, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `ReplayDetectedPacketReceived` event is triggered"] + #[inline] + fn on_replay_detected_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketReceived, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `ReplayDetectedPacketAccepted` event is triggered"] + #[inline] + fn on_replay_detected_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketAccepted, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `ReplayDetectedPacketRejected` event is triggered"] + #[inline] + fn on_replay_detected_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketRejected, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `StaleKeyPacketSent` event is triggered"] + #[inline] + fn on_stale_key_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketSent, + ) { + let _ = meta; + let _ = event; + } + #[doc = "Called when the `StaleKeyPacketReceived` event is triggered"] + #[inline] + fn on_stale_key_packet_received( &self, - context: &Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ApplicationWrite, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketReceived, ) { - let _ = context; let _ = meta; let _ = event; } - #[doc = "Called when the `ApplicationRead` event is triggered"] + #[doc = "Called when the `StaleKeyPacketAccepted` event is triggered"] #[inline] - fn on_application_read( + fn on_stale_key_packet_accepted( &self, - context: &Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ApplicationRead, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketAccepted, ) { - let _ = context; let _ = meta; let _ = event; } - #[doc = "Called when the `EndpointInitialized` event is triggered"] + #[doc = "Called when the `StaleKeyPacketRejected` event is triggered"] #[inline] - fn on_endpoint_initialized( + fn on_stale_key_packet_rejected( &self, meta: &api::EndpointMeta, - event: &api::EndpointInitialized, + event: &api::StaleKeyPacketRejected, ) { let _ = meta; let _ = event; @@ -322,88 +1422,471 @@ mod traits { (self.1).on_application_write(&context.1, meta, event); } #[inline] - fn on_application_read( + fn on_application_read( + &self, + context: &Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &api::ApplicationRead, + ) { + (self.0).on_application_read(&context.0, meta, event); + (self.1).on_application_read(&context.1, meta, event); + } + #[inline] + fn on_endpoint_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::EndpointInitialized, + ) { + (self.0).on_endpoint_initialized(meta, event); + (self.1).on_endpoint_initialized(meta, event); + } + #[inline] + fn on_path_secret_map_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapInitialized, + ) { + (self.0).on_path_secret_map_initialized(meta, event); + (self.1).on_path_secret_map_initialized(meta, event); + } + #[inline] + fn on_path_secret_map_uninitialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapUninitialized, + ) { + (self.0).on_path_secret_map_uninitialized(meta, event); + (self.1).on_path_secret_map_uninitialized(meta, event); + } + #[inline] + fn on_path_secret_map_background_handshake_requested( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapBackgroundHandshakeRequested, + ) { + (self.0).on_path_secret_map_background_handshake_requested(meta, event); + (self.1).on_path_secret_map_background_handshake_requested(meta, event); + } + #[inline] + fn on_path_secret_map_entry_inserted( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryInserted, + ) { + (self.0).on_path_secret_map_entry_inserted(meta, event); + (self.1).on_path_secret_map_entry_inserted(meta, event); + } + #[inline] + fn on_path_secret_map_entry_ready( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReady, + ) { + (self.0).on_path_secret_map_entry_ready(meta, event); + (self.1).on_path_secret_map_entry_ready(meta, event); + } + #[inline] + fn on_path_secret_map_entry_replaced( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReplaced, + ) { + (self.0).on_path_secret_map_entry_replaced(meta, event); + (self.1).on_path_secret_map_entry_replaced(meta, event); + } + #[inline] + fn on_unknown_path_secret_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketSent, + ) { + (self.0).on_unknown_path_secret_packet_sent(meta, event); + (self.1).on_unknown_path_secret_packet_sent(meta, event); + } + #[inline] + fn on_unknown_path_secret_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketReceived, + ) { + (self.0).on_unknown_path_secret_packet_received(meta, event); + (self.1).on_unknown_path_secret_packet_received(meta, event); + } + #[inline] + fn on_unknown_path_secret_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketAccepted, + ) { + (self.0).on_unknown_path_secret_packet_accepted(meta, event); + (self.1).on_unknown_path_secret_packet_accepted(meta, event); + } + #[inline] + fn on_unknown_path_secret_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketRejected, + ) { + (self.0).on_unknown_path_secret_packet_rejected(meta, event); + (self.1).on_unknown_path_secret_packet_rejected(meta, event); + } + #[inline] + fn on_replay_definitely_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDefinitelyDetected, + ) { + (self.0).on_replay_definitely_detected(meta, event); + (self.1).on_replay_definitely_detected(meta, event); + } + #[inline] + fn on_replay_potentially_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayPotentiallyDetected, + ) { + (self.0).on_replay_potentially_detected(meta, event); + (self.1).on_replay_potentially_detected(meta, event); + } + #[inline] + fn on_replay_detected_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketSent, + ) { + (self.0).on_replay_detected_packet_sent(meta, event); + (self.1).on_replay_detected_packet_sent(meta, event); + } + #[inline] + fn on_replay_detected_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketReceived, + ) { + (self.0).on_replay_detected_packet_received(meta, event); + (self.1).on_replay_detected_packet_received(meta, event); + } + #[inline] + fn on_replay_detected_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketAccepted, + ) { + (self.0).on_replay_detected_packet_accepted(meta, event); + (self.1).on_replay_detected_packet_accepted(meta, event); + } + #[inline] + fn on_replay_detected_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketRejected, + ) { + (self.0).on_replay_detected_packet_rejected(meta, event); + (self.1).on_replay_detected_packet_rejected(meta, event); + } + #[inline] + fn on_stale_key_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketSent, + ) { + (self.0).on_stale_key_packet_sent(meta, event); + (self.1).on_stale_key_packet_sent(meta, event); + } + #[inline] + fn on_stale_key_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketReceived, + ) { + (self.0).on_stale_key_packet_received(meta, event); + (self.1).on_stale_key_packet_received(meta, event); + } + #[inline] + fn on_stale_key_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketAccepted, + ) { + (self.0).on_stale_key_packet_accepted(meta, event); + (self.1).on_stale_key_packet_accepted(meta, event); + } + #[inline] + fn on_stale_key_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketRejected, + ) { + (self.0).on_stale_key_packet_rejected(meta, event); + (self.1).on_stale_key_packet_rejected(meta, event); + } + #[inline] + fn on_event(&self, meta: &M, event: &E) { + self.0.on_event(meta, event); + self.1.on_event(meta, event); + } + #[inline] + fn on_connection_event( + &self, + context: &Self::ConnectionContext, + meta: &api::ConnectionMeta, + event: &E, + ) { + self.0.on_connection_event(&context.0, meta, event); + self.1.on_connection_event(&context.1, meta, event); + } + #[inline] + fn query( + context: &Self::ConnectionContext, + query: &mut dyn query::Query, + ) -> query::ControlFlow { + query + .execute(context) + .and_then(|| A::query(&context.0, query)) + .and_then(|| B::query(&context.1, query)) + } + } + pub trait EndpointPublisher { + #[doc = "Publishes a `EndpointInitialized` event to the publisher's subscriber"] + fn on_endpoint_initialized(&self, event: builder::EndpointInitialized); + #[doc = "Publishes a `PathSecretMapInitialized` event to the publisher's subscriber"] + fn on_path_secret_map_initialized(&self, event: builder::PathSecretMapInitialized); + #[doc = "Publishes a `PathSecretMapUninitialized` event to the publisher's subscriber"] + fn on_path_secret_map_uninitialized(&self, event: builder::PathSecretMapUninitialized); + #[doc = "Publishes a `PathSecretMapBackgroundHandshakeRequested` event to the publisher's subscriber"] + fn on_path_secret_map_background_handshake_requested( + &self, + event: builder::PathSecretMapBackgroundHandshakeRequested, + ); + #[doc = "Publishes a `PathSecretMapEntryInserted` event to the publisher's subscriber"] + fn on_path_secret_map_entry_inserted(&self, event: builder::PathSecretMapEntryInserted); + #[doc = "Publishes a `PathSecretMapEntryReady` event to the publisher's subscriber"] + fn on_path_secret_map_entry_ready(&self, event: builder::PathSecretMapEntryReady); + #[doc = "Publishes a `PathSecretMapEntryReplaced` event to the publisher's subscriber"] + fn on_path_secret_map_entry_replaced(&self, event: builder::PathSecretMapEntryReplaced); + #[doc = "Publishes a `UnknownPathSecretPacketSent` event to the publisher's subscriber"] + fn on_unknown_path_secret_packet_sent(&self, event: builder::UnknownPathSecretPacketSent); + #[doc = "Publishes a `UnknownPathSecretPacketReceived` event to the publisher's subscriber"] + fn on_unknown_path_secret_packet_received( + &self, + event: builder::UnknownPathSecretPacketReceived, + ); + #[doc = "Publishes a `UnknownPathSecretPacketAccepted` event to the publisher's subscriber"] + fn on_unknown_path_secret_packet_accepted( + &self, + event: builder::UnknownPathSecretPacketAccepted, + ); + #[doc = "Publishes a `UnknownPathSecretPacketRejected` event to the publisher's subscriber"] + fn on_unknown_path_secret_packet_rejected( + &self, + event: builder::UnknownPathSecretPacketRejected, + ); + #[doc = "Publishes a `ReplayDefinitelyDetected` event to the publisher's subscriber"] + fn on_replay_definitely_detected(&self, event: builder::ReplayDefinitelyDetected); + #[doc = "Publishes a `ReplayPotentiallyDetected` event to the publisher's subscriber"] + fn on_replay_potentially_detected(&self, event: builder::ReplayPotentiallyDetected); + #[doc = "Publishes a `ReplayDetectedPacketSent` event to the publisher's subscriber"] + fn on_replay_detected_packet_sent(&self, event: builder::ReplayDetectedPacketSent); + #[doc = "Publishes a `ReplayDetectedPacketReceived` event to the publisher's subscriber"] + fn on_replay_detected_packet_received(&self, event: builder::ReplayDetectedPacketReceived); + #[doc = "Publishes a `ReplayDetectedPacketAccepted` event to the publisher's subscriber"] + fn on_replay_detected_packet_accepted(&self, event: builder::ReplayDetectedPacketAccepted); + #[doc = "Publishes a `ReplayDetectedPacketRejected` event to the publisher's subscriber"] + fn on_replay_detected_packet_rejected(&self, event: builder::ReplayDetectedPacketRejected); + #[doc = "Publishes a `StaleKeyPacketSent` event to the publisher's subscriber"] + fn on_stale_key_packet_sent(&self, event: builder::StaleKeyPacketSent); + #[doc = "Publishes a `StaleKeyPacketReceived` event to the publisher's subscriber"] + fn on_stale_key_packet_received(&self, event: builder::StaleKeyPacketReceived); + #[doc = "Publishes a `StaleKeyPacketAccepted` event to the publisher's subscriber"] + fn on_stale_key_packet_accepted(&self, event: builder::StaleKeyPacketAccepted); + #[doc = "Publishes a `StaleKeyPacketRejected` event to the publisher's subscriber"] + fn on_stale_key_packet_rejected(&self, event: builder::StaleKeyPacketRejected); + #[doc = r" Returns the QUIC version, if any"] + fn quic_version(&self) -> Option; + } + pub struct EndpointPublisherSubscriber<'a, Sub: Subscriber> { + meta: api::EndpointMeta, + quic_version: Option, + subscriber: &'a Sub, + } + impl<'a, Sub: Subscriber> fmt::Debug for EndpointPublisherSubscriber<'a, Sub> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("ConnectionPublisherSubscriber") + .field("meta", &self.meta) + .field("quic_version", &self.quic_version) + .finish() + } + } + impl<'a, Sub: Subscriber> EndpointPublisherSubscriber<'a, Sub> { + #[inline] + pub fn new( + meta: builder::EndpointMeta, + quic_version: Option, + subscriber: &'a Sub, + ) -> Self { + Self { + meta: meta.into_event(), + quic_version, + subscriber, + } + } + } + impl<'a, Sub: Subscriber> EndpointPublisher for EndpointPublisherSubscriber<'a, Sub> { + #[inline] + fn on_endpoint_initialized(&self, event: builder::EndpointInitialized) { + let event = event.into_event(); + self.subscriber.on_endpoint_initialized(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_path_secret_map_initialized(&self, event: builder::PathSecretMapInitialized) { + let event = event.into_event(); + self.subscriber + .on_path_secret_map_initialized(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_path_secret_map_uninitialized(&self, event: builder::PathSecretMapUninitialized) { + let event = event.into_event(); + self.subscriber + .on_path_secret_map_uninitialized(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_path_secret_map_background_handshake_requested( + &self, + event: builder::PathSecretMapBackgroundHandshakeRequested, + ) { + let event = event.into_event(); + self.subscriber + .on_path_secret_map_background_handshake_requested(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_path_secret_map_entry_inserted(&self, event: builder::PathSecretMapEntryInserted) { + let event = event.into_event(); + self.subscriber + .on_path_secret_map_entry_inserted(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_path_secret_map_entry_ready(&self, event: builder::PathSecretMapEntryReady) { + let event = event.into_event(); + self.subscriber + .on_path_secret_map_entry_ready(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_path_secret_map_entry_replaced(&self, event: builder::PathSecretMapEntryReplaced) { + let event = event.into_event(); + self.subscriber + .on_path_secret_map_entry_replaced(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_unknown_path_secret_packet_sent(&self, event: builder::UnknownPathSecretPacketSent) { + let event = event.into_event(); + self.subscriber + .on_unknown_path_secret_packet_sent(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_unknown_path_secret_packet_received( + &self, + event: builder::UnknownPathSecretPacketReceived, + ) { + let event = event.into_event(); + self.subscriber + .on_unknown_path_secret_packet_received(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_unknown_path_secret_packet_accepted( + &self, + event: builder::UnknownPathSecretPacketAccepted, + ) { + let event = event.into_event(); + self.subscriber + .on_unknown_path_secret_packet_accepted(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_unknown_path_secret_packet_rejected( &self, - context: &Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &api::ApplicationRead, + event: builder::UnknownPathSecretPacketRejected, ) { - (self.0).on_application_read(&context.0, meta, event); - (self.1).on_application_read(&context.1, meta, event); + let event = event.into_event(); + self.subscriber + .on_unknown_path_secret_packet_rejected(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); } #[inline] - fn on_endpoint_initialized( - &self, - meta: &api::EndpointMeta, - event: &api::EndpointInitialized, - ) { - (self.0).on_endpoint_initialized(meta, event); - (self.1).on_endpoint_initialized(meta, event); + fn on_replay_definitely_detected(&self, event: builder::ReplayDefinitelyDetected) { + let event = event.into_event(); + self.subscriber + .on_replay_definitely_detected(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); } #[inline] - fn on_event(&self, meta: &M, event: &E) { - self.0.on_event(meta, event); - self.1.on_event(meta, event); + fn on_replay_potentially_detected(&self, event: builder::ReplayPotentiallyDetected) { + let event = event.into_event(); + self.subscriber + .on_replay_potentially_detected(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); } #[inline] - fn on_connection_event( - &self, - context: &Self::ConnectionContext, - meta: &api::ConnectionMeta, - event: &E, - ) { - self.0.on_connection_event(&context.0, meta, event); - self.1.on_connection_event(&context.1, meta, event); + fn on_replay_detected_packet_sent(&self, event: builder::ReplayDetectedPacketSent) { + let event = event.into_event(); + self.subscriber + .on_replay_detected_packet_sent(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); } #[inline] - fn query( - context: &Self::ConnectionContext, - query: &mut dyn query::Query, - ) -> query::ControlFlow { - query - .execute(context) - .and_then(|| A::query(&context.0, query)) - .and_then(|| B::query(&context.1, query)) + fn on_replay_detected_packet_received(&self, event: builder::ReplayDetectedPacketReceived) { + let event = event.into_event(); + self.subscriber + .on_replay_detected_packet_received(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); } - } - pub trait EndpointPublisher { - #[doc = "Publishes a `EndpointInitialized` event to the publisher's subscriber"] - fn on_endpoint_initialized(&self, event: builder::EndpointInitialized); - #[doc = r" Returns the QUIC version, if any"] - fn quic_version(&self) -> Option; - } - pub struct EndpointPublisherSubscriber<'a, Sub: Subscriber> { - meta: api::EndpointMeta, - quic_version: Option, - subscriber: &'a Sub, - } - impl<'a, Sub: Subscriber> fmt::Debug for EndpointPublisherSubscriber<'a, Sub> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("ConnectionPublisherSubscriber") - .field("meta", &self.meta) - .field("quic_version", &self.quic_version) - .finish() + #[inline] + fn on_replay_detected_packet_accepted(&self, event: builder::ReplayDetectedPacketAccepted) { + let event = event.into_event(); + self.subscriber + .on_replay_detected_packet_accepted(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); } - } - impl<'a, Sub: Subscriber> EndpointPublisherSubscriber<'a, Sub> { #[inline] - pub fn new( - meta: builder::EndpointMeta, - quic_version: Option, - subscriber: &'a Sub, - ) -> Self { - Self { - meta: meta.into_event(), - quic_version, - subscriber, - } + fn on_replay_detected_packet_rejected(&self, event: builder::ReplayDetectedPacketRejected) { + let event = event.into_event(); + self.subscriber + .on_replay_detected_packet_rejected(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); } - } - impl<'a, Sub: Subscriber> EndpointPublisher for EndpointPublisherSubscriber<'a, Sub> { #[inline] - fn on_endpoint_initialized(&self, event: builder::EndpointInitialized) { + fn on_stale_key_packet_sent(&self, event: builder::StaleKeyPacketSent) { let event = event.into_event(); - self.subscriber.on_endpoint_initialized(&self.meta, &event); + self.subscriber.on_stale_key_packet_sent(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_stale_key_packet_received(&self, event: builder::StaleKeyPacketReceived) { + let event = event.into_event(); + self.subscriber + .on_stale_key_packet_received(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_stale_key_packet_accepted(&self, event: builder::StaleKeyPacketAccepted) { + let event = event.into_event(); + self.subscriber + .on_stale_key_packet_accepted(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] + fn on_stale_key_packet_rejected(&self, event: builder::StaleKeyPacketRejected) { + let event = event.into_event(); + self.subscriber + .on_stale_key_packet_rejected(&self.meta, &event); self.subscriber.on_event(&self.meta, &event); } #[inline] @@ -568,6 +2051,26 @@ pub mod testing { location: Option, output: Mutex>, pub endpoint_initialized: AtomicU32, + pub path_secret_map_initialized: AtomicU32, + pub path_secret_map_uninitialized: AtomicU32, + pub path_secret_map_background_handshake_requested: AtomicU32, + pub path_secret_map_entry_inserted: AtomicU32, + pub path_secret_map_entry_ready: AtomicU32, + pub path_secret_map_entry_replaced: AtomicU32, + pub unknown_path_secret_packet_sent: AtomicU32, + pub unknown_path_secret_packet_received: AtomicU32, + pub unknown_path_secret_packet_accepted: AtomicU32, + pub unknown_path_secret_packet_rejected: AtomicU32, + pub replay_definitely_detected: AtomicU32, + pub replay_potentially_detected: AtomicU32, + pub replay_detected_packet_sent: AtomicU32, + pub replay_detected_packet_received: AtomicU32, + pub replay_detected_packet_accepted: AtomicU32, + pub replay_detected_packet_rejected: AtomicU32, + pub stale_key_packet_sent: AtomicU32, + pub stale_key_packet_received: AtomicU32, + pub stale_key_packet_accepted: AtomicU32, + pub stale_key_packet_rejected: AtomicU32, } impl Drop for Subscriber { fn drop(&mut self) { @@ -600,23 +2103,282 @@ pub mod testing { location: None, output: Default::default(), endpoint_initialized: AtomicU32::new(0), + path_secret_map_initialized: AtomicU32::new(0), + path_secret_map_uninitialized: AtomicU32::new(0), + path_secret_map_background_handshake_requested: AtomicU32::new(0), + path_secret_map_entry_inserted: AtomicU32::new(0), + path_secret_map_entry_ready: AtomicU32::new(0), + path_secret_map_entry_replaced: AtomicU32::new(0), + unknown_path_secret_packet_sent: AtomicU32::new(0), + unknown_path_secret_packet_received: AtomicU32::new(0), + unknown_path_secret_packet_accepted: AtomicU32::new(0), + unknown_path_secret_packet_rejected: AtomicU32::new(0), + replay_definitely_detected: AtomicU32::new(0), + replay_potentially_detected: AtomicU32::new(0), + replay_detected_packet_sent: AtomicU32::new(0), + replay_detected_packet_received: AtomicU32::new(0), + replay_detected_packet_accepted: AtomicU32::new(0), + replay_detected_packet_rejected: AtomicU32::new(0), + stale_key_packet_sent: AtomicU32::new(0), + stale_key_packet_received: AtomicU32::new(0), + stale_key_packet_accepted: AtomicU32::new(0), + stale_key_packet_rejected: AtomicU32::new(0), } } - } - impl super::super::Subscriber for Subscriber { - type ConnectionContext = (); - fn create_connection_context( + } + impl super::super::Subscriber for Subscriber { + type ConnectionContext = (); + fn create_connection_context( + &self, + _meta: &api::ConnectionMeta, + _info: &api::ConnectionInfo, + ) -> Self::ConnectionContext { + } + fn on_endpoint_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::EndpointInitialized, + ) { + self.endpoint_initialized.fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapInitialized, + ) { + self.path_secret_map_initialized + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_uninitialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapUninitialized, + ) { + self.path_secret_map_uninitialized + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_background_handshake_requested( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapBackgroundHandshakeRequested, + ) { + self.path_secret_map_background_handshake_requested + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_entry_inserted( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryInserted, + ) { + self.path_secret_map_entry_inserted + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_entry_ready( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReady, + ) { + self.path_secret_map_entry_ready + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_entry_replaced( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReplaced, + ) { + self.path_secret_map_entry_replaced + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_unknown_path_secret_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketSent, + ) { + self.unknown_path_secret_packet_sent + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_unknown_path_secret_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketReceived, + ) { + self.unknown_path_secret_packet_received + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_unknown_path_secret_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketAccepted, + ) { + self.unknown_path_secret_packet_accepted + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_unknown_path_secret_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketRejected, + ) { + self.unknown_path_secret_packet_rejected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_definitely_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDefinitelyDetected, + ) { + self.replay_definitely_detected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_potentially_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayPotentiallyDetected, + ) { + self.replay_potentially_detected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_detected_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketSent, + ) { + self.replay_detected_packet_sent + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_detected_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketReceived, + ) { + self.replay_detected_packet_received + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_detected_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketAccepted, + ) { + self.replay_detected_packet_accepted + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_detected_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketRejected, + ) { + self.replay_detected_packet_rejected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_stale_key_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketSent, + ) { + self.stale_key_packet_sent.fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_stale_key_packet_received( &self, - _meta: &api::ConnectionMeta, - _info: &api::ConnectionInfo, - ) -> Self::ConnectionContext { + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketReceived, + ) { + self.stale_key_packet_received + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); } - fn on_endpoint_initialized( + fn on_stale_key_packet_accepted( &self, meta: &api::EndpointMeta, - event: &api::EndpointInitialized, + event: &api::StaleKeyPacketAccepted, ) { - self.endpoint_initialized.fetch_add(1, Ordering::Relaxed); + self.stale_key_packet_accepted + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_stale_key_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketRejected, + ) { + self.stale_key_packet_rejected + .fetch_add(1, Ordering::Relaxed); self.output .lock() .unwrap() @@ -631,6 +2393,26 @@ pub mod testing { pub application_write: AtomicU32, pub application_read: AtomicU32, pub endpoint_initialized: AtomicU32, + pub path_secret_map_initialized: AtomicU32, + pub path_secret_map_uninitialized: AtomicU32, + pub path_secret_map_background_handshake_requested: AtomicU32, + pub path_secret_map_entry_inserted: AtomicU32, + pub path_secret_map_entry_ready: AtomicU32, + pub path_secret_map_entry_replaced: AtomicU32, + pub unknown_path_secret_packet_sent: AtomicU32, + pub unknown_path_secret_packet_received: AtomicU32, + pub unknown_path_secret_packet_accepted: AtomicU32, + pub unknown_path_secret_packet_rejected: AtomicU32, + pub replay_definitely_detected: AtomicU32, + pub replay_potentially_detected: AtomicU32, + pub replay_detected_packet_sent: AtomicU32, + pub replay_detected_packet_received: AtomicU32, + pub replay_detected_packet_accepted: AtomicU32, + pub replay_detected_packet_rejected: AtomicU32, + pub stale_key_packet_sent: AtomicU32, + pub stale_key_packet_received: AtomicU32, + pub stale_key_packet_accepted: AtomicU32, + pub stale_key_packet_rejected: AtomicU32, } impl Drop for Subscriber { fn drop(&mut self) { @@ -665,6 +2447,26 @@ pub mod testing { application_write: AtomicU32::new(0), application_read: AtomicU32::new(0), endpoint_initialized: AtomicU32::new(0), + path_secret_map_initialized: AtomicU32::new(0), + path_secret_map_uninitialized: AtomicU32::new(0), + path_secret_map_background_handshake_requested: AtomicU32::new(0), + path_secret_map_entry_inserted: AtomicU32::new(0), + path_secret_map_entry_ready: AtomicU32::new(0), + path_secret_map_entry_replaced: AtomicU32::new(0), + unknown_path_secret_packet_sent: AtomicU32::new(0), + unknown_path_secret_packet_received: AtomicU32::new(0), + unknown_path_secret_packet_accepted: AtomicU32::new(0), + unknown_path_secret_packet_rejected: AtomicU32::new(0), + replay_definitely_detected: AtomicU32::new(0), + replay_potentially_detected: AtomicU32::new(0), + replay_detected_packet_sent: AtomicU32::new(0), + replay_detected_packet_received: AtomicU32::new(0), + replay_detected_packet_accepted: AtomicU32::new(0), + replay_detected_packet_rejected: AtomicU32::new(0), + stale_key_packet_sent: AtomicU32::new(0), + stale_key_packet_received: AtomicU32::new(0), + stale_key_packet_accepted: AtomicU32::new(0), + stale_key_packet_rejected: AtomicU32::new(0), } } } @@ -715,6 +2517,245 @@ pub mod testing { .unwrap() .push(format!("{meta:?} {event:?}")); } + fn on_path_secret_map_initialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapInitialized, + ) { + self.path_secret_map_initialized + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_uninitialized( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapUninitialized, + ) { + self.path_secret_map_uninitialized + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_background_handshake_requested( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapBackgroundHandshakeRequested, + ) { + self.path_secret_map_background_handshake_requested + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_entry_inserted( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryInserted, + ) { + self.path_secret_map_entry_inserted + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_entry_ready( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReady, + ) { + self.path_secret_map_entry_ready + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_path_secret_map_entry_replaced( + &self, + meta: &api::EndpointMeta, + event: &api::PathSecretMapEntryReplaced, + ) { + self.path_secret_map_entry_replaced + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_unknown_path_secret_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketSent, + ) { + self.unknown_path_secret_packet_sent + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_unknown_path_secret_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketReceived, + ) { + self.unknown_path_secret_packet_received + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_unknown_path_secret_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketAccepted, + ) { + self.unknown_path_secret_packet_accepted + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_unknown_path_secret_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketRejected, + ) { + self.unknown_path_secret_packet_rejected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_definitely_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDefinitelyDetected, + ) { + self.replay_definitely_detected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_potentially_detected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayPotentiallyDetected, + ) { + self.replay_potentially_detected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_detected_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketSent, + ) { + self.replay_detected_packet_sent + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_detected_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketReceived, + ) { + self.replay_detected_packet_received + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_detected_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketAccepted, + ) { + self.replay_detected_packet_accepted + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_replay_detected_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketRejected, + ) { + self.replay_detected_packet_rejected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_stale_key_packet_sent( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketSent, + ) { + self.stale_key_packet_sent.fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_stale_key_packet_received( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketReceived, + ) { + self.stale_key_packet_received + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_stale_key_packet_accepted( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketAccepted, + ) { + self.stale_key_packet_accepted + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } + fn on_stale_key_packet_rejected( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketRejected, + ) { + self.stale_key_packet_rejected + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } } #[derive(Debug)] pub struct Publisher { @@ -723,6 +2764,26 @@ pub mod testing { pub application_write: AtomicU32, pub application_read: AtomicU32, pub endpoint_initialized: AtomicU32, + pub path_secret_map_initialized: AtomicU32, + pub path_secret_map_uninitialized: AtomicU32, + pub path_secret_map_background_handshake_requested: AtomicU32, + pub path_secret_map_entry_inserted: AtomicU32, + pub path_secret_map_entry_ready: AtomicU32, + pub path_secret_map_entry_replaced: AtomicU32, + pub unknown_path_secret_packet_sent: AtomicU32, + pub unknown_path_secret_packet_received: AtomicU32, + pub unknown_path_secret_packet_accepted: AtomicU32, + pub unknown_path_secret_packet_rejected: AtomicU32, + pub replay_definitely_detected: AtomicU32, + pub replay_potentially_detected: AtomicU32, + pub replay_detected_packet_sent: AtomicU32, + pub replay_detected_packet_received: AtomicU32, + pub replay_detected_packet_accepted: AtomicU32, + pub replay_detected_packet_rejected: AtomicU32, + pub stale_key_packet_sent: AtomicU32, + pub stale_key_packet_received: AtomicU32, + pub stale_key_packet_accepted: AtomicU32, + pub stale_key_packet_rejected: AtomicU32, } impl Publisher { #[doc = r" Creates a publisher with snapshot assertions enabled"] @@ -747,6 +2808,26 @@ pub mod testing { application_write: AtomicU32::new(0), application_read: AtomicU32::new(0), endpoint_initialized: AtomicU32::new(0), + path_secret_map_initialized: AtomicU32::new(0), + path_secret_map_uninitialized: AtomicU32::new(0), + path_secret_map_background_handshake_requested: AtomicU32::new(0), + path_secret_map_entry_inserted: AtomicU32::new(0), + path_secret_map_entry_ready: AtomicU32::new(0), + path_secret_map_entry_replaced: AtomicU32::new(0), + unknown_path_secret_packet_sent: AtomicU32::new(0), + unknown_path_secret_packet_received: AtomicU32::new(0), + unknown_path_secret_packet_accepted: AtomicU32::new(0), + unknown_path_secret_packet_rejected: AtomicU32::new(0), + replay_definitely_detected: AtomicU32::new(0), + replay_potentially_detected: AtomicU32::new(0), + replay_detected_packet_sent: AtomicU32::new(0), + replay_detected_packet_received: AtomicU32::new(0), + replay_detected_packet_accepted: AtomicU32::new(0), + replay_detected_packet_rejected: AtomicU32::new(0), + stale_key_packet_sent: AtomicU32::new(0), + stale_key_packet_received: AtomicU32::new(0), + stale_key_packet_accepted: AtomicU32::new(0), + stale_key_packet_rejected: AtomicU32::new(0), } } } @@ -756,6 +2837,137 @@ pub mod testing { let event = event.into_event(); self.output.lock().unwrap().push(format!("{event:?}")); } + fn on_path_secret_map_initialized(&self, event: builder::PathSecretMapInitialized) { + self.path_secret_map_initialized + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_path_secret_map_uninitialized(&self, event: builder::PathSecretMapUninitialized) { + self.path_secret_map_uninitialized + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_path_secret_map_background_handshake_requested( + &self, + event: builder::PathSecretMapBackgroundHandshakeRequested, + ) { + self.path_secret_map_background_handshake_requested + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_path_secret_map_entry_inserted(&self, event: builder::PathSecretMapEntryInserted) { + self.path_secret_map_entry_inserted + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_path_secret_map_entry_ready(&self, event: builder::PathSecretMapEntryReady) { + self.path_secret_map_entry_ready + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_path_secret_map_entry_replaced(&self, event: builder::PathSecretMapEntryReplaced) { + self.path_secret_map_entry_replaced + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_unknown_path_secret_packet_sent(&self, event: builder::UnknownPathSecretPacketSent) { + self.unknown_path_secret_packet_sent + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_unknown_path_secret_packet_received( + &self, + event: builder::UnknownPathSecretPacketReceived, + ) { + self.unknown_path_secret_packet_received + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_unknown_path_secret_packet_accepted( + &self, + event: builder::UnknownPathSecretPacketAccepted, + ) { + self.unknown_path_secret_packet_accepted + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_unknown_path_secret_packet_rejected( + &self, + event: builder::UnknownPathSecretPacketRejected, + ) { + self.unknown_path_secret_packet_rejected + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_replay_definitely_detected(&self, event: builder::ReplayDefinitelyDetected) { + self.replay_definitely_detected + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_replay_potentially_detected(&self, event: builder::ReplayPotentiallyDetected) { + self.replay_potentially_detected + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_replay_detected_packet_sent(&self, event: builder::ReplayDetectedPacketSent) { + self.replay_detected_packet_sent + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_replay_detected_packet_received(&self, event: builder::ReplayDetectedPacketReceived) { + self.replay_detected_packet_received + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_replay_detected_packet_accepted(&self, event: builder::ReplayDetectedPacketAccepted) { + self.replay_detected_packet_accepted + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_replay_detected_packet_rejected(&self, event: builder::ReplayDetectedPacketRejected) { + self.replay_detected_packet_rejected + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_stale_key_packet_sent(&self, event: builder::StaleKeyPacketSent) { + self.stale_key_packet_sent.fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_stale_key_packet_received(&self, event: builder::StaleKeyPacketReceived) { + self.stale_key_packet_received + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_stale_key_packet_accepted(&self, event: builder::StaleKeyPacketAccepted) { + self.stale_key_packet_accepted + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } + fn on_stale_key_packet_rejected(&self, event: builder::StaleKeyPacketRejected) { + self.stale_key_packet_rejected + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } fn quic_version(&self) -> Option { Some(1) } diff --git a/dc/s2n-quic-dc/src/path/secret/map.rs b/dc/s2n-quic-dc/src/path/secret/map.rs index 22deb37a7..09f36a8c3 100644 --- a/dc/s2n-quic-dc/src/path/secret/map.rs +++ b/dc/s2n-quic-dc/src/path/secret/map.rs @@ -3,6 +3,7 @@ use crate::{ credentials::{Credentials, Id}, + event, packet::{secret_control as control, Packet}, path::secret::{open, seal, stateless_reset}, stream::TransportFeatures, @@ -43,10 +44,13 @@ pub struct Map { } impl Map { - pub fn new(signer: stateless_reset::Signer, capacity: usize) -> Self { - // TODO add the subscriber - let state = state::State::new(signer, capacity); - Self { store: state } + pub fn new( + signer: stateless_reset::Signer, + capacity: usize, + subscriber: S, + ) -> Self { + let store = state::State::new(signer, capacity, subscriber); + Self { store } } /// The number of trusted secrets. @@ -134,12 +138,12 @@ impl Map { /// /// For secret control packets, this will process those. /// For other packets, the map may collect metrics but will otherwise drop the packets. - pub fn handle_unexpected_packet(&self, packet: &Packet) { - self.store.handle_unexpected_packet(packet); + pub fn handle_unexpected_packet(&self, packet: &Packet, peer: &SocketAddr) { + self.store.handle_unexpected_packet(packet, peer); } - pub fn handle_control_packet(&self, packet: &control::Packet) { - self.store.handle_control_packet(packet) + pub fn handle_control_packet(&self, packet: &control::Packet, peer: &SocketAddr) { + self.store.handle_control_packet(packet, peer) } #[doc(hidden)] @@ -153,7 +157,11 @@ impl Map { ) -> (Self, Vec) { use crate::path::secret::{receiver, schedule, sender}; - let provider = Self::new(stateless_reset::Signer::random(), peers.len() * 3); + let provider = Self::new( + stateless_reset::Signer::random(), + peers.len() * 3, + event::testing::Subscriber::no_snapshot(), + ); let mut secret = [0; 32]; aws_lc_rs::rand::fill(&mut secret).unwrap(); let mut stateless_reset = [0; control::TAG_LEN]; diff --git a/dc/s2n-quic-dc/src/path/secret/map/cleaner.rs b/dc/s2n-quic-dc/src/path/secret/map/cleaner.rs index a5081407f..b47d08742 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/cleaner.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/cleaner.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use super::state::State; +use crate::event; use rand::Rng as _; use std::{ sync::{ @@ -50,7 +51,7 @@ impl Cleaner { } } - pub fn spawn_thread(&self, state: Arc) { + pub fn spawn_thread(&self, state: Arc>) { let state = Arc::downgrade(&state); let handle = std::thread::spawn(move || loop { let Some(state) = state.upgrade() else { @@ -68,7 +69,7 @@ impl Cleaner { } /// Periodic maintenance for various maps. - pub fn clean(&self, state: &State, eviction_cycles: u64) { + pub fn clean(&self, state: &State, eviction_cycles: u64) { let current_epoch = self.epoch.fetch_add(1, Ordering::Relaxed); let now = Instant::now(); diff --git a/dc/s2n-quic-dc/src/path/secret/map/handshake.rs b/dc/s2n-quic-dc/src/path/secret/map/handshake.rs index cb9ccf7aa..5d574c9a8 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/handshake.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/handshake.rs @@ -57,7 +57,7 @@ impl dc::Endpoint for Map { &mut self, // TODO: Maybe we should confirm that the sender IP at least matches the IP for the // corresponding control secret? - _datagram_info: &DatagramInfo, + datagram_info: &DatagramInfo, payload: &mut [u8], ) -> bool { let payload = s2n_codec::DecoderBufferMut::new(payload); @@ -68,7 +68,7 @@ impl dc::Endpoint for Map { ensure!(tail.is_empty(), false); // If we successfully decoded a control packet, pass it into our map to handle. - self.handle_control_packet(&packet); + self.handle_control_packet(&packet, &datagram_info.remote_address.clone().into()); true } diff --git a/dc/s2n-quic-dc/src/path/secret/map/state.rs b/dc/s2n-quic-dc/src/path/secret/map/state.rs index 141236f86..6fc3cd4e8 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/state.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/state.rs @@ -3,18 +3,18 @@ use super::{cleaner::Cleaner, stateless_reset, Entry, Store}; use crate::{ - credentials::Id, + credentials::{Credentials, Id}, + crypto, + event::{self, EndpointPublisher as _, IntoEvent as _}, fixed_map::{self, ReadGuard}, packet::{secret_control as control, Packet}, path::secret::receiver, }; +use s2n_quic_core::inet::SocketAddress; use std::{ hash::{BuildHasherDefault, Hasher}, net::{Ipv4Addr, SocketAddr}, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }, + sync::Arc, time::Duration, }; @@ -39,7 +39,7 @@ mod tests; // is defined by access to the entry in the map. Unfortunately we lack any good way to authenticate // a peer as *not* having credentials, especially after the peer is gone. It's possible that in the // future information could also come from the TLS provider. -pub(super) struct State { +pub(super) struct State { // This is in number of entries. max_capacity: usize, @@ -70,16 +70,17 @@ pub(super) struct State { // This socket is used *only* for sending secret control packets. // FIXME: This will get replaced with sending on a handshake socket associated with the map. pub(super) control_socket: std::net::UdpSocket, + control_socket_port: u16, pub(super) receiver_shared: Arc, - handled_control_packets: AtomicUsize, - cleaner: Cleaner, + + subscriber: S, } -impl State { - pub fn new(signer: stateless_reset::Signer, capacity: usize) -> Arc { +impl State { + pub fn new(signer: stateless_reset::Signer, capacity: usize, subscriber: S) -> Arc { // FIXME: Avoid unwrap and the whole socket. // // We only ever send on this socket - but we really should be sending on the same @@ -89,6 +90,7 @@ impl State { // of implementation). let control_socket = std::net::UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).unwrap(); control_socket.set_nonblocking(true).unwrap(); + let control_socket_port = control_socket.local_addr().unwrap().port(); let state = Self { // This is around 500MB with current entry size. @@ -100,17 +102,23 @@ impl State { requested_handshakes: Default::default(), cleaner: Cleaner::new(), signer, - receiver_shared: receiver::Shared::new(), - - handled_control_packets: AtomicUsize::new(0), control_socket, + control_socket_port, + subscriber, }; let state = Arc::new(state); state.cleaner.spawn_thread(state.clone()); + state.subscriber().on_path_secret_map_initialized( + event::builder::PathSecretMapInitialized { + capacity, + control_socket_port, + }, + ); + state } @@ -119,13 +127,33 @@ impl State { let handshakes = self.requested_handshakes.pin(); if handshakes.len() <= 6000 { handshakes.insert(peer); + self.subscriber() + .on_path_secret_map_background_handshake_requested( + event::builder::PathSecretMapBackgroundHandshakeRequested { + peer_address: SocketAddress::from(peer).into_event(), + }, + ); } } - fn handle_unknown_secret_packet(&self, packet: &control::unknown_path_secret::Packet) { + fn handle_unknown_secret( + &self, + packet: &control::unknown_path_secret::Packet, + peer: &SocketAddress, + ) { + let peer_address = peer.into_event(); + + self.subscriber().on_unknown_path_secret_packet_received( + event::builder::UnknownPathSecretPacketReceived { + credential_id: packet.credential_id().into_event(), + peer_address, + }, + ); + let Some(entry) = self.get_by_id(packet.credential_id()) else { return; }; + // Do not mark as live, this is lightly authenticated. // ensure the packet is authentic @@ -133,16 +161,120 @@ impl State { .authenticate(&entry.sender().stateless_reset) .is_none() { + self.subscriber().on_unknown_path_secret_packet_rejected( + event::builder::UnknownPathSecretPacketRejected { + credential_id: packet.credential_id().into_event(), + peer_address, + }, + ); + return; } - self.handled_control_packets.fetch_add(1, Ordering::Relaxed); + self.subscriber().on_unknown_path_secret_packet_accepted( + event::builder::UnknownPathSecretPacketAccepted { + credential_id: packet.credential_id().into_event(), + peer_address, + }, + ); // FIXME: More actively schedule a new handshake. // See comment on requested_handshakes for details. self.request_handshake(*entry.peer()); } + fn handle_stale_key(&self, packet: &control::stale_key::Packet, peer: &SocketAddress) { + let peer_address = peer.into_event(); + + self.subscriber() + .on_stale_key_packet_received(event::builder::StaleKeyPacketReceived { + credential_id: packet.credential_id().into_event(), + peer_address, + }); + + let Some(entry) = self.ids.get_by_key(packet.credential_id()) else { + // If we get a control packet we don't have a registered path secret for, ignore the + // packet. + return; + }; + + let key = entry.control_secret(); + + let Some(packet) = packet.authenticate(&key) else { + self.subscriber().on_stale_key_packet_rejected( + event::builder::StaleKeyPacketRejected { + credential_id: packet.credential_id().into_event(), + peer_address, + }, + ); + + return; + }; + + self.subscriber() + .on_stale_key_packet_accepted(event::builder::StaleKeyPacketAccepted { + credential_id: packet.credential_id.into_event(), + peer_address, + }); + + entry.sender().update_for_stale_key(packet.min_key_id); + } + + fn handle_replay_detected( + &self, + packet: &control::replay_detected::Packet, + peer: &SocketAddress, + ) { + let peer_address = peer.into_event(); + + self.subscriber().on_replay_detected_packet_received( + event::builder::ReplayDetectedPacketReceived { + credential_id: packet.credential_id().into_event(), + peer_address, + }, + ); + + let Some(entry) = self.ids.get_by_key(packet.credential_id()) else { + // If we get a control packet we don't have a registered path secret for, ignore the + // packet. + return; + }; + + let key = entry.control_secret(); + + let Some(packet) = packet.authenticate(&key) else { + self.subscriber().on_replay_detected_packet_rejected( + event::builder::ReplayDetectedPacketRejected { + credential_id: packet.credential_id().into_event(), + peer_address, + }, + ); + return; + }; + + self.subscriber().on_replay_detected_packet_accepted( + event::builder::ReplayDetectedPacketAccepted { + credential_id: packet.credential_id.into_event(), + key_id: packet.rejected_key_id.into_event(), + peer_address, + }, + ); + + // If we see replay then we're going to assume that we should re-handshake in the + // background with this peer. Currently we can't handshake in the background (only + // in the foreground on next handshake_with). + // + // Note that there's no good way for us to prevent an attacker causing us to hit + // this code: they can always trivially replay a packet we send. At most we could + // de-duplicate *receiving* so there's one handshake per sent packet at most, but + // that's not particularly useful: we expect to send a lot of new packets that + // could be harvested. + // + // Handshaking will be rate limited per destination peer (and at least + // de-duplicated). + self.request_handshake(*entry.peer()); + } + pub fn cleaner(&self) -> &Cleaner { &self.cleaner } @@ -154,9 +286,17 @@ impl State { self.peers = fixed_map::Map::with_capacity(new, Default::default()); self.ids = fixed_map::Map::with_capacity(new, Default::default()); } + + fn subscriber(&self) -> event::EndpointPublisherSubscriber { + event::EndpointPublisherSubscriber::new( + event::builder::EndpointMeta {}, + None, + &self.subscriber, + ) + } } -impl Store for State { +impl Store for State { fn secrets_len(&self) -> usize { self.ids.len() } @@ -179,26 +319,52 @@ impl Store for State { } fn on_new_path_secrets(&self, entry: Arc) { - // On insert clear our interest in a handshake. - self.requested_handshakes.pin().remove(entry.peer()); let id = *entry.id(); + let peer = entry.peer(); + + // On insert clear our interest in a handshake. + self.requested_handshakes.pin().remove(peer); + if self.ids.insert(id, entry.clone()).is_some() { // FIXME: Make insertion fallible and fail handshakes instead? panic!("inserting a path secret ID twice"); } + + self.subscriber().on_path_secret_map_entry_inserted( + event::builder::PathSecretMapEntryInserted { + peer_address: SocketAddress::from(*peer).into_event(), + credential_id: id.into_event(), + }, + ); } fn on_handshake_complete(&self, entry: Arc) { let id = *entry.id(); let peer = *entry.peer(); + if let Some(prev) = self.peers.insert(peer, entry) { // This shouldn't happen due to the panic in on_new_path_secrets, but just // in case something went wrong with the secret map we double check here. // FIXME: Make insertion fallible and fail handshakes instead? - assert_ne!(*prev.id(), id, "duplicate path secret id"); + let prev_id = *prev.id(); + assert_ne!(prev_id, id, "duplicate path secret id"); prev.retire(self.cleaner.epoch()); + + self.subscriber().on_path_secret_map_entry_replaced( + event::builder::PathSecretMapEntryReplaced { + peer_address: SocketAddress::from(peer).into_event(), + new_credential_id: id.into_event(), + previous_credential_id: prev_id.into_event(), + }, + ); } + + self.subscriber() + .on_path_secret_map_entry_ready(event::builder::PathSecretMapEntryReady { + peer_address: SocketAddress::from(peer).into_event(), + credential_id: id.into_event(), + }); } fn get_by_addr(&self, peer: &SocketAddr) -> Option>> { @@ -209,52 +375,19 @@ impl Store for State { self.ids.get_by_key(id) } - fn handle_control_packet(&self, packet: &control::Packet) { - if let control::Packet::UnknownPathSecret(ref packet) = &packet { - return self.handle_unknown_secret_packet(packet); - } - - let Some(entry) = self.ids.get_by_key(packet.credential_id()) else { - // If we get a control packet we don't have a registered path secret for, ignore the - // packet. - return; - }; - - let key = entry.control_secret(); - + fn handle_control_packet(&self, packet: &control::Packet, peer: &SocketAddr) { match packet { - control::Packet::StaleKey(packet) => { - let Some(packet) = packet.authenticate(&key) else { - return; - }; - entry.sender().update_for_stale_key(packet.min_key_id); - self.handled_control_packets.fetch_add(1, Ordering::Relaxed); - } + control::Packet::StaleKey(packet) => self.handle_stale_key(packet, &(*peer).into()), control::Packet::ReplayDetected(packet) => { - let Some(_packet) = packet.authenticate(&key) else { - return; - }; - self.handled_control_packets.fetch_add(1, Ordering::Relaxed); - - // If we see replay then we're going to assume that we should re-handshake in the - // background with this peer. Currently we can't handshake in the background (only - // in the foreground on next handshake_with). - // - // Note that there's no good way for us to prevent an attacker causing us to hit - // this code: they can always trivially replay a packet we send. At most we could - // de-duplicate *receiving* so there's one handshake per sent packet at most, but - // that's not particularly useful: we expect to send a lot of new packets that - // could be harvested. - // - // Handshaking will be rate limited per destination peer (and at least - // de-duplicated). - self.request_handshake(*entry.peer()); + self.handle_replay_detected(packet, &(*peer).into()) + } + control::Packet::UnknownPathSecret(packet) => { + self.handle_unknown_secret(packet, &(*peer).into()) } - control::Packet::UnknownPathSecret(_) => unreachable!(), } } - fn handle_unexpected_packet(&self, packet: &Packet) { + fn handle_unexpected_packet(&self, packet: &Packet, peer: &SocketAddr) { match packet { Packet::Stream(_) => { // no action for now. FIXME: Add metrics. @@ -265,9 +398,11 @@ impl Store for State { Packet::Control(_) => { // no action for now. FIXME: Add metrics. } - Packet::StaleKey(packet) => self.handle_control_packet(&(*packet).into()), - Packet::ReplayDetected(packet) => self.handle_control_packet(&(*packet).into()), - Packet::UnknownPathSecret(packet) => self.handle_control_packet(&(*packet).into()), + Packet::StaleKey(packet) => self.handle_stale_key(packet, &(*peer).into()), + Packet::ReplayDetected(packet) => self.handle_replay_detected(packet, &(*peer).into()), + Packet::UnknownPathSecret(packet) => { + self.handle_unknown_secret(packet, &(*peer).into()) + } } } @@ -279,10 +414,39 @@ impl Store for State { &self.receiver_shared } - fn send_control_packet(&self, dst: &SocketAddr, buffer: &[u8]) { + fn send_control_packet(&self, dst: &SocketAddr, buffer: &mut [u8]) { match self.control_socket.send_to(buffer, dst) { Ok(_) => { // all done + match control::Packet::decode(s2n_codec::DecoderBufferMut::new(buffer)) + .map(|(t, _)| t) + { + Ok(control::Packet::UnknownPathSecret(packet)) => { + self.subscriber().on_unknown_path_secret_packet_sent( + event::builder::UnknownPathSecretPacketSent { + peer_address: SocketAddress::from(*dst).into_event(), + credential_id: packet.credential_id().into_event(), + }, + ); + } + Ok(control::Packet::StaleKey(packet)) => { + self.subscriber().on_stale_key_packet_sent( + event::builder::StaleKeyPacketSent { + peer_address: SocketAddress::from(*dst).into_event(), + credential_id: packet.credential_id().into_event(), + }, + ); + } + Ok(control::Packet::ReplayDetected(packet)) => { + self.subscriber().on_replay_detected_packet_sent( + event::builder::ReplayDetectedPacketSent { + peer_address: SocketAddress::from(*dst).into_event(), + credential_id: packet.credential_id().into_event(), + }, + ); + } + Err(err) => debug_assert!(false, "decoder error {err:?}"), + } } Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => { // ignore would block -- we're not going to queue up control packet messages. @@ -296,6 +460,66 @@ impl Store for State { fn rehandshake_period(&self) -> Duration { self.rehandshake_period } + + fn check_dedup( + &self, + entry: &Entry, + key_id: s2n_quic_core::varint::VarInt, + ) -> crypto::open::Result { + let creds = &Credentials { + id: *entry.id(), + key_id, + }; + match entry.receiver().post_authentication(creds) { + Ok(()) => Ok(()), + Err(receiver::Error::AlreadyExists) => { + self.send_control_error(entry, creds, receiver::Error::AlreadyExists); + + self.subscriber().on_replay_definitely_detected( + event::builder::ReplayDefinitelyDetected { + credential_id: creds.id.into_event(), + key_id: key_id.into_event(), + }, + ); + + Err(crypto::open::Error::ReplayDefinitelyDetected) + } + Err(receiver::Error::Unknown) => { + self.send_control_error(entry, creds, receiver::Error::Unknown); + + let gap = (*entry.receiver().minimum_unseen_key_id()) + // This should never be negative, but saturate anyway to avoid + // wildly large numbers. + .saturating_sub(*creds.key_id); + + self.subscriber().on_replay_potentially_detected( + event::builder::ReplayPotentiallyDetected { + credential_id: creds.id.into_event(), + key_id: key_id.into_event(), + gap, + }, + ); + + Err(crypto::open::Error::ReplayPotentiallyDetected { gap: Some(gap) }) + } + } + } +} + +impl Drop for State { + fn drop(&mut self) { + if std::thread::panicking() { + return; + } + + self.subscriber().on_path_secret_map_uninitialized( + event::builder::PathSecretMapUninitialized { + capacity: self.secrets_capacity(), + control_socket_port: self.control_socket_port, + entries: self.secrets_len(), + }, + ); + } } #[derive(Default)] diff --git a/dc/s2n-quic-dc/src/path/secret/map/state/tests.rs b/dc/s2n-quic-dc/src/path/secret/map/state/tests.rs index 7d43489aa..853627a18 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/state/tests.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/state/tests.rs @@ -2,7 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 use super::*; -use crate::path::secret::{schedule, sender}; +use crate::{ + event::tracing::Subscriber, + path::secret::{schedule, sender}, +}; use s2n_quic_core::dc; use std::{ collections::HashSet, @@ -17,7 +20,7 @@ fn fake_entry(port: u16) -> Arc { #[test] fn cleans_after_delay() { let signer = stateless_reset::Signer::new(b"secret"); - let map = State::new(signer, 50); + let map = State::new(signer, 50, Subscriber::default()); // Stop background processing. We expect to manually invoke clean, and a background worker // might interfere with our state. @@ -45,7 +48,7 @@ fn cleans_after_delay() { #[test] fn thread_shutdown() { let signer = stateless_reset::Signer::new(b"secret"); - let map = State::new(signer, 10); + let map = State::new(signer, 10, Subscriber::default()); let state = Arc::downgrade(&map); drop(map); @@ -113,7 +116,7 @@ enum Invariant { } impl Model { - fn perform(&mut self, operation: Operation, state: &State) { + fn perform(&mut self, operation: Operation, state: &State) { match operation { Operation::Insert { ip, path_secret_id } => { let ip = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from([0, 0, 0, ip]), 0)); @@ -165,7 +168,7 @@ impl Model { id, &stateless_reset, ); - state.handle_unknown_secret_packet(&packet); + state.handle_unknown_secret(&packet, &Default::default()); // ReceiveUnknown does not cause any action with respect to our invariants, no // updates required. @@ -173,7 +176,7 @@ impl Model { } } - fn check_invariants(&self, state: &State) { + fn check_invariants(&self, state: &State) { for invariant in self.invariants.iter() { // We avoid assertions for contains() if we're running the small capacity test, since // they are likely broken -- we semi-randomly evict peers in that case. @@ -246,7 +249,7 @@ fn check_invariants() { let mut model = Model::default(); let signer = stateless_reset::Signer::new(b"secret"); - let mut map = State::new(signer, 10_000); + let mut map = State::new(signer, 10_000, Subscriber::default()); // Avoid background work interfering with testing. map.cleaner.stop(); @@ -276,7 +279,7 @@ fn check_invariants_no_overflow() { let mut model = Model::default(); let signer = stateless_reset::Signer::new(b"secret"); - let map = State::new(signer, 10_000); + let map = State::new(signer, 10_000, Subscriber::default()); // Avoid background work interfering with testing. map.cleaner.stop(); @@ -299,7 +302,7 @@ fn check_invariants_no_overflow() { #[ignore = "memory growth takes a long time to run"] fn no_memory_growth() { let signer = stateless_reset::Signer::new(b"secret"); - let map = State::new(signer, 100_000); + let map = State::new(signer, 100_000, Subscriber::default()); map.cleaner.stop(); for idx in 0..500_000 { diff --git a/dc/s2n-quic-dc/src/path/secret/map/status.rs b/dc/s2n-quic-dc/src/path/secret/map/status.rs index 76df63ccf..52ef8790d 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/status.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/status.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use super::{Entry, Map}; -use crate::{credentials::Credentials, crypto, path::secret::receiver}; +use crate::crypto; use core::{ fmt, sync::atomic::{AtomicU64, Ordering}, @@ -73,35 +73,7 @@ impl Dedup { pub fn check(&self) -> crypto::open::Result { *self.cell.get_or_init(|| { match self.init.take() { - Some((entry, key_id, map)) => { - let creds = &Credentials { - id: *entry.id(), - key_id, - }; - match entry.receiver().post_authentication(creds) { - Ok(()) => Ok(()), - Err(receiver::Error::AlreadyExists) => { - map.store.send_control_error( - &entry, - creds, - receiver::Error::AlreadyExists, - ); - Err(crypto::open::Error::ReplayDefinitelyDetected) - } - Err(receiver::Error::Unknown) => { - map.store - .send_control_error(&entry, creds, receiver::Error::Unknown); - Err(crypto::open::Error::ReplayPotentiallyDetected { - gap: Some( - (*entry.receiver().minimum_unseen_key_id()) - // This should never be negative, but saturate anyway to avoid - // wildly large numbers. - .saturating_sub(*creds.key_id), - ), - }) - } - } - } + Some((entry, key_id, map)) => map.store.check_dedup(&entry, key_id), None => { // Dedup has been poisoned! TODO log this Err(crypto::open::Error::ReplayPotentiallyDetected { gap: None }) diff --git a/dc/s2n-quic-dc/src/path/secret/map/store.rs b/dc/s2n-quic-dc/src/path/secret/map/store.rs index 40f15aa45..80ca4b579 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/store.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/store.rs @@ -37,22 +37,29 @@ pub trait Store: 'static + Send + Sync { fn get_by_id(&self, id: &Id) -> Option>>; - fn handle_unexpected_packet(&self, packet: &Packet); + fn handle_unexpected_packet(&self, packet: &Packet, peer: &SocketAddr); - fn handle_control_packet(&self, packet: &control::Packet); + fn handle_control_packet(&self, packet: &control::Packet, peer: &SocketAddr); fn signer(&self) -> &stateless_reset::Signer; fn receiver(&self) -> &Arc; - fn send_control_packet(&self, dst: &SocketAddr, buffer: &[u8]); + fn send_control_packet(&self, dst: &SocketAddr, buffer: &mut [u8]); fn rehandshake_period(&self) -> Duration; + fn check_dedup( + &self, + entry: &Entry, + key_id: s2n_quic_core::varint::VarInt, + ) -> crate::crypto::open::Result; + #[inline] fn send_control_error(&self, entry: &Entry, credentials: &Credentials, error: receiver::Error) { let mut buffer = [0; control::MAX_PACKET_SIZE]; - let buffer = error.to_packet(entry, credentials, &mut buffer); + let len = error.to_packet(entry, credentials, &mut buffer).len(); + let buffer = &mut buffer[..len]; let dst = entry.peer(); self.send_control_packet(dst, buffer); } diff --git a/dc/s2n-quic-dc/src/stream/recv/shared.rs b/dc/s2n-quic-dc/src/stream/recv/shared.rs index b42a7018d..a686eeef7 100644 --- a/dc/s2n-quic-dc/src/stream/recv/shared.rs +++ b/dc/s2n-quic-dc/src/stream/recv/shared.rs @@ -492,7 +492,10 @@ impl Inner { } other => { let kind = other.kind(); - shared.crypto.map().handle_unexpected_packet(other); + shared + .crypto + .map() + .handle_unexpected_packet(other, &shared.read_remote_addr().into()); // if we get a packet we don't expect then it's fatal for streams msg.clear(); @@ -586,7 +589,10 @@ impl Inner { }); } other => { - shared.crypto.map().handle_unexpected_packet(&other); + shared + .crypto + .map() + .handle_unexpected_packet(&other, &shared.read_remote_addr().into()); // TODO if the packet was authentic then close the receiver with an error } diff --git a/dc/s2n-quic-dc/src/stream/send/worker.rs b/dc/s2n-quic-dc/src/stream/send/worker.rs index ec3764372..b08d7461f 100644 --- a/dc/s2n-quic-dc/src/stream/send/worker.rs +++ b/dc/s2n-quic-dc/src/stream/send/worker.rs @@ -335,7 +335,11 @@ where any_valid_packets = true; } } - other => self.shared.crypto.map().handle_unexpected_packet(&other), + other => self + .shared + .crypto + .map() + .handle_unexpected_packet(&other, &self.shared.write_remote_addr().into()), } } } diff --git a/quic/s2n-quic-core/src/event/generated.rs b/quic/s2n-quic-core/src/event/generated.rs index 0382be4e6..805fadd1a 100644 --- a/quic/s2n-quic-core/src/event/generated.rs +++ b/quic/s2n-quic-core/src/event/generated.rs @@ -1757,6 +1757,14 @@ pub mod tracing { Self { client, server } } } + impl Subscriber { + fn parent(&self, meta: &M) -> Option { + match meta.endpoint_type() { + api::EndpointType::Client { .. } => self.client.id(), + api::EndpointType::Server { .. } => self.server.id(), + } + } + } impl super::Subscriber for Subscriber { type ConnectionContext = tracing::Span; fn create_connection_context( @@ -1764,10 +1772,7 @@ pub mod tracing { meta: &api::ConnectionMeta, _info: &api::ConnectionInfo, ) -> Self::ConnectionContext { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); tracing :: span ! (target : "s2n_quic" , parent : parent , tracing :: Level :: DEBUG , "conn" , id = meta . id) } #[inline] @@ -2331,10 +2336,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::VersionInformation, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::VersionInformation { server_versions, client_versions, @@ -2348,10 +2350,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::EndpointPacketSent, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::EndpointPacketSent { packet_header } = event; tracing :: event ! (target : "endpoint_packet_sent" , parent : parent , tracing :: Level :: DEBUG , packet_header = tracing :: field :: debug (packet_header)); } @@ -2361,10 +2360,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::EndpointPacketReceived, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::EndpointPacketReceived { packet_header } = event; tracing :: event ! (target : "endpoint_packet_received" , parent : parent , tracing :: Level :: DEBUG , packet_header = tracing :: field :: debug (packet_header)); } @@ -2374,10 +2370,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::EndpointDatagramSent, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::EndpointDatagramSent { len, gso_offset } = event; tracing :: event ! (target : "endpoint_datagram_sent" , parent : parent , tracing :: Level :: DEBUG , len = tracing :: field :: debug (len) , gso_offset = tracing :: field :: debug (gso_offset)); } @@ -2387,10 +2380,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::EndpointDatagramReceived, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::EndpointDatagramReceived { len } = event; tracing :: event ! (target : "endpoint_datagram_received" , parent : parent , tracing :: Level :: DEBUG , len = tracing :: field :: debug (len)); } @@ -2400,10 +2390,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::EndpointDatagramDropped, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::EndpointDatagramDropped { len, reason } = event; tracing :: event ! (target : "endpoint_datagram_dropped" , parent : parent , tracing :: Level :: DEBUG , len = tracing :: field :: debug (len) , reason = tracing :: field :: debug (reason)); } @@ -2413,19 +2400,13 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::EndpointConnectionAttemptFailed, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::EndpointConnectionAttemptFailed { error } = event; tracing :: event ! (target : "endpoint_connection_attempt_failed" , parent : parent , tracing :: Level :: DEBUG , error = tracing :: field :: debug (error)); } #[inline] fn on_platform_tx(&mut self, meta: &api::EndpointMeta, event: &api::PlatformTx) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::PlatformTx { count, syscalls, @@ -2437,19 +2418,13 @@ pub mod tracing { } #[inline] fn on_platform_tx_error(&mut self, meta: &api::EndpointMeta, event: &api::PlatformTxError) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::PlatformTxError { errno } = event; tracing :: event ! (target : "platform_tx_error" , parent : parent , tracing :: Level :: DEBUG , errno = tracing :: field :: debug (errno)); } #[inline] fn on_platform_rx(&mut self, meta: &api::EndpointMeta, event: &api::PlatformRx) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::PlatformRx { count, syscalls, @@ -2461,10 +2436,7 @@ pub mod tracing { } #[inline] fn on_platform_rx_error(&mut self, meta: &api::EndpointMeta, event: &api::PlatformRxError) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::PlatformRxError { errno } = event; tracing :: event ! (target : "platform_rx_error" , parent : parent , tracing :: Level :: DEBUG , errno = tracing :: field :: debug (errno)); } @@ -2474,10 +2446,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::PlatformFeatureConfigured, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::PlatformFeatureConfigured { configuration } = event; tracing :: event ! (target : "platform_feature_configured" , parent : parent , tracing :: Level :: DEBUG , configuration = tracing :: field :: debug (configuration)); } @@ -2487,10 +2456,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::PlatformEventLoopWakeup, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::PlatformEventLoopWakeup { timeout_expired, rx_ready, @@ -2505,10 +2471,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::PlatformEventLoopSleep, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::PlatformEventLoopSleep { timeout, processing_duration, @@ -2521,10 +2484,7 @@ pub mod tracing { meta: &api::EndpointMeta, event: &api::PlatformEventLoopStarted, ) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => self.client.id(), - api::EndpointType::Server { .. } => self.server.id(), - }; + let parent = self.parent(meta); let api::PlatformEventLoopStarted { local_address } = event; tracing :: event ! (target : "platform_event_loop_started" , parent : parent , tracing :: Level :: DEBUG , local_address = tracing :: field :: debug (local_address)); } diff --git a/quic/s2n-quic-events/src/main.rs b/quic/s2n-quic-events/src/main.rs index 83bddab66..d424eba00 100644 --- a/quic/s2n-quic-events/src/main.rs +++ b/quic/s2n-quic-events/src/main.rs @@ -90,6 +90,13 @@ impl OutputMode { } } + fn trait_constraints(&self) -> TokenStream { + match self { + OutputMode::Ref => quote!('static + Send + Sync), + OutputMode::Mut => quote!('static + Send), + } + } + fn query_mut(&self) -> TokenStream { match self { OutputMode::Ref => quote!(), @@ -307,6 +314,7 @@ struct Output { pub tuple_subscriber: TokenStream, pub tracing_subscriber: TokenStream, pub tracing_subscriber_attr: TokenStream, + pub tracing_subscriber_def: TokenStream, pub builders: TokenStream, pub api: TokenStream, pub testing_fields: TokenStream, @@ -337,6 +345,7 @@ impl ToTokens for Output { tuple_subscriber, tracing_subscriber, tracing_subscriber_attr, + tracing_subscriber_def, builders, api, testing_fields, @@ -366,6 +375,7 @@ impl ToTokens for Output { let supervisor_timeout_tuple = self.mode.supervisor_timeout_tuple(); let query_mut = self.mode.query_mut(); let query_mut_tuple = self.mode.query_mut_tuple(); + let trait_constraints = self.mode.trait_constraints(); tokens.extend(quote!( use super::*; @@ -386,25 +396,7 @@ impl ToTokens for Output { //! This module contains event integration with [`tracing`](https://docs.rs/tracing) use super::api; - /// Emits events with [`tracing`](https://docs.rs/tracing) - #[derive(Clone, Debug)] - pub struct Subscriber { - client: tracing::Span, - server: tracing::Span, - } - - impl Default for Subscriber { - fn default() -> Self { - let root = tracing::span!(target: #target_crate, tracing::Level::DEBUG, #target_crate); - let client = tracing::span!(parent: root.id(), tracing::Level::DEBUG, "client"); - let server = tracing::span!(parent: root.id(), tracing::Level::DEBUG, "server"); - - Self { - client, - server, - } - } - } + #tracing_subscriber_def impl super::Subscriber for Subscriber { type ConnectionContext = tracing::Span; @@ -414,14 +406,7 @@ impl ToTokens for Output { meta: &api::ConnectionMeta, _info: &api::ConnectionInfo ) -> Self::ConnectionContext { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => { - self.client.id() - } - api::EndpointType::Server { .. } => { - self.server.id() - } - }; + let parent = self.parent(meta); tracing::span!(target: #target_crate, parent: parent, tracing::Level::DEBUG, "conn", id = meta.id) } @@ -441,10 +426,11 @@ impl ToTokens for Output { mod traits { use super::*; use core::fmt; - use #s2n_quic_core_path::{query, event::Meta}; + use #s2n_quic_core_path::query; + use crate::event::Meta; /// Allows for events to be subscribed to - pub trait Subscriber: 'static + Send { + pub trait Subscriber: #trait_constraints { /// An application provided type associated with each connection. /// @@ -938,10 +924,42 @@ struct EventInfo<'a> { api: TokenStream, builder: TokenStream, tracing_subscriber_attr: TokenStream, + tracing_subscriber_def: TokenStream, } -fn main() -> Result<()> { - let event_paths = [ +impl EventInfo<'_> { + fn s2n_quic() -> Self { + let tracing_subscriber_def = quote!( + /// Emits events with [`tracing`](https://docs.rs/tracing) + #[derive(Clone, Debug)] + pub struct Subscriber { + client: tracing::Span, + server: tracing::Span, + } + + impl Default for Subscriber { + fn default() -> Self { + let root = tracing::span!(target: "s2n_quic", tracing::Level::DEBUG, "s2n_quic"); + let client = tracing::span!(parent: root.id(), tracing::Level::DEBUG, "client"); + let server = tracing::span!(parent: root.id(), tracing::Level::DEBUG, "server"); + + Self { + client, + server, + } + } + } + + impl Subscriber { + fn parent(&self, meta: &M) -> Option { + match meta.endpoint_type() { + api::EndpointType::Client { .. } => self.client.id(), + api::EndpointType::Server { .. } => self.server.id(), + } + } + } + ); + EventInfo { input_path: concat!( env!("CARGO_MANIFEST_DIR"), @@ -958,7 +976,35 @@ fn main() -> Result<()> { tracing_subscriber_attr: quote! { #[cfg(feature = "event-tracing")] }, - }, + tracing_subscriber_def, + } + } + + fn s2n_quic_dc() -> Self { + let tracing_subscriber_def = quote!( + /// Emits events with [`tracing`](https://docs.rs/tracing) + #[derive(Clone, Debug)] + pub struct Subscriber { + root: tracing::Span, + } + + impl Default for Subscriber { + fn default() -> Self { + let root = tracing::span!(target: "s2n_quic_dc", tracing::Level::DEBUG, "s2n_quic_dc"); + + Self { + root, + } + } + } + + impl Subscriber { + fn parent(&self, _meta: &M) -> Option { + self.root.id() + } + } + ); + EventInfo { input_path: concat!( env!("CARGO_MANIFEST_DIR"), @@ -972,9 +1018,6 @@ fn main() -> Result<()> { s2n_quic_core_path: quote!(s2n_quic_core), api: quote! { pub use s2n_quic_core::event::api::{ - ConnectionMeta, - EndpointMeta, - ConnectionInfo, Subject, EndpointType, SocketAddress, @@ -982,17 +1025,19 @@ fn main() -> Result<()> { }, builder: quote! { pub use s2n_quic_core::event::builder::{ - ConnectionMeta, - EndpointMeta, - ConnectionInfo, Subject, EndpointType, SocketAddress, }; }, tracing_subscriber_attr: quote!(), - }, - ]; + tracing_subscriber_def, + } + } +} + +fn main() -> Result<()> { + let event_paths = [EventInfo::s2n_quic(), EventInfo::s2n_quic_dc()]; for event_info in event_paths { let mut files = vec![]; @@ -1012,6 +1057,7 @@ fn main() -> Result<()> { api: event_info.api, builders: event_info.builder, tracing_subscriber_attr: event_info.tracing_subscriber_attr, + tracing_subscriber_def: event_info.tracing_subscriber_def, ..Default::default() }; diff --git a/quic/s2n-quic-events/src/parser.rs b/quic/s2n-quic-events/src/parser.rs index 13487924f..12317f74a 100644 --- a/quic/s2n-quic-events/src/parser.rs +++ b/quic/s2n-quic-events/src/parser.rs @@ -190,14 +190,7 @@ impl Struct { #[inline] #allow_deprecated fn #function(&#receiver self, meta: &api::EndpointMeta, event: &api::#ident) { - let parent = match meta.endpoint_type { - api::EndpointType::Client { .. } => { - self.client.id() - } - api::EndpointType::Server { .. } => { - self.server.id() - } - }; + let parent = self.parent(meta); let api::#ident { #(#destructure_fields),* } = event; tracing::event!(target: #snake, parent: parent, tracing::Level::DEBUG, #(#destructure_fields = tracing::field::debug(#destructure_fields)),*); } From a682947d06778647780b7a0c8a2da558fcb5ce2e Mon Sep 17 00:00:00 2001 From: Cameron Bytheway Date: Thu, 31 Oct 2024 14:04:18 -0600 Subject: [PATCH 2/2] pr feedback --- dc/s2n-quic-dc/events/map.rs | 30 +- dc/s2n-quic-dc/src/event/generated.rs | 405 ++++++++++++++++-- dc/s2n-quic-dc/src/path/secret/map/state.rs | 35 +- ...state__tests__thread_shutdown__events.snap | 6 + .../src/path/secret/map/state/tests.rs | 23 +- 5 files changed, 428 insertions(+), 71 deletions(-) create mode 100644 dc/s2n-quic-dc/src/path/secret/map/state/snapshots/path__secret__map__state__tests__thread_shutdown__events.snap diff --git a/dc/s2n-quic-dc/events/map.rs b/dc/s2n-quic-dc/events/map.rs index 245273848..162218c8e 100644 --- a/dc/s2n-quic-dc/events/map.rs +++ b/dc/s2n-quic-dc/events/map.rs @@ -6,9 +6,6 @@ struct PathSecretMapInitialized { /// The capacity of the path secret map capacity: usize, - - /// The port that the path secret is listening on - control_socket_port: u16, } #[event("path_secret_map:uninitialized")] @@ -17,9 +14,6 @@ struct PathSecretMapUninitialized { /// The capacity of the path secret map capacity: usize, - /// The port that the path secret is listening on - control_socket_port: u16, - /// The number of entries in the map entries: usize, } @@ -92,6 +86,14 @@ struct UnknownPathSecretPacketRejected<'a> { credential_id: &'a [u8], } +#[event("path_secret_map:unknown_path_secret_packet_dropped")] +#[subject(endpoint)] +/// Emitted when an UnknownPathSecret packet was dropped due to a missing entry +struct UnknownPathSecretPacketDropped<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + #[event("path_secret_map:replay_definitely_detected")] #[subject(endpoint)] /// Emitted when credential replay was definitely detected @@ -143,6 +145,14 @@ struct ReplayDetectedPacketRejected<'a> { credential_id: &'a [u8], } +#[event("path_secret_map:replay_detected_packet_dropped")] +#[subject(endpoint)] +/// Emitted when an ReplayDetected packet was dropped due to a missing entry +struct ReplayDetectedPacketDropped<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} + #[event("path_secret_map:stale_key_packet_sent")] #[subject(endpoint)] /// Emitted when an StaleKey packet was sent @@ -174,3 +184,11 @@ struct StaleKeyPacketRejected<'a> { peer_address: SocketAddress<'a>, credential_id: &'a [u8], } + +#[event("path_secret_map:stale_key_packet_dropped")] +#[subject(endpoint)] +/// Emitted when an StaleKey packet was dropped due to a missing entry +struct StaleKeyPacketDropped<'a> { + peer_address: SocketAddress<'a>, + credential_id: &'a [u8], +} diff --git a/dc/s2n-quic-dc/src/event/generated.rs b/dc/s2n-quic-dc/src/event/generated.rs index c1f461e20..7656279a8 100644 --- a/dc/s2n-quic-dc/src/event/generated.rs +++ b/dc/s2n-quic-dc/src/event/generated.rs @@ -26,7 +26,9 @@ pub mod api { #[non_exhaustive] pub struct ApplicationWrite { #[doc = " The number of bytes that the application tried to write"] - pub len: usize, + pub total_len: usize, + #[doc = " The amount that was written"] + pub write_len: usize, } impl Event for ApplicationWrite { const NAME: &'static str = "application:write"; @@ -35,10 +37,12 @@ pub mod api { #[non_exhaustive] pub struct ApplicationRead { #[doc = " The number of bytes that the application tried to read"] - pub len: usize, + pub capacity: usize, + #[doc = " The amount that was read"] + pub read_len: usize, } impl Event for ApplicationRead { - const NAME: &'static str = "application:write"; + const NAME: &'static str = "application:read"; } #[derive(Clone, Debug)] #[non_exhaustive] @@ -56,8 +60,6 @@ pub mod api { pub struct PathSecretMapInitialized { #[doc = " The capacity of the path secret map"] pub capacity: usize, - #[doc = " The port that the path secret is listening on"] - pub control_socket_port: u16, } impl Event for PathSecretMapInitialized { const NAME: &'static str = "path_secret_map:initialized"; @@ -67,8 +69,6 @@ pub mod api { pub struct PathSecretMapUninitialized { #[doc = " The capacity of the path secret map"] pub capacity: usize, - #[doc = " The port that the path secret is listening on"] - pub control_socket_port: u16, #[doc = " The number of entries in the map"] pub entries: usize, } @@ -157,6 +157,16 @@ pub mod api { } #[derive(Clone, Debug)] #[non_exhaustive] + #[doc = " Emitted when an UnknownPathSecret packet was dropped due to a missing entry"] + pub struct UnknownPathSecretPacketDropped<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for UnknownPathSecretPacketDropped<'a> { + const NAME: &'static str = "path_secret_map:unknown_path_secret_packet_dropped"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] #[doc = " Emitted when credential replay was definitely detected"] pub struct ReplayDefinitelyDetected<'a> { pub credential_id: &'a [u8], @@ -220,6 +230,16 @@ pub mod api { } #[derive(Clone, Debug)] #[non_exhaustive] + #[doc = " Emitted when an ReplayDetected packet was dropped due to a missing entry"] + pub struct ReplayDetectedPacketDropped<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for ReplayDetectedPacketDropped<'a> { + const NAME: &'static str = "path_secret_map:replay_detected_packet_dropped"; + } + #[derive(Clone, Debug)] + #[non_exhaustive] #[doc = " Emitted when an StaleKey packet was sent"] pub struct StaleKeyPacketSent<'a> { pub peer_address: SocketAddress<'a>, @@ -258,6 +278,16 @@ pub mod api { impl<'a> Event for StaleKeyPacketRejected<'a> { const NAME: &'static str = "path_secret_map:stale_key_packet_rejected"; } + #[derive(Clone, Debug)] + #[non_exhaustive] + #[doc = " Emitted when an StaleKey packet was dropped due to a missing entry"] + pub struct StaleKeyPacketDropped<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> Event for StaleKeyPacketDropped<'a> { + const NAME: &'static str = "path_secret_map:stale_key_packet_dropped"; + } } pub mod tracing { #![doc = r" This module contains event integration with [`tracing`](https://docs.rs/tracing)"] @@ -296,8 +326,11 @@ pub mod tracing { event: &api::ApplicationWrite, ) { let id = context.id(); - let api::ApplicationWrite { len } = event; - tracing :: event ! (target : "application_write" , parent : id , tracing :: Level :: DEBUG , len = tracing :: field :: debug (len)); + let api::ApplicationWrite { + total_len, + write_len, + } = event; + tracing :: event ! (target : "application_write" , parent : id , tracing :: Level :: DEBUG , total_len = tracing :: field :: debug (total_len) , write_len = tracing :: field :: debug (write_len)); } #[inline] fn on_application_read( @@ -307,8 +340,8 @@ pub mod tracing { event: &api::ApplicationRead, ) { let id = context.id(); - let api::ApplicationRead { len } = event; - tracing :: event ! (target : "application_read" , parent : id , tracing :: Level :: DEBUG , len = tracing :: field :: debug (len)); + let api::ApplicationRead { capacity, read_len } = event; + tracing :: event ! (target : "application_read" , parent : id , tracing :: Level :: DEBUG , capacity = tracing :: field :: debug (capacity) , read_len = tracing :: field :: debug (read_len)); } #[inline] fn on_endpoint_initialized( @@ -332,11 +365,8 @@ pub mod tracing { event: &api::PathSecretMapInitialized, ) { let parent = self.parent(meta); - let api::PathSecretMapInitialized { - capacity, - control_socket_port, - } = event; - tracing :: event ! (target : "path_secret_map_initialized" , parent : parent , tracing :: Level :: DEBUG , capacity = tracing :: field :: debug (capacity) , control_socket_port = tracing :: field :: debug (control_socket_port)); + let api::PathSecretMapInitialized { capacity } = event; + tracing :: event ! (target : "path_secret_map_initialized" , parent : parent , tracing :: Level :: DEBUG , capacity = tracing :: field :: debug (capacity)); } #[inline] fn on_path_secret_map_uninitialized( @@ -345,12 +375,8 @@ pub mod tracing { event: &api::PathSecretMapUninitialized, ) { let parent = self.parent(meta); - let api::PathSecretMapUninitialized { - capacity, - control_socket_port, - entries, - } = event; - tracing :: event ! (target : "path_secret_map_uninitialized" , parent : parent , tracing :: Level :: DEBUG , capacity = tracing :: field :: debug (capacity) , control_socket_port = tracing :: field :: debug (control_socket_port) , entries = tracing :: field :: debug (entries)); + let api::PathSecretMapUninitialized { capacity, entries } = event; + tracing :: event ! (target : "path_secret_map_uninitialized" , parent : parent , tracing :: Level :: DEBUG , capacity = tracing :: field :: debug (capacity) , entries = tracing :: field :: debug (entries)); } #[inline] fn on_path_secret_map_background_handshake_requested( @@ -455,6 +481,19 @@ pub mod tracing { tracing :: event ! (target : "unknown_path_secret_packet_rejected" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); } #[inline] + fn on_unknown_path_secret_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketDropped, + ) { + let parent = self.parent(meta); + let api::UnknownPathSecretPacketDropped { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "unknown_path_secret_packet_dropped" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] fn on_replay_definitely_detected( &self, meta: &api::EndpointMeta, @@ -535,6 +574,19 @@ pub mod tracing { tracing :: event ! (target : "replay_detected_packet_rejected" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); } #[inline] + fn on_replay_detected_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketDropped, + ) { + let parent = self.parent(meta); + let api::ReplayDetectedPacketDropped { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "replay_detected_packet_dropped" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } + #[inline] fn on_stale_key_packet_sent( &self, meta: &api::EndpointMeta, @@ -586,6 +638,19 @@ pub mod tracing { } = event; tracing :: event ! (target : "stale_key_packet_rejected" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); } + #[inline] + fn on_stale_key_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketDropped, + ) { + let parent = self.parent(meta); + let api::StaleKeyPacketDropped { + peer_address, + credential_id, + } = event; + tracing :: event ! (target : "stale_key_packet_dropped" , parent : parent , tracing :: Level :: DEBUG , peer_address = tracing :: field :: debug (peer_address) , credential_id = tracing :: field :: debug (credential_id)); + } } } pub mod builder { @@ -625,28 +690,37 @@ pub mod builder { #[derive(Clone, Debug)] pub struct ApplicationWrite { #[doc = " The number of bytes that the application tried to write"] - pub len: usize, + pub total_len: usize, + #[doc = " The amount that was written"] + pub write_len: usize, } impl IntoEvent for ApplicationWrite { #[inline] fn into_event(self) -> api::ApplicationWrite { - let ApplicationWrite { len } = self; + let ApplicationWrite { + total_len, + write_len, + } = self; api::ApplicationWrite { - len: len.into_event(), + total_len: total_len.into_event(), + write_len: write_len.into_event(), } } } #[derive(Clone, Debug)] pub struct ApplicationRead { #[doc = " The number of bytes that the application tried to read"] - pub len: usize, + pub capacity: usize, + #[doc = " The amount that was read"] + pub read_len: usize, } impl IntoEvent for ApplicationRead { #[inline] fn into_event(self) -> api::ApplicationRead { - let ApplicationRead { len } = self; + let ApplicationRead { capacity, read_len } = self; api::ApplicationRead { - len: len.into_event(), + capacity: capacity.into_event(), + read_len: read_len.into_event(), } } } @@ -678,19 +752,13 @@ pub mod builder { pub struct PathSecretMapInitialized { #[doc = " The capacity of the path secret map"] pub capacity: usize, - #[doc = " The port that the path secret is listening on"] - pub control_socket_port: u16, } impl IntoEvent for PathSecretMapInitialized { #[inline] fn into_event(self) -> api::PathSecretMapInitialized { - let PathSecretMapInitialized { - capacity, - control_socket_port, - } = self; + let PathSecretMapInitialized { capacity } = self; api::PathSecretMapInitialized { capacity: capacity.into_event(), - control_socket_port: control_socket_port.into_event(), } } } @@ -698,22 +766,15 @@ pub mod builder { pub struct PathSecretMapUninitialized { #[doc = " The capacity of the path secret map"] pub capacity: usize, - #[doc = " The port that the path secret is listening on"] - pub control_socket_port: u16, #[doc = " The number of entries in the map"] pub entries: usize, } impl IntoEvent for PathSecretMapUninitialized { #[inline] fn into_event(self) -> api::PathSecretMapUninitialized { - let PathSecretMapUninitialized { - capacity, - control_socket_port, - entries, - } = self; + let PathSecretMapUninitialized { capacity, entries } = self; api::PathSecretMapUninitialized { capacity: capacity.into_event(), - control_socket_port: control_socket_port.into_event(), entries: entries.into_event(), } } @@ -877,6 +938,25 @@ pub mod builder { } } #[derive(Clone, Debug)] + #[doc = " Emitted when an UnknownPathSecret packet was dropped due to a missing entry"] + pub struct UnknownPathSecretPacketDropped<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for UnknownPathSecretPacketDropped<'a> { + #[inline] + fn into_event(self) -> api::UnknownPathSecretPacketDropped<'a> { + let UnknownPathSecretPacketDropped { + peer_address, + credential_id, + } = self; + api::UnknownPathSecretPacketDropped { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] #[doc = " Emitted when credential replay was definitely detected"] pub struct ReplayDefinitelyDetected<'a> { pub credential_id: &'a [u8], @@ -998,6 +1078,25 @@ pub mod builder { } } #[derive(Clone, Debug)] + #[doc = " Emitted when an ReplayDetected packet was dropped due to a missing entry"] + pub struct ReplayDetectedPacketDropped<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for ReplayDetectedPacketDropped<'a> { + #[inline] + fn into_event(self) -> api::ReplayDetectedPacketDropped<'a> { + let ReplayDetectedPacketDropped { + peer_address, + credential_id, + } = self; + api::ReplayDetectedPacketDropped { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } + #[derive(Clone, Debug)] #[doc = " Emitted when an StaleKey packet was sent"] pub struct StaleKeyPacketSent<'a> { pub peer_address: SocketAddress<'a>, @@ -1073,6 +1172,25 @@ pub mod builder { } } } + #[derive(Clone, Debug)] + #[doc = " Emitted when an StaleKey packet was dropped due to a missing entry"] + pub struct StaleKeyPacketDropped<'a> { + pub peer_address: SocketAddress<'a>, + pub credential_id: &'a [u8], + } + impl<'a> IntoEvent> for StaleKeyPacketDropped<'a> { + #[inline] + fn into_event(self) -> api::StaleKeyPacketDropped<'a> { + let StaleKeyPacketDropped { + peer_address, + credential_id, + } = self; + api::StaleKeyPacketDropped { + peer_address: peer_address.into_event(), + credential_id: credential_id.into_event(), + } + } + } } pub use traits::*; mod traits { @@ -1265,6 +1383,16 @@ mod traits { let _ = meta; let _ = event; } + #[doc = "Called when the `UnknownPathSecretPacketDropped` event is triggered"] + #[inline] + fn on_unknown_path_secret_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketDropped, + ) { + let _ = meta; + let _ = event; + } #[doc = "Called when the `ReplayDefinitelyDetected` event is triggered"] #[inline] fn on_replay_definitely_detected( @@ -1325,6 +1453,16 @@ mod traits { let _ = meta; let _ = event; } + #[doc = "Called when the `ReplayDetectedPacketDropped` event is triggered"] + #[inline] + fn on_replay_detected_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketDropped, + ) { + let _ = meta; + let _ = event; + } #[doc = "Called when the `StaleKeyPacketSent` event is triggered"] #[inline] fn on_stale_key_packet_sent( @@ -1365,6 +1503,16 @@ mod traits { let _ = meta; let _ = event; } + #[doc = "Called when the `StaleKeyPacketDropped` event is triggered"] + #[inline] + fn on_stale_key_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketDropped, + ) { + let _ = meta; + let _ = event; + } #[doc = r" Called for each event that relates to the endpoint and all connections"] #[inline] fn on_event(&self, meta: &M, event: &E) { @@ -1531,6 +1679,15 @@ mod traits { (self.1).on_unknown_path_secret_packet_rejected(meta, event); } #[inline] + fn on_unknown_path_secret_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketDropped, + ) { + (self.0).on_unknown_path_secret_packet_dropped(meta, event); + (self.1).on_unknown_path_secret_packet_dropped(meta, event); + } + #[inline] fn on_replay_definitely_detected( &self, meta: &api::EndpointMeta, @@ -1585,6 +1742,15 @@ mod traits { (self.1).on_replay_detected_packet_rejected(meta, event); } #[inline] + fn on_replay_detected_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketDropped, + ) { + (self.0).on_replay_detected_packet_dropped(meta, event); + (self.1).on_replay_detected_packet_dropped(meta, event); + } + #[inline] fn on_stale_key_packet_sent( &self, meta: &api::EndpointMeta, @@ -1621,6 +1787,15 @@ mod traits { (self.1).on_stale_key_packet_rejected(meta, event); } #[inline] + fn on_stale_key_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketDropped, + ) { + (self.0).on_stale_key_packet_dropped(meta, event); + (self.1).on_stale_key_packet_dropped(meta, event); + } + #[inline] fn on_event(&self, meta: &M, event: &E) { self.0.on_event(meta, event); self.1.on_event(meta, event); @@ -1681,6 +1856,11 @@ mod traits { &self, event: builder::UnknownPathSecretPacketRejected, ); + #[doc = "Publishes a `UnknownPathSecretPacketDropped` event to the publisher's subscriber"] + fn on_unknown_path_secret_packet_dropped( + &self, + event: builder::UnknownPathSecretPacketDropped, + ); #[doc = "Publishes a `ReplayDefinitelyDetected` event to the publisher's subscriber"] fn on_replay_definitely_detected(&self, event: builder::ReplayDefinitelyDetected); #[doc = "Publishes a `ReplayPotentiallyDetected` event to the publisher's subscriber"] @@ -1693,6 +1873,8 @@ mod traits { fn on_replay_detected_packet_accepted(&self, event: builder::ReplayDetectedPacketAccepted); #[doc = "Publishes a `ReplayDetectedPacketRejected` event to the publisher's subscriber"] fn on_replay_detected_packet_rejected(&self, event: builder::ReplayDetectedPacketRejected); + #[doc = "Publishes a `ReplayDetectedPacketDropped` event to the publisher's subscriber"] + fn on_replay_detected_packet_dropped(&self, event: builder::ReplayDetectedPacketDropped); #[doc = "Publishes a `StaleKeyPacketSent` event to the publisher's subscriber"] fn on_stale_key_packet_sent(&self, event: builder::StaleKeyPacketSent); #[doc = "Publishes a `StaleKeyPacketReceived` event to the publisher's subscriber"] @@ -1701,6 +1883,8 @@ mod traits { fn on_stale_key_packet_accepted(&self, event: builder::StaleKeyPacketAccepted); #[doc = "Publishes a `StaleKeyPacketRejected` event to the publisher's subscriber"] fn on_stale_key_packet_rejected(&self, event: builder::StaleKeyPacketRejected); + #[doc = "Publishes a `StaleKeyPacketDropped` event to the publisher's subscriber"] + fn on_stale_key_packet_dropped(&self, event: builder::StaleKeyPacketDropped); #[doc = r" Returns the QUIC version, if any"] fn quic_version(&self) -> Option; } @@ -1821,6 +2005,16 @@ mod traits { self.subscriber.on_event(&self.meta, &event); } #[inline] + fn on_unknown_path_secret_packet_dropped( + &self, + event: builder::UnknownPathSecretPacketDropped, + ) { + let event = event.into_event(); + self.subscriber + .on_unknown_path_secret_packet_dropped(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] fn on_replay_definitely_detected(&self, event: builder::ReplayDefinitelyDetected) { let event = event.into_event(); self.subscriber @@ -1863,6 +2057,13 @@ mod traits { self.subscriber.on_event(&self.meta, &event); } #[inline] + fn on_replay_detected_packet_dropped(&self, event: builder::ReplayDetectedPacketDropped) { + let event = event.into_event(); + self.subscriber + .on_replay_detected_packet_dropped(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] fn on_stale_key_packet_sent(&self, event: builder::StaleKeyPacketSent) { let event = event.into_event(); self.subscriber.on_stale_key_packet_sent(&self.meta, &event); @@ -1890,6 +2091,13 @@ mod traits { self.subscriber.on_event(&self.meta, &event); } #[inline] + fn on_stale_key_packet_dropped(&self, event: builder::StaleKeyPacketDropped) { + let event = event.into_event(); + self.subscriber + .on_stale_key_packet_dropped(&self.meta, &event); + self.subscriber.on_event(&self.meta, &event); + } + #[inline] fn quic_version(&self) -> Option { self.quic_version } @@ -2061,16 +2269,19 @@ pub mod testing { pub unknown_path_secret_packet_received: AtomicU32, pub unknown_path_secret_packet_accepted: AtomicU32, pub unknown_path_secret_packet_rejected: AtomicU32, + pub unknown_path_secret_packet_dropped: AtomicU32, pub replay_definitely_detected: AtomicU32, pub replay_potentially_detected: AtomicU32, pub replay_detected_packet_sent: AtomicU32, pub replay_detected_packet_received: AtomicU32, pub replay_detected_packet_accepted: AtomicU32, pub replay_detected_packet_rejected: AtomicU32, + pub replay_detected_packet_dropped: AtomicU32, pub stale_key_packet_sent: AtomicU32, pub stale_key_packet_received: AtomicU32, pub stale_key_packet_accepted: AtomicU32, pub stale_key_packet_rejected: AtomicU32, + pub stale_key_packet_dropped: AtomicU32, } impl Drop for Subscriber { fn drop(&mut self) { @@ -2113,16 +2324,19 @@ pub mod testing { unknown_path_secret_packet_received: AtomicU32::new(0), unknown_path_secret_packet_accepted: AtomicU32::new(0), unknown_path_secret_packet_rejected: AtomicU32::new(0), + unknown_path_secret_packet_dropped: AtomicU32::new(0), replay_definitely_detected: AtomicU32::new(0), replay_potentially_detected: AtomicU32::new(0), replay_detected_packet_sent: AtomicU32::new(0), replay_detected_packet_received: AtomicU32::new(0), replay_detected_packet_accepted: AtomicU32::new(0), replay_detected_packet_rejected: AtomicU32::new(0), + replay_detected_packet_dropped: AtomicU32::new(0), stale_key_packet_sent: AtomicU32::new(0), stale_key_packet_received: AtomicU32::new(0), stale_key_packet_accepted: AtomicU32::new(0), stale_key_packet_rejected: AtomicU32::new(0), + stale_key_packet_dropped: AtomicU32::new(0), } } } @@ -2265,6 +2479,18 @@ pub mod testing { .unwrap() .push(format!("{meta:?} {event:?}")); } + fn on_unknown_path_secret_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketDropped, + ) { + self.unknown_path_secret_packet_dropped + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } fn on_replay_definitely_detected( &self, meta: &api::EndpointMeta, @@ -2337,6 +2563,18 @@ pub mod testing { .unwrap() .push(format!("{meta:?} {event:?}")); } + fn on_replay_detected_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketDropped, + ) { + self.replay_detected_packet_dropped + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } fn on_stale_key_packet_sent( &self, meta: &api::EndpointMeta, @@ -2384,6 +2622,18 @@ pub mod testing { .unwrap() .push(format!("{meta:?} {event:?}")); } + fn on_stale_key_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketDropped, + ) { + self.stale_key_packet_dropped + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } } } #[derive(Debug)] @@ -2403,16 +2653,19 @@ pub mod testing { pub unknown_path_secret_packet_received: AtomicU32, pub unknown_path_secret_packet_accepted: AtomicU32, pub unknown_path_secret_packet_rejected: AtomicU32, + pub unknown_path_secret_packet_dropped: AtomicU32, pub replay_definitely_detected: AtomicU32, pub replay_potentially_detected: AtomicU32, pub replay_detected_packet_sent: AtomicU32, pub replay_detected_packet_received: AtomicU32, pub replay_detected_packet_accepted: AtomicU32, pub replay_detected_packet_rejected: AtomicU32, + pub replay_detected_packet_dropped: AtomicU32, pub stale_key_packet_sent: AtomicU32, pub stale_key_packet_received: AtomicU32, pub stale_key_packet_accepted: AtomicU32, pub stale_key_packet_rejected: AtomicU32, + pub stale_key_packet_dropped: AtomicU32, } impl Drop for Subscriber { fn drop(&mut self) { @@ -2457,16 +2710,19 @@ pub mod testing { unknown_path_secret_packet_received: AtomicU32::new(0), unknown_path_secret_packet_accepted: AtomicU32::new(0), unknown_path_secret_packet_rejected: AtomicU32::new(0), + unknown_path_secret_packet_dropped: AtomicU32::new(0), replay_definitely_detected: AtomicU32::new(0), replay_potentially_detected: AtomicU32::new(0), replay_detected_packet_sent: AtomicU32::new(0), replay_detected_packet_received: AtomicU32::new(0), replay_detected_packet_accepted: AtomicU32::new(0), replay_detected_packet_rejected: AtomicU32::new(0), + replay_detected_packet_dropped: AtomicU32::new(0), stale_key_packet_sent: AtomicU32::new(0), stale_key_packet_received: AtomicU32::new(0), stale_key_packet_accepted: AtomicU32::new(0), stale_key_packet_rejected: AtomicU32::new(0), + stale_key_packet_dropped: AtomicU32::new(0), } } } @@ -2637,6 +2893,18 @@ pub mod testing { .unwrap() .push(format!("{meta:?} {event:?}")); } + fn on_unknown_path_secret_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::UnknownPathSecretPacketDropped, + ) { + self.unknown_path_secret_packet_dropped + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } fn on_replay_definitely_detected( &self, meta: &api::EndpointMeta, @@ -2709,6 +2977,18 @@ pub mod testing { .unwrap() .push(format!("{meta:?} {event:?}")); } + fn on_replay_detected_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::ReplayDetectedPacketDropped, + ) { + self.replay_detected_packet_dropped + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } fn on_stale_key_packet_sent( &self, meta: &api::EndpointMeta, @@ -2756,6 +3036,18 @@ pub mod testing { .unwrap() .push(format!("{meta:?} {event:?}")); } + fn on_stale_key_packet_dropped( + &self, + meta: &api::EndpointMeta, + event: &api::StaleKeyPacketDropped, + ) { + self.stale_key_packet_dropped + .fetch_add(1, Ordering::Relaxed); + self.output + .lock() + .unwrap() + .push(format!("{meta:?} {event:?}")); + } } #[derive(Debug)] pub struct Publisher { @@ -2774,16 +3066,19 @@ pub mod testing { pub unknown_path_secret_packet_received: AtomicU32, pub unknown_path_secret_packet_accepted: AtomicU32, pub unknown_path_secret_packet_rejected: AtomicU32, + pub unknown_path_secret_packet_dropped: AtomicU32, pub replay_definitely_detected: AtomicU32, pub replay_potentially_detected: AtomicU32, pub replay_detected_packet_sent: AtomicU32, pub replay_detected_packet_received: AtomicU32, pub replay_detected_packet_accepted: AtomicU32, pub replay_detected_packet_rejected: AtomicU32, + pub replay_detected_packet_dropped: AtomicU32, pub stale_key_packet_sent: AtomicU32, pub stale_key_packet_received: AtomicU32, pub stale_key_packet_accepted: AtomicU32, pub stale_key_packet_rejected: AtomicU32, + pub stale_key_packet_dropped: AtomicU32, } impl Publisher { #[doc = r" Creates a publisher with snapshot assertions enabled"] @@ -2818,16 +3113,19 @@ pub mod testing { unknown_path_secret_packet_received: AtomicU32::new(0), unknown_path_secret_packet_accepted: AtomicU32::new(0), unknown_path_secret_packet_rejected: AtomicU32::new(0), + unknown_path_secret_packet_dropped: AtomicU32::new(0), replay_definitely_detected: AtomicU32::new(0), replay_potentially_detected: AtomicU32::new(0), replay_detected_packet_sent: AtomicU32::new(0), replay_detected_packet_received: AtomicU32::new(0), replay_detected_packet_accepted: AtomicU32::new(0), replay_detected_packet_rejected: AtomicU32::new(0), + replay_detected_packet_dropped: AtomicU32::new(0), stale_key_packet_sent: AtomicU32::new(0), stale_key_packet_received: AtomicU32::new(0), stale_key_packet_accepted: AtomicU32::new(0), stale_key_packet_rejected: AtomicU32::new(0), + stale_key_packet_dropped: AtomicU32::new(0), } } } @@ -2909,6 +3207,15 @@ pub mod testing { let event = event.into_event(); self.output.lock().unwrap().push(format!("{event:?}")); } + fn on_unknown_path_secret_packet_dropped( + &self, + event: builder::UnknownPathSecretPacketDropped, + ) { + self.unknown_path_secret_packet_dropped + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } fn on_replay_definitely_detected(&self, event: builder::ReplayDefinitelyDetected) { self.replay_definitely_detected .fetch_add(1, Ordering::Relaxed); @@ -2945,6 +3252,12 @@ pub mod testing { let event = event.into_event(); self.output.lock().unwrap().push(format!("{event:?}")); } + fn on_replay_detected_packet_dropped(&self, event: builder::ReplayDetectedPacketDropped) { + self.replay_detected_packet_dropped + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } fn on_stale_key_packet_sent(&self, event: builder::StaleKeyPacketSent) { self.stale_key_packet_sent.fetch_add(1, Ordering::Relaxed); let event = event.into_event(); @@ -2968,6 +3281,12 @@ pub mod testing { let event = event.into_event(); self.output.lock().unwrap().push(format!("{event:?}")); } + fn on_stale_key_packet_dropped(&self, event: builder::StaleKeyPacketDropped) { + self.stale_key_packet_dropped + .fetch_add(1, Ordering::Relaxed); + let event = event.into_event(); + self.output.lock().unwrap().push(format!("{event:?}")); + } fn quic_version(&self) -> Option { Some(1) } diff --git a/dc/s2n-quic-dc/src/path/secret/map/state.rs b/dc/s2n-quic-dc/src/path/secret/map/state.rs index 6fc3cd4e8..51da6823b 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/state.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/state.rs @@ -70,7 +70,6 @@ pub(super) struct State { // This socket is used *only* for sending secret control packets. // FIXME: This will get replaced with sending on a handshake socket associated with the map. pub(super) control_socket: std::net::UdpSocket, - control_socket_port: u16, pub(super) receiver_shared: Arc, @@ -90,7 +89,6 @@ impl State { // of implementation). let control_socket = std::net::UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).unwrap(); control_socket.set_nonblocking(true).unwrap(); - let control_socket_port = control_socket.local_addr().unwrap().port(); let state = Self { // This is around 500MB with current entry size. @@ -104,7 +102,6 @@ impl State { signer, receiver_shared: receiver::Shared::new(), control_socket, - control_socket_port, subscriber, }; @@ -112,12 +109,9 @@ impl State { state.cleaner.spawn_thread(state.clone()); - state.subscriber().on_path_secret_map_initialized( - event::builder::PathSecretMapInitialized { - capacity, - control_socket_port, - }, - ); + state + .subscriber() + .on_path_secret_map_initialized(event::builder::PathSecretMapInitialized { capacity }); state } @@ -151,6 +145,13 @@ impl State { ); let Some(entry) = self.get_by_id(packet.credential_id()) else { + self.subscriber().on_unknown_path_secret_packet_dropped( + event::builder::UnknownPathSecretPacketDropped { + credential_id: packet.credential_id().into_event(), + peer_address, + }, + ); + return; }; @@ -193,8 +194,11 @@ impl State { }); let Some(entry) = self.ids.get_by_key(packet.credential_id()) else { - // If we get a control packet we don't have a registered path secret for, ignore the - // packet. + self.subscriber() + .on_stale_key_packet_dropped(event::builder::StaleKeyPacketDropped { + credential_id: packet.credential_id().into_event(), + peer_address, + }); return; }; @@ -235,8 +239,12 @@ impl State { ); let Some(entry) = self.ids.get_by_key(packet.credential_id()) else { - // If we get a control packet we don't have a registered path secret for, ignore the - // packet. + self.subscriber().on_replay_detected_packet_dropped( + event::builder::ReplayDetectedPacketDropped { + credential_id: packet.credential_id().into_event(), + peer_address, + }, + ); return; }; @@ -515,7 +523,6 @@ impl Drop for State { self.subscriber().on_path_secret_map_uninitialized( event::builder::PathSecretMapUninitialized { capacity: self.secrets_capacity(), - control_socket_port: self.control_socket_port, entries: self.secrets_len(), }, ); diff --git a/dc/s2n-quic-dc/src/path/secret/map/state/snapshots/path__secret__map__state__tests__thread_shutdown__events.snap b/dc/s2n-quic-dc/src/path/secret/map/state/snapshots/path__secret__map__state__tests__thread_shutdown__events.snap new file mode 100644 index 000000000..3c57f5302 --- /dev/null +++ b/dc/s2n-quic-dc/src/path/secret/map/state/snapshots/path__secret__map__state__tests__thread_shutdown__events.snap @@ -0,0 +1,6 @@ +--- +source: quic/s2n-quic-core/src/event/snapshot.rs +input_file: dc/s2n-quic-dc/src/path/secret/map/state/tests.rs +--- +EndpointMeta PathSecretMapInitialized { capacity: 10 } +EndpointMeta PathSecretMapUninitialized { capacity: 10, entries: 0 } diff --git a/dc/s2n-quic-dc/src/path/secret/map/state/tests.rs b/dc/s2n-quic-dc/src/path/secret/map/state/tests.rs index 853627a18..4d321f7dc 100644 --- a/dc/s2n-quic-dc/src/path/secret/map/state/tests.rs +++ b/dc/s2n-quic-dc/src/path/secret/map/state/tests.rs @@ -3,7 +3,7 @@ use super::*; use crate::{ - event::tracing::Subscriber, + event::{testing, tracing}, path::secret::{schedule, sender}, }; use s2n_quic_core::dc; @@ -20,7 +20,7 @@ fn fake_entry(port: u16) -> Arc { #[test] fn cleans_after_delay() { let signer = stateless_reset::Signer::new(b"secret"); - let map = State::new(signer, 50, Subscriber::default()); + let map = State::new(signer, 50, tracing::Subscriber::default()); // Stop background processing. We expect to manually invoke clean, and a background worker // might interfere with our state. @@ -48,7 +48,14 @@ fn cleans_after_delay() { #[test] fn thread_shutdown() { let signer = stateless_reset::Signer::new(b"secret"); - let map = State::new(signer, 10, Subscriber::default()); + let map = State::new( + signer, + 10, + ( + tracing::Subscriber::default(), + testing::Subscriber::snapshot(), + ), + ); let state = Arc::downgrade(&map); drop(map); @@ -116,7 +123,7 @@ enum Invariant { } impl Model { - fn perform(&mut self, operation: Operation, state: &State) { + fn perform(&mut self, operation: Operation, state: &State) { match operation { Operation::Insert { ip, path_secret_id } => { let ip = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from([0, 0, 0, ip]), 0)); @@ -176,7 +183,7 @@ impl Model { } } - fn check_invariants(&self, state: &State) { + fn check_invariants(&self, state: &State) { for invariant in self.invariants.iter() { // We avoid assertions for contains() if we're running the small capacity test, since // they are likely broken -- we semi-randomly evict peers in that case. @@ -249,7 +256,7 @@ fn check_invariants() { let mut model = Model::default(); let signer = stateless_reset::Signer::new(b"secret"); - let mut map = State::new(signer, 10_000, Subscriber::default()); + let mut map = State::new(signer, 10_000, tracing::Subscriber::default()); // Avoid background work interfering with testing. map.cleaner.stop(); @@ -279,7 +286,7 @@ fn check_invariants_no_overflow() { let mut model = Model::default(); let signer = stateless_reset::Signer::new(b"secret"); - let map = State::new(signer, 10_000, Subscriber::default()); + let map = State::new(signer, 10_000, tracing::Subscriber::default()); // Avoid background work interfering with testing. map.cleaner.stop(); @@ -302,7 +309,7 @@ fn check_invariants_no_overflow() { #[ignore = "memory growth takes a long time to run"] fn no_memory_growth() { let signer = stateless_reset::Signer::new(b"secret"); - let map = State::new(signer, 100_000, Subscriber::default()); + let map = State::new(signer, 100_000, tracing::Subscriber::default()); map.cleaner.stop(); for idx in 0..500_000 {