s2n_quic_core/
event.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{connection, endpoint};
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7use core::{fmt, ops::RangeInclusive, time::Duration};
8
9mod generated;
10pub mod metrics;
11pub use generated::*;
12
13#[cfg(any(test, feature = "testing"))]
14#[doc(hidden)]
15pub mod snapshot;
16
17/// All event types which can be emitted from this library.
18pub trait Event: core::fmt::Debug {
19    const NAME: &'static str;
20}
21
22pub trait IntoEvent<Target> {
23    fn into_event(self) -> Target;
24}
25
26macro_rules! ident_into_event {
27    ($($name:ty),* $(,)?) => {
28        $(
29            impl IntoEvent<$name> for $name {
30                #[inline]
31                fn into_event(self) -> Self {
32                    self
33                }
34            }
35        )*
36    };
37}
38
39macro_rules! borrowed_into_event {
40    ($($name:ty),* $(,)?) => {
41        $(
42            impl<'a> IntoEvent<&'a $name> for &'a $name {
43                #[inline]
44                fn into_event(self) -> Self {
45                    self
46                }
47            }
48        )*
49    };
50}
51
52ident_into_event!(
53    u8,
54    i8,
55    u16,
56    i16,
57    u32,
58    i32,
59    u64,
60    i64,
61    usize,
62    isize,
63    f32,
64    Duration,
65    bool,
66    connection::Error,
67    endpoint::Location,
68);
69borrowed_into_event!(
70    [u8; 4],
71    [u8; 16],
72    [u8],
73    [u32],
74    [&'a [u8]],
75    (dyn core::error::Error + Send + Sync + 'static)
76);
77
78impl<T: IntoEvent<U>, U> IntoEvent<Option<U>> for Option<T> {
79    #[inline]
80    fn into_event(self) -> Option<U> {
81        self.map(IntoEvent::into_event)
82    }
83}
84
85impl<'a> IntoEvent<&'a str> for &'a str {
86    #[inline]
87    fn into_event(self) -> Self {
88        self
89    }
90}
91
92impl<'a> IntoEvent<&'a (dyn core::any::Any + Send + 'static)>
93    for &'a (dyn core::any::Any + Send + 'static)
94{
95    #[inline]
96    fn into_event(self) -> Self {
97        self
98    }
99}
100
101impl<T> IntoEvent<RangeInclusive<T>> for RangeInclusive<T> {
102    #[inline]
103    fn into_event(self) -> RangeInclusive<T> {
104        self
105    }
106}
107
108#[derive(Clone, Copy)]
109pub struct Timestamp(crate::time::Timestamp);
110
111impl fmt::Debug for Timestamp {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        self.0.fmt(f)
114    }
115}
116
117impl fmt::Display for Timestamp {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        self.0.fmt(f)
120    }
121}
122
123impl Timestamp {
124    /// The duration since the start of the s2n-quic process.
125    ///
126    /// Record the start `SystemTime` at the start of the program
127    /// to derive the absolute time at which an event is emitted.
128    ///
129    /// ```rust
130    /// # use s2n_quic_core::{
131    /// #    endpoint,
132    /// #    event::{self, IntoEvent},
133    /// #    time::{Duration, Timestamp},
134    /// # };
135    ///
136    /// let start_time = std::time::SystemTime::now();
137    /// // `meta` is included as part of each event
138    /// # let meta: event::api::ConnectionMeta = event::builder::ConnectionMeta {
139    /// #     endpoint_type: endpoint::Type::Server,
140    /// #     id: 0,
141    /// #     timestamp: unsafe { Timestamp::from_duration(Duration::from_secs(1) )},
142    /// # }.into_event();
143    /// let event_time = start_time + meta.timestamp.duration_since_start();
144    /// ```
145    pub fn duration_since_start(&self) -> Duration {
146        // Safety: the duration is relative to start of program. This function along
147        // with it's documentation captures this intent.
148        unsafe { self.0.as_duration() }
149    }
150
151    /// Returns the `Duration` which elapsed since an earlier `Timestamp`.
152    /// If `earlier` is more recent, the method returns a `Duration` of 0.
153    #[inline]
154    pub fn saturating_duration_since(self, earlier: Self) -> Duration {
155        self.0.saturating_duration_since(earlier.0)
156    }
157}
158
159impl IntoEvent<Timestamp> for crate::time::Timestamp {
160    #[inline]
161    fn into_event(self) -> Timestamp {
162        Timestamp(self)
163    }
164}
165
166impl IntoEvent<Timestamp> for Timestamp {
167    #[inline]
168    fn into_event(self) -> Timestamp {
169        self
170    }
171}
172
173#[derive(Clone)]
174pub struct TlsSession<'a> {
175    session: &'a dyn crate::crypto::tls::TlsSession,
176}
177
178impl<'a> TlsSession<'a> {
179    #[doc(hidden)]
180    pub fn new(session: &'a dyn crate::crypto::tls::TlsSession) -> TlsSession<'a> {
181        TlsSession { session }
182    }
183
184    pub fn tls_exporter(
185        &self,
186        label: &[u8],
187        context: &[u8],
188        output: &mut [u8],
189    ) -> Result<(), crate::crypto::tls::TlsExportError> {
190        self.session.tls_exporter(label, context, output)
191    }
192
193    // Currently intended only for unstable usage
194    #[doc(hidden)]
195    #[cfg(feature = "alloc")]
196    pub fn peer_cert_chain_der(&self) -> Result<Vec<Vec<u8>>, crate::crypto::tls::ChainError> {
197        self.session.peer_cert_chain_der()
198    }
199
200    pub fn cipher_suite(&self) -> crate::event::api::CipherSuite {
201        self.session.cipher_suite().into_event()
202    }
203}
204
205impl<'a> crate::event::IntoEvent<TlsSession<'a>> for TlsSession<'a> {
206    #[inline]
207    fn into_event(self) -> Self {
208        self
209    }
210}
211
212impl core::fmt::Debug for TlsSession<'_> {
213    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
214        f.debug_struct("TlsSession").finish_non_exhaustive()
215    }
216}
217
218#[cfg(feature = "std")]
219impl<'a> IntoEvent<&'a std::io::Error> for &'a std::io::Error {
220    #[inline]
221    fn into_event(self) -> &'a std::io::Error {
222        self
223    }
224}
225
226/// Provides metadata related to an event
227pub trait Meta: core::fmt::Debug {
228    /// Returns whether the local endpoint is a Client or Server
229    fn endpoint_type(&self) -> &api::EndpointType;
230
231    /// A context from which the event is being emitted
232    ///
233    /// An event can occur in the context of an Endpoint or Connection
234    fn subject(&self) -> api::Subject;
235
236    /// The time the event occurred
237    fn timestamp(&self) -> &Timestamp;
238}
239
240impl Meta for api::ConnectionMeta {
241    fn endpoint_type(&self) -> &api::EndpointType {
242        &self.endpoint_type
243    }
244
245    fn subject(&self) -> api::Subject {
246        api::Subject::Connection { id: self.id }
247    }
248
249    fn timestamp(&self) -> &Timestamp {
250        &self.timestamp
251    }
252}
253
254impl Meta for api::EndpointMeta {
255    fn endpoint_type(&self) -> &api::EndpointType {
256        &self.endpoint_type
257    }
258
259    fn subject(&self) -> api::Subject {
260        api::Subject::Endpoint {}
261    }
262
263    fn timestamp(&self) -> &Timestamp {
264        &self.timestamp
265    }
266}