mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-04-25 11:02:12 +00:00
Merge branch 'master' into rand-feature
This commit is contained in:
commit
50ec01cc31
2
.github/workflows/docker-image.yml
vendored
2
.github/workflows/docker-image.yml
vendored
@ -34,6 +34,6 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./misc/server/Dockerfile
|
||||
push: ${{ ! github.event.pull_request.head.repo.fork }} # Only push image if we have the required permissions, i.e. not running from a fork
|
||||
push: ${{ ! github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }} # Only push image if we have the required permissions, i.e. not running from a fork
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -714,9 +714,9 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
@ -1236,6 +1236,7 @@ dependencies = [
|
||||
"futures-timer",
|
||||
"libp2p",
|
||||
"log",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2205,6 +2206,8 @@ dependencies = [
|
||||
"instant",
|
||||
"libp2p",
|
||||
"libp2p-mplex",
|
||||
"libp2p-noise",
|
||||
"libp2p-tls",
|
||||
"libp2p-webrtc",
|
||||
"libp2p-webrtc-websys",
|
||||
"log",
|
||||
@ -2386,6 +2389,7 @@ dependencies = [
|
||||
"libp2p-mdns",
|
||||
"libp2p-memory-connection-limits",
|
||||
"libp2p-metrics",
|
||||
"libp2p-mplex",
|
||||
"libp2p-noise",
|
||||
"libp2p-ping",
|
||||
"libp2p-plaintext",
|
||||
@ -2406,6 +2410,8 @@ dependencies = [
|
||||
"libp2p-yamux",
|
||||
"multiaddr",
|
||||
"pin-project",
|
||||
"rw-stream-sink",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@ -3045,7 +3051,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libp2p-swarm"
|
||||
version = "0.43.5"
|
||||
version = "0.43.6"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"either",
|
||||
@ -5559,9 +5565,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.32.0"
|
||||
version = "1.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
|
||||
checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
@ -101,7 +101,7 @@ libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" }
|
||||
libp2p-upnp = { version = "0.1.1", path = "protocols/upnp" }
|
||||
libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" }
|
||||
libp2p-server = { version = "0.12.3", path = "misc/server" }
|
||||
libp2p-swarm = { version = "0.43.5", path = "swarm" }
|
||||
libp2p-swarm = { version = "0.43.6", path = "swarm" }
|
||||
libp2p-swarm-derive = { version = "0.33.0", path = "swarm-derive" }
|
||||
libp2p-swarm-test = { version = "0.2.0", path = "swarm-test" }
|
||||
libp2p-tcp = { version = "0.40.0", path = "transports/tcp" }
|
||||
|
@ -6,7 +6,7 @@ publish = false
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.32", features = ["full"] }
|
||||
tokio = { version = "1.33", features = ["full"] }
|
||||
clap = { version = "4.3.23", features = ["derive"] }
|
||||
env_logger = "0.10.0"
|
||||
futures = "0.3.28"
|
||||
|
@ -21,10 +21,10 @@
|
||||
#![doc = include_str!("../../README.md")]
|
||||
|
||||
use clap::Parser;
|
||||
use futures::prelude::*;
|
||||
use futures::StreamExt;
|
||||
use libp2p::core::multiaddr::Protocol;
|
||||
use libp2p::core::{upgrade::Version, Multiaddr, Transport};
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent};
|
||||
use libp2p::core::Multiaddr;
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmEvent};
|
||||
use libp2p::{autonat, identify, identity, noise, tcp, yamux, PeerId};
|
||||
use std::error::Error;
|
||||
use std::net::Ipv4Addr;
|
||||
@ -49,18 +49,16 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
let opt = Opt::parse();
|
||||
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|key| Behaviour::new(key.public()))?
|
||||
.build();
|
||||
|
||||
let transport = tcp::tokio::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&local_key)?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
let behaviour = Behaviour::new(local_key.public());
|
||||
|
||||
let mut swarm = SwarmBuilder::with_tokio_executor(transport, behaviour, local_peer_id).build();
|
||||
swarm.listen_on(
|
||||
Multiaddr::empty()
|
||||
.with(Protocol::Ip4(Ipv4Addr::UNSPECIFIED))
|
||||
|
@ -21,10 +21,10 @@
|
||||
#![doc = include_str!("../../README.md")]
|
||||
|
||||
use clap::Parser;
|
||||
use futures::prelude::*;
|
||||
use libp2p::core::{multiaddr::Protocol, upgrade::Version, Multiaddr, Transport};
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent};
|
||||
use libp2p::{autonat, identify, identity, noise, tcp, yamux, PeerId};
|
||||
use futures::StreamExt;
|
||||
use libp2p::core::{multiaddr::Protocol, Multiaddr};
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmEvent};
|
||||
use libp2p::{autonat, identify, identity, noise, tcp, yamux};
|
||||
use std::error::Error;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
@ -41,18 +41,16 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
let opt = Opt::parse();
|
||||
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|key| Behaviour::new(key.public()))?
|
||||
.build();
|
||||
|
||||
let transport = tcp::tokio::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&local_key)?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
let behaviour = Behaviour::new(local_key.public());
|
||||
|
||||
let mut swarm = SwarmBuilder::with_tokio_executor(transport, behaviour, local_peer_id).build();
|
||||
swarm.listen_on(
|
||||
Multiaddr::empty()
|
||||
.with(Protocol::Ip4(Ipv4Addr::UNSPECIFIED))
|
||||
|
@ -24,7 +24,7 @@ axum = "0.6.19"
|
||||
libp2p = { path = "../../libp2p", features = [ "ed25519", "macros", "ping", "wasm-bindgen", "tokio"] }
|
||||
libp2p-webrtc = { workspace = true, features = ["tokio"] }
|
||||
rust-embed = { version = "8.0.0", features = ["include-exclude", "interpolate-folder-path"] }
|
||||
tokio = { version = "1.29", features = ["macros", "net", "rt", "signal"] }
|
||||
tokio = { version = "1.33", features = ["macros", "net", "rt", "signal"] }
|
||||
tokio-util = { version = "0.7", features = ["compat"] }
|
||||
tower = "0.4"
|
||||
tower-http = { version = "0.4.0", features = ["cors"] }
|
||||
|
@ -6,6 +6,7 @@ use libp2p::core::Multiaddr;
|
||||
use libp2p::identity::{Keypair, PeerId};
|
||||
use libp2p::ping;
|
||||
use libp2p::swarm::{keep_alive, NetworkBehaviour, SwarmBuilder, SwarmEvent};
|
||||
use libp2p::webrtc_websys;
|
||||
use std::convert::From;
|
||||
use std::io;
|
||||
use wasm_bindgen::prelude::*;
|
||||
@ -18,19 +19,16 @@ pub async fn run(libp2p_endpoint: String) -> Result<(), JsError> {
|
||||
let body = Body::from_current_window()?;
|
||||
body.append_p("Let's ping the WebRTC Server!")?;
|
||||
|
||||
let local_key = Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
let mut swarm = SwarmBuilder::with_wasm_executor(
|
||||
libp2p_webrtc_websys::Transport::new(libp2p_webrtc_websys::Config::new(&local_key)).boxed(),
|
||||
Behaviour {
|
||||
let swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_wasm_bindgen()
|
||||
.with_other_transport(|key| {
|
||||
webrtc_websys::Transport::new(webrtc_websys::Config::new(&key))
|
||||
})?
|
||||
.with_behaviour(|_| Behaviour {
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
keep_alive: keep_alive::Behaviour,
|
||||
},
|
||||
local_peer_id,
|
||||
)
|
||||
.build();
|
||||
|
||||
log::info!("Initialize swarm with identity: {local_peer_id}");
|
||||
})?
|
||||
.build();
|
||||
|
||||
let addr = libp2p_endpoint.parse::<Multiaddr>()?;
|
||||
log::info!("Dialing {addr}");
|
||||
|
@ -10,10 +10,9 @@ use futures::StreamExt;
|
||||
use libp2p::{
|
||||
core::muxing::StreamMuxerBox,
|
||||
core::Transport,
|
||||
identity,
|
||||
multiaddr::{Multiaddr, Protocol},
|
||||
ping,
|
||||
swarm::{SwarmBuilder, SwarmEvent},
|
||||
swarm::SwarmEvent,
|
||||
};
|
||||
use libp2p_webrtc as webrtc;
|
||||
use rand::thread_rng;
|
||||
@ -28,19 +27,22 @@ async fn main() -> anyhow::Result<()> {
|
||||
.parse_default_env()
|
||||
.init();
|
||||
|
||||
let id_keys = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = id_keys.public().to_peer_id();
|
||||
let transport = webrtc::tokio::Transport::new(
|
||||
id_keys,
|
||||
webrtc::tokio::Certificate::generate(&mut thread_rng())?,
|
||||
)
|
||||
.map(|(peer_id, conn), _| (peer_id, StreamMuxerBox::new(conn)))
|
||||
.boxed();
|
||||
|
||||
let mut swarm =
|
||||
SwarmBuilder::with_tokio_executor(transport, ping::Behaviour::default(), local_peer_id)
|
||||
.idle_connection_timeout(Duration::from_secs(30)) // Allows us to observe the pings.
|
||||
.build();
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.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_behaviour(|_| ping::Behaviour::default())?
|
||||
.with_swarm_config(|cfg| {
|
||||
cfg.with_idle_connection_timeout(
|
||||
Duration::from_secs(30), // Allows us to observe the pings.
|
||||
)
|
||||
})
|
||||
.build();
|
||||
|
||||
let address_webrtc = Multiaddr::from(Ipv4Addr::UNSPECIFIED)
|
||||
.with(Protocol::Udp(0))
|
||||
|
@ -6,7 +6,7 @@ publish = false
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.32", features = ["full"] }
|
||||
tokio = { version = "1.33", features = ["full"] }
|
||||
async-trait = "0.1"
|
||||
env_logger = "0.10.0"
|
||||
futures = "0.3.28"
|
||||
|
@ -20,14 +20,8 @@
|
||||
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use futures::{future::Either, stream::StreamExt};
|
||||
use libp2p::{
|
||||
core::{muxing::StreamMuxerBox, transport::OrTransport, upgrade},
|
||||
gossipsub, identity, mdns, noise, quic,
|
||||
swarm::NetworkBehaviour,
|
||||
swarm::{SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, PeerId, Transport,
|
||||
};
|
||||
use futures::stream::StreamExt;
|
||||
use libp2p::{gossipsub, mdns, noise, swarm::NetworkBehaviour, swarm::SwarmEvent, tcp, yamux};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::error::Error;
|
||||
use std::hash::{Hash, Hasher};
|
||||
@ -43,58 +37,46 @@ struct MyBehaviour {
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
// Create a random PeerId
|
||||
env_logger::init();
|
||||
let id_keys = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(id_keys.public());
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_quic()
|
||||
.with_behaviour(|key| {
|
||||
// To content-address message, we can take the hash of message and use it as an ID.
|
||||
let message_id_fn = |message: &gossipsub::Message| {
|
||||
let mut s = DefaultHasher::new();
|
||||
message.data.hash(&mut s);
|
||||
gossipsub::MessageId::from(s.finish().to_string())
|
||||
};
|
||||
|
||||
// Set up an encrypted DNS-enabled TCP Transport over the yamux protocol.
|
||||
let tcp_transport = tcp::tokio::Transport::new(tcp::Config::default().nodelay(true))
|
||||
.upgrade(upgrade::Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&id_keys).expect("signing libp2p-noise static keypair"))
|
||||
.multiplex(yamux::Config::default())
|
||||
.timeout(std::time::Duration::from_secs(20))
|
||||
.boxed();
|
||||
let quic_transport = quic::tokio::Transport::new(quic::Config::new(&id_keys));
|
||||
let transport = OrTransport::new(quic_transport, tcp_transport)
|
||||
.map(|either_output, _| match either_output {
|
||||
Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
|
||||
Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
|
||||
})
|
||||
.boxed();
|
||||
// Set a custom gossipsub configuration
|
||||
let gossipsub_config = gossipsub::ConfigBuilder::default()
|
||||
.heartbeat_interval(Duration::from_secs(10)) // This is set to aid debugging by not cluttering the log space
|
||||
.validation_mode(gossipsub::ValidationMode::Strict) // This sets the kind of message validation. The default is Strict (enforce message signing)
|
||||
.message_id_fn(message_id_fn) // content-address messages. No two messages of the same content will be propagated.
|
||||
.build()
|
||||
.map_err(|msg| io::Error::new(io::ErrorKind::Other, msg))?; // Temporary hack because `build` does not return a proper `std::error::Error`.
|
||||
|
||||
// To content-address message, we can take the hash of message and use it as an ID.
|
||||
let message_id_fn = |message: &gossipsub::Message| {
|
||||
let mut s = DefaultHasher::new();
|
||||
message.data.hash(&mut s);
|
||||
gossipsub::MessageId::from(s.finish().to_string())
|
||||
};
|
||||
// build a gossipsub network behaviour
|
||||
let gossipsub = gossipsub::Behaviour::new(
|
||||
gossipsub::MessageAuthenticity::Signed(key.clone()),
|
||||
gossipsub_config,
|
||||
)?;
|
||||
|
||||
// Set a custom gossipsub configuration
|
||||
let gossipsub_config = gossipsub::ConfigBuilder::default()
|
||||
.heartbeat_interval(Duration::from_secs(10)) // This is set to aid debugging by not cluttering the log space
|
||||
.validation_mode(gossipsub::ValidationMode::Strict) // This sets the kind of message validation. The default is Strict (enforce message signing)
|
||||
.message_id_fn(message_id_fn) // content-address messages. No two messages of the same content will be propagated.
|
||||
.build()
|
||||
.expect("Valid config");
|
||||
let mdns =
|
||||
mdns::tokio::Behaviour::new(mdns::Config::default(), key.public().to_peer_id())?;
|
||||
Ok(MyBehaviour { gossipsub, mdns })
|
||||
})?
|
||||
.build();
|
||||
|
||||
// build a gossipsub network behaviour
|
||||
let mut gossipsub = gossipsub::Behaviour::new(
|
||||
gossipsub::MessageAuthenticity::Signed(id_keys),
|
||||
gossipsub_config,
|
||||
)
|
||||
.expect("Correct configuration");
|
||||
// Create a Gossipsub topic
|
||||
let topic = gossipsub::IdentTopic::new("test-net");
|
||||
// subscribes to our topic
|
||||
gossipsub.subscribe(&topic)?;
|
||||
|
||||
// Create a Swarm to manage peers and events
|
||||
let mut swarm = {
|
||||
let mdns = mdns::tokio::Behaviour::new(mdns::Config::default(), local_peer_id)?;
|
||||
let behaviour = MyBehaviour { gossipsub, mdns };
|
||||
SwarmBuilder::with_tokio_executor(transport, behaviour, local_peer_id).build()
|
||||
};
|
||||
swarm.behaviour_mut().gossipsub.subscribe(&topic)?;
|
||||
|
||||
// Read full lines from stdin
|
||||
let mut stdin = io::BufReader::new(io::stdin()).lines();
|
||||
|
@ -10,8 +10,9 @@ clap = { version = "4.3.23", features = ["derive"] }
|
||||
env_logger = "0.10.0"
|
||||
futures = "0.3.28"
|
||||
futures-timer = "3.0"
|
||||
libp2p = { path = "../../libp2p", features = [ "async-std", "dns", "dcutr", "identify", "macros", "noise", "ping", "quic", "relay", "rendezvous", "tcp", "tokio", "yamux"] }
|
||||
libp2p = { path = "../../libp2p", features = [ "dns", "dcutr", "identify", "macros", "noise", "ping", "quic", "relay", "rendezvous", "tcp", "tokio", "yamux"] }
|
||||
log = "0.4"
|
||||
tokio = { version = "1.29", features = ["macros", "net", "rt", "signal"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -21,20 +21,11 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use clap::Parser;
|
||||
use futures::{
|
||||
executor::{block_on, ThreadPool},
|
||||
future::{Either, FutureExt},
|
||||
stream::StreamExt,
|
||||
};
|
||||
use futures::{executor::block_on, future::FutureExt, stream::StreamExt};
|
||||
use libp2p::{
|
||||
core::{
|
||||
multiaddr::{Multiaddr, Protocol},
|
||||
muxing::StreamMuxerBox,
|
||||
transport::Transport,
|
||||
upgrade,
|
||||
},
|
||||
dcutr, dns, identify, identity, noise, ping, quic, relay,
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
core::multiaddr::{Multiaddr, Protocol},
|
||||
dcutr, identify, identity, noise, ping, relay,
|
||||
swarm::{NetworkBehaviour, SwarmEvent},
|
||||
tcp, yamux, PeerId,
|
||||
};
|
||||
use log::info;
|
||||
@ -78,37 +69,12 @@ impl FromStr for Mode {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init();
|
||||
|
||||
let opts = Opts::parse();
|
||||
|
||||
let local_key = generate_ed25519(opts.secret_key_seed);
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
|
||||
let (relay_transport, client) = relay::client::new(local_peer_id);
|
||||
|
||||
let transport = {
|
||||
let relay_tcp_quic_transport = relay_transport
|
||||
.or_transport(tcp::async_io::Transport::new(
|
||||
tcp::Config::default().port_reuse(true),
|
||||
))
|
||||
.upgrade(upgrade::Version::V1)
|
||||
.authenticate(noise::Config::new(&local_key).unwrap())
|
||||
.multiplex(yamux::Config::default())
|
||||
.or_transport(quic::async_std::Transport::new(quic::Config::new(
|
||||
&local_key,
|
||||
)));
|
||||
|
||||
block_on(dns::async_std::Transport::system(relay_tcp_quic_transport))
|
||||
.unwrap()
|
||||
.map(|either_output, _| match either_output {
|
||||
Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
|
||||
Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
|
||||
})
|
||||
.boxed()
|
||||
};
|
||||
|
||||
#[derive(NetworkBehaviour)]
|
||||
struct Behaviour {
|
||||
relay_client: relay::client::Behaviour,
|
||||
@ -117,21 +83,27 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
dcutr: dcutr::Behaviour,
|
||||
}
|
||||
|
||||
let behaviour = Behaviour {
|
||||
relay_client: client,
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"/TODO/0.0.1".to_string(),
|
||||
local_key.public(),
|
||||
)),
|
||||
dcutr: dcutr::Behaviour::new(local_peer_id),
|
||||
};
|
||||
|
||||
let mut swarm = match ThreadPool::new() {
|
||||
Ok(tp) => SwarmBuilder::with_executor(transport, behaviour, local_peer_id, tp),
|
||||
Err(_) => SwarmBuilder::without_executor(transport, behaviour, local_peer_id),
|
||||
}
|
||||
.build();
|
||||
let mut swarm =
|
||||
libp2p::SwarmBuilder::with_existing_identity(generate_ed25519(opts.secret_key_seed))
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default().port_reuse(true).nodelay(true),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_quic()
|
||||
.with_dns()?
|
||||
.with_relay_client(noise::Config::new, yamux::Config::default)?
|
||||
.with_behaviour(|keypair, relay_behaviour| Behaviour {
|
||||
relay_client: relay_behaviour,
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"/TODO/0.0.1".to_string(),
|
||||
keypair.public(),
|
||||
)),
|
||||
dcutr: dcutr::Behaviour::new(keypair.public().to_peer_id()),
|
||||
})?
|
||||
.build();
|
||||
|
||||
swarm
|
||||
.listen_on("/ip4/0.0.0.0/udp/0/quic-v1".parse().unwrap())
|
||||
|
@ -10,7 +10,7 @@ async-std = { version = "1.12", features = ["attributes"] }
|
||||
async-trait = "0.1"
|
||||
env_logger = "0.10"
|
||||
futures = "0.3.28"
|
||||
libp2p = { path = "../../libp2p", features = [ "async-std", "dns", "kad", "mdns", "noise", "macros", "tcp", "websocket", "yamux"] }
|
||||
libp2p = { path = "../../libp2p", features = [ "async-std", "dns", "kad", "mdns", "noise", "macros", "tcp", "yamux"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -22,14 +22,13 @@
|
||||
|
||||
use async_std::io;
|
||||
use futures::{prelude::*, select};
|
||||
use libp2p::core::upgrade::Version;
|
||||
use libp2p::kad;
|
||||
use libp2p::kad::record::store::MemoryStore;
|
||||
use libp2p::kad::Mode;
|
||||
use libp2p::{
|
||||
identity, mdns, noise,
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, PeerId, Transport,
|
||||
mdns, noise,
|
||||
swarm::{NetworkBehaviour, SwarmEvent},
|
||||
tcp, yamux,
|
||||
};
|
||||
use std::error::Error;
|
||||
|
||||
@ -37,16 +36,6 @@ use std::error::Error;
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init();
|
||||
|
||||
// Create a random key for ourselves.
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
|
||||
let transport = tcp::async_io::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&local_key)?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
// We create a custom network behaviour that combines Kademlia and mDNS.
|
||||
#[derive(NetworkBehaviour)]
|
||||
struct Behaviour {
|
||||
@ -54,15 +43,26 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
mdns: mdns::async_io::Behaviour,
|
||||
}
|
||||
|
||||
// Create a swarm to manage peers and events.
|
||||
let mut swarm = {
|
||||
// Create a Kademlia behaviour.
|
||||
let store = MemoryStore::new(local_peer_id);
|
||||
let kademlia = kad::Behaviour::new(local_peer_id, store);
|
||||
let mdns = mdns::async_io::Behaviour::new(mdns::Config::default(), local_peer_id)?;
|
||||
let behaviour = Behaviour { kademlia, mdns };
|
||||
SwarmBuilder::with_async_std_executor(transport, behaviour, local_peer_id).build()
|
||||
};
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_async_std()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|key| {
|
||||
Ok(Behaviour {
|
||||
kademlia: kad::Behaviour::new(
|
||||
key.public().to_peer_id(),
|
||||
MemoryStore::new(key.public().to_peer_id()),
|
||||
),
|
||||
mdns: mdns::async_io::Behaviour::new(
|
||||
mdns::Config::default(),
|
||||
key.public().to_peer_id(),
|
||||
)?,
|
||||
})
|
||||
})?
|
||||
.build();
|
||||
|
||||
swarm.behaviour_mut().kademlia.set_mode(Some(Mode::Server));
|
||||
|
||||
|
@ -9,11 +9,10 @@ use libp2p::{
|
||||
multiaddr::Protocol,
|
||||
noise,
|
||||
request_response::{self, ProtocolSupport, RequestId, ResponseChannel},
|
||||
swarm::{NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, PeerId, Transport,
|
||||
swarm::{NetworkBehaviour, Swarm, SwarmEvent},
|
||||
tcp, yamux, PeerId,
|
||||
};
|
||||
|
||||
use libp2p::core::upgrade::Version;
|
||||
use libp2p::StreamProtocol;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{hash_map, HashMap, HashSet};
|
||||
@ -41,18 +40,18 @@ pub(crate) async fn new(
|
||||
};
|
||||
let peer_id = id_keys.public().to_peer_id();
|
||||
|
||||
let transport = tcp::async_io::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&id_keys)?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
// Build the Swarm, connecting the lower layer transport logic with the
|
||||
// higher layer network behaviour logic.
|
||||
let mut swarm = SwarmBuilder::with_async_std_executor(
|
||||
transport,
|
||||
Behaviour {
|
||||
kademlia: kad::Behaviour::new(peer_id, kad::record::store::MemoryStore::new(peer_id)),
|
||||
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(id_keys)
|
||||
.with_async_std()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|key| Behaviour {
|
||||
kademlia: kad::Behaviour::new(
|
||||
peer_id,
|
||||
kad::store::MemoryStore::new(key.public().to_peer_id()),
|
||||
),
|
||||
request_response: request_response::cbor::Behaviour::new(
|
||||
[(
|
||||
StreamProtocol::new("/file-exchange/1"),
|
||||
@ -60,10 +59,8 @@ pub(crate) async fn new(
|
||||
)],
|
||||
request_response::Config::default(),
|
||||
),
|
||||
},
|
||||
peer_id,
|
||||
)
|
||||
.build();
|
||||
})?
|
||||
.build();
|
||||
|
||||
swarm
|
||||
.behaviour_mut()
|
||||
|
@ -20,35 +20,28 @@
|
||||
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use futures::prelude::*;
|
||||
use libp2p::{
|
||||
core::{multiaddr::Multiaddr, upgrade::Version},
|
||||
identify, identity, noise,
|
||||
swarm::{SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, PeerId, Transport,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use libp2p::{core::multiaddr::Multiaddr, identify, noise, swarm::SwarmEvent, tcp, yamux};
|
||||
use std::error::Error;
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init();
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
|
||||
let transport = tcp::async_io::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&local_key).unwrap())
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
// Create a identify network behaviour.
|
||||
let behaviour = identify::Behaviour::new(identify::Config::new(
|
||||
"/ipfs/id/1.0.0".to_string(),
|
||||
local_key.public(),
|
||||
));
|
||||
|
||||
let mut swarm =
|
||||
SwarmBuilder::with_async_std_executor(transport, behaviour, local_peer_id).build();
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_async_std()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|key| {
|
||||
identify::Behaviour::new(identify::Config::new(
|
||||
"/ipfs/id/1.0.0".to_string(),
|
||||
key.public(),
|
||||
))
|
||||
})?
|
||||
.build();
|
||||
|
||||
// Tell the swarm to listen on all interfaces and a random, OS-assigned
|
||||
// port.
|
||||
|
@ -6,13 +6,13 @@ publish = false
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.12", features = ["rt-multi-thread", "macros"] }
|
||||
tokio = { version = "1.33", features = ["rt-multi-thread", "macros"] }
|
||||
async-trait = "0.1"
|
||||
clap = { version = "4.3.23", features = ["derive"] }
|
||||
env_logger = "0.10"
|
||||
futures = "0.3.28"
|
||||
anyhow = "1.0.75"
|
||||
libp2p = { path = "../../libp2p", features = [ "tokio", "dns", "kad", "noise", "tcp", "websocket", "yamux", "rsa"] }
|
||||
libp2p = { path = "../../libp2p", features = [ "tokio", "dns", "kad", "noise", "tcp", "yamux", "rsa"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -27,12 +27,7 @@ use std::time::{Duration, Instant};
|
||||
use anyhow::{bail, Result};
|
||||
use clap::Parser;
|
||||
use futures::StreamExt;
|
||||
use libp2p::{
|
||||
bytes::BufMut,
|
||||
identity, kad,
|
||||
swarm::{SwarmBuilder, SwarmEvent},
|
||||
tokio_development_transport, PeerId,
|
||||
};
|
||||
use libp2p::{bytes::BufMut, identity, kad, noise, swarm::SwarmEvent, tcp, yamux, PeerId};
|
||||
|
||||
const BOOTNODES: [&str; 4] = [
|
||||
"QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
|
||||
@ -47,28 +42,32 @@ async fn main() -> Result<()> {
|
||||
|
||||
// Create a random key for ourselves.
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
|
||||
// Set up a an encrypted DNS-enabled TCP Transport over the yamux protocol
|
||||
let transport = tokio_development_transport(local_key.clone())?;
|
||||
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(local_key.clone())
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_dns()?
|
||||
.with_behaviour(|key| {
|
||||
// Create a Kademlia behaviour.
|
||||
let mut cfg = kad::Config::default();
|
||||
cfg.set_query_timeout(Duration::from_secs(5 * 60));
|
||||
let store = kad::store::MemoryStore::new(key.public().to_peer_id());
|
||||
kad::Behaviour::with_config(key.public().to_peer_id(), store, cfg)
|
||||
})?
|
||||
.build();
|
||||
|
||||
// Create a swarm to manage peers and events.
|
||||
let mut swarm = {
|
||||
// Create a Kademlia behaviour.
|
||||
let mut cfg = kad::Config::default();
|
||||
cfg.set_query_timeout(Duration::from_secs(5 * 60));
|
||||
let store = kad::store::MemoryStore::new(local_peer_id);
|
||||
let mut behaviour = kad::Behaviour::with_config(local_peer_id, store, cfg);
|
||||
|
||||
// Add the bootnodes to the local routing table. `libp2p-dns` built
|
||||
// into the `transport` resolves the `dnsaddr` when Kademlia tries
|
||||
// to dial these nodes.
|
||||
for peer in &BOOTNODES {
|
||||
behaviour.add_address(&peer.parse()?, "/dnsaddr/bootstrap.libp2p.io".parse()?);
|
||||
}
|
||||
|
||||
SwarmBuilder::with_tokio_executor(transport, behaviour, local_peer_id).build()
|
||||
};
|
||||
// Add the bootnodes to the local routing table. `libp2p-dns` built
|
||||
// into the `transport` resolves the `dnsaddr` when Kademlia tries
|
||||
// to dial these nodes.
|
||||
for peer in &BOOTNODES {
|
||||
swarm
|
||||
.behaviour_mut()
|
||||
.add_address(&peer.parse()?, "/dnsaddr/bootstrap.libp2p.io".parse()?);
|
||||
}
|
||||
|
||||
let cli_opt = Opt::parse();
|
||||
|
||||
@ -83,11 +82,11 @@ async fn main() -> Result<()> {
|
||||
|
||||
let mut pk_record_key = vec![];
|
||||
pk_record_key.put_slice("/pk/".as_bytes());
|
||||
pk_record_key.put_slice(local_peer_id.to_bytes().as_slice());
|
||||
pk_record_key.put_slice(swarm.local_peer_id().to_bytes().as_slice());
|
||||
|
||||
let mut pk_record =
|
||||
kad::Record::new(pk_record_key, local_key.public().encode_protobuf());
|
||||
pk_record.publisher = Some(local_peer_id);
|
||||
pk_record.publisher = Some(*swarm.local_peer_id());
|
||||
pk_record.expires = Some(Instant::now().add(Duration::from_secs(60)));
|
||||
|
||||
swarm
|
||||
|
@ -6,7 +6,7 @@ publish = false
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
tokio = { version = "1.32", features = ["rt-multi-thread", "macros", "io-std"] }
|
||||
tokio = { version = "1.33", features = ["rt-multi-thread", "macros", "io-std"] }
|
||||
async-trait = "0.1"
|
||||
either = "1.9"
|
||||
env_logger = "0.10"
|
||||
|
@ -23,40 +23,17 @@
|
||||
use either::Either;
|
||||
use futures::prelude::*;
|
||||
use libp2p::{
|
||||
core::{muxing::StreamMuxerBox, transport, transport::upgrade::Version},
|
||||
gossipsub, identify, identity,
|
||||
core::transport::upgrade::Version,
|
||||
gossipsub, identify,
|
||||
multiaddr::Protocol,
|
||||
noise, ping,
|
||||
pnet::{PnetConfig, PreSharedKey},
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, Multiaddr, PeerId, Transport,
|
||||
swarm::{NetworkBehaviour, SwarmEvent},
|
||||
tcp, yamux, Multiaddr, Transport,
|
||||
};
|
||||
use std::{env, error::Error, fs, path::Path, str::FromStr, time::Duration};
|
||||
use std::{env, error::Error, fs, path::Path, str::FromStr};
|
||||
use tokio::{io, io::AsyncBufReadExt, select};
|
||||
|
||||
/// Builds the transport that serves as a common ground for all connections.
|
||||
pub fn build_transport(
|
||||
key_pair: identity::Keypair,
|
||||
psk: Option<PreSharedKey>,
|
||||
) -> transport::Boxed<(PeerId, StreamMuxerBox)> {
|
||||
let noise_config = noise::Config::new(&key_pair).unwrap();
|
||||
let yamux_config = yamux::Config::default();
|
||||
|
||||
let base_transport = tcp::tokio::Transport::new(tcp::Config::default().nodelay(true));
|
||||
let maybe_encrypted = match psk {
|
||||
Some(psk) => Either::Left(
|
||||
base_transport.and_then(move |socket, _| PnetConfig::new(psk).handshake(socket)),
|
||||
),
|
||||
None => Either::Right(base_transport),
|
||||
};
|
||||
maybe_encrypted
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise_config)
|
||||
.multiplex(yamux_config)
|
||||
.timeout(Duration::from_secs(20))
|
||||
.boxed()
|
||||
}
|
||||
|
||||
/// Get the current ipfs repo path, either from the IPFS_PATH environment variable or
|
||||
/// from the default $HOME/.ipfs
|
||||
fn get_ipfs_path() -> Box<Path> {
|
||||
@ -118,76 +95,67 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
.map(|text| PreSharedKey::from_str(&text))
|
||||
.transpose()?;
|
||||
|
||||
// Create a random PeerId
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
println!("using random peer id: {local_peer_id:?}");
|
||||
if let Some(psk) = psk {
|
||||
println!("using swarm key with fingerprint: {}", psk.fingerprint());
|
||||
}
|
||||
|
||||
// Set up a an encrypted DNS-enabled TCP Transport over and Yamux protocol
|
||||
let transport = build_transport(local_key.clone(), psk);
|
||||
|
||||
// Create a Gosspipsub topic
|
||||
let gossipsub_topic = gossipsub::IdentTopic::new("chat");
|
||||
|
||||
// We create a custom network behaviour that combines gossipsub, ping and identify.
|
||||
#[derive(NetworkBehaviour)]
|
||||
#[behaviour(to_swarm = "MyBehaviourEvent")]
|
||||
struct MyBehaviour {
|
||||
gossipsub: gossipsub::Behaviour,
|
||||
identify: identify::Behaviour,
|
||||
ping: ping::Behaviour,
|
||||
}
|
||||
|
||||
enum MyBehaviourEvent {
|
||||
Gossipsub(gossipsub::Event),
|
||||
Identify(identify::Event),
|
||||
Ping(ping::Event),
|
||||
}
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_other_transport(|key| {
|
||||
let noise_config = noise::Config::new(key).unwrap();
|
||||
let yamux_config = yamux::Config::default();
|
||||
|
||||
impl From<gossipsub::Event> for MyBehaviourEvent {
|
||||
fn from(event: gossipsub::Event) -> Self {
|
||||
MyBehaviourEvent::Gossipsub(event)
|
||||
}
|
||||
}
|
||||
let base_transport = tcp::tokio::Transport::new(tcp::Config::default().nodelay(true));
|
||||
let maybe_encrypted = match psk {
|
||||
Some(psk) => Either::Left(
|
||||
base_transport
|
||||
.and_then(move |socket, _| PnetConfig::new(psk).handshake(socket)),
|
||||
),
|
||||
None => Either::Right(base_transport),
|
||||
};
|
||||
maybe_encrypted
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise_config)
|
||||
.multiplex(yamux_config)
|
||||
})?
|
||||
.with_dns()?
|
||||
.with_behaviour(|key| {
|
||||
let gossipsub_config = gossipsub::ConfigBuilder::default()
|
||||
.max_transmit_size(262144)
|
||||
.build()
|
||||
.map_err(|msg| io::Error::new(io::ErrorKind::Other, msg))?; // Temporary hack because `build` does not return a proper `std::error::Error`.
|
||||
Ok(MyBehaviour {
|
||||
gossipsub: gossipsub::Behaviour::new(
|
||||
gossipsub::MessageAuthenticity::Signed(key.clone()),
|
||||
gossipsub_config,
|
||||
)
|
||||
.expect("Valid configuration"),
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"/ipfs/0.1.0".into(),
|
||||
key.public(),
|
||||
)),
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
})
|
||||
})?
|
||||
.build();
|
||||
|
||||
impl From<identify::Event> for MyBehaviourEvent {
|
||||
fn from(event: identify::Event) -> Self {
|
||||
MyBehaviourEvent::Identify(event)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ping::Event> for MyBehaviourEvent {
|
||||
fn from(event: ping::Event) -> Self {
|
||||
MyBehaviourEvent::Ping(event)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a Swarm to manage peers and events
|
||||
let mut swarm = {
|
||||
let gossipsub_config = gossipsub::ConfigBuilder::default()
|
||||
.max_transmit_size(262144)
|
||||
.build()
|
||||
.expect("valid config");
|
||||
let mut behaviour = MyBehaviour {
|
||||
gossipsub: gossipsub::Behaviour::new(
|
||||
gossipsub::MessageAuthenticity::Signed(local_key.clone()),
|
||||
gossipsub_config,
|
||||
)
|
||||
.expect("Valid configuration"),
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"/ipfs/0.1.0".into(),
|
||||
local_key.public(),
|
||||
)),
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
};
|
||||
|
||||
println!("Subscribing to {gossipsub_topic:?}");
|
||||
behaviour.gossipsub.subscribe(&gossipsub_topic).unwrap();
|
||||
SwarmBuilder::with_tokio_executor(transport, behaviour, local_peer_id).build()
|
||||
};
|
||||
println!("Subscribing to {gossipsub_topic:?}");
|
||||
swarm
|
||||
.behaviour_mut()
|
||||
.gossipsub
|
||||
.subscribe(&gossipsub_topic)
|
||||
.unwrap();
|
||||
|
||||
// Reach out to other nodes if specified
|
||||
for to_dial in std::env::args().skip(1) {
|
||||
|
@ -21,12 +21,10 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use env_logger::Env;
|
||||
use futures::executor::block_on;
|
||||
use futures::stream::StreamExt;
|
||||
use libp2p::core::{upgrade::Version, Multiaddr, Transport};
|
||||
use libp2p::identity::PeerId;
|
||||
use futures::{executor::block_on, StreamExt};
|
||||
use libp2p::core::Multiaddr;
|
||||
use libp2p::metrics::{Metrics, Recorder};
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent};
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmEvent};
|
||||
use libp2p::{identify, identity, noise, ping, tcp, yamux};
|
||||
use log::info;
|
||||
use prometheus_client::registry::Registry;
|
||||
@ -39,21 +37,16 @@ mod http_service;
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
|
||||
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
let local_pub_key = local_key.public();
|
||||
|
||||
let mut swarm = SwarmBuilder::without_executor(
|
||||
tcp::async_io::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&local_key)?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed(),
|
||||
Behaviour::new(local_pub_key),
|
||||
local_peer_id,
|
||||
)
|
||||
.idle_connection_timeout(Duration::from_secs(60))
|
||||
.build();
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_async_std()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|key| Behaviour::new(key.public()))?
|
||||
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(u64::MAX)))
|
||||
.build();
|
||||
|
||||
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
|
||||
|
||||
|
@ -9,7 +9,7 @@ license = "MIT"
|
||||
env_logger = "0.10.0"
|
||||
futures = "0.3.28"
|
||||
libp2p = { path = "../../libp2p", features = ["noise", "ping", "tcp", "tokio", "yamux"] }
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
tokio = { version = "1.33.0", features = ["full"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -21,31 +21,21 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use futures::prelude::*;
|
||||
use libp2p::core::upgrade::Version;
|
||||
use libp2p::{
|
||||
identity, noise, ping,
|
||||
swarm::{SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, Multiaddr, PeerId, Transport,
|
||||
};
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
use libp2p::{noise, ping, swarm::SwarmEvent, tcp, yamux, Multiaddr};
|
||||
use std::{error::Error, time::Duration};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init();
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
|
||||
let transport = tcp::tokio::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&local_key)?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
let mut swarm =
|
||||
SwarmBuilder::with_tokio_executor(transport, ping::Behaviour::default(), local_peer_id)
|
||||
.idle_connection_timeout(Duration::from_secs(60)) // For illustrative purposes, keep idle connections alive for a minute so we can observe a few pings.
|
||||
.build();
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|_| ping::Behaviour::default())?
|
||||
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(u64::MAX)))
|
||||
.build();
|
||||
|
||||
// Tell the swarm to listen on all interfaces and a random, OS-assigned
|
||||
// port.
|
||||
|
@ -22,18 +22,14 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use clap::Parser;
|
||||
use futures::executor::block_on;
|
||||
use futures::stream::StreamExt;
|
||||
use futures::{executor::block_on, future::Either};
|
||||
use libp2p::{
|
||||
core::multiaddr::Protocol,
|
||||
core::muxing::StreamMuxerBox,
|
||||
core::upgrade,
|
||||
core::{Multiaddr, Transport},
|
||||
identify, identity,
|
||||
identity::PeerId,
|
||||
noise, ping, quic, relay,
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
tcp,
|
||||
core::Multiaddr,
|
||||
identify, identity, noise, ping, relay,
|
||||
swarm::{NetworkBehaviour, SwarmEvent},
|
||||
tcp, yamux,
|
||||
};
|
||||
use std::error::Error;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
@ -42,41 +38,27 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init();
|
||||
|
||||
let opt = Opt::parse();
|
||||
println!("opt: {opt:?}");
|
||||
|
||||
// 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());
|
||||
|
||||
let tcp_transport = tcp::async_io::Transport::default();
|
||||
|
||||
let tcp_transport = tcp_transport
|
||||
.upgrade(upgrade::Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key).expect("Signing libp2p-noise static DH keypair failed."),
|
||||
)
|
||||
.multiplex(libp2p::yamux::Config::default());
|
||||
|
||||
let quic_transport = quic::async_std::Transport::new(quic::Config::new(&local_key));
|
||||
|
||||
let transport = quic_transport
|
||||
.or_transport(tcp_transport)
|
||||
.map(|either_output, _| match either_output {
|
||||
Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
|
||||
Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
|
||||
})
|
||||
.boxed();
|
||||
|
||||
let behaviour = Behaviour {
|
||||
relay: relay::Behaviour::new(local_peer_id, Default::default()),
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"/TODO/0.0.1".to_string(),
|
||||
local_key.public(),
|
||||
)),
|
||||
};
|
||||
|
||||
let mut swarm = SwarmBuilder::without_executor(transport, behaviour, local_peer_id).build();
|
||||
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(local_key)
|
||||
.with_async_std()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_quic()
|
||||
.with_behaviour(|key| Behaviour {
|
||||
relay: relay::Behaviour::new(key.public().to_peer_id(), Default::default()),
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"/TODO/0.0.1".to_string(),
|
||||
key.public(),
|
||||
)),
|
||||
})?
|
||||
.build();
|
||||
|
||||
// Listen on all interfaces
|
||||
let listen_addr_tcp = Multiaddr::empty()
|
||||
|
@ -12,7 +12,7 @@ env_logger = "0.10.0"
|
||||
futures = "0.3.28"
|
||||
libp2p = { path = "../../libp2p", features = [ "async-std", "identify", "macros", "noise", "ping", "rendezvous", "tcp", "tokio", "yamux"] }
|
||||
log = "0.4"
|
||||
tokio = { version = "1.32", features = ["rt-multi-thread", "macros", "time"] }
|
||||
tokio = { version = "1.33", features = ["rt-multi-thread", "macros", "time"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -20,41 +20,38 @@
|
||||
|
||||
use futures::StreamExt;
|
||||
use libp2p::{
|
||||
core::transport::upgrade::Version,
|
||||
identity,
|
||||
multiaddr::Protocol,
|
||||
noise, ping, rendezvous,
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, Multiaddr, PeerId, Transport,
|
||||
swarm::{NetworkBehaviour, SwarmEvent},
|
||||
tcp, yamux, Multiaddr,
|
||||
};
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
|
||||
const NAMESPACE: &str = "rendezvous";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init();
|
||||
|
||||
let key_pair = identity::Keypair::generate_ed25519();
|
||||
let rendezvous_point_address = "/ip4/127.0.0.1/tcp/62649".parse::<Multiaddr>().unwrap();
|
||||
let rendezvous_point = "12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let mut swarm = SwarmBuilder::with_tokio_executor(
|
||||
tcp::tokio::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&key_pair).unwrap())
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed(),
|
||||
MyBehaviour {
|
||||
rendezvous: rendezvous::client::Behaviour::new(key_pair.clone()),
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|key| MyBehaviour {
|
||||
rendezvous: rendezvous::client::Behaviour::new(key.clone()),
|
||||
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
|
||||
},
|
||||
PeerId::from(key_pair.public()),
|
||||
)
|
||||
.idle_connection_timeout(Duration::from_secs(5))
|
||||
.build();
|
||||
})?
|
||||
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build();
|
||||
|
||||
swarm.dial(rendezvous_point_address.clone()).unwrap();
|
||||
|
||||
|
@ -20,10 +20,9 @@
|
||||
|
||||
use futures::StreamExt;
|
||||
use libp2p::{
|
||||
core::transport::upgrade::Version,
|
||||
identify, identity, noise, ping, rendezvous,
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, Multiaddr, PeerId, Transport,
|
||||
identify, noise, ping, rendezvous,
|
||||
swarm::{NetworkBehaviour, SwarmEvent},
|
||||
tcp, yamux, Multiaddr,
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
@ -31,30 +30,30 @@ use std::time::Duration;
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let key_pair = identity::Keypair::generate_ed25519();
|
||||
let rendezvous_point_address = "/ip4/127.0.0.1/tcp/62649".parse::<Multiaddr>().unwrap();
|
||||
let rendezvous_point = "12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let mut swarm = SwarmBuilder::with_tokio_executor(
|
||||
tcp::tokio::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&key_pair).unwrap())
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed(),
|
||||
MyBehaviour {
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_behaviour(|key| MyBehaviour {
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"rendezvous-example/1.0.0".to_string(),
|
||||
key_pair.public(),
|
||||
key.public(),
|
||||
)),
|
||||
rendezvous: rendezvous::client::Behaviour::new(key_pair.clone()),
|
||||
rendezvous: rendezvous::client::Behaviour::new(key.clone()),
|
||||
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
|
||||
},
|
||||
PeerId::from(key_pair.public()),
|
||||
)
|
||||
.idle_connection_timeout(Duration::from_secs(5))
|
||||
.build();
|
||||
})
|
||||
.unwrap()
|
||||
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build();
|
||||
|
||||
let _ = swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse().unwrap());
|
||||
|
||||
|
@ -20,10 +20,9 @@
|
||||
|
||||
use futures::StreamExt;
|
||||
use libp2p::{
|
||||
core::transport::upgrade::Version,
|
||||
identity, noise, ping, rendezvous,
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, Multiaddr, PeerId, Transport,
|
||||
noise, ping, rendezvous,
|
||||
swarm::{NetworkBehaviour, SwarmEvent},
|
||||
tcp, yamux, Multiaddr,
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
@ -31,26 +30,26 @@ use std::time::Duration;
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
|
||||
let key_pair = identity::Keypair::generate_ed25519();
|
||||
let rendezvous_point_address = "/ip4/127.0.0.1/tcp/62649".parse::<Multiaddr>().unwrap();
|
||||
let rendezvous_point = "12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN"
|
||||
.parse()
|
||||
.unwrap();
|
||||
|
||||
let mut swarm = SwarmBuilder::with_tokio_executor(
|
||||
tcp::tokio::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&key_pair).unwrap())
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed(),
|
||||
MyBehaviour {
|
||||
rendezvous: rendezvous::client::Behaviour::new(key_pair.clone()),
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_behaviour(|key| MyBehaviour {
|
||||
rendezvous: rendezvous::client::Behaviour::new(key.clone()),
|
||||
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
|
||||
},
|
||||
PeerId::from(key_pair.public()),
|
||||
)
|
||||
.idle_connection_timeout(Duration::from_secs(5))
|
||||
.build();
|
||||
})
|
||||
.unwrap()
|
||||
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build();
|
||||
|
||||
// In production the external address should be the publicly facing IP address of the rendezvous point.
|
||||
// This address is recorded in the registration entry by the rendezvous point.
|
||||
|
@ -22,37 +22,34 @@
|
||||
|
||||
use futures::StreamExt;
|
||||
use libp2p::{
|
||||
core::transport::upgrade::Version,
|
||||
identify, identity, noise, ping, rendezvous,
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
tcp, yamux, PeerId, Transport,
|
||||
identify, noise, ping, rendezvous,
|
||||
swarm::{NetworkBehaviour, SwarmEvent},
|
||||
tcp, yamux,
|
||||
};
|
||||
use std::error::Error;
|
||||
use std::time::Duration;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
env_logger::init();
|
||||
|
||||
let key_pair = identity::Keypair::generate_ed25519();
|
||||
|
||||
let mut swarm = SwarmBuilder::with_tokio_executor(
|
||||
tcp::tokio::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&key_pair).unwrap())
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed(),
|
||||
MyBehaviour {
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|key| MyBehaviour {
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"rendezvous-example/1.0.0".to_string(),
|
||||
key_pair.public(),
|
||||
key.public(),
|
||||
)),
|
||||
rendezvous: rendezvous::server::Behaviour::new(rendezvous::server::Config::default()),
|
||||
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
|
||||
},
|
||||
PeerId::from(key_pair.public()),
|
||||
)
|
||||
.idle_connection_timeout(Duration::from_secs(5))
|
||||
.build();
|
||||
})?
|
||||
.with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build();
|
||||
|
||||
let _ = swarm.listen_on("/ip4/0.0.0.0/tcp/62649".parse().unwrap());
|
||||
|
||||
@ -90,6 +87,8 @@ async fn main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(NetworkBehaviour)]
|
||||
|
@ -8,7 +8,7 @@ license = "MIT"
|
||||
[dependencies]
|
||||
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
|
||||
futures = "0.3.28"
|
||||
libp2p = { path = "../../libp2p", features = ["tokio", "dns", "macros", "noise", "ping", "tcp", "websocket", "yamux", "upnp"] }
|
||||
libp2p = { path = "../../libp2p", features = ["tokio", "dns", "macros", "noise", "ping", "tcp", "yamux", "upnp"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -21,32 +21,20 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use futures::prelude::*;
|
||||
use libp2p::core::upgrade::Version;
|
||||
use libp2p::{
|
||||
identity, noise,
|
||||
swarm::{SwarmBuilder, SwarmEvent},
|
||||
tcp, upnp, yamux, Multiaddr, PeerId, Transport,
|
||||
};
|
||||
use libp2p::{noise, swarm::SwarmEvent, upnp, yamux, Multiaddr};
|
||||
use std::error::Error;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
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 = tcp::tokio::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(noise::Config::new(&local_key)?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
let mut swarm = SwarmBuilder::with_tokio_executor(
|
||||
transport,
|
||||
upnp::tokio::Behaviour::default(),
|
||||
local_peer_id,
|
||||
)
|
||||
.build();
|
||||
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(|_| upnp::tokio::Behaviour::default())?
|
||||
.build();
|
||||
|
||||
// Tell the swarm to listen on all interfaces and a random, OS-assigned
|
||||
// port.
|
||||
|
@ -20,8 +20,10 @@ rand = "0.8.5"
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
axum = "0.6"
|
||||
libp2p = { path = "../libp2p", features = [ "ping", "noise", "tls", "rsa", "macros", "websocket", "tokio", "yamux", "tcp", "dns", "identify", "quic"] }
|
||||
libp2p-webrtc = { workspace = true, features = ["tokio"] }
|
||||
libp2p-mplex = { path = "../muxers/mplex" }
|
||||
libp2p-noise = { workspace = true }
|
||||
libp2p-tls = { workspace = true }
|
||||
libp2p-webrtc = { workspace = true, features = ["tokio"] }
|
||||
mime_guess = "2.0"
|
||||
redis = { version = "0.23.3", default-features = false, features = [
|
||||
"tokio-comp",
|
||||
@ -29,7 +31,7 @@ redis = { version = "0.23.3", default-features = false, features = [
|
||||
rust-embed = "8.0"
|
||||
serde_json = "1"
|
||||
thirtyfour = "=0.32.0-rc.8" # https://github.com/stevepryde/thirtyfour/issues/169
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
tokio = { version = "1.33.0", features = ["full"] }
|
||||
tower-http = { version = "0.4", features = ["cors", "fs", "trace"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
@ -1,16 +1,10 @@
|
||||
use libp2p::core::muxing::StreamMuxerBox;
|
||||
use libp2p::core::transport::Boxed;
|
||||
use libp2p::PeerId;
|
||||
|
||||
// Native re-exports
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) use native::{build_transport, init_logger, sleep, swarm_builder, Instant, RedisClient};
|
||||
pub(crate) use native::{build_swarm, init_logger, sleep, Instant, RedisClient};
|
||||
|
||||
// Wasm re-exports
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub(crate) use wasm::{build_transport, init_logger, sleep, swarm_builder, Instant, RedisClient};
|
||||
|
||||
type BoxedTransport = Boxed<(PeerId, StreamMuxerBox)>;
|
||||
pub(crate) use wasm::{build_swarm, init_logger, sleep, Instant, RedisClient};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) mod native {
|
||||
@ -20,20 +14,15 @@ pub(crate) mod native {
|
||||
use env_logger::{Env, Target};
|
||||
use futures::future::BoxFuture;
|
||||
use futures::FutureExt;
|
||||
use libp2p::core::muxing::StreamMuxerBox;
|
||||
use libp2p::core::upgrade::Version;
|
||||
use libp2p::identity::Keypair;
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmBuilder};
|
||||
use libp2p::websocket::WsConfig;
|
||||
use libp2p::{noise, quic, tcp, tls, yamux, PeerId, Transport as _};
|
||||
use libp2p::swarm::{NetworkBehaviour, Swarm};
|
||||
use libp2p::{noise, tcp, tls, yamux};
|
||||
use libp2p_mplex as mplex;
|
||||
use libp2p_webrtc as webrtc;
|
||||
use redis::AsyncCommands;
|
||||
|
||||
use crate::{Muxer, SecProtocol, Transport};
|
||||
|
||||
use super::BoxedTransport;
|
||||
|
||||
pub(crate) type Instant = std::time::Instant;
|
||||
|
||||
pub(crate) fn init_logger() {
|
||||
@ -46,128 +35,132 @@ pub(crate) mod native {
|
||||
tokio::time::sleep(duration).boxed()
|
||||
}
|
||||
|
||||
pub(crate) fn build_transport(
|
||||
local_key: Keypair,
|
||||
pub(crate) async fn build_swarm<B: NetworkBehaviour>(
|
||||
ip: &str,
|
||||
transport: Transport,
|
||||
sec_protocol: Option<SecProtocol>,
|
||||
muxer: Option<Muxer>,
|
||||
) -> Result<(BoxedTransport, String)> {
|
||||
let (transport, addr) = match (transport, sec_protocol, muxer) {
|
||||
(Transport::QuicV1, _, _) => (
|
||||
quic::tokio::Transport::new(quic::Config::new(&local_key))
|
||||
.map(|(p, c), _| (p, StreamMuxerBox::new(c)))
|
||||
.boxed(),
|
||||
behaviour_constructor: impl FnOnce(&Keypair) -> B,
|
||||
) -> Result<(Swarm<B>, String)> {
|
||||
let (swarm, addr) = match (transport, sec_protocol, muxer) {
|
||||
(Transport::QuicV1, None, None) => (
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_quic()
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/udp/0/quic-v1"),
|
||||
),
|
||||
(Transport::Tcp, Some(SecProtocol::Tls), Some(Muxer::Mplex)) => (
|
||||
tcp::tokio::Transport::new(tcp::Config::new())
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(tls::Config::new(&local_key).context("failed to initialise tls")?)
|
||||
.multiplex(mplex::MplexConfig::new())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
tls::Config::new,
|
||||
mplex::MplexConfig::default,
|
||||
)?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0"),
|
||||
),
|
||||
(Transport::Tcp, Some(SecProtocol::Tls), Some(Muxer::Yamux)) => (
|
||||
tcp::tokio::Transport::new(tcp::Config::new())
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(tls::Config::new(&local_key).context("failed to initialise tls")?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
tls::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0"),
|
||||
),
|
||||
(Transport::Tcp, Some(SecProtocol::Noise), Some(Muxer::Mplex)) => (
|
||||
tcp::tokio::Transport::new(tcp::Config::new())
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key).context("failed to intialise noise")?,
|
||||
)
|
||||
.multiplex(mplex::MplexConfig::new())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
mplex::MplexConfig::default,
|
||||
)?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0"),
|
||||
),
|
||||
(Transport::Tcp, Some(SecProtocol::Noise), Some(Muxer::Yamux)) => (
|
||||
tcp::tokio::Transport::new(tcp::Config::new())
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key).context("failed to intialise noise")?,
|
||||
)
|
||||
.multiplex(yamux::Config::default())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default(),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0"),
|
||||
),
|
||||
(Transport::Ws, Some(SecProtocol::Tls), Some(Muxer::Mplex)) => (
|
||||
WsConfig::new(tcp::tokio::Transport::new(tcp::Config::new()))
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(tls::Config::new(&local_key).context("failed to initialise tls")?)
|
||||
.multiplex(mplex::MplexConfig::new())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_websocket(tls::Config::new, mplex::MplexConfig::default)
|
||||
.await?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0/ws"),
|
||||
),
|
||||
(Transport::Ws, Some(SecProtocol::Tls), Some(Muxer::Yamux)) => (
|
||||
WsConfig::new(tcp::tokio::Transport::new(tcp::Config::new()))
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
tls::Config::new(&local_key).context("failed to intialise noise")?,
|
||||
)
|
||||
.multiplex(yamux::Config::default())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_websocket(tls::Config::new, yamux::Config::default)
|
||||
.await?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0/ws"),
|
||||
),
|
||||
(Transport::Ws, Some(SecProtocol::Noise), Some(Muxer::Mplex)) => (
|
||||
WsConfig::new(tcp::tokio::Transport::new(tcp::Config::new()))
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key).context("failed to initialise tls")?,
|
||||
)
|
||||
.multiplex(mplex::MplexConfig::new())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_websocket(noise::Config::new, mplex::MplexConfig::default)
|
||||
.await?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0/ws"),
|
||||
),
|
||||
(Transport::Ws, Some(SecProtocol::Noise), Some(Muxer::Yamux)) => (
|
||||
WsConfig::new(tcp::tokio::Transport::new(tcp::Config::new()))
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key).context("failed to intialise noise")?,
|
||||
)
|
||||
.multiplex(yamux::Config::default())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_websocket(noise::Config::new, yamux::Config::default)
|
||||
.await?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0/ws"),
|
||||
),
|
||||
(Transport::WebRtcDirect, _, _) => (
|
||||
webrtc::tokio::Transport::new(
|
||||
local_key,
|
||||
webrtc::tokio::Certificate::generate(&mut rand::thread_rng())?,
|
||||
)
|
||||
.map(|(peer_id, conn), _| (peer_id, StreamMuxerBox::new(conn)))
|
||||
.boxed(),
|
||||
(Transport::WebRtcDirect, None, None) => (
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_other_transport(|key| {
|
||||
Ok(webrtc::tokio::Transport::new(
|
||||
key.clone(),
|
||||
webrtc::tokio::Certificate::generate(&mut rand::thread_rng())?,
|
||||
))
|
||||
})?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/udp/0/webrtc-direct"),
|
||||
),
|
||||
(Transport::Webtransport, _, _) => bail!("Webtransport can only be used with wasm"),
|
||||
(Transport::Tcp | Transport::Ws, None, _) => {
|
||||
bail!("Missing security protocol for {transport:?}")
|
||||
}
|
||||
(Transport::Tcp | Transport::Ws, _, None) => {
|
||||
bail!("Missing muxer protocol for {transport:?}")
|
||||
}
|
||||
(t, s, m) => bail!("Unsupported combination: {t:?} {s:?} {m:?}"),
|
||||
};
|
||||
Ok((transport, addr))
|
||||
}
|
||||
|
||||
pub(crate) fn swarm_builder<TBehaviour: NetworkBehaviour>(
|
||||
transport: BoxedTransport,
|
||||
behaviour: TBehaviour,
|
||||
peer_id: PeerId,
|
||||
) -> SwarmBuilder<TBehaviour> {
|
||||
SwarmBuilder::with_tokio_executor(transport, behaviour, peer_id)
|
||||
Ok((swarm, addr))
|
||||
}
|
||||
|
||||
pub(crate) struct RedisClient(redis::Client);
|
||||
@ -198,16 +191,14 @@ pub(crate) mod wasm {
|
||||
use futures::future::{BoxFuture, FutureExt};
|
||||
use libp2p::core::upgrade::Version;
|
||||
use libp2p::identity::Keypair;
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmBuilder};
|
||||
use libp2p::{noise, yamux, PeerId, Transport as _};
|
||||
use libp2p::swarm::{NetworkBehaviour, Swarm};
|
||||
use libp2p::{noise, websocket_websys, webtransport_websys, yamux, Transport as _};
|
||||
use libp2p_mplex as mplex;
|
||||
use libp2p_webrtc_websys as webrtc;
|
||||
use libp2p_webrtc_websys as webrtc_websys;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{BlpopRequest, Muxer, SecProtocol, Transport};
|
||||
|
||||
use super::BoxedTransport;
|
||||
|
||||
pub(crate) type Instant = instant::Instant;
|
||||
|
||||
pub(crate) fn init_logger() {
|
||||
@ -219,70 +210,76 @@ pub(crate) mod wasm {
|
||||
futures_timer::Delay::new(duration).boxed()
|
||||
}
|
||||
|
||||
pub(crate) fn build_transport(
|
||||
local_key: Keypair,
|
||||
pub(crate) async fn build_swarm<B: NetworkBehaviour>(
|
||||
ip: &str,
|
||||
transport: Transport,
|
||||
sec_protocol: Option<SecProtocol>,
|
||||
muxer: Option<Muxer>,
|
||||
) -> Result<(BoxedTransport, String)> {
|
||||
behaviour_constructor: impl FnOnce(&Keypair) -> B,
|
||||
) -> Result<(Swarm<B>, String)> {
|
||||
Ok(match (transport, sec_protocol, muxer) {
|
||||
(Transport::Webtransport, _, _) => (
|
||||
libp2p::webtransport_websys::Transport::new(
|
||||
libp2p::webtransport_websys::Config::new(&local_key),
|
||||
)
|
||||
.boxed(),
|
||||
(Transport::Webtransport, None, None) => (
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_wasm_bindgen()
|
||||
.with_other_transport(|local_key| {
|
||||
webtransport_websys::Transport::new(webtransport_websys::Config::new(
|
||||
&local_key,
|
||||
))
|
||||
})?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/udp/0/quic/webtransport"),
|
||||
),
|
||||
(Transport::Ws, Some(SecProtocol::Noise), Some(Muxer::Mplex)) => (
|
||||
libp2p::websocket_websys::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key).context("failed to initialise noise")?,
|
||||
)
|
||||
.multiplex(mplex::MplexConfig::new())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_wasm_bindgen()
|
||||
.with_other_transport(|local_key| {
|
||||
Ok(websocket_websys::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key)
|
||||
.context("failed to initialise noise")?,
|
||||
)
|
||||
.multiplex(mplex::MplexConfig::new()))
|
||||
})?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0/wss"),
|
||||
),
|
||||
(Transport::Ws, Some(SecProtocol::Noise), Some(Muxer::Yamux)) => (
|
||||
libp2p::websocket_websys::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key).context("failed to initialise noise")?,
|
||||
)
|
||||
.multiplex(yamux::Config::default())
|
||||
.timeout(Duration::from_secs(5))
|
||||
.boxed(),
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_wasm_bindgen()
|
||||
.with_other_transport(|local_key| {
|
||||
Ok(websocket_websys::Transport::default()
|
||||
.upgrade(Version::V1Lazy)
|
||||
.authenticate(
|
||||
noise::Config::new(&local_key)
|
||||
.context("failed to initialise noise")?,
|
||||
)
|
||||
.multiplex(yamux::Config::default()))
|
||||
})?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/tcp/0/wss"),
|
||||
),
|
||||
(Transport::Ws, None, _) => {
|
||||
bail!("Missing security protocol for WS")
|
||||
}
|
||||
(Transport::Ws, Some(SecProtocol::Tls), _) => {
|
||||
bail!("TLS not supported in WASM")
|
||||
}
|
||||
(Transport::Ws, _, None) => {
|
||||
bail!("Missing muxer protocol for WS")
|
||||
}
|
||||
(Transport::WebRtcDirect, _, _) => (
|
||||
webrtc::Transport::new(webrtc::Config::new(&local_key)).boxed(),
|
||||
(Transport::WebRtcDirect, None, None) => (
|
||||
libp2p::SwarmBuilder::with_new_identity()
|
||||
.with_wasm_bindgen()
|
||||
.with_other_transport(|local_key| {
|
||||
webrtc_websys::Transport::new(webrtc_websys::Config::new(&local_key))
|
||||
})?
|
||||
.with_behaviour(behaviour_constructor)?
|
||||
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
|
||||
.build(),
|
||||
format!("/ip4/{ip}/udp/0/webrtc-direct"),
|
||||
),
|
||||
(Transport::QuicV1 | Transport::Tcp, _, _) => {
|
||||
bail!("{transport:?} is not supported in WASM")
|
||||
}
|
||||
(t, s, m) => bail!("Unsupported combination: {t:?} {s:?} {m:?}"),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn swarm_builder<TBehaviour: NetworkBehaviour>(
|
||||
transport: BoxedTransport,
|
||||
behaviour: TBehaviour,
|
||||
peer_id: PeerId,
|
||||
) -> SwarmBuilder<TBehaviour> {
|
||||
SwarmBuilder::with_wasm_executor(transport, behaviour, peer_id)
|
||||
}
|
||||
|
||||
pub(crate) struct RedisClient(String);
|
||||
|
||||
impl RedisClient {
|
||||
|
@ -3,14 +3,15 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use libp2p::identity::Keypair;
|
||||
use libp2p::swarm::SwarmEvent;
|
||||
use libp2p::{identify, identity, ping, swarm::NetworkBehaviour, Multiaddr, PeerId};
|
||||
use libp2p::{identify, ping, swarm::NetworkBehaviour, Multiaddr};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
mod arch;
|
||||
|
||||
use arch::{build_transport, init_logger, swarm_builder, Instant, RedisClient};
|
||||
use arch::{build_swarm, init_logger, Instant, RedisClient};
|
||||
|
||||
pub async fn run_test(
|
||||
transport: &str,
|
||||
@ -40,37 +41,23 @@ pub async fn run_test(
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let local_key = identity::Keypair::generate_ed25519();
|
||||
let local_peer_id = PeerId::from(local_key.public());
|
||||
let redis_client = RedisClient::new(redis_addr).context("Could not connect to redis")?;
|
||||
|
||||
// Build the transport from the passed ENV var.
|
||||
let (boxed_transport, local_addr) =
|
||||
build_transport(local_key.clone(), ip, transport, sec_protocol, muxer)?;
|
||||
let mut swarm = swarm_builder(
|
||||
boxed_transport,
|
||||
Behaviour {
|
||||
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(10))),
|
||||
// Need to include identify until https://github.com/status-im/nim-libp2p/issues/924 is resolved.
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"/interop-tests".to_owned(),
|
||||
local_key.public(),
|
||||
)),
|
||||
},
|
||||
local_peer_id,
|
||||
)
|
||||
.idle_connection_timeout(Duration::from_secs(5))
|
||||
.build();
|
||||
let (mut swarm, local_addr) =
|
||||
build_swarm(ip, transport, sec_protocol, muxer, build_behaviour).await?;
|
||||
|
||||
log::info!("Running ping test: {}", swarm.local_peer_id());
|
||||
|
||||
let mut maybe_id = None;
|
||||
|
||||
// See https://github.com/libp2p/rust-libp2p/issues/4071.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if transport == Transport::WebRtcDirect {
|
||||
maybe_id = Some(swarm.listen_on(local_addr.parse()?)?);
|
||||
}
|
||||
let maybe_id = if transport == Transport::WebRtcDirect {
|
||||
Some(swarm.listen_on(local_addr.parse()?)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let maybe_id = None;
|
||||
|
||||
// Run a ping interop test. Based on `is_dialer`, either dial the address
|
||||
// retrieved via `listenAddr` key over the redis connection. Or wait to be pinged and have
|
||||
@ -129,9 +116,8 @@ pub async fn run_test(
|
||||
continue;
|
||||
}
|
||||
if listener_id == id {
|
||||
let ma = format!("{address}/p2p/{local_peer_id}");
|
||||
let ma = format!("{address}/p2p/{}", swarm.local_peer_id());
|
||||
redis_client.rpush("listenerAddr", ma.clone()).await?;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -271,7 +257,18 @@ impl FromStr for SecProtocol {
|
||||
}
|
||||
|
||||
#[derive(NetworkBehaviour)]
|
||||
struct Behaviour {
|
||||
pub(crate) struct Behaviour {
|
||||
ping: ping::Behaviour,
|
||||
identify: identify::Behaviour,
|
||||
}
|
||||
|
||||
pub(crate) fn build_behaviour(key: &Keypair) -> Behaviour {
|
||||
Behaviour {
|
||||
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
|
||||
// Need to include identify until https://github.com/status-im/nim-libp2p/issues/924 is resolved.
|
||||
identify: identify::Behaviour::new(identify::Config::new(
|
||||
"/interop-tests".to_owned(),
|
||||
key.public(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,17 @@
|
||||
This supersedes the existing `libp2p::wasm_ext` module which is now deprecated.
|
||||
See [PR 3679].
|
||||
|
||||
- Introduce a new `libp2p::SwarmBuilder` in favor of the now deprecated `libp2p::swarm::SwarmBuilder`.
|
||||
See `libp2p::SwarmBuilder` docs on how to use the new builder.
|
||||
Also see [PR 4120].
|
||||
|
||||
- Update `libp2p-identity` version to 0.2.6.
|
||||
Under the hood, we feature-flagged `libp2p-identity`'s `rand` dependency but it is enabled by default when using `libp2p`.
|
||||
See [PR 4349](https://github.com/libp2p/rust-libp2p/pull/4349).
|
||||
See [PR 4349].
|
||||
|
||||
[PR 3679]: https://github.com/libp2p/rust-libp2p/pull/3679
|
||||
[PR 4120]: https://github.com/libp2p/rust-libp2p/pull/4120
|
||||
[PR 4349]: https://github.com/libp2p/rust-libp2p/pull/4349
|
||||
|
||||
## 0.52.3
|
||||
|
||||
|
@ -97,10 +97,13 @@ upnp = ["dep:libp2p-upnp"]
|
||||
|
||||
[dependencies]
|
||||
bytes = "1"
|
||||
either = "1.9.0"
|
||||
futures = "0.3.26"
|
||||
futures-timer = "3.0.2" # Explicit dependency to be used in `wasm-bindgen` feature
|
||||
getrandom = "0.2.3" # Explicit dependency to be used in `wasm-bindgen` feature
|
||||
instant = "0.1.12" # Explicit dependency to be used in `wasm-bindgen` feature
|
||||
# TODO feature flag?
|
||||
rw-stream-sink = { workspace = true }
|
||||
|
||||
libp2p-allow-block-list = { workspace = true }
|
||||
libp2p-autonat = { workspace = true, optional = true }
|
||||
@ -127,6 +130,7 @@ libp2p-webtransport-websys = { workspace = true, optional = true }
|
||||
libp2p-yamux = { workspace = true, optional = true }
|
||||
multiaddr = { workspace = true }
|
||||
pin-project = "1.0.0"
|
||||
thiserror = "1.0"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
libp2p-deflate = { workspace = true, optional = true }
|
||||
@ -148,6 +152,7 @@ env_logger = "0.10.0"
|
||||
clap = { version = "4.1.6", features = ["derive"] }
|
||||
tokio = { version = "1.15", features = [ "io-util", "io-std", "macros", "rt", "rt-multi-thread"] }
|
||||
|
||||
libp2p-mplex = { workspace = true }
|
||||
libp2p-noise = { workspace = true }
|
||||
libp2p-tcp = { workspace = true, features = ["tokio"] }
|
||||
|
||||
|
322
libp2p/src/builder.rs
Normal file
322
libp2p/src/builder.rs
Normal file
@ -0,0 +1,322 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
mod phase;
|
||||
mod select_security;
|
||||
|
||||
/// Build a [`Swarm`](libp2p_swarm::Swarm) by combining an identity, a set of
|
||||
/// [`Transport`](libp2p_core::Transport)s and a
|
||||
/// [`NetworkBehaviour`](libp2p_swarm::NetworkBehaviour).
|
||||
///
|
||||
/// ```
|
||||
/// # use libp2p::{swarm::NetworkBehaviour, SwarmBuilder};
|
||||
/// # use libp2p::core::transport::dummy::DummyTransport;
|
||||
/// # use libp2p::core::muxing::StreamMuxerBox;
|
||||
/// # use libp2p::identity::PeerId;
|
||||
/// # use std::error::Error;
|
||||
/// #
|
||||
/// # #[cfg(all(
|
||||
/// # not(target_arch = "wasm32"),
|
||||
/// # feature = "tokio",
|
||||
/// # feature = "tcp",
|
||||
/// # feature = "tls",
|
||||
/// # feature = "noise",
|
||||
/// # feature = "quic",
|
||||
/// # feature = "dns",
|
||||
/// # feature = "relay",
|
||||
/// # feature = "websocket",
|
||||
/// # ))]
|
||||
/// # async fn build_swarm() -> Result<(), Box<dyn Error>> {
|
||||
/// # #[derive(NetworkBehaviour)]
|
||||
/// # #[behaviour(prelude = "libp2p_swarm::derive_prelude")]
|
||||
/// # struct MyBehaviour {
|
||||
/// # relay: libp2p_relay::client::Behaviour,
|
||||
/// # }
|
||||
///
|
||||
/// let swarm = SwarmBuilder::with_new_identity()
|
||||
/// .with_tokio()
|
||||
/// .with_tcp(
|
||||
/// Default::default(),
|
||||
/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
/// libp2p_yamux::Config::default,
|
||||
/// )?
|
||||
/// .with_quic()
|
||||
/// .with_other_transport(|_key| DummyTransport::<(PeerId, StreamMuxerBox)>::new())?
|
||||
/// .with_dns()?
|
||||
/// .with_relay_client(
|
||||
/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
/// libp2p_yamux::Config::default,
|
||||
/// )?
|
||||
/// .with_websocket(
|
||||
/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
/// libp2p_yamux::Config::default,
|
||||
/// )
|
||||
/// .await?
|
||||
/// .with_behaviour(|_key, relay| MyBehaviour { relay })?
|
||||
/// .build();
|
||||
/// #
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct SwarmBuilder<Provider, Phase> {
|
||||
keypair: libp2p_identity::Keypair,
|
||||
phantom: PhantomData<Provider>,
|
||||
phase: Phase,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::SwarmBuilder;
|
||||
use libp2p_swarm::{NetworkBehaviour, Swarm};
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "noise"))]
|
||||
fn tcp() {
|
||||
let _ = SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
libp2p_tls::Config::new,
|
||||
libp2p_yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(
|
||||
feature = "async-std",
|
||||
feature = "tcp",
|
||||
feature = "tls",
|
||||
feature = "noise"
|
||||
))]
|
||||
fn async_std_tcp() {
|
||||
let _ = SwarmBuilder::with_new_identity()
|
||||
.with_async_std()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
libp2p_tls::Config::new,
|
||||
libp2p_yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "mplex"))]
|
||||
fn tcp_yamux_mplex() {
|
||||
let _ = SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
libp2p_tls::Config::new,
|
||||
(
|
||||
libp2p_yamux::Config::default(),
|
||||
libp2p_mplex::MplexConfig::default(),
|
||||
),
|
||||
)
|
||||
.unwrap()
|
||||
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(feature = "tokio", feature = "tcp", feature = "tls", feature = "noise"))]
|
||||
fn tcp_tls_noise() {
|
||||
let _ = SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
(libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
(
|
||||
libp2p_yamux::Config::default,
|
||||
libp2p_mplex::MplexConfig::default,
|
||||
),
|
||||
)
|
||||
.unwrap()
|
||||
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(
|
||||
feature = "tokio",
|
||||
feature = "tcp",
|
||||
feature = "tls",
|
||||
feature = "noise",
|
||||
feature = "quic"
|
||||
))]
|
||||
fn tcp_quic() {
|
||||
let _ = SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
(libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
libp2p_yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_quic()
|
||||
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(
|
||||
feature = "tokio",
|
||||
feature = "tcp",
|
||||
feature = "tls",
|
||||
feature = "noise",
|
||||
feature = "relay"
|
||||
))]
|
||||
fn tcp_relay() {
|
||||
#[derive(libp2p_swarm::NetworkBehaviour)]
|
||||
#[behaviour(prelude = "libp2p_swarm::derive_prelude")]
|
||||
struct Behaviour {
|
||||
dummy: libp2p_swarm::dummy::Behaviour,
|
||||
relay: libp2p_relay::client::Behaviour,
|
||||
}
|
||||
|
||||
let _ = SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
libp2p_tls::Config::new,
|
||||
libp2p_yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_relay_client(libp2p_tls::Config::new, libp2p_yamux::Config::default)
|
||||
.unwrap()
|
||||
.with_behaviour(|_, relay| Behaviour {
|
||||
dummy: libp2p_swarm::dummy::Behaviour,
|
||||
relay,
|
||||
})
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(all(
|
||||
feature = "tokio",
|
||||
feature = "tcp",
|
||||
feature = "tls",
|
||||
feature = "noise",
|
||||
feature = "dns"
|
||||
))]
|
||||
async fn tcp_dns() {
|
||||
SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
(libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
libp2p_yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_dns()
|
||||
.unwrap()
|
||||
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
|
||||
/// Showcases how to provide custom transports unknown to the libp2p crate, e.g. WebRTC.
|
||||
#[test]
|
||||
#[cfg(feature = "tokio")]
|
||||
fn other_transport() -> Result<(), Box<dyn std::error::Error>> {
|
||||
use libp2p_core::{muxing::StreamMuxerBox, transport::dummy::DummyTransport};
|
||||
use libp2p_identity::PeerId;
|
||||
|
||||
let _ = SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
// Closure can either return a Transport directly.
|
||||
.with_other_transport(|_| DummyTransport::<(PeerId, StreamMuxerBox)>::new())?
|
||||
// Or a Result containing a Transport.
|
||||
.with_other_transport(|_| {
|
||||
if true {
|
||||
Ok(DummyTransport::<(PeerId, StreamMuxerBox)>::new())
|
||||
} else {
|
||||
Err(Box::from("test"))
|
||||
}
|
||||
})?
|
||||
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
|
||||
.unwrap()
|
||||
.build();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(all(
|
||||
feature = "tokio",
|
||||
feature = "tcp",
|
||||
feature = "tls",
|
||||
feature = "noise",
|
||||
feature = "dns",
|
||||
feature = "websocket",
|
||||
))]
|
||||
async fn tcp_websocket() {
|
||||
let _ = SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
(libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
libp2p_yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_websocket(
|
||||
(libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
libp2p_yamux::Config::default,
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(all(
|
||||
feature = "tokio",
|
||||
feature = "tcp",
|
||||
feature = "tls",
|
||||
feature = "noise",
|
||||
feature = "quic",
|
||||
feature = "dns",
|
||||
feature = "relay",
|
||||
feature = "websocket",
|
||||
))]
|
||||
async fn all() {
|
||||
#[derive(NetworkBehaviour)]
|
||||
#[behaviour(prelude = "libp2p_swarm::derive_prelude")]
|
||||
struct MyBehaviour {
|
||||
relay: libp2p_relay::client::Behaviour,
|
||||
}
|
||||
|
||||
let (builder, _bandwidth_sinks) = SwarmBuilder::with_new_identity()
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
Default::default(),
|
||||
libp2p_tls::Config::new,
|
||||
libp2p_yamux::Config::default,
|
||||
)
|
||||
.unwrap()
|
||||
.with_quic()
|
||||
.with_dns()
|
||||
.unwrap()
|
||||
.with_relay_client(libp2p_tls::Config::new, libp2p_yamux::Config::default)
|
||||
.unwrap()
|
||||
.with_websocket(libp2p_tls::Config::new, libp2p_yamux::Config::default)
|
||||
.await
|
||||
.unwrap()
|
||||
.with_bandwidth_logging();
|
||||
let _: Swarm<MyBehaviour> = builder
|
||||
.with_behaviour(|_key, relay| MyBehaviour { relay })
|
||||
.unwrap()
|
||||
.build();
|
||||
}
|
||||
}
|
134
libp2p/src/builder/phase.rs
Normal file
134
libp2p/src/builder/phase.rs
Normal file
@ -0,0 +1,134 @@
|
||||
#![allow(unused_imports)]
|
||||
|
||||
mod bandwidth_logging;
|
||||
mod behaviour;
|
||||
mod build;
|
||||
mod dns;
|
||||
mod identity;
|
||||
mod other_transport;
|
||||
mod provider;
|
||||
mod quic;
|
||||
mod relay;
|
||||
mod swarm;
|
||||
mod tcp;
|
||||
mod websocket;
|
||||
|
||||
use bandwidth_logging::*;
|
||||
use behaviour::*;
|
||||
use build::*;
|
||||
use dns::*;
|
||||
use other_transport::*;
|
||||
use provider::*;
|
||||
use quic::*;
|
||||
use relay::*;
|
||||
use swarm::*;
|
||||
use tcp::*;
|
||||
use websocket::*;
|
||||
|
||||
use super::select_security::SelectSecurityUpgrade;
|
||||
use super::SwarmBuilder;
|
||||
|
||||
use libp2p_core::{muxing::StreamMuxerBox, upgrade::SelectUpgrade, Transport};
|
||||
use libp2p_identity::Keypair;
|
||||
|
||||
pub trait IntoSecurityUpgrade<C> {
|
||||
type Upgrade;
|
||||
type Error;
|
||||
|
||||
fn into_security_upgrade(self, keypair: &Keypair) -> Result<Self::Upgrade, Self::Error>;
|
||||
}
|
||||
|
||||
impl<C, T, F, E> IntoSecurityUpgrade<C> for F
|
||||
where
|
||||
F: for<'a> FnOnce(&'a Keypair) -> Result<T, E>,
|
||||
{
|
||||
type Upgrade = T;
|
||||
type Error = E;
|
||||
|
||||
fn into_security_upgrade(self, keypair: &Keypair) -> Result<Self::Upgrade, Self::Error> {
|
||||
(self)(keypair)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F1, F2, C> IntoSecurityUpgrade<C> for (F1, F2)
|
||||
where
|
||||
F1: IntoSecurityUpgrade<C>,
|
||||
F2: IntoSecurityUpgrade<C>,
|
||||
{
|
||||
type Upgrade = SelectSecurityUpgrade<F1::Upgrade, F2::Upgrade>;
|
||||
type Error = either::Either<F1::Error, F2::Error>;
|
||||
|
||||
fn into_security_upgrade(self, keypair: &Keypair) -> Result<Self::Upgrade, Self::Error> {
|
||||
let (f1, f2) = self;
|
||||
|
||||
let u1 = f1
|
||||
.into_security_upgrade(keypair)
|
||||
.map_err(either::Either::Left)?;
|
||||
let u2 = f2
|
||||
.into_security_upgrade(keypair)
|
||||
.map_err(either::Either::Right)?;
|
||||
|
||||
Ok(SelectSecurityUpgrade::new(u1, u2))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoMultiplexerUpgrade<C> {
|
||||
type Upgrade;
|
||||
|
||||
fn into_multiplexer_upgrade(self) -> Self::Upgrade;
|
||||
}
|
||||
|
||||
impl<C, U, F> IntoMultiplexerUpgrade<C> for F
|
||||
where
|
||||
F: FnOnce() -> U,
|
||||
{
|
||||
type Upgrade = U;
|
||||
|
||||
fn into_multiplexer_upgrade(self) -> Self::Upgrade {
|
||||
(self)()
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, U1, U2> IntoMultiplexerUpgrade<C> for (U1, U2)
|
||||
where
|
||||
U1: IntoMultiplexerUpgrade<C>,
|
||||
U2: IntoMultiplexerUpgrade<C>,
|
||||
{
|
||||
type Upgrade = SelectUpgrade<U1::Upgrade, U2::Upgrade>;
|
||||
|
||||
fn into_multiplexer_upgrade(self) -> Self::Upgrade {
|
||||
let (f1, f2) = self;
|
||||
|
||||
let u1 = f1.into_multiplexer_upgrade();
|
||||
let u2 = f2.into_multiplexer_upgrade();
|
||||
|
||||
SelectUpgrade::new(u1, u2)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AuthenticatedMultiplexedTransport:
|
||||
Transport<
|
||||
Error = Self::E,
|
||||
Dial = Self::D,
|
||||
ListenerUpgrade = Self::U,
|
||||
Output = (libp2p_identity::PeerId, StreamMuxerBox),
|
||||
> + Send
|
||||
+ Unpin
|
||||
+ 'static
|
||||
{
|
||||
type E: Send + Sync + 'static;
|
||||
type D: Send;
|
||||
type U: Send;
|
||||
}
|
||||
|
||||
impl<T> AuthenticatedMultiplexedTransport for T
|
||||
where
|
||||
T: Transport<Output = (libp2p_identity::PeerId, StreamMuxerBox)> + Send + Unpin + 'static,
|
||||
<T as Transport>::Error: Send + Sync + 'static,
|
||||
<T as Transport>::Dial: Send,
|
||||
<T as Transport>::ListenerUpgrade: Send,
|
||||
{
|
||||
type E = T::Error;
|
||||
type D = T::Dial;
|
||||
type U = T::ListenerUpgrade;
|
||||
}
|
70
libp2p/src/builder/phase/bandwidth_logging.rs
Normal file
70
libp2p/src/builder/phase/bandwidth_logging.rs
Normal file
@ -0,0 +1,70 @@
|
||||
use super::*;
|
||||
use crate::bandwidth::BandwidthSinks;
|
||||
use crate::transport_ext::TransportExt;
|
||||
use crate::SwarmBuilder;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct BandwidthLoggingPhase<T, R> {
|
||||
pub(crate) relay_behaviour: R,
|
||||
pub(crate) transport: T,
|
||||
}
|
||||
|
||||
impl<T: AuthenticatedMultiplexedTransport, Provider, R>
|
||||
SwarmBuilder<Provider, BandwidthLoggingPhase<T, R>>
|
||||
{
|
||||
pub fn with_bandwidth_logging(
|
||||
self,
|
||||
) -> (
|
||||
SwarmBuilder<Provider, BehaviourPhase<impl AuthenticatedMultiplexedTransport, R>>,
|
||||
Arc<BandwidthSinks>,
|
||||
) {
|
||||
let (transport, sinks) = self.phase.transport.with_bandwidth_logging();
|
||||
(
|
||||
SwarmBuilder {
|
||||
phase: BehaviourPhase {
|
||||
relay_behaviour: self.phase.relay_behaviour,
|
||||
transport,
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
},
|
||||
sinks,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn without_bandwidth_logging(self) -> SwarmBuilder<Provider, BehaviourPhase<T, R>> {
|
||||
SwarmBuilder {
|
||||
phase: BehaviourPhase {
|
||||
relay_behaviour: self.phase.relay_behaviour,
|
||||
transport: self.phase.transport,
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
#[cfg(feature = "relay")]
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<Provider, BandwidthLoggingPhase<T, libp2p_relay::client::Behaviour>>
|
||||
{
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair, libp2p_relay::client::Behaviour) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
self.without_bandwidth_logging().with_behaviour(constructor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<Provider, BandwidthLoggingPhase<T, NoRelayBehaviour>>
|
||||
{
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
self.without_bandwidth_logging().with_behaviour(constructor)
|
||||
}
|
||||
}
|
90
libp2p/src/builder/phase/behaviour.rs
Normal file
90
libp2p/src/builder/phase/behaviour.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use super::*;
|
||||
use crate::SwarmBuilder;
|
||||
use libp2p_swarm::NetworkBehaviour;
|
||||
use std::convert::Infallible;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct BehaviourPhase<T, R> {
|
||||
pub(crate) relay_behaviour: R,
|
||||
pub(crate) transport: T,
|
||||
}
|
||||
|
||||
#[cfg(feature = "relay")]
|
||||
impl<T, Provider> SwarmBuilder<Provider, BehaviourPhase<T, libp2p_relay::client::Behaviour>> {
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair, libp2p_relay::client::Behaviour) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
Ok(SwarmBuilder {
|
||||
phase: SwarmPhase {
|
||||
behaviour: constructor(&self.keypair, self.phase.relay_behaviour)
|
||||
.try_into_behaviour()?,
|
||||
transport: self.phase.transport,
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Provider> SwarmBuilder<Provider, BehaviourPhase<T, NoRelayBehaviour>> {
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
// Discard `NoRelayBehaviour`.
|
||||
let _ = self.phase.relay_behaviour;
|
||||
|
||||
Ok(SwarmBuilder {
|
||||
phase: SwarmPhase {
|
||||
behaviour: constructor(&self.keypair).try_into_behaviour()?,
|
||||
transport: self.phase.transport,
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TryIntoBehaviour<B>: private::Sealed<Self::Error> {
|
||||
type Error;
|
||||
|
||||
fn try_into_behaviour(self) -> Result<B, Self::Error>;
|
||||
}
|
||||
|
||||
impl<B> TryIntoBehaviour<B> for B
|
||||
where
|
||||
B: NetworkBehaviour,
|
||||
{
|
||||
type Error = Infallible;
|
||||
|
||||
fn try_into_behaviour(self) -> Result<B, Self::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> TryIntoBehaviour<B> for Result<B, Box<dyn std::error::Error + Send + Sync>>
|
||||
where
|
||||
B: NetworkBehaviour,
|
||||
{
|
||||
type Error = BehaviourError;
|
||||
|
||||
fn try_into_behaviour(self) -> Result<B, Self::Error> {
|
||||
self.map_err(BehaviourError)
|
||||
}
|
||||
}
|
||||
|
||||
mod private {
|
||||
pub trait Sealed<Error> {}
|
||||
}
|
||||
|
||||
impl<B: NetworkBehaviour> private::Sealed<Infallible> for B {}
|
||||
|
||||
impl<B: NetworkBehaviour> private::Sealed<BehaviourError>
|
||||
for Result<B, Box<dyn std::error::Error + Send + Sync>>
|
||||
{
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("failed to build behaviour: {0}")]
|
||||
pub struct BehaviourError(Box<dyn std::error::Error + Send + Sync + 'static>);
|
31
libp2p/src/builder/phase/build.rs
Normal file
31
libp2p/src/builder/phase/build.rs
Normal file
@ -0,0 +1,31 @@
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
|
||||
use crate::SwarmBuilder;
|
||||
use libp2p_core::Transport;
|
||||
use libp2p_swarm::Swarm;
|
||||
|
||||
pub struct BuildPhase<T, B> {
|
||||
pub(crate) behaviour: B,
|
||||
pub(crate) transport: T,
|
||||
pub(crate) swarm_config: libp2p_swarm::Config,
|
||||
}
|
||||
|
||||
const CONNECTION_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
|
||||
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport, B: libp2p_swarm::NetworkBehaviour>
|
||||
SwarmBuilder<Provider, BuildPhase<T, B>>
|
||||
{
|
||||
pub fn build(self) -> Swarm<B> {
|
||||
Swarm::new(
|
||||
libp2p_core::transport::timeout::TransportTimeout::new(
|
||||
self.phase.transport,
|
||||
CONNECTION_TIMEOUT,
|
||||
)
|
||||
.boxed(),
|
||||
self.phase.behaviour,
|
||||
self.keypair.public().to_peer_id(),
|
||||
self.phase.swarm_config,
|
||||
)
|
||||
}
|
||||
}
|
68
libp2p/src/builder/phase/dns.rs
Normal file
68
libp2p/src/builder/phase/dns.rs
Normal file
@ -0,0 +1,68 @@
|
||||
use super::*;
|
||||
use crate::SwarmBuilder;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct DnsPhase<T> {
|
||||
pub(crate) transport: T,
|
||||
}
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
|
||||
impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::AsyncStd, DnsPhase<T>> {
|
||||
pub async fn with_dns(
|
||||
self,
|
||||
) -> Result<
|
||||
SwarmBuilder<super::provider::AsyncStd, RelayPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
std::io::Error,
|
||||
> {
|
||||
Ok(SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: RelayPhase {
|
||||
transport: libp2p_dns::async_std::Transport::system(self.phase.transport).await?,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))]
|
||||
impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::Tokio, DnsPhase<T>> {
|
||||
pub fn with_dns(
|
||||
self,
|
||||
) -> Result<
|
||||
SwarmBuilder<super::provider::Tokio, RelayPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
std::io::Error,
|
||||
> {
|
||||
Ok(SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: RelayPhase {
|
||||
transport: libp2p_dns::tokio::Transport::system(self.phase.transport)?,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Provider, T> SwarmBuilder<Provider, DnsPhase<T>> {
|
||||
pub(crate) fn without_dns(self) -> SwarmBuilder<Provider, RelayPhase<T>> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: RelayPhase {
|
||||
transport: self.phase.transport,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, DnsPhase<T>> {
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
self.without_dns()
|
||||
.without_relay()
|
||||
.without_websocket()
|
||||
.with_behaviour(constructor)
|
||||
}
|
||||
}
|
21
libp2p/src/builder/phase/identity.rs
Normal file
21
libp2p/src/builder/phase/identity.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use super::*;
|
||||
use crate::SwarmBuilder;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct IdentityPhase {}
|
||||
|
||||
impl SwarmBuilder<NoProviderSpecified, IdentityPhase> {
|
||||
pub fn with_new_identity() -> SwarmBuilder<NoProviderSpecified, ProviderPhase> {
|
||||
SwarmBuilder::with_existing_identity(libp2p_identity::Keypair::generate_ed25519())
|
||||
}
|
||||
|
||||
pub fn with_existing_identity(
|
||||
keypair: libp2p_identity::Keypair,
|
||||
) -> SwarmBuilder<NoProviderSpecified, ProviderPhase> {
|
||||
SwarmBuilder {
|
||||
keypair,
|
||||
phantom: PhantomData,
|
||||
phase: ProviderPhase {},
|
||||
}
|
||||
}
|
||||
}
|
208
libp2p/src/builder/phase/other_transport.rs
Normal file
208
libp2p/src/builder/phase/other_transport.rs
Normal file
@ -0,0 +1,208 @@
|
||||
use std::convert::Infallible;
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
use libp2p_core::Transport;
|
||||
#[cfg(feature = "relay")]
|
||||
use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, UpgradeInfo};
|
||||
#[cfg(feature = "relay")]
|
||||
use libp2p_identity::PeerId;
|
||||
|
||||
use crate::bandwidth::BandwidthSinks;
|
||||
use crate::SwarmBuilder;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct OtherTransportPhase<T> {
|
||||
pub(crate) transport: T,
|
||||
}
|
||||
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<Provider, OtherTransportPhase<T>>
|
||||
{
|
||||
pub fn with_other_transport<
|
||||
Muxer: libp2p_core::muxing::StreamMuxer + Send + 'static,
|
||||
OtherTransport: Transport<Output = (libp2p_identity::PeerId, Muxer)> + Send + Unpin + 'static,
|
||||
R: TryIntoTransport<OtherTransport>,
|
||||
>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<
|
||||
SwarmBuilder<Provider, OtherTransportPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
R::Error,
|
||||
>
|
||||
where
|
||||
<OtherTransport as Transport>::Error: Send + Sync + 'static,
|
||||
<OtherTransport as Transport>::Dial: Send,
|
||||
<OtherTransport as Transport>::ListenerUpgrade: Send,
|
||||
<Muxer as libp2p_core::muxing::StreamMuxer>::Substream: Send,
|
||||
<Muxer as libp2p_core::muxing::StreamMuxer>::Error: Send + Sync,
|
||||
{
|
||||
Ok(SwarmBuilder {
|
||||
phase: OtherTransportPhase {
|
||||
transport: self
|
||||
.phase
|
||||
.transport
|
||||
.or_transport(
|
||||
constructor(&self.keypair)
|
||||
.try_into_transport()?
|
||||
.map(|(peer_id, conn), _| (peer_id, StreamMuxerBox::new(conn))),
|
||||
)
|
||||
.map(|either, _| either.into_inner()),
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn without_any_other_transports(self) -> SwarmBuilder<Provider, DnsPhase<T>> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: DnsPhase {
|
||||
transport: self.phase.transport,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
|
||||
impl<T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<super::provider::AsyncStd, OtherTransportPhase<T>>
|
||||
{
|
||||
pub async fn with_dns(
|
||||
self,
|
||||
) -> Result<
|
||||
SwarmBuilder<super::provider::AsyncStd, RelayPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
std::io::Error,
|
||||
> {
|
||||
self.without_any_other_transports().with_dns().await
|
||||
}
|
||||
}
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))]
|
||||
impl<T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<super::provider::Tokio, OtherTransportPhase<T>>
|
||||
{
|
||||
pub fn with_dns(
|
||||
self,
|
||||
) -> Result<
|
||||
SwarmBuilder<super::provider::Tokio, RelayPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
std::io::Error,
|
||||
> {
|
||||
self.without_any_other_transports().with_dns()
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "relay")]
|
||||
impl<T: AuthenticatedMultiplexedTransport, Provider>
|
||||
SwarmBuilder<Provider, OtherTransportPhase<T>>
|
||||
{
|
||||
/// See [`SwarmBuilder::with_relay_client`].
|
||||
pub fn with_relay_client<SecUpgrade, SecStream, SecError, MuxUpgrade, MuxStream, MuxError>(
|
||||
self,
|
||||
security_upgrade: SecUpgrade,
|
||||
multiplexer_upgrade: MuxUpgrade,
|
||||
) -> Result<
|
||||
SwarmBuilder<
|
||||
Provider,
|
||||
WebsocketPhase<impl AuthenticatedMultiplexedTransport, libp2p_relay::client::Behaviour>,
|
||||
>,
|
||||
SecUpgrade::Error,
|
||||
> where
|
||||
|
||||
SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
|
||||
SecError: std::error::Error + Send + Sync + 'static,
|
||||
SecUpgrade: IntoSecurityUpgrade<libp2p_relay::client::Connection>,
|
||||
SecUpgrade::Upgrade: InboundUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (PeerId, SecStream), Error = SecError> + OutboundUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
|
||||
<SecUpgrade::Upgrade as InboundUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
|
||||
<SecUpgrade::Upgrade as OutboundUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
|
||||
<<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
MuxStream: libp2p_core::muxing::StreamMuxer + Send + 'static,
|
||||
MuxStream::Substream: Send + 'static,
|
||||
MuxStream::Error: Send + Sync + 'static,
|
||||
MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
|
||||
MuxUpgrade::Upgrade: InboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
|
||||
<MuxUpgrade::Upgrade as InboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
<MuxUpgrade::Upgrade as OutboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
MuxError: std::error::Error + Send + Sync + 'static,
|
||||
<<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
{
|
||||
self.without_any_other_transports()
|
||||
.without_dns()
|
||||
.with_relay_client(security_upgrade, multiplexer_upgrade)
|
||||
}
|
||||
}
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<Provider, OtherTransportPhase<T>>
|
||||
{
|
||||
pub fn with_bandwidth_logging(
|
||||
self,
|
||||
) -> (
|
||||
SwarmBuilder<
|
||||
Provider,
|
||||
BehaviourPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
|
||||
>,
|
||||
Arc<BandwidthSinks>,
|
||||
) {
|
||||
self.without_any_other_transports()
|
||||
.without_dns()
|
||||
.without_relay()
|
||||
.without_websocket()
|
||||
.with_bandwidth_logging()
|
||||
}
|
||||
}
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<Provider, OtherTransportPhase<T>>
|
||||
{
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
self.without_any_other_transports()
|
||||
.without_dns()
|
||||
.without_relay()
|
||||
.without_websocket()
|
||||
.without_bandwidth_logging()
|
||||
.with_behaviour(constructor)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TryIntoTransport<T>: private::Sealed<Self::Error> {
|
||||
type Error;
|
||||
|
||||
fn try_into_transport(self) -> Result<T, Self::Error>;
|
||||
}
|
||||
|
||||
impl<T: Transport> TryIntoTransport<T> for T {
|
||||
type Error = Infallible;
|
||||
|
||||
fn try_into_transport(self) -> Result<T, Self::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transport> TryIntoTransport<T> for Result<T, Box<dyn std::error::Error + Send + Sync>> {
|
||||
type Error = TransportError;
|
||||
|
||||
fn try_into_transport(self) -> Result<T, Self::Error> {
|
||||
self.map_err(TransportError)
|
||||
}
|
||||
}
|
||||
|
||||
mod private {
|
||||
pub trait Sealed<Error> {}
|
||||
}
|
||||
|
||||
impl<T: Transport> private::Sealed<Infallible> for T {}
|
||||
|
||||
impl<T: Transport> private::Sealed<TransportError>
|
||||
for Result<T, Box<dyn std::error::Error + Send + Sync>>
|
||||
{
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("failed to build transport: {0}")]
|
||||
pub struct TransportError(Box<dyn std::error::Error + Send + Sync + 'static>);
|
46
libp2p/src/builder/phase/provider.rs
Normal file
46
libp2p/src/builder/phase/provider.rs
Normal file
@ -0,0 +1,46 @@
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
|
||||
use crate::SwarmBuilder;
|
||||
|
||||
pub struct ProviderPhase {}
|
||||
|
||||
impl SwarmBuilder<NoProviderSpecified, ProviderPhase> {
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "async-std"))]
|
||||
pub fn with_async_std(self) -> SwarmBuilder<AsyncStd, TcpPhase> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: std::marker::PhantomData,
|
||||
phase: TcpPhase {},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio"))]
|
||||
pub fn with_tokio(self) -> SwarmBuilder<Tokio, TcpPhase> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: std::marker::PhantomData,
|
||||
phase: TcpPhase {},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wasm-bindgen")]
|
||||
pub fn with_wasm_bindgen(self) -> SwarmBuilder<WasmBindgen, TcpPhase> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: std::marker::PhantomData,
|
||||
phase: TcpPhase {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum NoProviderSpecified {}
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "async-std"))]
|
||||
pub enum AsyncStd {}
|
||||
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio"))]
|
||||
pub enum Tokio {}
|
||||
|
||||
#[cfg(feature = "wasm-bindgen")]
|
||||
pub enum WasmBindgen {}
|
239
libp2p/src/builder/phase/quic.rs
Normal file
239
libp2p/src/builder/phase/quic.rs
Normal file
@ -0,0 +1,239 @@
|
||||
use super::*;
|
||||
use crate::SwarmBuilder;
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
use libp2p_core::muxing::StreamMuxer;
|
||||
#[cfg(any(
|
||||
feature = "relay",
|
||||
all(not(target_arch = "wasm32"), feature = "websocket")
|
||||
))]
|
||||
use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, UpgradeInfo};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct QuicPhase<T> {
|
||||
pub(crate) transport: T,
|
||||
}
|
||||
|
||||
macro_rules! impl_quic_builder {
|
||||
($providerKebabCase:literal, $providerPascalCase:ty, $quic:ident) => {
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "quic", feature = $providerKebabCase))]
|
||||
impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<$providerPascalCase, QuicPhase<T>> {
|
||||
pub fn with_quic(
|
||||
self,
|
||||
) -> SwarmBuilder<
|
||||
$providerPascalCase,
|
||||
OtherTransportPhase<impl AuthenticatedMultiplexedTransport>,
|
||||
> {
|
||||
self.with_quic_config(std::convert::identity)
|
||||
}
|
||||
|
||||
pub fn with_quic_config(
|
||||
self,
|
||||
constructor: impl FnOnce(libp2p_quic::Config) -> libp2p_quic::Config,
|
||||
) -> SwarmBuilder<
|
||||
$providerPascalCase,
|
||||
OtherTransportPhase<impl AuthenticatedMultiplexedTransport>,
|
||||
> {
|
||||
SwarmBuilder {
|
||||
phase: OtherTransportPhase {
|
||||
transport: self
|
||||
.phase
|
||||
.transport
|
||||
.or_transport(
|
||||
libp2p_quic::$quic::Transport::new(constructor(
|
||||
libp2p_quic::Config::new(&self.keypair),
|
||||
))
|
||||
.map(|(peer_id, muxer), _| {
|
||||
(peer_id, libp2p_core::muxing::StreamMuxerBox::new(muxer))
|
||||
}),
|
||||
)
|
||||
.map(|either, _| either.into_inner()),
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_quic_builder!("async-std", AsyncStd, async_std);
|
||||
impl_quic_builder!("tokio", super::provider::Tokio, tokio);
|
||||
|
||||
impl<Provider, T> SwarmBuilder<Provider, QuicPhase<T>> {
|
||||
pub(crate) fn without_quic(self) -> SwarmBuilder<Provider, OtherTransportPhase<T>> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: OtherTransportPhase {
|
||||
transport: self.phase.transport,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, QuicPhase<T>> {
|
||||
/// See [`SwarmBuilder::with_relay_client`].
|
||||
#[cfg(feature = "relay")]
|
||||
pub fn with_relay_client<SecUpgrade, SecStream, SecError, MuxUpgrade, MuxStream, MuxError>(
|
||||
self,
|
||||
security_upgrade: SecUpgrade,
|
||||
multiplexer_upgrade: MuxUpgrade,
|
||||
) -> Result<
|
||||
SwarmBuilder<
|
||||
Provider,
|
||||
super::websocket::WebsocketPhase<impl AuthenticatedMultiplexedTransport, libp2p_relay::client::Behaviour>,
|
||||
>,
|
||||
SecUpgrade::Error,
|
||||
> where
|
||||
|
||||
SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
|
||||
SecError: std::error::Error + Send + Sync + 'static,
|
||||
SecUpgrade: IntoSecurityUpgrade<libp2p_relay::client::Connection>,
|
||||
SecUpgrade::Upgrade: InboundUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
|
||||
<SecUpgrade::Upgrade as InboundUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
|
||||
<SecUpgrade::Upgrade as OutboundUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
|
||||
<<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
MuxStream: libp2p_core::muxing::StreamMuxer + Send + 'static,
|
||||
MuxStream::Substream: Send + 'static,
|
||||
MuxStream::Error: Send + Sync + 'static,
|
||||
MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
|
||||
MuxUpgrade::Upgrade: InboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
|
||||
<MuxUpgrade::Upgrade as InboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
<MuxUpgrade::Upgrade as OutboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
MuxError: std::error::Error + Send + Sync + 'static,
|
||||
<<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
{
|
||||
self.without_quic()
|
||||
.with_relay_client(security_upgrade, multiplexer_upgrade)
|
||||
}
|
||||
|
||||
pub fn with_other_transport<
|
||||
Muxer: libp2p_core::muxing::StreamMuxer + Send + 'static,
|
||||
OtherTransport: Transport<Output = (libp2p_identity::PeerId, Muxer)> + Send + Unpin + 'static,
|
||||
R: TryIntoTransport<OtherTransport>,
|
||||
>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<
|
||||
SwarmBuilder<Provider, OtherTransportPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
R::Error,
|
||||
>
|
||||
where
|
||||
<OtherTransport as Transport>::Error: Send + Sync + 'static,
|
||||
<OtherTransport as Transport>::Dial: Send,
|
||||
<OtherTransport as Transport>::ListenerUpgrade: Send,
|
||||
<Muxer as libp2p_core::muxing::StreamMuxer>::Substream: Send,
|
||||
<Muxer as libp2p_core::muxing::StreamMuxer>::Error: Send + Sync,
|
||||
{
|
||||
self.without_quic().with_other_transport(constructor)
|
||||
}
|
||||
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
self.without_quic()
|
||||
.without_any_other_transports()
|
||||
.without_dns()
|
||||
.without_relay()
|
||||
.without_websocket()
|
||||
.with_behaviour(constructor)
|
||||
}
|
||||
}
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
|
||||
impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::AsyncStd, QuicPhase<T>> {
|
||||
pub async fn with_dns(
|
||||
self,
|
||||
) -> Result<
|
||||
SwarmBuilder<super::provider::AsyncStd, RelayPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
std::io::Error,
|
||||
> {
|
||||
self.without_quic()
|
||||
.without_any_other_transports()
|
||||
.with_dns()
|
||||
.await
|
||||
}
|
||||
}
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))]
|
||||
impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<super::provider::Tokio, QuicPhase<T>> {
|
||||
pub fn with_dns(
|
||||
self,
|
||||
) -> Result<
|
||||
SwarmBuilder<super::provider::Tokio, RelayPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
std::io::Error,
|
||||
> {
|
||||
self.without_quic()
|
||||
.without_any_other_transports()
|
||||
.with_dns()
|
||||
}
|
||||
}
|
||||
macro_rules! impl_quic_phase_with_websocket {
|
||||
($providerKebabCase:literal, $providerPascalCase:ty, $websocketStream:ty) => {
|
||||
#[cfg(all(feature = $providerKebabCase, not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<$providerPascalCase, QuicPhase<T>> {
|
||||
/// See [`SwarmBuilder::with_websocket`].
|
||||
pub async fn with_websocket <
|
||||
SecUpgrade,
|
||||
SecStream,
|
||||
SecError,
|
||||
MuxUpgrade,
|
||||
MuxStream,
|
||||
MuxError,
|
||||
> (
|
||||
self,
|
||||
security_upgrade: SecUpgrade,
|
||||
multiplexer_upgrade: MuxUpgrade,
|
||||
) -> Result<
|
||||
SwarmBuilder<
|
||||
$providerPascalCase,
|
||||
BandwidthLoggingPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
|
||||
>,
|
||||
super::websocket::WebsocketError<SecUpgrade::Error>,
|
||||
>
|
||||
where
|
||||
SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
|
||||
SecError: std::error::Error + Send + Sync + 'static,
|
||||
SecUpgrade: IntoSecurityUpgrade<$websocketStream>,
|
||||
SecUpgrade::Upgrade: InboundUpgrade<Negotiated<$websocketStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundUpgrade<Negotiated<$websocketStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
|
||||
<SecUpgrade::Upgrade as InboundUpgrade<Negotiated<$websocketStream>>>::Future: Send,
|
||||
<SecUpgrade::Upgrade as OutboundUpgrade<Negotiated<$websocketStream>>>::Future: Send,
|
||||
<<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
MuxStream: StreamMuxer + Send + 'static,
|
||||
MuxStream::Substream: Send + 'static,
|
||||
MuxStream::Error: Send + Sync + 'static,
|
||||
MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
|
||||
MuxUpgrade::Upgrade: InboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
|
||||
<MuxUpgrade::Upgrade as InboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
<MuxUpgrade::Upgrade as OutboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
MuxError: std::error::Error + Send + Sync + 'static,
|
||||
<<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
{
|
||||
self.without_quic()
|
||||
.without_any_other_transports()
|
||||
.without_dns()
|
||||
.without_relay()
|
||||
.with_websocket(security_upgrade, multiplexer_upgrade)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl_quic_phase_with_websocket!(
|
||||
"async-std",
|
||||
super::provider::AsyncStd,
|
||||
rw_stream_sink::RwStreamSink<
|
||||
libp2p_websocket::BytesConnection<libp2p_tcp::async_io::TcpStream>,
|
||||
>
|
||||
);
|
||||
impl_quic_phase_with_websocket!(
|
||||
"tokio",
|
||||
super::provider::Tokio,
|
||||
rw_stream_sink::RwStreamSink<libp2p_websocket::BytesConnection<libp2p_tcp::tokio::TcpStream>>
|
||||
);
|
192
libp2p/src/builder/phase/relay.rs
Normal file
192
libp2p/src/builder/phase/relay.rs
Normal file
@ -0,0 +1,192 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[cfg(feature = "relay")]
|
||||
use libp2p_core::muxing::StreamMuxerBox;
|
||||
#[cfg(feature = "relay")]
|
||||
use libp2p_core::Transport;
|
||||
#[cfg(any(feature = "relay", feature = "websocket"))]
|
||||
use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, StreamMuxer, UpgradeInfo};
|
||||
#[cfg(feature = "relay")]
|
||||
use libp2p_identity::PeerId;
|
||||
|
||||
use crate::SwarmBuilder;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct RelayPhase<T> {
|
||||
pub(crate) transport: T,
|
||||
}
|
||||
|
||||
#[cfg(feature = "relay")]
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, RelayPhase<T>> {
|
||||
/// Adds a relay client transport.
|
||||
///
|
||||
/// Note that both `security_upgrade` and `multiplexer_upgrade` take function pointers,
|
||||
/// i.e. they take the function themselves (without the invocation via `()`), not the
|
||||
/// result of the function invocation. See example below.
|
||||
///
|
||||
/// ``` rust
|
||||
/// # use libp2p::SwarmBuilder;
|
||||
/// # use std::error::Error;
|
||||
/// # async fn build_swarm() -> Result<(), Box<dyn Error>> {
|
||||
/// let swarm = SwarmBuilder::with_new_identity()
|
||||
/// .with_tokio()
|
||||
/// .with_tcp(
|
||||
/// Default::default(),
|
||||
/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
/// libp2p_yamux::Config::default,
|
||||
/// )?
|
||||
/// .with_relay_client(
|
||||
/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
/// libp2p_yamux::Config::default,
|
||||
/// )?
|
||||
/// # ;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn with_relay_client<SecUpgrade, SecStream, SecError, MuxUpgrade, MuxStream, MuxError>(
|
||||
self,
|
||||
security_upgrade: SecUpgrade,
|
||||
multiplexer_upgrade: MuxUpgrade,
|
||||
) -> Result<
|
||||
SwarmBuilder<
|
||||
Provider,
|
||||
WebsocketPhase<impl AuthenticatedMultiplexedTransport, libp2p_relay::client::Behaviour>,
|
||||
>,
|
||||
SecUpgrade::Error,
|
||||
> where
|
||||
|
||||
SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
|
||||
SecError: std::error::Error + Send + Sync + 'static,
|
||||
SecUpgrade: IntoSecurityUpgrade<libp2p_relay::client::Connection>,
|
||||
SecUpgrade::Upgrade: InboundUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (PeerId, SecStream), Error = SecError> + OutboundUpgrade<Negotiated<libp2p_relay::client::Connection>, Output = (PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
|
||||
<SecUpgrade::Upgrade as InboundUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
|
||||
<SecUpgrade::Upgrade as OutboundUpgrade<Negotiated<libp2p_relay::client::Connection>>>::Future: Send,
|
||||
<<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<SecUpgrade as IntoSecurityUpgrade<libp2p_relay::client::Connection>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
MuxStream: StreamMuxer + Send + 'static,
|
||||
MuxStream::Substream: Send + 'static,
|
||||
MuxStream::Error: Send + Sync + 'static,
|
||||
MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
|
||||
MuxUpgrade::Upgrade: InboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
|
||||
<MuxUpgrade::Upgrade as InboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
<MuxUpgrade::Upgrade as OutboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
MuxError: std::error::Error + Send + Sync + 'static,
|
||||
<<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
{
|
||||
let (relay_transport, relay_behaviour) =
|
||||
libp2p_relay::client::new(self.keypair.public().to_peer_id());
|
||||
|
||||
Ok(SwarmBuilder {
|
||||
phase: WebsocketPhase {
|
||||
relay_behaviour,
|
||||
transport: self
|
||||
.phase
|
||||
.transport
|
||||
.or_transport(
|
||||
relay_transport
|
||||
.upgrade(libp2p_core::upgrade::Version::V1Lazy)
|
||||
.authenticate(security_upgrade.into_security_upgrade(&self.keypair)?)
|
||||
.multiplex(multiplexer_upgrade.into_multiplexer_upgrade())
|
||||
.map(|(p, c), _| (p, StreamMuxerBox::new(c))),
|
||||
)
|
||||
.map(|either, _| either.into_inner()),
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NoRelayBehaviour;
|
||||
|
||||
impl<Provider, T> SwarmBuilder<Provider, RelayPhase<T>> {
|
||||
pub(crate) fn without_relay(
|
||||
self,
|
||||
) -> SwarmBuilder<Provider, WebsocketPhase<T, NoRelayBehaviour>> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: WebsocketPhase {
|
||||
transport: self.phase.transport,
|
||||
relay_behaviour: NoRelayBehaviour,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport> SwarmBuilder<Provider, RelayPhase<T>> {
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
self.without_relay()
|
||||
.without_websocket()
|
||||
.with_behaviour(constructor)
|
||||
}
|
||||
}
|
||||
macro_rules! impl_relay_phase_with_websocket {
|
||||
($providerKebabCase:literal, $providerPascalCase:ty, $websocketStream:ty) => {
|
||||
#[cfg(all(feature = $providerKebabCase, not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
impl<T: AuthenticatedMultiplexedTransport> SwarmBuilder<$providerPascalCase, RelayPhase<T>> {
|
||||
pub async fn with_websocket <
|
||||
SecUpgrade,
|
||||
SecStream,
|
||||
SecError,
|
||||
MuxUpgrade,
|
||||
MuxStream,
|
||||
MuxError,
|
||||
> (
|
||||
self,
|
||||
security_upgrade: SecUpgrade,
|
||||
multiplexer_upgrade: MuxUpgrade,
|
||||
) -> Result<
|
||||
SwarmBuilder<
|
||||
$providerPascalCase,
|
||||
BandwidthLoggingPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
|
||||
>,
|
||||
super::websocket::WebsocketError<SecUpgrade::Error>,
|
||||
>
|
||||
where
|
||||
SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
|
||||
SecError: std::error::Error + Send + Sync + 'static,
|
||||
SecUpgrade: IntoSecurityUpgrade<$websocketStream>,
|
||||
SecUpgrade::Upgrade: InboundUpgrade<Negotiated<$websocketStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundUpgrade<Negotiated<$websocketStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
|
||||
<SecUpgrade::Upgrade as InboundUpgrade<Negotiated<$websocketStream>>>::Future: Send,
|
||||
<SecUpgrade::Upgrade as OutboundUpgrade<Negotiated<$websocketStream>>>::Future: Send,
|
||||
<<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
MuxStream: StreamMuxer + Send + 'static,
|
||||
MuxStream::Substream: Send + 'static,
|
||||
MuxStream::Error: Send + Sync + 'static,
|
||||
MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
|
||||
MuxUpgrade::Upgrade: InboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
|
||||
<MuxUpgrade::Upgrade as InboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
<MuxUpgrade::Upgrade as OutboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
MuxError: std::error::Error + Send + Sync + 'static,
|
||||
<<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
{
|
||||
self.without_relay()
|
||||
.with_websocket(security_upgrade, multiplexer_upgrade)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl_relay_phase_with_websocket!(
|
||||
"async-std",
|
||||
super::provider::AsyncStd,
|
||||
rw_stream_sink::RwStreamSink<
|
||||
libp2p_websocket::BytesConnection<libp2p_tcp::async_io::TcpStream>,
|
||||
>
|
||||
);
|
||||
impl_relay_phase_with_websocket!(
|
||||
"tokio",
|
||||
super::provider::Tokio,
|
||||
rw_stream_sink::RwStreamSink<libp2p_websocket::BytesConnection<libp2p_tcp::tokio::TcpStream>>
|
||||
);
|
60
libp2p/src/builder/phase/swarm.rs
Normal file
60
libp2p/src/builder/phase/swarm.rs
Normal file
@ -0,0 +1,60 @@
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct SwarmPhase<T, B> {
|
||||
pub(crate) behaviour: B,
|
||||
pub(crate) transport: T,
|
||||
}
|
||||
|
||||
macro_rules! impl_with_swarm_config {
|
||||
($providerKebabCase:literal, $providerPascalCase:ty, $config:expr) => {
|
||||
#[cfg(feature = $providerKebabCase)]
|
||||
impl<T, B> SwarmBuilder<$providerPascalCase, SwarmPhase<T, B>> {
|
||||
pub fn with_swarm_config(
|
||||
self,
|
||||
constructor: impl FnOnce(libp2p_swarm::Config) -> libp2p_swarm::Config,
|
||||
) -> SwarmBuilder<$providerPascalCase, BuildPhase<T, B>> {
|
||||
SwarmBuilder {
|
||||
phase: BuildPhase {
|
||||
behaviour: self.phase.behaviour,
|
||||
transport: self.phase.transport,
|
||||
swarm_config: constructor($config),
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
pub fn build(self) -> libp2p_swarm::Swarm<B>
|
||||
where
|
||||
B: libp2p_swarm::NetworkBehaviour,
|
||||
T: AuthenticatedMultiplexedTransport,
|
||||
{
|
||||
self.with_swarm_config(std::convert::identity).build()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl_with_swarm_config!(
|
||||
"async-std",
|
||||
super::provider::AsyncStd,
|
||||
libp2p_swarm::Config::with_async_std_executor()
|
||||
);
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl_with_swarm_config!(
|
||||
"tokio",
|
||||
super::provider::Tokio,
|
||||
libp2p_swarm::Config::with_tokio_executor()
|
||||
);
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
impl_with_swarm_config!(
|
||||
"wasm-bindgen",
|
||||
super::provider::WasmBindgen,
|
||||
libp2p_swarm::Config::with_wasm_executor()
|
||||
);
|
226
libp2p/src/builder/phase/tcp.rs
Normal file
226
libp2p/src/builder/phase/tcp.rs
Normal file
@ -0,0 +1,226 @@
|
||||
use super::*;
|
||||
use crate::SwarmBuilder;
|
||||
#[cfg(all(
|
||||
not(target_arch = "wasm32"),
|
||||
any(feature = "tcp", feature = "websocket")
|
||||
))]
|
||||
use libp2p_core::muxing::{StreamMuxer, StreamMuxerBox};
|
||||
#[cfg(all(feature = "websocket", not(target_arch = "wasm32")))]
|
||||
use libp2p_core::Transport;
|
||||
#[cfg(all(
|
||||
not(target_arch = "wasm32"),
|
||||
any(feature = "tcp", feature = "websocket")
|
||||
))]
|
||||
use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, UpgradeInfo};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct TcpPhase {}
|
||||
|
||||
macro_rules! impl_tcp_builder {
|
||||
($providerKebabCase:literal, $providerPascalCase:ty, $path:ident) => {
|
||||
#[cfg(all(
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "tcp",
|
||||
feature = $providerKebabCase,
|
||||
))]
|
||||
impl SwarmBuilder<$providerPascalCase, TcpPhase> {
|
||||
/// Adds a TCP based transport.
|
||||
///
|
||||
/// Note that both `security_upgrade` and `multiplexer_upgrade` take function pointers,
|
||||
/// i.e. they take the function themselves (without the invocation via `()`), not the
|
||||
/// result of the function invocation. See example below.
|
||||
///
|
||||
/// ``` rust
|
||||
/// # use libp2p::SwarmBuilder;
|
||||
/// # use std::error::Error;
|
||||
/// # async fn build_swarm() -> Result<(), Box<dyn Error>> {
|
||||
/// let swarm = SwarmBuilder::with_new_identity()
|
||||
/// .with_tokio()
|
||||
/// .with_tcp(
|
||||
/// Default::default(),
|
||||
/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
/// libp2p_yamux::Config::default,
|
||||
/// )?
|
||||
/// # ;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn with_tcp<SecUpgrade, SecStream, SecError, MuxUpgrade, MuxStream, MuxError>(
|
||||
self,
|
||||
tcp_config: libp2p_tcp::Config,
|
||||
security_upgrade: SecUpgrade,
|
||||
multiplexer_upgrade: MuxUpgrade,
|
||||
) -> Result<
|
||||
SwarmBuilder<$providerPascalCase, QuicPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
SecUpgrade::Error,
|
||||
>
|
||||
where
|
||||
SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
|
||||
SecError: std::error::Error + Send + Sync + 'static,
|
||||
SecUpgrade: IntoSecurityUpgrade<libp2p_tcp::$path::TcpStream>,
|
||||
SecUpgrade::Upgrade: InboundUpgrade<Negotiated<libp2p_tcp::$path::TcpStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundUpgrade<Negotiated<libp2p_tcp::$path::TcpStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
|
||||
<SecUpgrade::Upgrade as InboundUpgrade<Negotiated<libp2p_tcp::$path::TcpStream>>>::Future: Send,
|
||||
<SecUpgrade::Upgrade as OutboundUpgrade<Negotiated<libp2p_tcp::$path::TcpStream>>>::Future: Send,
|
||||
<<<SecUpgrade as IntoSecurityUpgrade<libp2p_tcp::$path::TcpStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<SecUpgrade as IntoSecurityUpgrade<libp2p_tcp::$path::TcpStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
MuxStream: StreamMuxer + Send + 'static,
|
||||
MuxStream::Substream: Send + 'static,
|
||||
MuxStream::Error: Send + Sync + 'static,
|
||||
MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
|
||||
MuxUpgrade::Upgrade: InboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
|
||||
<MuxUpgrade::Upgrade as InboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
<MuxUpgrade::Upgrade as OutboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
MuxError: std::error::Error + Send + Sync + 'static,
|
||||
<<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
{
|
||||
Ok(SwarmBuilder {
|
||||
phase: QuicPhase {
|
||||
transport: libp2p_tcp::$path::Transport::new(tcp_config)
|
||||
.upgrade(libp2p_core::upgrade::Version::V1Lazy)
|
||||
.authenticate(
|
||||
security_upgrade.into_security_upgrade(&self.keypair)?,
|
||||
)
|
||||
.multiplex(multiplexer_upgrade.into_multiplexer_upgrade())
|
||||
.map(|(p, c), _| (p, StreamMuxerBox::new(c))),
|
||||
},
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_tcp_builder!("async-std", super::provider::AsyncStd, async_io);
|
||||
impl_tcp_builder!("tokio", super::provider::Tokio, tokio);
|
||||
|
||||
impl<Provider> SwarmBuilder<Provider, TcpPhase> {
|
||||
pub(crate) fn without_tcp(
|
||||
self,
|
||||
) -> SwarmBuilder<Provider, QuicPhase<impl AuthenticatedMultiplexedTransport>> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: QuicPhase {
|
||||
transport: libp2p_core::transport::dummy::DummyTransport::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "quic", feature = "async-std"))]
|
||||
impl SwarmBuilder<super::provider::AsyncStd, TcpPhase> {
|
||||
pub fn with_quic(
|
||||
self,
|
||||
) -> SwarmBuilder<
|
||||
super::provider::AsyncStd,
|
||||
OtherTransportPhase<impl AuthenticatedMultiplexedTransport>,
|
||||
> {
|
||||
self.without_tcp().with_quic()
|
||||
}
|
||||
}
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "quic", feature = "tokio"))]
|
||||
impl SwarmBuilder<super::provider::Tokio, TcpPhase> {
|
||||
pub fn with_quic(
|
||||
self,
|
||||
) -> SwarmBuilder<
|
||||
super::provider::Tokio,
|
||||
OtherTransportPhase<impl AuthenticatedMultiplexedTransport>,
|
||||
> {
|
||||
self.without_tcp().with_quic()
|
||||
}
|
||||
}
|
||||
impl<Provider> SwarmBuilder<Provider, TcpPhase> {
|
||||
pub fn with_other_transport<
|
||||
Muxer: libp2p_core::muxing::StreamMuxer + Send + 'static,
|
||||
OtherTransport: Transport<Output = (libp2p_identity::PeerId, Muxer)> + Send + Unpin + 'static,
|
||||
R: TryIntoTransport<OtherTransport>,
|
||||
>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<
|
||||
SwarmBuilder<Provider, OtherTransportPhase<impl AuthenticatedMultiplexedTransport>>,
|
||||
R::Error,
|
||||
>
|
||||
where
|
||||
<OtherTransport as Transport>::Error: Send + Sync + 'static,
|
||||
<OtherTransport as Transport>::Dial: Send,
|
||||
<OtherTransport as Transport>::ListenerUpgrade: Send,
|
||||
<Muxer as libp2p_core::muxing::StreamMuxer>::Substream: Send,
|
||||
<Muxer as libp2p_core::muxing::StreamMuxer>::Error: Send + Sync,
|
||||
{
|
||||
self.without_tcp()
|
||||
.without_quic()
|
||||
.with_other_transport(constructor)
|
||||
}
|
||||
}
|
||||
macro_rules! impl_tcp_phase_with_websocket {
|
||||
($providerKebabCase:literal, $providerPascalCase:ty, $websocketStream:ty) => {
|
||||
#[cfg(all(feature = $providerKebabCase, not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
impl SwarmBuilder<$providerPascalCase, TcpPhase> {
|
||||
/// See [`SwarmBuilder::with_websocket`].
|
||||
pub async fn with_websocket <
|
||||
SecUpgrade,
|
||||
SecStream,
|
||||
SecError,
|
||||
MuxUpgrade,
|
||||
MuxStream,
|
||||
MuxError,
|
||||
> (
|
||||
self,
|
||||
security_upgrade: SecUpgrade,
|
||||
multiplexer_upgrade: MuxUpgrade,
|
||||
) -> Result<
|
||||
SwarmBuilder<
|
||||
$providerPascalCase,
|
||||
BandwidthLoggingPhase<impl AuthenticatedMultiplexedTransport, NoRelayBehaviour>,
|
||||
>,
|
||||
WebsocketError<SecUpgrade::Error>,
|
||||
>
|
||||
where
|
||||
SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
|
||||
SecError: std::error::Error + Send + Sync + 'static,
|
||||
SecUpgrade: IntoSecurityUpgrade<$websocketStream>,
|
||||
SecUpgrade::Upgrade: InboundUpgrade<Negotiated<$websocketStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + OutboundUpgrade<Negotiated<$websocketStream>, Output = (libp2p_identity::PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
|
||||
<SecUpgrade::Upgrade as InboundUpgrade<Negotiated<$websocketStream>>>::Future: Send,
|
||||
<SecUpgrade::Upgrade as OutboundUpgrade<Negotiated<$websocketStream>>>::Future: Send,
|
||||
<<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
MuxStream: StreamMuxer + Send + 'static,
|
||||
MuxStream::Substream: Send + 'static,
|
||||
MuxStream::Error: Send + Sync + 'static,
|
||||
MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
|
||||
MuxUpgrade::Upgrade: InboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
|
||||
<MuxUpgrade::Upgrade as InboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
<MuxUpgrade::Upgrade as OutboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
MuxError: std::error::Error + Send + Sync + 'static,
|
||||
<<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
{
|
||||
self.without_tcp()
|
||||
.without_quic()
|
||||
.without_any_other_transports()
|
||||
.without_dns()
|
||||
.without_relay()
|
||||
.with_websocket(security_upgrade, multiplexer_upgrade)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl_tcp_phase_with_websocket!(
|
||||
"async-std",
|
||||
super::provider::AsyncStd,
|
||||
rw_stream_sink::RwStreamSink<
|
||||
libp2p_websocket::BytesConnection<libp2p_tcp::async_io::TcpStream>,
|
||||
>
|
||||
);
|
||||
impl_tcp_phase_with_websocket!(
|
||||
"tokio",
|
||||
super::provider::Tokio,
|
||||
rw_stream_sink::RwStreamSink<libp2p_websocket::BytesConnection<libp2p_tcp::tokio::TcpStream>>
|
||||
);
|
188
libp2p/src/builder/phase/websocket.rs
Normal file
188
libp2p/src/builder/phase/websocket.rs
Normal file
@ -0,0 +1,188 @@
|
||||
use super::*;
|
||||
use crate::SwarmBuilder;
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
use libp2p_core::muxing::{StreamMuxer, StreamMuxerBox};
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
use libp2p_core::Transport;
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, UpgradeInfo};
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
use libp2p_identity::PeerId;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct WebsocketPhase<T, R> {
|
||||
pub(crate) transport: T,
|
||||
pub(crate) relay_behaviour: R,
|
||||
}
|
||||
|
||||
macro_rules! impl_websocket_builder {
|
||||
($providerKebabCase:literal, $providerPascalCase:ty, $dnsTcp:expr, $websocketStream:ty) => {
|
||||
/// Adds a websocket client transport.
|
||||
///
|
||||
/// Note that both `security_upgrade` and `multiplexer_upgrade` take function pointers,
|
||||
/// i.e. they take the function themselves (without the invocation via `()`), not the
|
||||
/// result of the function invocation. See example below.
|
||||
///
|
||||
/// ``` rust
|
||||
/// # use libp2p::SwarmBuilder;
|
||||
/// # use std::error::Error;
|
||||
/// # async fn build_swarm() -> Result<(), Box<dyn Error>> {
|
||||
/// let swarm = SwarmBuilder::with_new_identity()
|
||||
/// .with_tokio()
|
||||
/// .with_websocket(
|
||||
/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
|
||||
/// libp2p_yamux::Config::default,
|
||||
/// )
|
||||
/// .await?
|
||||
/// # ;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = $providerKebabCase, feature = "websocket"))]
|
||||
impl<T, R> SwarmBuilder<$providerPascalCase, WebsocketPhase<T, R>> {
|
||||
pub async fn with_websocket<
|
||||
SecUpgrade,
|
||||
SecStream,
|
||||
SecError,
|
||||
MuxUpgrade,
|
||||
MuxStream,
|
||||
MuxError,
|
||||
>(
|
||||
self,
|
||||
security_upgrade: SecUpgrade,
|
||||
multiplexer_upgrade: MuxUpgrade,
|
||||
) -> Result<
|
||||
SwarmBuilder<
|
||||
$providerPascalCase,
|
||||
BandwidthLoggingPhase<impl AuthenticatedMultiplexedTransport, R>,
|
||||
>,
|
||||
WebsocketError<SecUpgrade::Error>,
|
||||
>
|
||||
|
||||
where
|
||||
T: AuthenticatedMultiplexedTransport,
|
||||
|
||||
SecStream: futures::AsyncRead + futures::AsyncWrite + Unpin + Send + 'static,
|
||||
SecError: std::error::Error + Send + Sync + 'static,
|
||||
SecUpgrade: IntoSecurityUpgrade<$websocketStream>,
|
||||
SecUpgrade::Upgrade: InboundUpgrade<Negotiated<$websocketStream>, Output = (PeerId, SecStream), Error = SecError> + OutboundUpgrade<Negotiated<$websocketStream>, Output = (PeerId, SecStream), Error = SecError> + Clone + Send + 'static,
|
||||
<SecUpgrade::Upgrade as InboundUpgrade<Negotiated<$websocketStream>>>::Future: Send,
|
||||
<SecUpgrade::Upgrade as OutboundUpgrade<Negotiated<$websocketStream>>>::Future: Send,
|
||||
<<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<SecUpgrade as IntoSecurityUpgrade<$websocketStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
MuxStream: StreamMuxer + Send + 'static,
|
||||
MuxStream::Substream: Send + 'static,
|
||||
MuxStream::Error: Send + Sync + 'static,
|
||||
MuxUpgrade: IntoMultiplexerUpgrade<SecStream>,
|
||||
MuxUpgrade::Upgrade: InboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + OutboundUpgrade<Negotiated<SecStream>, Output = MuxStream, Error = MuxError> + Clone + Send + 'static,
|
||||
<MuxUpgrade::Upgrade as InboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
<MuxUpgrade::Upgrade as OutboundUpgrade<Negotiated<SecStream>>>::Future: Send,
|
||||
MuxError: std::error::Error + Send + Sync + 'static,
|
||||
<<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::InfoIter as IntoIterator>::IntoIter: Send,
|
||||
<<MuxUpgrade as IntoMultiplexerUpgrade<SecStream>>::Upgrade as UpgradeInfo>::Info: Send,
|
||||
|
||||
{
|
||||
let security_upgrade = security_upgrade.into_security_upgrade(&self.keypair)
|
||||
.map_err(WebsocketErrorInner::SecurityUpgrade)?;
|
||||
let websocket_transport = libp2p_websocket::WsConfig::new(
|
||||
$dnsTcp.await.map_err(WebsocketErrorInner::Dns)?,
|
||||
)
|
||||
.upgrade(libp2p_core::upgrade::Version::V1Lazy)
|
||||
.authenticate(security_upgrade)
|
||||
.multiplex(multiplexer_upgrade.into_multiplexer_upgrade())
|
||||
.map(|(p, c), _| (p, StreamMuxerBox::new(c)));
|
||||
|
||||
Ok(SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: BandwidthLoggingPhase {
|
||||
transport: websocket_transport
|
||||
.or_transport(self.phase.transport)
|
||||
.map(|either, _| either.into_inner()),
|
||||
relay_behaviour: self.phase.relay_behaviour,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_websocket_builder!(
|
||||
"async-std",
|
||||
super::provider::AsyncStd,
|
||||
libp2p_dns::async_std::Transport::system(libp2p_tcp::async_io::Transport::new(
|
||||
libp2p_tcp::Config::default(),
|
||||
)),
|
||||
rw_stream_sink::RwStreamSink<
|
||||
libp2p_websocket::BytesConnection<libp2p_tcp::async_io::TcpStream>,
|
||||
>
|
||||
);
|
||||
impl_websocket_builder!(
|
||||
"tokio",
|
||||
super::provider::Tokio,
|
||||
// Note this is an unnecessary await for Tokio Websocket (i.e. tokio dns) in order to be consistent
|
||||
// with above AsyncStd construction.
|
||||
futures::future::ready(libp2p_dns::tokio::Transport::system(
|
||||
libp2p_tcp::tokio::Transport::new(libp2p_tcp::Config::default())
|
||||
)),
|
||||
rw_stream_sink::RwStreamSink<libp2p_websocket::BytesConnection<libp2p_tcp::tokio::TcpStream>>
|
||||
);
|
||||
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport, R>
|
||||
SwarmBuilder<Provider, WebsocketPhase<T, R>>
|
||||
{
|
||||
pub(crate) fn without_websocket(self) -> SwarmBuilder<Provider, BandwidthLoggingPhase<T, R>> {
|
||||
SwarmBuilder {
|
||||
keypair: self.keypair,
|
||||
phantom: PhantomData,
|
||||
phase: BandwidthLoggingPhase {
|
||||
relay_behaviour: self.phase.relay_behaviour,
|
||||
transport: self.phase.transport,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shortcuts
|
||||
#[cfg(feature = "relay")]
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<Provider, WebsocketPhase<T, libp2p_relay::client::Behaviour>>
|
||||
{
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair, libp2p_relay::client::Behaviour) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
self.without_websocket()
|
||||
.without_bandwidth_logging()
|
||||
.with_behaviour(constructor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Provider, T: AuthenticatedMultiplexedTransport>
|
||||
SwarmBuilder<Provider, WebsocketPhase<T, NoRelayBehaviour>>
|
||||
{
|
||||
pub fn with_behaviour<B, R: TryIntoBehaviour<B>>(
|
||||
self,
|
||||
constructor: impl FnOnce(&libp2p_identity::Keypair) -> R,
|
||||
) -> Result<SwarmBuilder<Provider, SwarmPhase<T, B>>, R::Error> {
|
||||
self.without_websocket()
|
||||
.without_bandwidth_logging()
|
||||
.with_behaviour(constructor)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error(transparent)]
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
pub struct WebsocketError<Sec>(#[from] WebsocketErrorInner<Sec>);
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
|
||||
enum WebsocketErrorInner<Sec> {
|
||||
#[error("SecurityUpgrade")]
|
||||
SecurityUpgrade(Sec),
|
||||
#[cfg(feature = "dns")]
|
||||
#[error("Dns")]
|
||||
Dns(#[from] std::io::Error),
|
||||
}
|
113
libp2p/src/builder/select_security.rs
Normal file
113
libp2p/src/builder/select_security.rs
Normal file
@ -0,0 +1,113 @@
|
||||
// Copyright 2023 Protocol Labs.
|
||||
// Copyright 2018 Parity Technologies (UK) Ltd.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use either::Either;
|
||||
use futures::future::MapOk;
|
||||
use futures::{future, TryFutureExt};
|
||||
use libp2p_core::either::EitherFuture;
|
||||
use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
|
||||
use libp2p_identity::PeerId;
|
||||
use std::iter::{Chain, Map};
|
||||
|
||||
/// Upgrade that combines two upgrades into one. Supports all the protocols supported by either
|
||||
/// sub-upgrade.
|
||||
///
|
||||
/// The protocols supported by the first element have a higher priority.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SelectSecurityUpgrade<A, B>(A, B);
|
||||
|
||||
impl<A, B> SelectSecurityUpgrade<A, B> {
|
||||
/// Combines two upgrades into an `SelectUpgrade`.
|
||||
///
|
||||
/// The protocols supported by the first element have a higher priority.
|
||||
pub fn new(a: A, b: B) -> Self {
|
||||
SelectSecurityUpgrade(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> UpgradeInfo for SelectSecurityUpgrade<A, B>
|
||||
where
|
||||
A: UpgradeInfo,
|
||||
B: UpgradeInfo,
|
||||
{
|
||||
type Info = Either<A::Info, B::Info>;
|
||||
type InfoIter = Chain<
|
||||
Map<<A::InfoIter as IntoIterator>::IntoIter, fn(A::Info) -> Self::Info>,
|
||||
Map<<B::InfoIter as IntoIterator>::IntoIter, fn(B::Info) -> Self::Info>,
|
||||
>;
|
||||
|
||||
fn protocol_info(&self) -> Self::InfoIter {
|
||||
let a = self
|
||||
.0
|
||||
.protocol_info()
|
||||
.into_iter()
|
||||
.map(Either::Left as fn(A::Info) -> _);
|
||||
let b = self
|
||||
.1
|
||||
.protocol_info()
|
||||
.into_iter()
|
||||
.map(Either::Right as fn(B::Info) -> _);
|
||||
|
||||
a.chain(b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, A, B, TA, TB, EA, EB> InboundUpgrade<C> for SelectSecurityUpgrade<A, B>
|
||||
where
|
||||
A: InboundUpgrade<C, Output = (PeerId, TA), Error = EA>,
|
||||
B: InboundUpgrade<C, Output = (PeerId, TB), Error = EB>,
|
||||
{
|
||||
type Output = (PeerId, future::Either<TA, TB>);
|
||||
type Error = Either<EA, EB>;
|
||||
type Future = MapOk<
|
||||
EitherFuture<A::Future, B::Future>,
|
||||
fn(future::Either<(PeerId, TA), (PeerId, TB)>) -> (PeerId, future::Either<TA, TB>),
|
||||
>;
|
||||
|
||||
fn upgrade_inbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
match info {
|
||||
Either::Left(info) => EitherFuture::First(self.0.upgrade_inbound(sock, info)),
|
||||
Either::Right(info) => EitherFuture::Second(self.1.upgrade_inbound(sock, info)),
|
||||
}
|
||||
.map_ok(future::Either::factor_first)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, A, B, TA, TB, EA, EB> OutboundUpgrade<C> for SelectSecurityUpgrade<A, B>
|
||||
where
|
||||
A: OutboundUpgrade<C, Output = (PeerId, TA), Error = EA>,
|
||||
B: OutboundUpgrade<C, Output = (PeerId, TB), Error = EB>,
|
||||
{
|
||||
type Output = (PeerId, future::Either<TA, TB>);
|
||||
type Error = Either<EA, EB>;
|
||||
type Future = MapOk<
|
||||
EitherFuture<A::Future, B::Future>,
|
||||
fn(future::Either<(PeerId, TA), (PeerId, TB)>) -> (PeerId, future::Either<TA, TB>),
|
||||
>;
|
||||
|
||||
fn upgrade_outbound(self, sock: C, info: Self::Info) -> Self::Future {
|
||||
match info {
|
||||
Either::Left(info) => EitherFuture::First(self.0.upgrade_outbound(sock, info)),
|
||||
Either::Right(info) => EitherFuture::Second(self.1.upgrade_outbound(sock, info)),
|
||||
}
|
||||
.map_ok(future::Either::factor_first)
|
||||
}
|
||||
}
|
@ -22,8 +22,9 @@
|
||||
//!
|
||||
//! To learn more about the general libp2p multi-language framework visit <https://libp2p.io>.
|
||||
//!
|
||||
//! To get started with this libp2p implementation in Rust, please take a look at the [`tutorials`].
|
||||
//! Further examples can be found in the [examples] directory.
|
||||
//! To get started with this libp2p implementation in Rust, please take a look
|
||||
//! at the [`tutorials`]. Further examples can be found in the
|
||||
//! [examples] directory.
|
||||
//!
|
||||
//! [examples]: https://github.com/libp2p/rust-libp2p/tree/master/examples
|
||||
|
||||
@ -157,6 +158,7 @@ pub use libp2p_webtransport_websys as webtransport_websys;
|
||||
#[doc(inline)]
|
||||
pub use libp2p_yamux as yamux;
|
||||
|
||||
mod builder;
|
||||
mod transport_ext;
|
||||
|
||||
pub mod bandwidth;
|
||||
@ -164,6 +166,7 @@ pub mod bandwidth;
|
||||
#[cfg(doc)]
|
||||
pub mod tutorials;
|
||||
|
||||
pub use self::builder::SwarmBuilder;
|
||||
pub use self::core::{
|
||||
transport::TransportError,
|
||||
upgrade::{InboundUpgrade, OutboundUpgrade},
|
||||
@ -187,6 +190,7 @@ pub use libp2p_swarm::{Stream, StreamProtocol};
|
||||
///
|
||||
/// > **Note**: This `Transport` is not suitable for production usage, as its implementation
|
||||
/// > reserves the right to support additional protocols or remove deprecated protocols.
|
||||
#[deprecated(note = "Use `libp2p::SwarmBuilder` instead.")]
|
||||
#[cfg(all(
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "tcp",
|
||||
@ -232,6 +236,7 @@ pub async fn development_transport(
|
||||
///
|
||||
/// > **Note**: This `Transport` is not suitable for production usage, as its implementation
|
||||
/// > reserves the right to support additional protocols or remove deprecated protocols.
|
||||
#[deprecated(note = "Use `libp2p::SwarmBuilder` instead.")]
|
||||
#[cfg(all(
|
||||
not(target_arch = "wasm32"),
|
||||
feature = "tcp",
|
||||
|
@ -55,10 +55,10 @@
|
||||
//! edition = "2021"
|
||||
//!
|
||||
//! [dependencies]
|
||||
//! libp2p = { version = "0.50", features = ["tcp", "dns", "async-std", "noise", "yamux", "websocket", "ping", "macros"] }
|
||||
//! futures = "0.3.21"
|
||||
//! libp2p = { version = "0.52", features = ["tcp", "dns", "async-std", "noise", "yamux", "websocket", "ping", "macros"] }
|
||||
//! futures = "0.3"
|
||||
//! env_logger = "0.10.0"
|
||||
//! async-std = { version = "1.12.0", features = ["attributes"] }
|
||||
//! async-std = { version = "1.12", features = ["attributes"] }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Network identity
|
||||
@ -71,38 +71,27 @@
|
||||
//! derived from their public key. Now, replace the contents of main.rs by:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use libp2p::{identity, PeerId};
|
||||
//! use std::error::Error;
|
||||
//!
|
||||
//! #[async_std::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! let local_key = identity::Keypair::generate_ed25519();
|
||||
//! let local_peer_id = PeerId::from(local_key.public());
|
||||
//! println!("Local peer id: {local_peer_id:?}");
|
||||
//! env_logger::init();
|
||||
//!
|
||||
//! let mut swarm = libp2p::SwarmBuilder::with_new_identity();
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Go ahead and build and run the above code with: `cargo run`. A unique
|
||||
//! [`PeerId`](crate::PeerId) should be displayed.
|
||||
//! Go ahead and build and run the above code with: `cargo run`. Nothing happening thus far.
|
||||
//!
|
||||
//! ## Transport
|
||||
//!
|
||||
//! Next up we need to construct a transport. A transport in libp2p provides
|
||||
//! connection-oriented communication channels (e.g. TCP) as well as upgrades
|
||||
//! on top of those like authentication and encryption protocols. Technically,
|
||||
//! a libp2p transport is anything that implements the [`Transport`] trait.
|
||||
//!
|
||||
//! Instead of constructing a transport ourselves for this tutorial, we use the
|
||||
//! convenience function [`development_transport`](crate::development_transport)
|
||||
//! that creates a TCP transport with [`noise`](crate::noise) for authenticated
|
||||
//! encryption.
|
||||
//!
|
||||
//! Furthermore, [`development_transport`] builds a multiplexed transport,
|
||||
//! whereby multiple logical substreams can coexist on the same underlying (TCP)
|
||||
//! connection. For further details on substream multiplexing, take a look at
|
||||
//! [`crate::core::muxing`] and [`yamux`](crate::yamux).
|
||||
//! Next up we need to construct a transport. Each transport in libp2p provides encrypted streams.
|
||||
//! E.g. combining TCP to establish connections, TLS to encrypt these connections and Yamux to run
|
||||
//! one or more streams on a connection. Another libp2p transport is QUIC, providing encrypted
|
||||
//! streams out-of-the-box. We will stick to TCP for now. Each of these implement the [`Transport`]
|
||||
//! trait.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use libp2p::{identity, PeerId};
|
||||
@ -110,11 +99,15 @@
|
||||
//!
|
||||
//! #[async_std::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! let local_key = identity::Keypair::generate_ed25519();
|
||||
//! let local_peer_id = PeerId::from(local_key.public());
|
||||
//! println!("Local peer id: {local_peer_id:?}");
|
||||
//! env_logger::init();
|
||||
//!
|
||||
//! let transport = libp2p::development_transport(local_key).await?;
|
||||
//! let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
//! .with_async_std()
|
||||
//! .with_tcp(
|
||||
//! libp2p_tcp::Config::default(),
|
||||
//! libp2p_tls::Config::new,
|
||||
//! libp2p_yamux::Config::default,
|
||||
//! )?;
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
@ -125,20 +118,20 @@
|
||||
//! Now it is time to look at another core trait of rust-libp2p: the
|
||||
//! [`NetworkBehaviour`]. While the previously introduced trait [`Transport`]
|
||||
//! defines _how_ to send bytes on the network, a [`NetworkBehaviour`] defines
|
||||
//! _what_ bytes to send on the network.
|
||||
//! _what_ bytes and to _whom_ to send on the network.
|
||||
//!
|
||||
//! To make this more concrete, let's take a look at a simple implementation of
|
||||
//! the [`NetworkBehaviour`] trait: the [`ping::Behaviour`](crate::ping::Behaviour).
|
||||
//! As you might have guessed, similar to the good old `ping` network tool,
|
||||
//! As you might have guessed, similar to the good old ICMP `ping` network tool,
|
||||
//! libp2p [`ping::Behaviour`](crate::ping::Behaviour) sends a ping to a peer and expects
|
||||
//! to receive a pong in turn. The [`ping::Behaviour`](crate::ping::Behaviour) does not care _how_
|
||||
//! the ping and pong messages are sent on the network, whether they are sent via
|
||||
//! TCP, whether they are encrypted via [noise](crate::noise) or just in
|
||||
//! [plaintext](crate::plaintext). It only cares about _what_ messages are sent
|
||||
//! on the network.
|
||||
//! [plaintext](crate::plaintext). It only cares about _what_ messages and to _whom_ to sent on the
|
||||
//! network.
|
||||
//!
|
||||
//! The two traits [`Transport`] and [`NetworkBehaviour`] allow us to cleanly
|
||||
//! separate _how_ to send bytes from _what_ bytes to send.
|
||||
//! separate _how_ to send bytes from _what_ bytes and to _whom_ to send.
|
||||
//!
|
||||
//! With the above in mind, let's extend our example, creating a [`ping::Behaviour`](crate::ping::Behaviour) at the end:
|
||||
//!
|
||||
@ -149,13 +142,16 @@
|
||||
//!
|
||||
//! #[async_std::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! let local_key = identity::Keypair::generate_ed25519();
|
||||
//! let local_peer_id = PeerId::from(local_key.public());
|
||||
//! println!("Local peer id: {local_peer_id:?}");
|
||||
//! env_logger::init();
|
||||
//!
|
||||
//! let transport = libp2p::development_transport(local_key).await?;
|
||||
//!
|
||||
//! let behaviour = ping::Behaviour::default();
|
||||
//! let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
//! .with_async_std()
|
||||
//! .with_tcp(
|
||||
//! libp2p_tcp::Config::default(),
|
||||
//! libp2p_tls::Config::new,
|
||||
//! libp2p_yamux::Config::default,
|
||||
//! )?
|
||||
//! .with_behaviour(|_| ping::Behaviour::default())?;
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
@ -163,16 +159,10 @@
|
||||
//!
|
||||
//! ## Swarm
|
||||
//!
|
||||
//! Now that we have a [`Transport`] and a [`NetworkBehaviour`], we need
|
||||
//! something that connects the two, allowing both to make progress. This job is
|
||||
//! carried out by a [`Swarm`]. Put simply, a [`Swarm`] drives both a
|
||||
//! [`Transport`] and a [`NetworkBehaviour`] forward, passing commands from the
|
||||
//! [`NetworkBehaviour`] to the [`Transport`] as well as events from the
|
||||
//! [`Transport`] to the [`NetworkBehaviour`]. As you can see, after [`Swarm`] initialization, we
|
||||
//! removed the print of the local [`PeerId`](crate::PeerId) because every time a [`Swarm`] is
|
||||
//! created, it prints the local [`PeerId`](crate::PeerId) in the logs at the INFO level. In order
|
||||
//! to continue to see the local [`PeerId`](crate::PeerId) you must initialize the logger
|
||||
//! (In our example, `env_logger` is used)
|
||||
//! Now that we have a [`Transport`] and a [`NetworkBehaviour`], we can build the [`Swarm`]
|
||||
//! which connects the two, allowing both to make progress. Put simply, a [`Swarm`] drives both a
|
||||
//! [`Transport`] and a [`NetworkBehaviour`] forward, passing commands from the [`NetworkBehaviour`]
|
||||
//! to the [`Transport`] as well as events from the [`Transport`] to the [`NetworkBehaviour`].
|
||||
//!
|
||||
//! ```rust
|
||||
//! use libp2p::swarm::{NetworkBehaviour, SwarmBuilder};
|
||||
@ -182,14 +172,16 @@
|
||||
//! #[async_std::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! env_logger::init();
|
||||
//! let local_key = identity::Keypair::generate_ed25519();
|
||||
//! let local_peer_id = PeerId::from(local_key.public());
|
||||
//!
|
||||
//! let transport = libp2p::development_transport(local_key).await?;
|
||||
//!
|
||||
//! let behaviour = ping::Behaviour::default();
|
||||
//!
|
||||
//! let mut swarm = SwarmBuilder::with_async_std_executor(transport, behaviour, local_peer_id).build();
|
||||
//! let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
//! .with_async_std()
|
||||
//! .with_tcp(
|
||||
//! libp2p_tcp::Config::default(),
|
||||
//! libp2p_tls::Config::new,
|
||||
//! libp2p_yamux::Config::default,
|
||||
//! )?
|
||||
//! .with_behaviour(|_| ping::Behaviour::default())?
|
||||
//! .build();
|
||||
//!
|
||||
//! Ok(())
|
||||
//! }
|
||||
@ -213,17 +205,17 @@
|
||||
//!
|
||||
//! #[async_std::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! use std::time::Duration;
|
||||
//! let local_key = identity::Keypair::generate_ed25519();
|
||||
//! let local_peer_id = PeerId::from(local_key.public());
|
||||
//! println!("Local peer id: {local_peer_id:?}");
|
||||
//! env_logger::init();
|
||||
//!
|
||||
//! let transport = libp2p::development_transport(local_key).await?;
|
||||
//!
|
||||
//! let behaviour = ping::Behaviour::default();
|
||||
//!
|
||||
//! let mut swarm = SwarmBuilder::with_async_std_executor(transport, behaviour, local_peer_id)
|
||||
//! .idle_connection_timeout(Duration::from_secs(30)) // Allows us to observe pings for 30 seconds.
|
||||
//! let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
//! .with_async_std()
|
||||
//! .with_tcp(
|
||||
//! libp2p_tcp::Config::default(),
|
||||
//! libp2p_tls::Config::new,
|
||||
//! libp2p_yamux::Config::default,
|
||||
//! )?
|
||||
//! .with_behaviour(|_| ping::Behaviour::default())?
|
||||
//! .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(30))) // Allows us to observe pings for 30 seconds.
|
||||
//! .build();
|
||||
//!
|
||||
//! Ok(())
|
||||
@ -264,16 +256,15 @@
|
||||
//!
|
||||
//! #[async_std::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! env_logger::init();
|
||||
//! let local_key = identity::Keypair::generate_ed25519();
|
||||
//! let local_peer_id = PeerId::from(local_key.public());
|
||||
//!
|
||||
//! let transport = libp2p::development_transport(local_key).await?;
|
||||
//!
|
||||
//! let behaviour = ping::Behaviour::default();
|
||||
//!
|
||||
//! let mut swarm = SwarmBuilder::with_async_std_executor(transport, behaviour, local_peer_id)
|
||||
//! .idle_connection_timeout(Duration::from_secs(30)) // Allows us to observe pings for 30 seconds.
|
||||
//! let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
//! .with_async_std()
|
||||
//! .with_tcp(
|
||||
//! libp2p_tcp::Config::default(),
|
||||
//! libp2p_tls::Config::new,
|
||||
//! libp2p_yamux::Config::default,
|
||||
//! )?
|
||||
//! .with_behaviour(|_| ping::Behaviour::default())?
|
||||
//! .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(30))) // Allows us to observe pings for 30 seconds.
|
||||
//! .build();
|
||||
//!
|
||||
//! // Tell the swarm to listen on all interfaces and a random, OS-assigned
|
||||
@ -307,16 +298,15 @@
|
||||
//!
|
||||
//! #[async_std::main]
|
||||
//! async fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! env_logger::init();
|
||||
//! let local_key = identity::Keypair::generate_ed25519();
|
||||
//! let local_peer_id = PeerId::from(local_key.public());
|
||||
//!
|
||||
//! let transport = libp2p::development_transport(local_key).await?;
|
||||
//!
|
||||
//! let behaviour = ping::Behaviour::default();
|
||||
//!
|
||||
//! let mut swarm = SwarmBuilder::with_async_std_executor(transport, behaviour, local_peer_id)
|
||||
//! .idle_connection_timeout(Duration::from_secs(30)) // Allows us to observe pings for 30 seconds.
|
||||
//! let mut swarm = libp2p::SwarmBuilder::with_new_identity()
|
||||
//! .with_async_std()
|
||||
//! .with_tcp(
|
||||
//! libp2p_tcp::Config::default(),
|
||||
//! libp2p_tls::Config::new,
|
||||
//! libp2p_yamux::Config::default,
|
||||
//! )?
|
||||
//! .with_behaviour(|_| ping::Behaviour::default())?
|
||||
//! .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(30))) // Allows us to observe pings for 30 seconds.
|
||||
//! .build();
|
||||
//!
|
||||
//! // Tell the swarm to listen on all interfaces and a random, OS-assigned
|
||||
|
@ -17,7 +17,7 @@ futures-util = { version = "0.3.28" }
|
||||
futures-timer = "3.0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1.29.1", features = ["macros", "rt"] }
|
||||
tokio = { version = "1.33.0", features = ["macros", "rt"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
@ -1,27 +1,18 @@
|
||||
use base64::Engine;
|
||||
use clap::Parser;
|
||||
use futures::future::Either;
|
||||
use futures::stream::StreamExt;
|
||||
use futures_timer::Delay;
|
||||
use libp2p::core::muxing::StreamMuxerBox;
|
||||
use libp2p::core::upgrade;
|
||||
use libp2p::dns;
|
||||
use libp2p::identify;
|
||||
use libp2p::identity;
|
||||
use libp2p::identity::PeerId;
|
||||
use libp2p::kad;
|
||||
use libp2p::metrics::{Metrics, Recorder};
|
||||
use libp2p::noise;
|
||||
use libp2p::quic;
|
||||
use libp2p::swarm::{SwarmBuilder, SwarmEvent};
|
||||
use libp2p::swarm::SwarmEvent;
|
||||
use libp2p::tcp;
|
||||
use libp2p::yamux;
|
||||
use libp2p::Transport;
|
||||
use libp2p::{identify, noise, yamux};
|
||||
use log::{debug, info, warn};
|
||||
use prometheus_client::metrics::info::Info;
|
||||
use prometheus_client::registry::Registry;
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::task::Poll;
|
||||
@ -62,7 +53,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
let config = Zeroizing::new(config::Config::from_file(opt.config.as_path())?);
|
||||
|
||||
let (local_peer_id, local_keypair) = {
|
||||
let local_keypair = {
|
||||
let keypair = identity::Keypair::from_protobuf_encoding(&Zeroizing::new(
|
||||
base64::engine::general_purpose::STANDARD
|
||||
.decode(config.identity.priv_key.as_bytes())?,
|
||||
@ -75,37 +66,25 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
"Expect peer id derived from private key and peer id retrieved from config to match."
|
||||
);
|
||||
|
||||
(peer_id, keypair)
|
||||
keypair
|
||||
};
|
||||
|
||||
let transport = {
|
||||
let tcp_transport =
|
||||
tcp::tokio::Transport::new(tcp::Config::new().port_reuse(true).nodelay(true))
|
||||
.upgrade(upgrade::Version::V1)
|
||||
.authenticate(noise::Config::new(&local_keypair)?)
|
||||
.multiplex(yamux::Config::default())
|
||||
.timeout(Duration::from_secs(20));
|
||||
|
||||
let quic_transport = quic::tokio::Transport::new(quic::Config::new(&local_keypair));
|
||||
|
||||
dns::tokio::Transport::system(libp2p::core::transport::OrTransport::new(
|
||||
quic_transport,
|
||||
tcp_transport,
|
||||
))?
|
||||
.map(|either_output, _| match either_output {
|
||||
Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
|
||||
Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
|
||||
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(local_keypair)
|
||||
.with_tokio()
|
||||
.with_tcp(
|
||||
tcp::Config::default().port_reuse(true).nodelay(true),
|
||||
noise::Config::new,
|
||||
yamux::Config::default,
|
||||
)?
|
||||
.with_quic_config(|mut cfg| {
|
||||
cfg.support_draft_29 = true;
|
||||
cfg
|
||||
})
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
|
||||
.boxed()
|
||||
};
|
||||
|
||||
let behaviour = behaviour::Behaviour::new(
|
||||
local_keypair.public(),
|
||||
opt.enable_kademlia,
|
||||
opt.enable_autonat,
|
||||
);
|
||||
let mut swarm = SwarmBuilder::with_tokio_executor(transport, behaviour, local_peer_id).build();
|
||||
.with_dns()?
|
||||
.with_behaviour(|key| {
|
||||
behaviour::Behaviour::new(key.public(), opt.enable_kademlia, opt.enable_autonat)
|
||||
})?
|
||||
.build();
|
||||
|
||||
if config.addresses.swarm.is_empty() {
|
||||
warn!("No listen addresses configured.");
|
||||
|
@ -26,7 +26,7 @@ use libp2p_identity as identity;
|
||||
use libp2p_identity::PeerId;
|
||||
use libp2p_plaintext as plaintext;
|
||||
use libp2p_relay as relay;
|
||||
use libp2p_swarm::{NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent};
|
||||
use libp2p_swarm::{Config, NetworkBehaviour, Swarm, SwarmEvent};
|
||||
use libp2p_swarm_test::SwarmExt as _;
|
||||
use std::time::Duration;
|
||||
|
||||
@ -123,15 +123,15 @@ fn build_client() -> Swarm<Client> {
|
||||
.multiplex(libp2p_yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
SwarmBuilder::without_executor(
|
||||
Swarm::new(
|
||||
transport,
|
||||
Client {
|
||||
relay: behaviour,
|
||||
dcutr: dcutr::Behaviour::new(local_peer_id),
|
||||
},
|
||||
local_peer_id,
|
||||
Config::with_async_std_executor(),
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
#[derive(NetworkBehaviour)]
|
||||
|
@ -16,7 +16,7 @@ wasm-bindgen = ["getrandom/js", "instant/wasm-bindgen"]
|
||||
[dependencies]
|
||||
asynchronous-codec = "0.6"
|
||||
base64 = "0.21.4"
|
||||
byteorder = "1.3.4"
|
||||
byteorder = "1.5.0"
|
||||
bytes = "1.5"
|
||||
either = "1.9"
|
||||
fnv = "1.0.7"
|
||||
|
@ -37,7 +37,7 @@ use libp2p_core::{
|
||||
use libp2p_identity as identity;
|
||||
use libp2p_identity::PeerId;
|
||||
use libp2p_noise as noise;
|
||||
use libp2p_swarm::{ConnectionId, Swarm, SwarmBuilder, SwarmEvent};
|
||||
use libp2p_swarm::{self as swarm, ConnectionId, Swarm, SwarmEvent};
|
||||
use libp2p_yamux as yamux;
|
||||
use quickcheck::*;
|
||||
use rand::{random, rngs::StdRng, thread_rng, Rng, SeedableRng};
|
||||
@ -67,7 +67,12 @@ fn build_node_with_config(cfg: Config) -> (Multiaddr, TestSwarm) {
|
||||
let store = MemoryStore::new(local_id);
|
||||
let behaviour = Behaviour::with_config(local_id, store, cfg);
|
||||
|
||||
let mut swarm = SwarmBuilder::without_executor(transport, behaviour, local_id).build();
|
||||
let mut swarm = Swarm::new(
|
||||
transport,
|
||||
behaviour,
|
||||
local_id,
|
||||
swarm::Config::with_async_std_executor(),
|
||||
);
|
||||
|
||||
let address: Multiaddr = Protocol::Memory(random::<u64>()).into();
|
||||
swarm.listen_on(address.clone()).unwrap();
|
||||
|
@ -22,7 +22,7 @@ log = "0.4.20"
|
||||
rand = "0.8.3"
|
||||
smallvec = "1.11.1"
|
||||
socket2 = { version = "0.5.4", features = ["all"] }
|
||||
tokio = { version = "1.32", default-features = false, features = ["net", "time"], optional = true}
|
||||
tokio = { version = "1.33", default-features = false, features = ["net", "time"], optional = true}
|
||||
trust-dns-proto = { version = "0.23.0", default-features = false, features = ["mdns"] }
|
||||
void = "1.0.2"
|
||||
|
||||
@ -37,7 +37,7 @@ libp2p-noise = { workspace = true }
|
||||
libp2p-swarm = { workspace = true, features = ["tokio", "async-std"] }
|
||||
libp2p-tcp = { workspace = true, features = ["tokio", "async-io"] }
|
||||
libp2p-yamux = { workspace = true }
|
||||
tokio = { version = "1.32", default-features = false, features = ["macros", "rt", "rt-multi-thread", "time"] }
|
||||
tokio = { version = "1.33", default-features = false, features = ["macros", "rt", "rt-multi-thread", "time"] }
|
||||
libp2p-swarm-test = { path = "../../swarm-test" }
|
||||
|
||||
[[test]]
|
||||
|
@ -30,7 +30,7 @@ log = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
tokio = { version = "1.33.0", features = ["full"] }
|
||||
void = "1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@ -31,7 +31,7 @@ use libp2p_core::{
|
||||
};
|
||||
use libp2p_identity::PeerId;
|
||||
use libp2p_perf::{Run, RunDuration, RunParams};
|
||||
use libp2p_swarm::{NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent};
|
||||
use libp2p_swarm::{Config, NetworkBehaviour, Swarm, SwarmEvent};
|
||||
use log::{error, info};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -414,11 +414,15 @@ async fn swarm<B: NetworkBehaviour + Default>() -> Result<Swarm<B>> {
|
||||
.boxed()
|
||||
};
|
||||
|
||||
Ok(
|
||||
SwarmBuilder::with_tokio_executor(transport, Default::default(), local_peer_id)
|
||||
.substream_upgrade_protocol_override(upgrade::Version::V1Lazy)
|
||||
.build(),
|
||||
)
|
||||
let swarm = Swarm::new(
|
||||
transport,
|
||||
Default::default(),
|
||||
local_peer_id,
|
||||
Config::with_tokio_executor()
|
||||
.with_substream_upgrade_protocol_override(upgrade::Version::V1Lazy),
|
||||
);
|
||||
|
||||
Ok(swarm)
|
||||
}
|
||||
|
||||
async fn connect(
|
||||
|
@ -33,7 +33,7 @@ use libp2p_identity::PeerId;
|
||||
use libp2p_ping as ping;
|
||||
use libp2p_plaintext as plaintext;
|
||||
use libp2p_relay as relay;
|
||||
use libp2p_swarm::{NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent};
|
||||
use libp2p_swarm::{Config, NetworkBehaviour, Swarm, SwarmEvent};
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
@ -310,7 +310,7 @@ fn build_relay() -> Swarm<Relay> {
|
||||
|
||||
let transport = upgrade_transport(MemoryTransport::default().boxed(), &local_key);
|
||||
|
||||
SwarmBuilder::with_async_std_executor(
|
||||
Swarm::new(
|
||||
transport,
|
||||
Relay {
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
@ -323,8 +323,8 @@ fn build_relay() -> Swarm<Relay> {
|
||||
),
|
||||
},
|
||||
local_peer_id,
|
||||
Config::with_async_std_executor(),
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
fn build_client() -> Swarm<Client> {
|
||||
@ -337,15 +337,15 @@ fn build_client() -> Swarm<Client> {
|
||||
&local_key,
|
||||
);
|
||||
|
||||
SwarmBuilder::with_async_std_executor(
|
||||
Swarm::new(
|
||||
transport,
|
||||
Client {
|
||||
ping: ping::Behaviour::new(ping::Config::new()),
|
||||
relay: behaviour,
|
||||
},
|
||||
local_peer_id,
|
||||
Config::with_async_std_executor(),
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
fn upgrade_transport<StreamSink>(
|
||||
|
@ -37,7 +37,7 @@ libp2p-identify = { workspace = true }
|
||||
libp2p-yamux = { workspace = true }
|
||||
libp2p-tcp = { workspace = true, features = ["tokio"] }
|
||||
rand = "0.8"
|
||||
tokio = { version = "1.32", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] }
|
||||
tokio = { version = "1.33", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] }
|
||||
libp2p-swarm-test = { path = "../../swarm-test" }
|
||||
|
||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||
|
@ -18,7 +18,7 @@ libp2p-core = { workspace = true }
|
||||
libp2p-swarm = { workspace = true }
|
||||
log = "0.4.19"
|
||||
void = "1.0.2"
|
||||
tokio = { version = "1.29", default-features = false, features = ["rt"], optional = true }
|
||||
tokio = { version = "1.33", default-features = false, features = ["rt"], optional = true }
|
||||
|
||||
[features]
|
||||
tokio = ["igd-next/aio_tokio", "dep:tokio"]
|
||||
|
@ -16,7 +16,7 @@ async-trait = "0.1.73"
|
||||
libp2p-core = { workspace = true }
|
||||
libp2p-identity = { workspace = true, features = ["rand"] }
|
||||
libp2p-plaintext = { workspace = true }
|
||||
libp2p-swarm = { workspace = true }
|
||||
libp2p-swarm = { workspace = true, features = ["async-std"] }
|
||||
libp2p-tcp = { workspace = true, features = ["async-io"] }
|
||||
libp2p-yamux = { workspace = true }
|
||||
futures = "0.3.28"
|
||||
|
@ -28,7 +28,7 @@ use libp2p_identity::{Keypair, PeerId};
|
||||
use libp2p_plaintext as plaintext;
|
||||
use libp2p_swarm::dial_opts::PeerCondition;
|
||||
use libp2p_swarm::{
|
||||
dial_opts::DialOpts, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent, THandlerErr,
|
||||
self as swarm, dial_opts::DialOpts, NetworkBehaviour, Swarm, SwarmEvent, THandlerErr,
|
||||
};
|
||||
use libp2p_yamux as yamux;
|
||||
use std::fmt::Debug;
|
||||
@ -216,9 +216,13 @@ where
|
||||
.timeout(Duration::from_secs(20))
|
||||
.boxed();
|
||||
|
||||
SwarmBuilder::without_executor(transport, behaviour_fn(identity), peer_id)
|
||||
.idle_connection_timeout(Duration::from_secs(5)) // Some tests need connections to be kept alive beyond what the individual behaviour configures.
|
||||
.build()
|
||||
Swarm::new(
|
||||
transport,
|
||||
behaviour_fn(identity),
|
||||
peer_id,
|
||||
swarm::Config::with_async_std_executor()
|
||||
.with_idle_connection_timeout(Duration::from_secs(5)), // Some tests need connections to be kept alive beyond what the individual behaviour configures.,
|
||||
)
|
||||
}
|
||||
|
||||
async fn connect<T>(&mut self, other: &mut Swarm<T>)
|
||||
|
@ -1,3 +1,12 @@
|
||||
## 0.43.6 - unreleased
|
||||
|
||||
- Deprecate `libp2p::swarm::SwarmBuilder`.
|
||||
Most users should use `libp2p::SwarmBuilder`.
|
||||
In some special cases, users may need to use `Swarm::new` and `Config` instead of the new `libp2p::SwarmBuilder`.
|
||||
See [PR 4120].
|
||||
|
||||
[PR 4120]: https://github.com/libp2p/rust-libp2p/pull/4120
|
||||
|
||||
## 0.43.5
|
||||
|
||||
- Fix overflow in `KeepAlive` computation that could occur if `SwarmBuilder::idle_connection_timeout` is configured with `u64::MAX`.
|
||||
|
@ -3,7 +3,7 @@ name = "libp2p-swarm"
|
||||
edition = "2021"
|
||||
rust-version = { workspace = true }
|
||||
description = "The libp2p swarm"
|
||||
version = "0.43.5"
|
||||
version = "0.43.6"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
license = "MIT"
|
||||
repository = "https://github.com/libp2p/rust-libp2p"
|
||||
@ -30,7 +30,7 @@ multistream-select = { workspace = true }
|
||||
|
||||
[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies]
|
||||
async-std = { version = "1.6.2", optional = true }
|
||||
tokio = { version = "1.32", features = ["rt"], optional = true }
|
||||
tokio = { version = "1.33", features = ["rt"], optional = true }
|
||||
|
||||
[features]
|
||||
macros = ["dep:libp2p-swarm-derive"]
|
||||
@ -55,7 +55,7 @@ quickcheck = { workspace = true }
|
||||
void = "1"
|
||||
once_cell = "1.18.0"
|
||||
trybuild = "1.0.85"
|
||||
tokio = { version = "1.29.1", features = ["time", "rt", "macros"] }
|
||||
tokio = { version = "1.33.0", features = ["time", "rt", "macros", "rt-multi-thread"] }
|
||||
|
||||
[[test]]
|
||||
name = "swarm_derive"
|
||||
|
@ -748,6 +748,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn max_negotiating_inbound_streams() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
fn prop(max_negotiating_inbound_streams: u8) {
|
||||
let max_negotiating_inbound_streams: usize = max_negotiating_inbound_streams.into();
|
||||
|
||||
@ -756,7 +758,7 @@ mod tests {
|
||||
StreamMuxerBox::new(DummyStreamMuxer {
|
||||
counter: alive_substream_counter.clone(),
|
||||
}),
|
||||
MockConnectionHandler::new(Duration::ZERO),
|
||||
MockConnectionHandler::new(Duration::from_secs(10)),
|
||||
None,
|
||||
max_negotiating_inbound_streams,
|
||||
Duration::ZERO,
|
||||
|
293
swarm/src/lib.rs
293
swarm/src/lib.rs
@ -359,6 +359,26 @@ impl<TBehaviour> Swarm<TBehaviour>
|
||||
where
|
||||
TBehaviour: NetworkBehaviour,
|
||||
{
|
||||
/// Creates a new [`Swarm`] from the given [`Transport`], [`NetworkBehaviour`], [`PeerId`] and
|
||||
/// [`Config`].
|
||||
pub fn new(
|
||||
transport: transport::Boxed<(PeerId, StreamMuxerBox)>,
|
||||
behaviour: TBehaviour,
|
||||
local_peer_id: PeerId,
|
||||
config: Config,
|
||||
) -> Self {
|
||||
Swarm {
|
||||
local_peer_id,
|
||||
transport,
|
||||
pool: Pool::new(local_peer_id, config.pool_config),
|
||||
behaviour,
|
||||
supported_protocols: Default::default(),
|
||||
confirmed_external_addr: Default::default(),
|
||||
listened_addrs: HashMap::new(),
|
||||
pending_event: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns information about the connections underlying the [`Swarm`].
|
||||
pub fn network_info(&self) -> NetworkInfo {
|
||||
let num_peers = self.pool.num_peers();
|
||||
@ -401,7 +421,9 @@ where
|
||||
/// # use libp2p_swarm::dummy;
|
||||
/// # use libp2p_identity::PeerId;
|
||||
/// #
|
||||
/// let mut swarm = SwarmBuilder::without_executor(
|
||||
/// # #[tokio::main]
|
||||
/// # async fn main() {
|
||||
/// let mut swarm = SwarmBuilder::with_tokio_executor(
|
||||
/// DummyTransport::new().boxed(),
|
||||
/// dummy::Behaviour,
|
||||
/// PeerId::random(),
|
||||
@ -412,6 +434,7 @@ where
|
||||
///
|
||||
/// // Dial an unknown peer.
|
||||
/// swarm.dial("/ip6/::1/tcp/12345".parse::<Multiaddr>().unwrap());
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn dial(&mut self, opts: impl Into<DialOpts>) -> Result<(), DialError> {
|
||||
let dial_opts = opts.into();
|
||||
@ -1346,7 +1369,132 @@ impl<'a> PollParameters for SwarmPollParameters<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Config {
|
||||
pool_config: PoolConfig,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Creates a new [`Config`] from the given executor. The [`Swarm`] is obtained via
|
||||
/// [`Swarm::new`].
|
||||
pub fn with_executor(executor: impl Executor + Send + 'static) -> Self {
|
||||
Self {
|
||||
pool_config: PoolConfig::new(Some(Box::new(executor))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets executor to the `wasm` executor.
|
||||
/// Background tasks will be executed by the browser on the next micro-tick.
|
||||
///
|
||||
/// Spawning a task is similar too:
|
||||
/// ```typescript
|
||||
/// function spawn(task: () => Promise<void>) {
|
||||
/// task()
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "wasm-bindgen")]
|
||||
pub fn with_wasm_executor() -> Self {
|
||||
Self::with_executor(crate::executor::WasmBindgenExecutor)
|
||||
}
|
||||
|
||||
/// Builds a new [`Config`] from the given `tokio` executor.
|
||||
#[cfg(all(
|
||||
feature = "tokio",
|
||||
not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown"))
|
||||
))]
|
||||
pub fn with_tokio_executor() -> Self {
|
||||
Self::with_executor(crate::executor::TokioExecutor)
|
||||
}
|
||||
|
||||
/// Builds a new [`Config`] from the given `async-std` executor.
|
||||
#[cfg(all(
|
||||
feature = "async-std",
|
||||
not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown"))
|
||||
))]
|
||||
pub fn with_async_std_executor() -> Self {
|
||||
Self::with_executor(crate::executor::AsyncStdExecutor)
|
||||
}
|
||||
|
||||
/// Configures the number of events from the [`NetworkBehaviour`] in
|
||||
/// destination to the [`ConnectionHandler`] that can be buffered before
|
||||
/// the [`Swarm`] has to wait. An individual buffer with this number of
|
||||
/// events exists for each individual connection.
|
||||
///
|
||||
/// The ideal value depends on the executor used, the CPU speed, and the
|
||||
/// volume of events. If this value is too low, then the [`Swarm`] will
|
||||
/// be sleeping more often than necessary. Increasing this value increases
|
||||
/// the overall memory usage.
|
||||
pub fn with_notify_handler_buffer_size(mut self, n: NonZeroUsize) -> Self {
|
||||
self.pool_config = self.pool_config.with_notify_handler_buffer_size(n);
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the size of the buffer for events sent by a [`ConnectionHandler`] to the
|
||||
/// [`NetworkBehaviour`].
|
||||
///
|
||||
/// Each connection has its own buffer.
|
||||
///
|
||||
/// The ideal value depends on the executor used, the CPU speed and the volume of events.
|
||||
/// If this value is too low, then the [`ConnectionHandler`]s will be sleeping more often
|
||||
/// than necessary. Increasing this value increases the overall memory
|
||||
/// usage, and more importantly the latency between the moment when an
|
||||
/// event is emitted and the moment when it is received by the
|
||||
/// [`NetworkBehaviour`].
|
||||
pub fn with_per_connection_event_buffer_size(mut self, n: usize) -> Self {
|
||||
self.pool_config = self.pool_config.with_per_connection_event_buffer_size(n);
|
||||
self
|
||||
}
|
||||
|
||||
/// Number of addresses concurrently dialed for a single outbound connection attempt.
|
||||
pub fn with_dial_concurrency_factor(mut self, factor: NonZeroU8) -> Self {
|
||||
self.pool_config = self.pool_config.with_dial_concurrency_factor(factor);
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures an override for the substream upgrade protocol to use.
|
||||
///
|
||||
/// The subtream upgrade protocol is the multistream-select protocol
|
||||
/// used for protocol negotiation on substreams. Since a listener
|
||||
/// supports all existing versions, the choice of upgrade protocol
|
||||
/// only effects the "dialer", i.e. the peer opening a substream.
|
||||
///
|
||||
/// > **Note**: If configured, specific upgrade protocols for
|
||||
/// > individual [`SubstreamProtocol`]s emitted by the `NetworkBehaviour`
|
||||
/// > are ignored.
|
||||
pub fn with_substream_upgrade_protocol_override(
|
||||
mut self,
|
||||
v: libp2p_core::upgrade::Version,
|
||||
) -> Self {
|
||||
self.pool_config = self.pool_config.with_substream_upgrade_protocol_override(v);
|
||||
self
|
||||
}
|
||||
|
||||
/// The maximum number of inbound streams concurrently negotiating on a
|
||||
/// connection. New inbound streams exceeding the limit are dropped and thus
|
||||
/// reset.
|
||||
///
|
||||
/// Note: This only enforces a limit on the number of concurrently
|
||||
/// negotiating inbound streams. The total number of inbound streams on a
|
||||
/// connection is the sum of negotiating and negotiated streams. A limit on
|
||||
/// the total number of streams can be enforced at the
|
||||
/// [`StreamMuxerBox`] level.
|
||||
pub fn with_max_negotiating_inbound_streams(mut self, v: usize) -> Self {
|
||||
self.pool_config = self.pool_config.with_max_negotiating_inbound_streams(v);
|
||||
self
|
||||
}
|
||||
|
||||
/// How long to keep a connection alive once it is idling.
|
||||
///
|
||||
/// Defaults to 0.
|
||||
pub fn with_idle_connection_timeout(mut self, timeout: Duration) -> Self {
|
||||
self.pool_config.idle_connection_timeout = timeout;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`SwarmBuilder`] provides an API for configuring and constructing a [`Swarm`].
|
||||
#[deprecated(
|
||||
note = "Use the new `libp2p::SwarmBuilder` instead of `libp2p::swarm::SwarmBuilder` or create a `Swarm` directly via `Swarm::new`."
|
||||
)]
|
||||
pub struct SwarmBuilder<TBehaviour> {
|
||||
local_peer_id: PeerId,
|
||||
transport: transport::Boxed<(PeerId, StreamMuxerBox)>,
|
||||
@ -1354,6 +1502,7 @@ pub struct SwarmBuilder<TBehaviour> {
|
||||
pool_config: PoolConfig,
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<TBehaviour> SwarmBuilder<TBehaviour>
|
||||
where
|
||||
TBehaviour: NetworkBehaviour,
|
||||
@ -1820,9 +1969,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::dummy;
|
||||
use crate::test::{CallTraceBehaviour, MockBehaviour};
|
||||
use futures::executor::block_on;
|
||||
use futures::executor::ThreadPool;
|
||||
use futures::{executor, future};
|
||||
use futures::future;
|
||||
use libp2p_core::multiaddr::multiaddr;
|
||||
use libp2p_core::transport::memory::MemoryTransportError;
|
||||
use libp2p_core::transport::TransportEvent;
|
||||
@ -1841,7 +1988,8 @@ mod tests {
|
||||
}
|
||||
|
||||
fn new_test_swarm(
|
||||
) -> SwarmBuilder<CallTraceBehaviour<MockBehaviour<dummy::ConnectionHandler, ()>>> {
|
||||
config: Config,
|
||||
) -> Swarm<CallTraceBehaviour<MockBehaviour<dummy::ConnectionHandler, ()>>> {
|
||||
let id_keys = identity::Keypair::generate_ed25519();
|
||||
let local_public_key = id_keys.public();
|
||||
let transport = transport::MemoryTransport::default()
|
||||
@ -1850,14 +1998,13 @@ mod tests {
|
||||
.multiplex(yamux::Config::default())
|
||||
.boxed();
|
||||
let behaviour = CallTraceBehaviour::new(MockBehaviour::new(dummy::ConnectionHandler));
|
||||
let builder = match ThreadPool::new().ok() {
|
||||
Some(tp) => {
|
||||
SwarmBuilder::with_executor(transport, behaviour, local_public_key.into(), tp)
|
||||
}
|
||||
None => SwarmBuilder::without_executor(transport, behaviour, local_public_key.into()),
|
||||
};
|
||||
|
||||
builder.idle_connection_timeout(Duration::from_secs(5))
|
||||
Swarm::new(
|
||||
transport,
|
||||
behaviour,
|
||||
local_public_key.into(),
|
||||
config.with_idle_connection_timeout(Duration::from_secs(5)),
|
||||
)
|
||||
}
|
||||
|
||||
fn swarms_connected<TBehaviour>(
|
||||
@ -1906,10 +2053,10 @@ mod tests {
|
||||
///
|
||||
/// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`]
|
||||
/// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`]
|
||||
#[test]
|
||||
fn test_swarm_disconnect() {
|
||||
let mut swarm1 = new_test_swarm().build();
|
||||
let mut swarm2 = new_test_swarm().build();
|
||||
#[tokio::test]
|
||||
async fn test_swarm_disconnect() {
|
||||
let mut swarm1 = new_test_swarm(Config::with_tokio_executor());
|
||||
let mut swarm2 = new_test_swarm(Config::with_tokio_executor());
|
||||
|
||||
let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::<u64>()).into();
|
||||
let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::<u64>()).into();
|
||||
@ -1927,7 +2074,7 @@ mod tests {
|
||||
}
|
||||
let mut state = State::Connecting;
|
||||
|
||||
executor::block_on(future::poll_fn(move |cx| loop {
|
||||
future::poll_fn(move |cx| loop {
|
||||
let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx);
|
||||
let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx);
|
||||
match state {
|
||||
@ -1959,7 +2106,8 @@ mod tests {
|
||||
if poll1.is_pending() && poll2.is_pending() {
|
||||
return Poll::Pending;
|
||||
}
|
||||
}))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Establishes multiple connections between two peers,
|
||||
@ -1968,10 +2116,10 @@ mod tests {
|
||||
///
|
||||
/// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`]
|
||||
/// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`]
|
||||
#[test]
|
||||
fn test_behaviour_disconnect_all() {
|
||||
let mut swarm1 = new_test_swarm().build();
|
||||
let mut swarm2 = new_test_swarm().build();
|
||||
#[tokio::test]
|
||||
async fn test_behaviour_disconnect_all() {
|
||||
let mut swarm1 = new_test_swarm(Config::with_tokio_executor());
|
||||
let mut swarm2 = new_test_swarm(Config::with_tokio_executor());
|
||||
|
||||
let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::<u64>()).into();
|
||||
let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::<u64>()).into();
|
||||
@ -1989,7 +2137,7 @@ mod tests {
|
||||
}
|
||||
let mut state = State::Connecting;
|
||||
|
||||
executor::block_on(future::poll_fn(move |cx| loop {
|
||||
future::poll_fn(move |cx| loop {
|
||||
let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx);
|
||||
let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx);
|
||||
match state {
|
||||
@ -2025,7 +2173,8 @@ mod tests {
|
||||
if poll1.is_pending() && poll2.is_pending() {
|
||||
return Poll::Pending;
|
||||
}
|
||||
}))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Establishes multiple connections between two peers,
|
||||
@ -2034,10 +2183,10 @@ mod tests {
|
||||
///
|
||||
/// The test expects both behaviours to be notified via calls to [`NetworkBehaviour::on_swarm_event`]
|
||||
/// with pairs of [`FromSwarm::ConnectionEstablished`] / [`FromSwarm::ConnectionClosed`]
|
||||
#[test]
|
||||
fn test_behaviour_disconnect_one() {
|
||||
let mut swarm1 = new_test_swarm().build();
|
||||
let mut swarm2 = new_test_swarm().build();
|
||||
#[tokio::test]
|
||||
async fn test_behaviour_disconnect_one() {
|
||||
let mut swarm1 = new_test_swarm(Config::with_tokio_executor());
|
||||
let mut swarm2 = new_test_swarm(Config::with_tokio_executor());
|
||||
|
||||
let addr1: Multiaddr = multiaddr::Protocol::Memory(rand::random::<u64>()).into();
|
||||
let addr2: Multiaddr = multiaddr::Protocol::Memory(rand::random::<u64>()).into();
|
||||
@ -2055,7 +2204,7 @@ mod tests {
|
||||
let mut state = State::Connecting;
|
||||
let mut disconnected_conn_id = None;
|
||||
|
||||
executor::block_on(future::poll_fn(move |cx| loop {
|
||||
future::poll_fn(move |cx| loop {
|
||||
let poll1 = Swarm::poll_next_event(Pin::new(&mut swarm1), cx);
|
||||
let poll2 = Swarm::poll_next_event(Pin::new(&mut swarm2), cx);
|
||||
match state {
|
||||
@ -2099,7 +2248,8 @@ mod tests {
|
||||
if poll1.is_pending() && poll2.is_pending() {
|
||||
return Poll::Pending;
|
||||
}
|
||||
}))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -2114,10 +2264,11 @@ mod tests {
|
||||
}
|
||||
|
||||
fn prop(concurrency_factor: DialConcurrencyFactor) {
|
||||
block_on(async {
|
||||
let mut swarm = new_test_swarm()
|
||||
.dial_concurrency_factor(concurrency_factor.0)
|
||||
.build();
|
||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||
let mut swarm = new_test_swarm(
|
||||
Config::with_tokio_executor()
|
||||
.with_dial_concurrency_factor(concurrency_factor.0),
|
||||
);
|
||||
|
||||
// Listen on `concurrency_factor + 1` addresses.
|
||||
//
|
||||
@ -2173,31 +2324,29 @@ mod tests {
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn(_) -> _);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_peer_id() {
|
||||
#[tokio::test]
|
||||
async fn invalid_peer_id() {
|
||||
// Checks whether dialing an address containing the wrong peer id raises an error
|
||||
// for the expected peer id instead of the obtained peer id.
|
||||
|
||||
let mut swarm1 = new_test_swarm().build();
|
||||
let mut swarm2 = new_test_swarm().build();
|
||||
let mut swarm1 = new_test_swarm(Config::with_tokio_executor());
|
||||
let mut swarm2 = new_test_swarm(Config::with_tokio_executor());
|
||||
|
||||
swarm1.listen_on("/memory/0".parse().unwrap()).unwrap();
|
||||
|
||||
let address =
|
||||
futures::executor::block_on(future::poll_fn(|cx| match swarm1.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(SwarmEvent::NewListenAddr { address, .. })) => {
|
||||
Poll::Ready(address)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
_ => panic!("Was expecting the listen address to be reported"),
|
||||
}));
|
||||
let address = future::poll_fn(|cx| match swarm1.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(SwarmEvent::NewListenAddr { address, .. })) => Poll::Ready(address),
|
||||
Poll::Pending => Poll::Pending,
|
||||
_ => panic!("Was expecting the listen address to be reported"),
|
||||
})
|
||||
.await;
|
||||
|
||||
let other_id = PeerId::random();
|
||||
let other_addr = address.with(multiaddr::Protocol::P2p(other_id));
|
||||
|
||||
swarm2.dial(other_addr.clone()).unwrap();
|
||||
|
||||
let (peer_id, error) = futures::executor::block_on(future::poll_fn(|cx| {
|
||||
let (peer_id, error) = future::poll_fn(|cx| {
|
||||
if let Poll::Ready(Some(SwarmEvent::IncomingConnection { .. })) =
|
||||
swarm1.poll_next_unpin(cx)
|
||||
{}
|
||||
@ -2209,7 +2358,8 @@ mod tests {
|
||||
Poll::Ready(x) => panic!("unexpected {x:?}"),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}));
|
||||
})
|
||||
.await;
|
||||
assert_eq!(peer_id.unwrap(), other_id);
|
||||
match error {
|
||||
DialError::WrongPeerId { obtained, endpoint } => {
|
||||
@ -2226,8 +2376,8 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dial_self() {
|
||||
#[tokio::test]
|
||||
async fn dial_self() {
|
||||
// Check whether dialing ourselves correctly fails.
|
||||
//
|
||||
// Dialing the same address we're listening should result in three events:
|
||||
@ -2238,17 +2388,15 @@ mod tests {
|
||||
//
|
||||
// The last two can happen in any order.
|
||||
|
||||
let mut swarm = new_test_swarm().build();
|
||||
let mut swarm = new_test_swarm(Config::with_tokio_executor());
|
||||
swarm.listen_on("/memory/0".parse().unwrap()).unwrap();
|
||||
|
||||
let local_address =
|
||||
futures::executor::block_on(future::poll_fn(|cx| match swarm.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(SwarmEvent::NewListenAddr { address, .. })) => {
|
||||
Poll::Ready(address)
|
||||
}
|
||||
Poll::Pending => Poll::Pending,
|
||||
_ => panic!("Was expecting the listen address to be reported"),
|
||||
}));
|
||||
let local_address = future::poll_fn(|cx| match swarm.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(SwarmEvent::NewListenAddr { address, .. })) => Poll::Ready(address),
|
||||
Poll::Pending => Poll::Pending,
|
||||
_ => panic!("Was expecting the listen address to be reported"),
|
||||
})
|
||||
.await;
|
||||
|
||||
swarm.listened_addrs.clear(); // This is a hack to actually execute the dial to ourselves which would otherwise be filtered.
|
||||
|
||||
@ -2256,7 +2404,7 @@ mod tests {
|
||||
|
||||
let mut got_dial_err = false;
|
||||
let mut got_inc_err = false;
|
||||
futures::executor::block_on(future::poll_fn(|cx| -> Poll<Result<(), io::Error>> {
|
||||
future::poll_fn(|cx| -> Poll<Result<(), io::Error>> {
|
||||
loop {
|
||||
match swarm.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(SwarmEvent::OutgoingConnectionError {
|
||||
@ -2290,26 +2438,27 @@ mod tests {
|
||||
Poll::Pending => break Poll::Pending,
|
||||
}
|
||||
}
|
||||
}))
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dial_self_by_id() {
|
||||
#[tokio::test]
|
||||
async fn dial_self_by_id() {
|
||||
// Trying to dial self by passing the same `PeerId` shouldn't even be possible in the first
|
||||
// place.
|
||||
let swarm = new_test_swarm().build();
|
||||
let swarm = new_test_swarm(Config::with_tokio_executor());
|
||||
let peer_id = *swarm.local_peer_id();
|
||||
assert!(!swarm.is_connected(&peer_id));
|
||||
}
|
||||
|
||||
#[async_std::test]
|
||||
#[tokio::test]
|
||||
async fn multiple_addresses_err() {
|
||||
// Tries dialing multiple addresses, and makes sure there's one dialing error per address.
|
||||
|
||||
let target = PeerId::random();
|
||||
|
||||
let mut swarm = new_test_swarm().build();
|
||||
let mut swarm = new_test_swarm(Config::with_tokio_executor());
|
||||
|
||||
let addresses = HashSet::from([
|
||||
multiaddr![Ip4([0, 0, 0, 0]), Tcp(rand::random::<u16>())],
|
||||
@ -2351,16 +2500,16 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aborting_pending_connection_surfaces_error() {
|
||||
#[tokio::test]
|
||||
async fn aborting_pending_connection_surfaces_error() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let mut dialer = new_test_swarm().build();
|
||||
let mut listener = new_test_swarm().build();
|
||||
let mut dialer = new_test_swarm(Config::with_tokio_executor());
|
||||
let mut listener = new_test_swarm(Config::with_tokio_executor());
|
||||
|
||||
let listener_peer_id = *listener.local_peer_id();
|
||||
listener.listen_on(multiaddr![Memory(0u64)]).unwrap();
|
||||
let listener_address = match block_on(listener.next()).unwrap() {
|
||||
let listener_address = match listener.next().await.unwrap() {
|
||||
SwarmEvent::NewListenAddr { address, .. } => address,
|
||||
e => panic!("Unexpected network event: {e:?}"),
|
||||
};
|
||||
@ -2377,7 +2526,7 @@ mod tests {
|
||||
.disconnect_peer_id(listener_peer_id)
|
||||
.expect_err("Expect peer to not yet be connected.");
|
||||
|
||||
match block_on(dialer.next()).unwrap() {
|
||||
match dialer.next().await.unwrap() {
|
||||
SwarmEvent::OutgoingConnectionError {
|
||||
error: DialError::Aborted,
|
||||
..
|
||||
|
@ -27,7 +27,7 @@ libp2p-tcp = { workspace = true, features = ["tokio"] }
|
||||
libp2p-websocket = { workspace = true }
|
||||
libp2p-yamux = { workspace = true }
|
||||
quickcheck = { workspace = true }
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
tokio = { version = "1.33.0", features = ["full"] }
|
||||
|
||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||
# More information: https://docs.rs/about/builds#cross-compiling
|
||||
|
@ -6,7 +6,7 @@ use libp2p_core::upgrade::Version;
|
||||
use libp2p_core::Transport;
|
||||
use libp2p_core::{multiaddr::Protocol, Multiaddr};
|
||||
use libp2p_pnet::{PnetConfig, PreSharedKey};
|
||||
use libp2p_swarm::{dummy, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent};
|
||||
use libp2p_swarm::{dummy, Config, NetworkBehaviour, Swarm, SwarmEvent};
|
||||
|
||||
const TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
@ -113,9 +113,12 @@ where
|
||||
.authenticate(libp2p_noise::Config::new(&identity).unwrap())
|
||||
.multiplex(libp2p_yamux::Config::default())
|
||||
.boxed();
|
||||
SwarmBuilder::with_tokio_executor(transport, dummy::Behaviour, identity.public().to_peer_id())
|
||||
.idle_connection_timeout(Duration::from_secs(5))
|
||||
.build()
|
||||
Swarm::new(
|
||||
transport,
|
||||
dummy::Behaviour,
|
||||
identity.public().to_peer_id(),
|
||||
Config::with_tokio_executor(),
|
||||
)
|
||||
}
|
||||
|
||||
async fn listen_on<B: NetworkBehaviour>(swarm: &mut Swarm<B>, addr: Multiaddr) -> Multiaddr {
|
||||
|
@ -23,7 +23,7 @@ quinn = { version = "0.10.2", default-features = false, features = ["tls-rustls"
|
||||
rand = "0.8.5"
|
||||
rustls = { version = "0.21.7", default-features = false }
|
||||
thiserror = "1.0.49"
|
||||
tokio = { version = "1.32.0", default-features = false, features = ["net", "rt", "time"], optional = true }
|
||||
tokio = { version = "1.33.0", default-features = false, features = ["net", "rt", "time"], optional = true }
|
||||
socket2 = "0.5.4"
|
||||
ring = "0.16.20"
|
||||
|
||||
@ -46,7 +46,7 @@ libp2p-noise = { workspace = true }
|
||||
libp2p-tcp = { workspace = true, features = ["async-io"] }
|
||||
libp2p-yamux = { workspace = true }
|
||||
quickcheck = "1"
|
||||
tokio = { version = "1.32.0", features = ["macros", "rt-multi-thread", "time"] }
|
||||
tokio = { version = "1.33.0", features = ["macros", "rt-multi-thread", "time"] }
|
||||
|
||||
[[test]]
|
||||
name = "stream_compliance"
|
||||
|
@ -20,7 +20,7 @@ libp2p-core = { workspace = true }
|
||||
libp2p-identity = { workspace = true }
|
||||
log = "0.4.20"
|
||||
socket2 = { version = "0.5.4", features = ["all"] }
|
||||
tokio = { version = "1.32.0", default-features = false, features = ["net"], optional = true }
|
||||
tokio = { version = "1.33.0", default-features = false, features = ["net"], optional = true }
|
||||
|
||||
[features]
|
||||
tokio = ["dep:tokio", "if-watch/tokio"]
|
||||
@ -28,7 +28,7 @@ async-io = ["dep:async-io", "if-watch/smol"]
|
||||
|
||||
[dev-dependencies]
|
||||
async-std = { version = "1.6.5", features = ["attributes"] }
|
||||
tokio = { version = "1.32.0", default-features = false, features = ["full"] }
|
||||
tokio = { version = "1.33.0", default-features = false, features = ["full"] }
|
||||
env_logger = "0.10.0"
|
||||
|
||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||
|
@ -54,7 +54,7 @@ pub type Transport = crate::Transport<Tcp>;
|
||||
pub enum Tcp {}
|
||||
|
||||
impl Provider for Tcp {
|
||||
type Stream = Async<net::TcpStream>;
|
||||
type Stream = TcpStream;
|
||||
type Listener = Async<net::TcpListener>;
|
||||
type IfWatcher = if_watch::smol::IfWatcher;
|
||||
|
||||
@ -116,3 +116,5 @@ impl Provider for Tcp {
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub type TcpStream = Async<net::TcpStream>;
|
||||
|
@ -31,9 +31,9 @@ hex = "0.4.3"
|
||||
hex-literal = "0.4.1"
|
||||
libp2p-core = { workspace = true }
|
||||
libp2p-identity = { workspace = true, features = ["ed25519", "rsa", "secp256k1", "ecdsa"] }
|
||||
libp2p-swarm = { workspace = true }
|
||||
libp2p-swarm = { workspace = true, features = ["tokio"] }
|
||||
libp2p-yamux = { workspace = true }
|
||||
tokio = { version = "1.32.0", features = ["full"] }
|
||||
tokio = { version = "1.33.0", features = ["full"] }
|
||||
|
||||
# Passing arguments to the docsrs builder in order to properly document cfg's.
|
||||
# More information: https://docs.rs/about/builds#cross-compiling
|
||||
|
@ -3,7 +3,7 @@ use libp2p_core::multiaddr::Protocol;
|
||||
use libp2p_core::transport::MemoryTransport;
|
||||
use libp2p_core::upgrade::Version;
|
||||
use libp2p_core::Transport;
|
||||
use libp2p_swarm::{dummy, Swarm, SwarmBuilder, SwarmEvent};
|
||||
use libp2p_swarm::{dummy, Config, Swarm, SwarmEvent};
|
||||
use std::time::Duration;
|
||||
|
||||
#[tokio::test]
|
||||
@ -65,7 +65,10 @@ fn make_swarm() -> Swarm<dummy::Behaviour> {
|
||||
.multiplex(libp2p_yamux::Config::default())
|
||||
.boxed();
|
||||
|
||||
SwarmBuilder::without_executor(transport, dummy::Behaviour, identity.public().to_peer_id())
|
||||
.idle_connection_timeout(Duration::from_secs(5))
|
||||
.build()
|
||||
Swarm::new(
|
||||
transport,
|
||||
dummy::Behaviour,
|
||||
identity.public().to_peer_id(),
|
||||
Config::with_tokio_executor().with_idle_connection_timeout(Duration::from_secs(60)),
|
||||
)
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ async-std = { version = "1.6.2", optional = true }
|
||||
libp2p-core = { workspace = true }
|
||||
log = "0.4.20"
|
||||
futures = "0.3.28"
|
||||
tokio = { version = "1.32", default-features = false, features = ["net"], optional = true }
|
||||
tokio = { version = "1.33", default-features = false, features = ["net"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.8"
|
||||
|
@ -29,7 +29,7 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
stun = "0.5"
|
||||
thiserror = "1"
|
||||
tinytemplate = "1.2"
|
||||
tokio = { version = "1.32", features = ["net"], optional = true }
|
||||
tokio = { version = "1.33", features = ["net"], optional = true }
|
||||
tokio-util = { version = "0.7", features = ["compat"], optional = true }
|
||||
webrtc = { version = "0.9.0", optional = true }
|
||||
|
||||
@ -39,7 +39,7 @@ pem = ["webrtc?/pem"]
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.10"
|
||||
tokio = { version = "1.32", features = ["full"] }
|
||||
tokio = { version = "1.33", features = ["full"] }
|
||||
quickcheck = "1.0.3"
|
||||
|
||||
[[test]]
|
||||
|
Loading…
x
Reference in New Issue
Block a user