Created
December 21, 2021 23:01
-
-
Save sireliah/2d5924e65ed71d62c9acad2ccd516793 to your computer and use it in GitHub Desktop.
Rendezvous in wasm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use libp2p::{ | |
| core::transport::upgrade, | |
| futures::StreamExt, | |
| identity, mplex, noise, | |
| ping::{Ping, PingConfig, PingEvent}, | |
| rendezvous, | |
| swarm::{AddressScore, SwarmBuilder, SwarmEvent}, | |
| Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport, | |
| }; | |
| use libp2p::wasm_ext; | |
| use std::time::Duration; | |
| use wasm_bindgen::prelude::*; | |
| use wasm_bindgen_futures::spawn_local; | |
| mod utils; | |
| macro_rules! console_log { | |
| // Note that this is using the `log` function imported above during | |
| // `bare_bones` | |
| ($($t:tt)*) => (log(&format_args!($($t)*).to_string())) | |
| } | |
| // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global | |
| // allocator. | |
| #[cfg(feature = "wee_alloc")] | |
| #[global_allocator] | |
| static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; | |
| #[wasm_bindgen] | |
| extern "C" { | |
| fn alert(s: &str); | |
| #[wasm_bindgen(js_namespace = console)] | |
| fn log(s: &str); | |
| } | |
| #[derive(Debug)] | |
| enum MyEvent { | |
| Ping(PingEvent), | |
| Rendezvous(rendezvous::client::Event), | |
| } | |
| impl From<PingEvent> for MyEvent { | |
| fn from(event: PingEvent) -> Self { | |
| MyEvent::Ping(event) | |
| } | |
| } | |
| #[derive(NetworkBehaviour)] | |
| #[behaviour(out_event = "MyEvent")] | |
| struct MyBehaviour { | |
| rendezvous: rendezvous::client::Behaviour, | |
| ping: Ping, | |
| } | |
| impl From<rendezvous::client::Event> for MyEvent { | |
| fn from(event: rendezvous::client::Event) -> Self { | |
| MyEvent::Rendezvous(event) | |
| } | |
| } | |
| fn build_ws_swarm(local_keys: identity::Keypair) -> Swarm<MyBehaviour> { | |
| let local_peer_id = PeerId::from(&local_keys.public()); | |
| console_log!("I am peer {:?}", local_peer_id); | |
| let transport = { | |
| let transport_base = wasm_ext::ffi::websocket_transport(); | |
| let transport_base = wasm_ext::ExtTransport::new(transport_base); | |
| let noise_keys = noise::Keypair::<noise::X25519Spec>::new() | |
| .into_authentic(&local_keys) | |
| .expect("Failed to produce noise keys"); | |
| let mut mplex_config = mplex::MplexConfig::new(); | |
| let mp = mplex_config | |
| .set_max_buffer_size(40960) | |
| .set_split_send_size(1024 * 512); | |
| let noise = noise::NoiseConfig::xx(noise_keys).into_authenticated(); | |
| transport_base | |
| .upgrade(upgrade::Version::V1Lazy) | |
| .authenticate(noise) | |
| .multiplex(mp.clone()) | |
| .timeout(std::time::Duration::from_secs(20)) | |
| .boxed() | |
| }; | |
| let behaviour = MyBehaviour { | |
| rendezvous: rendezvous::client::Behaviour::new(local_keys), | |
| ping: Ping::new(PingConfig::new().with_interval(Duration::from_secs(1))), | |
| }; | |
| let swarm = SwarmBuilder::new(transport, behaviour, local_peer_id); | |
| swarm.build() | |
| } | |
| #[wasm_bindgen] | |
| pub fn info(message: &str) { | |
| log(message); | |
| } | |
| #[wasm_bindgen] | |
| pub async fn listen(peer_address: String) { | |
| utils::set_panic_hook(); | |
| let local_keys = identity::Keypair::generate_ed25519(); | |
| let local_keys_clone = local_keys.clone(); | |
| let mut swarm = build_ws_swarm(local_keys); | |
| let rendezvous_addr = "/ip4/127.0.0.1/tcp/45555/ws".parse::<Multiaddr>().unwrap(); | |
| swarm.add_external_address(rendezvous_addr.clone(), AddressScore::Infinite); | |
| swarm | |
| .dial(rendezvous_addr) | |
| .expect("Dialing rendezvous failed"); | |
| let sw = async move { | |
| while let Some(event) = swarm.next().await { | |
| match event { | |
| SwarmEvent::NewListenAddr { | |
| listener_id, | |
| address, | |
| } => { | |
| console_log!("New listener: {:?}, Address: {:?}", listener_id, address); | |
| if peer_address.len() > 0 { | |
| let addr = peer_address | |
| .parse::<Multiaddr>() | |
| .expect("Parsing address failed"); | |
| swarm.dial(addr).expect("Dialing failed"); | |
| } | |
| } | |
| SwarmEvent::ConnectionEstablished { peer_id, .. } => { | |
| console_log!("Connection established: {:?}", peer_id); | |
| // TODO: check if this is rendezvous server | |
| let behaviour = swarm.behaviour_mut(); | |
| let namespace = rendezvous::Namespace::new("discovery".to_string()) | |
| .expect("Failed to create namespace"); | |
| let namespace_c = namespace.clone(); | |
| console_log!("Registering"); | |
| behaviour.rendezvous.register(namespace, peer_id, None); | |
| console_log!("Discovering"); | |
| behaviour | |
| .rendezvous | |
| .discover(Some(namespace_c), None, None, peer_id); | |
| } | |
| SwarmEvent::Behaviour(MyEvent::Rendezvous( | |
| rendezvous::client::Event::Registered { namespace, .. }, | |
| )) => { | |
| console_log!("Registered in {:?}", namespace); | |
| } | |
| other => console_log!("Event: {:?}", other), | |
| } | |
| } | |
| swarm | |
| }; | |
| sw.await; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment