diff --git a/Cargo.lock b/Cargo.lock index f0b9391e2ab..7117f4ed109 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4913,7 +4913,10 @@ dependencies = [ "clap", "futures", "libp2p", + "libp2p-webrtc", + "rand 0.8.5", "tokio", + "tracing", "tracing-subscriber", ] diff --git a/examples/relay-server/Cargo.toml b/examples/relay-server/Cargo.toml index 1e0e2a780ba..0cb15f4df35 100644 --- a/examples/relay-server/Cargo.toml +++ b/examples/relay-server/Cargo.toml @@ -12,8 +12,11 @@ release = false clap = { version = "4.5.6", features = ["derive"] } tokio = { version = "1.37.0", features = ["full"] } futures = { workspace = true } -libp2p = { path = "../../libp2p", features = ["tokio", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay", "quic"] } +libp2p = { path = "../../libp2p", features = ["tokio", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay", "quic", "websocket", "dns", "tls"] } +libp2p-webrtc = { workspace = true, features = ["tokio"] } tracing-subscriber = { workspace = true, features = ["env-filter"] } +tracing = "0.1" +rand = "0.8" [lints] workspace = true diff --git a/examples/relay-server/README.md b/examples/relay-server/README.md index cd8f0340a5a..7af37bd1a60 100644 --- a/examples/relay-server/README.md +++ b/examples/relay-server/README.md @@ -13,14 +13,21 @@ To run the example, follow these steps: ``` Replace `` with the port number on which the relay node will listen for incoming connections. + Replace `` with a seed value used to generate a deterministic peer ID for the relay node. - -2. The relay node will start listening for incoming connections. + + Replace `` with the port number on which the relay node will listen for websocket incoming connections. + + Replace `` with the port number on which the relay node will listen for webrtc incoming connections. + + If you do **not** provide `--websocket-port` or `--webrtc-port`, the relay will **not** listen on those transports. + +3. The relay node will start listening for incoming connections. It will print the listening address once it is ready. -3. Connect other **libp2p** nodes to the relay node by specifying the relay's listening address as one of the bootstrap nodes in their configuration. +4. Connect other **libp2p** nodes to the relay node by specifying the relay's listening address as one of the bootstrap nodes in their configuration. -4. Once the connections are established, the relay node will facilitate communication between the connected peers, allowing them to exchange messages and data. +5. Once the connections are established, the relay node will facilitate communication between the connected peers, allowing them to exchange messages and data. ## Conclusion diff --git a/examples/relay-server/src/main.rs b/examples/relay-server/src/main.rs index c5742b8fe7f..e02ccd3ac8d 100644 --- a/examples/relay-server/src/main.rs +++ b/examples/relay-server/src/main.rs @@ -29,11 +29,14 @@ use std::{ use clap::Parser; use futures::StreamExt; use libp2p::{ - core::{multiaddr::Protocol, Multiaddr}, + core::{multiaddr::Protocol, muxing::StreamMuxerBox, Multiaddr, Transport}, identify, identity, noise, ping, relay, swarm::{NetworkBehaviour, SwarmEvent}, - tcp, yamux, + tcp, yamux, PeerId, Swarm, }; +use libp2p_webrtc as webrtc; +use rand::thread_rng; +use tracing::info; use tracing_subscriber::EnvFilter; #[tokio::main] @@ -46,6 +49,8 @@ async fn main() -> Result<(), Box> { // Create a static known PeerId based on given secret let local_key: identity::Keypair = generate_ed25519(opt.secret_key_seed); + let local_peer_id = PeerId::from(local_key.public()); + info!(?local_peer_id, "Local peer id"); let mut swarm = libp2p::SwarmBuilder::with_existing_identity(local_key) .with_tokio() @@ -55,6 +60,16 @@ async fn main() -> Result<(), Box> { yamux::Config::default, )? .with_quic() + .with_other_transport(|id_keys| { + Ok(webrtc::tokio::Transport::new( + id_keys.clone(), + webrtc::tokio::Certificate::generate(&mut thread_rng())?, + ) + .map(|(peer_id, conn), _| (peer_id, StreamMuxerBox::new(conn)))) + })? + .with_dns()? + .with_websocket(noise::Config::new, yamux::Config::default) + .await? .with_behaviour(|key| Behaviour { relay: relay::Behaviour::new(key.public().to_peer_id(), Default::default()), ping: ping::Behaviour::new(ping::Config::new()), @@ -83,6 +98,9 @@ async fn main() -> Result<(), Box> { .with(Protocol::QuicV1); swarm.listen_on(listen_addr_quic)?; + listen_on_websocket(&mut swarm, &opt)?; + listen_on_webrtc(&mut swarm, &opt)?; + loop { match swarm.next().await.expect("Infinite Stream.") { SwarmEvent::Behaviour(event) => { @@ -96,7 +114,8 @@ async fn main() -> Result<(), Box> { println!("{event:?}") } - SwarmEvent::NewListenAddr { address, .. } => { + SwarmEvent::NewListenAddr { mut address, .. } => { + address.push(Protocol::P2p(local_peer_id)); println!("Listening on {address:?}"); } _ => {} @@ -104,6 +123,40 @@ async fn main() -> Result<(), Box> { } } +fn listen_on_websocket(swarm: &mut Swarm, opt: &Opt) -> Result<(), Box> { + match opt.websocket_port { + Some(port) => { + let address = Multiaddr::from(Ipv4Addr::UNSPECIFIED) + .with(Protocol::Tcp(port)) + .with(Protocol::Ws(std::borrow::Cow::Borrowed("/"))); + + info!(?address, "Listening on webSocket"); + swarm.listen_on(address.clone())?; + } + None => { + info!("Does not use websocket"); + } + } + Ok(()) +} + +fn listen_on_webrtc(swarm: &mut Swarm, opt: &Opt) -> Result<(), Box> { + match opt.webrtc_port { + Some(port) => { + let address = Multiaddr::from(Ipv4Addr::UNSPECIFIED) + .with(Protocol::Udp(port)) + .with(Protocol::WebRTCDirect); + + info!(?address, "Listening on webRTC"); + swarm.listen_on(address.clone())?; + } + None => { + info!("Does not use webRTC"); + } + } + Ok(()) +} + #[derive(NetworkBehaviour)] struct Behaviour { relay: relay::Behaviour, @@ -132,4 +185,12 @@ struct Opt { /// The port used to listen on all interfaces #[arg(long)] port: u16, + + /// The websocket port used to listen on all interfaces + #[arg(long)] + websocket_port: Option, + + /// The webrtc port used to listen on all interfaces + #[arg(long)] + webrtc_port: Option, }