Skip to main content

FipsEndpoint

Struct FipsEndpoint 

Source
pub struct FipsEndpoint { /* private fields */ }
Expand description

A running embedded FIPS endpoint.

Implementations§

Source§

impl FipsEndpoint

Source

pub fn builder() -> FipsEndpointBuilder

Create a builder for an embedded endpoint.

Source

pub fn npub(&self) -> &str

Local endpoint npub.

Source

pub fn node_addr(&self) -> &NodeAddr

Local FIPS node address.

Source

pub fn address(&self) -> FipsAddress

Local FIPS IPv6-compatible address.

Source

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

Application-level discovery scope, if configured.

Source

pub async fn send( &self, remote_npub: impl Into<String>, data: impl Into<Vec<u8>>, ) -> Result<(), FipsEndpointError>

Send application-owned endpoint data to a remote npub.

Fire-and-forget: enqueues the Send command on the node task and returns once the command channel accepts it. The node task’s send result is discarded — TCP and the upper protocol handle loss recovery, and the per-packet oneshot round-trip the previous design used for error reporting added several hundred microseconds of queueing latency under load (measured: 456ms avg ping under iperf3 saturation → 1ms after this change, 430× lower).

PeerIdentity for remote_npub is cached after first resolution to avoid the secp256k1 EC point parse on every packet.

Source

pub async fn send_to_peer( &self, remote: PeerIdentity, data: impl Into<Vec<u8>>, ) -> Result<(), FipsEndpointError>

Send application-owned endpoint data to a resolved remote identity.

This is the fast path for applications that already validate and cache peer identities in their own routing table. It avoids per-packet npub allocation, endpoint cache lookup, and PeerIdentity::from_npub parsing while preserving the same owned-payload command semantics as Self::send.

Source

pub async fn send_batch_to_peer( &self, remote: PeerIdentity, payloads: Vec<Vec<u8>>, ) -> Result<(), FipsEndpointError>

Send a burst of application-owned endpoint payloads to one resolved peer.

Raw payloads are classified once, then enqueued as bounded lane batches instead of one command per packet. Callers that already classified packets while staging their own queues can use Self::send_classified_batch_to_peer.

Source

pub async fn send_classified_batch_to_peer( &self, remote: PeerIdentity, payloads: Vec<FipsEndpointPayload>, ) -> Result<(), FipsEndpointError>

Send a burst of already-classified endpoint payloads to one resolved peer.

Source

pub async fn recv(&self) -> Option<FipsEndpointMessage>

Receive the next source-attributed endpoint data message.

Translation from the internal NodeEndpointEvent::Data shape to the public FipsEndpointMessage shape happens inline here — the rx_loop pushes directly onto this channel, no relay task in between, no extra cross-task hop per packet.

Source

pub async fn recv_batch(&self, max: usize) -> Option<Vec<FipsEndpointMessage>>

Receive one endpoint message, then drain currently queued follow-ons.

This is the receive-side counterpart to Self::send_batch_to_peer: callers still get individual source-attributed messages, but a hot dataplane consumer can amortize the endpoint receiver lock and task wake across a bounded burst.

Source

pub async fn recv_batch_into( &self, messages: &mut Vec<FipsEndpointMessage>, max: usize, ) -> Option<usize>

Receive one endpoint message, then drain ready follow-ons into a caller-owned buffer.

This is the allocation-conscious form of Self::recv_batch for hot dataplane consumers. The provided buffer is cleared before use and keeps its allocation across calls.

Source

pub fn blocking_send( &self, remote_npub: impl Into<String>, data: impl Into<Vec<u8>>, ) -> Result<(), FipsEndpointError>

Synchronous blocking send — parks the calling OS thread on the FIPS endpoint command channel until the runtime accepts the send. MUST be called only from a thread spawned via std::thread::spawn, not from inside a tokio runtime.

Companion to Self::blocking_recv for control-frame replies (e.g. responding to a Ping with a Pong) issued from the dedicated TUN-write thread. Failures are returned via FipsEndpointError::Closed if the runtime has stopped.

Source

pub fn blocking_send_to_peer( &self, remote: PeerIdentity, data: impl Into<Vec<u8>>, ) -> Result<(), FipsEndpointError>

Synchronous blocking send to a resolved remote identity.

This mirrors Self::send_to_peer for callers that already own a PeerIdentity but need to use the blocking endpoint command path.

