s2n_quic/server/
providers.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use super::*;
5use core::marker::PhantomData;
6use s2n_quic_core::{connection::id::Generator, crypto, path};
7use s2n_quic_transport::{connection, endpoint, stream};
8
9impl_providers_state! {
10    #[derive(Debug, Default)]
11    struct Providers {
12        congestion_controller: CongestionController,
13        connection_close_formatter: ConnectionCloseFormatter,
14        connection_id: ConnectionID,
15        packet_interceptor: PacketInterceptor,
16        stateless_reset_token: StatelessResetToken,
17        random: Random,
18        endpoint_limits: EndpointLimits,
19        event: Event,
20        limits: Limits,
21        mtu: Mtu,
22        io: IO,
23        path_migration: PathMigration,
24        sync: Sync,
25        tls: Tls,
26        address_token: AddressToken,
27        datagram: Datagram,
28        dc: Dc,
29    }
30
31    /// Opaque trait containing all of the configured providers
32    trait ServerProviders {}
33}
34
35impl<
36        CongestionController: congestion_controller::Provider,
37        ConnectionCloseFormatter: connection_close_formatter::Provider,
38        ConnectionID: connection_id::Provider,
39        PacketInterceptor: packet_interceptor::Provider,
40        StatelessResetToken: stateless_reset_token::Provider,
41        Random: random::Provider,
42        EndpointLimits: endpoint_limits::Provider,
43        Event: event::Provider,
44        Limits: limits::Provider,
45        Mtu: mtu::Provider,
46        IO: io::Provider,
47        PathMigration: path_migration::Provider,
48        Sync: sync::Provider,
49        Tls: tls::Provider,
50        AddressToken: address_token::Provider,
51        Datagram: datagram::Provider,
52        Dc: dc::Provider,
53    >
54    Providers<
55        CongestionController,
56        ConnectionCloseFormatter,
57        ConnectionID,
58        PacketInterceptor,
59        StatelessResetToken,
60        Random,
61        EndpointLimits,
62        Event,
63        Limits,
64        Mtu,
65        IO,
66        PathMigration,
67        Sync,
68        Tls,
69        AddressToken,
70        Datagram,
71        Dc,
72    >
73{
74    pub fn start(self) -> Result<Server, StartError> {
75        let Self {
76            congestion_controller,
77            connection_close_formatter,
78            connection_id,
79            packet_interceptor,
80            stateless_reset_token,
81            random,
82            endpoint_limits,
83            event,
84            limits,
85            mtu,
86            address_token,
87            io,
88            path_migration,
89            sync,
90            tls,
91            datagram,
92            dc,
93        } = self;
94
95        let congestion_controller = congestion_controller.start().map_err(StartError::new)?;
96        let connection_close_formatter = connection_close_formatter
97            .start()
98            .map_err(StartError::new)?;
99        let connection_id = connection_id.start().map_err(StartError::new)?;
100        let packet_interceptor = packet_interceptor.start().map_err(StartError::new)?;
101        let stateless_reset_token = stateless_reset_token.start().map_err(StartError::new)?;
102        let random = random.start().map_err(StartError::new)?;
103        let endpoint_limits = endpoint_limits.start().map_err(StartError::new)?;
104        let limits = limits.start().map_err(StartError::new)?;
105        let mtu = mtu.start().map_err(StartError::new)?;
106        let event = event.start().map_err(StartError::new)?;
107        let address_token = address_token.start().map_err(StartError::new)?;
108        let sync = sync.start().map_err(StartError::new)?;
109        let path_migration = path_migration.start().map_err(StartError::new)?;
110        let tls = tls.start_server().map_err(StartError::new)?;
111        let datagram = datagram.start().map_err(StartError::new)?;
112        let dc = dc.start().map_err(StartError::new)?;
113
114        // Validate providers
115        // TODO: Add more validation https://github.com/aws/s2n-quic/issues/285
116        let valid_lifetime = |lifetime| {
117            (connection::id::MIN_LIFETIME..=connection::id::MAX_LIFETIME).contains(&lifetime)
118        };
119        if connection_id
120            .lifetime()
121            .is_some_and(|lifetime| !valid_lifetime(lifetime))
122        {
123            return Err(StartError::new(connection::id::Error::InvalidLifetime));
124        };
125        let mtu = path::mtu::Manager::new(mtu);
126
127        let endpoint_config = EndpointConfig {
128            congestion_controller,
129            connection_close_formatter,
130            connection_id,
131            packet_interceptor,
132            stateless_reset_token,
133            random,
134            endpoint_limits,
135            event,
136            limits,
137            mtu,
138            sync,
139            tls,
140            address_token,
141            path_handle: PhantomData,
142            path_migration,
143            datagram,
144            dc,
145        };
146
147        let (endpoint, acceptor) = endpoint::Endpoint::new_server(endpoint_config);
148
149        // Start the IO last
150        let local_addr = io.start(endpoint).map_err(StartError::new)?;
151
152        Ok(Server {
153            acceptor,
154            local_addr,
155        })
156    }
157}
158
159#[allow(dead_code)] // don't warn on unused providers for now
160struct EndpointConfig<
161    CongestionController,
162    ConnectionCloseFormatter,
163    ConnectionID,
164    PacketInterceptor,
165    PathHandle,
166    PathMigration,
167    StatelessResetToken,
168    Random,
169    EndpointLimits,
170    Event,
171    Limits,
172    Mtu: path::Endpoint,
173    Sync,
174    Tls,
175    AddressToken,
176    Datagram,
177    Dc,
178> {
179    congestion_controller: CongestionController,
180    connection_close_formatter: ConnectionCloseFormatter,
181    connection_id: ConnectionID,
182    packet_interceptor: PacketInterceptor,
183    stateless_reset_token: StatelessResetToken,
184    random: Random,
185    endpoint_limits: EndpointLimits,
186    event: Event,
187    limits: Limits,
188    mtu: path::mtu::Manager<Mtu>,
189    sync: Sync,
190    tls: Tls,
191    address_token: AddressToken,
192    path_handle: PhantomData<PathHandle>,
193    path_migration: PathMigration,
194    datagram: Datagram,
195    dc: Dc,
196}
197
198impl<
199        CongestionController: congestion_controller::Endpoint,
200        ConnectionCloseFormatter: connection_close_formatter::Formatter,
201        ConnectionID: connection::id::Format,
202        PacketInterceptor: packet_interceptor::PacketInterceptor,
203        PathMigration: path_migration::Validator,
204        PathHandle: path::Handle,
205        StatelessResetToken: stateless_reset_token::Generator,
206        Random: s2n_quic_core::random::Generator,
207        EndpointLimits: s2n_quic_core::endpoint::Limiter,
208        Event: s2n_quic_core::event::Subscriber,
209        Limits: s2n_quic_core::connection::limits::Limiter,
210        Mtu: s2n_quic_core::path::mtu::Endpoint,
211        Sync,
212        Tls: crypto::tls::Endpoint,
213        AddressToken: address_token::Format,
214        Datagram: s2n_quic_core::datagram::Endpoint,
215        Dc: s2n_quic_core::dc::Endpoint,
216    > core::fmt::Debug
217    for EndpointConfig<
218        CongestionController,
219        ConnectionCloseFormatter,
220        ConnectionID,
221        PacketInterceptor,
222        PathHandle,
223        PathMigration,
224        StatelessResetToken,
225        Random,
226        EndpointLimits,
227        Event,
228        Limits,
229        Mtu,
230        Sync,
231        Tls,
232        AddressToken,
233        Datagram,
234        Dc,
235    >
236{
237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238        f.debug_struct("ServerConfig").finish()
239    }
240}
241
242impl<
243        CongestionController: congestion_controller::Endpoint,
244        ConnectionCloseFormatter: connection_close_formatter::Formatter,
245        ConnectionID: connection::id::Format,
246        PacketInterceptor: packet_interceptor::PacketInterceptor,
247        PathHandle: path::Handle,
248        PathMigration: path_migration::Validator,
249        StatelessResetToken: stateless_reset_token::Generator,
250        Random: s2n_quic_core::random::Generator,
251        EndpointLimits: s2n_quic_core::endpoint::Limiter,
252        Event: s2n_quic_core::event::Subscriber,
253        Limits: s2n_quic_core::connection::limits::Limiter,
254        Mtu: s2n_quic_core::path::mtu::Endpoint,
255        Sync: 'static + Send,
256        Tls: crypto::tls::Endpoint,
257        AddressToken: address_token::Format,
258        Datagram: s2n_quic_core::datagram::Endpoint,
259        Dc: s2n_quic_core::dc::Endpoint,
260    > endpoint::Config
261    for EndpointConfig<
262        CongestionController,
263        ConnectionCloseFormatter,
264        ConnectionID,
265        PacketInterceptor,
266        PathHandle,
267        PathMigration,
268        StatelessResetToken,
269        Random,
270        EndpointLimits,
271        Event,
272        Limits,
273        Mtu,
274        Sync,
275        Tls,
276        AddressToken,
277        Datagram,
278        Dc,
279    >
280{
281    type ConnectionIdFormat = ConnectionID;
282    type ConnectionCloseFormatter = ConnectionCloseFormatter;
283    type PathHandle = PathHandle;
284    type StatelessResetTokenGenerator = StatelessResetToken;
285    type RandomGenerator = Random;
286    type Connection = connection::Implementation<Self>;
287    // TODO allow users to specify another lock type
288    type ConnectionLock = std::sync::Mutex<Self::Connection>;
289    type CongestionControllerEndpoint = CongestionController;
290    type EndpointLimits = EndpointLimits;
291    type EventSubscriber = Event;
292    type TLSEndpoint = Tls;
293    type TokenFormat = AddressToken;
294    type ConnectionLimits = Limits;
295    type Mtu = Mtu;
296    type StreamManager = stream::DefaultStreamManager;
297    type PathMigrationValidator = PathMigration;
298    type PacketInterceptor = PacketInterceptor;
299    type DatagramEndpoint = Datagram;
300    type DcEndpoint = Dc;
301
302    const ENDPOINT_TYPE: endpoint::Type = endpoint::Type::Server;
303
304    fn context(&mut self) -> endpoint::Context<'_, Self> {
305        endpoint::Context {
306            congestion_controller: &mut self.congestion_controller,
307            connection_close_formatter: &mut self.connection_close_formatter,
308            connection_id_format: &mut self.connection_id,
309            packet_interceptor: &mut self.packet_interceptor,
310            stateless_reset_token_generator: &mut self.stateless_reset_token,
311            random_generator: &mut self.random,
312            tls: &mut self.tls,
313            endpoint_limits: &mut self.endpoint_limits,
314            token: &mut self.address_token,
315            connection_limits: &mut self.limits,
316            mtu: &mut self.mtu,
317            event_subscriber: &mut self.event,
318            path_migration: &mut self.path_migration,
319            datagram: &mut self.datagram,
320            dc: &mut self.dc,
321        }
322    }
323}