Skip to main content

TransportManager

Struct TransportManager 

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

Manages multiple transports and handles transport selection.

Implementations§

Source§

impl TransportManager

Source

pub fn new(selector: TransportSelector) -> Self

Creates a new transport manager with default configuration.

Source

pub fn peer_supports_binary_wire(&self, peer_id: &str) -> bool

Returns whether a peer is recorded as able to decode the binary wire codec (and would therefore be sent binary frames).

Source

pub fn mark_peer_binary_wire(&mut self, peer_id: &str, supported: bool)

Records whether a peer can decode our binary wire frames, learned from its signed key package. Messages addressed to a capable peer are stamped WireCodec::BinaryV1 at send; all others stay JSON.

Source

pub fn mark_peer_nostr_pubkey( &mut self, peer_id: &str, pubkey_hex: Option<&str>, )

Forwards a peer’s advertised Nostr public key to the Nostr transport, so gift wraps addressed to them are sealed to a key only their install holds instead of to the publicly computable bootstrap key.

None means “this peer advertises no Nostr key”, which forgets any key already held rather than leaving it in place. That is what keeps the in-memory copy consistent with the durable record, whose downgrade semantics delete on an empty advertisement: retaining it here instead would keep sealing to a key the peer has stopped claiming, and survive only until the next restart — a divergence with no symptom.

A no-op when the Nostr transport is not installed (the common case — nostr_enabled defaults off). The bound on the underlying map lives in the transport.

Source

pub fn clear_peer_nostr_pubkey(&mut self, peer_id: &str)

Forgets a peer’s Nostr public key, so frames to them revert to the publicly computable bootstrap key.

Used by the unblock clean slate, which declares everything learned about a peer stale. Reverting is the right fallback rather than refusing to send: the bootstrap key is derived from the peer’s user id, so it works whatever install they are on now.

Source

pub fn nostr_public_key(&self) -> Option<String>

This install’s Nostr public key, for advertising in outgoing key packages. None when the Nostr transport is not installed.

Source

pub fn set_nostr_sealing_enabled(&mut self, enabled: bool)

Applies the sealed-envelope kill switch to the Nostr transport.

Source

pub fn set_nostr_cold_contact_enabled(&mut self, enabled: bool)

Applies the cold-contact kill switch to the Nostr transport.

Source

pub fn publish_nostr_key_package( &mut self, slot_id: &str, message: &Message, ) -> Result<()>

Queues a key-package record for publication at slot_id.

A no-op when the Nostr transport is not installed, which is the common case: publication is driven from the engine’s tick, and that tick runs whether or not Nostr is enabled.

Serializes through the transport’s own chokepoint, which yields JSON for an unstamped message — and a published record must never be anything else. The binary codec is negotiated per peer from that peer’s key package, and the reader of this record is by definition a stranger whose key package we have not seen. Emitting binary here would make the record unreadable by exactly the audience it exists for.

Source

pub fn take_failed_nostr_publications(&self) -> Vec<String>

Drains the slot ids whose publication never reached a relay.

Empty when Nostr is not installed, which keeps the caller’s tick free of a transport check it would otherwise need.

Source

pub fn nostr_cold_contact_active(&self) -> bool

Whether the Nostr transport is installed and publishing records.

Source

pub fn set_dors_event_callback( &mut self, callback: Option<Arc<dyn Fn(Event) + Send + Sync>>, )

