Simple example with stream between two peers #2396
-
Hello all. I'm a newcomer to h.SetStreamHandler("/bencher", func(s inet.Stream) {
defer s.Close()
r := rand.New(rand.NewSource(time.Now().UnixNano()))
start := time.Now()
n, err := io.CopyN(s, r, 100<<20)
if err != nil {
fmt.Println("copy error: ", err)
}
took := time.Since(start)
fmt.Printf("transfer took %s (%d bps)\n", took, int(float64(n)/took.Seconds()))
}) Now fetching that data in const {stream} = await libp2p.dialProtocol(pid, '/bencher');
for await (const _ of stream.source) { } Or in go I can call s, err := h.NewStream(context.TODO(), pid, "/bencher")
n, err := io.Copy(ioutil.Discard, s) I've been trying to achieve similar results using |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 7 replies
-
There is a hierachy of The upgrade traits define how to go from bytes to higher-level messages on a protocol stream. The The To achieve what you want is unfortunately not as light-weight as in Go or JS because there is currently no way of not using these abstractions. However, whilst it might not be as appealing for prototyping, these abstractions make it possible to very easily write fast and isolated tests for |
Beta Was this translation helpful? Give feedback.
-
@thomaseizinger I somehow managed to get this to work + compile to #[cfg(feature = "browser")]
mod browser;
use libp2p::core::muxing::outbound_from_ref_and_wrap;
use libp2p::core::{self, transport::OptionalTransport};
use async_std;
use libp2p::wasm_ext;
use libp2p::{identity, Multiaddr, PeerId};
use libp2p::{mplex, noise, Transport};
use multistream_select::dialer_select_proto;
use std::sync::Arc;
#[cfg(feature = "native")]
use libp2p::websocket;
#[cfg(feature = "native")]
use libp2p_dns as dns;
#[cfg(feature = "native")]
use libp2p_tcp as tcp;
pub async fn service(wasm_external_transport: Option<wasm_ext::ExtTransport>, dial: String) {
// Create a random PeerId
let local_key = identity::Keypair::generate_ed25519();
let local_peer_id = PeerId::from(local_key.public());
log::info!("Local peer id: {:?}", local_peer_id);
let dh_keys = noise::Keypair::<noise::X25519Spec>::new()
.into_authentic(&local_key)
.unwrap();
let noise = noise::NoiseConfig::xx(dh_keys).into_authenticated();
log::info!("Attempting to dial: {:?}", dial);
let transport = if let Some(t) = wasm_external_transport {
OptionalTransport::some(t)
} else {
OptionalTransport::none()
};
// if not compiling for wasm
#[cfg(feature = "native")]
let transport = transport.or_transport({
let desktop_trans = tcp::TcpConfig::new();
let desktop_trans =
websocket::WsConfig::new(desktop_trans.clone()).or_transport(desktop_trans);
OptionalTransport::some(
if let Ok(dns) = dns::DnsConfig::system(desktop_trans.clone()).await {
dns.boxed()
} else {
desktop_trans.map_err(dns::DnsErr::Transport).boxed()
},
)
});
// gets an outbound stream from Muxer when dialing
let transport = transport
.upgrade(core::upgrade::Version::V1)
.authenticate(noise)
.multiplex(mplex::MplexConfig::new())
.map(|(peer, muxer), _| (peer, outbound_from_ref_and_wrap(Arc::new(muxer))));
let dial = dial.parse::<Multiaddr>().ok().unwrap();
let protos = vec![b"/bencher"];
// Reach out to another node
let connect = transport.dial(dial.clone()).ok().unwrap().await.unwrap();
// select for a custom protocol ID
let (proto, mut io) = dialer_select_proto(
connect.1.await.unwrap(),
protos.into_iter(),
multistream_select::Version::V1,
)
.await
.unwrap();
log::info!("Dialed proto {:?}!", proto);
// empty out stream into the void !
async_std::io::copy(&mut io, &mut async_std::io::sink())
.await
.ok();
} |
Beta Was this translation helpful? Give feedback.
-
Just to update the thread, the #5027 has been merged into the master branch. You can find an easier method for establishing basic stream between peers in the stream protocol example. |
Beta Was this translation helpful? Give feedback.
rust-libp2p
's design is centered around the idea of modelling each protocol as a pluggable component.There is a hierachy of
NetworkBehaviour
>ProtocolsHandler
>InboundUpgrade
/OutboundUpgrade
.The upgrade traits define how to go from bytes to higher-level messages on a protocol stream.
The
ProtocolsHandler
is responsible for connection-level state management with one peer (per protocol).The
NetworkBehaviour
is responsible for managing state across multiple peers AND connections per protocol.To achieve what you want is unfortunately not as light-weight as in Go or JS because there is currently no way of not using these abstractions.
However, whilst it might not be as appealing for prot…