Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement mdns and rendezvous peer discovery #9

Merged
merged 6 commits into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion examples/chat/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "chat-example"
version = "0.1.0"
version = "0.2.0"
authors = ["Calimero Limited <[email protected]>"]
edition = "2021"
repository = "https://github.com/calimero-network/boot-node"
Expand All @@ -15,9 +15,11 @@ libp2p = { version = "0.53.2", features = [
"gossipsub",
"identify",
"macros",
"mdns",
"noise",
"ping",
"quic",
"rendezvous",
"relay",
"tokio",
"tcp",
Expand Down
38 changes: 9 additions & 29 deletions examples/chat/README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,24 @@
# Chat
This examples show cases how to manually dial (connect to) either local peer or remote peer has a reservation on relay-server.
This examples show cases how to build chat application with DCUtR, mDNS, Relay, Rendezvous and GossipSub protocols.
- Local node gets reservation on the relay.
- Local node advertises relayed address at the Rendezvous node.
- Local nodes discovers other local nodes via mDNS discovery and attempts direct connection.
- Local nodes discovers other remote nodes via Rendezvous discovery and attempts hole punched connectioned.

## Run local only
This examples shows how to run two sessions locally and connect sessions by manually dialing local peer.

Run first chat session in echo mode.
```
cargo run -p chat-example -- --mode echo --port 4002 --secret-key-seed 102 --gossip-topic-names calimero-network/examples/chat/v0.0.1 --relay-address /ip4/3.71.239.80/udp/4001/quic-v1/p2p/12D3KooWAgFah4EZtWnMMGMUddGdJpb5cq2NubNCAD2jA5AZgbXF
```

Run second chat session in interactive mode with local peer dial.
```
cargo run -p chat-example -- --mode interactive --port 4003 --secret-key-seed 103 --gossip-topic-names calimero-network/examples/chat/v0.0.1 --dial-peer-addrs /ip4/127.0.0.1/udp/4002/quic-v1/p2p/12D3KooWMpeKAbMK4BTPsQY3rG7XwtdstseHGcq7kffY8LToYYKK --relay-address /ip4/3.71.239.80/udp/4001/quic-v1/p2p/12D3KooWAgFah4EZtWnMMGMUddGdJpb5cq2NubNCAD2jA5AZgbXF
```

In the interactive session publish new message manually:
```
publish calimero-network/examples/chat/v0.0.1 ola
```

## Run locally with remote peer dial in
This examples shows how to run two sessions locally and connect sessions manually by dialing private remote peer from each session. For the gossip message to pass from one local session to second local session it needs to go "the long way" around (local -> remote -> local).

Additional info:
- Remote instance is running in a private subnet behind NAT.
- Remote instance PeerId: `12D3KooWP285Hw3CSTdr9oU6Ezz4hDoi6XS5vfDjjNeTJ1uFMGvp`
- Remote instance address at the relay server: `ip4/3.71.239.80/udp/4001/quic-v1/p2p/12D3KooWAgFah4EZtWnMMGMUddGdJpb5cq2NubNCAD2jA5AZgbXF/p2p-circuit/p2p/12D3KooWP285Hw3CSTdr9oU6Ezz4hDoi6XS5vfDjjNeTJ1uFMGvp`
## Run
Run first chat session in interactive mode with remote peer dial.
```
cargo run -p chat-example -- --mode interactive --port 4002 --secret-key-seed 102 --gossip-topic-names calimero-network/examples/chat/v0.0.1 --dial-peer-addrs /ip4/3.71.239.80/udp/4001/quic-v1/p2p/12D3KooWAgFah4EZtWnMMGMUddGdJpb5cq2NubNCAD2jA5AZgbXF/p2p-circuit/p2p/12D3KooWP285Hw3CSTdr9oU6Ezz4hDoi6XS5vfDjjNeTJ1uFMGvp --relay-address /ip4/3.71.239.80/udp/4001/quic-v1/p2p/12D3KooWAgFah4EZtWnMMGMUddGdJpb5cq2NubNCAD2jA5AZgbXF
cargo run -p chat-example -- --mode interactive --port 4002 --secret-key-seed 102 --gossip-topic-names calimero-network/examples/chat/v0.0.2 --boot-nodes /ip4/35.156.78.13/udp/4001/quic-v1/p2p/12D3KooWRnt7EmBwrNALhAXAgM151MdH7Ka9tvYS91ZUqnqwpjVg
```

Run second chat session in interactive mode with remote peer dial.
```
cargo run -p chat-example -- --mode interactive --port 4003 --secret-key-seed 103 --gossip-topic-names calimero-network/examples/chat/v0.0.1 --dial-peer-addrs /ip4/3.71.239.80/udp/4001/quic-v1/p2p/12D3KooWAgFah4EZtWnMMGMUddGdJpb5cq2NubNCAD2jA5AZgbXF/p2p-circuit/p2p/12D3KooWP285Hw3CSTdr9oU6Ezz4hDoi6XS5vfDjjNeTJ1uFMGvp --relay-address /ip4/3.71.239.80/udp/4001/quic-v1/p2p/12D3KooWAgFah4EZtWnMMGMUddGdJpb5cq2NubNCAD2jA5AZgbXF
cargo run -p chat-example -- --mode interactive --port 4003 --secret-key-seed 103 --gossip-topic-names calimero-network/examples/chat/v0.0.2 --boot-nodes /ip4/35.156.78.13/udp/4001/quic-v1/p2p/12D3KooWRnt7EmBwrNALhAXAgM151MdH7Ka9tvYS91ZUqnqwpjVg
```

In any interactive session publish new message manually:
```
publish calimero-network/examples/chat/v0.0.1 ola
publish calimero-network/examples/chat/v0.0.2 ola
```

## Debugging and known issues
Expand Down
35 changes: 15 additions & 20 deletions examples/chat/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ struct Opt {

/// The listening address of a relay server to connect to.
#[clap(long)]
relay_address: Multiaddr,
boot_nodes: Vec<Multiaddr>,

/// The listening address of a relay server to connect to.
#[clap(long, default_value = "/calimero/devnet/examples/chat")]
rendezvous_namespace: String,

/// Optional list of peer addresses to dial immediately after network bootstrap.
#[clap(long)]
Expand All @@ -51,9 +55,9 @@ enum Mode {
#[tokio::main]
async fn main() -> eyre::Result<()> {
tracing_subscriber::registry()
// "info,chat_example=debug,{}",
// "info,chat_example=debug,libp2p_mdns=warn,{}",
.with(EnvFilter::builder().parse(format!(
"info,chat_example=debug,{}",
"info,libp2p_mdns=warn,{}",
std::env::var("RUST_LOG").unwrap_or_default()
))?)
.with(tracing_subscriber::fmt::layer())
Expand All @@ -63,8 +67,14 @@ async fn main() -> eyre::Result<()> {

let keypair = generate_ed25519(opt.secret_key_seed);

let (network_client, mut network_events) =
network::run(keypair.clone(), opt.port, opt.relay_address.clone()).await?;
let (network_client, mut network_events) = network::run(
keypair.clone(),
opt.port,
libp2p::rendezvous::Namespace::new(opt.rendezvous_namespace)?,
opt.boot_nodes.clone(),
opt.boot_nodes.clone(),
)
.await?;

if let Some(peer_addrs) = opt.dial_peer_addrs {
for addr in peer_addrs {
Expand Down Expand Up @@ -128,18 +138,6 @@ async fn handle_network_event(
is_echo: bool,
) -> eyre::Result<()> {
match event {
network::types::NetworkEvent::IdentifySent { peer_id } => {
debug!("Identify sent to {:?}", peer_id);
}
network::types::NetworkEvent::IdentifyReceived {
peer_id,
observed_addr,
} => {
debug!(
"Identify received from {:?} at {:?}",
peer_id, observed_addr
);
}
network::types::NetworkEvent::Message { message, .. } => {
let text = String::from_utf8_lossy(&message.data);
println!("{LINE_START} Received message: {:?}", text);
Expand All @@ -166,9 +164,6 @@ async fn handle_network_event(
network::types::NetworkEvent::ListeningOn { address, .. } => {
info!("Listening on: {}", address);
}
event => {
info!("Unhandled event: {:?}", event);
}
}
Ok(())
}
Expand Down
Loading