1use crate::{
5 clock::Clock,
6 credentials::Credentials,
7 event::{self, IntoEvent as _},
8 packet::stream,
9 path::secret::map::ApplicationData,
10 stream::{
11 recv::shared as recv,
12 send::{application, shared as send},
13 tls::S2nTlsConnection,
14 },
15};
16use core::{
17 cell::UnsafeCell,
18 ops,
19 sync::atomic::{AtomicU64, AtomicU8, Ordering},
20 time::Duration,
21};
22use s2n_quic_core::{
23 ensure,
24 inet::{IpAddress, SocketAddress},
25 time::Timestamp,
26 varint::VarInt,
27};
28use s2n_quic_platform::features;
29use std::sync::{atomic::AtomicU16, Arc};
30
31pub mod handshake;
32
33pub use crate::stream::crypto::Crypto;
34
35#[derive(Clone, Copy, Debug)]
36pub enum Half {
37 Read,
38 Write,
39}
40
41#[derive(Debug, Clone, Copy)]
42pub enum ShutdownKind {
43 Normal,
44 Panicking,
45 Pruned,
46}
47
48impl ShutdownKind {
49 pub const PRUNED_CODE: u8 = 0x02;
50
51 pub fn error_code(&self) -> Option<u8> {
52 match self {
53 ShutdownKind::Normal => None,
54 ShutdownKind::Panicking => Some(0x01),
55 ShutdownKind::Pruned => Some(Self::PRUNED_CODE),
56 }
57 }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub enum AcceptState {
63 Waiting,
64 Accepted,
65}
66
67pub type ArcShared<Sub> = Arc<Shared<Sub, dyn Clock>>;
68
69pub struct Shared<Subscriber, Clk>
70where
71 Subscriber: event::Subscriber,
72 Clk: ?Sized + Clock,
73{
74 pub receiver: recv::State,
75 pub sender: send::State,
76 pub crypto: Crypto,
77 pub application_data: Option<ApplicationData>,
78 pub common: Common<Subscriber, Clk>,
79}
80
81impl<Sub, C> Shared<Sub, C>
82where
83 Sub: event::Subscriber,
84 C: Clock + ?Sized,
85{
86 #[inline]
87 pub fn on_valid_packet(
88 &self,
89 remote_addr: &SocketAddress,
90 remote_queue_id: Option<VarInt>,
91 handshake: &mut handshake::State,
92 ) {
93 match handshake {
94 handshake::State::ClientQueueIdObserved => {
95 self.local_queue_id.store(u64::MAX, Ordering::Relaxed);
97
98 self.remote_port
100 .store(remote_addr.port(), Ordering::Relaxed);
101
102 if let Some(server_queue_id) = remote_queue_id {
104 if stream::Id::normal(server_queue_id).is_some() {
106 self.remote_queue_id
107 .store(server_queue_id.as_u64(), Ordering::Relaxed);
108
109 let _ = handshake.on_observation_finished();
110 } else {
111 use event::ConnectionPublisher as _;
112 self.common.publisher().on_stream_handshake_packet_rejected(
113 event::builder::StreamHandshakePacketRejected {
114 reason: event::builder::StreamHandshakePacketRejectedReason::InvalidQueueId,
115 },
116 );
117 }
118 }
119 }
120 handshake::State::ServerQueueIdObserved => {
121 self.local_queue_id.store(u64::MAX, Ordering::Relaxed);
123
124 let _ = handshake.on_observation_finished();
126 }
127 _ => {}
128 }
129
130 self.on_peer_activity();
132 }
133
134 #[inline]
135 pub fn on_peer_activity(&self) {
136 self.last_peer_activity.fetch_max(
137 unsafe { self.clock.get_time().as_duration().as_micros() as _ },
138 Ordering::Relaxed,
139 );
140 }
141}
142
143impl<Sub, C> Shared<Sub, C>
144where
145 Sub: event::Subscriber,
146 C: ?Sized + Clock,
147{
148 #[inline]
149 pub fn last_peer_activity(&self) -> Timestamp {
150 let timestamp = self.last_peer_activity.load(Ordering::Relaxed);
151 let timestamp = Duration::from_micros(timestamp);
152 unsafe { Timestamp::from_duration(timestamp) }
153 }
154
155 #[inline]
156 pub fn stream_id(&self) -> stream::Id {
157 let queue_id = self.remote_queue_id.load(Ordering::Relaxed);
158 stream::Id::normal(unsafe { VarInt::new_unchecked(queue_id) })
160 .expect("queue_id exceeds encoding limit")
161 }
162
163 #[inline]
164 pub fn local_queue_id(&self) -> Option<VarInt> {
165 let queue_id = self.local_queue_id.load(Ordering::Relaxed);
166 VarInt::new(queue_id).ok()
167 }
168
169 #[inline]
170 pub fn remote_addr(&self) -> SocketAddress {
171 unsafe {
172 *self.common.fixed.remote_ip.get()
174 }
175 .with_port(self.remote_port.load(Ordering::Relaxed))
176 }
177
178 #[inline]
179 pub fn application(&self) -> application::state::State {
180 unsafe {
181 *self.common.fixed.application.get()
183 }
184 }
185
186 #[inline]
187 pub fn credentials(&self) -> &Credentials {
188 unsafe {
189 &*self.common.fixed.credentials.get()
191 }
192 }
193
194 #[inline]
195 pub fn application_data(&self) -> Option<&ApplicationData> {
196 self.application_data.as_ref()
197 }
198}
199
200impl<Sub, C> ops::Deref for Shared<Sub, C>
201where
202 Sub: event::Subscriber,
203 C: ?Sized + Clock,
204{
205 type Target = Common<Sub, C>;
206
207 #[inline]
208 fn deref(&self) -> &Self::Target {
209 &self.common
210 }
211}
212
213pub struct Common<Sub, Clk>
214where
215 Sub: event::Subscriber,
216 Clk: ?Sized + Clock,
217{
218 pub gso: features::Gso,
219 pub(super) remote_port: AtomicU16,
220 pub(super) local_queue_id: AtomicU64,
221 pub(super) remote_queue_id: AtomicU64,
222 pub fixed: FixedValues,
223 pub last_peer_activity: AtomicU64,
225 pub closed_halves: AtomicU8,
226 pub subscriber: Subscriber<Sub>,
227 pub s2n_connection: Option<S2nTlsConnection>,
228 pub clock: Clk,
229}
230
231impl<Sub, Clk> Common<Sub, Clk>
232where
233 Sub: event::Subscriber,
234 Clk: ?Sized + Clock,
235{
236 #[inline]
237 pub fn ensure_open(&self) -> std::io::Result<()> {
238 ensure!(
239 self.closed_halves.load(Ordering::Relaxed) < 2,
240 Err(if cfg!(target_os = "macos") {
242 std::io::ErrorKind::InvalidInput
243 } else {
244 std::io::ErrorKind::NotConnected
245 }
246 .into())
247 );
248 Ok(())
249 }
250
251 #[inline]
252 pub fn publisher(&self) -> event::ConnectionPublisherSubscriber<'_, Sub> {
253 self.publisher_with_timestamp(self.clock.get_time())
254 }
255
256 #[inline]
257 pub fn publisher_with_timestamp(
258 &self,
259 timestamp: Timestamp,
260 ) -> event::ConnectionPublisherSubscriber<'_, Sub> {
261 self.subscriber.publisher(timestamp)
262 }
263
264 #[inline]
265 pub fn endpoint_publisher(
266 &self,
267 timestamp: Timestamp,
268 ) -> event::EndpointPublisherSubscriber<'_, Sub> {
269 self.subscriber.endpoint_publisher(timestamp)
270 }
271}
272
273pub struct Subscriber<Sub>
274where
275 Sub: event::Subscriber,
276{
277 pub subscriber: Sub,
278 pub context: Sub::ConnectionContext,
279}
280
281impl<Sub> Subscriber<Sub>
282where
283 Sub: event::Subscriber,
284{
285 #[inline]
286 pub fn publisher(&self, timestamp: Timestamp) -> event::ConnectionPublisherSubscriber<'_, Sub> {
287 event::ConnectionPublisherSubscriber::new(
288 event::builder::ConnectionMeta {
289 id: 0, timestamp: timestamp.into_event(),
291 },
292 0,
293 &self.subscriber,
294 &self.context,
295 )
296 }
297
298 #[inline]
299 pub fn endpoint_publisher(
300 &self,
301 timestamp: Timestamp,
302 ) -> event::EndpointPublisherSubscriber<'_, Sub> {
303 event::EndpointPublisherSubscriber::new(
304 event::builder::EndpointMeta {
305 timestamp: timestamp.into_event(),
306 },
307 None,
308 &self.subscriber,
309 )
310 }
311}
312
313impl<Sub, Clk> Drop for Common<Sub, Clk>
314where
315 Sub: event::Subscriber,
316 Clk: ?Sized + Clock,
317{
318 #[inline]
319 fn drop(&mut self) {
320 use event::ConnectionPublisher as _;
321
322 self.publisher()
323 .on_connection_closed(event::builder::ConnectionClosed {});
324 }
325}
326
327pub struct FixedValues {
329 pub remote_ip: UnsafeCell<IpAddress>,
330 pub application: UnsafeCell<application::state::State>,
331 pub credentials: UnsafeCell<Credentials>,
332}
333
334unsafe impl Send for FixedValues {}
335unsafe impl Sync for FixedValues {}