Skip to main content

Node

Struct Node 

Source
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:

  1. Connection phase (connections): Handshake in progress, indexed by LinkId
  2. 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

Source

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

Source

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.

Source

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.

Source

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

Source

pub fn new(config: Config) -> Result<Self, NodeError>

Create a new node from configuration.

Source

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.

Source

pub fn leaf_only(config: Config) -> Result<Self, NodeError>

Create a leaf-only node (simplified state).

Source

pub fn identity(&self) -> &Identity

Get this node’s identity.

Source

pub fn node_addr(&self) -> &NodeAddr

Get this node’s NodeAddr.

Source

pub fn npub(&self) -> String

Get this node’s npub.

Source

pub fn config(&self) -> &Config

Get the configuration.

Source

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.

Source

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.

Source

pub fn state(&self) -> NodeState

Get the node state.

Source

pub fn uptime(&self) -> Duration

Get the node uptime.

Source

pub fn is_running(&self) -> bool

Check if node is operational.

Source

pub fn is_leaf_only(&self) -> bool

Check if this is a leaf-only node.

Source

pub fn tree_state(&self) -> &TreeState

Get the tree state.

Source

pub fn tree_state_mut(&mut self) -> &mut TreeState

Get mutable tree state.

Source

pub fn bloom_state(&self) -> &BloomState

Get the Bloom filter state.

Source

pub fn bloom_state_mut(&mut self) -> &mut BloomState

Get mutable Bloom filter state.

Source

pub fn estimated_mesh_size(&self) -> Option<u64>

Get the cached estimated mesh size.

Source

pub fn coord_cache(&self) -> &CoordCache

Get the coordinate cache.

Source

pub fn coord_cache_mut(&mut self) -> &mut CoordCache

Get mutable coordinate cache.

Source

pub fn stats(&self) -> &NodeStats

Get the node statistics.

Source

pub fn stats_history(&self) -> &StatsHistory

Get the stats history collector.

Source

pub fn tun_state(&self) -> TunState

Get the TUN state.

Source

pub fn tun_name(&self) -> Option<&str>

Get the TUN interface name, if active.

Source

pub fn set_max_connections(&mut self, max: usize)

Set the maximum number of connections (handshake phase).

Source

pub fn set_max_peers(&mut self, max: usize)

Set the maximum number of peers (authenticated).

Set the maximum number of links.

Source

pub fn connection_count(&self) -> usize

Number of pending connections (handshake in progress).

Source

pub fn peer_count(&self) -> usize

Number of authenticated peers.

Number of active links.

Source

pub fn transport_count(&self) -> usize

Number of active transports.

Source

pub fn allocate_transport_id(&mut self) -> TransportId

Allocate a new transport ID.

Source

pub fn get_transport(&self, id: &TransportId) -> Option<&TransportHandle>

Get a transport by ID.

Source

pub fn get_transport_mut( &mut self, id: &TransportId, ) -> Option<&mut TransportHandle>

Get mutable transport by ID.

Source

pub fn transport_ids(&self) -> impl Iterator<Item = &TransportId>

Iterate over transport IDs.

Source

pub fn packet_rx(&mut self) -> Option<&mut PacketRx>

Get the packet receiver for the event loop.

Allocate a new link ID.

Add a link.

Get a link by ID.

Get a mutable link by ID.

Find link ID by transport address.

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.

Iterate over all links.

Source

pub fn add_connection( &mut self, connection: PeerConnection, ) -> Result<(), NodeError>

Add a pending connection.

Source

pub fn get_connection(&self, link_id: &LinkId) -> Option<&PeerConnection>

Get a connection by LinkId.

Source

pub fn get_connection_mut( &mut self, link_id: &LinkId, ) -> Option<&mut PeerConnection>

Get a mutable connection by LinkId.

Source

pub fn remove_connection(&mut self, link_id: &LinkId) -> Option<PeerConnection>

Remove a connection.

Source

pub fn connections(&self) -> impl Iterator<Item = &PeerConnection>

Iterate over all connections.

Source

pub fn get_peer(&self, node_addr: &NodeAddr) -> Option<&ActivePeer>

Get a peer by NodeAddr.

Source

pub fn get_peer_mut(&mut self, node_addr: &NodeAddr) -> Option<&mut ActivePeer>

Get a mutable peer by NodeAddr.

Source

pub fn remove_peer(&mut self, node_addr: &NodeAddr) -> Option<ActivePeer>

Remove a peer.

Source

pub fn peers(&self) -> impl Iterator<Item = &ActivePeer>

Iterate over all peers.

Source

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.

Source

pub fn peer_ids(&self) -> impl Iterator<Item = &NodeAddr>

Iterate over all peer node IDs.

Source

pub fn sendable_peers(&self) -> impl Iterator<Item = &ActivePeer>

Iterate over peers that can send traffic.

Source

pub fn sendable_peer_count(&self) -> usize

Number of peers that can send traffic.

Source

pub fn session_count(&self) -> usize

Number of end-to-end sessions.

Source

pub fn identity_cache_len(&self) -> usize

Number of identity cache entries.

Source

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.

Source

pub fn identity_cache_max(&self) -> usize

Configured maximum identity cache size.

Source

pub fn pending_lookup_count(&self) -> usize

Number of pending discovery lookups.

Source

pub fn pending_lookups_iter( &self, ) -> impl Iterator<Item = (&NodeAddr, &PendingLookup)>

Iterate over pending discovery lookups for diagnostics.

Source

pub fn recent_request_count(&self) -> usize

Number of recent discovery requests tracked.

Source

pub fn pending_tun_destinations(&self) -> usize

Count of destinations with queued TUN packets awaiting session setup.

Source

pub fn pending_tun_total_packets(&self) -> usize

Total TUN packets queued across all destinations.

Source

pub fn retry_state_iter(&self) -> impl Iterator<Item = (&NodeAddr, &RetryState)>

Iterate over retry state for diagnostics.

Source

pub fn find_next_hop( &mut self, dest_node_addr: &NodeAddr, ) -> Option<&ActivePeer>

Find next hop for a destination node address.

Routing priority:

  1. Destination is self → None (local delivery)
  2. Destination is a direct peer → that peer
  3. Reply-learned routes in reply_learned mode. These are locally observed reverse paths, selected with weighted multipath plus periodic coordinate/tree exploration.
  4. 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).
  5. Greedy tree routing fallback (requires cached dest coords)
  6. 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.

Source

pub fn destination_in_filters(&self, dest: &NodeAddr) -> Vec<&ActivePeer>

Check if a destination is in any peer’s bloom filter.

Source

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.

Source

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§

Source§

impl Debug for Node

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more