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 From<$name> for core::net::SocketAddr {
149 #[inline]
150 fn from(value: $name) -> Self {
151 value.0.into()
152 }
153 }
154
155 impl core::ops::Deref for $name {
156 type Target = SocketAddress;
157
158 fn deref(&self) -> &Self::Target {
159 &self.0
160 }
161 }
162
163 impl core::ops::DerefMut for $name {
164 fn deref_mut(&mut self) -> &mut Self::Target {
165 &mut self.0
166 }
167 }
168 };
169}
170
171impl_addr!(LocalAddress);
172
173impl LocalAddress {
174 #[inline]
175 pub fn maybe_update(&mut self, other: &Self) {
176 ensure!(!other.is_unspecified());
178
179 *self = *other;
180 }
181}
182
183impl_addr!(RemoteAddress);
184
185impl Handle for RemoteAddress {
186 #[inline]
187 fn from_remote_address(remote_address: RemoteAddress) -> Self {
188 remote_address
189 }
190
191 #[inline]
192 fn remote_address(&self) -> RemoteAddress {
193 *self
194 }
195
196 #[inline]
197 fn set_remote_address(&mut self, addr: RemoteAddress) {
198 *self = addr;
199 }
200
201 #[inline]
202 fn local_address(&self) -> LocalAddress {
203 SocketAddressV4::UNSPECIFIED.into()
204 }
205
206 #[inline]
207 fn set_local_address(&mut self, _addr: LocalAddress) {
208 }
210
211 #[inline]
212 fn unmapped_eq(&self, other: &Self) -> bool {
213 Self::unmapped_eq(self, other)
214 }
215
216 #[inline]
217 fn strict_eq(&self, other: &Self) -> bool {
218 PartialEq::eq(self, other)
219 }
220
221 #[inline]
222 fn maybe_update(&mut self, _other: &Self) {
223 }
225}
226
227#[derive(Clone, Copy, Debug, Eq)]
228#[cfg_attr(any(test, feature = "generator"), derive(TypeGenerator))]
229pub struct Tuple {
230 pub remote_address: RemoteAddress,
231 pub local_address: LocalAddress,
232}
233
234impl PartialEq for Tuple {
235 #[inline]
236 fn eq(&self, other: &Self) -> bool {
237 PartialEq::eq(&self.remote_address, &other.remote_address)
238 && PartialEq::eq(&self.local_address, &other.local_address)
239 }
240}
241
242impl Handle for Tuple {
243 #[inline]
244 fn from_remote_address(remote_address: RemoteAddress) -> Self {
245 let local_address = SocketAddressV4::UNSPECIFIED.into();
246 Self {
247 remote_address,
248 local_address,
249 }
250 }
251
252 #[inline]
253 fn remote_address(&self) -> RemoteAddress {
254 self.remote_address
255 }
256
257 #[inline]
258 fn set_remote_address(&mut self, addr: RemoteAddress) {
259 self.remote_address = addr;
260 }
261
262 #[inline]
263 fn local_address(&self) -> LocalAddress {
264 self.local_address
265 }
266
267 #[inline]
268 fn set_local_address(&mut self, addr: LocalAddress) {
269 self.local_address = addr;
270 }
271
272 #[inline]
273 fn unmapped_eq(&self, other: &Self) -> bool {
274 self.local_address.unmapped_eq(&other.local_address)
275 && self.remote_address.unmapped_eq(&other.remote_address)
276 }
277
278 #[inline]
279 fn strict_eq(&self, other: &Self) -> bool {
280 PartialEq::eq(self, other)
281 }
282
283 #[inline]
284 fn maybe_update(&mut self, other: &Self) {
285 self.local_address.maybe_update(&other.local_address);
286 }
287}
288
289const BLOCKED_PORTS: [u16; 11] = [
310 0, 17, 19, 53, 111, 123, 137, 138, 161, 389, 500, ];
322const MAX_BLOCKED_PORT: u16 = BLOCKED_PORTS[BLOCKED_PORTS.len() - 1];
323
324#[inline]
325pub fn remote_port_blocked(port: u16) -> bool {
326 if port > MAX_BLOCKED_PORT {
327 return false;
329 }
330
331 for blocked in BLOCKED_PORTS {
332 if port == blocked {
333 return true;
334 }
335 }
336
337 false
338}
339
340const THROTTLED_PORTS: [u16; 5] = [
349 1900, 3702, 5353, 5355, 11211, ];
355const MAX_THROTTLED_PORT: u16 = THROTTLED_PORTS[THROTTLED_PORTS.len() - 1];
356pub const THROTTLED_PORTS_LEN: usize = THROTTLED_PORTS.len();
357
358#[inline]
359pub fn remote_port_throttled_index(port: u16) -> Option<usize> {
360 for (idx, throttled_port) in THROTTLED_PORTS.iter().enumerate() {
361 if *throttled_port == port {
362 return Some(idx);
363 }
364 }
365 None
366}
367
368#[inline]
369pub fn remote_port_throttled(port: u16) -> bool {
370 if port > MAX_THROTTLED_PORT {
371 return false;
373 }
374
375 for throttled in THROTTLED_PORTS {
376 if port == throttled {
377 return true;
378 }
379 }
380
381 false
382}
383
384#[cfg(test)]
385mod tests {
386 use crate::path::{
387 remote_port_blocked, remote_port_throttled, BLOCKED_PORTS, MAX_BLOCKED_PORT,
388 MAX_THROTTLED_PORT, THROTTLED_PORTS,
389 };
390
391 #[test]
392 fn blocked_ports_is_sorted() {
393 assert_eq!(Some(MAX_BLOCKED_PORT), BLOCKED_PORTS.iter().max().copied());
394
395 let mut sorted = BLOCKED_PORTS.to_vec();
396 sorted.sort_unstable();
397
398 for i in 0..BLOCKED_PORTS.len() {
399 assert_eq!(sorted[i], BLOCKED_PORTS[i]);
400 }
401 }
402
403 #[test]
404 #[cfg_attr(miri, ignore)]
405 fn blocked_port() {
406 for port in 0..u16::MAX {
407 let blocked_expected = BLOCKED_PORTS.iter().copied().any(|blocked| blocked == port);
408 assert_eq!(blocked_expected, remote_port_blocked(port));
409 }
410 }
411
412 #[test]
413 fn throttled_ports_is_sorted() {
414 assert_eq!(
415 Some(MAX_THROTTLED_PORT),
416 THROTTLED_PORTS.iter().max().copied()
417 );
418
419 let mut sorted = THROTTLED_PORTS.to_vec();
420 sorted.sort_unstable();
421
422 for i in 0..THROTTLED_PORTS.len() {
423 assert_eq!(sorted[i], THROTTLED_PORTS[i]);
424 }
425 }
426
427 #[test]
428 #[cfg_attr(miri, ignore)]
429 fn throttled_port() {
430 for port in 0..u16::MAX {
431 let throttled_expected = THROTTLED_PORTS
432 .iter()
433 .copied()
434 .any(|throttled| throttled == port);
435 assert_eq!(throttled_expected, remote_port_throttled(port));
436 }
437 }
438}
439
440#[cfg(any(test, feature = "testing"))]
441pub mod testing {
442 use crate::{
443 connection, event,
444 event::{builder::SocketAddress, IntoEvent},
445 };
446
447 impl event::builder::Path<'_> {
448 pub fn test() -> Self {
449 Self {
450 local_addr: SocketAddress::IpV4 {
451 ip: &[127, 0, 0, 1],
452 port: 0,
453 },
454 local_cid: connection::LocalId::TEST_ID.into_event(),
455 remote_addr: SocketAddress::IpV4 {
456 ip: &[127, 0, 0, 1],
457 port: 0,
458 },
459 remote_cid: connection::PeerId::TEST_ID.into_event(),
460 id: 0,
461 is_active: false,
462 }
463 }
464 }
465}