pub struct FipsEndpoint { /* private fields */ }Expand description
A running embedded FIPS endpoint.
Implementations§
Source§impl FipsEndpoint
impl FipsEndpoint
Sourcepub fn builder() -> FipsEndpointBuilder
pub fn builder() -> FipsEndpointBuilder
Create a builder for an embedded endpoint.
Sourcepub fn address(&self) -> FipsAddress
pub fn address(&self) -> FipsAddress
Local FIPS IPv6-compatible address.
Sourcepub fn discovery_scope(&self) -> Option<&str>
pub fn discovery_scope(&self) -> Option<&str>
Application-level discovery scope, if configured.
Sourcepub async fn send(
&self,
remote_npub: impl Into<String>,
data: impl Into<Vec<u8>>,
) -> Result<(), FipsEndpointError>
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.
Sourcepub async fn send_to_peer(
&self,
remote: PeerIdentity,
data: impl Into<Vec<u8>>,
) -> Result<(), FipsEndpointError>
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.
Sourcepub async fn send_batch_to_peer(
&self,
remote: PeerIdentity,
payloads: Vec<Vec<u8>>,
) -> Result<(), FipsEndpointError>
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.
Sourcepub async fn send_classified_batch_to_peer(
&self,
remote: PeerIdentity,
payloads: Vec<FipsEndpointPayload>,
) -> Result<(), FipsEndpointError>
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.
Sourcepub async fn recv(&self) -> Option<FipsEndpointMessage>
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.
Sourcepub async fn recv_batch(&self, max: usize) -> Option<Vec<FipsEndpointMessage>>
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.
Sourcepub async fn recv_batch_into(
&self,
messages: &mut Vec<FipsEndpointMessage>,
max: usize,
) -> Option<usize>
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.
Sourcepub fn blocking_send(
&self,
remote_npub: impl Into<String>,
data: impl Into<Vec<u8>>,
) -> Result<(), FipsEndpointError>
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.
Sourcepub fn blocking_send_to_peer(
&self,
remote: PeerIdentity,
data: impl Into<Vec<u8>>,
) -> Result<(), FipsEndpointError>
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.
Sourcepub fn blocking_recv(&self) -> Option<FipsEndpointMessage>
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.
Sourcepub fn blocking_recv_batch_into(
&self,
messages: &mut Vec<FipsEndpointMessage>,
max: usize,
) -> Option<usize>
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.
Sourcepub fn blocking_recv_batch_for_each(
&self,
max: usize,
handle_message: impl FnMut(FipsEndpointMessage) -> bool,
) -> Option<usize>
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.
Sourcepub fn try_recv(&self) -> Option<FipsEndpointMessage>
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.
Sourcepub async fn update_peers(
&self,
peers: Vec<PeerConfig>,
) -> Result<UpdatePeersOutcome, FipsEndpointError>
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.
Sourcepub async fn refresh_peer_paths(
&self,
peers: Vec<PeerIdentity>,
) -> Result<usize, FipsEndpointError>
pub async fn refresh_peer_paths( &self, peers: Vec<PeerIdentity>, ) -> Result<usize, FipsEndpointError>
Force immediate direct-path refresh attempts for configured peers.
Unlike FipsEndpoint::update_peers, this does not require a config
diff. It asks the running node to race a fresh direct handshake for the
supplied active peers while preserving existing sessions and routes.
Sourcepub async fn peers(&self) -> Result<Vec<FipsEndpointPeer>, FipsEndpointError>
pub async fn peers(&self) -> Result<Vec<FipsEndpointPeer>, FipsEndpointError>
Snapshot authenticated peers known by the endpoint.
Sourcepub async fn local_advertised_endpoints(
&self,
) -> Result<Vec<OverlayEndpointAdvert>, FipsEndpointError>
pub async fn local_advertised_endpoints( &self, ) -> Result<Vec<OverlayEndpointAdvert>, FipsEndpointError>
Snapshot the endpoint addresses this node is currently advertising via Nostr discovery.
Sourcepub async fn relay_statuses(
&self,
) -> Result<Vec<FipsEndpointRelayStatus>, FipsEndpointError>
pub async fn relay_statuses( &self, ) -> Result<Vec<FipsEndpointRelayStatus>, FipsEndpointError>
Snapshot live Nostr relay states used by the embedded endpoint.
Sourcepub async fn update_relays(
&self,
advert_relays: Vec<String>,
dm_relays: Vec<String>,
) -> Result<(), FipsEndpointError>
pub async fn update_relays( &self, advert_relays: Vec<String>, dm_relays: Vec<String>, ) -> Result<(), FipsEndpointError>
Replace Nostr discovery relays without rebuilding the endpoint.
Sourcepub async fn send_ip_packet(
&self,
packet: impl Into<Vec<u8>>,
) -> Result<(), FipsEndpointError>
pub async fn send_ip_packet( &self, packet: impl Into<Vec<u8>>, ) -> Result<(), FipsEndpointError>
Send an outbound IPv6 packet into the FIPS session pipeline.
Sourcepub async fn recv_ip_packet(&self) -> Option<NodeDeliveredPacket>
pub async fn recv_ip_packet(&self) -> Option<NodeDeliveredPacket>
Receive the next source-attributed IPv6 packet delivered by FIPS.
Sourcepub async fn shutdown(&self) -> Result<(), FipsEndpointError>
pub async fn shutdown(&self) -> Result<(), FipsEndpointError>
Shut down the endpoint and wait for the node task to stop.
Trait Implementations§
Source§impl Drop for FipsEndpoint
impl Drop for FipsEndpoint
Auto Trait Implementations§
impl !Freeze for FipsEndpoint
impl !RefUnwindSafe for FipsEndpoint
impl !UnwindSafe for FipsEndpoint
impl Send for FipsEndpoint
impl Sync for FipsEndpoint
impl Unpin for FipsEndpoint
impl UnsafeUnpin for FipsEndpoint
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