Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rust API Reference

This chapter is a reference for the key entry points and core value types of the Leviculum Rust API, organized by type. Each signature carries a file:line citation to the source as of this writing. It is deliberately not exhaustive: the complete per-type method list is generated rustdoc (see Full rustdoc at the end). Use this chapter to orient, then rustdoc for the long tail.

The hands-on introduction is the tutorial; the layer overview is Choosing a layer.

All reticulum-std types are re-exported from the crate root (reticulum-std/src/lib.rs:35-57), so use reticulum_std::{NodeEvent, LinkHandle, …} works without naming submodules.

reticulum-std (std / tokio)

Reticulum

The configuration-driven entry point, wrapping a ReticulumNode. Defined at reticulum-std/src/reticulum.rs:13. Use this when your node is described by a Config (an INI file or a programmatic Config); use ReticulumNodeBuilder when you assemble interfaces in code.

SignaturePurpose
fn new() -> Result<Self>reticulum.rs:22Build from the default config path, or defaults if absent
fn with_config(config: Config) -> Result<Self>reticulum.rs:37Build from an explicit Config
fn with_config_daemon(config: Config) -> Result<Self>reticulum.rs:55Like with_config but with no application event channel (daemon mode); take_event_receiver() then returns None
async fn start(&mut self) -> Result<()>reticulum.rs:67Spawn the event loop
async fn stop(&mut self) -> Result<()>reticulum.rs:73Stop and persist
fn is_running(&self) -> boolreticulum.rs:80Whether the loop is running
fn config(&self) -> &Configreticulum.rs:85Borrow the active config
fn take_event_receiver(&mut self) -> Option<EventReceiver>reticulum.rs:110Take the event stream, once

ReticulumNodeBuilder

The programmatic builder. Defined at reticulum-std/src/driver/builder.rs:34; re-exported as reticulum_std::ReticulumNodeBuilder. Each setter consumes and returns self.

SignaturePurpose
fn new() -> Selfbuilder.rs:74Builder with defaults
fn identity(self, identity: Identity) -> Selfbuilder.rs:113Pin an explicit identity (else one is generated/persisted)
fn add_tcp_client(self, addr: SocketAddr) -> Selfbuilder.rs:155Connect outward to a Reticulum node
fn add_tcp_server(self, addr: SocketAddr) -> Selfbuilder.rs:168Listen for inbound connections
fn add_udp_interface(self, listen: SocketAddr, forward: SocketAddr) -> Selfbuilder.rs:182One datagram per packet
fn add_rnode_interface(self, port: String, frequency: u64, bandwidth: u32, spreading_factor: u8, coding_rate: u8, tx_power: i8) -> Selfbuilder.rs:198LoRa interface; required radio settings
fn add_serial_interface(self, port: String, speed: u32, databits: u8, parity: String, stopbits: u8) -> Selfbuilder.rs:222KISS over raw serial
fn add_auto_interface(self) -> Selfbuilder.rs:246IPv6 multicast LAN discovery
fn enable_transport(self, enabled: bool) -> Selfbuilder.rs:281Act as a relay/forwarder
fn config(self, config: Config) -> Selfbuilder.rs:129Use a pre-loaded Config
fn config_file(self, path: PathBuf) -> Selfbuilder.rs:139Load an INI config file
fn storage_path(self, path: PathBuf) -> Selfbuilder.rs:147Identity / known-destinations / ratchet store dir
fn connect_to_shared_instance(self, name: impl Into<String>) -> Selfbuilder.rs:322Attach to a running lnsd/rnsd instead of bringing up own interfaces
fn without_events(self) -> Selfbuilder.rs:105Daemon mode: no application event channel
async fn build(self) -> Result<ReticulumNode, Error>builder.rs:518Build the node (not yet running)
fn build_sync(self) -> Result<ReticulumNode, Error>builder.rs:389Same as build, outside an async context

ReticulumNode

The running node. Defined at reticulum-std/src/driver/mod.rs:412; re-exported as reticulum_std::ReticulumNode. Selected methods:

