Skip to content

Peers (Rust)

When someone running the same protocol comes online, you get a peer. Send them data and pin connections you care about. Reach the peer API through app.peer(); peers themselves arrive as Events on app.events().

Peers vs. connections

These are two different layers, and the distinction matters when you build UI around presence:

  • A connection is a transport-level encrypted link between two hosts (devices). There is one connection per (luid, ruid, rhid), shared by every app talking to that host. Connections are wish-core's concern — your app never opens or sees them directly.
  • A peer is an app-level relationship: the tuple (luid, ruid, rhid, rsid, protocol). A peer exists only when all three hold:
    1. the two hosts have a connection,
    2. both sides run the same protocol, and
    3. the local app is permitted to use luid on that connection.

So a host can be connected without any peer being online for your app — the device is reachable, but nothing is speaking your protocol there. Presence in an app should track peers, not connections: a peer going online is the signal that there is something at the other end you can actually talk to.

You learn about peers through Event::Online / Event::Offline on app.events()Online when a peer appears, Offline when it goes away.

The Peer value:

rust
peer.luid      // Vec<u8> — local identity UID
peer.ruid      // Vec<u8> — remote identity UID
peer.rhid      // Vec<u8> — remote host ID
peer.rsid      // Vec<u8> — remote service/app ID
peer.protocol  // String  — protocol name
peer.online    // bool

Sending data

peer().send(peer, frame) (peer: &Peer, frame: &[u8]) -> bool

Send a payload to a peer. No built-in retry — a full send buffer fails the call (507); resending is your app's decision (drop, queue, or back off).

rust
app.peer().send(&peer, b"hello")?;

Frames are raw bytes — you choose the encoding. Most apps use CBOR (ciborium):

rust
let mut buf = Vec::new();
ciborium::into_writer(&msg, &mut buf)?;
app.peer().send(&peer, &buf)?;

Inbound frames arrive as Event::Frame { peer, data }.

Peer pins

By default, connections are opportunistic — wish-core connects when it discovers a peer and disconnects when idle. Pins let you declare which connections matter.

peer().pin(...) (luid, ruid, rhid: &[u8], policy: PinPolicy, priority: u8) -> bool

Pin a peer — tell wish-core to maintain this connection.

rust
use wish_sdk::PinPolicy;

let any_host = [0u8; 32]; // all zeros = any host

app.peer().pin(&my_uid, &bob_uid, &any_host, PinPolicy::Eager, 0)?;

Policies (PinPolicy):

  • Always — maintain connection persistently, reconnect on failure
  • Eager — connect when possible, allow disconnect when idle

Priority: 0 = highest, 255 = lowest. When resources are limited, higher priority pins are maintained first.

peer().unpin(luid, ruid, rhid) (luid, ruid, rhid: &[u8]) -> bool

Remove a peer pin.

peer().pins() () -> Vec<Pin>

List this app's peer pins.

rust
for pin in app.peer().pins()? {
    println!("{:?} {}", pin.policy, pin.priority);
}