-
-
Notifications
You must be signed in to change notification settings - Fork 409
/
Copy pathshared.rs
180 lines (158 loc) · 5.3 KB
/
shared.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
use std::{fmt, net::SocketAddr};
use bytes::{Buf, BufMut, BytesMut};
use crate::{coding::BufExt, packet::PartialDecode, Instant, ResetToken, MAX_CID_SIZE};
/// Events sent from an Endpoint to a Connection
#[derive(Debug)]
pub struct ConnectionEvent(pub(crate) ConnectionEventInner);
#[derive(Debug)]
pub(crate) enum ConnectionEventInner {
/// A datagram has been received for the Connection
Datagram(DatagramConnectionEvent),
/// New connection identifiers have been issued for the Connection
NewIdentifiers(Vec<IssuedCid>, Instant),
}
/// Variant of [`ConnectionEventInner`].
#[derive(Debug)]
pub(crate) struct DatagramConnectionEvent {
pub(crate) now: Instant,
pub(crate) remote: SocketAddr,
pub(crate) ecn: Option<EcnCodepoint>,
pub(crate) first_decode: PartialDecode,
pub(crate) remaining: Option<BytesMut>,
}
/// Events sent from a Connection to an Endpoint
#[derive(Debug)]
pub struct EndpointEvent(pub(crate) EndpointEventInner);
impl EndpointEvent {
/// Construct an event that indicating that a `Connection` will no longer emit events
///
/// Useful for notifying an `Endpoint` that a `Connection` has been destroyed outside of the
/// usual state machine flow, e.g. when being dropped by the user.
pub fn drained() -> Self {
Self(EndpointEventInner::Drained)
}
/// Determine whether this is the last event a `Connection` will emit
///
/// Useful for determining when connection-related event loop state can be freed.
pub fn is_drained(&self) -> bool {
self.0 == EndpointEventInner::Drained
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub(crate) enum EndpointEventInner {
/// The connection has been drained
Drained,
/// The reset token and/or address eligible for generating resets has been updated
ResetToken(SocketAddr, ResetToken),
/// The connection needs connection identifiers
NeedIdentifiers(Instant, u64),
/// Stop routing connection ID for this sequence number to the connection
/// When `bool == true`, a new connection ID will be issued to peer
RetireConnectionId(Instant, u64, bool),
}
/// Protocol-level identifier for a connection.
///
/// Mainly useful for identifying this connection's packets on the wire with tools like Wireshark.
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ConnectionId {
/// length of CID
len: u8,
/// CID in byte array
bytes: [u8; MAX_CID_SIZE],
}
impl ConnectionId {
/// Construct cid from byte array
pub fn new(bytes: &[u8]) -> Self {
debug_assert!(bytes.len() <= MAX_CID_SIZE);
let mut res = Self {
len: bytes.len() as u8,
bytes: [0; MAX_CID_SIZE],
};
res.bytes[..bytes.len()].copy_from_slice(bytes);
res
}
/// Constructs cid by reading `len` bytes from a `Buf`
///
/// Callers need to assure that `buf.remaining() >= len`
pub fn from_buf(buf: &mut (impl Buf + ?Sized), len: usize) -> Self {
debug_assert!(len <= MAX_CID_SIZE);
let mut res = Self {
len: len as u8,
bytes: [0; MAX_CID_SIZE],
};
buf.copy_to_slice(&mut res[..len]);
res
}
/// Decode from long header format
pub(crate) fn decode_long(buf: &mut impl Buf) -> Option<Self> {
let len = buf.get::<u8>().ok()? as usize;
match len > MAX_CID_SIZE || buf.remaining() < len {
false => Some(Self::from_buf(buf, len)),
true => None,
}
}
/// Encode in long header format
pub(crate) fn encode_long(&self, buf: &mut impl BufMut) {
buf.put_u8(self.len() as u8);
buf.put_slice(self);
}
}
impl ::std::ops::Deref for ConnectionId {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes[0..self.len as usize]
}
}
impl ::std::ops::DerefMut for ConnectionId {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.bytes[0..self.len as usize]
}
}
impl fmt::Debug for ConnectionId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.bytes[0..self.len as usize].fmt(f)
}
}
impl fmt::Display for ConnectionId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for byte in self.iter() {
write!(f, "{byte:02x}")?;
}
Ok(())
}
}
/// Explicit congestion notification codepoint
#[repr(u8)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum EcnCodepoint {
/// The ECT(0) codepoint, indicating that an endpoint is ECN-capable
Ect0 = 0b10,
/// The ECT(1) codepoint, indicating that an endpoint is ECN-capable
Ect1 = 0b01,
/// The CE codepoint, signalling that congestion was experienced
Ce = 0b11,
}
impl EcnCodepoint {
/// Create new object from the given bits
pub fn from_bits(x: u8) -> Option<Self> {
use EcnCodepoint::*;
Some(match x & 0b11 {
0b10 => Ect0,
0b01 => Ect1,
0b11 => Ce,
_ => {
return None;
}
})
}
/// Returns whether the codepoint is a CE, signalling that congestion was experienced
pub fn is_ce(self) -> bool {
matches!(self, Self::Ce)
}
}
#[derive(Debug, Copy, Clone)]
pub(crate) struct IssuedCid {
pub(crate) sequence: u64,
pub(crate) id: ConnectionId,
pub(crate) reset_token: ResetToken,
}