SignaturePurpose
async fn start(&mut self) -> Result<(), Error>driver/mod.rs:575Spawn the event loop, bring interfaces up
async fn stop(&mut self) -> Result<(), Error>driver/mod.rs:1123Stop and flush
fn is_running(&self) -> booldriver/mod.rs:1176Loop state
fn register_destination(&self, destination: Destination)driver/mod.rs:1184Make a local destination reachable (consumes it)
async fn announce_destination(&self, dest_hash: &DestinationHash, app_data: Option<&[u8]>) -> …driver/mod.rs:1590Announce a registered destination
async fn connect(&self, dest_hash: &DestinationHash, dest_signing_key: &[u8; 32]) -> Result<LinkHandle, Error>driver/mod.rs:1202Open a link; returns a pending handle
fn link_handle(&self, link_id: &LinkId) -> LinkHandledriver/mod.rs:1235Writable handle for an already-established inbound link
fn packet_sender(&self, dest_hash: &DestinationHash) -> PacketSenderdriver/mod.rs:1843Single-packet send handle
async fn send_single_packet(&self, …) -> …driver/mod.rs:1797Send one unreliable datagram
fn take_event_receiver(&mut self) -> Option<EventReceiver>driver/mod.rs:1251Take the event stream, once
fn identity_hash(&self) -> [u8; 16]driver/mod.rs:1357The node’s own identity hash
fn has_path(&self, dest_hash: &DestinationHash) -> booldriver/mod.rs:1402Whether a path is known
fn hops_to(&self, dest_hash: &DestinationHash) -> Option<u8>driver/mod.rs:1443Hop count to a destination
async fn request_path(&self, dest_hash: &DestinationHash) -> Result<(), Error>driver/mod.rs:1427Send a PATH_REQUEST; result arrives as PathFound
fn get_identity(&self, dest_hash: &DestinationHash) -> Option<Identity>driver/mod.rs:1411Identity learned from an announce (its signing key feeds connect)
fn transport_stats(&self) -> TransportStatsdriver/mod.rs:1537rnstatus-style counters
fn is_transport_enabled(&self) -> booldriver/mod.rs:1857Relay mode flag

The stable, curated facade reticulum_std::api (reticulum-std/src/api/mod.rs:55 NodeBuilder / :206 Node) re-projects this surface with core internals hidden; it is what reticulum-ffi wraps. Notable facade-only helpers: api::generate_identity() (api/mod.rs:30), api::version() (api/mod.rs:37), api::version_string() (api/mod.rs:46), and Node::connect_with_key (api/mod.rs:329) / Node::accept_link (api/mod.rs:345).

LinkHandle

Send-only async handle for a link. Defined at reticulum-std/src/driver/stream.rs:45; re-exported as reticulum_std::LinkHandle. Incoming data is delivered via NodeEvent, not on the handle.

SignaturePurpose
fn link_id(&self) -> &LinkIdstream.rs:72The link’s id
fn is_closed(&self) -> boolstream.rs:77Handle state
async fn try_send(&self, data: &[u8]) -> Result<(), Error>stream.rs:86Non-blocking send; surfaces Busy / PacingDelay
async fn send(&self, data: &[u8]) -> Result<(), Error>stream.rs:108Send, retrying pacing/busy internally
async fn close(&mut self) -> Result<(), Error>stream.rs:145Graceful close (sends LINKCLOSE)

PacketSender

Send-only async handle for single packets, the single-packet analog of LinkHandle. Defined at reticulum-std/src/driver/sender.rs:42; re-exported as reticulum_std::PacketSender.

SignaturePurpose
fn dest_hash(&self) -> &DestinationHashsender.rs:63The target destination
async fn send(&self, data: &[u8]) -> Result<[u8; TRUNCATED_HASHBYTES], Error>sender.rs:74Send one unreliable packet; returns the truncated packet hash. A path must already be known

EventReceiver and NodeEvent

