pub struct Node { /* private fields */ }Expand description
A running FIPS node instance.
This is the top-level container holding all node state.
§Peer Lifecycle
Peers go through two phases:
- Connection phase (
connections): Handshake in progress, indexed by LinkId - Active phase (
peers): Authenticated, indexed by NodeAddr
The addr_to_link map enables dispatching incoming packets to the right
connection before authentication completes.
Implementations§
Source§impl Node
impl Node
Sourcepub async fn run_rx_loop(&mut self) -> Result<(), NodeError>
pub async fn run_rx_loop(&mut self) -> Result<(), NodeError>
Run the receive event loop.
Processes packets from all transports, dispatching based on the phase field in the 4-byte common prefix:
- Phase 0x0: Encrypted frame (session data)
- Phase 0x1: Handshake message 1 (initiator -> responder)
- Phase 0x2: Handshake message 2 (responder -> initiator)
Also processes outbound IPv6 packets from the TUN reader for session encapsulation and routing through the mesh.
Also processes DNS-resolved identities for identity cache population.
Also runs a periodic tick (1s) to clean up stale handshake connections that never received a response. This prevents resource leaks when peers are unreachable.
This method takes ownership of the packet_rx channel and runs until the channel is closed (typically when stop() is called).
Source§impl Node
impl Node
Sourcepub async fn start(&mut self) -> Result<(), NodeError>
pub async fn start(&mut self) -> Result<(), NodeError>
Start the node.
Initializes the TUN interface (if configured), spawns I/O threads, and transitions to the Running state.
Sourcepub async fn stop(&mut self) -> Result<(), NodeError>
pub async fn stop(&mut self) -> Result<(), NodeError>
Stop the node.
Shuts down TUN interface, stops I/O threads, and transitions to the Stopped state.
Sourcepub async fn adopt_established_traversal(
&mut self,
traversal: EstablishedTraversal,
) -> Result<BootstrapHandoffResult, NodeError>
pub async fn adopt_established_traversal( &mut self, traversal: EstablishedTraversal, ) -> Result<BootstrapHandoffResult, NodeError>
Adopt an already-established UDP traversal and start the normal FIPS Noise handshake over it.
This is intended for integration with an external rendezvous runtime that has already completed relay signaling, STUN observation, and UDP hole punching. After handoff, the adopted socket is owned by FIPS.
Source§impl Node
impl Node
Sourcepub fn with_identity(
identity: Identity,
config: Config,
) -> Result<Self, NodeError>
pub fn with_identity( identity: Identity, config: Config, ) -> Result<Self, NodeError>
Create a node with a specific identity.
This constructor validates cross-field config invariants before
constructing the node, same as Node::new.
Sourcepub fn leaf_only(config: Config) -> Result<Self, NodeError>
pub fn leaf_only(config: Config) -> Result<Self, NodeError>
Create a leaf-only node (simplified state).
Sourcepub fn effective_ipv6_mtu(&self) -> u16
pub fn effective_ipv6_mtu(&self) -> u16
Calculate the effective IPv6 MTU that can be sent over FIPS.
Delegates to upper::icmp::effective_ipv6_mtu() with this node’s
transport MTU. Returns the maximum IPv6 packet size (including
IPv6 header) that can be transmitted through the FIPS mesh.
Sourcepub fn transport_mtu(&self) -> u16
pub fn transport_mtu(&self) -> u16
Get the transport MTU governing the global TUN-boundary MSS clamp.
Returns the minimum MTU across all operational transports, or
1280 (IPv6 minimum) as fallback. Used for initial TUN configuration
where a specific egress transport isn’t yet known: the resulting
effective_ipv6_mtu (transport_mtu - 77) and max_mss
(effective_mtu - 60) form a conservative ceiling that fits ANY
configured-transport’s egress, eliminating PMTU-D black holes that
would otherwise occur when a flow’s actual egress is smaller than
the clamp ceiling assumed at TUN init.
Returning the smallest (rather than the first-iterated, which used to vary across HashMap iteration order + async-startup race) makes the clamp deterministic across daemon restarts.
See ISSUE-2026-0011 for the empirical investigation.
Sourcepub fn is_running(&self) -> bool
pub fn is_running(&self) -> bool
Check if node is operational.
Sourcepub fn is_leaf_only(&self) -> bool
pub fn is_leaf_only(&self) -> bool
Check if this is a leaf-only node.
Sourcepub fn tree_state(&self) -> &TreeState
pub fn tree_state(&self) -> &TreeState
Get the tree state.
Sourcepub fn tree_state_mut(&mut self) -> &mut TreeState
pub fn tree_state_mut(&mut self) -> &mut TreeState
Get mutable tree state.
Sourcepub fn bloom_state(&self) -> &BloomState
pub fn bloom_state(&self) -> &BloomState
Get the Bloom filter state.
Sourcepub fn bloom_state_mut(&mut self) -> &mut BloomState
pub fn bloom_state_mut(&mut self) -> &mut BloomState
Get mutable Bloom filter state.
Sourcepub fn estimated_mesh_size(&self) -> Option<u64>
pub fn estimated_mesh_size(&self) -> Option<u64>
Get the cached estimated mesh size.
Sourcepub fn coord_cache(&self) -> &CoordCache
pub fn coord_cache(&self) -> &CoordCache
Get the coordinate cache.
Sourcepub fn coord_cache_mut(&mut self) -> &mut CoordCache
pub fn coord_cache_mut(&mut self) -> &mut CoordCache
Get mutable coordinate cache.
Sourcepub fn stats_history(&self) -> &StatsHistory
pub fn stats_history(&self) -> &StatsHistory
Get the stats history collector.
Sourcepub fn set_max_connections(&mut self, max: usize)
pub fn set_max_connections(&mut self, max: usize)
Set the maximum number of connections (handshake phase).
Sourcepub fn set_max_peers(&mut self, max: usize)
pub fn set_max_peers(&mut self, max: usize)
Set the maximum number of peers (authenticated).
Sourcepub fn set_max_links(&mut self, max: usize)
pub fn set_max_links(&mut self, max: usize)
Set the maximum number of links.
Sourcepub fn connection_count(&self) -> usize
pub fn connection_count(&self) -> usize
Number of pending connections (handshake in progress).
Sourcepub fn peer_count(&self) -> usize
pub fn peer_count(&self) -> usize
Number of authenticated peers.
Sourcepub fn link_count(&self) -> usize
pub fn link_count(&self) -> usize
Number of active links.
Sourcepub fn transport_count(&self) -> usize
pub fn transport_count(&self) -> usize
Number of active transports.
Sourcepub fn allocate_transport_id(&mut self) -> TransportId
pub fn allocate_transport_id(&mut self) -> TransportId
Allocate a new transport ID.
Sourcepub fn get_transport(&self, id: &TransportId) -> Option<&TransportHandle>
pub fn get_transport(&self, id: &TransportId) -> Option<&TransportHandle>
Get a transport by ID.
Sourcepub fn get_transport_mut(
&mut self,
id: &TransportId,
) -> Option<&mut TransportHandle>
pub fn get_transport_mut( &mut self, id: &TransportId, ) -> Option<&mut TransportHandle>
Get mutable transport by ID.
Sourcepub fn transport_ids(&self) -> impl Iterator<Item = &TransportId>
pub fn transport_ids(&self) -> impl Iterator<Item = &TransportId>
Iterate over transport IDs.
Sourcepub fn packet_rx(&mut self) -> Option<&mut PacketRx>
pub fn packet_rx(&mut self) -> Option<&mut PacketRx>
Get the packet receiver for the event loop.
Sourcepub fn allocate_link_id(&mut self) -> LinkId
pub fn allocate_link_id(&mut self) -> LinkId
Allocate a new link ID.
Sourcepub fn get_link_mut(&mut self, link_id: &LinkId) -> Option<&mut Link>
pub fn get_link_mut(&mut self, link_id: &LinkId) -> Option<&mut Link>
Get a mutable link by ID.
Sourcepub fn find_link_by_addr(
&self,
transport_id: TransportId,
addr: &TransportAddr,
) -> Option<LinkId>
pub fn find_link_by_addr( &self, transport_id: TransportId, addr: &TransportAddr, ) -> Option<LinkId>
Find link ID by transport address.
Sourcepub fn remove_link(&mut self, link_id: &LinkId) -> Option<Link>
pub fn remove_link(&mut self, link_id: &LinkId) -> Option<Link>
Remove a link.
Only removes the addr_to_link reverse lookup if it still points to this link. In cross-connection scenarios, a newer link may have replaced the entry for the same address.
Sourcepub fn add_connection(
&mut self,
connection: PeerConnection,
) -> Result<(), NodeError>
pub fn add_connection( &mut self, connection: PeerConnection, ) -> Result<(), NodeError>
Add a pending connection.
Sourcepub fn get_connection(&self, link_id: &LinkId) -> Option<&PeerConnection>
pub fn get_connection(&self, link_id: &LinkId) -> Option<&PeerConnection>
Get a connection by LinkId.
Sourcepub fn get_connection_mut(
&mut self,
link_id: &LinkId,
) -> Option<&mut PeerConnection>
pub fn get_connection_mut( &mut self, link_id: &LinkId, ) -> Option<&mut PeerConnection>
Get a mutable connection by LinkId.
Sourcepub fn remove_connection(&mut self, link_id: &LinkId) -> Option<PeerConnection>
pub fn remove_connection(&mut self, link_id: &LinkId) -> Option<PeerConnection>
Remove a connection.
Sourcepub fn connections(&self) -> impl Iterator<Item = &PeerConnection>
pub fn connections(&self) -> impl Iterator<Item = &PeerConnection>
Iterate over all connections.
Sourcepub fn get_peer(&self, node_addr: &NodeAddr) -> Option<&ActivePeer>
pub fn get_peer(&self, node_addr: &NodeAddr) -> Option<&ActivePeer>
Get a peer by NodeAddr.
Sourcepub fn get_peer_mut(&mut self, node_addr: &NodeAddr) -> Option<&mut ActivePeer>
pub fn get_peer_mut(&mut self, node_addr: &NodeAddr) -> Option<&mut ActivePeer>
Get a mutable peer by NodeAddr.
Sourcepub fn remove_peer(&mut self, node_addr: &NodeAddr) -> Option<ActivePeer>
pub fn remove_peer(&mut self, node_addr: &NodeAddr) -> Option<ActivePeer>
Remove a peer.
Sourcepub fn peers(&self) -> impl Iterator<Item = &ActivePeer>
pub fn peers(&self) -> impl Iterator<Item = &ActivePeer>
Iterate over all peers.
Sourcepub fn nostr_discovery_handle(&self) -> Option<&NostrDiscovery>
pub fn nostr_discovery_handle(&self) -> Option<&NostrDiscovery>
Reference to the Nostr discovery handle if discovery is enabled.
Used by control queries (show_peers per-peer Nostr-traversal
state) to read failure-state without taking shared ownership.
Sourcepub fn sendable_peers(&self) -> impl Iterator<Item = &ActivePeer>
pub fn sendable_peers(&self) -> impl Iterator<Item = &ActivePeer>
Iterate over peers that can send traffic.
Sourcepub fn sendable_peer_count(&self) -> usize
pub fn sendable_peer_count(&self) -> usize
Number of peers that can send traffic.
Sourcepub fn session_count(&self) -> usize
pub fn session_count(&self) -> usize
Number of end-to-end sessions.
Sourcepub fn identity_cache_len(&self) -> usize
pub fn identity_cache_len(&self) -> usize
Number of identity cache entries.
Sourcepub fn identity_cache_iter(
&self,
) -> impl Iterator<Item = (&NodeAddr, &PublicKey, u64)>
pub fn identity_cache_iter( &self, ) -> impl Iterator<Item = (&NodeAddr, &PublicKey, u64)>
Iterate over identity cache entries.
Returns (NodeAddr, PublicKey, last_seen_ms) for each cached identity.
Used by the show_identity_cache control query.
Sourcepub fn identity_cache_max(&self) -> usize
pub fn identity_cache_max(&self) -> usize
Configured maximum identity cache size.
Sourcepub fn pending_lookup_count(&self) -> usize
pub fn pending_lookup_count(&self) -> usize
Number of pending discovery lookups.
Sourcepub fn pending_lookups_iter(
&self,
) -> impl Iterator<Item = (&NodeAddr, &PendingLookup)>
pub fn pending_lookups_iter( &self, ) -> impl Iterator<Item = (&NodeAddr, &PendingLookup)>
Iterate over pending discovery lookups for diagnostics.
Sourcepub fn recent_request_count(&self) -> usize
pub fn recent_request_count(&self) -> usize
Number of recent discovery requests tracked.
Sourcepub fn pending_tun_destinations(&self) -> usize
pub fn pending_tun_destinations(&self) -> usize
Count of destinations with queued TUN packets awaiting session setup.
Sourcepub fn pending_tun_total_packets(&self) -> usize
pub fn pending_tun_total_packets(&self) -> usize
Total TUN packets queued across all destinations.
Sourcepub fn retry_state_iter(&self) -> impl Iterator<Item = (&NodeAddr, &RetryState)>
pub fn retry_state_iter(&self) -> impl Iterator<Item = (&NodeAddr, &RetryState)>
Iterate over retry state for diagnostics.
Sourcepub fn find_next_hop(
&mut self,
dest_node_addr: &NodeAddr,
) -> Option<&ActivePeer>
pub fn find_next_hop( &mut self, dest_node_addr: &NodeAddr, ) -> Option<&ActivePeer>
Find next hop for a destination node address.
Routing priority:
- Destination is self →
None(local delivery) - Destination is a direct peer → that peer
- Reply-learned routes in
reply_learnedmode. These are locally observed reverse paths, selected with weighted multipath plus periodic coordinate/tree exploration. - Bloom filter candidates with cached dest coords → among peers whose
bloom filter contains the destination, pick the one that minimizes
tree distance to the destination, with
(link_cost, tree_distance_to_dest, node_addr)tie-breaking. The self-distance check ensures only peers strictly closer to the destination than us are considered (prevents routing loops). - Greedy tree routing fallback (requires cached dest coords)
- No route →
None
Both the bloom filter and tree routing paths require cached destination
coordinates (checked in coord_cache). Without coordinates, the node
cannot make loop-free forwarding decisions. The caller should signal
CoordsRequired back to the source when None is returned for a
non-local destination.
Sourcepub fn destination_in_filters(&self, dest: &NodeAddr) -> Vec<&ActivePeer>
pub fn destination_in_filters(&self, dest: &NodeAddr) -> Vec<&ActivePeer>
Check if a destination is in any peer’s bloom filter.
Sourcepub fn tun_tx(&self) -> Option<&TunTx>
pub fn tun_tx(&self) -> Option<&TunTx>
Get the TUN packet sender channel.
Returns None if TUN is not active or the node hasn’t been started.
Sourcepub fn attach_external_packet_io(
&mut self,
capacity: usize,
) -> Result<ExternalPacketIo, NodeError>
pub fn attach_external_packet_io( &mut self, capacity: usize, ) -> Result<ExternalPacketIo, NodeError>
Attach app-owned packet I/O for embedded operation without a system TUN.
This must be called before Node::start and requires tun.enabled = false. Outbound packets sent to the returned sender are processed by the
normal session pipeline. Inbound packets delivered by FIPS sessions are
sent to the returned receiver with source attribution.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Node
impl !RefUnwindSafe for Node
impl Send for Node
impl Sync for Node
impl Unpin for Node
impl UnsafeUnpin for Node
impl !UnwindSafe for Node
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more