for PendingUpgrade
where
P: AsRef + Clone,
{
- type Output = Void;
- type Error = Void;
+ type Output = Infallible;
+ type Error = Infallible;
type Future = future::Pending>;
fn upgrade_inbound(self, _: C, _: Self::Info) -> Self::Future {
@@ -66,8 +67,8 @@ impl OutboundUpgrade for PendingUpgrade
where
P: AsRef + Clone,
{
- type Output = Void;
- type Error = Void;
+ type Output = Infallible;
+ type Error = Infallible;
type Future = future::Pending>;
fn upgrade_outbound(self, _: C, _: Self::Info) -> Self::Future {
diff --git a/core/src/upgrade/ready.rs b/core/src/upgrade/ready.rs
index 323f1f73f32..22708d726e7 100644
--- a/core/src/upgrade/ready.rs
+++ b/core/src/upgrade/ready.rs
@@ -19,19 +19,21 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-use crate::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
+use std::{convert::Infallible, iter};
+
use futures::future;
-use std::iter;
-use void::Void;
-/// Implementation of [`UpgradeInfo`], [`InboundUpgrade`] and [`OutboundUpgrade`] that directly yields the substream.
+use crate::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo};
+
+/// Implementation of [`UpgradeInfo`], [`InboundUpgrade`] and [`OutboundUpgrade`]
+/// that directly yields the substream.
#[derive(Debug, Copy, Clone)]
pub struct ReadyUpgrade {
protocol_name: P,
}
impl
ReadyUpgrade
{
- pub fn new(protocol_name: P) -> Self {
+ pub const fn new(protocol_name: P) -> Self {
Self { protocol_name }
}
}
@@ -53,7 +55,7 @@ where
P: AsRef + Clone,
{
type Output = C;
- type Error = Void;
+ type Error = Infallible;
type Future = future::Ready>;
fn upgrade_inbound(self, stream: C, _: Self::Info) -> Self::Future {
@@ -66,7 +68,7 @@ where
P: AsRef + Clone,
{
type Output = C;
- type Error = Void;
+ type Error = Infallible;
type Future = future::Ready>;
fn upgrade_outbound(self, stream: C, _: Self::Info) -> Self::Future {
diff --git a/core/src/upgrade/select.rs b/core/src/upgrade/select.rs
index 037045a2f29..b7fe4a53a7f 100644
--- a/core/src/upgrade/select.rs
+++ b/core/src/upgrade/select.rs
@@ -18,14 +18,18 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-use crate::either::EitherFuture;
-use crate::upgrade::{
- InboundConnectionUpgrade, InboundUpgrade, OutboundConnectionUpgrade, OutboundUpgrade,
- UpgradeInfo,
-};
+use std::iter::{Chain, Map};
+
use either::Either;
use futures::future;
-use std::iter::{Chain, Map};
+
+use crate::{
+ either::EitherFuture,
+ upgrade::{
+ InboundConnectionUpgrade, InboundUpgrade, OutboundConnectionUpgrade, OutboundUpgrade,
+ UpgradeInfo,
+ },
+};
/// Upgrade that combines two upgrades into one. Supports all the protocols supported by either
/// sub-upgrade.
diff --git a/core/tests/transport_upgrade.rs b/core/tests/transport_upgrade.rs
index a8872051618..b9733e38322 100644
--- a/core/tests/transport_upgrade.rs
+++ b/core/tests/transport_upgrade.rs
@@ -18,17 +18,19 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+use std::{io, pin::Pin};
+
use futures::prelude::*;
-use libp2p_core::transport::{ListenerId, MemoryTransport, Transport};
-use libp2p_core::upgrade::{
- self, InboundConnectionUpgrade, OutboundConnectionUpgrade, UpgradeInfo,
+use libp2p_core::{
+ transport::{DialOpts, ListenerId, MemoryTransport, PortUse, Transport},
+ upgrade::{self, InboundConnectionUpgrade, OutboundConnectionUpgrade, UpgradeInfo},
+ Endpoint,
};
use libp2p_identity as identity;
use libp2p_mplex::MplexConfig;
use libp2p_noise as noise;
use multiaddr::{Multiaddr, Protocol};
use rand::random;
-use std::{io, pin::Pin};
#[derive(Clone)]
struct HelloUpgrade {}
@@ -121,7 +123,17 @@ fn upgrade_pipeline() {
};
let client = async move {
- let (peer, _mplex) = dialer_transport.dial(listen_addr2).unwrap().await.unwrap();
+ let (peer, _mplex) = dialer_transport
+ .dial(
+ listen_addr2,
+ DialOpts {
+ role: Endpoint::Dialer,
+ port_use: PortUse::New,
+ },
+ )
+ .unwrap()
+ .await
+ .unwrap();
assert_eq!(peer, listener_id);
};
diff --git a/deny.toml b/deny.toml
index 6634887128e..47487553028 100644
--- a/deny.toml
+++ b/deny.toml
@@ -2,20 +2,14 @@
# More documentation for the advisories section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
[advisories]
+# Version of the advisory config. See https://github.com/EmbarkStudios/cargo-deny/pull/611
+version = 2
# The path where the advisory database is cloned/fetched into
db-path = "~/cargo/advisory-db"
# The url of the advisory database to use
-db-urls = [ "https://github.com/rustsec/advisory-db" ]
-# The lint level for security vulnerabilities
-vulnerability = "deny"
-# The lint level for unmaintained crates
-unmaintained = "warn"
+db-urls = ["https://github.com/rustsec/advisory-db"]
# The lint level for crates that have been yanked from their source registry
yanked = "warn"
-# The lint level for crates with security notices. Note that as of
-# 2019-12-17 there are no security notice advisories in
-# https://github.com/rustsec/advisory-db
-notice = "warn"
# A list of advisory IDs to ignore. Note that ignored advisories will still
# output a note when they are encountered.
ignore = [
@@ -35,35 +29,23 @@ ignore = [
# More documentation for the licenses section can be found here:
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
[licenses]
-# The lint level for crates which do not have a detectable license
-unlicensed = "deny"
-# List of explictly allowed licenses
+# Version of the license config. See https://github.com/EmbarkStudios/cargo-deny/pull/611
+version = 2
+# List of explicitly allowed licenses
# See https://spdx.org/licenses/ for list of possible licenses
-# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
+# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
allow = [
+ "Apache-2.0 WITH LLVM-exception",
"Apache-2.0",
"BSD-2-Clause",
+ "BSD-3-Clause",
+ "ISC",
"MIT",
+ "MPL-2.0",
"Unlicense",
+ "Unicode-3.0",
+ "Zlib",
]
-# List of explictly disallowed licenses
-# See https://spdx.org/licenses/ for list of possible licenses
-# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
-deny = []
-# Lint level for licenses considered copyleft
-copyleft = "allow"
-# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
-# * both - The license will be approved if it is both OSI-approved *AND* FSF
-# * either - The license will be approved if it is either OSI-approved *OR* FSF
-# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
-# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
-# * neither - This predicate is ignored and the default lint level is used
-allow-osi-fsf-free = "both"
-# Lint level used when no other predicates are matched
-# 1. License isn't in the allow or deny lists
-# 2. License isn't copyleft
-# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
-default = "deny"
# The confidence threshold for detecting a license from license text.
# The higher the value, the more closely the license text must be to the
# canonical license text of a valid SPDX license file.
@@ -76,7 +58,7 @@ exceptions = [
# https://www.openssl.org/blog/blog/2017/03/22/license/
# ring crate is ISC & MIT
{ allow = ["ISC", "MIT", "OpenSSL"], name = "ring" },
- # libp2p is not re-distributing unicode tables data by itself
+ # libp2p is not re-distributing unicode tables data by itself
{ allow = ["MIT", "Apache-2.0", "Unicode-DFS-2016"], name = "unicode-ident" },
]
diff --git a/docs/coding-guidelines.md b/docs/coding-guidelines.md
index bacbfe9509e..473d7020fcf 100644
--- a/docs/coding-guidelines.md
+++ b/docs/coding-guidelines.md
@@ -236,7 +236,7 @@ Concurrency adds complexity. Concurrency adds overhead due to synchronization.
Thus unless proven to be a bottleneck, don't make things concurrent. As an example
the hierarchical `NetworkBehaviour` state machine runs sequentially. It is easy
to debug as it runs sequentially. Thus far there has been no proof that
-shows a speed up when running it concurrently.
+shows a speed-up when running it concurrently.
## Use `async/await` for sequential execution only
diff --git a/docs/maintainer-handbook.md b/docs/maintainer-handbook.md
index 6d36f6fe77c..0b090901216 100644
--- a/docs/maintainer-handbook.md
+++ b/docs/maintainer-handbook.md
@@ -31,7 +31,7 @@ This will have mergify approve your PR, thus fulfilling all requirements to auto
Our CI checks that each crate which is modified gets a changelog entry.
Whilst this is a good default safety-wise, it creates a lot of false-positives for changes that are internal and don't need a changelog entry.
-For PRs that in the categories `chore`, `deps`, `refactor` and `docs`, this check is disabled automatically.
+For PRs in the categories `chore`, `deps`, `refactor` and `docs`, this check is disabled automatically.
Any other PR needs to explicitly disable this check if desired by applying the `internal-change` label.
## Dependencies
diff --git a/examples/README.md b/examples/README.md
index 28e085587b7..0a3e55aed39 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -20,6 +20,6 @@ A set of examples showcasing how to use rust-libp2p.
- [IPFS Private](./ipfs-private) Implementation using the gossipsub, ping and identify protocols to implement the ipfs private swarms feature.
-- [Ping](./ping) Small `ping` clone, sending a ping to a peer, expecting a pong as a response. See [tutorial](../src/tutorials/ping.rs) for a step-by-step guide building the example.
+- [Ping](./ping) Small `ping` clone, sending a ping to a peer, expecting a pong as a response. See [tutorial](../libp2p/src/tutorials/ping.rs) for a step-by-step guide building the example.
- [Rendezvous](./rendezvous) Rendezvous Protocol. See [specs](https://github.com/libp2p/specs/blob/master/rendezvous/README.md).
diff --git a/examples/autonat/Cargo.toml b/examples/autonat/Cargo.toml
index cca3b5e326e..7c06b48a105 100644
--- a/examples/autonat/Cargo.toml
+++ b/examples/autonat/Cargo.toml
@@ -3,18 +3,17 @@ name = "autonat-example"
version = "0.1.0"
edition = "2021"
publish = false
-license = "MIT"
+license = "MIT or Apache-2.0"
[package.metadata.release]
release = false
[dependencies]
-tokio = { version = "1.34", features = ["full"] }
-clap = { version = "4.4.10", features = ["derive"] }
-futures = "0.3.29"
+tokio = { workspace = true, features = ["full"] }
+clap = { version = "4.5.6", features = ["derive"] }
+futures = { workspace = true }
libp2p = { path = "../../libp2p", features = ["tokio", "tcp", "noise", "yamux", "autonat", "identify", "macros"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/autonat/src/bin/autonat_client.rs b/examples/autonat/src/bin/autonat_client.rs
index 3fb25aa6222..768a2052c80 100644
--- a/examples/autonat/src/bin/autonat_client.rs
+++ b/examples/autonat/src/bin/autonat_client.rs
@@ -20,15 +20,17 @@
#![doc = include_str!("../../README.md")]
+use std::{error::Error, net::Ipv4Addr, time::Duration};
+
use clap::Parser;
use futures::StreamExt;
-use libp2p::core::multiaddr::Protocol;
-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;
-use std::time::Duration;
+use libp2p::{
+ autonat,
+ core::{multiaddr::Protocol, Multiaddr},
+ identify, identity, noise,
+ swarm::{NetworkBehaviour, SwarmEvent},
+ tcp, yamux, PeerId,
+};
use tracing_subscriber::EnvFilter;
#[derive(Debug, Parser)]
@@ -60,7 +62,6 @@ async fn main() -> Result<(), Box> {
yamux::Config::default,
)?
.with_behaviour(|key| Behaviour::new(key.public()))?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
swarm.listen_on(
@@ -110,22 +111,3 @@ impl Behaviour {
}
}
}
-
-#[derive(Debug)]
-#[allow(clippy::large_enum_variant)]
-enum Event {
- AutoNat(autonat::Event),
- Identify(identify::Event),
-}
-
-impl From for Event {
- fn from(v: identify::Event) -> Self {
- Self::Identify(v)
- }
-}
-
-impl From for Event {
- fn from(v: autonat::Event) -> Self {
- Self::AutoNat(v)
- }
-}
diff --git a/examples/autonat/src/bin/autonat_server.rs b/examples/autonat/src/bin/autonat_server.rs
index 44a53f0d17f..f3bb6b6a439 100644
--- a/examples/autonat/src/bin/autonat_server.rs
+++ b/examples/autonat/src/bin/autonat_server.rs
@@ -20,14 +20,17 @@
#![doc = include_str!("../../README.md")]
+use std::{error::Error, net::Ipv4Addr};
+
use clap::Parser;
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;
-use std::time::Duration;
+use libp2p::{
+ autonat,
+ core::{multiaddr::Protocol, Multiaddr},
+ identify, identity, noise,
+ swarm::{NetworkBehaviour, SwarmEvent},
+ tcp, yamux,
+};
use tracing_subscriber::EnvFilter;
#[derive(Debug, Parser)]
@@ -53,7 +56,6 @@ async fn main() -> Result<(), Box> {
yamux::Config::default,
)?
.with_behaviour(|key| Behaviour::new(key.public()))?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
swarm.listen_on(
@@ -94,22 +96,3 @@ impl Behaviour {
}
}
}
-
-#[derive(Debug)]
-#[allow(clippy::large_enum_variant)]
-enum Event {
- AutoNat(autonat::Event),
- Identify(identify::Event),
-}
-
-impl From for Event {
- fn from(v: identify::Event) -> Self {
- Self::Identify(v)
- }
-}
-
-impl From for Event {
- fn from(v: autonat::Event) -> Self {
- Self::AutoNat(v)
- }
-}
diff --git a/examples/autonatv2/Cargo.toml b/examples/autonatv2/Cargo.toml
new file mode 100644
index 00000000000..d400c53e7fd
--- /dev/null
+++ b/examples/autonatv2/Cargo.toml
@@ -0,0 +1,36 @@
+[package]
+name = "autonatv2"
+version = "0.1.0"
+edition = "2021"
+publish = false
+license = "MIT or Apache-2.0"
+
+[package.metadata.release]
+release = false
+
+[[bin]]
+name = "autonatv2_client"
+
+[[bin]]
+name = "autonatv2_server"
+
+[dependencies]
+libp2p = { workspace = true, features = ["macros", "tokio", "tcp", "noise", "yamux", "autonat", "identify", "dns", "quic"] }
+clap = { version = "4.4.18", features = ["derive"] }
+tokio = { version = "1.35.1", features = ["macros", "rt-multi-thread"] }
+tracing = "0.1.40"
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
+rand = "0.8.5"
+opentelemetry_sdk = { version = "0.21.1", optional = true, features = ["rt-tokio"] }
+tracing-opentelemetry = { version = "0.22.0", optional = true }
+opentelemetry-jaeger = { version = "0.20.0", optional = true, features = ["rt-tokio"] }
+cfg-if = "1.0.0"
+
+[features]
+jaeger = ["opentelemetry_sdk", "tracing-opentelemetry", "opentelemetry-jaeger"]
+opentelemetry_sdk = ["dep:opentelemetry_sdk"]
+tracing-opentelemetry = ["dep:tracing-opentelemetry"]
+opentelemetry-jaeger = ["dep:opentelemetry-jaeger"]
+
+[lints]
+workspace = true
diff --git a/examples/autonatv2/Dockerfile b/examples/autonatv2/Dockerfile
new file mode 100644
index 00000000000..6bc92e4d11b
--- /dev/null
+++ b/examples/autonatv2/Dockerfile
@@ -0,0 +1,20 @@
+FROM rust:1.81-alpine as builder
+
+RUN apk add musl-dev
+
+WORKDIR /workspace
+COPY . .
+RUN --mount=type=cache,target=./target \
+ --mount=type=cache,target=/usr/local/cargo/registry \
+ cargo build --release --package autonatv2 --bin autonatv2_server -F jaeger
+
+RUN --mount=type=cache,target=./target \
+ mv ./target/release/autonatv2_server /usr/local/bin/autonatv2_server
+
+FROM alpine:latest
+
+COPY --from=builder /usr/local/bin/autonatv2_server /app/autonatv2_server
+
+EXPOSE 4884
+
+ENTRYPOINT [ "/app/autonatv2_server", "-l", "4884" ]
diff --git a/examples/autonatv2/docker-compose.yml b/examples/autonatv2/docker-compose.yml
new file mode 100644
index 00000000000..75f44e7e6f9
--- /dev/null
+++ b/examples/autonatv2/docker-compose.yml
@@ -0,0 +1,16 @@
+version: '3'
+
+services:
+ autonatv2:
+ build:
+ context: ../..
+ dockerfile: examples/autonatv2/Dockerfile
+ ports:
+ - 4884:4884
+ jaeger:
+ image: jaegertracing/all-in-one
+ ports:
+ - 6831:6831/udp
+ - 6832:6832/udp
+ - 16686:16686
+ - 14268:14268
diff --git a/examples/autonatv2/src/bin/autonatv2_client.rs b/examples/autonatv2/src/bin/autonatv2_client.rs
new file mode 100644
index 00000000000..de902514dd8
--- /dev/null
+++ b/examples/autonatv2/src/bin/autonatv2_client.rs
@@ -0,0 +1,111 @@
+use std::{error::Error, net::Ipv4Addr, time::Duration};
+
+use clap::Parser;
+use libp2p::{
+ autonat,
+ futures::StreamExt,
+ identify, identity,
+ multiaddr::Protocol,
+ noise,
+ swarm::{dial_opts::DialOpts, NetworkBehaviour, SwarmEvent},
+ tcp, yamux, Multiaddr, SwarmBuilder,
+};
+use rand::rngs::OsRng;
+use tracing_subscriber::EnvFilter;
+
+#[derive(Debug, Parser)]
+#[clap(name = "libp2p autonatv2 client")]
+struct Opt {
+ /// Port where the client will listen for incoming connections.
+ #[clap(short = 'p', long, default_value_t = 0)]
+ listen_port: u16,
+
+ /// Address of the server where want to connect to.
+ #[clap(short = 'a', long)]
+ server_address: Multiaddr,
+
+ /// Probe interval in seconds.
+ #[clap(short = 't', long, default_value = "2")]
+ probe_interval: u64,
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box> {
+ let _ = tracing_subscriber::fmt()
+ .with_env_filter(EnvFilter::from_default_env())
+ .try_init();
+
+ let opt = Opt::parse();
+
+ let mut swarm = SwarmBuilder::with_new_identity()
+ .with_tokio()
+ .with_tcp(
+ tcp::Config::default(),
+ noise::Config::new,
+ yamux::Config::default,
+ )?
+ .with_quic()
+ .with_dns()?
+ .with_behaviour(|key| Behaviour::new(key.public(), opt.probe_interval))?
+ .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(10)))
+ .build();
+
+ swarm.listen_on(
+ Multiaddr::empty()
+ .with(Protocol::Ip4(Ipv4Addr::UNSPECIFIED))
+ .with(Protocol::Tcp(opt.listen_port)),
+ )?;
+
+ swarm.dial(
+ DialOpts::unknown_peer_id()
+ .address(opt.server_address)
+ .build(),
+ )?;
+
+ loop {
+ match swarm.select_next_some().await {
+ SwarmEvent::NewListenAddr { address, .. } => {
+ println!("Listening on {address:?}");
+ }
+ SwarmEvent::Behaviour(BehaviourEvent::Autonat(autonat::v2::client::Event {
+ server,
+ tested_addr,
+ bytes_sent,
+ result: Ok(()),
+ })) => {
+ println!("Tested {tested_addr} with {server}. Sent {bytes_sent} bytes for verification. Everything Ok and verified.");
+ }
+ SwarmEvent::Behaviour(BehaviourEvent::Autonat(autonat::v2::client::Event {
+ server,
+ tested_addr,
+ bytes_sent,
+ result: Err(e),
+ })) => {
+ println!("Tested {tested_addr} with {server}. Sent {bytes_sent} bytes for verification. Failed with {e:?}.");
+ }
+ SwarmEvent::ExternalAddrConfirmed { address } => {
+ println!("External address confirmed: {address}");
+ }
+ _ => {}
+ }
+ }
+}
+
+#[derive(NetworkBehaviour)]
+pub struct Behaviour {
+ autonat: autonat::v2::client::Behaviour,
+ identify: identify::Behaviour,
+}
+
+impl Behaviour {
+ pub fn new(key: identity::PublicKey, probe_interval: u64) -> Self {
+ Self {
+ autonat: autonat::v2::client::Behaviour::new(
+ OsRng,
+ autonat::v2::client::Config::default()
+ .with_probe_interval(Duration::from_secs(probe_interval)),
+ ),
+ identify: identify::Behaviour::new(identify::Config::new("/ipfs/0.1.0".into(), key)),
+ }
+ }
+}
diff --git a/examples/autonatv2/src/bin/autonatv2_server.rs b/examples/autonatv2/src/bin/autonatv2_server.rs
new file mode 100644
index 00000000000..849ed3b3b0a
--- /dev/null
+++ b/examples/autonatv2/src/bin/autonatv2_server.rs
@@ -0,0 +1,87 @@
+use std::{error::Error, net::Ipv4Addr, time::Duration};
+
+use cfg_if::cfg_if;
+use clap::Parser;
+use libp2p::{
+ autonat,
+ futures::StreamExt,
+ identify, identity,
+ multiaddr::Protocol,
+ noise,
+ swarm::{NetworkBehaviour, SwarmEvent},
+ tcp, yamux, Multiaddr, SwarmBuilder,
+};
+use rand::rngs::OsRng;
+
+#[derive(Debug, Parser)]
+#[clap(name = "libp2p autonatv2 server")]
+struct Opt {
+ #[clap(short, long, default_value_t = 0)]
+ listen_port: u16,
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box> {
+ cfg_if! {
+ if #[cfg(feature = "jaeger")] {
+ use tracing_subscriber::layer::SubscriberExt;
+ use opentelemetry_sdk::runtime::Tokio;
+ let tracer = opentelemetry_jaeger::new_agent_pipeline()
+ .with_endpoint("jaeger:6831")
+ .with_service_name("autonatv2")
+ .install_batch(Tokio)?;
+ let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
+ let subscriber = tracing_subscriber::Registry::default()
+ .with(telemetry);
+ } else {
+ let subscriber = tracing_subscriber::fmt()
+ .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
+ .finish();
+ }
+ }
+ tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
+
+ let opt = Opt::parse();
+
+ let mut swarm = SwarmBuilder::with_new_identity()
+ .with_tokio()
+ .with_tcp(
+ tcp::Config::default(),
+ noise::Config::new,
+ yamux::Config::default,
+ )?
+ .with_quic()
+ .with_dns()?
+ .with_behaviour(|key| Behaviour::new(key.public()))?
+ .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
+ .build();
+
+ swarm.listen_on(
+ Multiaddr::empty()
+ .with(Protocol::Ip4(Ipv4Addr::UNSPECIFIED))
+ .with(Protocol::Tcp(opt.listen_port)),
+ )?;
+
+ loop {
+ match swarm.select_next_some().await {
+ SwarmEvent::NewListenAddr { address, .. } => println!("Listening on {address:?}"),
+ SwarmEvent::Behaviour(event) => println!("{event:?}"),
+ e => println!("{e:?}"),
+ }
+ }
+}
+
+#[derive(NetworkBehaviour)]
+pub struct Behaviour {
+ autonat: autonat::v2::server::Behaviour,
+ identify: identify::Behaviour,
+}
+
+impl Behaviour {
+ pub fn new(key: identity::PublicKey) -> Self {
+ Self {
+ autonat: autonat::v2::server::Behaviour::new(OsRng),
+ identify: identify::Behaviour::new(identify::Config::new("/ipfs/0.1.0".into(), key)),
+ }
+ }
+}
diff --git a/examples/browser-webrtc/Cargo.toml b/examples/browser-webrtc/Cargo.toml
index 57232abeb5e..c3630d805fb 100644
--- a/examples/browser-webrtc/Cargo.toml
+++ b/examples/browser-webrtc/Cargo.toml
@@ -16,30 +16,30 @@ release = false
crate-type = ["cdylib"]
[dependencies]
-anyhow = "1.0.72"
-futures = "0.3.29"
+anyhow = "1.0.86"
+futures = { workspace = true }
rand = "0.8"
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tracing = { workspace = true }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
-axum = "0.6.19"
+axum = "0.7.5"
libp2p = { path = "../../libp2p", features = [ "ed25519", "macros", "ping", "tokio"] }
libp2p-webrtc = { workspace = true, features = ["tokio"] }
-rust-embed = { version = "8.0.0", features = ["include-exclude", "interpolate-folder-path"] }
-tokio = { version = "1.34", features = ["macros", "net", "rt", "signal"] }
+rust-embed = { version = "8.4.0", features = ["include-exclude", "interpolate-folder-path"] }
+tokio = { workspace = true, features = ["macros", "net", "rt", "signal"] }
tokio-util = { version = "0.7", features = ["compat"] }
tower = "0.4"
-tower-http = { version = "0.4.0", features = ["cors"] }
+tower-http = { version = "0.5.2", features = ["cors"] }
mime_guess = "2.0.4"
[target.'cfg(target_arch = "wasm32")'.dependencies]
-js-sys = "0.3.66"
+js-sys = "0.3.69"
libp2p = { path = "../../libp2p", features = [ "ed25519", "macros", "ping", "wasm-bindgen"] }
libp2p-webrtc-websys = { workspace = true }
tracing-wasm = "0.2.1"
-wasm-bindgen = "0.2.89"
-wasm-bindgen-futures = "0.4.38"
+wasm-bindgen = "0.2.90"
+wasm-bindgen-futures = "0.4.42"
web-sys = { version = "0.3", features = ['Document', 'Element', 'HtmlElement', 'Node', 'Response', 'Window'] }
[lints]
diff --git a/examples/browser-webrtc/README.md b/examples/browser-webrtc/README.md
index d44cf879905..eec2c9c0494 100644
--- a/examples/browser-webrtc/README.md
+++ b/examples/browser-webrtc/README.md
@@ -5,6 +5,8 @@ It uses [wasm-pack](https://rustwasm.github.io/docs/wasm-pack/) to build the pro
## Running the example
+Ensure you have `wasm-pack` [installed](https://rustwasm.github.io/wasm-pack/).
+
1. Build the client library:
```shell
wasm-pack build --target web --out-dir static
diff --git a/examples/browser-webrtc/src/lib.rs b/examples/browser-webrtc/src/lib.rs
index 2112919c6de..e2d884cb445 100644
--- a/examples/browser-webrtc/src/lib.rs
+++ b/examples/browser-webrtc/src/lib.rs
@@ -1,13 +1,11 @@
#![cfg(target_arch = "wasm32")]
+use std::{io, time::Duration};
+
use futures::StreamExt;
use js_sys::Date;
-use libp2p::core::Multiaddr;
-use libp2p::ping;
-use libp2p::swarm::SwarmEvent;
+use libp2p::{core::Multiaddr, ping, swarm::SwarmEvent};
use libp2p_webrtc_websys as webrtc_websys;
-use std::io;
-use std::time::Duration;
use wasm_bindgen::prelude::*;
use web_sys::{Document, HtmlElement};
@@ -15,8 +13,13 @@ use web_sys::{Document, HtmlElement};
pub async fn run(libp2p_endpoint: String) -> Result<(), JsError> {
tracing_wasm::set_as_global_default();
+ let ping_duration = Duration::from_secs(30);
+
let body = Body::from_current_window()?;
- body.append_p("Let's ping the WebRTC Server!")?;
+ body.append_p(&format!(
+ "Let's ping the rust-libp2p server over WebRTC for {:?}:",
+ ping_duration
+ ))?;
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
.with_wasm_bindgen()
@@ -24,7 +27,7 @@ pub async fn run(libp2p_endpoint: String) -> Result<(), JsError> {
webrtc_websys::Transport::new(webrtc_websys::Config::new(&key))
})?
.with_behaviour(|_| ping::Behaviour::new(ping::Config::new()))?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
+ .with_swarm_config(|c| c.with_idle_connection_timeout(ping_duration))
.build();
let addr = libp2p_endpoint.parse::()?;
@@ -46,6 +49,18 @@ pub async fn run(libp2p_endpoint: String) -> Result<(), JsError> {
tracing::info!("Ping successful: RTT: {rtt:?}, from {peer}");
body.append_p(&format!("RTT: {rtt:?} at {}", Date::new_0().to_string()))?;
}
+ SwarmEvent::ConnectionClosed {
+ cause: Some(cause), ..
+ } => {
+ tracing::info!("Swarm event: {:?}", cause);
+
+ if let libp2p::swarm::ConnectionError::KeepAliveTimeout = cause {
+ body.append_p("All done with pinging! ")?;
+
+ break;
+ }
+ body.append_p(&format!("Connection closed due to: {:?}", cause))?;
+ }
evt => tracing::info!("Swarm event: {:?}", evt),
}
}
diff --git a/examples/browser-webrtc/src/main.rs b/examples/browser-webrtc/src/main.rs
index 098b70f3054..52222dc882b 100644
--- a/examples/browser-webrtc/src/main.rs
+++ b/examples/browser-webrtc/src/main.rs
@@ -1,23 +1,25 @@
#![allow(non_upper_case_globals)]
+use std::net::{Ipv4Addr, SocketAddr};
+
use anyhow::Result;
-use axum::extract::{Path, State};
-use axum::http::header::CONTENT_TYPE;
-use axum::http::StatusCode;
-use axum::response::{Html, IntoResponse};
-use axum::{http::Method, routing::get, Router};
+use axum::{
+ extract::{Path, State},
+ http::{header::CONTENT_TYPE, Method, StatusCode},
+ response::{Html, IntoResponse},
+ routing::get,
+ Router,
+};
use futures::StreamExt;
use libp2p::{
- core::muxing::StreamMuxerBox,
- core::Transport,
+ core::{muxing::StreamMuxerBox, Transport},
multiaddr::{Multiaddr, Protocol},
ping,
swarm::SwarmEvent,
};
use libp2p_webrtc as webrtc;
use rand::thread_rng;
-use std::net::{Ipv4Addr, SocketAddr};
-use std::time::Duration;
+use tokio::net::TcpListener;
use tower_http::cors::{Any, CorsLayer};
#[tokio::main]
@@ -36,11 +38,6 @@ async fn main() -> anyhow::Result<()> {
.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)
@@ -112,10 +109,12 @@ pub(crate) async fn serve(libp2p_transport: Multiaddr) {
tracing::info!(url=%format!("http://{addr}"), "Serving client files at url");
- axum::Server::bind(&addr)
- .serve(server.into_make_service())
- .await
- .unwrap();
+ axum::serve(
+ TcpListener::bind((listen_addr, 8080)).await.unwrap(),
+ server.into_make_service(),
+ )
+ .await
+ .unwrap();
}
#[derive(Clone)]
@@ -124,7 +123,8 @@ struct Libp2pEndpoint(Multiaddr);
/// Serves the index.html file for our client.
///
/// Our server listens on a random UDP port for the WebRTC transport.
-/// To allow the client to connect, we replace the `__LIBP2P_ENDPOINT__` placeholder with the actual address.
+/// To allow the client to connect, we replace the `__LIBP2P_ENDPOINT__`
+/// placeholder with the actual address.
async fn get_index(
State(Libp2pEndpoint(libp2p_endpoint)): State,
) -> Result, StatusCode> {
diff --git a/examples/chat/Cargo.toml b/examples/chat/Cargo.toml
index 9b3561dab48..031f84b6f95 100644
--- a/examples/chat/Cargo.toml
+++ b/examples/chat/Cargo.toml
@@ -9,12 +9,10 @@ license = "MIT"
release = false
[dependencies]
-tokio = { version = "1.34", features = ["full"] }
-async-trait = "0.1"
-futures = "0.3.29"
+tokio = { workspace = true, features = ["full"] }
+futures = { workspace = true }
libp2p = { path = "../../libp2p", features = [ "tokio", "gossipsub", "mdns", "noise", "macros", "tcp", "yamux", "quic"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/chat/README.md b/examples/chat/README.md
index 96bad137b07..2dbf585100b 100644
--- a/examples/chat/README.md
+++ b/examples/chat/README.md
@@ -11,7 +11,7 @@ It showcases how peers can connect, discover each other using mDNS, and engage i
```
2. Mutual mDNS discovery may take a few seconds. When each peer does discover the other
-it will print a message like:
+ it will print a message like:
```sh
mDNS discovered a new peer: {peerId}
```
diff --git a/examples/chat/src/main.rs b/examples/chat/src/main.rs
index c785d301c2f..b0dcc767b6f 100644
--- a/examples/chat/src/main.rs
+++ b/examples/chat/src/main.rs
@@ -20,12 +20,19 @@
#![doc = include_str!("../README.md")]
+use std::{
+ collections::hash_map::DefaultHasher,
+ error::Error,
+ hash::{Hash, Hasher},
+ time::Duration,
+};
+
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};
-use std::time::Duration;
+use libp2p::{
+ gossipsub, mdns, noise,
+ swarm::{NetworkBehaviour, SwarmEvent},
+ tcp, yamux,
+};
use tokio::{io, io::AsyncBufReadExt, select};
use tracing_subscriber::EnvFilter;
@@ -61,7 +68,8 @@ async fn main() -> Result<(), Box> {
// 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)
+ .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`.
@@ -76,7 +84,6 @@ async fn main() -> Result<(), Box> {
mdns::tokio::Behaviour::new(mdns::Config::default(), key.public().to_peer_id())?;
Ok(MyBehaviour { gossipsub, mdns })
})?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
// Create a Gossipsub topic
diff --git a/examples/dcutr/Cargo.toml b/examples/dcutr/Cargo.toml
index 8dcb403218e..67edf04e2b0 100644
--- a/examples/dcutr/Cargo.toml
+++ b/examples/dcutr/Cargo.toml
@@ -9,14 +9,13 @@ license = "MIT"
release = false
[dependencies]
-clap = { version = "4.4.10", features = ["derive"] }
-futures = "0.3.29"
+clap = { version = "4.5.6", features = ["derive"] }
+futures = { workspace = true }
futures-timer = "3.0"
libp2p = { path = "../../libp2p", features = [ "dns", "dcutr", "identify", "macros", "noise", "ping", "quic", "relay", "rendezvous", "tcp", "tokio", "yamux"] }
-log = "0.4"
-tokio = { version = "1.34", features = ["macros", "net", "rt", "signal"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tokio = { workspace = true, features = ["macros", "net", "rt", "signal"] }
+tracing = { workspace = true }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/dcutr/src/main.rs b/examples/dcutr/src/main.rs
index 51df670f8a7..3f403d534e7 100644
--- a/examples/dcutr/src/main.rs
+++ b/examples/dcutr/src/main.rs
@@ -20,6 +20,8 @@
#![doc = include_str!("../README.md")]
+use std::{error::Error, str::FromStr};
+
use clap::Parser;
use futures::{executor::block_on, future::FutureExt, stream::StreamExt};
use libp2p::{
@@ -28,8 +30,6 @@ use libp2p::{
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux, PeerId,
};
-use std::str::FromStr;
-use std::{error::Error, time::Duration};
use tracing_subscriber::EnvFilter;
#[derive(Debug, Parser)]
@@ -89,7 +89,7 @@ async fn main() -> Result<(), Box> {
libp2p::SwarmBuilder::with_existing_identity(generate_ed25519(opts.secret_key_seed))
.with_tokio()
.with_tcp(
- tcp::Config::default().port_reuse(true).nodelay(true),
+ tcp::Config::default().nodelay(true),
noise::Config::new,
yamux::Config::default,
)?
@@ -105,7 +105,6 @@ async fn main() -> Result<(), Box> {
)),
dcutr: dcutr::Behaviour::new(keypair.public().to_peer_id()),
})?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
swarm
diff --git a/examples/distributed-key-value-store/Cargo.toml b/examples/distributed-key-value-store/Cargo.toml
index dc084b30091..8e30dd2c75d 100644
--- a/examples/distributed-key-value-store/Cargo.toml
+++ b/examples/distributed-key-value-store/Cargo.toml
@@ -9,12 +9,10 @@ license = "MIT"
release = false
[dependencies]
-async-std = { version = "1.12", features = ["attributes"] }
-async-trait = "0.1"
-futures = "0.3.29"
-libp2p = { path = "../../libp2p", features = [ "async-std", "dns", "kad", "mdns", "noise", "macros", "tcp", "yamux"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tokio = { workspace = true, features = ["full"] }
+futures = { workspace = true }
+libp2p = { path = "../../libp2p", features = [ "tokio", "dns", "kad", "mdns", "noise", "macros", "tcp", "yamux"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/distributed-key-value-store/README.md b/examples/distributed-key-value-store/README.md
index 6065609cfdf..4a44e0c5427 100644
--- a/examples/distributed-key-value-store/README.md
+++ b/examples/distributed-key-value-store/README.md
@@ -9,10 +9,10 @@ This example showcases a basic distributed key-value store implemented using **l
1. Open two terminal windows, type `cargo run` and press Enter.
2. In terminal one, type `PUT my-key my-value` and press Enter.
-This command will store the value `my-value` with the key `my-key` in the distributed key-value store.
+ This command will store the value `my-value` with the key `my-key` in the distributed key-value store.
3. In terminal two, type `GET my-key` and press Enter.
-This command will retrieve the value associated with the key `my-key` from the key-value store.
+ This command will retrieve the value associated with the key `my-key` from the key-value store.
4. To exit, press `Ctrl-c` in each terminal window to gracefully close the instances.
@@ -22,13 +22,13 @@ This command will retrieve the value associated with the key `my-key` from the k
You can also use provider records instead of key-value records in the distributed store.
1. Open two terminal windows and start two instances of the key-value store.
-If your local network supports mDNS, the instances will automatically connect.
+ If your local network supports mDNS, the instances will automatically connect.
2. In terminal one, type `PUT_PROVIDER my-key` and press Enter.
-This command will register the peer as a provider for the key `my-key` in the distributed key-value store.
+ This command will register the peer as a provider for the key `my-key` in the distributed key-value store.
3. In terminal two, type `GET_PROVIDERS my-key` and press Enter.
-This command will retrieve the list of providers for the key `my-key` from the key-value store.
+ This command will retrieve the list of providers for the key `my-key` from the key-value store.
4. To exit, press `Ctrl-c` in each terminal window to gracefully close the instances.
diff --git a/examples/distributed-key-value-store/src/main.rs b/examples/distributed-key-value-store/src/main.rs
index 404333f3d20..3522c84c720 100644
--- a/examples/distributed-key-value-store/src/main.rs
+++ b/examples/distributed-key-value-store/src/main.rs
@@ -20,21 +20,23 @@
#![doc = include_str!("../README.md")]
-use async_std::io;
-use futures::{prelude::*, select};
-use libp2p::kad;
-use libp2p::kad::store::MemoryStore;
-use libp2p::kad::Mode;
+use std::error::Error;
+
+use futures::stream::StreamExt;
use libp2p::{
+ kad,
+ kad::{store::MemoryStore, Mode},
mdns, noise,
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux,
};
-use std::error::Error;
-use std::time::Duration;
+use tokio::{
+ io::{self, AsyncBufReadExt},
+ select,
+};
use tracing_subscriber::EnvFilter;
-#[async_std::main]
+#[tokio::main]
async fn main() -> Result<(), Box> {
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
@@ -44,11 +46,11 @@ async fn main() -> Result<(), Box> {
#[derive(NetworkBehaviour)]
struct Behaviour {
kademlia: kad::Behaviour,
- mdns: mdns::async_io::Behaviour,
+ mdns: mdns::tokio::Behaviour,
}
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
- .with_async_std()
+ .with_tokio()
.with_tcp(
tcp::Config::default(),
noise::Config::new,
@@ -60,19 +62,18 @@ async fn main() -> Result<(), Box> {
key.public().to_peer_id(),
MemoryStore::new(key.public().to_peer_id()),
),
- mdns: mdns::async_io::Behaviour::new(
+ mdns: mdns::tokio::Behaviour::new(
mdns::Config::default(),
key.public().to_peer_id(),
)?,
})
})?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
swarm.behaviour_mut().kademlia.set_mode(Some(Mode::Server));
// Read full lines from stdin
- let mut stdin = io::BufReader::new(io::stdin()).lines().fuse();
+ let mut stdin = io::BufReader::new(io::stdin()).lines();
// Listen on all interfaces and whatever port the OS assigns.
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
@@ -80,7 +81,9 @@ async fn main() -> Result<(), Box> {
// Kick it off.
loop {
select! {
- line = stdin.select_next_some() => handle_input_line(&mut swarm.behaviour_mut().kademlia, line.expect("Stdin not to close")),
+ Ok(Some(line)) = stdin.next_line() => {
+ handle_input_line(&mut swarm.behaviour_mut().kademlia, line);
+ }
event = swarm.select_next_some() => match event {
SwarmEvent::NewListenAddr { address, .. } => {
println!("Listening in {address:?}");
diff --git a/examples/file-sharing/Cargo.toml b/examples/file-sharing/Cargo.toml
index 52d1b3b9b20..021215c003b 100644
--- a/examples/file-sharing/Cargo.toml
+++ b/examples/file-sharing/Cargo.toml
@@ -10,14 +10,11 @@ release = false
[dependencies]
serde = { version = "1.0", features = ["derive"] }
-async-std = { version = "1.12", features = ["attributes"] }
-clap = { version = "4.4.10", features = ["derive"] }
-either = "1.9"
-futures = "0.3.29"
-libp2p = { path = "../../libp2p", features = [ "async-std", "cbor", "dns", "kad", "noise", "macros", "request-response", "tcp", "websocket", "yamux"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
-void = "1.0.2"
+tokio = { workspace = true, features = ["full"] }
+clap = { version = "4.5.6", features = ["derive"] }
+futures = { workspace = true }
+libp2p = { path = "../../libp2p", features = [ "tokio", "cbor", "dns", "kad", "noise", "macros", "request-response", "tcp", "websocket", "yamux"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/file-sharing/README.md b/examples/file-sharing/README.md
index 2a2b3ec5317..5424026bb12 100644
--- a/examples/file-sharing/README.md
+++ b/examples/file-sharing/README.md
@@ -12,28 +12,28 @@ Retrievers can locate and retrieve files by their names from any node in the net
Let's understand the flow of the file sharing process:
- **File Providers**: Nodes A and B serve as file providers.
-Each node offers a specific file: file FA for node A and file FB for node B.
-To make their files available, they advertise themselves as providers on the DHT using `libp2p-kad`.
-This enables other nodes in the network to discover and retrieve their files.
+ Each node offers a specific file: file FA for node A and file FB for node B.
+ To make their files available, they advertise themselves as providers on the DHT using `libp2p-kad`.
+ This enables other nodes in the network to discover and retrieve their files.
- **File Retrievers**: Node C acts as a file retriever.
-It wants to retrieve either file FA or FB.
-Using `libp2p-kad`, it can locate the providers for these files on the DHT without being directly connected to them.
-Node C connects to the corresponding provider node and requests the file content using `libp2p-request-response`.
+ It wants to retrieve either file FA or FB.
+ Using `libp2p-kad`, it can locate the providers for these files on the DHT without being directly connected to them.
+ Node C connects to the corresponding provider node and requests the file content using `libp2p-request-response`.
- **DHT and Network Connectivity**: The DHT (Distributed Hash Table) plays a crucial role in the file sharing process.
-It allows nodes to store and discover information about file providers.
-Nodes in the network are interconnected via the DHT, enabling efficient file discovery and retrieval.
+ It allows nodes to store and discover information about file providers.
+ Nodes in the network are interconnected via the DHT, enabling efficient file discovery and retrieval.
## Architectural Properties
The File Sharing application has the following architectural properties:
- **Clean and Clonable Interface**: The application provides a clean and clonable async/await interface, allowing users to interact with the network layer seamlessly.
-The `Client` module encapsulates the necessary functionality for network communication.
+ The `Client` module encapsulates the necessary functionality for network communication.
- **Efficient Network Handling**: The application operates with a single task that drives the network layer.
-This design choice ensures efficient network communication without the need for locks or complex synchronization mechanisms.
+ This design choice ensures efficient network communication without the need for locks or complex synchronization mechanisms.
## Usage
diff --git a/examples/file-sharing/src/main.rs b/examples/file-sharing/src/main.rs
index a834ee0600e..1e3b80a330c 100644
--- a/examples/file-sharing/src/main.rs
+++ b/examples/file-sharing/src/main.rs
@@ -22,18 +22,15 @@
mod network;
-use async_std::task::spawn;
-use clap::Parser;
+use std::{error::Error, io::Write, path::PathBuf};
-use futures::prelude::*;
-use futures::StreamExt;
+use clap::Parser;
+use futures::{prelude::*, StreamExt};
use libp2p::{core::Multiaddr, multiaddr::Protocol};
-use std::error::Error;
-use std::io::Write;
-use std::path::PathBuf;
+use tokio::task::spawn;
use tracing_subscriber::EnvFilter;
-#[async_std::main]
+#[tokio::main]
async fn main() -> Result<(), Box> {
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
diff --git a/examples/file-sharing/src/network.rs b/examples/file-sharing/src/network.rs
index 59625fc39ea..409255ee9ec 100644
--- a/examples/file-sharing/src/network.rs
+++ b/examples/file-sharing/src/network.rs
@@ -1,6 +1,14 @@
-use futures::channel::{mpsc, oneshot};
-use futures::prelude::*;
+use std::{
+ collections::{hash_map, HashMap, HashSet},
+ error::Error,
+ time::Duration,
+};
+use futures::{
+ channel::{mpsc, oneshot},
+ prelude::*,
+ StreamExt,
+};
use libp2p::{
core::Multiaddr,
identity, kad,
@@ -8,19 +16,13 @@ use libp2p::{
noise,
request_response::{self, OutboundRequestId, ProtocolSupport, ResponseChannel},
swarm::{NetworkBehaviour, Swarm, SwarmEvent},
- tcp, yamux, PeerId,
+ tcp, yamux, PeerId, StreamProtocol,
};
-
-use libp2p::StreamProtocol;
use serde::{Deserialize, Serialize};
-use std::collections::{hash_map, HashMap, HashSet};
-use std::error::Error;
-use std::time::Duration;
/// Creates the network components, namely:
///
-/// - The network client to interact with the network layer from anywhere
-/// within your application.
+/// - The network client to interact with the network layer from anywhere within your application.
///
/// - The network event stream, e.g. for incoming requests.
///
@@ -40,7 +42,7 @@ pub(crate) async fn new(
let peer_id = id_keys.public().to_peer_id();
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(id_keys)
- .with_async_std()
+ .with_tokio()
.with_tcp(
tcp::Config::default(),
noise::Config::new,
@@ -197,8 +199,8 @@ impl EventLoop {
pub(crate) async fn run(mut self) {
loop {
- futures::select! {
- event = self.swarm.next() => self.handle_event(event.expect("Swarm stream to be infinite.")).await ,
+ tokio::select! {
+ event = self.swarm.select_next_some() => self.handle_event(event).await,
command = self.command_receiver.next() => match command {
Some(c) => self.handle_command(c).await,
// Command channel closed, thus shutting down the network event loop.
diff --git a/examples/identify/Cargo.toml b/examples/identify/Cargo.toml
index 48449636c61..c18f71a0386 100644
--- a/examples/identify/Cargo.toml
+++ b/examples/identify/Cargo.toml
@@ -9,12 +9,10 @@ license = "MIT"
release = false
[dependencies]
-async-std = { version = "1.12", features = ["attributes"] }
-async-trait = "0.1"
-futures = "0.3.29"
-libp2p = { path = "../../libp2p", features = ["async-std", "dns", "dcutr", "identify", "macros", "noise", "ping", "relay", "rendezvous", "tcp", "tokio","yamux"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tokio = { version = "1.37.0", features = ["full"] }
+futures = { workspace = true }
+libp2p = { path = "../../libp2p", features = ["identify", "noise", "tcp", "tokio", "yamux"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/identify/src/main.rs b/examples/identify/src/main.rs
index 916317a5a43..3f08ac01e23 100644
--- a/examples/identify/src/main.rs
+++ b/examples/identify/src/main.rs
@@ -20,19 +20,20 @@
#![doc = include_str!("../README.md")]
+use std::error::Error;
+
use futures::StreamExt;
use libp2p::{core::multiaddr::Multiaddr, identify, noise, swarm::SwarmEvent, tcp, yamux};
-use std::{error::Error, time::Duration};
use tracing_subscriber::EnvFilter;
-#[async_std::main]
+#[tokio::main]
async fn main() -> Result<(), Box> {
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init();
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
- .with_async_std()
+ .with_tokio()
.with_tcp(
tcp::Config::default(),
noise::Config::new,
@@ -44,7 +45,6 @@ async fn main() -> Result<(), Box> {
key.public(),
))
})?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
// Tell the swarm to listen on all interfaces and a random, OS-assigned
diff --git a/examples/ipfs-kad/Cargo.toml b/examples/ipfs-kad/Cargo.toml
index 7870d3adb79..fa04da4edcf 100644
--- a/examples/ipfs-kad/Cargo.toml
+++ b/examples/ipfs-kad/Cargo.toml
@@ -9,15 +9,12 @@ license = "MIT"
release = false
[dependencies]
-tokio = { version = "1.34", features = ["rt-multi-thread", "macros"] }
-async-trait = "0.1"
-clap = { version = "4.4.10", features = ["derive"] }
-env_logger = "0.10"
-futures = "0.3.29"
-anyhow = "1.0.75"
+tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
+clap = { version = "4.5.6", features = ["derive"] }
+futures = { workspace = true }
+anyhow = "1.0.86"
libp2p = { path = "../../libp2p", features = [ "tokio", "dns", "kad", "noise", "tcp", "yamux", "rsa"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/ipfs-kad/README.md b/examples/ipfs-kad/README.md
index ccefb6b1d9f..05556c89382 100644
--- a/examples/ipfs-kad/README.md
+++ b/examples/ipfs-kad/README.md
@@ -11,7 +11,7 @@ By running this example, users can gain a better understanding of how the Kademl
The example code demonstrates how to perform Kademlia queries on the IPFS network using the Rust P2P Library.
-### Getting closes peers
+### Getting closest peers
By specifying a peer ID as a parameter, the code will search for the closest peers to the given peer ID.
@@ -87,5 +87,5 @@ Failed to insert the PK record
## Conclusion
In conclusion, this example provides a practical demonstration of using the Rust P2P Library to interact with the Kademlia protocol on the IPFS network.
-By examining the code and running the example, users can gain insights into the inner workings of Kademlia and how it performs various basic actions like getting the closes peers or inserting records into the DHT.
+By examining the code and running the example, users can gain insights into the inner workings of Kademlia and how it performs various basic actions like getting the closest peers or inserting records into the DHT.
This knowledge can be valuable when developing peer-to-peer applications or understanding decentralized networks.
diff --git a/examples/ipfs-kad/src/main.rs b/examples/ipfs-kad/src/main.rs
index 0d11bdd851a..8d9a289bdd1 100644
--- a/examples/ipfs-kad/src/main.rs
+++ b/examples/ipfs-kad/src/main.rs
@@ -20,14 +20,21 @@
#![doc = include_str!("../README.md")]
-use std::num::NonZeroUsize;
-use std::ops::Add;
-use std::time::{Duration, Instant};
+use std::{
+ num::NonZeroUsize,
+ ops::Add,
+ time::{Duration, Instant},
+};
use anyhow::{bail, Result};
use clap::Parser;
use futures::StreamExt;
-use libp2p::{bytes::BufMut, identity, kad, noise, swarm::SwarmEvent, tcp, yamux, PeerId};
+use libp2p::{
+ bytes::BufMut,
+ identity, kad, noise,
+ swarm::{StreamProtocol, SwarmEvent},
+ tcp, yamux, PeerId,
+};
use tracing_subscriber::EnvFilter;
const BOOTNODES: [&str; 4] = [
@@ -37,6 +44,8 @@ const BOOTNODES: [&str; 4] = [
"QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
];
+const IPFS_PROTO_NAME: StreamProtocol = StreamProtocol::new("/ipfs/kad/1.0.0");
+
#[tokio::main]
async fn main() -> Result<()> {
let _ = tracing_subscriber::fmt()
@@ -56,12 +65,11 @@ async fn main() -> Result<()> {
.with_dns()?
.with_behaviour(|key| {
// Create a Kademlia behaviour.
- let mut cfg = kad::Config::default();
+ let mut cfg = kad::Config::new(IPFS_PROTO_NAME);
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)
})?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
.build();
// Add the bootnodes to the local routing table. `libp2p-dns` built
diff --git a/examples/ipfs-private/Cargo.toml b/examples/ipfs-private/Cargo.toml
index 97c1ca59368..4dfe596d609 100644
--- a/examples/ipfs-private/Cargo.toml
+++ b/examples/ipfs-private/Cargo.toml
@@ -9,13 +9,11 @@ license = "MIT"
release = false
[dependencies]
-tokio = { version = "1.34", features = ["rt-multi-thread", "macros", "io-std"] }
-async-trait = "0.1"
-either = "1.9"
-futures = "0.3.29"
+tokio = { workspace = true, features = ["rt-multi-thread", "macros", "io-std"] }
+either = "1.12"
+futures = { workspace = true }
libp2p = { path = "../../libp2p", features = [ "tokio", "gossipsub", "dns", "identify", "kad", "macros", "noise", "ping", "pnet", "tcp", "websocket", "yamux"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/ipfs-private/README.md b/examples/ipfs-private/README.md
index bc3b12a7ac8..ae7fc42c9c4 100644
--- a/examples/ipfs-private/README.md
+++ b/examples/ipfs-private/README.md
@@ -24,11 +24,11 @@ To run the example, follow these steps:
2. Once the example is running, you can interact with the IPFS node using the following commands:
- **Pubsub (Gossipsub):** You can use the gossipsub protocol to send and receive messages on the "chat" topic.
- To send a message, type it in the console and press Enter.
- The message will be broadcasted to other connected nodes using gossipsub.
+ To send a message, type it in the console and press Enter.
+ The message will be broadcasted to other connected nodes using gossipsub.
- **Ping:** You can ping other connected nodes to test network connectivity.
- The example will display the round-trip time (RTT) for successful pings or indicate if a timeout occurs.
+ The example will display the round-trip time (RTT) for successful pings or indicate if a timeout occurs.
## Conclusion
diff --git a/examples/ipfs-private/src/main.rs b/examples/ipfs-private/src/main.rs
index a57bfd465e0..6d8f9beb75d 100644
--- a/examples/ipfs-private/src/main.rs
+++ b/examples/ipfs-private/src/main.rs
@@ -20,6 +20,8 @@
#![doc = include_str!("../README.md")]
+use std::{env, error::Error, fs, path::Path, str::FromStr};
+
use either::Either;
use futures::prelude::*;
use libp2p::{
@@ -31,7 +33,6 @@ use libp2p::{
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux, Multiaddr, Transport,
};
-use std::{env, error::Error, fs, path::Path, str::FromStr, time::Duration};
use tokio::{io, io::AsyncBufReadExt, select};
use tracing_subscriber::EnvFilter;
@@ -151,7 +152,6 @@ async fn main() -> Result<(), Box> {
ping: ping::Behaviour::new(ping::Config::new()),
})
})?
- .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
.build();
println!("Subscribing to {gossipsub_topic:?}");
diff --git a/examples/metrics/Cargo.toml b/examples/metrics/Cargo.toml
index c8f74a17ebd..ad2941e3761 100644
--- a/examples/metrics/Cargo.toml
+++ b/examples/metrics/Cargo.toml
@@ -9,17 +9,17 @@ license = "MIT"
release = false
[dependencies]
-futures = "0.3.29"
-hyper = { version = "0.14", features = ["server", "tcp", "http1"] }
+futures = { workspace = true }
+axum = "0.7"
libp2p = { path = "../../libp2p", features = ["tokio", "metrics", "ping", "noise", "identify", "tcp", "yamux", "macros"] }
-opentelemetry = { version = "0.20.0", features = ["rt-tokio", "metrics"] }
-opentelemetry-otlp = { version = "0.13.0", features = ["metrics"]}
-opentelemetry_api = "0.20.0"
+opentelemetry = { version = "0.27.0", features = ["metrics"] }
+opentelemetry-otlp = { version = "0.27.0", features = ["metrics"] }
+opentelemetry_sdk = { version = "0.27.0", features = ["rt-tokio", "metrics"] }
prometheus-client = { workspace = true }
-tokio = { version = "1", features = ["full"] }
-tracing = "0.1.37"
-tracing-opentelemetry = "0.21.0"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tokio = { workspace = true, features = ["full"] }
+tracing = { workspace = true }
+tracing-opentelemetry = "0.28.0"
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/metrics/src/http_service.rs b/examples/metrics/src/http_service.rs
index 8c77d724ea3..f1485832d86 100644
--- a/examples/metrics/src/http_service.rs
+++ b/examples/metrics/src/http_service.rs
@@ -18,109 +18,58 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
-use hyper::http::StatusCode;
-use hyper::service::Service;
-use hyper::{Body, Method, Request, Response, Server};
-use prometheus_client::encoding::text::encode;
-use prometheus_client::registry::Registry;
-use std::future::Future;
-use std::pin::Pin;
-use std::sync::{Arc, Mutex};
-use std::task::{Context, Poll};
+use std::{
+ net::SocketAddr,
+ sync::{Arc, Mutex},
+};
+
+use axum::{extract::State, http::StatusCode, response::IntoResponse, routing::get, Router};
+use prometheus_client::{encoding::text::encode, registry::Registry};
+use tokio::net::TcpListener;
const METRICS_CONTENT_TYPE: &str = "application/openmetrics-text;charset=utf-8;version=1.0.0";
pub(crate) async fn metrics_server(registry: Registry) -> Result<(), std::io::Error> {
// Serve on localhost.
- let addr = ([127, 0, 0, 1], 0).into();
-
- let server = Server::bind(&addr).serve(MakeMetricService::new(registry));
- tracing::info!(metrics_server=%format!("http://{}/metrics", server.local_addr()));
- if let Err(e) = server.await {
- tracing::error!("server error: {}", e);
- }
+ let addr: SocketAddr = ([127, 0, 0, 1], 0).into();
+ let service = MetricService::new(registry);
+ let server = Router::new()
+ .route("/metrics", get(respond_with_metrics))
+ .with_state(service);
+ let tcp_listener = TcpListener::bind(addr).await?;
+ let local_addr = tcp_listener.local_addr()?;
+ tracing::info!(metrics_server=%format!("http://{}/metrics", local_addr));
+ axum::serve(tcp_listener, server.into_make_service()).await?;
Ok(())
}
+#[derive(Clone)]
pub(crate) struct MetricService {
reg: Arc>,
}
-type SharedRegistry = Arc>;
-
-impl MetricService {
- fn get_reg(&mut self) -> SharedRegistry {
- Arc::clone(&self.reg)
- }
- fn respond_with_metrics(&mut self) -> Response {
- let mut response: Response = Response::default();
-
- response.headers_mut().insert(
- hyper::header::CONTENT_TYPE,
- METRICS_CONTENT_TYPE.try_into().unwrap(),
- );
-
- let reg = self.get_reg();
- encode(&mut response.body_mut(), ®.lock().unwrap()).unwrap();
-
- *response.status_mut() = StatusCode::OK;
+async fn respond_with_metrics(state: State) -> impl IntoResponse {
+ let mut sink = String::new();
+ let reg = state.get_reg();
+ encode(&mut sink, ®.lock().unwrap()).unwrap();
- response
- }
- fn respond_with_404_not_found(&mut self) -> Response {
- Response::builder()
- .status(StatusCode::NOT_FOUND)
- .body("Not found try localhost:[port]/metrics".to_string())
- .unwrap()
- }
+ (
+ StatusCode::OK,
+ [(axum::http::header::CONTENT_TYPE, METRICS_CONTENT_TYPE)],
+ sink,
+ )
}
-impl Service> for MetricService {
- type Response = Response;
- type Error = hyper::Error;
- type Future = Pin> + Send>>;
-
- fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> {
- Poll::Ready(Ok(()))
- }
-
- fn call(&mut self, req: Request) -> Self::Future {
- let req_path = req.uri().path();
- let req_method = req.method();
- let resp = if (req_method == Method::GET) && (req_path == "/metrics") {
- // Encode and serve metrics from registry.
- self.respond_with_metrics()
- } else {
- self.respond_with_404_not_found()
- };
- Box::pin(async { Ok(resp) })
- }
-}
-
-pub(crate) struct MakeMetricService {
- reg: SharedRegistry,
-}
+type SharedRegistry = Arc>;
-impl MakeMetricService {
- pub(crate) fn new(registry: Registry) -> MakeMetricService {
- MakeMetricService {
+impl MetricService {
+ fn new(registry: Registry) -> Self {
+ Self {
reg: Arc::new(Mutex::new(registry)),
}
}
-}
-
-impl Service for MakeMetricService {
- type Response = MetricService;
- type Error = hyper::Error;
- type Future = Pin> + Send>>;
-
- fn poll_ready(&mut self, _: &mut Context) -> Poll> {
- Poll::Ready(Ok(()))
- }
- fn call(&mut self, _: T) -> Self::Future {
- let reg = self.reg.clone();
- let fut = async move { Ok(MetricService { reg }) };
- Box::pin(fut)
+ fn get_reg(&self) -> SharedRegistry {
+ Arc::clone(&self.reg)
}
}
diff --git a/examples/metrics/src/main.rs b/examples/metrics/src/main.rs
index 3ab6815cb32..6f6e9d08e31 100644
--- a/examples/metrics/src/main.rs
+++ b/examples/metrics/src/main.rs
@@ -20,19 +20,22 @@
#![doc = include_str!("../README.md")]
+use std::error::Error;
+
use futures::StreamExt;
-use libp2p::core::Multiaddr;
-use libp2p::metrics::{Metrics, Recorder};
-use libp2p::swarm::{NetworkBehaviour, SwarmEvent};
-use libp2p::{identify, identity, noise, ping, tcp, yamux};
-use opentelemetry::sdk;
-use opentelemetry_api::KeyValue;
+use libp2p::{
+ core::Multiaddr,
+ identify, identity,
+ metrics::{Metrics, Recorder},
+ noise, ping,
+ swarm::{NetworkBehaviour, SwarmEvent},
+ tcp, yamux,
+};
+use opentelemetry::{trace::TracerProvider as _, KeyValue};
+use opentelemetry_otlp::SpanExporter;
+use opentelemetry_sdk::{runtime, trace::TracerProvider};
use prometheus_client::registry::Registry;
-use std::error::Error;
-use std::time::Duration;
-use tracing_subscriber::layer::SubscriberExt;
-use tracing_subscriber::util::SubscriberInitExt;
-use tracing_subscriber::{EnvFilter, Layer};
+use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
mod http_service;
@@ -51,7 +54,6 @@ async fn main() -> Result<(), Box> {
)?
.with_bandwidth_metrics(&mut metric_registry)
.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()?)?;
@@ -67,6 +69,13 @@ async fn main() -> Result<(), Box> {
loop {
match swarm.select_next_some().await {
+ SwarmEvent::NewListenAddr { address, .. } => {
+ tracing::info!(
+ "Local node is listening on\n {}/p2p/{}",
+ address,
+ swarm.local_peer_id()
+ );
+ }
SwarmEvent::Behaviour(BehaviourEvent::Ping(ping_event)) => {
tracing::info!(?ping_event);
metrics.record(&ping_event);
@@ -84,25 +93,24 @@ async fn main() -> Result<(), Box> {
}
fn setup_tracing() -> Result<(), Box> {
- let tracer = opentelemetry_otlp::new_pipeline()
- .tracing()
- .with_exporter(opentelemetry_otlp::new_exporter().tonic())
- .with_trace_config(
- sdk::trace::Config::default().with_resource(sdk::Resource::new(vec![KeyValue::new(
- "service.name",
- "libp2p",
- )])),
+ let provider = TracerProvider::builder()
+ .with_batch_exporter(
+ SpanExporter::builder().with_tonic().build()?,
+ runtime::Tokio,
)
- .install_batch(opentelemetry::runtime::Tokio)?;
-
+ .with_resource(opentelemetry_sdk::Resource::new(vec![KeyValue::new(
+ "service.name",
+ "libp2p",
+ )]))
+ .build();
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer().with_filter(EnvFilter::from_default_env()))
.with(
tracing_opentelemetry::layer()
- .with_tracer(tracer)
+ .with_tracer(provider.tracer("libp2p-subscriber"))
.with_filter(EnvFilter::from_default_env()),
)
- .try_init()?;
+ .init();
Ok(())
}
diff --git a/examples/ping/Cargo.toml b/examples/ping/Cargo.toml
index 66d2847cb8f..acc3b2affed 100644
--- a/examples/ping/Cargo.toml
+++ b/examples/ping/Cargo.toml
@@ -9,11 +9,10 @@ license = "MIT"
release = false
[dependencies]
-futures = "0.3.29"
+futures = { workspace = true }
libp2p = { path = "../../libp2p", features = ["noise", "ping", "tcp", "tokio", "yamux"] }
-tokio = { version = "1.34.0", features = ["full"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tokio = { workspace = true, features = ["full"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/ping/src/main.rs b/examples/ping/src/main.rs
index 911b0384f89..565ef057c0d 100644
--- a/examples/ping/src/main.rs
+++ b/examples/ping/src/main.rs
@@ -20,9 +20,10 @@
#![doc = include_str!("../README.md")]
+use std::{error::Error, time::Duration};
+
use futures::prelude::*;
use libp2p::{noise, ping, swarm::SwarmEvent, tcp, yamux, Multiaddr};
-use std::{error::Error, time::Duration};
use tracing_subscriber::EnvFilter;
#[tokio::main]
diff --git a/examples/relay-server/Cargo.toml b/examples/relay-server/Cargo.toml
index fe18106e60c..3bdaf89b04f 100644
--- a/examples/relay-server/Cargo.toml
+++ b/examples/relay-server/Cargo.toml
@@ -9,13 +9,11 @@ license = "MIT"
release = false
[dependencies]
-clap = { version = "4.4.10", features = ["derive"] }
-async-std = { version = "1.12", features = ["attributes"] }
-async-trait = "0.1"
-futures = "0.3.2"
-libp2p = { path = "../../libp2p", features = [ "async-std", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay", "quic"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+clap = { version = "4.5.6", features = ["derive"] }
+tokio = { version = "1.37.0", features = ["full"] }
+futures = { workspace = true }
+libp2p = { path = "../../libp2p", features = ["tokio", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay", "quic"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/relay-server/README.md b/examples/relay-server/README.md
index ae2ab3fdfd8..cd8f0340a5a 100644
--- a/examples/relay-server/README.md
+++ b/examples/relay-server/README.md
@@ -16,7 +16,7 @@ To run the example, follow these steps:
Replace `` with a seed value used to generate a deterministic peer ID for the relay node.
2. The relay node will start listening for incoming connections.
-It will print the listening address once it is ready.
+ It will print the listening address once it is ready.
3. Connect other **libp2p** nodes to the relay node by specifying the relay's listening address as one of the bootstrap nodes in their configuration.
diff --git a/examples/relay-server/src/main.rs b/examples/relay-server/src/main.rs
index bf5817454f8..b7868418fb0 100644
--- a/examples/relay-server/src/main.rs
+++ b/examples/relay-server/src/main.rs
@@ -21,21 +21,23 @@
#![doc = include_str!("../README.md")]
+use std::{
+ error::Error,
+ net::{Ipv4Addr, Ipv6Addr},
+};
+
use clap::Parser;
-use futures::executor::block_on;
-use futures::stream::StreamExt;
+use futures::StreamExt;
use libp2p::{
- core::multiaddr::Protocol,
- core::Multiaddr,
+ core::{multiaddr::Protocol, Multiaddr},
identify, identity, noise, ping, relay,
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux,
};
-use std::error::Error;
-use std::net::{Ipv4Addr, Ipv6Addr};
use tracing_subscriber::EnvFilter;
-fn main() -> Result<(), Box> {
+#[tokio::main]
+async fn main() -> Result<(), Box> {
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init();
@@ -46,7 +48,7 @@ fn main() -> Result<(), Box> {
let local_key: identity::Keypair = generate_ed25519(opt.secret_key_seed);
let mut swarm = libp2p::SwarmBuilder::with_existing_identity(local_key)
- .with_async_std()
+ .with_tokio()
.with_tcp(
tcp::Config::default(),
noise::Config::new,
@@ -81,27 +83,25 @@ fn main() -> Result<(), Box> {
.with(Protocol::QuicV1);
swarm.listen_on(listen_addr_quic)?;
- block_on(async {
- loop {
- match swarm.next().await.expect("Infinite Stream.") {
- SwarmEvent::Behaviour(event) => {
- if let BehaviourEvent::Identify(identify::Event::Received {
- info: identify::Info { observed_addr, .. },
- ..
- }) = &event
- {
- swarm.add_external_address(observed_addr.clone());
- }
-
- println!("{event:?}")
- }
- SwarmEvent::NewListenAddr { address, .. } => {
- println!("Listening on {address:?}");
+ loop {
+ match swarm.next().await.expect("Infinite Stream.") {
+ SwarmEvent::Behaviour(event) => {
+ if let BehaviourEvent::Identify(identify::Event::Received {
+ info: identify::Info { observed_addr, .. },
+ ..
+ }) = &event
+ {
+ swarm.add_external_address(observed_addr.clone());
}
- _ => {}
+
+ println!("{event:?}")
+ }
+ SwarmEvent::NewListenAddr { address, .. } => {
+ println!("Listening on {address:?}");
}
+ _ => {}
}
- })
+ }
}
#[derive(NetworkBehaviour)]
diff --git a/examples/rendezvous/Cargo.toml b/examples/rendezvous/Cargo.toml
index fbb2ed44a03..4eea38616f4 100644
--- a/examples/rendezvous/Cargo.toml
+++ b/examples/rendezvous/Cargo.toml
@@ -9,13 +9,11 @@ license = "MIT"
release = false
[dependencies]
-async-std = { version = "1.12", features = ["attributes"] }
-async-trait = "0.1"
-futures = "0.3.29"
-libp2p = { path = "../../libp2p", features = [ "async-std", "identify", "macros", "noise", "ping", "rendezvous", "tcp", "tokio", "yamux"] }
-tokio = { version = "1.34", features = ["rt-multi-thread", "macros", "time"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+futures = { workspace = true }
+libp2p = { path = "../../libp2p", features = ["identify", "macros", "noise", "ping", "rendezvous", "tcp", "tokio", "yamux"] }
+tokio = { workspace = true, features = ["rt-multi-thread", "macros", "time"] }
+tracing = { workspace = true }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/rendezvous/src/bin/rzv-discover.rs b/examples/rendezvous/src/bin/rzv-discover.rs
index edd3d10a0ce..bdf9aeafdab 100644
--- a/examples/rendezvous/src/bin/rzv-discover.rs
+++ b/examples/rendezvous/src/bin/rzv-discover.rs
@@ -18,6 +18,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+use std::{error::Error, time::Duration};
+
use futures::StreamExt;
use libp2p::{
multiaddr::Protocol,
@@ -25,8 +27,6 @@ use libp2p::{
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux, Multiaddr,
};
-use std::error::Error;
-use std::time::Duration;
use tracing_subscriber::EnvFilter;
const NAMESPACE: &str = "rendezvous";
@@ -53,7 +53,6 @@ async fn main() -> Result<(), Box> {
rendezvous: rendezvous::client::Behaviour::new(key.clone()),
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
})?
- .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(5)))
.build();
swarm.dial(rendezvous_point_address.clone()).unwrap();
diff --git a/examples/rendezvous/src/bin/rzv-identify.rs b/examples/rendezvous/src/bin/rzv-identify.rs
index 1d545592829..00e94627292 100644
--- a/examples/rendezvous/src/bin/rzv-identify.rs
+++ b/examples/rendezvous/src/bin/rzv-identify.rs
@@ -18,13 +18,14 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+use std::time::Duration;
+
use futures::StreamExt;
use libp2p::{
identify, noise, ping, rendezvous,
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux, Multiaddr,
};
-use std::time::Duration;
use tracing_subscriber::EnvFilter;
#[tokio::main]
@@ -55,7 +56,6 @@ async fn main() {
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
})
.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());
@@ -76,8 +76,12 @@ async fn main() {
}
// once `/identify` did its job, we know our external address and can register
SwarmEvent::Behaviour(MyBehaviourEvent::Identify(identify::Event::Received {
+ info,
..
})) => {
+ // Register our external address. Needs to be done explicitly
+ // for this case, as it's a local address.
+ swarm.add_external_address(info.observed_addr);
if let Err(error) = swarm.behaviour_mut().rendezvous.register(
rendezvous::Namespace::from_static("rendezvous"),
rendezvous_point,
diff --git a/examples/rendezvous/src/bin/rzv-register.rs b/examples/rendezvous/src/bin/rzv-register.rs
index bd848238d4a..f70eda5d55e 100644
--- a/examples/rendezvous/src/bin/rzv-register.rs
+++ b/examples/rendezvous/src/bin/rzv-register.rs
@@ -18,13 +18,14 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+use std::time::Duration;
+
use futures::StreamExt;
use libp2p::{
noise, ping, rendezvous,
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux, Multiaddr,
};
-use std::time::Duration;
use tracing_subscriber::EnvFilter;
#[tokio::main]
@@ -51,11 +52,10 @@ async fn main() {
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
})
.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.
+ // 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.
let external_address = "/ip4/127.0.0.1/tcp/0".parse::().unwrap();
swarm.add_external_address(external_address);
diff --git a/examples/rendezvous/src/main.rs b/examples/rendezvous/src/main.rs
index a15bc1ca2d3..a345d0faed9 100644
--- a/examples/rendezvous/src/main.rs
+++ b/examples/rendezvous/src/main.rs
@@ -20,14 +20,14 @@
#![doc = include_str!("../README.md")]
+use std::{error::Error, time::Duration};
+
use futures::StreamExt;
use libp2p::{
identify, noise, ping, rendezvous,
swarm::{NetworkBehaviour, SwarmEvent},
tcp, yamux,
};
-use std::error::Error;
-use std::time::Duration;
use tracing_subscriber::EnvFilter;
#[tokio::main]
@@ -55,7 +55,6 @@ async fn main() -> Result<(), Box> {
rendezvous: rendezvous::server::Behaviour::new(rendezvous::server::Config::default()),
ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))),
})?
- .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());
diff --git a/examples/stream/Cargo.toml b/examples/stream/Cargo.toml
new file mode 100644
index 00000000000..ba31d4d9e13
--- /dev/null
+++ b/examples/stream/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "stream-example"
+version = "0.1.0"
+edition = "2021"
+publish = false
+license = "MIT"
+
+[package.metadata.release]
+release = false
+
+[dependencies]
+anyhow = "1"
+futures = { workspace = true }
+libp2p = { path = "../../libp2p", features = [ "tokio", "quic"] }
+libp2p-stream = { path = "../../protocols/stream", version = "0.2.0-alpha" }
+rand = "0.8"
+tokio = { workspace = true, features = ["full"] }
+tracing = { workspace = true }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
+
+[lints]
+workspace = true
diff --git a/examples/stream/README.md b/examples/stream/README.md
new file mode 100644
index 00000000000..3b0325519f7
--- /dev/null
+++ b/examples/stream/README.md
@@ -0,0 +1,35 @@
+## Description
+
+This example shows the usage of the `stream::Behaviour`.
+As a counter-part to the `request_response::Behaviour`, the `stream::Behaviour` allows users to write stream-oriented protocols whilst having minimal interaction with the `Swarm`.
+
+In this showcase, we implement an echo protocol: All incoming data is echoed back to the dialer, until the stream is closed.
+
+## Usage
+
+To run the example, follow these steps:
+
+1. Start an instance of the example in one terminal:
+
+ ```sh
+ cargo run --bin stream-example
+ ```
+
+ Observe printed listen address.
+
+2. Start another instance in a new terminal, providing the listen address of the first one.
+
+ ```sh
+ cargo run --bin stream-example --
+ ```
+
+3. Both terminals should now continuously print messages.
+
+## Conclusion
+
+The `stream::Behaviour` is an "escape-hatch" from the way typical rust-libp2p protocols are written.
+It is suitable for several scenarios including:
+
+- prototyping of new protocols
+- experimentation with rust-libp2p
+- integration in `async/await`-heavy applications
\ No newline at end of file
diff --git a/examples/stream/src/main.rs b/examples/stream/src/main.rs
new file mode 100644
index 00000000000..71d2d2fcc76
--- /dev/null
+++ b/examples/stream/src/main.rs
@@ -0,0 +1,157 @@
+use std::{io, time::Duration};
+
+use anyhow::{Context, Result};
+use futures::{AsyncReadExt, AsyncWriteExt, StreamExt};
+use libp2p::{multiaddr::Protocol, Multiaddr, PeerId, Stream, StreamProtocol};
+use libp2p_stream as stream;
+use rand::RngCore;
+use tracing::level_filters::LevelFilter;
+use tracing_subscriber::EnvFilter;
+
+const ECHO_PROTOCOL: StreamProtocol = StreamProtocol::new("/echo");
+
+#[tokio::main]
+async fn main() -> Result<()> {
+ tracing_subscriber::fmt()
+ .with_env_filter(
+ EnvFilter::builder()
+ .with_default_directive(LevelFilter::INFO.into())
+ .from_env()?,
+ )
+ .init();
+
+ let maybe_address = std::env::args()
+ .nth(1)
+ .map(|arg| arg.parse::())
+ .transpose()
+ .context("Failed to parse argument as `Multiaddr`")?;
+
+ let mut swarm = libp2p::SwarmBuilder::with_new_identity()
+ .with_tokio()
+ .with_quic()
+ .with_behaviour(|_| stream::Behaviour::new())?
+ .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(10)))
+ .build();
+
+ swarm.listen_on("/ip4/127.0.0.1/udp/0/quic-v1".parse()?)?;
+
+ let mut incoming_streams = swarm
+ .behaviour()
+ .new_control()
+ .accept(ECHO_PROTOCOL)
+ .unwrap();
+
+ // Deal with incoming streams.
+ // Spawning a dedicated task is just one way of doing this.
+ // libp2p doesn't care how you handle incoming streams but you _must_ handle them somehow.
+ // To mitigate DoS attacks, libp2p will internally drop incoming streams if your application
+ // cannot keep up processing them.
+ tokio::spawn(async move {
+ // This loop handles incoming streams _sequentially_ but that doesn't have to be the case.
+ // You can also spawn a dedicated task per stream if you want to.
+ // Be aware that this breaks backpressure though as spawning new tasks is equivalent to an
+ // unbounded buffer. Each task needs memory meaning an aggressive remote peer may
+ // force you OOM this way.
+
+ while let Some((peer, stream)) = incoming_streams.next().await {
+ match echo(stream).await {
+ Ok(n) => {
+ tracing::info!(%peer, "Echoed {n} bytes!");
+ }
+ Err(e) => {
+ tracing::warn!(%peer, "Echo failed: {e}");
+ continue;
+ }
+ };
+ }
+ });
+
+ // In this demo application, the dialing peer initiates the protocol.
+ if let Some(address) = maybe_address {
+ let Some(Protocol::P2p(peer_id)) = address.iter().last() else {
+ anyhow::bail!("Provided address does not end in `/p2p`");
+ };
+
+ swarm.dial(address)?;
+
+ tokio::spawn(connection_handler(peer_id, swarm.behaviour().new_control()));
+ }
+
+ // Poll the swarm to make progress.
+ loop {
+ let event = swarm.next().await.expect("never terminates");
+
+ match event {
+ libp2p::swarm::SwarmEvent::NewListenAddr { address, .. } => {
+ let listen_address = address.with_p2p(*swarm.local_peer_id()).unwrap();
+ tracing::info!(%listen_address);
+ }
+ event => tracing::trace!(?event),
+ }
+ }
+}
+
+/// A very simple, `async fn`-based connection handler for our custom echo protocol.
+async fn connection_handler(peer: PeerId, mut control: stream::Control) {
+ loop {
+ tokio::time::sleep(Duration::from_secs(1)).await; // Wait a second between echos.
+
+ let stream = match control.open_stream(peer, ECHO_PROTOCOL).await {
+ Ok(stream) => stream,
+ Err(error @ stream::OpenStreamError::UnsupportedProtocol(_)) => {
+ tracing::info!(%peer, %error);
+ return;
+ }
+ Err(error) => {
+ // Other errors may be temporary.
+ // In production, something like an exponential backoff / circuit-breaker may be
+ // more appropriate.
+ tracing::debug!(%peer, %error);
+ continue;
+ }
+ };
+
+ if let Err(e) = send(stream).await {
+ tracing::warn!(%peer, "Echo protocol failed: {e}");
+ continue;
+ }
+
+ tracing::info!(%peer, "Echo complete!")
+ }
+}
+
+async fn echo(mut stream: Stream) -> io::Result {
+ let mut total = 0;
+
+ let mut buf = [0u8; 100];
+
+ loop {
+ let read = stream.read(&mut buf).await?;
+ if read == 0 {
+ return Ok(total);
+ }
+
+ total += read;
+ stream.write_all(&buf[..read]).await?;
+ }
+}
+
+async fn send(mut stream: Stream) -> io::Result<()> {
+ let num_bytes = rand::random::() % 1000;
+
+ let mut bytes = vec![0; num_bytes];
+ rand::thread_rng().fill_bytes(&mut bytes);
+
+ stream.write_all(&bytes).await?;
+
+ let mut buf = vec![0; num_bytes];
+ stream.read_exact(&mut buf).await?;
+
+ if bytes != buf {
+ return Err(io::Error::new(io::ErrorKind::Other, "incorrect echo"));
+ }
+
+ stream.close().await?;
+
+ Ok(())
+}
diff --git a/examples/upnp/Cargo.toml b/examples/upnp/Cargo.toml
index 940f3dff65f..ae292e0a48d 100644
--- a/examples/upnp/Cargo.toml
+++ b/examples/upnp/Cargo.toml
@@ -9,10 +9,10 @@ license = "MIT"
release = false
[dependencies]
-tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
-futures = "0.3.29"
+tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
+futures = { workspace = true }
libp2p = { path = "../../libp2p", features = ["tokio", "dns", "macros", "noise", "ping", "tcp", "yamux", "upnp"] }
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[lints]
workspace = true
diff --git a/examples/upnp/src/main.rs b/examples/upnp/src/main.rs
index fd0764990d1..19de8d773ae 100644
--- a/examples/upnp/src/main.rs
+++ b/examples/upnp/src/main.rs
@@ -20,9 +20,10 @@
#![doc = include_str!("../README.md")]
+use std::error::Error;
+
use futures::prelude::*;
use libp2p::{noise, swarm::SwarmEvent, upnp, yamux, Multiaddr};
-use std::error::Error;
use tracing_subscriber::EnvFilter;
#[tokio::main]
diff --git a/hole-punching-tests/Cargo.toml b/hole-punching-tests/Cargo.toml
index a6f1bd6571c..c4f36d2a990 100644
--- a/hole-punching-tests/Cargo.toml
+++ b/hole-punching-tests/Cargo.toml
@@ -7,12 +7,12 @@ license = "MIT"
[dependencies]
anyhow = "1"
-env_logger = "0.10.1"
-futures = "0.3.29"
+env_logger = { workspace = true }
+futures = { workspace = true }
libp2p = { path = "../libp2p", features = ["tokio", "dcutr", "identify", "macros", "noise", "ping", "relay", "tcp", "yamux", "quic"] }
-tracing = "0.1.37"
-redis = { version = "0.23.0", default-features = false, features = ["tokio-comp"] }
-tokio = { version = "1.34.0", features = ["full"] }
-serde = { version = "1.0.193", features = ["derive"] }
-serde_json = "1.0.108"
-either = "1.9.0"
+tracing = { workspace = true }
+redis = { version = "0.24.0", default-features = false, features = ["tokio-comp"] }
+tokio = { workspace = true, features = ["full"] }
+serde = { version = "1.0.203", features = ["derive"] }
+serde_json = "1.0.117"
+either = "1.12.0"
diff --git a/hole-punching-tests/Dockerfile b/hole-punching-tests/Dockerfile
index 864f058799e..403cc301fc6 100644
--- a/hole-punching-tests/Dockerfile
+++ b/hole-punching-tests/Dockerfile
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1.5-labs
-FROM rust:1.73.0 as builder
+FROM rust:1.81.0 as builder
# Run with access to the target cache to speed up builds
WORKDIR /workspace
diff --git a/hole-punching-tests/src/main.rs b/hole-punching-tests/src/main.rs
index 4f81cd65480..bc5a1bae4f5 100644
--- a/hole-punching-tests/src/main.rs
+++ b/hole-punching-tests/src/main.rs
@@ -18,24 +18,27 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+use std::{
+ collections::HashMap,
+ fmt, io,
+ net::{IpAddr, Ipv4Addr},
+ str::FromStr,
+ time::Duration,
+};
+
use anyhow::{Context, Result};
use either::Either;
use futures::stream::StreamExt;
-use libp2p::core::transport::ListenerId;
-use libp2p::swarm::dial_opts::DialOpts;
-use libp2p::swarm::ConnectionId;
use libp2p::{
- core::multiaddr::{Multiaddr, Protocol},
+ core::{
+ multiaddr::{Multiaddr, Protocol},
+ transport::ListenerId,
+ },
dcutr, identify, noise, ping, relay,
- swarm::{NetworkBehaviour, SwarmEvent},
+ swarm::{dial_opts::DialOpts, ConnectionId, NetworkBehaviour, SwarmEvent},
tcp, yamux, Swarm,
};
use redis::AsyncCommands;
-use std::collections::HashMap;
-use std::net::{IpAddr, Ipv4Addr};
-use std::str::FromStr;
-use std::time::Duration;
-use std::{fmt, io};
/// The redis key we push the relay's TCP listen address to.
const RELAY_TCP_ADDRESS: &str = "RELAY_TCP_ADDRESS";
@@ -64,7 +67,7 @@ async fn main() -> Result<()> {
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
.with_tokio()
.with_tcp(
- tcp::Config::new().port_reuse(true).nodelay(true),
+ tcp::Config::new().nodelay(true),
noise::Config::new,
yamux::Config::default,
)?
@@ -294,9 +297,7 @@ impl RedisClient {
tracing::debug!("Pushing {key}={value} to redis");
- self.inner.rpush(key, value).await?;
-
- Ok(())
+ self.inner.rpush(key, value).await.map_err(Into::into)
}
async fn pop(&mut self, key: &str) -> Result
@@ -308,7 +309,7 @@ impl RedisClient {
let value = self
.inner
- .blpop::<_, HashMap>(key, 0)
+ .blpop::<_, HashMap>(key, 0.0)
.await?
.remove(key)
.with_context(|| format!("Failed to get value for {key} from redis"))?
diff --git a/identity/CHANGELOG.md b/identity/CHANGELOG.md
index 004943ce195..98f3e5c5636 100644
--- a/identity/CHANGELOG.md
+++ b/identity/CHANGELOG.md
@@ -1,6 +1,16 @@
+## 0.2.10
+
+- Deprecate `void` crate.
+ See [PR 5676](https://github.com/libp2p/rust-libp2p/pull/5676).
+
+## 0.2.9
+
+- Add `rand` feature gate to ecdsa methods requiring a random number generator.
+ See [PR 5212](https://github.com/libp2p/rust-libp2p/pull/5212).
+
## 0.2.8
-- Bump `ring` to `0.17.5.
+- Bump `ring` to `0.17.5`.
See [PR 4779](https://github.com/libp2p/rust-libp2p/pull/4779).
## 0.2.7
diff --git a/identity/Cargo.toml b/identity/Cargo.toml
index e7aa15fef07..b13229c5826 100644
--- a/identity/Cargo.toml
+++ b/identity/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "libp2p-identity"
-version = "0.2.8"
+version = "0.2.10"
edition = "2021"
description = "Data structures and algorithms for identifying peers in libp2p."
rust-version = "1.73.0" # MUST NOT inherit from workspace because we don't want to publish breaking changes to `libp2p-identity`.
@@ -13,28 +13,27 @@ categories = ["cryptography"]
[dependencies]
asn1_der = { version = "0.7.6", optional = true }
-bs58 = { version = "0.5.0", optional = true }
+bs58 = { version = "0.5.1", optional = true }
ed25519-dalek = { version = "2.1", optional = true }
-hkdf = { version = "0.12.3", optional = true }
+hkdf = { version = "0.12.4", optional = true }
libsecp256k1 = { version = "0.7.0", optional = true }
-tracing = "0.1.37"
+tracing = { workspace = true }
multihash = { version = "0.19.1", optional = true }
-p256 = { version = "0.13", default-features = false, features = [ "ecdsa", "std", "pem"], optional = true }
+p256 = { version = "0.13", default-features = false, features = ["ecdsa", "std", "pem"], optional = true }
quick-protobuf = "0.8.1"
rand = { version = "0.8", optional = true }
sec1 = { version = "0.7", default-features = false, optional = true }
serde = { version = "1", optional = true, features = ["derive"] }
sha2 = { version = "0.10.8", optional = true }
-thiserror = { version = "1.0", optional = true }
-void = { version = "1.0", optional = true }
-zeroize = { version = "1.7", optional = true }
+thiserror = { workspace = true, optional = true }
+zeroize = { version = "1.8", optional = true }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
-ring = { version = "0.17.5", features = [ "alloc", "std"], default-features = false, optional = true }
+ring = { workspace = true, features = ["alloc", "std"], optional = true }
[features]
secp256k1 = ["dep:libsecp256k1", "dep:asn1_der", "dep:sha2", "dep:hkdf", "dep:zeroize"]
-ecdsa = ["dep:p256", "dep:void", "dep:zeroize", "dep:sec1", "dep:sha2", "dep:hkdf"]
+ecdsa = ["dep:p256", "dep:zeroize", "dep:sec1", "dep:sha2", "dep:hkdf"]
rsa = ["dep:ring", "dep:asn1_der", "dep:rand", "dep:zeroize"]
ed25519 = ["dep:ed25519-dalek", "dep:zeroize", "dep:sha2", "dep:hkdf"]
peerid = ["dep:multihash", "dep:bs58", "dep:thiserror", "dep:sha2", "dep:hkdf"]
@@ -42,9 +41,8 @@ rand = ["dep:rand", "ed25519-dalek?/rand_core"]
[dev-dependencies]
quickcheck = { workspace = true }
-base64 = "0.21.5"
serde_json = "1.0"
-rmp-serde = "1.1"
+rmp-serde = "1.3"
criterion = "0.5"
hex-literal = "0.4.1"
@@ -56,8 +54,6 @@ harness = false
# More information: https://docs.rs/about/builds#cross-compiling
[package.metadata.docs.rs]
all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
-rustc-args = ["--cfg", "docsrs"]
[lints]
workspace = true
diff --git a/identity/src/ecdsa.rs b/identity/src/ecdsa.rs
index 2f1a286d46d..11cdaced795 100644
--- a/identity/src/ecdsa.rs
+++ b/identity/src/ecdsa.rs
@@ -20,10 +20,9 @@
//! ECDSA keys with secp256r1 curve support.
-use super::error::DecodingError;
-use core::cmp;
-use core::fmt;
-use core::hash;
+use core::{cmp, fmt, hash};
+use std::convert::Infallible;
+
use p256::{
ecdsa::{
signature::{Signer, Verifier},
@@ -32,9 +31,10 @@ use p256::{
EncodedPoint,
};
use sec1::{DecodeEcPrivateKey, EncodeEcPrivateKey};
-use void::Void;
use zeroize::Zeroize;
+use super::error::DecodingError;
+
/// An ECDSA keypair generated using `secp256r1` curve.
#[derive(Clone)]
pub struct Keypair {
@@ -94,6 +94,7 @@ pub struct SecretKey(SigningKey);
impl SecretKey {
/// Generate a new random ECDSA secret key.
+ #[cfg(feature = "rand")]
pub fn generate() -> SecretKey {
SecretKey(SigningKey::random(&mut rand::thread_rng()))
}
@@ -157,7 +158,8 @@ impl PublicKey {
self.0.verify(msg, &sig).is_ok()
}
- /// Try to parse a public key from a byte buffer containing raw components of a key with or without compression.
+ /// Try to parse a public key from a byte buffer containing raw
+ /// components of a key with or without compression.
pub fn try_from_bytes(k: &[u8]) -> Result {
let enc_pt = EncodedPoint::from_bytes(k)
.map_err(|e| DecodingError::failed_to_parse("ecdsa p256 encoded point", e))?;
@@ -167,7 +169,8 @@ impl PublicKey {
.map(PublicKey)
}
- /// Convert a public key into a byte buffer containing raw components of the key without compression.
+ /// Convert a public key into a byte buffer containing
+ /// raw components of the key without compression.
pub fn to_bytes(&self) -> Vec {
self.0.to_encoded_point(false).as_bytes().to_owned()
}
@@ -181,7 +184,10 @@ impl PublicKey {
/// Try to decode a public key from a DER encoded byte buffer as defined by SEC1 standard.
pub fn try_decode_der(k: &[u8]) -> Result {
let buf = Self::del_asn1_header(k).ok_or_else(|| {
- DecodingError::failed_to_parse::("ASN.1-encoded ecdsa p256 public key", None)
+ DecodingError::failed_to_parse::(
+ "ASN.1-encoded ecdsa p256 public key",
+ None,
+ )
})?;
Self::try_from_bytes(buf)
}
diff --git a/identity/src/ed25519.rs b/identity/src/ed25519.rs
index 529a4dddea1..5a1a53dd4af 100644
--- a/identity/src/ed25519.rs
+++ b/identity/src/ed25519.rs
@@ -20,14 +20,13 @@
//! Ed25519 keys.
-use super::error::DecodingError;
-use core::cmp;
-use core::fmt;
-use core::hash;
+use core::{cmp, fmt, hash};
+
use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
-use std::convert::TryFrom;
use zeroize::Zeroize;
+use super::error::DecodingError;
+
/// An Ed25519 keypair.
#[derive(Clone)]
pub struct Keypair(ed25519::SigningKey);
@@ -153,7 +152,8 @@ impl PublicKey {
self.0.to_bytes()
}
- /// Try to parse a public key from a byte array containing the actual key as produced by `to_bytes`.
+ /// Try to parse a public key from a byte array containing
+ /// the actual key as produced by `to_bytes`.
pub fn try_from_bytes(k: &[u8]) -> Result {
let k = <[u8; 32]>::try_from(k)
.map_err(|e| DecodingError::failed_to_parse("Ed25519 public key", e))?;
@@ -207,9 +207,10 @@ impl SecretKey {
#[cfg(test)]
mod tests {
- use super::*;
use quickcheck::*;
+ use super::*;
+
fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes()
}
diff --git a/identity/src/error.rs b/identity/src/error.rs
index 71cd78fe1ea..6e8c4d02caa 100644
--- a/identity/src/error.rs
+++ b/identity/src/error.rs
@@ -20,8 +20,7 @@
//! Errors during identity key operations.
-use std::error::Error;
-use std::fmt;
+use std::{error::Error, fmt};
use crate::KeyType;
diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs
index bdfb68c0091..a1bbba00fa9 100644
--- a/identity/src/keypair.rs
+++ b/identity/src/keypair.rs
@@ -24,42 +24,40 @@
feature = "ed25519",
feature = "rsa"
))]
-use crate::error::OtherVariantError;
-use crate::error::{DecodingError, SigningError};
+use quick_protobuf::{BytesReader, Writer};
+
+#[cfg(feature = "ecdsa")]
+use crate::ecdsa;
#[cfg(any(
feature = "ecdsa",
feature = "secp256k1",
feature = "ed25519",
feature = "rsa"
))]
-use crate::proto;
+#[cfg(feature = "ed25519")]
+use crate::ed25519;
#[cfg(any(
feature = "ecdsa",
feature = "secp256k1",
feature = "ed25519",
feature = "rsa"
))]
-use quick_protobuf::{BytesReader, Writer};
+use crate::error::OtherVariantError;
#[cfg(any(
feature = "ecdsa",
feature = "secp256k1",
feature = "ed25519",
feature = "rsa"
))]
-use std::convert::TryFrom;
-
-#[cfg(feature = "ed25519")]
-use crate::ed25519;
-
+use crate::proto;
#[cfg(all(feature = "rsa", not(target_arch = "wasm32")))]
use crate::rsa;
-
#[cfg(feature = "secp256k1")]
use crate::secp256k1;
-
-#[cfg(feature = "ecdsa")]
-use crate::ecdsa;
-use crate::KeyType;
+use crate::{
+ error::{DecodingError, SigningError},
+ KeyType,
+};
/// Identity keypair of a node.
///
@@ -77,7 +75,6 @@ use crate::KeyType;
/// let mut bytes = std::fs::read("private.pk8").unwrap();
/// let keypair = Keypair::rsa_from_pkcs8(&mut bytes);
/// ```
-///
#[derive(Debug, Clone)]
pub struct Keypair {
keypair: KeyPairInner,
@@ -343,7 +340,8 @@ impl Keypair {
}
}
- /// Deterministically derive a new secret from this [`Keypair`], taking into account the provided domain.
+ /// Deterministically derive a new secret from this [`Keypair`],
+ /// taking into account the provided domain.
///
/// This works for all key types except RSA where it returns `None`.
///
@@ -354,10 +352,11 @@ impl Keypair {
/// # use libp2p_identity as identity;
/// let key = identity::Keypair::generate_ed25519();
///
- /// let new_key = key.derive_secret(b"my encryption key").expect("can derive secret for ed25519");
+ /// let new_key = key
+ /// .derive_secret(b"my encryption key")
+ /// .expect("can derive secret for ed25519");
/// # }
/// ```
- ///
#[cfg(any(
feature = "ecdsa",
feature = "secp256k1",
@@ -906,9 +905,10 @@ mod tests {
#[test]
fn public_key_implements_hash() {
- use crate::PublicKey;
use std::hash::Hash;
+ use crate::PublicKey;
+
fn assert_implements_hash() {}
assert_implements_hash::();
@@ -916,9 +916,10 @@ mod tests {
#[test]
fn public_key_implements_ord() {
- use crate::PublicKey;
use std::cmp::Ord;
+ use crate::PublicKey;
+
fn assert_implements_ord() {}
assert_implements_ord::();
diff --git a/identity/src/lib.rs b/identity/src/lib.rs
index c78e68d1652..4f4313e8f17 100644
--- a/identity/src/lib.rs
+++ b/identity/src/lib.rs
@@ -34,7 +34,7 @@
//! All key types have functions to enable conversion to/from their binary representations.
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
-
+#![allow(unreachable_pub)]
#[cfg(any(
feature = "ecdsa",
feature = "secp256k1",
@@ -42,7 +42,6 @@
feature = "rsa"
))]
mod proto {
- #![allow(unreachable_pub)]
include!("generated/mod.rs");
pub(crate) use self::keys_proto::*;
}
diff --git a/identity/src/peer_id.rs b/identity/src/peer_id.rs
index 1d85fe66ffa..7f6d1f44eab 100644
--- a/identity/src/peer_id.rs
+++ b/identity/src/peer_id.rs
@@ -18,17 +18,19 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+use std::{fmt, str::FromStr};
+
#[cfg(feature = "rand")]
use rand::Rng;
use sha2::Digest as _;
-use std::{convert::TryFrom, fmt, str::FromStr};
use thiserror::Error;
/// Local type-alias for multihash.
///
/// Must be big enough to accommodate for `MAX_INLINE_KEY_LENGTH`.
/// 64 satisfies that and can hold 512 bit hashes which is what the ecosystem typically uses.
-/// Given that this appears in our type-signature, using a "common" number here makes us more compatible.
+/// Given that this appears in our type-signature,
+/// using a "common" number here makes us more compatible.
type Multihash = multihash::Multihash<64>;
#[cfg(feature = "serde")]
@@ -191,7 +193,7 @@ impl<'de> Deserialize<'de> for PeerId {
struct PeerIdVisitor;
- impl<'de> Visitor<'de> for PeerIdVisitor {
+ impl Visitor<'_> for PeerIdVisitor {
type Value = PeerId;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/identity/src/rsa.rs b/identity/src/rsa.rs
index cbfe3c1b919..b14d8c66d86 100644
--- a/identity/src/rsa.rs
+++ b/identity/src/rsa.rs
@@ -20,15 +20,20 @@
//! RSA keys.
-use super::error::*;
-use asn1_der::typed::{DerDecodable, DerEncodable, DerTypeView, Sequence};
-use asn1_der::{Asn1DerError, Asn1DerErrorVariant, DerObject, Sink, VecBacking};
-use ring::rand::SystemRandom;
-use ring::signature::KeyPair;
-use ring::signature::{self, RsaKeyPair, RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_SHA256};
use std::{fmt, sync::Arc};
+
+use asn1_der::{
+ typed::{DerDecodable, DerEncodable, DerTypeView, Sequence},
+ Asn1DerError, Asn1DerErrorVariant, DerObject, Sink, VecBacking,
+};
+use ring::{
+ rand::SystemRandom,
+ signature::{self, KeyPair, RsaKeyPair, RSA_PKCS1_2048_8192_SHA256, RSA_PKCS1_SHA256},
+};
use zeroize::Zeroize;
+use super::error::*;
+
/// An RSA keypair.
#[derive(Clone)]
pub struct Keypair(Arc);
@@ -149,7 +154,7 @@ struct Asn1RawOid<'a> {
object: DerObject<'a>,
}
-impl<'a> Asn1RawOid<'a> {
+impl Asn1RawOid<'_> {
/// The underlying OID as byte literal.
pub(crate) fn oid(&self) -> &[u8] {
self.object.value()
@@ -169,7 +174,7 @@ impl<'a> DerTypeView<'a> for Asn1RawOid<'a> {
}
}
-impl<'a> DerEncodable for Asn1RawOid<'a> {
+impl DerEncodable for Asn1RawOid<'_> {
fn encode(&self, sink: &mut S) -> Result<(), Asn1DerError> {
self.object.encode(sink)
}
@@ -315,9 +320,10 @@ impl DerDecodable<'_> for Asn1SubjectPublicKeyInfo {
#[cfg(test)]
mod tests {
- use super::*;
use quickcheck::*;
+ use super::*;
+
const KEY1: &[u8] = include_bytes!("test/rsa-2048.pk8");
const KEY2: &[u8] = include_bytes!("test/rsa-3072.pk8");
const KEY3: &[u8] = include_bytes!("test/rsa-4096.pk8");
diff --git a/identity/src/secp256k1.rs b/identity/src/secp256k1.rs
index 5e1fda2933b..e884cf1385d 100644
--- a/identity/src/secp256k1.rs
+++ b/identity/src/secp256k1.rs
@@ -20,15 +20,15 @@
//! Secp256k1 keys.
-use super::error::DecodingError;
+use core::{cmp, fmt, hash};
+
use asn1_der::typed::{DerDecodable, Sequence};
-use core::cmp;
-use core::fmt;
-use core::hash;
use libsecp256k1::{Message, Signature};
use sha2::{Digest as ShaDigestTrait, Sha256};
use zeroize::Zeroize;
+use super::error::DecodingError;
+
/// A Secp256k1 keypair.
#[derive(Clone)]
pub struct Keypair {
@@ -214,7 +214,7 @@ impl PublicKey {
self.0.serialize()
}
- /// Decode a public key from a byte slice in the the format produced
+ /// Decode a public key from a byte slice in the format produced
/// by `encode`.
pub fn try_from_bytes(k: &[u8]) -> Result {
libsecp256k1::PublicKey::parse_slice(k, Some(libsecp256k1::PublicKeyFormat::Compressed))
diff --git a/interop-tests/Cargo.toml b/interop-tests/Cargo.toml
index eba65b782e7..8f12275668d 100644
--- a/interop-tests/Cargo.toml
+++ b/interop-tests/Cargo.toml
@@ -13,31 +13,30 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
anyhow = "1"
-either = "1.9.0"
-futures = "0.3.29"
+futures = { workspace = true }
rand = "0.8.5"
serde = { version = "1", features = ["derive"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tracing = { workspace = true }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
-axum = "0.6"
+axum = "0.7"
libp2p = { path = "../libp2p", features = [ "ping", "noise", "tls", "rsa", "macros", "websocket", "tokio", "yamux", "tcp", "dns", "identify", "quic"] }
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 = [
+redis = { version = "0.24.0", default-features = false, features = [
"tokio-comp",
] }
-rust-embed = "8.0"
+rust-embed = "8.4"
serde_json = "1"
-thirtyfour = "=0.32.0-rc.8" # https://github.com/stevepryde/thirtyfour/issues/169
-tokio = { version = "1.34.0", features = ["full"] }
-tower-http = { version = "0.4", features = ["cors", "fs", "trace"] }
-tracing = "0.1.37"
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+thirtyfour = "=0.32.0" # https://github.com/stevepryde/thirtyfour/issues/169
+tokio = { workspace = true, features = ["full"] }
+tower-http = { version = "0.5", features = ["cors", "fs", "trace"] }
+tracing = { workspace = true }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
libp2p = { path = "../libp2p", features = [ "ping", "macros", "webtransport-websys", "wasm-bindgen", "identify", "websocket-websys", "yamux", "noise"] }
@@ -46,10 +45,10 @@ libp2p-webrtc-websys = { workspace = true }
wasm-bindgen = { version = "0.2" }
wasm-bindgen-futures = { version = "0.4" }
wasm-logger = { version = "0.2.0" }
-instant = "0.1.12"
-reqwest = { version = "0.11", features = ["json"] }
+web-time = { workspace = true }
+reqwest = { version = "0.12", features = ["json"] }
console_error_panic_hook = { version = "0.1.7" }
-futures-timer = "3.0.2"
+futures-timer = "3.0.3"
[lints]
workspace = true
diff --git a/interop-tests/Dockerfile.chromium b/interop-tests/Dockerfile.chromium
index 5ec46e313aa..86edbc5b9d2 100644
--- a/interop-tests/Dockerfile.chromium
+++ b/interop-tests/Dockerfile.chromium
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1.5-labs
-FROM rust:1.73.0 as chef
+FROM rust:1.81 as chef
RUN rustup target add wasm32-unknown-unknown
RUN wget -q -O- https://github.com/rustwasm/wasm-pack/releases/download/v0.12.1/wasm-pack-v0.12.1-x86_64-unknown-linux-musl.tar.gz | tar -zx -C /usr/local/bin --strip-components 1 --wildcards "wasm-pack-*/wasm-pack"
RUN wget -q -O- https://github.com/WebAssembly/binaryen/releases/download/version_115/binaryen-version_115-x86_64-linux.tar.gz | tar -zx -C /usr/local/bin --strip-components 2 --wildcards "binaryen-version_*/bin/wasm-opt"
@@ -20,7 +20,7 @@ COPY . .
RUN wasm-pack build --target web interop-tests
RUN RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --package interop-tests --target x86_64-unknown-linux-gnu --bin wasm_ping
-FROM selenium/standalone-chrome:115.0
+FROM selenium/standalone-chrome:125.0
COPY --from=builder /app/target/x86_64-unknown-linux-gnu/release/wasm_ping /usr/local/bin/testplan
ENV RUST_BACKTRACE=1
ENTRYPOINT ["testplan"]
diff --git a/interop-tests/Dockerfile.native b/interop-tests/Dockerfile.native
index 91e6cf8893e..499c73437fc 100644
--- a/interop-tests/Dockerfile.native
+++ b/interop-tests/Dockerfile.native
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1.5-labs
-FROM lukemathwalker/cargo-chef:0.1.62-rust-1.73.0 as chef
+FROM lukemathwalker/cargo-chef:0.1.67-rust-bullseye as chef
WORKDIR /app
FROM chef AS planner
diff --git a/interop-tests/src/arch.rs b/interop-tests/src/arch.rs
index 52000f90a86..91fc69dc215 100644
--- a/interop-tests/src/arch.rs
+++ b/interop-tests/src/arch.rs
@@ -1,7 +1,6 @@
// Native re-exports
#[cfg(not(target_arch = "wasm32"))]
pub(crate) use native::{build_swarm, init_logger, sleep, Instant, RedisClient};
-
// Wasm re-exports
#[cfg(target_arch = "wasm32")]
pub(crate) use wasm::{build_swarm, init_logger, sleep, Instant, RedisClient};
@@ -11,11 +10,13 @@ pub(crate) mod native {
use std::time::Duration;
use anyhow::{bail, Context, Result};
- use futures::future::BoxFuture;
- use futures::FutureExt;
- use libp2p::identity::Keypair;
- use libp2p::swarm::{NetworkBehaviour, Swarm};
- use libp2p::{noise, tcp, tls, yamux};
+ use futures::{future::BoxFuture, FutureExt};
+ use libp2p::{
+ identity::Keypair,
+ noise,
+ swarm::{NetworkBehaviour, Swarm},
+ tcp, tls, yamux,
+ };
use libp2p_mplex as mplex;
use libp2p_webrtc as webrtc;
use redis::AsyncCommands;
@@ -48,7 +49,6 @@ pub(crate) mod native {
.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"),
),
@@ -61,7 +61,6 @@ pub(crate) mod native {
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"),
),
@@ -74,7 +73,6 @@ pub(crate) mod native {
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"),
),
@@ -87,7 +85,6 @@ pub(crate) mod native {
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"),
),
@@ -100,7 +97,6 @@ pub(crate) mod native {
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"),
),
@@ -110,7 +106,6 @@ pub(crate) mod native {
.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"),
),
@@ -120,7 +115,6 @@ pub(crate) mod native {
.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"),
),
@@ -130,7 +124,6 @@ pub(crate) mod native {
.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"),
),
@@ -140,7 +133,6 @@ pub(crate) mod native {
.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"),
),
@@ -154,7 +146,6 @@ pub(crate) mod native {
))
})?
.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"),
),
@@ -174,32 +165,35 @@ pub(crate) mod native {
pub(crate) async fn blpop(&self, key: &str, timeout: u64) -> Result> {
let mut conn = self.0.get_async_connection().await?;
- Ok(conn.blpop(key, timeout as usize).await?)
+ Ok(conn.blpop(key, timeout as f64).await?)
}
pub(crate) async fn rpush(&self, key: &str, value: String) -> Result<()> {
let mut conn = self.0.get_async_connection().await?;
- conn.rpush(key, value).await?;
- Ok(())
+ conn.rpush(key, value).await.map_err(Into::into)
}
}
}
#[cfg(target_arch = "wasm32")]
pub(crate) mod wasm {
+ use std::time::Duration;
+
use anyhow::{bail, Context, Result};
use futures::future::{BoxFuture, FutureExt};
- use libp2p::core::upgrade::Version;
- use libp2p::identity::Keypair;
- use libp2p::swarm::{NetworkBehaviour, Swarm};
- use libp2p::{noise, websocket_websys, webtransport_websys, yamux, Transport as _};
+ use libp2p::{
+ core::upgrade::Version,
+ identity::Keypair,
+ noise,
+ swarm::{NetworkBehaviour, Swarm},
+ websocket_websys, webtransport_websys, yamux, Transport as _,
+ };
use libp2p_mplex as mplex;
use libp2p_webrtc_websys as webrtc_websys;
- use std::time::Duration;
use crate::{BlpopRequest, Muxer, SecProtocol, Transport};
- pub(crate) type Instant = instant::Instant;
+ pub(crate) type Instant = web_time::Instant;
pub(crate) fn init_logger() {
console_error_panic_hook::set_once();
@@ -246,7 +240,7 @@ pub(crate) mod wasm {
.with_behaviour(behaviour_constructor)?
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
.build(),
- format!("/ip4/{ip}/tcp/0/wss"),
+ format!("/ip4/{ip}/tcp/0/tls/ws"),
),
(Transport::Ws, Some(SecProtocol::Noise), Some(Muxer::Yamux)) => (
libp2p::SwarmBuilder::with_new_identity()
@@ -263,7 +257,7 @@ pub(crate) mod wasm {
.with_behaviour(behaviour_constructor)?
.with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(5)))
.build(),
- format!("/ip4/{ip}/tcp/0/wss"),
+ format!("/ip4/{ip}/tcp/0/tls/ws"),
),
(Transport::WebRtcDirect, None, None) => (
libp2p::SwarmBuilder::with_new_identity()
diff --git a/interop-tests/src/bin/wasm_ping.rs b/interop-tests/src/bin/wasm_ping.rs
index 8269ff064ad..7730b869456 100644
--- a/interop-tests/src/bin/wasm_ping.rs
+++ b/interop-tests/src/bin/wasm_ping.rs
@@ -1,24 +1,27 @@
#![allow(non_upper_case_globals)]
-use std::process::Stdio;
-use std::time::Duration;
+
+use std::{future::IntoFuture, process::Stdio, time::Duration};
use anyhow::{bail, Context, Result};
-use axum::body;
-use axum::http::{header, Uri};
-use axum::response::{Html, IntoResponse, Response};
-use axum::routing::get;
-use axum::{extract::State, http::StatusCode, routing::post, Json, Router};
+use axum::{
+ extract::State,
+ http::{header, StatusCode, Uri},
+ response::{Html, IntoResponse, Response},
+ routing::{get, post},
+ Json, Router,
+};
+use interop_tests::{BlpopRequest, Report};
use redis::{AsyncCommands, Client};
use thirtyfour::prelude::*;
-use tokio::io::{AsyncBufReadExt, BufReader};
-use tokio::process::Child;
-use tokio::sync::mpsc;
-use tower_http::cors::CorsLayer;
-use tower_http::trace::TraceLayer;
+use tokio::{
+ io::{AsyncBufReadExt, BufReader},
+ net::TcpListener,
+ process::Child,
+ sync::mpsc,
+};
+use tower_http::{cors::CorsLayer, trace::TraceLayer};
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
-use interop_tests::{BlpopRequest, Report};
-
mod config;
const BIND_ADDR: &str = "127.0.0.1:8080";
@@ -76,7 +79,7 @@ async fn main() -> Result<()> {
.with_state(state);
// Run the service in background
- tokio::spawn(axum::Server::bind(&BIND_ADDR.parse()?).serve(app.into_make_service()));
+ tokio::spawn(axum::serve(TcpListener::bind(BIND_ADDR).await?, app).into_future());
// Start executing the test in a browser
let (mut chrome, driver) = open_in_browser().await?;
@@ -128,6 +131,8 @@ async fn open_in_browser() -> Result<(Child, WebDriver)> {
// run a webdriver client
let mut caps = DesiredCapabilities::chrome();
caps.set_headless()?;
+ caps.set_disable_dev_shm_usage()?;
+ caps.set_no_sandbox()?;
let driver = WebDriver::new("http://localhost:45782", caps).await?;
// go to the wasm test service
driver.goto(format!("http://{BIND_ADDR}")).await?;
@@ -147,7 +152,7 @@ async fn redis_blpop(
StatusCode::INTERNAL_SERVER_ERROR
})?;
let res = conn
- .blpop(&request.key, request.timeout as usize)
+ .blpop(&request.key, request.timeout as f64)
.await
.map_err(|e| {
tracing::warn!(
@@ -229,7 +234,7 @@ async fn serve_wasm_pkg(uri: Uri) -> Result {
let mime = mime_guess::from_path(&path).first_or_octet_stream();
Ok(Response::builder()
.header(header::CONTENT_TYPE, mime.as_ref())
- .body(body::boxed(body::Full::from(content.data)))
+ .body(content.data.into())
.unwrap())
} else {
Err(StatusCode::NOT_FOUND)
diff --git a/interop-tests/src/lib.rs b/interop-tests/src/lib.rs
index 0154bec51a4..a16dc4b8228 100644
--- a/interop-tests/src/lib.rs
+++ b/interop-tests/src/lib.rs
@@ -1,11 +1,14 @@
-use std::str::FromStr;
-use std::time::Duration;
+use std::{str::FromStr, time::Duration};
use anyhow::{bail, Context, Result};
use futures::{FutureExt, StreamExt};
-use libp2p::identity::Keypair;
-use libp2p::swarm::SwarmEvent;
-use libp2p::{identify, ping, swarm::NetworkBehaviour, Multiaddr};
+use libp2p::{
+ identify,
+ identity::Keypair,
+ ping,
+ swarm::{NetworkBehaviour, SwarmEvent},
+ Multiaddr,
+};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
diff --git a/libp2p/CHANGELOG.md b/libp2p/CHANGELOG.md
index 80b32c35643..8b7bf0ff55f 100644
--- a/libp2p/CHANGELOG.md
+++ b/libp2p/CHANGELOG.md
@@ -1,3 +1,48 @@
+## 0.54.2
+
+- Add `with_connection_timeout` on `SwarmBuilder` to allow configuration of the connection_timeout parameter.
+ See [PR 5575](https://github.com/libp2p/rust-libp2p/pull/5575).
+
+- Deprecate `void` crate.
+ See [PR 5676](https://github.com/libp2p/rust-libp2p/pull/5676).
+
+- Update default for idle-connection-timeout to 10s.
+ See [PR 4967](https://github.com/libp2p/rust-libp2p/pull/4967).
+
+- Expose swarm builder phase errors.
+ See [PR 5726](https://github.com/libp2p/rust-libp2p/pull/5726).
+
+## 0.54.1
+
+- Update individual crates.
+ - Update to [`libp2p-metrics` `0.15.0`](misc/metrics/CHANGELOG.md#0150).
+
+## 0.54.0
+
+- Update individual crates.
+ - Update to [`libp2p-kad` `v0.46.0`](protocols/kad/CHANGELOG.md#0460).
+ - Update to [`libp2p-identify` `v0.45.0`](protocols/identify/CHANGELOG.md#0450).
+
+- Raise MSRV to 1.73.
+ See [PR 5266](https://github.com/libp2p/rust-libp2p/pull/5266).
+
+- Implement refactored `Transport`.
+ See [PR 4568].
+
+- Move `address_translation` from `libp2p-core` to `libp2p-swarm` and `libp2p-identify`. To now get
+ address translation behaviour, i.e. discovery of extern address (candidates) based on connecting
+ to other peers, one needs to use `libp2p-identify` now. This pertains to you if your nodes can be
+ behind NATs and they aren't aware of their true external address.
+ See [PR 4568].
+
+- Use `web-time` instead of `instant`.
+ See [PR 5347](https://github.com/libp2p/rust-libp2p/pull/5347).
+
+- Remove redundant async signature from builder methods.
+ See [PR 5468](https://github.com/libp2p/rust-libp2p/pull/5468).
+
+[PR 4568]: https://github.com/libp2p/rust-libp2p/pull/4568
+
## 0.53.2
- Allow `SwarmBuilder::with_bandwidth_metrics` after `SwarmBuilder::with_websocket`.
@@ -1185,7 +1230,7 @@ must not be skipped!
- Merged `PeriodicPing` and `PingListen` into one `Ping` behaviour.
- `Floodsub` now generates `FloodsubEvent`s instead of direct floodsub messages.
- Added `ProtocolsHandler::connection_keep_alive`. If all the handlers return `false`, then the connection to the remote node will automatically be gracefully closed after a few seconds.
-- The crate now successfuly compiles for the `wasm32-unknown-unknown` target.
+- The crate now successfully compiles for the `wasm32-unknown-unknown` target.
- Updated `ring` to version 0.13.
- Updated `secp256k1` to version 0.12.
- The enum returned by `RawSwarm::peer()` can now return `LocalNode`. This makes it impossible to accidentally attempt to dial the local node.
diff --git a/libp2p/Cargo.toml b/libp2p/Cargo.toml
index 9dc9667be10..ae23dcf0db5 100644
--- a/libp2p/Cargo.toml
+++ b/libp2p/Cargo.toml
@@ -3,7 +3,7 @@ name = "libp2p"
edition = "2021"
rust-version = { workspace = true }
description = "Peer-to-peer networking library"
-version = "0.53.2"
+version = "0.54.2"
authors = ["Parity Technologies "]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
@@ -82,7 +82,7 @@ tcp = ["dep:libp2p-tcp"]
tls = ["dep:libp2p-tls"]
tokio = [ "libp2p-swarm/tokio", "libp2p-mdns?/tokio", "libp2p-tcp?/tokio", "libp2p-dns?/tokio", "libp2p-quic?/tokio", "libp2p-upnp?/tokio"]
uds = ["dep:libp2p-uds"]
-wasm-bindgen = [ "futures-timer/wasm-bindgen", "instant/wasm-bindgen", "getrandom/js", "libp2p-swarm/wasm-bindgen", "libp2p-gossipsub?/wasm-bindgen",]
+wasm-bindgen = [ "futures-timer/wasm-bindgen", "getrandom/js", "libp2p-swarm/wasm-bindgen", "libp2p-gossipsub?/wasm-bindgen"]
websocket-websys = ["dep:libp2p-websocket-websys"]
websocket = ["dep:libp2p-websocket"]
webtransport-websys = ["dep:libp2p-webtransport-websys"]
@@ -92,10 +92,9 @@ upnp = ["dep:libp2p-upnp"]
[dependencies]
bytes = "1"
either = "1.9.0"
-futures = "0.3.26"
+futures = { workspace = true }
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
+getrandom = { workspace = true } # Explicit dependency to be used in `wasm-bindgen` feature
# TODO feature flag?
rw-stream-sink = { workspace = true }
@@ -123,7 +122,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"
+thiserror = { workspace = true }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
libp2p-dns = { workspace = true, optional = true }
@@ -138,21 +137,16 @@ libp2p-websocket = { workspace = true, optional = true }
[dev-dependencies]
async-std = { version = "1.6.2", features = ["attributes"] }
-async-trait = "0.1"
-clap = { version = "4.1.6", features = ["derive"] }
-tokio = { version = "1.15", features = [ "io-util", "io-std", "macros", "rt", "rt-multi-thread"] }
+tokio = { workspace = true, features = [ "io-util", "io-std", "macros", "rt", "rt-multi-thread"] }
libp2p-mplex = { workspace = true }
-libp2p-noise = { workspace = true }
libp2p-tcp = { workspace = true, features = ["tokio"] }
-tracing-subscriber = { version = "0.3", features = ["env-filter"] }
+tracing-subscriber = { workspace = true, features = ["env-filter"] }
# Passing arguments to the docsrs builder in order to properly document cfg's.
# More information: https://docs.rs/about/builds#cross-compiling
[package.metadata.docs.rs]
all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
-rustc-args = ["--cfg", "docsrs"]
[lints]
workspace = true
diff --git a/libp2p/src/bandwidth.rs b/libp2p/src/bandwidth.rs
index b84cbb7e27b..ac668e26b3f 100644
--- a/libp2p/src/bandwidth.rs
+++ b/libp2p/src/bandwidth.rs
@@ -20,13 +20,6 @@
#![allow(deprecated)]
-use crate::core::muxing::{StreamMuxer, StreamMuxerEvent};
-
-use futures::{
- io::{IoSlice, IoSliceMut},
- prelude::*,
- ready,
-};
use std::{
convert::TryFrom as _,
io,
@@ -38,6 +31,14 @@ use std::{
task::{Context, Poll},
};
+use futures::{
+ io::{IoSlice, IoSliceMut},
+ prelude::*,
+ ready,
+};
+
+use crate::core::muxing::{StreamMuxer, StreamMuxerEvent};
+
/// Wraps around a [`StreamMuxer`] and counts the number of bytes that go through all the opened
/// streams.
#[derive(Clone)]
@@ -123,7 +124,7 @@ impl BandwidthSinks {
/// Returns the total number of bytes that have been downloaded on all the streams.
///
/// > **Note**: This method is by design subject to race conditions. The returned value should
- /// > only ever be used for statistics purposes.
+ /// > only ever be used for statistics purposes.
pub fn total_inbound(&self) -> u64 {
self.inbound.load(Ordering::Relaxed)
}
@@ -131,7 +132,7 @@ impl BandwidthSinks {
/// Returns the total number of bytes that have been uploaded on all the streams.
///
/// > **Note**: This method is by design subject to race conditions. The returned value should
- /// > only ever be used for statistics purposes.
+ /// > only ever be used for statistics purposes.
pub fn total_outbound(&self) -> u64 {
self.outbound.load(Ordering::Relaxed)
}
@@ -154,7 +155,7 @@ impl AsyncRead for InstrumentedStream {
let this = self.project();
let num_bytes = ready!(this.inner.poll_read(cx, buf))?;
this.sinks.inbound.fetch_add(
- u64::try_from(num_bytes).unwrap_or(u64::max_value()),
+ u64::try_from(num_bytes).unwrap_or(u64::MAX),
Ordering::Relaxed,
);
Poll::Ready(Ok(num_bytes))
@@ -168,7 +169,7 @@ impl AsyncRead for InstrumentedStream {
let this = self.project();
let num_bytes = ready!(this.inner.poll_read_vectored(cx, bufs))?;
this.sinks.inbound.fetch_add(
- u64::try_from(num_bytes).unwrap_or(u64::max_value()),
+ u64::try_from(num_bytes).unwrap_or(u64::MAX),
Ordering::Relaxed,
);
Poll::Ready(Ok(num_bytes))
@@ -184,7 +185,7 @@ impl AsyncWrite for InstrumentedStream {
let this = self.project();
let num_bytes = ready!(this.inner.poll_write(cx, buf))?;
this.sinks.outbound.fetch_add(
- u64::try_from(num_bytes).unwrap_or(u64::max_value()),
+ u64::try_from(num_bytes).unwrap_or(u64::MAX),
Ordering::Relaxed,
);
Poll::Ready(Ok(num_bytes))
@@ -198,7 +199,7 @@ impl AsyncWrite for InstrumentedStream {
let this = self.project();
let num_bytes = ready!(this.inner.poll_write_vectored(cx, bufs))?;
this.sinks.outbound.fetch_add(
- u64::try_from(num_bytes).unwrap_or(u64::max_value()),
+ u64::try_from(num_bytes).unwrap_or(u64::MAX),
Ordering::Relaxed,
);
Poll::Ready(Ok(num_bytes))
diff --git a/libp2p/src/builder.rs b/libp2p/src/builder.rs
index c96c20d470a..ae4d0b0d4e4 100644
--- a/libp2p/src/builder.rs
+++ b/libp2p/src/builder.rs
@@ -4,6 +4,10 @@ mod phase;
mod select_muxer;
mod select_security;
+#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
+pub use phase::WebsocketError;
+pub use phase::{BehaviourError, TransportError};
+
/// Build a [`Swarm`](libp2p_swarm::Swarm) by combining an identity, a set of
/// [`Transport`](libp2p_core::Transport)s and a
/// [`NetworkBehaviour`](libp2p_swarm::NetworkBehaviour).
@@ -33,31 +37,31 @@ mod select_security;
/// # 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_websocket(
-/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
-/// libp2p_yamux::Config::default,
-/// )
-/// .await?
-/// .with_relay_client(
-/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
-/// libp2p_yamux::Config::default,
-/// )?
-/// .with_behaviour(|_key, relay| MyBehaviour { relay })?
-/// .with_swarm_config(|cfg| {
-/// // Edit cfg here.
-/// cfg
-/// })
-/// .build();
+/// 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_websocket(
+/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
+/// libp2p_yamux::Config::default,
+/// )
+/// .await?
+/// .with_relay_client(
+/// (libp2p_tls::Config::new, libp2p_noise::Config::new),
+/// libp2p_yamux::Config::default,
+/// )?
+/// .with_behaviour(|_key, relay| MyBehaviour { relay })?
+/// .with_swarm_config(|cfg| {
+/// // Edit cfg here.
+/// cfg
+/// })
+/// .build();
/// #
/// # Ok(())
/// # }
@@ -70,11 +74,12 @@ pub struct SwarmBuilder {
#[cfg(test)]
mod tests {
- use crate::SwarmBuilder;
use libp2p_core::{muxing::StreamMuxerBox, transport::dummy::DummyTransport};
use libp2p_identity::PeerId;
use libp2p_swarm::NetworkBehaviour;
+ use crate::SwarmBuilder;
+
#[test]
#[cfg(all(
feature = "tokio",
@@ -575,7 +580,7 @@ mod tests {
#[test]
#[cfg(all(feature = "tokio", feature = "quic"))]
- fn quic_bandwidth_metrics() -> Result<(), Box> {
+ fn quic_bandwidth_metrics() {
let _ = SwarmBuilder::with_new_identity()
.with_tokio()
.with_quic()
@@ -583,8 +588,6 @@ mod tests {
.with_behaviour(|_| libp2p_swarm::dummy::Behaviour)
.unwrap()
.build();
-
- Ok(())
}
#[test]
diff --git a/libp2p/src/builder/phase.rs b/libp2p/src/builder/phase.rs
index c9679a46767..f8f1672f952 100644
--- a/libp2p/src/builder/phase.rs
+++ b/libp2p/src/builder/phase.rs
@@ -16,23 +16,26 @@ mod websocket;
use bandwidth_logging::*;
use bandwidth_metrics::*;
+pub use behaviour::BehaviourError;
use behaviour::*;
use build::*;
use dns::*;
+use libp2p_core::{muxing::StreamMuxerBox, Transport};
+use libp2p_identity::Keypair;
+pub use other_transport::TransportError;
use other_transport::*;
use provider::*;
use quic::*;
use relay::*;
use swarm::*;
use tcp::*;
+#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
+pub use websocket::WebsocketError;
use websocket::*;
-use super::select_muxer::SelectMuxerUpgrade;
-use super::select_security::SelectSecurityUpgrade;
-use super::SwarmBuilder;
-
-use libp2p_core::{muxing::StreamMuxerBox, Transport};
-use libp2p_identity::Keypair;
+use super::{
+ select_muxer::SelectMuxerUpgrade, select_security::SelectSecurityUpgrade, SwarmBuilder,
+};
#[allow(unreachable_pub)]
pub trait IntoSecurityUpgrade {
diff --git a/libp2p/src/builder/phase/bandwidth_logging.rs b/libp2p/src/builder/phase/bandwidth_logging.rs
index cee9498fcaa..f24df5f3df5 100644
--- a/libp2p/src/builder/phase/bandwidth_logging.rs
+++ b/libp2p/src/builder/phase/bandwidth_logging.rs
@@ -1,10 +1,9 @@
+use std::{marker::PhantomData, sync::Arc};
+
use super::*;
#[allow(deprecated)]
use crate::bandwidth::BandwidthSinks;
-use crate::transport_ext::TransportExt;
-use crate::SwarmBuilder;
-use std::marker::PhantomData;
-use std::sync::Arc;
+use crate::{transport_ext::TransportExt, SwarmBuilder};
pub struct BandwidthLoggingPhase {
pub(crate) relay_behaviour: R,
diff --git a/libp2p/src/builder/phase/bandwidth_metrics.rs b/libp2p/src/builder/phase/bandwidth_metrics.rs
index 52daa731ddd..ddd292c140e 100644
--- a/libp2p/src/builder/phase/bandwidth_metrics.rs
+++ b/libp2p/src/builder/phase/bandwidth_metrics.rs
@@ -1,10 +1,9 @@
+use std::{marker::PhantomData, sync::Arc};
+
use super::*;
#[allow(deprecated)]
use crate::bandwidth::BandwidthSinks;
-use crate::transport_ext::TransportExt;
-use crate::SwarmBuilder;
-use std::marker::PhantomData;
-use std::sync::Arc;
+use crate::{transport_ext::TransportExt, SwarmBuilder};
pub struct BandwidthMetricsPhase {
pub(crate) relay_behaviour: R,
diff --git a/libp2p/src/builder/phase/behaviour.rs b/libp2p/src/builder/phase/behaviour.rs
index 939db935c80..22f8c617051 100644
--- a/libp2p/src/builder/phase/behaviour.rs
+++ b/libp2p/src/builder/phase/behaviour.rs
@@ -1,8 +1,9 @@
+use std::{convert::Infallible, marker::PhantomData};
+
+use libp2p_swarm::NetworkBehaviour;
+
use super::*;
use crate::SwarmBuilder;
-use libp2p_swarm::NetworkBehaviour;
-use std::convert::Infallible;
-use std::marker::PhantomData;
pub struct BehaviourPhase {
pub(crate) relay_behaviour: R,
diff --git a/libp2p/src/builder/phase/build.rs b/libp2p/src/builder/phase/build.rs
index 80a83994eeb..d3138cb8b8d 100644
--- a/libp2p/src/builder/phase/build.rs
+++ b/libp2p/src/builder/phase/build.rs
@@ -1,28 +1,31 @@
+use std::time::Duration;
+
+use libp2p_core::{transport::timeout::TransportTimeout, Transport};
+use libp2p_swarm::Swarm;
+
#[allow(unused_imports)]
use super::*;
-
use crate::SwarmBuilder;
-use libp2p_core::Transport;
-use libp2p_swarm::Swarm;
pub struct BuildPhase {
pub(crate) behaviour: B,
pub(crate) transport: T,
pub(crate) swarm_config: libp2p_swarm::Config,
+ pub(crate) connection_timeout: Duration,
}
-const CONNECTION_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
-
impl
SwarmBuilder>
{
+ /// Timeout of the [`TransportTimeout`] wrapping the transport.
+ pub fn with_connection_timeout(mut self, connection_timeout: Duration) -> Self {
+ self.phase.connection_timeout = connection_timeout;
+ self
+ }
+
pub fn build(self) -> Swarm {
Swarm::new(
- libp2p_core::transport::timeout::TransportTimeout::new(
- self.phase.transport,
- CONNECTION_TIMEOUT,
- )
- .boxed(),
+ TransportTimeout::new(self.phase.transport, self.phase.connection_timeout).boxed(),
self.phase.behaviour,
self.keypair.public().to_peer_id(),
self.phase.swarm_config,
diff --git a/libp2p/src/builder/phase/dns.rs b/libp2p/src/builder/phase/dns.rs
index 135f6c57b19..83653836a34 100644
--- a/libp2p/src/builder/phase/dns.rs
+++ b/libp2p/src/builder/phase/dns.rs
@@ -1,6 +1,7 @@
+use std::marker::PhantomData;
+
use super::*;
use crate::SwarmBuilder;
-use std::marker::PhantomData;
pub struct DnsPhase {
pub(crate) transport: T,
@@ -8,8 +9,7 @@ pub struct DnsPhase {
#[cfg(all(not(target_arch = "wasm32"), feature = "async-std", feature = "dns"))]
impl SwarmBuilder> {
- // TODO: Remove `async`
- pub async fn with_dns(
+ pub fn with_dns(
self,
) -> Result<
SwarmBuilder<
diff --git a/libp2p/src/builder/phase/identity.rs b/libp2p/src/builder/phase/identity.rs
index ceb86819dc7..e2511267cd3 100644
--- a/libp2p/src/builder/phase/identity.rs
+++ b/libp2p/src/builder/phase/identity.rs
@@ -1,6 +1,7 @@
+use std::marker::PhantomData;
+
use super::*;
use crate::SwarmBuilder;
-use std::marker::PhantomData;
pub struct IdentityPhase {}
diff --git a/libp2p/src/builder/phase/other_transport.rs b/libp2p/src/builder/phase/other_transport.rs
index b0d56cd92d2..c3b951c8c75 100644
--- a/libp2p/src/builder/phase/other_transport.rs
+++ b/libp2p/src/builder/phase/other_transport.rs
@@ -1,20 +1,19 @@
-use std::convert::Infallible;
-use std::marker::PhantomData;
-use std::sync::Arc;
+use std::{convert::Infallible, marker::PhantomData, sync::Arc};
-use libp2p_core::upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade};
-use libp2p_core::Transport;
+use libp2p_core::{
+ upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade},
+ Transport,
+};
#[cfg(feature = "relay")]
use libp2p_core::{Negotiated, UpgradeInfo};
#[cfg(feature = "relay")]
use libp2p_identity::PeerId;
+use super::*;
#[allow(deprecated)]
use crate::bandwidth::BandwidthSinks;
use crate::SwarmBuilder;
-use super::*;
-
pub struct OtherTransportPhase {
pub(crate) transport: T,
}
@@ -73,7 +72,7 @@ impl
impl
SwarmBuilder>
{
- pub async fn with_dns(
+ pub fn with_dns(
self,
) -> Result<
SwarmBuilder<
@@ -82,7 +81,7 @@ impl
>,
std::io::Error,
> {
- self.without_any_other_transports().with_dns().await
+ self.without_any_other_transports().with_dns()
}
}
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio", feature = "dns"))]
diff --git a/libp2p/src/builder/phase/provider.rs b/libp2p/src/builder/phase/provider.rs
index 32321442689..00a79e14a30 100644
--- a/libp2p/src/builder/phase/provider.rs
+++ b/libp2p/src/builder/phase/provider.rs
@@ -1,46 +1,64 @@
+use std::marker::PhantomData;
+
#[allow(unused_imports)]
use super::*;
-
use crate::SwarmBuilder;
+/// Represents the phase where a provider is not yet specified.
+/// This is a marker type used in the type-state pattern to ensure compile-time checks of the
+/// builder's state.
+pub enum NoProviderSpecified {}
+
+// Define enums for each of the possible runtime environments. These are used as markers in the
+// type-state pattern, allowing compile-time checks for the appropriate environment configuration.
+
+#[cfg(all(not(target_arch = "wasm32"), feature = "async-std"))]
+/// Represents the AsyncStd runtime environment.
+pub enum AsyncStd {}
+
+#[cfg(all(not(target_arch = "wasm32"), feature = "tokio"))]
+/// Represents the Tokio runtime environment.
+pub enum Tokio {}
+
+#[cfg(feature = "wasm-bindgen")]
+/// Represents the WasmBindgen environment for WebAssembly.
+pub enum WasmBindgen {}
+/// Represents a phase in the SwarmBuilder where a provider has been chosen but not yet specified.
pub struct ProviderPhase {}
impl SwarmBuilder {
+ /// Configures the SwarmBuilder to use the AsyncStd runtime.
+ /// This method is only available when compiling for non-Wasm
+ /// targets with the `async-std` feature enabled.
#[cfg(all(not(target_arch = "wasm32"), feature = "async-std"))]
pub fn with_async_std(self) -> SwarmBuilder {
SwarmBuilder {
keypair: self.keypair,
- phantom: std::marker::PhantomData,
+ phantom: PhantomData,
phase: TcpPhase {},
}
}
+ /// Configures the SwarmBuilder to use the Tokio runtime.
+ /// This method is only available when compiling for non-Wasm
+ /// targets with the `tokio` feature enabled
#[cfg(all(not(target_arch = "wasm32"), feature = "tokio"))]
pub fn with_tokio(self) -> SwarmBuilder {
SwarmBuilder {
keypair: self.keypair,
- phantom: std::marker::PhantomData,
+ phantom: PhantomData,
phase: TcpPhase {},
}
}
+ /// Configures the SwarmBuilder for WebAssembly using WasmBindgen.
+ /// This method is available when the `wasm-bindgen` feature is enabled.
#[cfg(feature = "wasm-bindgen")]
pub fn with_wasm_bindgen(self) -> SwarmBuilder {
SwarmBuilder {
keypair: self.keypair,
- phantom: std::marker::PhantomData,
+ phantom: 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 {}
diff --git a/libp2p/src/builder/phase/quic.rs b/libp2p/src/builder/phase/quic.rs
index 885b16e2e03..1b6329c1095 100644
--- a/libp2p/src/builder/phase/quic.rs
+++ b/libp2p/src/builder/phase/quic.rs
@@ -1,5 +1,5 @@
-use super::*;
-use crate::SwarmBuilder;
+use std::{marker::PhantomData, sync::Arc};
+
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
use libp2p_core::muxing::StreamMuxer;
use libp2p_core::upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade};
@@ -8,7 +8,9 @@ use libp2p_core::upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade};
all(not(target_arch = "wasm32"), feature = "websocket")
))]
use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, UpgradeInfo};
-use std::{marker::PhantomData, sync::Arc};
+
+use super::*;
+use crate::SwarmBuilder;
pub struct QuicPhase {
pub(crate) transport: T,
@@ -150,7 +152,7 @@ impl SwarmBuilder SwarmBuilder> {
- pub async fn with_dns(
+ pub fn with_dns(
self,
) -> Result<
SwarmBuilder<
@@ -162,7 +164,6 @@ impl SwarmBuilder {
pub(crate) transport: T,
diff --git a/libp2p/src/builder/phase/swarm.rs b/libp2p/src/builder/phase/swarm.rs
index ee456ced927..e751ad672e4 100644
--- a/libp2p/src/builder/phase/swarm.rs
+++ b/libp2p/src/builder/phase/swarm.rs
@@ -1,6 +1,9 @@
#[allow(unused_imports)]
use super::*;
+#[allow(unused)] // used below but due to feature flag combinations, clippy gives an unnecessary warning.
+const DEFAULT_CONNECTION_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
+
#[allow(dead_code)]
pub struct SwarmPhase {
pub(crate) behaviour: B,
@@ -20,6 +23,7 @@ macro_rules! impl_with_swarm_config {
behaviour: self.phase.behaviour,
transport: self.phase.transport,
swarm_config: constructor($config),
+ connection_timeout: DEFAULT_CONNECTION_TIMEOUT,
},
keypair: self.keypair,
phantom: std::marker::PhantomData,
diff --git a/libp2p/src/builder/phase/tcp.rs b/libp2p/src/builder/phase/tcp.rs
index 4b7cf29b3d2..f38f52441e5 100644
--- a/libp2p/src/builder/phase/tcp.rs
+++ b/libp2p/src/builder/phase/tcp.rs
@@ -1,5 +1,5 @@
-use super::*;
-use crate::SwarmBuilder;
+use std::marker::PhantomData;
+
#[cfg(all(
not(target_arch = "wasm32"),
any(feature = "tcp", feature = "websocket")
@@ -14,7 +14,9 @@ use libp2p_core::Transport;
use libp2p_core::{
upgrade::InboundConnectionUpgrade, upgrade::OutboundConnectionUpgrade, Negotiated, UpgradeInfo,
};
-use std::marker::PhantomData;
+
+use super::*;
+use crate::SwarmBuilder;
pub struct TcpPhase {}
diff --git a/libp2p/src/builder/phase/websocket.rs b/libp2p/src/builder/phase/websocket.rs
index 68a85bb77b7..a23c6eca854 100644
--- a/libp2p/src/builder/phase/websocket.rs
+++ b/libp2p/src/builder/phase/websocket.rs
@@ -1,5 +1,5 @@
-use super::*;
-use crate::SwarmBuilder;
+use std::marker::PhantomData;
+
#[cfg(all(not(target_arch = "wasm32"), feature = "websocket"))]
use libp2p_core::muxing::{StreamMuxer, StreamMuxerBox};
use libp2p_core::upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade};
@@ -15,7 +15,9 @@ use libp2p_core::{InboundUpgrade, Negotiated, OutboundUpgrade, UpgradeInfo};
feature = "relay"
))]
use libp2p_identity::PeerId;
-use std::marker::PhantomData;
+
+use super::*;
+use crate::SwarmBuilder;
pub struct WebsocketPhase