Sets the callback for DORS decision events (dors_score_updated, dors_transport_selected,

Source

pub fn add_transport( &mut self, transport_type: TransportType, transport: Box<dyn Transport>, )

Adds a transport to the manager.

§Arguments
  • transport_type - Type of transport to add
  • transport - The transport implementation
Source

pub fn send(&mut self, message: &Message) -> Result<()>

Sends a message through the best available transport, with fallback.

DORS selects a primary transport (applying hysteresis, cooldown, and stability checks). If the primary’s send() fails synchronously, the remaining transports are tried in descending score order before returning an error. Each synchronous failure is recorded via record_retry_failure so DORS can adjust future scoring.

§Internet transport — fallback does NOT apply

Internet send() enqueues the message and returns Ok(()) immediately. The actual wire-level outcome is reported asynchronously via the confirm_sent / report_send_failure confirmation loop on InternetTransport. Because send() never fails synchronously, the fallback loop below will not trigger for Internet. If the WebSocket is silently broken (status still Available but sends fail), messages will be enqueued, detected as failures by the confirmation-loop timeout, and counted in DORS metrics — but they are not retried on an alternative transport by this method. Retry/re-routing for those messages is handled by the higher-level outbox retry mechanism.

Source

pub fn send_via_transport( &mut self, message: &Message, transport_type: TransportType, ) -> Result<()>

Sends a message via a specific transport, bypassing DORS selection.

§Arguments
  • message - The message to send
  • transport_type - The transport to use
§Returns

Returns Ok(()) if sent successfully, Err otherwise.

Source

pub fn mesh_neighbors(&self) -> Vec<MeshNeighbor>

Lists every peer reachable over a direct mesh link, with the transport that link runs on.

Only the peer-to-peer carriers are consulted: a mesh neighbor is one we can hand a frame to over our own radio, which is what makes it a candidate next hop. Infrastructure carriers (Internet, Nostr, Reticulum) reach peers through something else, so they report no links and appear here as nothing — a message routed through them is not taking a mesh hop, it is leaving the mesh.

A peer visible on more than one carrier is reported once, on the first carrier that claims it; Self::send_to_neighbor resolves the same way, so the pair stay consistent.

Source

pub fn can_reach_without_carrying(&self, peer_id: &str) -> bool

Whether a frame for peer_id can plausibly arrive without being carried by other devices.

This exists because a send returning Ok is not evidence of reachability. Only BLE refuses a recipient it holds no link to; Wi-Fi Direct and Reticulum enqueue for any recipient and report success, so a frame handed to them for someone out of range is queued for a link that will never drain — reported as sent, silently swallowed. Anything that decides “the mesh has to carry this” from a send failure therefore never fires on a device where one of those carriers is up. Asking this instead keeps that decision on facts we can check.

Two ways the answer is yes:

  • An infrastructure carrier is available. Internet, Nostr and Reticulum do their own routing and reach peers we hold no radio link to, so a direct send is a real delivery attempt. (Reticulum counts here because it is a routing network in its own right — its Ok means “accepted for routing”, which is as much as any relay-style carrier promises.)
  • The peer is one of our own mesh neighbors, so a mesh carrier can hand the frame straight over.

Checked in that order so the common online case costs a status scan and never enumerates links.

Source

pub fn can_address_via( &self, transport_type: TransportType, peer_id: &str, ) -> bool

Whether transport_type can actually put a frame in front of peer_id.

The narrower question Self::can_reach_without_carrying answers across every carrier, asked of one. It exists for the same reason: a transport returning Ok is not evidence the frame can arrive. A mesh carrier can only address a peer it holds a live link to, and Wi-Fi Direct enqueues for any recipient regardless — so a frame handed to it for someone several hops away is queued for a link that never drains. Infrastructure carriers do their own routing, so for them the answer is yes whenever they are available.

Callers that would otherwise trust a preferred transport — replying on the link a message arrived over, above all — must ask this first, or the reply dies on exactly the multi-hop path that made forwarding necessary.

Source

pub fn send_to_neighbor( &self, peer_id: &str, message: &Message, ) -> Result<TransportType>

Hands message to a specific mesh neighbor, whatever the message’s own recipient is.

This is the forwarding primitive: the frame crosses one link, to the peer named by peer_id. Because that peer is the physical target, the binary wire codec is negotiated against its capabilities rather than the recipient’s — stamping a forwarded frame binary because the distant recipient supports it could put bytes a neighbor cannot decode onto that neighbor’s link.

Returns the transport the frame went out on.

Source

pub fn receive(&self) -> Result<Option<(TransportType, Message)>>

Attempts to receive a message from any transport.

§Returns

Returns Ok(Some((TransportType, Message))) if a message was received, Ok(None) if no message available.

Source

pub fn get_available_transports( &self, ) -> HashMap<TransportType, TransportMetrics>

Gets metrics for all available transports.

§Returns

Returns a map of transport type to metrics.

Source

pub fn current_transport(&self) -> Option<TransportType>

Gets the current active transport type.

Source

pub fn get_all_transport_statuses( &self, ) -> HashMap<TransportType, TransportStatus>

Returns the current status of every registered transport, including those not currently TransportStatus::Available.

Used by the telemetry aggregator to detect state transitions; unlike TransportManager::get_available_transports, this only reads each transport’s status with no metrics work.

Source

pub fn snapshot_status_and_available( &self, ) -> (HashMap<TransportType, TransportStatus>, HashMap<TransportType, TransportMetrics>)

Returns the per-transport status map AND the available-only metrics map in a single pass.

Equivalent to calling Self::get_all_transport_statuses and Self::get_available_transports back-to-back, but reads each transport’s status once instead of twice. Used by the per-tick telemetry aggregator.

Source

pub fn start(&mut self) -> Result<()>

Starts all transports.

Source

pub fn stop(&mut self) -> Result<()>

Stops all transports.

Source

pub fn get_transport( &self, transport_type: TransportType, ) -> Option<Arc<dyn Transport>>

Gets a shared handle to a specific transport.

Source

pub fn remove_transport(&mut self, transport_type: TransportType)

Removes a transport from the manager.

§Arguments
  • transport_type - Type of transport to remove
Source

pub fn get_active_transports(&self) -> Vec<TransportType>

Gets a list of all active transport types.

§Returns

Returns a vector of transport types that are currently added to the manager.

Source

pub fn should_escalate_to_wifi(&self) -> bool

Checks if DORS suggests escalating from BLE to WiFi Direct.

Source

pub fn record_retry_failure(&mut self, transport_type: TransportType)

Records a retry failure for the given transport.

Source

pub fn reset_retry_count(&mut self, transport_type: TransportType)

Resets retry count for the given transport after successful delivery.

Source

pub fn record_delivery_success( &mut self, transport_type: TransportType, latency_ms: u32, hop_count: u8, )

Records a successful end-to-end delivery for the given transport.

Source

pub fn record_delivery_failure(&mut self, transport_type: TransportType)

Records a delivery failure (after exhausting retries) for the given transport.

Source

pub fn update_selector_config(&mut self, config: DorsConfig)

Updates the DORS selector configuration at runtime, preserving accumulated state (transport history, retry counts, signal tracking).

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> Classify for T

Source§

type Classified = T

Source§

fn classify(self) -> T

Source§

impl<T> Declassify for T

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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. 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