openrtc 2.8.0

OpenRTC: a Rust-first P2P runtime for device discovery, signaling, and iroh/QUIC networking.
Documentation
use anyhow::{Context, Result};

use super::Client;

impl Client {
    /// Reduce one authoritative avenue roster through the shared Rust policy.
    /// The returned JSON is input to the existing desired-peer actor; this
    /// method never dials or schedules lifecycle work.
    pub async fn configure_sparse_fanout(
        &self,
        capability: &str,
        revision: u64,
        local_device_id: &str,
        local_device_key_x: &str,
        peers_json: &str,
        sparse: bool,
    ) -> Result<(String, crate::sparse_fanout::SparseFanoutProjection)> {
        anyhow::ensure!(
            peers_json.len() <= 256 * 1024,
            "sparse fanout roster exceeds 256 KiB"
        );
        let peers = serde_json::from_str::<Vec<serde_json::Value>>(peers_json)
            .context("decode sparse fanout roster")?;
        anyhow::ensure!(peers.len() <= 100, "sparse fanout roster exceeds 100 peers");
        let local_node_id = self.sparse_fanout_node_id().await?;
        let (projected, diagnostics) = self.sparse_fanout.lock().await.configure(
            capability,
            revision,
            local_device_id,
            &local_node_id,
            local_device_key_x,
            peers,
            sparse,
        )?;
        Ok((serde_json::to_string(&projected)?, diagnostics))
    }

    /// Canonicalize one bounded overlay payload for the existing platform
    /// device signer. This never exposes or imports private key bytes.
    pub async fn prepare_sparse_fanout_message(
        &self,
        capability: &str,
        payload: &[u8],
    ) -> Result<crate::sparse_fanout::SparseFanoutSigningRequest> {
        self.sparse_fanout
            .lock()
            .await
            .prepare(capability, payload, sparse_fanout_now_ms())
    }

    /// Finalize exactly one canonical draft after the platform device signer
    /// returns an Ed25519 signature. Rust verifies the signature before bytes
    /// become eligible for transport.
    pub async fn finalize_sparse_fanout_message(
        &self,
        request_id: &str,
        signature: &str,
    ) -> Result<Vec<u8>> {
        self.sparse_fanout
            .lock()
            .await
            .finalize(request_id, signature, sparse_fanout_now_ms())
    }

    /// Validate and deduplicate one sparse overlay frame. `source_peer_id` is
    /// the already-admitted immediate Iroh peer that delivered the frame.
    pub async fn accept_sparse_fanout_message(
        &self,
        capability: &str,
        source_peer_id: &str,
        encoded: &[u8],
    ) -> Result<crate::sparse_fanout::SparseFanoutDecision> {
        self.sparse_fanout.lock().await.accept(
            capability,
            source_peer_id,
            encoded,
            sparse_fanout_now_ms(),
        )
    }

    pub async fn sparse_fanout_diagnostics(
        &self,
        capability: &str,
    ) -> crate::sparse_fanout::SparseFanoutDiagnostics {
        self.sparse_fanout.lock().await.diagnostics(capability)
    }

    pub async fn record_sparse_fanout_forward_queue_drop(
        &self,
        capability: &str,
        count: u64,
    ) -> Result<()> {
        self.sparse_fanout
            .lock()
            .await
            .record_forward_queue_drop(capability, count)
    }

    async fn sparse_fanout_node_id(&self) -> Result<String> {
        let node = self.iroh_node.read().await;
        let node = node
            .as_ref()
            .ok_or_else(|| anyhow::anyhow!("Iroh node is not initialized"))?;
        Ok(node.endpoint().id().to_string())
    }
}

fn sparse_fanout_now_ms() -> u64 {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap_or_default()
        .as_millis()
        .min(u128::from(u64::MAX)) as u64
}