Skip to content

Commit

Permalink
Construct addresses using MultiAddr, defaulting to IPv6 (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
DougAnderson444 authored Apr 18, 2023
1 parent bd1ed98 commit b136592
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 32 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,28 @@ npm run dev

## Getting started: Rust

### 1. Start peer
### 1. Start your own Rust peer

If you are the first peer in the network, simply run:

```
cd rust-peer
cargo run
```

However, for this repo, we have a rust server already running in the cloud, and you can add your own Rust server peer to the chat network with `cargo run` from the `rust-peer` directory.

To connect your rust peer to the rest of the network, you need to add the remote multiaddress of any peer already running as a the command line argument.

Below we have added our already running Rust peer as the arg `remote-address`:

```
cd rust-peer
cargo run -- --remote-address=/ip4/18.195.246.16/udp/9091/quic-v1/p2p/12D3KooWSmtsbL2ukwVwf8gDoTYZHnCd7sVNNVdMnCa4MkWjLujm
```

This will bootstrap your peer to the rest of the network, so you will see all messages sent on the chat topic in your own peer. It needs to connect via `quic-v1` because it works with all servers.

You should see the multiaddr of the peer once its loaded, e.g.

```
Expand Down
2 changes: 0 additions & 2 deletions rust-peer/Cargo.lock

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

2 changes: 0 additions & 2 deletions rust-peer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ libp2p-webrtc = { git = "https://github.com/p-shahi/rust-libp2p.git", branch = "
] }
libp2p-quic = { git = "https://github.com/p-shahi/rust-libp2p.git", branch = "master-plus-webrtc-code", features = ["tokio"] }
log = "0.4.17"
multiaddr = { git = "https://github.com/p-shahi/rust-multiaddr.git", branch = "support-webrtc-protocol-code" }
rand = "0.8.5"
tokio = { version = "1.27.0", features = ["full"] }
tokio-util = { version = "0.7", features = ["full"] }
webrtc = { version = "0.6.0", optional = true }
92 changes: 65 additions & 27 deletions rust-peer/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
use anyhow::{Context, Result};
use clap::Parser;
use futures::future::{select, Either};
use futures::StreamExt;
use libp2p::{
core::muxing::StreamMuxerBox,
gossipsub, identify, identity,
kad::record::store::MemoryStore,
kad::{Kademlia, KademliaConfig},
multiaddr::Protocol,
multiaddr::{Multiaddr, Protocol},
relay,
swarm::{
keep_alive, AddressRecord, AddressScore, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent,
},
Multiaddr, PeerId, Transport,
PeerId, Transport,
};
use libp2p_quic as quic;
use libp2p_webrtc as webrtc;
use libp2p_webrtc::tokio::Certificate;
use log::{debug, error, info, warn};
use std::net::{IpAddr, Ipv6Addr};
use std::path::Path;
use std::{
borrow::Cow,
Expand All @@ -27,7 +29,11 @@ use std::{
use tokio::fs;

const TICK_INTERVAL: Duration = Duration::from_secs(15);
const KADEMLIA_PROTOCOL_NAME: &'static [u8] = b"/universal-connectivity/lan/kad/1.0.0";
const KADEMLIA_PROTOCOL_NAME: &[u8] = b"/universal-connectivity/lan/kad/1.0.0";
const PORT_WEBRTC: u16 = 9090;
const PORT_QUIC: u16 = 9091;
const LOCAL_KEY_PATH: &str = "./local_key";
const LOCAL_CERT_PATH: &str = "./cert.pem";

#[derive(Debug, Parser)]
#[clap(name = "universal connectivity rust peer")]
Expand All @@ -47,39 +53,75 @@ async fn main() -> Result<()> {
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();

let opt = Opt::parse();
let local_key = read_or_create_identity(&Path::new("./local_key"))
let local_key = read_or_create_identity(Path::new(LOCAL_KEY_PATH))
.await
.context("Failed to read identity")?;
let webrtc_cert = read_or_create_certificate(&Path::new("./cert.pem"))
let webrtc_cert = read_or_create_certificate(Path::new(LOCAL_CERT_PATH))
.await
.context("Failed to read certificate")?;

let mut swarm = create_swarm(local_key, webrtc_cert)?;

swarm.listen_on(format!("/ip4/0.0.0.0/udp/9090/webrtc-direct").parse()?)?;
swarm.listen_on(format!("/ip4/0.0.0.0/udp/9091/quic-v1").parse()?)?;
let address_webrtc = Multiaddr::from(Ipv6Addr::UNSPECIFIED)
.with(Protocol::Udp(PORT_WEBRTC))
.with(Protocol::WebRTCDirect);

let address_quic = Multiaddr::from(Ipv6Addr::UNSPECIFIED)
.with(Protocol::Udp(PORT_QUIC))
.with(Protocol::QuicV1);

swarm
.listen_on(address_webrtc.clone())
.expect("listen on webrtc");
swarm
.listen_on(address_quic.clone())
.expect("listen on quic");

if let Some(listen_address) = opt.listen_address {
swarm.add_external_address(
format!("/ip4/{}/udp/9090/webrtc-direct", listen_address).parse()?,
AddressScore::Infinite,
);
// match on whether the listen address string is an IP address or not (do nothing if not)
match listen_address.parse::<IpAddr>() {
Ok(ip) => {
let opt_address_webrtc = Multiaddr::from(ip)
.with(Protocol::Udp(PORT_WEBRTC))
.with(Protocol::WebRTCDirect);
swarm.add_external_address(opt_address_webrtc, AddressScore::Infinite);
}
Err(_) => {
debug!(
"listen_address provided is not an IP address: {}",
listen_address
)
}
}
}

if let Some(remote_address) = opt.remote_address {
swarm.dial(remote_address).unwrap();
swarm
.dial(remote_address)
.expect("a valid remote address to be provided");
}

let mut tick = futures_timer::Delay::new(TICK_INTERVAL);

let now = Instant::now();
loop {
match futures::future::select(swarm.next(), &mut tick).await {
futures::future::Either::Left((event, _)) => match event.unwrap() {
match select(swarm.next(), &mut tick).await {
Either::Left((event, _)) => match event.unwrap() {
SwarmEvent::NewListenAddr { address, .. } => {
let p2p_address = address.with(Protocol::P2p((*swarm.local_peer_id()).into()));
info!("Listen p2p address: {p2p_address:?}");
swarm.add_external_address(p2p_address, AddressScore::Infinite);
// closure shortcut to sift through address response
let mut add_addr = |address: Multiaddr| {
let p2p_address = address.with(Protocol::P2p((*swarm.local_peer_id()).into()));
info!("Listen p2p address: {p2p_address:?}");
swarm.add_external_address(p2p_address, AddressScore::Infinite);
};
// Only add globally available IPv6 addresses to the external addresses list.
if let Protocol::Ip6(ip6) = address.iter().next().unwrap() {
if !ip6.is_loopback() && !ip6.is_unspecified() {
add_addr(address.clone());
}
} else {
add_addr(address.clone());
}
}
SwarmEvent::ConnectionEstablished { peer_id, .. } => {
info!("Connected to {peer_id}");
Expand Down Expand Up @@ -153,19 +195,15 @@ async fn main() -> Result<()> {
// TODO (fixme): the below doesn't work because the address is still missing /webrtc/p2p even after https://github.com/libp2p/js-libp2p-webrtc/pull/121
// swarm.behaviour_mut().kademlia.add_address(&peer_id, addr);

let webrtc_address = Multiaddr::try_from(
addr.to_string()
+ "/webrtc/p2p/"
+ &peer_id.clone().to_string(),
)?;
let webrtc_address = addr
.with(Protocol::WebRTCDirect)
.with(Protocol::P2p(peer_id.into()));

swarm
.behaviour_mut()
.kademlia
.add_address(&peer_id, webrtc_address.clone());
info!("Added {webrtc_address} to the routing table.");

// TODO: below is how we should be constructing the address (not string manipulation)
// let webrtc_address = addr.with(Protocol::WebRTC(peer_id.clone().into()));
}
}
}
Expand All @@ -177,7 +215,7 @@ async fn main() -> Result<()> {
debug!("Other type of event: {:?}", event);
}
},
futures::future::Either::Right(_) => {
Either::Right(_) => {
tick = futures_timer::Delay::new(TICK_INTERVAL);

debug!(
Expand Down Expand Up @@ -270,7 +308,7 @@ fn create_swarm(
};

let identify_config = identify::Behaviour::new(
identify::Config::new("/ipfs/0.1.0".into(), local_key.public().clone())
identify::Config::new("/ipfs/0.1.0".into(), local_key.public())
.with_interval(Duration::from_secs(60)), // do this so we can get timeouts for dropped WebRTC connections
);

Expand Down

1 comment on commit b136592

@vercel
Copy link

@vercel vercel bot commented on b136592 Apr 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.