Skip to main content

Crate karyon_p2p

Crate karyon_p2p 

Source
Expand description

§Karyon p2p

A lightweight, extensible, and customizable peer-to-peer network stack. Multi-transport (TCP, TCP/TLS, QUIC) with pluggable custom protocols via the Protocol trait, pluggable discovery with a built-in Kademlia DHT.

§Install

$ cargo add karyon_p2p

§Feature Flags

FeatureDescription
smolUse smol async runtime (default)
tokioUse tokio async runtime
quicEnable QUIC transport
serdeEnable serde support for p2p types
# Default (smol + TCP/TLS)
karyon_p2p = "1.0"

# With QUIC
karyon_p2p = { version = "1.0", features = ["quic"] }

# With tokio
karyon_p2p = { version = "1.0", default-features = false, features = ["tokio", "quic"] }

§Architecture

                          Node
                            |
   +------------+-----------+-----------+
   |            |                       |
Discovery   PeerPool             Connector / Listener
   |            |                       |
Routing     Peers + Protocols       ConnQueue
table           |                       |
                +------- Handshake -----+
                             |
                          karyon_net (TCP / TLS / QUIC)
  • Node: top-level lifecycle. Creates the discovery, pool, connector, and listener; wires them together; exposes the public API.
  • Discovery: finds peers and yields them as DiscoveredPeer. Default is Kademlia DHT; custom implementations of the Discovery trait plug in.
  • Connector / Listener: dial and accept connections over the configured transports, then hand them to ConnQueue.
  • ConnQueue: short-lived bridge between accept/dial and handshake.
  • Handshake: version + protocol negotiation. Verifies peer identity bound to the secure transport’s certificate.
  • PeerPool: registry of post-handshake peers. Owns the per-peer Peer state and broadcasts lifecycle events.
  • Peer / Protocol: per-peer read loop dispatching to the registered protocols. Custom protocols implement the Protocol trait.

§Transport

Peers can listen and connect over multiple transports simultaneously. Configuration uses endpoint URLs (tcp://, tls://, quic://); TLS uses self-signed certs derived from the node’s keypair, and QUIC multiplexes one stream per protocol.

§Discovery

Implementations of the Discovery trait yield candidate peers; the Node dials them. The default is a Kademlia DHT; plug in your own (mDNS, static, …) by implementing the trait.

#[async_trait]
pub trait Discovery: Send + Sync {
    async fn start(self: Arc<Self>) -> Result<()>;
    async fn shutdown(&self);
    async fn recv(&self) -> DiscoveredPeer;
    fn on_event(&self, event: PeerConnectionEvent);
    fn find_peers_with(&self, item: &[u8]) -> Vec<DiscoveredPeer>;
}

§Protocols

A built-in Ping keep-alive runs on every connection; everything else is a custom protocol. For TCP/TLS, protocols share a single framed connection. For QUIC, each protocol gets its own bidirectional stream.

Protocol::kind() defaults to Optional. Override to Mandatory for protocols every peer must speak.

pub struct MyProtocol {
    peer: PeerConn,
}

impl MyProtocol {
    fn new(peer: PeerConn) -> Arc<dyn Protocol> {
        Arc::new(Self { peer })
    }
}

#[async_trait]
impl Protocol for MyProtocol {
    async fn start(self: Arc<Self>) -> Result<(), Error> {
        loop {
            match self.peer.recv().await {
                Ok(_msg) => { /* handle */ }
                Err(Error::PeerShutdown) => break,
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }

    fn version() -> Result<Version, Error> {
        "0.1.0, >0.1.0".parse()
    }

    fn id() -> ProtocolID {
        "MYPROTO".into()
    }

    // Optional override (defaults to ProtocolKind::Optional)
    // fn kind() -> ProtocolKind { ProtocolKind::Mandatory }
}

§Monitor

Subscribe to node.monitor() to observe what the network is doing - connections opening and closing, peer add/remove, handshake failures, discovery lookups and refreshes. Each topic is a separate event type with its own listener; every subscriber gets every event independently.

let listener = node.monitor().register::<ConnectionEvent>();
while let Ok(ev) = listener.recv().await {
    println!("conn event: {} {:?}", ev.event, ev.endpoint);
}

Available event types: ConnectionEvent, PeerPoolEvent, DiscoveryEvent. Gated by Config::enable_monitor.

§Network Security

TLS is available for TCP connections. QUIC has built-in TLS 1.3. The p2p layer generates self-signed certificates from the node’s key pair for mutual authentication.

§Example

use karyon_core::async_runtime::global_executor;
use karyon_p2p::{
    Node, Config,
    keypair::{KeyPair, KeyPairType},
};

async {
    let key_pair = KeyPair::generate(&KeyPairType::Ed25519);

    let config = Config {
        listen_endpoints: vec![
            "tcp://0.0.0.0:8000".parse().unwrap(),
        ],
        discovery_endpoints: vec![
            "tcp://0.0.0.0:7000".parse().unwrap(),
            "udp://0.0.0.0:7000".parse().unwrap(),
        ],
        ..Config::default()
    };

    let node = Node::new(&key_pair, config, global_executor());

    node.run().await.expect("run node");

    // Register custom protocols, connect to peers, etc.

    node.shutdown().await;
};

§Examples

See examples/ for a basic peer node and a chat application.

Modules§

access_control 🔒
bloom 🔒
codec 🔒
config 🔒
conn_queue 🔒
connector 🔒
discovery 🔒
endpoint
error 🔒
handshake 🔒
keypair
listener 🔒
message 🔒
monitor
Responsible for network and system monitoring. Read More
node 🔒
peer 🔒
peer_pool 🔒
protocol
Defines the protocol trait. Read More
protocols 🔒
slots 🔒
tls_config 🔒
util
Bincode encode/decode helpers.
version 🔒

Structs§

AllowAll
Default policy. Allows everything.
Bloom
Two 128-bit bloom filters (k=2 hashes) bundled into one wire type.
Config
Configuration for the p2p network.
DiscoveredPeer
Represents a discovered peer that the discovery protocol wants the Node to connect to.
KademliaDiscovery
Node
Central entry point for the p2p network.
Peer
A connected peer. Holds a Wire that hides the wire shape (single framed pipe vs. per-protocol streams).
PeerAddr
A peer address with protocol and priority. Lower priority number means higher preference.
PeerCandidate
A peer that has completed the handshake but has not joined the pool yet.
PeerID
Represents a unique identifier for a peer.
PeerPool
Version
Represents the network version and protocol version used in karyon p2p.

Enums§

Action
The purpose of the connection.
ConnDirection
Error
Represents karyon’s p2p Error.
PeerEvent
Peer-lifecycle events. Each registered listener receives every event independently.
Protocol
Transport protocol used by a peer address.
Subject
The party being evaluated.

Traits§

AccessControl
Policy that decides which peers this node talks to, and for what.
Discovery
Trait that any discovery protocol must implement.

Type Aliases§

BloomRef
Shared handle to the local bloom. Readers snapshot via *b.read(); writers (attach_protocol, swarm joins, …) update in place. Cheap to clone (Arc) and lock-free for short reads (parking_lot RwLock).
Result