Skip to main content

P2PNode

Struct P2PNode 

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

Main P2P network node that manages connections, routing, and communication

This struct represents a complete P2P network participant that can:

  • Connect to other peers via QUIC transport
  • Participate in distributed hash table (DHT) operations
  • Send and receive messages through various protocols
  • Handle network events and peer lifecycle

Transport concerns (connections, messaging, events) are delegated to TransportHandle.

Implementations§

Source§

impl P2PNode

Source

pub async fn new(config: NodeConfig) -> Result<Self, P2PError>

Create a new P2P node with the given configuration

Source

pub fn peer_id(&self) -> &PeerId

Get the peer ID of this node.

Source

pub fn transport(&self) -> &Arc<TransportHandle>

Get the transport handle for sharing with other components.

Source

pub fn local_addr(&self) -> Option<MultiAddr>

Source

pub fn is_bootstrapped(&self) -> bool

Check if the node has completed the initial bootstrap process

Returns true if the node has successfully connected to at least one bootstrap peer and performed peer discovery (FIND_NODE).

Source

pub async fn re_bootstrap(&self) -> Result<(), P2PError>

Manually trigger re-bootstrap (useful for recovery or network rejoin)

This clears the bootstrapped state and attempts to reconnect to bootstrap peers and discover new peers.

Source

pub fn trust_engine(&self) -> Arc<TrustEngine>

Get the trust engine for advanced use cases

Source

pub async fn report_trust_event(&self, peer_id: &PeerId, event: TrustEvent)

Report a trust event for a peer.

Records a network-observable outcome (connection success/failure) that the DHT layer did not record automatically. See TrustEvent for the supported variants.

§Example
use saorsa_core::adaptive::TrustEvent;

node.report_trust_event(&peer_id, TrustEvent::SuccessfulResponse).await;
node.report_trust_event(&peer_id, TrustEvent::ConnectionFailed).await;
Source

pub fn peer_trust(&self, peer_id: &PeerId) -> f64

Get the current trust score for a peer (0.0 to 1.0).

Returns 0.5 (neutral) for unknown peers.

Source

pub fn adaptive_dht(&self) -> &AdaptiveDHT

Get the AdaptiveDHT component for direct access

Source

pub async fn send_request( &self, peer_id: &PeerId, protocol: &str, data: Vec<u8>, timeout: Duration, ) -> Result<PeerResponse, P2PError>

Send a request to a peer and wait for a response with automatic trust reporting.

Unlike fire-and-forget send_message(), this method:

  1. Wraps the payload in a RequestResponseEnvelope with a unique message ID
  2. Sends it on the /rr/<protocol> protocol prefix
  3. Waits for a matching response (or timeout)
  4. Automatically reports success or failure to the trust engine

The remote peer’s handler should call send_response() with the incoming message ID to route the response back.

§Arguments
  • peer_id - Target peer
  • protocol - Application protocol name (e.g. "peer_info")
  • data - Request payload bytes
  • timeout - Maximum time to wait for a response
§Returns

A [PeerResponse] on success, or an error on timeout / connection failure.

§Example
let response = node.send_request(&peer_id, "peer_info", request_data, Duration::from_secs(10)).await?;
println!("Got {} bytes from {}", response.data.len(), response.peer_id);
Source

pub async fn send_response( &self, peer_id: &PeerId, protocol: &str, message_id: &str, data: Vec<u8>, ) -> Result<(), P2PError>

Source

pub fn parse_request_envelope(data: &[u8]) -> Option<(String, bool, Vec<u8>)>

Source

pub async fn subscribe(&self, topic: &str) -> Result<(), P2PError>

Source

pub async fn publish(&self, topic: &str, data: &[u8]) -> Result<(), P2PError>

Source

pub fn config(&self) -> &NodeConfig

Get the node configuration

Source

pub async fn start(&self) -> Result<(), P2PError>

Start the P2P node

Source

pub async fn run(&self) -> Result<(), P2PError>

Run the P2P node (blocks until shutdown)

Source

pub async fn stop(&self) -> Result<(), P2PError>

Stop the P2P node

Source

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

Graceful shutdown alias for tests

Source

pub fn is_running(&self) -> bool

Check if the node is running

Source

pub async fn listen_addrs(&self) -> Vec<MultiAddr>

Get the current listen addresses

Source

pub async fn connected_peers(&self) -> Vec<PeerId>

Get connected peers

Source

pub async fn peer_count(&self) -> usize

Get peer count

Source

pub async fn peer_info(&self, peer_id: &PeerId) -> Option<PeerInfo>

Get peer info

Source

pub async fn is_peer_connected(&self, peer_id: &PeerId) -> bool

Check if an authenticated peer is connected (has at least one active channel).

Source

pub async fn connect_peer( &self, address: &MultiAddr, ) -> Result<String, P2PError>

Connect to a peer, returning the transport-level channel ID.

The returned channel ID is not the app-level PeerId. To obtain the authenticated peer identity, call wait_for_peer_identity with the returned channel ID.

Source

pub async fn wait_for_peer_identity( &self, channel_id: &str, timeout: Duration, ) -> Result<PeerId, P2PError>

Wait for the identity exchange on channel_id to complete, returning the authenticated PeerId.

Use this after connect_peer to bridge the gap between the transport-level channel ID and the app-level peer identity required by send_message.

Source

pub async fn disconnect_peer(&self, peer_id: &PeerId) -> Result<(), P2PError>

Disconnect from a peer

Source

pub async fn send_message( &self, peer_id: &PeerId, protocol: &str, data: Vec<u8>, addrs: &[MultiAddr], ) -> Result<(), P2PError>

Send a message to an authenticated peer, reconnecting on demand.

Tries the existing connection first. If the send fails (stale QUIC session, peer not found, etc.), resolves a dial address from:

  1. Caller-provided addrs (highest priority)
  2. Addresses cached in the transport layer (snapshotted before the send attempt, since stale-channel cleanup removes them)
  3. DHT routing table

Then dials, waits for identity exchange, and retries the send exactly once on the fresh connection. Concurrent reconnects to the same peer are serialised so only one dial is attempted at a time.

Source§

impl P2PNode

Source

pub fn subscribe_events(&self) -> Receiver<P2PEvent>

Subscribe to network events

Source

pub fn events(&self) -> Receiver<P2PEvent>

Backwards-compat event stream accessor for tests

Source

pub fn uptime(&self) -> Duration

Get node uptime

Source

pub async fn health_check(&self) -> Result<(), P2PError>

Check system health

Source

pub fn dht_manager(&self) -> &Arc<DhtNetworkManager>

Get the attached DHT manager.

Source

pub fn dht(&self) -> &Arc<DhtNetworkManager>

Backwards-compatible alias for dht_manager().

Source

pub async fn add_discovered_peer( &self, _peer_id: PeerId, addresses: Vec<MultiAddr>, ) -> Result<(), P2PError>

Add a discovered peer to the bootstrap cache

Source

pub async fn update_peer_metrics( &self, addr: &MultiAddr, success: bool, latency_ms: Option<u64>, _error: Option<String>, ) -> Result<(), P2PError>

Update connection metrics for a peer in the bootstrap cache

Source

pub async fn get_bootstrap_cache_stats( &self, ) -> Result<Option<BootstrapStats>, P2PError>

Get bootstrap cache statistics

Source

pub async fn cached_peer_count(&self) -> usize

Get the number of cached bootstrap peers

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