ant_quic/
shared.rs

1// Copyright 2024 Saorsa Labs Ltd.
2//
3// This Saorsa Network Software is licensed under the General Public License (GPL), version 3.
4// Please see the file LICENSE-GPL, or visit <http://www.gnu.org/licenses/> for the full text.
5//
6// Full details available at https://saorsalabs.com/licenses
7
8use std::{fmt, net::SocketAddr};
9
10use bytes::{Buf, BufMut, BytesMut};
11
12use crate::{Instant, MAX_CID_SIZE, ResetToken, coding::BufExt, packet::PartialDecode};
13
14/// Events sent from an Endpoint to a Connection
15#[derive(Debug)]
16pub struct ConnectionEvent(pub(crate) ConnectionEventInner);
17
18#[derive(Debug)]
19pub(crate) enum ConnectionEventInner {
20    /// A datagram has been received for the Connection
21    Datagram(DatagramConnectionEvent),
22    /// New connection identifiers have been issued for the Connection
23    NewIdentifiers(Vec<IssuedCid>, Instant),
24    /// Queue an ADD_ADDRESS frame for transmission
25    QueueAddAddress(crate::frame::AddAddress),
26    /// Queue a PUNCH_ME_NOW frame for transmission
27    QueuePunchMeNow(crate::frame::PunchMeNow),
28}
29
30/// Variant of [`ConnectionEventInner`].
31#[derive(Debug)]
32pub(crate) struct DatagramConnectionEvent {
33    pub(crate) now: Instant,
34    pub(crate) remote: SocketAddr,
35    pub(crate) ecn: Option<EcnCodepoint>,
36    pub(crate) first_decode: PartialDecode,
37    pub(crate) remaining: Option<BytesMut>,
38}
39
40/// Events sent from a Connection to an Endpoint
41#[derive(Debug)]
42pub struct EndpointEvent(pub(crate) EndpointEventInner);
43
44impl EndpointEvent {
45    /// Construct an event that indicating that a `Connection` will no longer emit events
46    ///
47    /// Useful for notifying an `Endpoint` that a `Connection` has been destroyed outside of the
48    /// usual state machine flow, e.g. when being dropped by the user.
49    pub fn drained() -> Self {
50        Self(EndpointEventInner::Drained)
51    }
52
53    /// Determine whether this is the last event a `Connection` will emit
54    ///
55    /// Useful for determining when connection-related event loop state can be freed.
56    pub fn is_drained(&self) -> bool {
57        self.0 == EndpointEventInner::Drained
58    }
59}
60
61#[derive(Clone, Debug, Eq, PartialEq)]
62
63pub(crate) enum EndpointEventInner {
64    /// The connection has been drained
65    Drained,
66    /// The reset token and/or address eligible for generating resets has been updated
67    ResetToken(SocketAddr, ResetToken),
68    /// The connection needs connection identifiers
69    NeedIdentifiers(Instant, u64),
70    /// Stop routing connection ID for this sequence number to the connection
71    /// When `bool == true`, a new connection ID will be issued to peer
72    RetireConnectionId(Instant, u64, bool),
73    /// Request to relay a PunchMeNow frame to a target peer
74    RelayPunchMeNow([u8; 32], crate::frame::PunchMeNow),
75    /// Request to send an AddAddress frame to the peer
76    #[allow(dead_code)]
77    SendAddressFrame(crate::frame::AddAddress),
78    /// NAT traversal candidate validation succeeded
79    #[allow(dead_code)]
80    NatCandidateValidated { address: SocketAddr, challenge: u64 },
81    /// Request to attempt connection to a target address (NAT callback mechanism)
82    TryConnectTo {
83        request_id: crate::VarInt,
84        target_address: SocketAddr,
85        timeout_ms: u16,
86        requester_connection: SocketAddr,
87        requested_at: crate::Instant,
88    },
89}
90
91/// Protocol-level identifier for a connection.
92///
93/// Mainly useful for identifying this connection's packets on the wire with tools like Wireshark.
94#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
95pub struct ConnectionId {
96    /// length of CID
97    len: u8,
98    /// CID in byte array
99    bytes: [u8; MAX_CID_SIZE],
100}
101
102impl ConnectionId {
103    /// Construct cid from byte array
104    pub fn new(bytes: &[u8]) -> Self {
105        debug_assert!(bytes.len() <= MAX_CID_SIZE);
106        let mut res = Self {
107            len: bytes.len() as u8,
108            bytes: [0; MAX_CID_SIZE],
109        };
110        res.bytes[..bytes.len()].copy_from_slice(bytes);
111        res
112    }
113
114    /// Constructs cid by reading `len` bytes from a `Buf`
115    ///
116    /// Callers need to assure that `buf.remaining() >= len`
117    pub fn from_buf(buf: &mut (impl Buf + ?Sized), len: usize) -> Self {
118        debug_assert!(len <= MAX_CID_SIZE);
119        let mut res = Self {
120            len: len as u8,
121            bytes: [0; MAX_CID_SIZE],
122        };
123        buf.copy_to_slice(&mut res[..len]);
124        res
125    }
126
127    /// Decode from long header format
128    pub(crate) fn decode_long(buf: &mut impl Buf) -> Option<Self> {
129        let len = buf.get::<u8>().ok()? as usize;
130        match len > MAX_CID_SIZE || buf.remaining() < len {
131            false => Some(Self::from_buf(buf, len)),
132            true => None,
133        }
134    }
135
136    /// Encode in long header format
137    pub(crate) fn encode_long(&self, buf: &mut impl BufMut) {
138        buf.put_u8(self.len() as u8);
139        buf.put_slice(self);
140    }
141}
142
143impl ::std::ops::Deref for ConnectionId {
144    type Target = [u8];
145    fn deref(&self) -> &[u8] {
146        &self.bytes[0..self.len as usize]
147    }
148}
149
150impl ::std::ops::DerefMut for ConnectionId {
151    fn deref_mut(&mut self) -> &mut [u8] {
152        &mut self.bytes[0..self.len as usize]
153    }
154}
155
156impl fmt::Debug for ConnectionId {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        self.bytes[0..self.len as usize].fmt(f)
159    }
160}
161
162impl fmt::Display for ConnectionId {
163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164        for byte in self.iter() {
165            write!(f, "{byte:02x}")?;
166        }
167        Ok(())
168    }
169}
170
171/// Explicit congestion notification codepoint
172#[repr(u8)]
173#[derive(Debug, Copy, Clone, Eq, PartialEq)]
174pub enum EcnCodepoint {
175    /// The ECT(0) codepoint, indicating that an endpoint is ECN-capable
176    Ect0 = 0b10,
177    /// The ECT(1) codepoint, indicating that an endpoint is ECN-capable
178    Ect1 = 0b01,
179    /// The CE codepoint, signalling that congestion was experienced
180    Ce = 0b11,
181}
182
183impl EcnCodepoint {
184    /// Create new object from the given bits
185    pub fn from_bits(x: u8) -> Option<Self> {
186        use EcnCodepoint::*;
187        Some(match x & 0b11 {
188            0b10 => Ect0,
189            0b01 => Ect1,
190            0b11 => Ce,
191            _ => {
192                return None;
193            }
194        })
195    }
196
197    /// Returns whether the codepoint is a CE, signalling that congestion was experienced
198    pub fn is_ce(self) -> bool {
199        matches!(self, Self::Ce)
200    }
201}
202
203#[derive(Debug, Copy, Clone)]
204pub(crate) struct IssuedCid {
205    pub(crate) sequence: u64,
206    pub(crate) id: ConnectionId,
207    pub(crate) reset_token: ResetToken,
208}