Hello libp2p folks. I’m trying to setup a connection between two nodes, and I’m following the tutorial and using the Ping Behaviour (libp2p-basic-example.rs). Two nodes are able to connect and ping each other if I’m using raw TCP, but when I use WebSockets, nothing happens.
I’m using the development_transport, that has websocket transport defined, and also when I connect to one of the nodes using websocat, I get an info that a connection was established. However I’m not able to get the nodes to talk to each other using Ping over WS.
Console output from node 2
$ cargo run --example basic -- /ip4/127.0.0.1/tcp/35637
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `target/debug/examples/basic /ip4/127.0.0.1/tcp/35637`
local peer id: 12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee
dialed /ip4/127.0.0.1/tcp/35637
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/127.0.0.1/tcp/45767" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/127.0.0.1/tcp/46283/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/192.168.0.199/tcp/45767" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/192.168.0.199/tcp/46283/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/172.17.0.1/tcp/45767" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/172.17.0.1/tcp/46283/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/172.18.0.1/tcp/45767" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/172.18.0.1/tcp/46283/ws" }
swarm event: ConnectionEstablished { peer_id: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), endpoint: Dialer { address: "/ip4/127.0.0.1/tcp/35637" }, num_established: 1, concurrent_dial_errors: Some([]) }
swarm event: Behaviour(Event { peer: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), result: Ok(Pong) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), result: Ok(Ping { rtt: 681.662µs }) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), result: Ok(Pong) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), result: Ok(Ping { rtt: 1.380899ms }) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), result: Ok(Pong) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), result: Ok(Ping { rtt: 1.278549ms }) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), result: Ok(Pong) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr"), result: Ok(Ping { rtt: 1.294483ms }) })
^C
$ cargo run --example basic -- /ip4/192.168.0.199/tcp/36839/ws
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `target/debug/examples/basic /ip4/192.168.0.199/tcp/36839/ws`
local peer id: 12D3KooWRzSG5dFSgsJj7wTfqf9rPRpDEzWbNHwyoTJS61eAVkiM
dialed /ip4/192.168.0.199/tcp/36839/ws
swarm event: OutgoingConnectionError { peer_id: None, error: Transport([("/ip4/192.168.0.199/tcp/36839/ws", Other(Custom { kind: Other, error: Other(A(A(A(MultiaddrNotSupported("/ip4/192.168.0.199/tcp/36839/ws"))))) }))]) }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/127.0.0.1/tcp/34029/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/127.0.0.1/tcp/35629" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/192.168.0.199/tcp/34029/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/192.168.0.199/tcp/35629" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/172.17.0.1/tcp/34029/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/172.17.0.1/tcp/35629" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/172.18.0.1/tcp/34029/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/172.18.0.1/tcp/35629" }
(nothing)
console output from node 1:
$ cargo run --example basic
WARN rustc_metadata::locator no metadata found: incompatible metadata version found: '/home/karim/dev/solcial/copia/target/debug/deps/libprost_derive-cb21d5e1c33265fb.so'
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `target/debug/examples/basic`
local peer id: 12D3KooWM9KT1ioBhWYktvnYpYJChAyLqN3ANkKdGjAjcU8npiUr
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/127.0.0.1/tcp/36839/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/127.0.0.1/tcp/35637" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/192.168.0.199/tcp/36839/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/192.168.0.199/tcp/35637" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/172.17.0.1/tcp/36839/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/172.17.0.1/tcp/35637" }
swarm event: NewListenAddr { listener_id: ListenerId(2), address: "/ip4/172.18.0.1/tcp/36839/ws" }
swarm event: NewListenAddr { listener_id: ListenerId(1), address: "/ip4/172.18.0.1/tcp/35637" }
(... after connecting to /ip4/127.0.0.1/tcp/35637 by another instance....)
swarm event: IncomingConnection { local_addr: "/ip4/127.0.0.1/tcp/35637", send_back_addr: "/ip4/127.0.0.1/tcp/50626" }
swarm event: ConnectionEstablished { peer_id: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), endpoint: Listener { local_addr: "/ip4/127.0.0.1/tcp/35637", send_back_addr: "/ip4/127.0.0.1/tcp/50626" }, num_established: 1, concurrent_dial_errors: None }
swarm event: Behaviour(Event { peer: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), result: Ok(Pong) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), result: Ok(Ping { rtt: 507.696µs }) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), result: Ok(Pong) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), result: Ok(Ping { rtt: 1.373089ms }) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), result: Ok(Pong) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), result: Ok(Ping { rtt: 1.25048ms }) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), result: Ok(Pong) })
swarm event: Behaviour(Event { peer: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), result: Ok(Ping { rtt: 1.247696ms }) })
swarm event: ConnectionClosed { peer_id: PeerId("12D3KooWB2j1S3cGvBFZif8J1ZYs7Q39zMjCFRRwFACqYhumw3Ee"), endpoint: Listener { local_addr: "/ip4/127.0.0.1/tcp/35637", send_back_addr: "/ip4/127.0.0.1/tcp/50626" }, num_established: 0, cause: Some(IO(Custom { kind: Other, error: Closed })) }
(... no more output for /ip4/192.168.0.199/tcp/36839/ws ...)
Rust code:
use anyhow::Result;
use futures::{future, StreamExt};
use libp2p::{
identity,
ping::{Ping, PingConfig},
swarm::Swarm,
PeerId,
};
use std::{task::Poll, time::Duration};
#[tokio::main]
async fn main() -> Result<()> {
let local_key = identity::Keypair::generate_ed25519();
let local_peer_id = PeerId::from(local_key.public());
println!("local peer id: {}", &local_peer_id);
let transport = libp2p::development_transport(local_key).await?;
let behaviour = Ping::new(
PingConfig::new()
.with_keep_alive(true)
.with_interval(Duration::from_secs(1)),
);
let mut swarm = Swarm::new(transport, behaviour, local_peer_id);
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
swarm.listen_on("/ip4/0.0.0.0/tcp/0/ws".parse()?)?;
if let Some(addr) = std::env::args().nth(1) {
let remote = addr.parse()?;
swarm.dial_addr(remote)?;
println!("dialed {}", addr);
}
future::poll_fn(move |cx| loop {
match swarm.poll_next_unpin(cx) {
Poll::Ready(Some(event)) => {
println!("swarm event: {:?}", &event);
}
Poll::Ready(None) => return Poll::Ready(()),
Poll::Pending => return Poll::Pending,
}
})
.await;
#[allow(unreachable_code)]
Ok(())
}
also, for your convenience, the source of the development_transport
adds WebSockets:
pub async fn development_transport(
keypair: identity::Keypair,
) -> std::io::Result<core::transport::Boxed<(PeerId, core::muxing::StreamMuxerBox)>> {
let transport = {
let tcp = tcp::TcpConfig::new().nodelay(true);
let dns_tcp = dns::DnsConfig::system(tcp).await?;
let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone());
dns_tcp.or_transport(ws_dns_tcp)
};
let noise_keys = noise::Keypair::<noise::X25519Spec>::new()
.into_authentic(&keypair)
.expect("Signing libp2p-noise static DH keypair failed.");
Ok(transport
.upgrade(core::upgrade::Version::V1)
.authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated())
.multiplex(core::upgrade::SelectUpgrade::new(
yamux::YamuxConfig::default(),
mplex::MplexConfig::default(),
))
.timeout(std::time::Duration::from_secs(20))
.boxed())
}
also when I connect with websocat, it does recognize a connection, so it does kind of accept WS:
machine 1:
swarm event: IncomingConnection { local_addr: "/ip4/192.168.0.199/tcp/34363/ws", send_back_addr: "/ip4/192.168.0.199/tcp/45178/ws" }
swarm event: IncomingConnectionError { local_addr: "/ip4/192.168.0.199/tcp/34363/ws",
machine 2:
$ websocat ws://192.168.0.199:34363