Skip to main content

s2n_quic_dc/stream/
environment.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    clock,
6    either::Either,
7    event,
8    stream::{recv, runtime, socket, TransportFeatures},
9};
10use core::future::Future;
11use s2n_quic_core::{inet::SocketAddress, time::Timestamp, varint::VarInt};
12use s2n_quic_platform::features;
13use std::{io, sync::Arc};
14
15use super::recv::buffer::Buffer;
16
17type Result<T = (), E = io::Error> = core::result::Result<T, E>;
18
19#[cfg(any(feature = "testing", test))]
20#[allow(
21    clippy::unwrap_used,
22    clippy::unwrap_in_result,
23    clippy::panic,
24    clippy::panic_in_result_fn,
25    reason = "bach simulation environment is test-support code and may panic to surface setup failures"
26)]
27pub mod bach;
28#[cfg(feature = "tokio")]
29pub mod tokio;
30pub mod udp;
31
32pub trait Environment {
33    type Clock: Clone + clock::Clock;
34    type Subscriber: event::Subscriber + Clone;
35
36    fn subscriber(&self) -> &Self::Subscriber;
37    fn clock(&self) -> Self::Clock;
38    fn gso(&self) -> features::Gso;
39    fn reader_rt(&self) -> runtime::ArcHandle<Self::Subscriber>;
40    fn spawn_reader<F: 'static + Send + Future<Output = ()>>(&self, f: F);
41    fn writer_rt(&self) -> runtime::ArcHandle<Self::Subscriber>;
42    fn spawn_writer<F: 'static + Send + Future<Output = ()>>(&self, f: F);
43
44    /// Creates an endpoint publisher with the environment's subscriber
45    #[inline]
46    fn endpoint_publisher(&self) -> event::EndpointPublisherSubscriber<'_, Self::Subscriber> {
47        use s2n_quic_core::time::Clock as _;
48
49        self.endpoint_publisher_with_time(self.clock().get_time())
50    }
51
52    #[inline]
53    fn endpoint_publisher_with_time(
54        &self,
55        timestamp: Timestamp,
56    ) -> event::EndpointPublisherSubscriber<'_, Self::Subscriber> {
57        use s2n_quic_core::event::IntoEvent;
58
59        let timestamp = timestamp.into_event();
60
61        event::EndpointPublisherSubscriber::new(
62            event::builder::EndpointMeta { timestamp },
63            None,
64            self.subscriber(),
65        )
66    }
67}
68
69impl<A, B> Environment for Either<A, B>
70where
71    A: Environment,
72    B: Environment<Subscriber = A::Subscriber>,
73{
74    type Clock = Either<A::Clock, B::Clock>;
75    type Subscriber = A::Subscriber;
76
77    fn subscriber(&self) -> &Self::Subscriber {
78        match self {
79            Either::A(a) => a.subscriber(),
80            Either::B(b) => b.subscriber(),
81        }
82    }
83
84    fn clock(&self) -> Self::Clock {
85        match self {
86            Either::A(a) => Either::A(a.clock()),
87            Either::B(b) => Either::B(b.clock()),
88        }
89    }
90
91    fn gso(&self) -> features::Gso {
92        match self {
93            Either::A(a) => a.gso(),
94            Either::B(b) => b.gso(),
95        }
96    }
97
98    fn reader_rt(&self) -> runtime::ArcHandle<Self::Subscriber> {
99        match self {
100            Either::A(a) => a.reader_rt(),
101            Either::B(b) => b.reader_rt(),
102        }
103    }
104
105    fn spawn_reader<F: 'static + Send + Future<Output = ()>>(&self, f: F) {
106        match self {
107            Either::A(a) => a.spawn_reader(f),
108            Either::B(b) => b.spawn_reader(f),
109        }
110    }
111
112    fn writer_rt(&self) -> runtime::ArcHandle<Self::Subscriber> {
113        match self {
114            Either::A(a) => a.writer_rt(),
115            Either::B(b) => b.writer_rt(),
116        }
117    }
118
119    fn spawn_writer<F: 'static + Send + Future<Output = ()>>(&self, f: F) {
120        match self {
121            Either::A(a) => a.spawn_writer(f),
122            Either::B(b) => b.spawn_writer(f),
123        }
124    }
125}
126
127pub struct SocketSet<R, W = R> {
128    pub application: Box<dyn socket::application::Builder>,
129    pub read_worker: Option<R>,
130    pub write_worker: Option<W>,
131    pub remote_addr: SocketAddress,
132    pub source_queue_id: Option<VarInt>,
133}
134
135type SetupResult<ReadWorker, WriteWorker> =
136    Result<(SocketSet<ReadWorker, WriteWorker>, recv::shared::RecvBuffer)>;
137
138pub trait Peer<E: Environment> {
139    type ReadWorkerSocket: ReadWorkerSocket;
140    type WriteWorkerSocket: WriteWorkerSocket;
141
142    fn features(&self) -> TransportFeatures;
143    fn setup(self, env: &E) -> SetupResult<Self::ReadWorkerSocket, Self::WriteWorkerSocket>;
144}
145
146pub trait ReadWorkerSocket {
147    type Socket: super::socket::Socket;
148
149    fn setup(self) -> Self::Socket;
150}
151
152impl ReadWorkerSocket for () {
153    type Socket = super::socket::SendOnly<Arc<std::net::UdpSocket>>;
154
155    #[inline]
156    fn setup(self) -> Self::Socket {
157        unreachable!()
158    }
159}
160
161impl<T: super::socket::Socket> ReadWorkerSocket for T {
162    type Socket = T;
163
164    #[inline]
165    fn setup(self) -> Self::Socket {
166        self
167    }
168}
169
170pub trait WriteWorkerSocket {
171    type Socket: super::socket::Socket;
172    type Buffer: 'static + Buffer + Send;
173
174    fn setup(self) -> (Self::Socket, Self::Buffer);
175}
176
177impl WriteWorkerSocket for () {
178    type Socket = super::socket::SendOnly<Arc<std::net::UdpSocket>>;
179    type Buffer = recv::buffer::Local;
180
181    #[inline]
182    fn setup(self) -> (Self::Socket, Self::Buffer) {
183        unreachable!()
184    }
185}
186
187impl<T: super::socket::Socket, B: 'static + Buffer + Send> WriteWorkerSocket for (T, B) {
188    type Socket = T;
189    type Buffer = B;
190
191    #[inline]
192    fn setup(self) -> (Self::Socket, Self::Buffer) {
193        self
194    }
195}
196
197pub struct AcceptError<Peer> {
198    pub secret_control: Vec<u8>,
199    pub peer: Option<Peer>,
200    pub error: io::Error,
201}
202
203pub struct Builder<E: Environment> {
204    env: E,
205}
206
207impl<E: Environment> Builder<E> {
208    #[inline]
209    pub fn new(env: E) -> Self {
210        Self { env }
211    }
212
213    #[inline]
214    pub fn clock(&self) -> E::Clock {
215        self.env.clock()
216    }
217}