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}