Skip to content
minip2p
Esc
navigateopen⌘Jpreview
On this page

Discover peers

Activate signed presence beacons or local-link mDNS with a bounded peer book and automatic dialing.

Choose the source that matches where peers meet:

  • Use mDNS for peers on the same local network.
  • Use signed discovery when peers already share a pubsub mesh.
  • Enable both when the application needs both sources.

Both sources feed one bounded peer book and one automatic-dial policy.

Enable signed discovery

cargo add minip2p-rs --features discovery

Signed discovery publishes application-scoped presence beacons over pubsub:

let mut node = minip2p::Endpoint::builder()
    .discovery()
    .bind_quic_dual_stack()?;

node.listen_all()?;

.discovery_config(...) selects a custom topic, publication cadence, and announcement limit. Tune the shared address book and dial policy with .peer_discovery_config(...).

Discovery can dial direct addresses announced by other peers without a relay. A configured relay is still required for relay circuits, reservations, and relay-assisted hole punching:

let node = minip2p::Endpoint::builder()
    .relay(relay)
    .discovery()
    .bind_quic_dual_stack()?;

Enable local mDNS

cargo add minip2p-rs --features mdns

Then enable it on the endpoint:

let node = minip2p::Endpoint::builder()
    .mdns()
    .bind_quic_dual_stack()?;

mDNS needs no pubsub or relay. Its observations are unauthenticated until the transport verifies the remote peer, and its automatic dials remain direct-only. KnownPeer::beacon_addrs and KnownPeer::mdns_addrs show where each address came from.

Enable both methods on the same builder when the application needs LAN and pubsub-based discovery.

How peers appear

Each endpoint periodically publishes a signed beacon containing its current dialable address snapshot. Discovery:

  1. verifies the beacon identity and signature;
  2. normalizes and bounds the advertised addresses;
  3. updates the TTL-based known-peer book;
  4. starts or cancels NAT-aware dials according to discovery policy.

Address-less beacons can refresh peer presence without starting a dial. Wildcard listen addresses are filtered because another peer cannot dial them.

Observe the address book

for peer in node.known_peers() {
    println!(
        "peer={} connected={} addresses={:?}",
        peer.peer,
        peer.connected,
        peer.addrs,
    );
}

for event in node.take_discovery_events() {
    println!("{event:?}");
}

DiscoveryEvent reports peers being discovered, updated, or expired, plus automatic dial failures and rejected beacons. Use next_discovery_event(deadline) when a synchronous loop wants one focused event.

Customize policy

use minip2p::{BeaconConfig, Endpoint, PeerDiscoveryConfig};

let beacon = BeaconConfig {
    topic: "my-app/discovery/v1".into(),
    ..BeaconConfig::default()
};
let policy = PeerDiscoveryConfig {
    max_known_peers: 256,
    ..PeerDiscoveryConfig::default()
};

let node = Endpoint::builder()
    .discovery_config(beacon)?
    .peer_discovery_config(policy)?
    .bind_quic_dual_stack()?;

BeaconConfig controls the pubsub topic, cadence, and local announcement cap. PeerDiscoveryConfig is shared by signed discovery and mDNS; it controls peer and address bounds, source TTLs, automatic dialing, tie breaking, retry backoff, and mDNS dial-rate limits. Invalid bounds are rejected before a socket is allocated.

For a complete mesh demonstration, use the existing minip2p-chat example. It combines discovery, gossipsub, relay circuits, and direct upgrades.

Last updated on September 7, 2026

Was this page helpful?