EventReceiver is the merged event stream, defined at reticulum-std/src/driver/mod.rs:259. It internally fronts a lossless control plane and a droppable data plane (Codeberg #71), draining control first.

SignaturePurpose
async fn recv(&mut self) -> Option<NodeEvent>driver/mod.rs:273Next event, control plane prioritized; None once shut down. Cancel-safe
fn try_recv(&mut self) -> Result<NodeEvent, TryRecvError>driver/mod.rs:298Non-blocking receive

NodeEvent is the event enum, defined in core at reticulum-core/src/node/event.rs:21 and re-exported as reticulum_std::NodeEvent. It is #[non_exhaustive], so always include a catch-all arm. The variants most applications match (field names verbatim from source):

VariantFieldsSource
AnnounceReceivedannounce: ReceivedAnnounce, interface_index: usizeevent.rs:24
PathFounddestination_hash: DestinationHash, hops: u8, interface_index: usizeevent.rs:32
PacketReceiveddestination: DestinationHash, data: Vec<u8>, interface_index: usizeevent.rs:59
PacketDeliveryConfirmedpacket_hash: [u8; TRUNCATED_HASHBYTES]event.rs:69
LinkEstablishedlink_id: LinkId, is_initiator: boolevent.rs:84
MessageReceivedlink_id: LinkId, msgtype: u16, sequence: u16, data: Vec<u8>event.rs:95
LinkDataReceivedlink_id: LinkId, data: Vec<u8>event.rs:111
LinkClosed(see source)event.rs:155

MessageReceived is the channel-multiplexed (sequenced) receive path; LinkDataReceived is the raw-link-packet path. The full variant list (resources, requests/responses, identify, stale/recovered, control-plane overflow) is in event.rs and in rustdoc.

Config

Configuration, defined at reticulum-std/src/config.rs:11; re-exported as reticulum_std::Config. pub reticulum: ReticulumConfig (config.rs:14) and pub interfaces: HashMap<String, InterfaceConfig> (config.rs:17).

SignaturePurpose
fn load<P: AsRef<Path>>(path: P) -> Result<Self>config.rs:315Load an INI config (the rnsd/lnsd format)
fn default_config_dir() -> PathBufconfig.rs:360Default config directory
fn default_config_path() -> PathBufconfig.rs:369Default config file path

reticulum-core (no_std, sans-IO)

The core is the no_std engine the std layer drives. You use these types directly only when building on reticulum-core — see Embedded development. All are re-exported from reticulum-core/src/lib.rs:123-143.

NodeCore<R, C, S>

The sans-IO protocol engine, generic over an RNG R: CryptoRngCore, a clock C: Clock, and storage S: Storage. Defined at reticulum-core/src/node/mod.rs:143. It never performs I/O; every method that can produce output returns a TickOutput the caller must dispatch.

SignaturePurpose
fn new(identity: Identity, config: TransportConfig, proof_strategy: ProofStrategy, max_incoming_resource_size: usize, rng: R, clock: C, storage: S) -> Selfnode/mod.rs:213Construct directly
fn register_destination(&mut self, dest: Destination)node/mod.rs:256Register a local destination
fn announce_destination(&mut self, dest_hash: &DestinationHash, app_data: Option<&[u8]>) -> Result<TickOutput, AnnounceError>node/mod.rs:410Build and queue an announce
fn send_single_packet(&mut self, dest_hash: &DestinationHash, data: &[u8]) -> Result<([u8; TRUNCATED_HASHBYTES], TickOutput), SendError>node/mod.rs:473Build an unreliable data packet
fn connect(&mut self, dest_hash: DestinationHash, dest_signing_key: &[u8; 32]) -> (LinkId, bool, TickOutput)node/link_management.rs:185Build a link request
fn send_on_link(&mut self, link_id: &LinkId, data: &[u8]) -> Result<TickOutput, SendError>node/link_management.rs:504Send on an established link
fn close_link(&mut self, link_id: &LinkId) -> TickOutputnode/link_management.rs:419Close a link
fn handle_packet(&mut self, iface: InterfaceId, data: &[u8]) -> TickOutputnode/mod.rs:1006Feed received bytes from an interface
fn handle_timeout(&mut self) -> TickOutputnode/mod.rs:1098Run periodic maintenance (call at the next deadline)
fn next_deadline(&self) -> Option<u64>node/mod.rs:1129Earliest timer deadline (ms); when to call handle_timeout

A node is more often built with NodeCoreBuilder (node/builder.rs:38), whose fn build<R, Clk, S>(self, rng: R, clock: Clk, storage: S) -> NodeCore<R, Clk, S> (node/builder.rs:168) supplies the platform triple. Setters include identity, proof_strategy, and enable_transport.

Core TickOutput and Action

TickOutput is what every core method returns. Defined at reticulum-core/src/transport.rs:138. It is #[must_use] — dropping it silently loses outbound packets and events.

FieldTypeSource
actionsVec<Action> — I/O for the driver to executetransport.rs:140
eventsVec<NodeEvent> — application-visible eventstransport.rs:142
next_deadline_msOption<u64> — when to next call handle_timeouttransport.rs:145

Action is the I/O the driver performs, defined at reticulum-core/src/transport.rs:113:

VariantFieldsSource
SendPacketiface: InterfaceId, data: Vec<u8>transport.rs:115
Broadcastdata: Vec<u8>, exclude_iface: Option<InterfaceId>transport.rs:122

The helper dispatch_actions(interfaces: &mut [&mut dyn Interface], actions: Vec<Action>, ifac_configs: &BTreeMap<usize, IfacConfig>) -> DispatchResult (transport.rs:211) routes Actions to interfaces with broadcast-exclusion and IFAC wrapping handled in core, so every driver gets it for free.

Value types

Identity — a key pair or public-only identity. Defined at reticulum-core/src/identity.rs. Re-exported as reticulum_std::Identity.

SignaturePurpose
fn generate<R: CryptoRngCore>(rng: &mut R) -> Selfidentity.rs:71New random identity
fn from_public_key_bytes(bytes: &[u8]) -> Result<Self, IdentityError>identity.rs:113Public-only identity
fn from_private_key_bytes(bytes: &[u8]) -> Result<Self, IdentityError>identity.rs:127From the raw 64-byte private key (Python-compatible)
fn hash(&self) -> &[u8; IDENTITY_HASHBYTES]identity.rs:155The 16-byte identity hash
fn public_key_bytes(&self) -> [u8; IDENTITY_KEY_SIZE]identity.rs:16064 bytes: X25519 [0..32], Ed25519 [32..64]
fn has_private_keys(&self) -> boolidentity.rs:185Whether it can sign/decrypt
fn sign(&self, message: &[u8]) -> Result<…, IdentityError>identity.rs:190Ed25519 sign
fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool, IdentityError>identity.rs:202Ed25519 verify

Destination — a local or remote destination. Defined at reticulum-core/src/destination.rs. Re-exported as reticulum_std::Destination.

SignaturePurpose
fn new(identity: Option<Identity>, direction: Direction, dest_type: DestinationType, app_name: &str, aspects: &[&str]) -> Result<Self, DestinationError>destination.rs:285Construct a destination
fn hash(&self) -> &DestinationHashdestination.rs:336Its 16-byte hash
fn direction(&self) -> Directiondestination.rs:351In / Out

DestinationHash — a 16-byte address (newtype, destination.rs:158): fn new(bytes: [u8; TRUNCATED_HASHBYTES]) -> Self (destination.rs:162), fn as_bytes(&self) -> &[u8; TRUNCATED_HASHBYTES] (destination.rs:167), fn into_bytes(self) -> [u8; TRUNCATED_HASHBYTES] (destination.rs:172). Direction (destination.rs:130) and DestinationType (destination.rs:102) are the small enums passed to Destination::new. Packets are constructed internally (reticulum_core::packet::Packet); applications work with destinations and links, not raw packets.

Platform traits

The three abstractions you implement to run the core on a platform. Defined in reticulum-core/src/traits.rs and re-exported from lib.rs:141.

TraitRequired methods (selected)Source
Clockfn now_ms(&self) -> u64traits.rs:162
Storagekey-value persistence: has_packet_hash, get_path/set_path, link/announce tables, identities, ratchets (large trait)traits.rs:196
Interfaceid, name, mtu, is_online, fn try_send(&mut self, data: &[u8]) -> Result<(), InterfaceError>traits.rs:97

Provided Storage implementations: NoStorage (traits.rs:506, zero-sized no-op for stubs and stateless devices), MemoryStorage (reticulum-core/src/memory_storage.rs, BTreeMap-backed with caps), and EmbeddedStorage (reticulum-core/src/embedded_storage.rs:37, heapless-backed for flash-constrained targets; fn new() -> Self at embedded_storage.rs:344). reticulum-std adds a file-backed Storage with Python-compatible on-disk formats.

Full rustdoc

This chapter covers the load-bearing surface; the exhaustive method list is the generated rustdoc. Build and open it with:

cargo doc --no-deps --open -p reticulum-std    # std/tokio layer
cargo doc --no-deps --open -p reticulum-core   # no_std core