clawft_kernel/
mesh_limits.rs1use std::sync::Arc;
6
7pub const MAX_CONNECTIONS: usize = 1024;
9pub const HANDSHAKE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
11pub const ROUTE_CHECK: std::time::Duration = std::time::Duration::from_millis(250);
14
15pub const MAX_CONNECTIONS_PER_IP: usize = 64;
18pub const FIRST_FRAME_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
21pub const IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(900);
23
24pub(crate) struct IpSlot {
26 ip: std::net::IpAddr,
27 map: Arc<std::sync::Mutex<std::collections::HashMap<std::net::IpAddr, usize>>>,
28}
29
30impl IpSlot {
31 fn key(ip: std::net::IpAddr) -> std::net::IpAddr {
35 match ip.to_canonical() {
36 std::net::IpAddr::V6(v6) => {
37 let mut o = v6.octets();
38 o[8..].fill(0);
39 std::net::IpAddr::V6(o.into())
40 }
41 v4 => v4,
42 }
43 }
44
45 pub(crate) fn acquire(
46 map: &Arc<std::sync::Mutex<std::collections::HashMap<std::net::IpAddr, usize>>>,
47 ip: std::net::IpAddr,
48 max: usize,
49 ) -> Option<Self> {
50 let ip = Self::key(ip);
51 let mut m = map.lock().unwrap();
52 let n = m.entry(ip).or_insert(0);
53 if *n >= max {
54 return None;
55 }
56 *n += 1;
57 Some(Self { ip, map: Arc::clone(map) })
58 }
59}
60
61impl Drop for IpSlot {
62 fn drop(&mut self) {
63 let mut m = self.map.lock().unwrap();
64 if let Some(n) = m.get_mut(&self.ip) {
65 *n -= 1;
66 if *n == 0 {
67 m.remove(&self.ip);
68 }
69 }
70 }
71}
72
73
74#[derive(Debug, Clone, Copy)]
78pub struct Limits {
79 pub first_frame: std::time::Duration,
81 pub idle: std::time::Duration,
84 pub per_ip: usize,
86}
87
88impl Default for Limits {
89 fn default() -> Self {
90 Self {
91 first_frame: FIRST_FRAME_TIMEOUT,
92 idle: IDLE_TIMEOUT,
93 per_ip: MAX_CONNECTIONS_PER_IP,
94 }
95 }
96}
97
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use std::net::IpAddr;
103
104 #[test]
105 fn mapped_and_prefix_addresses_share_a_slot() {
106 let map = Arc::new(std::sync::Mutex::new(Default::default()));
107 let v4: IpAddr = "192.0.2.1".parse().unwrap();
108 let mapped: IpAddr = "::ffff:192.0.2.1".parse().unwrap();
109 let _a = IpSlot::acquire(&map, v4, 1).unwrap();
110 assert!(IpSlot::acquire(&map, mapped, 1).is_none());
111
112 let p1: IpAddr = "2001:db8:1:2::1".parse().unwrap();
113 let p2: IpAddr = "2001:db8:1:2:ffff::9".parse().unwrap();
114 let other: IpAddr = "2001:db8:1:3::1".parse().unwrap();
115 let _b = IpSlot::acquire(&map, p1, 1).unwrap();
116 assert!(IpSlot::acquire(&map, p2, 1).is_none(), "same /64");
117 assert!(IpSlot::acquire(&map, other, 1).is_some(), "different /64");
118 }
119}