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.dataplane
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.dataplane
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.dataplane.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::dataplane::DataplaneFspMmpSnapshot> {
77        self.dataplane.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    /// Register an identity explicitly resolved through the authenticated
100    /// `.fips` DNS namespace.
101    pub(crate) fn register_dns_identity(
102        &mut self,
103        node_addr: NodeAddr,
104        pubkey: secp256k1::PublicKey,
105    ) -> bool {
106        self.identity_cache.register_dns_resolved(
107            node_addr,
108            pubkey,
109            Self::now_ms(),
110            self.config.node.cache.identity_size,
111        )
112    }
113
114    pub(crate) fn is_dns_resolved_identity(&self, node_addr: &NodeAddr) -> bool {
115        self.identity_cache.is_dns_resolved(node_addr)
116    }
117
118    /// Look up a destination by FipsAddress prefix (bytes 1-15 of the IPv6 address).
119    pub(crate) fn lookup_by_fips_prefix(
120        &mut self,
121        prefix: &[u8; 15],
122    ) -> Option<(NodeAddr, secp256k1::PublicKey)> {
123        self.identity_cache.lookup_by_prefix(prefix, Self::now_ms())
124    }
125
126    /// Check if a node's identity is in the cache (without LRU touch).
127    pub(crate) fn has_cached_identity(&self, addr: &NodeAddr) -> bool {
128        self.identity_cache.has_prefix_for(addr)
129    }
130
131    /// Number of identity cache entries.
132    pub fn identity_cache_len(&self) -> usize {
133        self.identity_cache.len()
134    }
135
136    /// Iterate over identity cache entries.
137    ///
138    /// Returns `(NodeAddr, PublicKey, last_seen_ms)` for each cached identity.
139    /// Used by the `show_identity_cache` control query.
140    pub fn identity_cache_iter(
141        &self,
142    ) -> impl Iterator<Item = (&NodeAddr, &secp256k1::PublicKey, u64)> {
143        self.identity_cache.iter()
144    }
145
146    /// Configured maximum identity cache size.
147    pub fn identity_cache_max(&self) -> usize {
148        self.config.node.cache.identity_size
149    }
150
151    /// Number of pending discovery lookups.
152    pub fn pending_lookup_count(&self) -> usize {
153        self.pending_lookups.len()
154    }
155
156    /// Iterate over pending discovery lookups for diagnostics.
157    pub fn pending_lookups_iter(
158        &self,
159    ) -> impl Iterator<Item = (&NodeAddr, &handlers::discovery::PendingLookup)> {
160        self.pending_lookups.iter()
161    }
162
163    /// Number of recent discovery requests tracked.
164    pub fn recent_request_count(&self) -> usize {
165        self.recent_requests.len()
166    }
167
168    /// Count of destinations with queued TUN packets awaiting session setup.
169    pub fn pending_tun_destinations(&self) -> usize {
170        self.pending_session_traffic.tun_destination_count()
171    }
172
173    /// Total TUN packets queued across all destinations.
174    pub fn pending_tun_total_packets(&self) -> usize {
175        self.pending_session_traffic.tun_packet_count()
176    }
177
178    /// Iterate over retry state for diagnostics.
179    pub fn retry_state_iter(&self) -> impl Iterator<Item = (&NodeAddr, &retry::RetryState)> {
180        self.retry_pending.iter()
181    }
182}