Skip to main content

fips_core/node/
session_access_impl.rs

1use super::*;
2
3impl Node {
4    // === End-to-End Sessions ===
5
6    /// Get a session by remote NodeAddr.
7    /// Disable the discovery forward rate limiter (for tests).
8    #[cfg(test)]
9    pub(crate) fn disable_discovery_forward_rate_limit(&mut self) {
10        self.discovery_forward_limiter
11            .set_interval(std::time::Duration::ZERO);
12    }
13
14    #[cfg(test)]
15    pub(crate) fn get_session(&self, remote: &NodeAddr) -> Option<&SessionEntry> {
16        self.sessions.get(remote)
17    }
18
19    /// Remove a session.
20    #[cfg(test)]
21    pub(crate) fn remove_session(&mut self, remote: &NodeAddr) -> Option<SessionEntry> {
22        self.sessions.remove(remote)
23    }
24
25    /// Read the path_mtu_lookup entry for a destination FipsAddress.
26    #[cfg(test)]
27    pub(crate) fn path_mtu_lookup_get(&self, fips_addr: &crate::FipsAddress) -> Option<u16> {
28        self.path_mtu_lookup
29            .read()
30            .ok()
31            .and_then(|map| map.get(fips_addr).copied())
32    }
33
34    /// Write a path_mtu_lookup entry directly (for tests that pre-seed the map).
35    #[cfg(test)]
36    pub(crate) fn path_mtu_lookup_insert(&self, fips_addr: crate::FipsAddress, mtu: u16) {
37        if let Ok(mut map) = self.path_mtu_lookup.write() {
38            map.insert(fips_addr, mtu);
39        }
40    }
41
42    /// Number of end-to-end sessions.
43    pub fn session_count(&self) -> usize {
44        self.sessions.len()
45    }
46
47    /// Iterate over all session entries (for control queries).
48    pub(crate) fn session_entries(&self) -> impl Iterator<Item = (&NodeAddr, &SessionEntry)> {
49        self.sessions.iter()
50    }
51
52    pub(crate) fn session_dataplane_counters(&self, addr: &NodeAddr) -> (u64, u64, u64, u64) {
53        self.packet_mover2
54            .fsp_owner_activity(addr)
55            .map_or((0, 0, 0, 0), |activity| activity.traffic_counters())
56    }
57
58    pub(crate) fn session_dataplane_activity_ms(&self, addr: &NodeAddr) -> Option<u64> {
59        self.packet_mover2
60            .fsp_owner_activity(addr)
61            .and_then(|activity| activity.session_idle_activity_ms())
62    }
63
64    pub(crate) fn session_dataplane_epoch(&self, addr: &NodeAddr) -> Option<(u64, bool, bool)> {
65        let activity = self.packet_mover2.fsp_owner_activity(addr)?;
66        Some((
67            activity.fsp_session_start_ms()?,
68            activity.current_k_bit(),
69            activity.is_draining(),
70        ))
71    }
72
73    pub(crate) fn session_mmp_snapshot(
74        &self,
75        addr: &NodeAddr,
76    ) -> Option<crate::packet_mover2::PacketMover2FspMmpSnapshot> {
77        self.packet_mover2.fsp_mmp_snapshot(addr)
78    }
79
80    // === Identity Cache ===
81
82    /// Register a node in the identity cache for FipsAddress → NodeAddr lookup.
83    pub(crate) fn register_identity(
84        &mut self,
85        node_addr: NodeAddr,
86        pubkey: secp256k1::PublicKey,
87    ) -> bool {
88        // Endpoint sends pass the same PeerIdentity on every packet. Once
89        // validated, avoid re-deriving NodeAddr from the public key in the
90        // data path; that hash showed up in macOS sender profiles.
91        self.identity_cache.register(
92            node_addr,
93            pubkey,
94            Self::now_ms(),
95            self.config.node.cache.identity_size,
96        )
97    }
98
99    /// Look up a destination by FipsAddress prefix (bytes 1-15 of the IPv6 address).
100    pub(crate) fn lookup_by_fips_prefix(
101        &mut self,
102        prefix: &[u8; 15],
103    ) -> Option<(NodeAddr, secp256k1::PublicKey)> {
104        self.identity_cache.lookup_by_prefix(prefix, Self::now_ms())
105    }
106
107    /// Check if a node's identity is in the cache (without LRU touch).
108    pub(crate) fn has_cached_identity(&self, addr: &NodeAddr) -> bool {
109        self.identity_cache.has_prefix_for(addr)
110    }
111
112    /// Number of identity cache entries.
113    pub fn identity_cache_len(&self) -> usize {
114        self.identity_cache.len()
115    }
116
117    /// Iterate over identity cache entries.
118    ///
119    /// Returns `(NodeAddr, PublicKey, last_seen_ms)` for each cached identity.
120    /// Used by the `show_identity_cache` control query.
121    pub fn identity_cache_iter(
122        &self,
123    ) -> impl Iterator<Item = (&NodeAddr, &secp256k1::PublicKey, u64)> {
124        self.identity_cache.iter()
125    }
126
127    /// Configured maximum identity cache size.
128    pub fn identity_cache_max(&self) -> usize {
129        self.config.node.cache.identity_size
130    }
131
132    /// Number of pending discovery lookups.
133    pub fn pending_lookup_count(&self) -> usize {
134        self.pending_lookups.len()
135    }
136
137    /// Iterate over pending discovery lookups for diagnostics.
138    pub fn pending_lookups_iter(
139        &self,
140    ) -> impl Iterator<Item = (&NodeAddr, &handlers::discovery::PendingLookup)> {
141        self.pending_lookups.iter()
142    }
143
144    /// Number of recent discovery requests tracked.
145    pub fn recent_request_count(&self) -> usize {
146        self.recent_requests.len()
147    }
148
149    /// Count of destinations with queued TUN packets awaiting session setup.
150    pub fn pending_tun_destinations(&self) -> usize {
151        self.pending_session_traffic.tun_destination_count()
152    }
153
154    /// Total TUN packets queued across all destinations.
155    pub fn pending_tun_total_packets(&self) -> usize {
156        self.pending_session_traffic.tun_packet_count()
157    }
158
159    /// Iterate over retry state for diagnostics.
160    pub fn retry_state_iter(&self) -> impl Iterator<Item = (&NodeAddr, &retry::RetryState)> {
161        self.retry_pending.iter()
162    }
163}