1use crate::{
5 event,
6 inet::{
7 IpV4Address, IpV6Address, SocketAddress, SocketAddressV4, SocketAddressV6, Unspecified as _,
8 },
9};
10use core::fmt;
11
12#[cfg(any(test, feature = "generator"))]
13use bolero_generator::prelude::*;
14
15pub mod ecn;
16pub mod migration;
17pub mod mtu;
18
19pub use mtu::{BaseMtu, Config, Endpoint, InitialMtu, MaxMtu, MtuError, MINIMUM_MAX_DATAGRAM_SIZE};
20
21pub const INITIAL_PTO_BACKOFF: u32 = 1;
23
24#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
26pub struct Id(u8);
27
28impl Id {
29 pub unsafe fn new(id: u8) -> Self {
34 Self(id)
35 }
36
37 pub fn as_u8(&self) -> u8 {
38 self.0
39 }
40}
41
42impl event::IntoEvent<u64> for Id {
43 #[inline]
44 fn into_event(self) -> u64 {
45 self.0 as u64
46 }
47}
48
49#[cfg(any(test, feature = "testing"))]
50impl Id {
51 pub fn test_id() -> Self {
52 unsafe { Id::new(0) }
53 }
54}
55
56pub trait Handle: 'static + Copy + Send + fmt::Debug {
58 fn from_remote_address(remote_addr: RemoteAddress) -> Self;
60
61 fn remote_address(&self) -> RemoteAddress;
63
64 fn set_remote_address(&mut self, addr: RemoteAddress);
66
67 fn local_address(&self) -> LocalAddress;
69
70 fn set_local_address(&mut self, addr: LocalAddress);
72
73 fn unmapped_eq(&self, other: &Self) -> bool;
78
79 fn strict_eq(&self, other: &Self) -> bool;
82
83 fn maybe_update(&mut self, other: &Self);
94}
95
96macro_rules! impl_addr {
97 ($name:ident) => {
98 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
99 #[cfg_attr(any(test, feature = "generator"), derive(TypeGenerator))]
100 #[cfg_attr(kani, derive(kani::Arbitrary))]
101 pub struct $name(pub SocketAddress);
102
103 impl $name {
104 #[inline]
108 pub fn unmapped_eq(&self, other: &Self) -> bool {
109 self.0.unmapped_eq(&other.0)
110 }
111 }
112
113 impl From<event::api::SocketAddress<'_>> for $name {
114 #[inline]
115 fn from(value: event::api::SocketAddress<'_>) -> Self {
116 match value {
117 event::api::SocketAddress::IpV4 { ip, port } => {
118 $name(IpV4Address::new(*ip).with_port(port).into())
119 }
120 event::api::SocketAddress::IpV6 { ip, port } => {
121 $name(IpV6Address::new(*ip).with_port(port).into())
122 }
123 }
124 }
125 }
126
127 impl From<SocketAddress> for $name {
128 #[inline]
129 fn from(value: SocketAddress) -> Self {
130 Self(value)
131 }
132 }
133
134 impl From<SocketAddressV4> for $name {
135 #[inline]
136 fn from(value: SocketAddressV4) -> Self {
137 Self(value.into())
138 }
139 }
140
141 impl From<SocketAddressV6> for $name {
142 #[inline]
143 fn from(value: SocketAddressV6) -> Self {
144 Self(value.into())
145 }
146 }
147
148 impl core::ops::Deref for $name {
149 type Target = SocketAddress;
150
151 fn deref(&self) -> &Self::Target {
152 &self.0
153 }
154 }
155
156 impl core::ops::DerefMut for $name {
157 fn deref_mut(&mut self) -> &mut Self::Target {
158 &mut self.0
159 }
160 }
161 };
162}
163
164impl_addr!(LocalAddress);
165
166impl LocalAddress {
167 #[inline]
168 pub fn maybe_update(&mut self, other: &Self) {
169 ensure!(!other.is_unspecified());
171
172 *self = *other;
173 }
174}
175
176impl_addr!(RemoteAddress);
177
178impl Handle for RemoteAddress {
179 #[inline]
180 fn from_remote_address(remote_address: RemoteAddress) -> Self {
181 remote_address
182 }
183
184 #[inline]
185 fn remote_address(&self) -> RemoteAddress {
186 *self
187 }
188
189 #[inline]
190 fn set_remote_address(&mut self, addr: RemoteAddress) {
191 *self = addr;
192 }
193
194 #[inline]
195 fn local_address(&self) -> LocalAddress {
196 SocketAddressV4::UNSPECIFIED.into()
197 }
198
199 #[inline]
200 fn set_local_address(&mut self, _addr: LocalAddress) {
201 }
203
204 #[inline]
205 fn unmapped_eq(&self, other: &Self) -> bool {
206 Self::unmapped_eq(self, other)
207 }
208
209 #[inline]
210 fn strict_eq(&self, other: &Self) -> bool {
211 PartialEq::eq(self, other)
212 }
213
214 #[inline]
215 fn maybe_update(&mut self, _other: &Self) {
216 }
218}
219
220#[derive(Clone, Copy, Debug, Eq)]
221#[cfg_attr(any(test, feature = "generator"), derive(TypeGenerator))]
222pub struct Tuple {
223 pub remote_address: RemoteAddress,
224 pub local_address: LocalAddress,
225}
226
227impl PartialEq for Tuple {
228 #[inline]
229 fn eq(&self, other: &Self) -> bool {
230 PartialEq::eq(&self.remote_address, &other.remote_address)
231 && PartialEq::eq(&self.local_address, &other.local_address)
232 }
233}
234
235impl Handle for Tuple {
236 #[inline]
237 fn from_remote_address(remote_address: RemoteAddress) -> Self {
238 let local_address = SocketAddressV4::UNSPECIFIED.into();
239 Self {
240 remote_address,
241 local_address,
242 }
243 }
244
245 #[inline]
246 fn remote_address(&self) -> RemoteAddress {
247 self.remote_address
248 }
249
250 #[inline]
251 fn set_remote_address(&mut self, addr: RemoteAddress) {
252 self.remote_address = addr;
253 }
254
255 #[inline]
256 fn local_address(&self) -> LocalAddress {
257 self.local_address
258 }
259
260 #[inline]
261 fn set_local_address(&mut self, addr: LocalAddress) {
262 self.local_address = addr;
263 }
264
265 #[inline]
266 fn unmapped_eq(&self, other: &Self) -> bool {
267 self.local_address.unmapped_eq(&other.local_address)
268 && self.remote_address.unmapped_eq(&other.remote_address)
269 }
270
271 #[inline]
272 fn strict_eq(&self, other: &Self) -> bool {
273 PartialEq::eq(self, other)
274 }
275
276 #[inline]
277 fn maybe_update(&mut self, other: &Self) {
278 self.local_address.maybe_update(&other.local_address);
279 }
280}
281
282const BLOCKED_PORTS: [u16; 11] = [
303 0, 17, 19, 53, 111, 123, 137, 138, 161, 389, 500, ];
315const MAX_BLOCKED_PORT: u16 = BLOCKED_PORTS[BLOCKED_PORTS.len() - 1];
316
317#[inline]
318pub fn remote_port_blocked(port: u16) -> bool {
319 if port > MAX_BLOCKED_PORT {
320 return false;
322 }
323
324 for blocked in BLOCKED_PORTS {
325 if port == blocked {
326 return true;
327 }
328 }
329
330 false
331}
332
333const THROTTLED_PORTS: [u16; 5] = [
342 1900, 3702, 5353, 5355, 11211, ];
348const MAX_THROTTLED_PORT: u16 = THROTTLED_PORTS[THROTTLED_PORTS.len() - 1];
349pub const THROTTLED_PORTS_LEN: usize = THROTTLED_PORTS.len();
350
351#[inline]
352pub fn remote_port_throttled_index(port: u16) -> Option<usize> {
353 for (idx, throttled_port) in THROTTLED_PORTS.iter().enumerate() {
354 if *throttled_port == port {
355 return Some(idx);
356 }
357 }
358 None
359}
360
361#[inline]
362pub fn remote_port_throttled(port: u16) -> bool {
363 if port > MAX_THROTTLED_PORT {
364 return false;
366 }
367
368 for throttled in THROTTLED_PORTS {
369 if port == throttled {
370 return true;
371 }
372 }
373
374 false
375}
376
377#[cfg(test)]
378mod tests {
379 use crate::path::{
380 remote_port_blocked, remote_port_throttled, BLOCKED_PORTS, MAX_BLOCKED_PORT,
381 MAX_THROTTLED_PORT, THROTTLED_PORTS,
382 };
383
384 #[test]
385 fn blocked_ports_is_sorted() {
386 assert_eq!(Some(MAX_BLOCKED_PORT), BLOCKED_PORTS.iter().max().copied());
387
388 let mut sorted = BLOCKED_PORTS.to_vec();
389 sorted.sort_unstable();
390
391 for i in 0..BLOCKED_PORTS.len() {
392 assert_eq!(sorted[i], BLOCKED_PORTS[i]);
393 }
394 }
395
396 #[test]
397 #[cfg_attr(miri, ignore)]
398 fn blocked_port() {
399 for port in 0..u16::MAX {
400 let blocked_expected = BLOCKED_PORTS.iter().copied().any(|blocked| blocked == port);
401 assert_eq!(blocked_expected, remote_port_blocked(port));
402 }
403 }
404
405 #[test]
406 fn throttled_ports_is_sorted() {
407 assert_eq!(
408 Some(MAX_THROTTLED_PORT),
409 THROTTLED_PORTS.iter().max().copied()
410 );
411
412 let mut sorted = THROTTLED_PORTS.to_vec();
413 sorted.sort_unstable();
414
415 for i in 0..THROTTLED_PORTS.len() {
416 assert_eq!(sorted[i], THROTTLED_PORTS[i]);
417 }
418 }
419
420 #[test]
421 #[cfg_attr(miri, ignore)]
422 fn throttled_port() {
423 for port in 0..u16::MAX {
424 let throttled_expected = THROTTLED_PORTS
425 .iter()
426 .copied()
427 .any(|throttled| throttled == port);
428 assert_eq!(throttled_expected, remote_port_throttled(port));
429 }
430 }
431}
432
433#[cfg(any(test, feature = "testing"))]
434pub mod testing {
435 use crate::{
436 connection, event,
437 event::{builder::SocketAddress, IntoEvent},
438 };
439
440 impl event::builder::Path<'_> {
441 pub fn test() -> Self {
442 Self {
443 local_addr: SocketAddress::IpV4 {
444 ip: &[127, 0, 0, 1],
445 port: 0,
446 },
447 local_cid: connection::LocalId::TEST_ID.into_event(),
448 remote_addr: SocketAddress::IpV4 {
449 ip: &[127, 0, 0, 1],
450 port: 0,
451 },
452 remote_cid: connection::PeerId::TEST_ID.into_event(),
453 id: 0,
454 is_active: false,
455 }
456 }
457 }
458}