Skip to main content

First App: P2P Chat

Build a minimal peer-to-peer chat app. Two terminals, one initiator, one responder. Under 50 lines of code.

Setup

Open two terminals side by side. Terminal A is the initiator, Terminal B is the responder.

Full Code

// chat.rs
use cairn_p2p::{Node, CairnConfig, create};
use cairn_p2p::api::NodeEvent;
use std::io::{self, BufRead};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = std::env::args().collect();

let node = create(CairnConfig::default())?;
node.start().await?;
println!("Peer ID: {}", node.peer_id());

let peer_id = if args.len() > 1 && args[1] == "--pair-pin" {
let data = node.pair_generate_pin().await?;
println!("PIN: {}", data.pin);
println!("Waiting for peer...");
data.peer_id
} else if args.len() > 2 && args[1] == "--enter-pin" {
node.pair_enter_pin(&args[2]).await?
} else {
eprintln!("Usage: chat --pair-pin | --enter-pin <PIN>");
std::process::exit(1);
};

println!("Paired with: {}", peer_id);
let session = node.connect(&peer_id).await?;
println!("Connected!");

// Receive messages in background
let mut events = node.subscribe();
tokio::spawn(async move {
while let Some(event) = events.recv().await {
if let NodeEvent::MessageReceived { peer_id, channel, data } = event {
println!("[{}] {}: {}", channel, peer_id, String::from_utf8_lossy(&data));
}
}
});

// Read stdin and send
let stdin = io::stdin();
for line in stdin.lock().lines() {
let line = line?;
session.send("chat", line.as_bytes()).await?;
}

Ok(())
}

Running

Open two terminals and run the chat app in your language of choice.

Terminal A (initiator):

cargo run -- --pair-pin

Terminal A will print a PIN code (e.g., A1B2-C3D4). Copy it.

Terminal B (responder):

cargo run -- --enter-pin A1B2-C3D4

Both terminals can now type messages back and forth.

Expected Output

Terminal A:
$ cargo run -- --pair-pin
Peer ID: <base58...>
PIN: A1B2-C3D4
Waiting for peer...
Paired with: <peer_id>
Connected!
> hello
[chat] <peer_id>: hi back!

Terminal B:
$ cargo run -- --enter-pin A1B2-C3D4
Peer ID: <base58...>
Paired with: <peer_id>
Connected!
[chat] <peer_id>: hello
> hi back!

Next Steps