s2n_quic_core/endpoint/
limits.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    event::{api::SocketAddress, IntoEvent, Timestamp},
6    inet,
7};
8
9/// Outcome describes how the library should proceed on a connection attempt. The implementor will
10/// use information from the ConnectionAttempt object to determine how the library should handle
11/// the connection attempt
12#[non_exhaustive]
13#[derive(Clone, Debug, Eq, PartialEq)]
14pub enum Outcome {
15    /// Allow the connection to continue
16    ///
17    /// Use `Outcome::allow()` to construct this variant
18    #[non_exhaustive]
19    Allow,
20
21    /// Defer the connection by sending a Retry packet
22    ///
23    /// Use `Outcome::retry()` to construct this variant
24    #[non_exhaustive]
25    Retry,
26
27    /// Silently drop the connection attempt
28    ///
29    /// Use `Outcome::drop()` to construct this variant
30    #[non_exhaustive]
31    Drop,
32
33    /// Cleanly close the connection
34    ///
35    /// Use `Outcome::close()` to construct this variant
36    #[non_exhaustive]
37    Close,
38}
39
40impl Outcome {
41    /// Allow the connection to continue
42    pub fn allow() -> Self {
43        Self::Allow
44    }
45
46    /// Defer the connection by sending a Retry packet
47    pub fn retry() -> Self {
48        Self::Retry
49    }
50
51    /// Silently drop the connection attempt
52    pub fn drop() -> Self {
53        Self::Drop
54    }
55
56    /// Cleanly close the connection
57    pub fn close() -> Self {
58        Self::Close
59    }
60}
61
62/// A ConnectionAttempt holds information about the state of endpoint receiving a connect, along
63/// with information about the connection. This can be used to make decisions about the Outcome of
64/// an attempted connection
65#[non_exhaustive]
66#[derive(Debug)]
67pub struct ConnectionAttempt<'a> {
68    /// Number of handshakes the have begun but not completed
69    pub inflight_handshakes: usize,
70
71    /// Number of open connections
72    pub connection_count: usize,
73
74    /// The unverified address of the connecting peer
75    /// This address comes from the datagram
76    pub remote_address: SocketAddress<'a>,
77    pub timestamp: Timestamp,
78}
79
80impl<'a> ConnectionAttempt<'a> {
81    #[doc(hidden)]
82    pub fn new(
83        inflight_handshakes: usize,
84        connection_count: usize,
85        remote_address: &'a inet::SocketAddress,
86        timestamp: Timestamp,
87    ) -> Self {
88        Self {
89            inflight_handshakes,
90            connection_count,
91            remote_address: remote_address.into_event(),
92            timestamp,
93        }
94    }
95}
96
97pub trait Limiter: 'static + Send {
98    /// This trait is used to determine the outcome of connection attempts on an endpoint. The
99    /// implementor returns an Outcome based on the ConnectionAttempt, or other information that the
100    /// implementor may have.
101    ///
102    /// ```rust
103    /// # mod s2n_quic { pub mod provider { pub mod endpoint_limits { pub use s2n_quic_core::endpoint::limits::*; } } }
104    /// use s2n_quic::provider::endpoint_limits::{Limiter, ConnectionAttempt, Outcome};
105    ///
106    /// struct MyEndpointLimits {
107    ///    handshake_limit: usize,
108    ///    delay: core::time::Duration,
109    /// }
110    ///
111    /// impl Limiter for MyEndpointLimits {
112    ///    fn on_connection_attempt(&mut self, info: &ConnectionAttempt) -> Outcome {
113    ///        if info.inflight_handshakes > self.handshake_limit {
114    ///            Outcome::retry()
115    ///        } else {
116    ///            Outcome::allow()
117    ///        }
118    ///    }
119    /// }
120    /// ```
121    fn on_connection_attempt(&mut self, info: &ConnectionAttempt) -> Outcome;
122}