Skip to main content

PeerRegistry

Struct PeerRegistry 

Source
pub struct PeerRegistry<N: NetworkProvider + 'static> { /* private fields */ }
Expand description

Manages peer state and WebSocket connections.

The PeerRegistry is the heart of Layer 5. It:

  1. Tracks peers from Layer 3 discovery events — peers exist in the registry even with zero transport connections.
  2. Manages lazy connections — the first send() to a peer triggers a WebSocket connection via Layer 4. Subsequent sends reuse the cached connection.
  3. Routes messages — incoming messages from any peer are forwarded to subscribers via a broadcast channel.
  4. Emits lifecycle eventsPeerEvents for peer discovery changes and connection state changes.

§Example

use std::sync::Arc;
use truffle_core::session::PeerRegistry;

let registry = PeerRegistry::new(network, ws_transport);
registry.start().await;

// Peers appear from Layer 3 discovery
let peers = registry.peers().await;

// First send lazily connects
registry.send("peer-id", b"hello").await?;

Implementations§

Source§

impl<N: NetworkProvider + 'static> PeerRegistry<N>

Source

pub fn new(network: Arc<N>, ws_transport: Arc<WebSocketTransport<N>>) -> Self

Create a new peer registry with default options (eager identity on).

  • network: The Layer 3 network provider for peer discovery.
  • ws_transport: The Layer 4 WebSocket transport for connections.

Call start() after creation to begin processing peer events and accepting incoming connections.

Source

pub fn with_options( network: Arc<N>, ws_transport: Arc<WebSocketTransport<N>>, options: PeerRegistryOptions, ) -> Self

Create a peer registry with explicit options (RFC 022 Phase C).

Source

pub async fn start(&self)

Start the peer registry.

This spawns two background tasks:

  1. A task that subscribes to Layer 3 peer events and maintains the peer list (Joined/Left/Updated).
  2. A task that listens for incoming WebSocket connections from peers and spawns connection tasks for each.

Call this once after constructing the registry.

Source

pub async fn peers(&self) -> Vec<PeerState>

Return all known peers.

This returns peers discovered by Layer 3, including those with no active transport connections (ws_connected: false).

Source

pub fn on_peer_change(&self) -> Receiver<PeerEvent>

Subscribe to peer change events.

Returns a broadcast receiver that yields PeerEvents for peer discovery changes (Joined/Left/Updated) and connection lifecycle changes (Connected/Disconnected).

Source

pub async fn send(&self, peer_id: &str, data: &[u8]) -> Result<(), SessionError>

Send data to a specific peer.

If no WebSocket connection exists to the peer, one is lazily established via Layer 4. The connection is cached for subsequent sends. If the peer is unknown or offline, an error is returned.

§Errors
Source

pub async fn ensure_ws_connected( &self, peer_id: &str, ) -> Result<(), SessionError>

Ensure a WS session exists to peer_id (Tailscale routing key). Completes the RFC 017 hello and applies identity (RFC 022).

Used by app send and by eager-identity (Phase C). Idempotent when already connected.

Source

pub async fn ensure_identity(&self, peer_id: &str) -> Result<(), SessionError>

One-shot identity exchange for an online peer (RFC 022 Phase C).

No-ops if identity is already published or the peer is offline.

Source

pub async fn broadcast(&self, data: &[u8]) -> BroadcastReport

Broadcast data to all peers with active WebSocket connections.

Sends to all currently connected peers. Peers with no active connection are skipped (no lazy connect on broadcast). Errors from individual sends are logged but do not fail the broadcast.

Source

pub fn subscribe(&self) -> Receiver<IncomingMessage>

Subscribe to incoming messages from any connected peer.

Returns a broadcast receiver that yields IncomingMessages. Messages include the sender’s peer ID and raw bytes — Layer 5 does not interpret the payload.

Source

pub async fn disconnect(&self, peer_id: &str)

Disconnect a specific peer’s WebSocket connection.

Removes the cached connection and marks the peer as disconnected. Does not remove the peer from the registry (that only happens when Layer 3 emits a Left event).

Source

pub async fn shutdown(&self)

Close all active WebSocket connections and mark every peer as disconnected. Called by Node::stop() during teardown. Safe to call multiple times — with no active connections it is a no-op.

Auto Trait Implementations§

§

impl<N> !Freeze for PeerRegistry<N>

§

impl<N> !RefUnwindSafe for PeerRegistry<N>

§

impl<N> !UnwindSafe for PeerRegistry<N>

§

impl<N> Send for PeerRegistry<N>

§

impl<N> Sync for PeerRegistry<N>

§

impl<N> Unpin for PeerRegistry<N>

§

impl<N> UnsafeUnpin for PeerRegistry<N>

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