Source

pub fn blocking_recv(&self) -> Option<FipsEndpointMessage>

Synchronous blocking receive — parks the calling OS thread on the channel until an event arrives or the channel closes.

MUST NOT be called from inside a tokio runtime; use this only from a thread spawned via std::thread::spawn so the tokio scheduler doesn’t deadlock.

The motivation is the bench’s CLI receive task: when run as a regular tokio task each recv().await is a full task-wake on the runtime (~1–3 µs scheduler bookkeeping), and at 113 kpps that’s ~10–30% of one core spent in plumbing the wake-up rather than writing the packet to TUN. A dedicated OS thread blocked on the channel via blocking_recv parks on a futex directly — the wake is a single futex_wake() with no scheduler involvement, an order of magnitude cheaper.

Source

pub fn blocking_recv_batch_into( &self, messages: &mut Vec<FipsEndpointMessage>, max: usize, ) -> Option<usize>

Synchronous blocking batch receive into a caller-owned buffer.

This is the blocking-thread counterpart to Self::recv_batch_into: it parks the calling OS thread for the first message, then drains ready follow-ons while holding the endpoint receiver lock. MUST NOT be called from inside a tokio runtime; use this only from a dedicated blocking thread.

Source

pub fn blocking_recv_batch_for_each( &self, max: usize, handle_message: impl FnMut(FipsEndpointMessage) -> bool, ) -> Option<usize>

Synchronous blocking batch receive that invokes a callback for each delivered endpoint message without staging them in a caller-owned Vec.

This is for dedicated packet-mover threads that immediately forward messages onward. It preserves the same priority-before-bulk ordering, internal batch-tail handling, and receive limit as Self::blocking_recv_batch_into. Returning false from the callback stops the current drain after that message; any unconsumed messages from the current internal batch are retained for the next receive.

Source

pub fn try_recv(&self) -> Option<FipsEndpointMessage>

Non-blocking receive — returns the next ready endpoint message if one is queued, otherwise None. Pair with recv() to drain follow-on packets without paying a scheduler wake per packet:

// wake on the first packet, then drain everything ready
while let Some(msg) = endpoint.recv().await { process(msg); }
while let Some(msg) = endpoint.try_recv() { process(msg); }

On the bench’s FIPS-tunnel receive path the kernel UDP socket delivers packets in recvmmsg-sized bursts, so after a .recv() await there are typically 5–30 packets queued waiting. Draining them inline with try_recv saves N-1 scheduler hops per burst at line rate, freeing the consumer task to spend its time on the TUN write syscall instead of cross-task plumbing.

Returns None if the channel is empty, closed, or briefly contested by another consumer.

Source

pub async fn update_peers( &self, peers: Vec<PeerConfig>, ) -> Result<UpdatePeersOutcome, FipsEndpointError>

Replace the runtime peer list. Newly added auto-connect peers get dialed immediately using every known address (overlay-fresh first, then operator/cache hints). Removed peers are dropped from the retry queue but stay connected if they currently are — the regular liveness timeout reaps idle sessions. Existing entries get their addresses field refreshed so the next retry sees the latest hints.

Pass an empty addresses vector for a peer if you want fips to resolve them entirely from the Nostr advert at dial time.

Source

pub async fn peers(&self) -> Result<Vec<FipsEndpointPeer>, FipsEndpointError>

Snapshot authenticated peers known by the endpoint.

Source

pub async fn relay_statuses( &self, ) -> Result<Vec<FipsEndpointRelayStatus>, FipsEndpointError>

Snapshot live Nostr relay states used by the embedded endpoint.

Source

pub async fn update_relays( &self, advert_relays: Vec<String>, dm_relays: Vec<String>, ) -> Result<(), FipsEndpointError>

Replace Nostr discovery relays without rebuilding the endpoint.

Source

pub async fn send_ip_packet( &self, packet: impl Into<Vec<u8>>, ) -> Result<(), FipsEndpointError>

Send an outbound IPv6 packet into the FIPS session pipeline.

Source

pub async fn recv_ip_packet(&self) -> Option<NodeDeliveredPacket>

Receive the next source-attributed IPv6 packet delivered by FIPS.

Source

pub async fn shutdown(self) -> Result<(), FipsEndpointError>

Shut down the endpoint and wait for the node task to stop.

Auto Trait Implementations§

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