From 53df98298ab94f831e508170dbf952209beb2bd8 Mon Sep 17 00:00:00 2001 From: Age Manning Date: Wed, 26 Jul 2023 23:36:14 +1000 Subject: [PATCH 01/44] fix(connection-limits): correct connection tracking The connection limit behaviour was not taking into account connection errors. Also, it was using the behaviour events to indicate established connections which is not always going to be the case because other behaviours can deny the connections (thanks @divagant-martian). Closes #4249 Pull-Request: #4250. --- Cargo.lock | 2 +- Cargo.toml | 2 +- misc/connection-limits/CHANGELOG.md | 16 ++- misc/connection-limits/Cargo.toml | 2 +- misc/connection-limits/src/lib.rs | 154 +++++++++++++++++++++++++--- 5 files changed, 155 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e89447b4edb..b2fb6e87074 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2594,7 +2594,7 @@ dependencies = [ [[package]] name = "libp2p-connection-limits" -version = "0.2.0" +version = "0.2.1" dependencies = [ "async-std", "libp2p-core", diff --git a/Cargo.toml b/Cargo.toml index 07ac8ab9e85..66b2cfc58ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,7 +64,7 @@ rust-version = "1.65.0" [workspace.dependencies] libp2p-allow-block-list = { version = "0.2.0", path = "misc/allow-block-list" } libp2p-autonat = { version = "0.11.0", path = "protocols/autonat" } -libp2p-connection-limits = { version = "0.2.0", path = "misc/connection-limits" } +libp2p-connection-limits = { version = "0.2.1", path = "misc/connection-limits" } libp2p-core = { version = "0.40.0", path = "core" } libp2p-dcutr = { version = "0.10.0", path = "protocols/dcutr" } libp2p-deflate = { version = "0.40.0", path = "transports/deflate" } diff --git a/misc/connection-limits/CHANGELOG.md b/misc/connection-limits/CHANGELOG.md index e46a94e981a..a8bd071e6fe 100644 --- a/misc/connection-limits/CHANGELOG.md +++ b/misc/connection-limits/CHANGELOG.md @@ -1,4 +1,18 @@ -## 0.2.0 +## 0.2.1 + +- Do not count a connection as established when it is denied by another sibling `NetworkBehaviour`. + In other words, do not increase established connection counter in `handle_established_outbound_connection` or `handle_established_inbound_connection`, but in `FromSwarm::ConnectionEstablished` instead. + + See [PR 4250]. + +- Decrease `pending_inbound_connections` on `FromSwarm::ListenFailure` and `pending_outbound_connections` on `FromSwarm::DialFailure`. + + See [PR 4250]. + +[PR 4250]: https://github.com/libp2p/rust-libp2p/pull/4250 + +## 0.2.0 + - Raise MSRV to 1.65. See [PR 3715]. diff --git a/misc/connection-limits/Cargo.toml b/misc/connection-limits/Cargo.toml index db662f518aa..25347e29b16 100644 --- a/misc/connection-limits/Cargo.toml +++ b/misc/connection-limits/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-connection-limits" edition = "2021" rust-version = { workspace = true } description = "Connection limits for libp2p." -version = "0.2.0" +version = "0.2.1" license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" keywords = ["peer-to-peer", "libp2p", "networking"] diff --git a/misc/connection-limits/src/lib.rs b/misc/connection-limits/src/lib.rs index 52d0aa62c39..e4723dd95c6 100644 --- a/misc/connection-limits/src/lib.rs +++ b/misc/connection-limits/src/lib.rs @@ -18,9 +18,10 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use libp2p_core::{Endpoint, Multiaddr}; +use libp2p_core::{ConnectedPoint, Endpoint, Multiaddr}; use libp2p_identity::PeerId; use libp2p_swarm::{ + behaviour::{ConnectionEstablished, DialFailure, ListenFailure}, dummy, ConnectionClosed, ConnectionDenied, ConnectionId, FromSwarm, NetworkBehaviour, PollParameters, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, }; @@ -249,12 +250,6 @@ impl NetworkBehaviour for Behaviour { Kind::EstablishedTotal, )?; - self.established_inbound_connections.insert(connection_id); - self.established_per_peer - .entry(peer) - .or_default() - .insert(connection_id); - Ok(dummy::ConnectionHandler) } @@ -305,12 +300,6 @@ impl NetworkBehaviour for Behaviour { Kind::EstablishedTotal, )?; - self.established_outbound_connections.insert(connection_id); - self.established_per_peer - .entry(peer) - .or_default() - .insert(connection_id); - Ok(dummy::ConnectionHandler) } @@ -328,10 +317,33 @@ impl NetworkBehaviour for Behaviour { .or_default() .remove(&connection_id); } - FromSwarm::ConnectionEstablished(_) => {} + FromSwarm::ConnectionEstablished(ConnectionEstablished { + peer_id, + endpoint, + connection_id, + .. + }) => { + match endpoint { + ConnectedPoint::Listener { .. } => { + self.established_inbound_connections.insert(connection_id); + } + ConnectedPoint::Dialer { .. } => { + self.established_outbound_connections.insert(connection_id); + } + } + + self.established_per_peer + .entry(peer_id) + .or_default() + .insert(connection_id); + } + FromSwarm::DialFailure(DialFailure { connection_id, .. }) => { + self.pending_outbound_connections.remove(&connection_id); + } FromSwarm::AddressChange(_) => {} - FromSwarm::DialFailure(_) => {} - FromSwarm::ListenFailure(_) => {} + FromSwarm::ListenFailure(ListenFailure { connection_id, .. }) => { + self.pending_inbound_connections.remove(&connection_id); + } FromSwarm::NewListener(_) => {} FromSwarm::NewListenAddr(_) => {} FromSwarm::ExpiredListenAddr(_) => {} @@ -364,7 +376,9 @@ impl NetworkBehaviour for Behaviour { #[cfg(test)] mod tests { use super::*; - use libp2p_swarm::{dial_opts::DialOpts, DialError, ListenError, Swarm, SwarmEvent}; + use libp2p_swarm::{ + behaviour::toggle::Toggle, dial_opts::DialOpts, DialError, ListenError, Swarm, SwarmEvent, + }; use libp2p_swarm_test::SwarmExt; use quickcheck::*; @@ -466,11 +480,57 @@ mod tests { quickcheck(prop as fn(_)); } + /// Another sibling [`NetworkBehaviour`] implementation might deny established connections in + /// [`handle_established_outbound_connection`] or [`handle_established_inbound_connection`]. + /// [`Behaviour`] must not increase the established counters in + /// [`handle_established_outbound_connection`] or [`handle_established_inbound_connection`], but + /// in [`SwarmEvent::ConnectionEstablished`] as the connection might still be denied by a + /// sibling [`NetworkBehaviour`] in the former case. Only in the latter case + /// ([`SwarmEvent::ConnectionEstablished`]) can the connection be seen as established. + #[test] + fn support_other_behaviour_denying_connection() { + let mut swarm1 = Swarm::new_ephemeral(|_| { + Behaviour::new_with_connection_denier(ConnectionLimits::default()) + }); + let mut swarm2 = Swarm::new_ephemeral(|_| Behaviour::new(ConnectionLimits::default())); + + async_std::task::block_on(async { + // Have swarm2 dial swarm1. + let (listen_addr, _) = swarm1.listen().await; + swarm2.dial(listen_addr).unwrap(); + async_std::task::spawn(swarm2.loop_on_next()); + + // Wait for the ConnectionDenier of swarm1 to deny the established connection. + let cause = swarm1 + .wait(|event| match event { + SwarmEvent::IncomingConnectionError { + error: ListenError::Denied { cause }, + .. + } => Some(cause), + _ => None, + }) + .await; + + cause.downcast::().unwrap(); + + assert_eq!( + 0, + swarm1 + .behaviour_mut() + .limits + .established_inbound_connections + .len(), + "swarm1 connection limit behaviour to not count denied established connection as established connection" + ) + }); + } + #[derive(libp2p_swarm_derive::NetworkBehaviour)] #[behaviour(prelude = "libp2p_swarm::derive_prelude")] struct Behaviour { limits: super::Behaviour, keep_alive: libp2p_swarm::keep_alive::Behaviour, + connection_denier: Toggle, } impl Behaviour { @@ -478,7 +538,67 @@ mod tests { Self { limits: super::Behaviour::new(limits), keep_alive: libp2p_swarm::keep_alive::Behaviour, + connection_denier: None.into(), } } + fn new_with_connection_denier(limits: ConnectionLimits) -> Self { + Self { + limits: super::Behaviour::new(limits), + keep_alive: libp2p_swarm::keep_alive::Behaviour, + connection_denier: Some(ConnectionDenier {}).into(), + } + } + } + + struct ConnectionDenier {} + + impl NetworkBehaviour for ConnectionDenier { + type ConnectionHandler = dummy::ConnectionHandler; + type ToSwarm = Void; + + fn handle_established_inbound_connection( + &mut self, + _connection_id: ConnectionId, + _peer: PeerId, + _local_addr: &Multiaddr, + _remote_addr: &Multiaddr, + ) -> Result, ConnectionDenied> { + Err(ConnectionDenied::new(std::io::Error::new( + std::io::ErrorKind::Other, + "ConnectionDenier", + ))) + } + + fn handle_established_outbound_connection( + &mut self, + _connection_id: ConnectionId, + _peer: PeerId, + _addr: &Multiaddr, + _role_override: Endpoint, + ) -> Result, ConnectionDenied> { + Err(ConnectionDenied::new(std::io::Error::new( + std::io::ErrorKind::Other, + "ConnectionDenier", + ))) + } + + fn on_swarm_event(&mut self, _event: FromSwarm) {} + + fn on_connection_handler_event( + &mut self, + _peer_id: PeerId, + _connection_id: ConnectionId, + event: THandlerOutEvent, + ) { + void::unreachable(event) + } + + fn poll( + &mut self, + _cx: &mut Context<'_>, + _params: &mut impl PollParameters, + ) -> Poll>> { + Poll::Pending + } } } From f10f1a274abe6e5193de653aa4dd951ae56c775e Mon Sep 17 00:00:00 2001 From: Max Inden Date: Wed, 26 Jul 2023 15:59:01 +0200 Subject: [PATCH 02/44] chore: prepare identity v0.2.2 and swarm v0.43.2 Pull-Request: #4256. --- identity/CHANGELOG.md | 2 +- swarm/CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/identity/CHANGELOG.md b/identity/CHANGELOG.md index 6d6c83962c5..bfe46076a3a 100644 --- a/identity/CHANGELOG.md +++ b/identity/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.2.2 - unreleased +## 0.2.2 - Implement `from_protobuf_encoding` for RSA `Keypair`. See [PR 4193]. diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index b5c33d90eb4..1d4108ac92c 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.43.2 - unreleased +## 0.43.2 - Display the cause of a `ListenError::Denied`. See [PR 4232] From 4e1fa9b8b8f1c62b86bcbf088dde790bafd3e008 Mon Sep 17 00:00:00 2001 From: Roman Date: Fri, 28 Jul 2023 18:22:03 +0800 Subject: [PATCH 03/44] refactor(quic): rewrite quic using quinn Rewrite quic using quinn instead of quinn-proto. libp2p-quic::endpoint::Driver is eliminated (and that hard quinn-proto machinery). Also: - ECN bits are handled - Support Generic Send Offload (GSO) Pull-Request: #3454. --- Cargo.lock | 37 +- Cargo.toml | 2 +- transports/quic/CHANGELOG.md | 7 + transports/quic/Cargo.toml | 8 +- transports/quic/src/config.rs | 142 ++++ transports/quic/src/connection.rs | 422 ++---------- transports/quic/src/connection/connecting.rs | 81 +-- transports/quic/src/connection/stream.rs | 86 +++ transports/quic/src/connection/substream.rs | 257 ------- transports/quic/src/endpoint.rs | 674 ------------------- transports/quic/src/hole_punching.rs | 36 +- transports/quic/src/lib.rs | 14 +- transports/quic/src/provider.rs | 51 +- transports/quic/src/provider/async_std.rs | 118 +--- transports/quic/src/provider/tokio.rs | 69 +- transports/quic/src/transport.rs | 380 ++++------- transports/quic/tests/smoke.rs | 27 +- 17 files changed, 608 insertions(+), 1803 deletions(-) create mode 100644 transports/quic/src/config.rs create mode 100644 transports/quic/src/connection/stream.rs delete mode 100644 transports/quic/src/connection/substream.rs delete mode 100644 transports/quic/src/endpoint.rs diff --git a/Cargo.lock b/Cargo.lock index b2fb6e87074..de08f42e91b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3040,7 +3040,7 @@ dependencies = [ [[package]] name = "libp2p-quic" -version = "0.8.0-alpha" +version = "0.9.0-alpha" dependencies = [ "async-std", "bytes", @@ -3058,7 +3058,7 @@ dependencies = [ "log", "parking_lot", "quickcheck", - "quinn-proto", + "quinn", "rand 0.8.5", "rustls 0.21.2", "thiserror", @@ -4313,6 +4313,26 @@ dependencies = [ "pin-project-lite 0.1.12", ] +[[package]] +name = "quinn" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21252f1c0fc131f1b69182db8f34837e8a69737b8251dff75636a9be0518c324" +dependencies = [ + "async-io", + "async-std", + "bytes", + "futures-io", + "pin-project-lite 0.2.9", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.21.2", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "quinn-proto" version = "0.10.1" @@ -4330,6 +4350,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "quinn-udp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df19e284d93757a9fb91d63672f7741b129246a669db09d1c0063071debc0c0" +dependencies = [ + "bytes", + "libc", + "socket2 0.5.3", + "tracing", + "windows-sys 0.48.0", +] + [[package]] name = "quote" version = "1.0.32" diff --git a/Cargo.toml b/Cargo.toml index 66b2cfc58ee..fa8c70eb4ea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,7 +83,7 @@ libp2p-perf = { version = "0.2.0", path = "protocols/perf" } libp2p-ping = { version = "0.43.0", path = "protocols/ping" } libp2p-plaintext = { version = "0.40.0", path = "transports/plaintext" } libp2p-pnet = { version = "0.23.0", path = "transports/pnet" } -libp2p-quic = { version = "0.8.0-alpha", path = "transports/quic" } +libp2p-quic = { version = "0.9.0-alpha", path = "transports/quic" } libp2p-relay = { version = "0.16.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" } diff --git a/transports/quic/CHANGELOG.md b/transports/quic/CHANGELOG.md index 6e3ce801a2c..2012a3caf94 100644 --- a/transports/quic/CHANGELOG.md +++ b/transports/quic/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.9.0-alpha - unreleased + +- Use `quinn` instead of `quinn-proto`. + See [PR 3454]. + +[PR 3454]: https://github.com/libp2p/rust-libp2p/pull/3454 + ## 0.8.0-alpha - Raise MSRV to 1.65. diff --git a/transports/quic/Cargo.toml b/transports/quic/Cargo.toml index a04cc8d48b5..5d810860912 100644 --- a/transports/quic/Cargo.toml +++ b/transports/quic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libp2p-quic" -version = "0.8.0-alpha" +version = "0.9.0-alpha" authors = ["Parity Technologies "] edition = "2021" rust-version = { workspace = true } @@ -19,15 +19,15 @@ libp2p-tls = { workspace = true } libp2p-identity = { workspace = true } log = "0.4" parking_lot = "0.12.0" -quinn-proto = { version = "0.10.1", default-features = false, features = ["tls-rustls"] } +quinn = { version = "0.10.1", default-features = false, features = ["tls-rustls", "futures-io"] } rand = "0.8.5" rustls = { version = "0.21.2", default-features = false } thiserror = "1.0.44" tokio = { version = "1.29.1", default-features = false, features = ["net", "rt", "time"], optional = true } [features] -tokio = ["dep:tokio", "if-watch/tokio"] -async-std = ["dep:async-std", "if-watch/smol"] +tokio = ["dep:tokio", "if-watch/tokio", "quinn/runtime-tokio"] +async-std = ["dep:async-std", "if-watch/smol", "quinn/runtime-async-std"] # Passing arguments to the docsrs builder in order to properly document cfg's. # More information: https://docs.rs/about/builds#cross-compiling diff --git a/transports/quic/src/config.rs b/transports/quic/src/config.rs new file mode 100644 index 00000000000..201594e247c --- /dev/null +++ b/transports/quic/src/config.rs @@ -0,0 +1,142 @@ +// Copyright 2017-2020 Parity Technologies (UK) Ltd. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use quinn::VarInt; +use std::{sync::Arc, time::Duration}; + +/// Config for the transport. +#[derive(Clone)] +pub struct Config { + /// Timeout for the initial handshake when establishing a connection. + /// The actual timeout is the minimum of this and the [`Config::max_idle_timeout`]. + pub handshake_timeout: Duration, + /// Maximum duration of inactivity in ms to accept before timing out the connection. + pub max_idle_timeout: u32, + /// Period of inactivity before sending a keep-alive packet. + /// Must be set lower than the idle_timeout of both + /// peers to be effective. + /// + /// See [`quinn::TransportConfig::keep_alive_interval`] for more + /// info. + pub keep_alive_interval: Duration, + /// Maximum number of incoming bidirectional streams that may be open + /// concurrently by the remote peer. + pub max_concurrent_stream_limit: u32, + + /// Max unacknowledged data in bytes that may be send on a single stream. + pub max_stream_data: u32, + + /// Max unacknowledged data in bytes that may be send in total on all streams + /// of a connection. + pub max_connection_data: u32, + + /// Support QUIC version draft-29 for dialing and listening. + /// + /// Per default only QUIC Version 1 / [`libp2p_core::multiaddr::Protocol::QuicV1`] + /// is supported. + /// + /// If support for draft-29 is enabled servers support draft-29 and version 1 on all + /// QUIC listening addresses. + /// As client the version is chosen based on the remote's address. + pub support_draft_29: bool, + + /// TLS client config for the inner [`quinn::ClientConfig`]. + client_tls_config: Arc, + /// TLS server config for the inner [`quinn::ServerConfig`]. + server_tls_config: Arc, +} + +impl Config { + /// Creates a new configuration object with default values. + pub fn new(keypair: &libp2p_identity::Keypair) -> Self { + let client_tls_config = Arc::new(libp2p_tls::make_client_config(keypair, None).unwrap()); + let server_tls_config = Arc::new(libp2p_tls::make_server_config(keypair).unwrap()); + Self { + client_tls_config, + server_tls_config, + support_draft_29: false, + handshake_timeout: Duration::from_secs(5), + max_idle_timeout: 30 * 1000, + max_concurrent_stream_limit: 256, + keep_alive_interval: Duration::from_secs(15), + max_connection_data: 15_000_000, + + // Ensure that one stream is not consuming the whole connection. + max_stream_data: 10_000_000, + } + } +} + +/// Represents the inner configuration for [`quinn`]. +#[derive(Debug, Clone)] +pub(crate) struct QuinnConfig { + pub(crate) client_config: quinn::ClientConfig, + pub(crate) server_config: quinn::ServerConfig, + pub(crate) endpoint_config: quinn::EndpointConfig, +} + +impl From for QuinnConfig { + fn from(config: Config) -> QuinnConfig { + let Config { + client_tls_config, + server_tls_config, + max_idle_timeout, + max_concurrent_stream_limit, + keep_alive_interval, + max_connection_data, + max_stream_data, + support_draft_29, + handshake_timeout: _, + } = config; + let mut transport = quinn::TransportConfig::default(); + // Disable uni-directional streams. + transport.max_concurrent_uni_streams(0u32.into()); + transport.max_concurrent_bidi_streams(max_concurrent_stream_limit.into()); + // Disable datagrams. + transport.datagram_receive_buffer_size(None); + transport.keep_alive_interval(Some(keep_alive_interval)); + transport.max_idle_timeout(Some(VarInt::from_u32(max_idle_timeout).into())); + transport.allow_spin(false); + transport.stream_receive_window(max_stream_data.into()); + transport.receive_window(max_connection_data.into()); + let transport = Arc::new(transport); + + let mut server_config = quinn::ServerConfig::with_crypto(server_tls_config); + server_config.transport = Arc::clone(&transport); + // Disables connection migration. + // Long-term this should be enabled, however we then need to handle address change + // on connections in the `Connection`. + server_config.migration(false); + + let mut client_config = quinn::ClientConfig::new(client_tls_config); + client_config.transport_config(transport); + + let mut endpoint_config = quinn::EndpointConfig::default(); + if !support_draft_29 { + endpoint_config.supported_versions(vec![1]); + } + + QuinnConfig { + client_config, + server_config, + endpoint_config, + } + } +} diff --git a/transports/quic/src/connection.rs b/transports/quic/src/connection.rs index 0e5727dcf21..783258a0130 100644 --- a/transports/quic/src/connection.rs +++ b/transports/quic/src/connection.rs @@ -19,409 +19,113 @@ // DEALINGS IN THE SOFTWARE. mod connecting; -mod substream; +mod stream; -use crate::{ - endpoint::{self, ToEndpoint}, - Error, -}; pub use connecting::Connecting; -pub use substream::Substream; -use substream::{SubstreamState, WriteState}; +pub use stream::Stream; + +use crate::{ConnectionError, Error}; -use futures::{channel::mpsc, ready, FutureExt, StreamExt}; -use futures_timer::Delay; +use futures::{future::BoxFuture, FutureExt}; use libp2p_core::muxing::{StreamMuxer, StreamMuxerEvent}; -use parking_lot::Mutex; use std::{ - any::Any, - collections::HashMap, - net::SocketAddr, pin::Pin, - sync::Arc, - task::{Context, Poll, Waker}, - time::Instant, + task::{Context, Poll}, }; /// State for a single opened QUIC connection. -#[derive(Debug)] pub struct Connection { - /// State shared with the substreams. - state: Arc>, - /// Channel to the [`endpoint::Driver`] that drives the [`quinn_proto::Endpoint`] that - /// this connection belongs to. - endpoint_channel: endpoint::Channel, - /// Pending message to be sent to the [`quinn_proto::Endpoint`] in the [`endpoint::Driver`]. - pending_to_endpoint: Option, - /// Events that the [`quinn_proto::Endpoint`] will send in destination to our local - /// [`quinn_proto::Connection`]. - from_endpoint: mpsc::Receiver, - /// Identifier for this connection according to the [`quinn_proto::Endpoint`]. - /// Used when sending messages to the endpoint. - connection_id: quinn_proto::ConnectionHandle, - /// `Future` that triggers at the [`Instant`] that [`quinn_proto::Connection::poll_timeout`] - /// indicates. - next_timeout: Option<(Delay, Instant)>, + /// Underlying connection. + connection: quinn::Connection, + /// Future for accepting a new incoming bidirectional stream. + incoming: Option< + BoxFuture<'static, Result<(quinn::SendStream, quinn::RecvStream), quinn::ConnectionError>>, + >, + /// Future for opening a new outgoing bidirectional stream. + outgoing: Option< + BoxFuture<'static, Result<(quinn::SendStream, quinn::RecvStream), quinn::ConnectionError>>, + >, + /// Future to wait for the connection to be closed. + closing: Option>, } impl Connection { /// Build a [`Connection`] from raw components. /// - /// This function assumes that there exists a [`Driver`](super::endpoint::Driver) - /// that will process the messages sent to `EndpointChannel::to_endpoint` and send us messages - /// on `from_endpoint`. - /// - /// `connection_id` is used to identify the local connection in the messages sent to - /// `to_endpoint`. - /// - /// This function assumes that the [`quinn_proto::Connection`] is completely fresh and none of + /// This function assumes that the [`quinn::Connection`] is completely fresh and none of /// its methods has ever been called. Failure to comply might lead to logic errors and panics. - pub(crate) fn from_quinn_connection( - endpoint_channel: endpoint::Channel, - connection: quinn_proto::Connection, - connection_id: quinn_proto::ConnectionHandle, - from_endpoint: mpsc::Receiver, - ) -> Self { - let state = State { - connection, - substreams: HashMap::new(), - poll_connection_waker: None, - poll_inbound_waker: None, - poll_outbound_waker: None, - }; + fn new(connection: quinn::Connection) -> Self { Self { - endpoint_channel, - pending_to_endpoint: None, - next_timeout: None, - from_endpoint, - connection_id, - state: Arc::new(Mutex::new(state)), - } - } - - /// The address that the local socket is bound to. - pub(crate) fn local_addr(&self) -> &SocketAddr { - self.endpoint_channel.socket_addr() - } - - /// Returns the address of the node we're connected to. - pub(crate) fn remote_addr(&self) -> SocketAddr { - self.state.lock().connection.remote_address() - } - - /// Identity of the remote peer inferred from the handshake. - /// - /// `None` if the handshake is not complete yet, i.e. [`Self::poll_event`] - /// has not yet reported a [`quinn_proto::Event::Connected`] - fn peer_identity(&self) -> Option> { - self.state - .lock() - .connection - .crypto_session() - .peer_identity() - } - - /// Polls the connection for an event that happened on it. - /// - /// `quinn::proto::Connection` is polled in the order instructed in their docs: - /// 1. [`quinn_proto::Connection::poll_transmit`] - /// 2. [`quinn_proto::Connection::poll_timeout`] - /// 3. [`quinn_proto::Connection::poll_endpoint_events`] - /// 4. [`quinn_proto::Connection::poll`] - fn poll_event(&mut self, cx: &mut Context<'_>) -> Poll> { - let mut inner = self.state.lock(); - loop { - // Sending the pending event to the endpoint. If the endpoint is too busy, we just - // stop the processing here. - // We don't deliver substream-related events to the user as long as - // `to_endpoint` is full. This should propagate the back-pressure of `to_endpoint` - // being full to the user. - if let Some(to_endpoint) = self.pending_to_endpoint.take() { - match self.endpoint_channel.try_send(to_endpoint, cx) { - Ok(Ok(())) => {} - Ok(Err(to_endpoint)) => { - self.pending_to_endpoint = Some(to_endpoint); - return Poll::Pending; - } - Err(endpoint::Disconnected {}) => { - return Poll::Ready(None); - } - } - } - - match self.from_endpoint.poll_next_unpin(cx) { - Poll::Ready(Some(event)) => { - inner.connection.handle_event(event); - continue; - } - Poll::Ready(None) => { - return Poll::Ready(None); - } - Poll::Pending => {} - } - - // The maximum amount of segments which can be transmitted in a single Transmit - // if a platform supports Generic Send Offload (GSO). - // Set to 1 for now since not all platforms support GSO. - // TODO: Fix for platforms that support GSO. - let max_datagrams = 1; - // Poll the connection for packets to send on the UDP socket and try to send them on - // `to_endpoint`. - if let Some(transmit) = inner - .connection - .poll_transmit(Instant::now(), max_datagrams) - { - // TODO: ECN bits not handled - self.pending_to_endpoint = Some(ToEndpoint::SendUdpPacket(transmit)); - continue; - } - - match inner.connection.poll_timeout() { - Some(timeout) => match self.next_timeout { - Some((_, when)) if when == timeout => {} - _ => { - let now = Instant::now(); - // 0ns if now > when - let duration = timeout.duration_since(now); - let next_timeout = Delay::new(duration); - self.next_timeout = Some((next_timeout, timeout)) - } - }, - None => self.next_timeout = None, - } - - if let Some((timeout, when)) = self.next_timeout.as_mut() { - if timeout.poll_unpin(cx).is_ready() { - inner.connection.handle_timeout(*when); - continue; - } - } - - // The connection also needs to be able to send control messages to the endpoint. This is - // handled here, and we try to send them on `to_endpoint` as well. - if let Some(event) = inner.connection.poll_endpoint_events() { - let connection_id = self.connection_id; - self.pending_to_endpoint = Some(ToEndpoint::ProcessConnectionEvent { - connection_id, - event, - }); - continue; - } - - // The final step consists in returning the events related to the various substreams. - if let Some(ev) = inner.connection.poll() { - return Poll::Ready(Some(ev)); - } - - return Poll::Pending; + connection, + incoming: None, + outgoing: None, + closing: None, } } } impl StreamMuxer for Connection { - type Substream = Substream; + type Substream = Stream; type Error = Error; - fn poll( - mut self: Pin<&mut Self>, - cx: &mut Context<'_>, - ) -> Poll> { - while let Poll::Ready(event) = self.poll_event(cx) { - let mut inner = self.state.lock(); - let event = match event { - Some(event) => event, - None => return Poll::Ready(Err(Error::EndpointDriverCrashed)), - }; - match event { - quinn_proto::Event::Connected | quinn_proto::Event::HandshakeDataReady => { - debug_assert!( - false, - "Unexpected event {event:?} on established QUIC connection" - ); - } - quinn_proto::Event::ConnectionLost { reason } => { - inner - .connection - .close(Instant::now(), From::from(0u32), Default::default()); - inner.substreams.values_mut().for_each(|s| s.wake_all()); - return Poll::Ready(Err(Error::Connection(reason.into()))); - } - quinn_proto::Event::Stream(quinn_proto::StreamEvent::Opened { - dir: quinn_proto::Dir::Bi, - }) => { - if let Some(waker) = inner.poll_outbound_waker.take() { - waker.wake(); - } - } - quinn_proto::Event::Stream(quinn_proto::StreamEvent::Available { - dir: quinn_proto::Dir::Bi, - }) => { - if let Some(waker) = inner.poll_inbound_waker.take() { - waker.wake(); - } - } - quinn_proto::Event::Stream(quinn_proto::StreamEvent::Readable { id }) => { - if let Some(substream) = inner.substreams.get_mut(&id) { - if let Some(waker) = substream.read_waker.take() { - waker.wake(); - } - } - } - quinn_proto::Event::Stream(quinn_proto::StreamEvent::Writable { id }) => { - if let Some(substream) = inner.substreams.get_mut(&id) { - if let Some(waker) = substream.write_waker.take() { - waker.wake(); - } - } - } - quinn_proto::Event::Stream(quinn_proto::StreamEvent::Finished { id }) => { - if let Some(substream) = inner.substreams.get_mut(&id) { - if matches!( - substream.write_state, - WriteState::Open | WriteState::Closing - ) { - substream.write_state = WriteState::Closed; - } - if let Some(waker) = substream.write_waker.take() { - waker.wake(); - } - if let Some(waker) = substream.close_waker.take() { - waker.wake(); - } - } - } - quinn_proto::Event::Stream(quinn_proto::StreamEvent::Stopped { - id, - error_code: _, - }) => { - if let Some(substream) = inner.substreams.get_mut(&id) { - substream.write_state = WriteState::Stopped; - if let Some(waker) = substream.write_waker.take() { - waker.wake(); - } - if let Some(waker) = substream.close_waker.take() { - waker.wake(); - } - } - } - quinn_proto::Event::DatagramReceived - | quinn_proto::Event::Stream(quinn_proto::StreamEvent::Available { - dir: quinn_proto::Dir::Uni, - }) - | quinn_proto::Event::Stream(quinn_proto::StreamEvent::Opened { - dir: quinn_proto::Dir::Uni, - }) => { - unreachable!("We don't use datagrams or unidirectional streams.") - } - } - } - // TODO: If connection migration is enabled (currently disabled) address - // change on the connection needs to be handled. - - self.state.lock().poll_connection_waker = Some(cx.waker().clone()); - Poll::Pending - } - fn poll_inbound( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - let mut inner = self.state.lock(); + let this = self.get_mut(); - let substream_id = match inner.connection.streams().accept(quinn_proto::Dir::Bi) { - Some(id) => { - inner.poll_inbound_waker = None; - id - } - None => { - inner.poll_inbound_waker = Some(cx.waker().clone()); - return Poll::Pending; - } - }; - inner.substreams.insert(substream_id, Default::default()); - let substream = Substream::new(substream_id, self.state.clone()); + let incoming = this.incoming.get_or_insert_with(|| { + let connection = this.connection.clone(); + async move { connection.accept_bi().await }.boxed() + }); - Poll::Ready(Ok(substream)) + let (send, recv) = futures::ready!(incoming.poll_unpin(cx)).map_err(ConnectionError)?; + this.incoming.take(); + let stream = Stream::new(send, recv); + Poll::Ready(Ok(stream)) } fn poll_outbound( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - let mut inner = self.state.lock(); - let substream_id = match inner.connection.streams().open(quinn_proto::Dir::Bi) { - Some(id) => { - inner.poll_outbound_waker = None; - id - } - None => { - inner.poll_outbound_waker = Some(cx.waker().clone()); - return Poll::Pending; - } - }; - inner.substreams.insert(substream_id, Default::default()); - let substream = Substream::new(substream_id, self.state.clone()); - Poll::Ready(Ok(substream)) - } + let this = self.get_mut(); - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let mut inner = self.state.lock(); - if inner.connection.is_drained() { - return Poll::Ready(Ok(())); - } + let outgoing = this.outgoing.get_or_insert_with(|| { + let connection = this.connection.clone(); + async move { connection.open_bi().await }.boxed() + }); - for substream in inner.substreams.keys().cloned().collect::>() { - let _ = inner.connection.send_stream(substream).finish(); - } - - if inner.connection.streams().send_streams() == 0 && !inner.connection.is_closed() { - inner - .connection - .close(Instant::now(), From::from(0u32), Default::default()) - } - drop(inner); - - loop { - match ready!(self.poll_event(cx)) { - Some(quinn_proto::Event::ConnectionLost { .. }) => return Poll::Ready(Ok(())), - None => return Poll::Ready(Err(Error::EndpointDriverCrashed)), - _ => {} - } - } + let (send, recv) = futures::ready!(outgoing.poll_unpin(cx)).map_err(ConnectionError)?; + this.outgoing.take(); + let stream = Stream::new(send, recv); + Poll::Ready(Ok(stream)) } -} -impl Drop for Connection { - fn drop(&mut self) { - let to_endpoint = ToEndpoint::ProcessConnectionEvent { - connection_id: self.connection_id, - event: quinn_proto::EndpointEvent::drained(), - }; - self.endpoint_channel.send_on_drop(to_endpoint); + fn poll( + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + ) -> Poll> { + // TODO: If connection migration is enabled (currently disabled) address + // change on the connection needs to be handled. + Poll::Pending } -} -/// Mutex-protected state of [`Connection`]. -#[derive(Debug)] -pub struct State { - /// The QUIC inner state machine for this specific connection. - connection: quinn_proto::Connection, + fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.get_mut(); - /// State of all the substreams that the muxer reports as open. - pub substreams: HashMap, + let closing = this.closing.get_or_insert_with(|| { + this.connection.close(From::from(0u32), &[]); + let connection = this.connection.clone(); + async move { connection.closed().await }.boxed() + }); - /// Waker to wake if a new outbound substream is opened. - pub poll_outbound_waker: Option, - /// Waker to wake if a new inbound substream was happened. - pub poll_inbound_waker: Option, - /// Waker to wake if the connection should be polled again. - pub poll_connection_waker: Option, -} + match futures::ready!(closing.poll_unpin(cx)) { + // Expected error given that `connection.close` was called above. + quinn::ConnectionError::LocallyClosed => {} + error => return Poll::Ready(Err(Error::Connection(ConnectionError(error)))), + }; -impl State { - fn unchecked_substream_state(&mut self, id: quinn_proto::StreamId) -> &mut SubstreamState { - self.substreams - .get_mut(&id) - .expect("Substream should be known.") + Poll::Ready(Ok(())) } } diff --git a/transports/quic/src/connection/connecting.rs b/transports/quic/src/connection/connecting.rs index e9a7d3e5f2c..b911eaa7dfe 100644 --- a/transports/quic/src/connection/connecting.rs +++ b/transports/quic/src/connection/connecting.rs @@ -20,9 +20,12 @@ //! Future that drives a QUIC connection until is has performed its TLS handshake. -use crate::{Connection, Error}; +use crate::{Connection, ConnectionError, Error}; -use futures::prelude::*; +use futures::{ + future::{select, Either, FutureExt, Select}, + prelude::*, +}; use futures_timer::Delay; use libp2p_identity::PeerId; use std::{ @@ -34,64 +37,46 @@ use std::{ /// A QUIC connection currently being negotiated. #[derive(Debug)] pub struct Connecting { - connection: Option, - timeout: Delay, + connecting: Select, } impl Connecting { - pub(crate) fn new(connection: Connection, timeout: Duration) -> Self { + pub(crate) fn new(connection: quinn::Connecting, timeout: Duration) -> Self { Connecting { - connection: Some(connection), - timeout: Delay::new(timeout), + connecting: select(connection, Delay::new(timeout)), } } } +impl Connecting { + /// Returns the address of the node we're connected to. + /// Panics if the connection is still handshaking. + fn remote_peer_id(connection: &quinn::Connection) -> PeerId { + let identity = connection + .peer_identity() + .expect("connection got identity because it passed TLS handshake; qed"); + let certificates: Box> = + identity.downcast().expect("we rely on rustls feature; qed"); + let end_entity = certificates + .get(0) + .expect("there should be exactly one certificate; qed"); + let p2p_cert = libp2p_tls::certificate::parse(end_entity) + .expect("the certificate was validated during TLS handshake; qed"); + p2p_cert.peer_id() + } +} + impl Future for Connecting { type Output = Result<(PeerId, Connection), Error>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let connection = self - .connection - .as_mut() - .expect("Future polled after it has completed"); - - loop { - let event = match connection.poll_event(cx) { - Poll::Ready(Some(event)) => event, - Poll::Ready(None) => return Poll::Ready(Err(Error::EndpointDriverCrashed)), - Poll::Pending => { - return self - .timeout - .poll_unpin(cx) - .map(|()| Err(Error::HandshakeTimedOut)); - } - }; - match event { - quinn_proto::Event::Connected => { - // Parse the remote's Id identity from the certificate. - let identity = connection - .peer_identity() - .expect("connection got identity because it passed TLS handshake; qed"); - let certificates: Box> = - identity.downcast().expect("we rely on rustls feature; qed"); - let end_entity = certificates - .get(0) - .expect("there should be exactly one certificate; qed"); - let p2p_cert = libp2p_tls::certificate::parse(end_entity) - .expect("the certificate was validated during TLS handshake; qed"); - let peer_id = p2p_cert.peer_id(); + let connection = match futures::ready!(self.connecting.poll_unpin(cx)) { + Either::Right(_) => return Poll::Ready(Err(Error::HandshakeTimedOut)), + Either::Left((connection, _)) => connection.map_err(ConnectionError)?, + }; - return Poll::Ready(Ok((peer_id, self.connection.take().unwrap()))); - } - quinn_proto::Event::ConnectionLost { reason } => { - return Poll::Ready(Err(Error::Connection(reason.into()))) - } - quinn_proto::Event::HandshakeDataReady | quinn_proto::Event::Stream(_) => {} - quinn_proto::Event::DatagramReceived => { - debug_assert!(false, "Datagrams are not supported") - } - } - } + let peer_id = Self::remote_peer_id(&connection); + let muxer = Connection::new(connection); + Poll::Ready(Ok((peer_id, muxer))) } } diff --git a/transports/quic/src/connection/stream.rs b/transports/quic/src/connection/stream.rs new file mode 100644 index 00000000000..b0c505bf856 --- /dev/null +++ b/transports/quic/src/connection/stream.rs @@ -0,0 +1,86 @@ +// Copyright 2022 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use std::{ + io::{self}, + pin::Pin, + task::{Context, Poll}, +}; + +use futures::{AsyncRead, AsyncWrite}; + +/// A single stream on a connection +pub struct Stream { + /// A send part of the stream + send: quinn::SendStream, + /// A receive part of the stream + recv: quinn::RecvStream, + /// Whether the stream is closed or not + close_result: Option>, +} + +impl Stream { + pub(super) fn new(send: quinn::SendStream, recv: quinn::RecvStream) -> Self { + Self { + send, + recv, + close_result: None, + } + } +} + +impl AsyncRead for Stream { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context, + buf: &mut [u8], + ) -> Poll> { + if let Some(close_result) = self.close_result { + if close_result.is_err() { + return Poll::Ready(Ok(0)); + } + } + Pin::new(&mut self.recv).poll_read(cx, buf) + } +} + +impl AsyncWrite for Stream { + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context, + buf: &[u8], + ) -> Poll> { + Pin::new(&mut self.send).poll_write(cx, buf) + } + + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + Pin::new(&mut self.send).poll_flush(cx) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + if let Some(close_result) = self.close_result { + // For some reason poll_close needs to be 'fuse'able + return Poll::Ready(close_result.map_err(Into::into)); + } + let close_result = futures::ready!(Pin::new(&mut self.send).poll_close(cx)); + self.close_result = Some(close_result.as_ref().map_err(|e| e.kind()).copied()); + Poll::Ready(close_result) + } +} diff --git a/transports/quic/src/connection/substream.rs b/transports/quic/src/connection/substream.rs deleted file mode 100644 index b3a82542e9c..00000000000 --- a/transports/quic/src/connection/substream.rs +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright 2022 Protocol Labs. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use std::{ - io::{self, Write}, - pin::Pin, - sync::Arc, - task::{Context, Poll, Waker}, -}; - -use futures::{AsyncRead, AsyncWrite}; -use parking_lot::Mutex; - -use super::State; - -/// Wakers for the [`AsyncRead`] and [`AsyncWrite`] on a substream. -#[derive(Debug, Default, Clone)] -pub struct SubstreamState { - /// Waker to wake if the substream becomes readable. - pub read_waker: Option, - /// Waker to wake if the substream becomes writable, closed or stopped. - pub write_waker: Option, - /// Waker to wake if the substream becomes closed or stopped. - pub close_waker: Option, - - pub write_state: WriteState, -} - -impl SubstreamState { - /// Wake all wakers for reading, writing and closed the stream. - pub fn wake_all(&mut self) { - if let Some(waker) = self.read_waker.take() { - waker.wake(); - } - if let Some(waker) = self.write_waker.take() { - waker.wake(); - } - if let Some(waker) = self.close_waker.take() { - waker.wake(); - } - } -} - -/// A single stream on a connection -#[derive(Debug)] -pub struct Substream { - /// The id of the stream. - id: quinn_proto::StreamId, - /// The state of the [`super::Connection`] this stream belongs to. - state: Arc>, -} - -impl Substream { - pub fn new(id: quinn_proto::StreamId, state: Arc>) -> Self { - Self { id, state } - } -} - -impl AsyncRead for Substream { - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - mut buf: &mut [u8], - ) -> Poll> { - let mut state = self.state.lock(); - - let mut stream = state.connection.recv_stream(self.id); - let mut chunks = match stream.read(true) { - Ok(chunks) => chunks, - Err(quinn_proto::ReadableError::UnknownStream) => { - return Poll::Ready(Ok(0)); - } - Err(quinn_proto::ReadableError::IllegalOrderedRead) => { - unreachable!( - "Illegal ordered read can only happen if `stream.read(false)` is used." - ); - } - }; - - let mut bytes = 0; - let mut pending = false; - let mut error = None; - loop { - if buf.is_empty() { - // Chunks::next will continue returning `Ok(Some(_))` with an - // empty chunk if there is no space left in the buffer, so we - // break early here. - break; - } - let chunk = match chunks.next(buf.len()) { - Ok(Some(chunk)) => chunk, - Ok(None) => break, - Err(err @ quinn_proto::ReadError::Reset(_)) => { - error = Some(Err(io::Error::new(io::ErrorKind::ConnectionReset, err))); - break; - } - Err(quinn_proto::ReadError::Blocked) => { - pending = true; - break; - } - }; - - buf.write_all(&chunk.bytes).expect("enough buffer space"); - bytes += chunk.bytes.len(); - } - if chunks.finalize().should_transmit() { - if let Some(waker) = state.poll_connection_waker.take() { - waker.wake(); - } - } - if let Some(err) = error { - return Poll::Ready(err); - } - - if pending && bytes == 0 { - let substream_state = state.unchecked_substream_state(self.id); - substream_state.read_waker = Some(cx.waker().clone()); - return Poll::Pending; - } - - Poll::Ready(Ok(bytes)) - } -} - -impl AsyncWrite for Substream { - fn poll_write( - self: Pin<&mut Self>, - cx: &mut Context<'_>, - buf: &[u8], - ) -> Poll> { - let mut state = self.state.lock(); - - match state.connection.send_stream(self.id).write(buf) { - Ok(bytes) => { - if let Some(waker) = state.poll_connection_waker.take() { - waker.wake(); - } - Poll::Ready(Ok(bytes)) - } - Err(quinn_proto::WriteError::Blocked) => { - let substream_state = state.unchecked_substream_state(self.id); - substream_state.write_waker = Some(cx.waker().clone()); - Poll::Pending - } - Err(err @ quinn_proto::WriteError::Stopped(_)) => { - Poll::Ready(Err(io::Error::new(io::ErrorKind::ConnectionReset, err))) - } - Err(quinn_proto::WriteError::UnknownStream) => { - Poll::Ready(Err(io::ErrorKind::BrokenPipe.into())) - } - } - } - - fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - // quinn doesn't support flushing, calling close will flush all substreams. - Poll::Ready(Ok(())) - } - - fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let mut inner = self.state.lock(); - - let substream_state = inner.unchecked_substream_state(self.id); - match substream_state.write_state { - WriteState::Open => {} - WriteState::Closing => { - substream_state.close_waker = Some(cx.waker().clone()); - return Poll::Pending; - } - WriteState::Closed => return Poll::Ready(Ok(())), - WriteState::Stopped => { - let err = quinn_proto::FinishError::Stopped(0u32.into()); - return Poll::Ready(Err(io::Error::new(io::ErrorKind::ConnectionReset, err))); - } - } - - match inner.connection.send_stream(self.id).finish() { - Ok(()) => { - let substream_state = inner.unchecked_substream_state(self.id); - substream_state.close_waker = Some(cx.waker().clone()); - substream_state.write_state = WriteState::Closing; - Poll::Pending - } - Err(err @ quinn_proto::FinishError::Stopped(_)) => { - Poll::Ready(Err(io::Error::new(io::ErrorKind::ConnectionReset, err))) - } - Err(quinn_proto::FinishError::UnknownStream) => { - // We never make up IDs so the stream must have existed at some point if we get to here. - // `UnknownStream` is also emitted in case the stream is already finished, hence just - // return `Ok(())` here. - Poll::Ready(Ok(())) - } - } - } -} - -impl Drop for Substream { - fn drop(&mut self) { - let mut state = self.state.lock(); - state.substreams.remove(&self.id); - // Send `STOP_STREAM` if the remote did not finish the stream yet. - // We have to manually check the read stream since we might have - // received a `FIN` (without any other stream data) after the last - // time we tried to read. - let mut is_read_done = false; - if let Ok(mut chunks) = state.connection.recv_stream(self.id).read(true) { - if let Ok(chunk) = chunks.next(0) { - is_read_done = chunk.is_none(); - } - let _ = chunks.finalize(); - } - if !is_read_done { - let _ = state.connection.recv_stream(self.id).stop(0u32.into()); - } - // Close the writing side. - let mut send_stream = state.connection.send_stream(self.id); - match send_stream.finish() { - Ok(()) => {} - // Already finished or reset, which is fine. - Err(quinn_proto::FinishError::UnknownStream) => {} - Err(quinn_proto::FinishError::Stopped(reason)) => { - let _ = send_stream.reset(reason); - } - } - } -} - -#[derive(Debug, Default, Clone)] -pub enum WriteState { - /// The stream is open for writing. - #[default] - Open, - /// The writing side of the stream is closing. - Closing, - /// All data was successfully sent to the remote and the stream closed, - /// i.e. a [`quinn_proto::StreamEvent::Finished`] was reported for it. - Closed, - /// The stream was stopped by the remote before all data could be - /// sent. - Stopped, -} diff --git a/transports/quic/src/endpoint.rs b/transports/quic/src/endpoint.rs deleted file mode 100644 index bf69df50b62..00000000000 --- a/transports/quic/src/endpoint.rs +++ /dev/null @@ -1,674 +0,0 @@ -// Copyright 2017-2020 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -use crate::{ - provider::Provider, - transport::{ProtocolVersion, SocketFamily}, - ConnectError, Connection, Error, -}; - -use bytes::BytesMut; -use futures::{ - channel::{mpsc, oneshot}, - prelude::*, -}; -use quinn_proto::VarInt; -use std::{ - collections::HashMap, - net::{Ipv4Addr, Ipv6Addr, SocketAddr}, - ops::ControlFlow, - pin::Pin, - sync::Arc, - task::{Context, Poll}, - time::{Duration, Instant}, -}; - -// The `Driver` drops packets if the channel to the connection -// or transport is full. -// Set capacity 10 to avoid unnecessary packet drops if the receiver -// is only very briefly busy, but not buffer a large amount of packets -// if it is blocked longer. -const CHANNEL_CAPACITY: usize = 10; - -/// Config for the transport. -#[derive(Clone)] -pub struct Config { - /// Timeout for the initial handshake when establishing a connection. - /// The actual timeout is the minimum of this an the [`Config::max_idle_timeout`]. - pub handshake_timeout: Duration, - /// Maximum duration of inactivity in ms to accept before timing out the connection. - pub max_idle_timeout: u32, - /// Period of inactivity before sending a keep-alive packet. - /// Must be set lower than the idle_timeout of both - /// peers to be effective. - /// - /// See [`quinn_proto::TransportConfig::keep_alive_interval`] for more - /// info. - pub keep_alive_interval: Duration, - /// Maximum number of incoming bidirectional streams that may be open - /// concurrently by the remote peer. - pub max_concurrent_stream_limit: u32, - - /// Max unacknowledged data in bytes that may be send on a single stream. - pub max_stream_data: u32, - - /// Max unacknowledged data in bytes that may be send in total on all streams - /// of a connection. - pub max_connection_data: u32, - - /// Support QUIC version draft-29 for dialing and listening. - /// - /// Per default only QUIC Version 1 / [`libp2p_core::multiaddr::Protocol::QuicV1`] - /// is supported. - /// - /// If support for draft-29 is enabled servers support draft-29 and version 1 on all - /// QUIC listening addresses. - /// As client the version is chosen based on the remote's address. - pub support_draft_29: bool, - - /// TLS client config for the inner [`quinn_proto::ClientConfig`]. - client_tls_config: Arc, - /// TLS server config for the inner [`quinn_proto::ServerConfig`]. - server_tls_config: Arc, -} - -impl Config { - /// Creates a new configuration object with default values. - pub fn new(keypair: &libp2p_identity::Keypair) -> Self { - let client_tls_config = Arc::new(libp2p_tls::make_client_config(keypair, None).unwrap()); - let server_tls_config = Arc::new(libp2p_tls::make_server_config(keypair).unwrap()); - Self { - client_tls_config, - server_tls_config, - support_draft_29: false, - handshake_timeout: Duration::from_secs(5), - max_idle_timeout: 30 * 1000, - max_concurrent_stream_limit: 256, - keep_alive_interval: Duration::from_secs(15), - max_connection_data: 15_000_000, - - // Ensure that one stream is not consuming the whole connection. - max_stream_data: 10_000_000, - } - } -} - -/// Represents the inner configuration for [`quinn_proto`]. -#[derive(Debug, Clone)] -pub(crate) struct QuinnConfig { - client_config: quinn_proto::ClientConfig, - server_config: Arc, - endpoint_config: Arc, -} - -impl From for QuinnConfig { - fn from(config: Config) -> QuinnConfig { - let Config { - client_tls_config, - server_tls_config, - max_idle_timeout, - max_concurrent_stream_limit, - keep_alive_interval, - max_connection_data, - max_stream_data, - support_draft_29, - handshake_timeout: _, - } = config; - let mut transport = quinn_proto::TransportConfig::default(); - // Disable uni-directional streams. - transport.max_concurrent_uni_streams(0u32.into()); - transport.max_concurrent_bidi_streams(max_concurrent_stream_limit.into()); - // Disable datagrams. - transport.datagram_receive_buffer_size(None); - transport.keep_alive_interval(Some(keep_alive_interval)); - transport.max_idle_timeout(Some(VarInt::from_u32(max_idle_timeout).into())); - transport.allow_spin(false); - transport.stream_receive_window(max_stream_data.into()); - transport.receive_window(max_connection_data.into()); - let transport = Arc::new(transport); - - let mut server_config = quinn_proto::ServerConfig::with_crypto(server_tls_config); - server_config.transport = Arc::clone(&transport); - // Disables connection migration. - // Long-term this should be enabled, however we then need to handle address change - // on connections in the `Connection`. - server_config.migration(false); - - let mut client_config = quinn_proto::ClientConfig::new(client_tls_config); - client_config.transport_config(transport); - - let mut endpoint_config = quinn_proto::EndpointConfig::default(); - if !support_draft_29 { - endpoint_config.supported_versions(vec![1]); - } - - QuinnConfig { - client_config, - server_config: Arc::new(server_config), - endpoint_config: Arc::new(endpoint_config), - } - } -} - -/// Channel used to send commands to the [`Driver`]. -#[derive(Debug, Clone)] -pub(crate) struct Channel { - /// Channel to the background of the endpoint. - to_endpoint: mpsc::Sender, - /// Address that the socket is bound to. - /// Note: this may be a wildcard ip address. - socket_addr: SocketAddr, -} - -impl Channel { - /// Builds a new endpoint that is listening on the [`SocketAddr`]. - pub(crate) fn new_bidirectional( - quinn_config: QuinnConfig, - socket_addr: SocketAddr, - ) -> Result<(Self, mpsc::Receiver), Error> { - // Channel for forwarding new inbound connections to the listener. - let (new_connections_tx, new_connections_rx) = mpsc::channel(CHANNEL_CAPACITY); - let endpoint = Self::new::

(quinn_config, socket_addr, Some(new_connections_tx))?; - Ok((endpoint, new_connections_rx)) - } - - /// Builds a new endpoint that only supports outbound connections. - pub(crate) fn new_dialer( - quinn_config: QuinnConfig, - socket_family: SocketFamily, - ) -> Result { - let socket_addr = match socket_family { - SocketFamily::Ipv4 => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), - SocketFamily::Ipv6 => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), - }; - Self::new::

(quinn_config, socket_addr, None) - } - - /// Spawn a new [`Driver`] that runs in the background. - fn new( - quinn_config: QuinnConfig, - socket_addr: SocketAddr, - new_connections: Option>, - ) -> Result { - let socket = std::net::UdpSocket::bind(socket_addr)?; - // NOT blocking, as per man:bind(2), as we pass an IP address. - socket.set_nonblocking(true)?; - // Capacity 0 to back-pressure the rest of the application if - // the udp socket is busy. - let (to_endpoint_tx, to_endpoint_rx) = mpsc::channel(0); - - let channel = Self { - to_endpoint: to_endpoint_tx, - socket_addr: socket.local_addr()?, - }; - - let server_config = new_connections - .is_some() - .then_some(quinn_config.server_config); - - let provider_socket = P::from_socket(socket)?; - - let driver = Driver::

::new( - quinn_config.endpoint_config, - quinn_config.client_config, - new_connections, - server_config, - channel.clone(), - provider_socket, - to_endpoint_rx, - ); - - // Drive the endpoint future in the background. - P::spawn(driver); - - Ok(channel) - } - - pub(crate) fn socket_addr(&self) -> &SocketAddr { - &self.socket_addr - } - - /// Try to send a message to the background task without blocking. - /// - /// This first polls the channel for capacity. - /// If the channel is full, the message is returned in `Ok(Err(_))` - /// and the context's waker is registered for wake-up. - /// - /// If the background task crashed `Err` is returned. - pub(crate) fn try_send( - &mut self, - to_endpoint: ToEndpoint, - cx: &mut Context<'_>, - ) -> Result, Disconnected> { - match self.to_endpoint.poll_ready_unpin(cx) { - Poll::Ready(Ok(())) => {} - Poll::Ready(Err(e)) => { - debug_assert!( - e.is_disconnected(), - "mpsc::Sender can only be disconnected when calling `poll_ready_unpin" - ); - - return Err(Disconnected {}); - } - Poll::Pending => return Ok(Err(to_endpoint)), - }; - - if let Err(e) = self.to_endpoint.start_send(to_endpoint) { - debug_assert!(e.is_disconnected(), "We called `Sink::poll_ready` so we are guaranteed to have a slot. If this fails, it means we are disconnected."); - - return Err(Disconnected {}); - } - - Ok(Ok(())) - } - - pub(crate) async fn send(&mut self, to_endpoint: ToEndpoint) -> Result<(), Disconnected> { - self.to_endpoint - .send(to_endpoint) - .await - .map_err(|_| Disconnected {}) - } - - /// Send a message to inform the [`Driver`] about an - /// event caused by the owner of this [`Channel`] dropping. - /// This clones the sender to the endpoint to guarantee delivery. - /// This should *not* be called for regular messages. - pub(crate) fn send_on_drop(&mut self, to_endpoint: ToEndpoint) { - let _ = self.to_endpoint.clone().try_send(to_endpoint); - } -} - -#[derive(Debug, thiserror::Error, Clone, PartialEq, Eq)] -#[error("Background task disconnected")] -pub(crate) struct Disconnected {} -/// Message sent to the endpoint background task. -#[derive(Debug)] -pub(crate) enum ToEndpoint { - /// Instruct the [`quinn_proto::Endpoint`] to start connecting to the given address. - Dial { - /// UDP address to connect to. - addr: SocketAddr, - /// Version to dial the remote on. - version: ProtocolVersion, - /// Channel to return the result of the dialing to. - result: oneshot::Sender>, - }, - /// Send by a [`quinn_proto::Connection`] when the endpoint needs to process an event generated - /// by a connection. The event itself is opaque to us. Only `quinn_proto` knows what is in - /// there. - ProcessConnectionEvent { - connection_id: quinn_proto::ConnectionHandle, - event: quinn_proto::EndpointEvent, - }, - /// Instruct the endpoint to send a packet of data on its UDP socket. - SendUdpPacket(quinn_proto::Transmit), - /// The [`GenTransport`][crate::GenTransport] dialer or listener coupled to this endpoint - /// was dropped. - /// Once all pending connections are closed, the [`Driver`] should shut down. - Decoupled, -} - -/// Driver that runs in the background for as long as the endpoint is alive. Responsible for -/// processing messages and the UDP socket. -/// -/// # Behaviour -/// -/// This background task is responsible for the following: -/// -/// - Sending packets on the UDP socket. -/// - Receiving packets from the UDP socket and feed them to the [`quinn_proto::Endpoint`] state -/// machine. -/// - Transmitting events generated by the [`quinn_proto::Endpoint`] to the corresponding -/// [`crate::Connection`]. -/// - Receiving messages from the `rx` and processing the requested actions. This includes -/// UDP packets to send and events emitted by the [`crate::Connection`] objects. -/// - Sending new connections on `new_connection_tx`. -/// -/// When it comes to channels, there exists three main multi-producer-single-consumer channels -/// in play: -/// -/// - One channel, represented by `EndpointChannel::to_endpoint` and `Driver::rx`, -/// that communicates messages from [`Channel`] to the [`Driver`]. -/// - One channel for each existing connection that communicates messages from the -/// [`Driver` to that [`crate::Connection`]. -/// - One channel for the [`Driver`] to send newly-opened connections to. The receiving -/// side is processed by the [`GenTransport`][crate::GenTransport]. -/// -/// -/// ## Back-pressure -/// -/// ### If writing to the UDP socket is blocked -/// -/// In order to avoid an unbounded buffering of events, we prioritize sending data on the UDP -/// socket over everything else. Messages from the rest of the application sent through the -/// [`Channel`] are only processed if the UDP socket is ready so that we propagate back-pressure -/// in case of a busy socket. For connections, thus this eventually also back-pressures the -/// `AsyncWrite`on substreams. -/// -/// -/// ### Back-pressuring the remote if the application is busy -/// -/// If the channel to a connection is full because the connection is busy, inbound datagrams -/// for that connection are dropped so that the remote is backpressured. -/// The same applies for new connections if the transport is too busy to received it. -/// -/// -/// # Shutdown -/// -/// The background task shuts down if an [`ToEndpoint::Decoupled`] event was received and the -/// last active connection has drained. -#[derive(Debug)] -pub(crate) struct Driver { - // The actual QUIC state machine. - endpoint: quinn_proto::Endpoint, - // QuinnConfig for client connections. - client_config: quinn_proto::ClientConfig, - // Copy of the channel to the endpoint driver that is passed to each new connection. - channel: Channel, - // Channel to receive messages from the transport or connections. - rx: mpsc::Receiver, - - // Socket for sending and receiving datagrams. - provider_socket: P, - // Future for writing the next packet to the socket. - next_packet_out: Option, - - // List of all active connections, with a sender to notify them of events. - alive_connections: - HashMap>, - // Channel to forward new inbound connections to the transport. - // `None` if server capabilities are disabled, i.e. the endpoint is only used for dialing. - new_connection_tx: Option>, - // Whether the transport dropped its handle for this endpoint. - is_decoupled: bool, -} - -impl Driver

{ - fn new( - endpoint_config: Arc, - client_config: quinn_proto::ClientConfig, - new_connection_tx: Option>, - server_config: Option>, - channel: Channel, - socket: P, - rx: mpsc::Receiver, - ) -> Self { - Driver { - endpoint: quinn_proto::Endpoint::new(endpoint_config, server_config, false), - client_config, - channel, - rx, - provider_socket: socket, - next_packet_out: None, - alive_connections: HashMap::new(), - new_connection_tx, - is_decoupled: false, - } - } - - /// Handle a message sent from either the [`GenTransport`](super::GenTransport) - /// or a [`crate::Connection`]. - fn handle_message( - &mut self, - to_endpoint: ToEndpoint, - ) -> ControlFlow<(), Option> { - match to_endpoint { - ToEndpoint::Dial { - addr, - result, - version, - } => { - let mut config = self.client_config.clone(); - if version == ProtocolVersion::Draft29 { - config.version(0xff00_001d); - } - // This `"l"` seems necessary because an empty string is an invalid domain - // name. While we don't use domain names, the underlying rustls library - // is based upon the assumption that we do. - let (connection_id, connection) = match self.endpoint.connect(config, addr, "l") { - Ok(c) => c, - Err(err) => { - let _ = result.send(Err(ConnectError::from(err).into())); - return ControlFlow::Continue(None); - } - }; - - debug_assert_eq!(connection.side(), quinn_proto::Side::Client); - let (tx, rx) = mpsc::channel(CHANNEL_CAPACITY); - let connection = Connection::from_quinn_connection( - self.channel.clone(), - connection, - connection_id, - rx, - ); - self.alive_connections.insert(connection_id, tx); - let _ = result.send(Ok(connection)); - } - - // A connection wants to notify the endpoint of something. - ToEndpoint::ProcessConnectionEvent { - connection_id, - event, - } => { - let has_key = self.alive_connections.contains_key(&connection_id); - if !has_key { - return ControlFlow::Continue(None); - } - // We "drained" event indicates that the connection no longer exists and - // its ID can be reclaimed. - let is_drained_event = event.is_drained(); - if is_drained_event { - self.alive_connections.remove(&connection_id); - if self.is_decoupled && self.alive_connections.is_empty() { - log::debug!( - "Driver is decoupled and no active connections remain. Shutting down." - ); - return ControlFlow::Break(()); - } - } - - let event_back = self.endpoint.handle_event(connection_id, event); - - if let Some(event_back) = event_back { - debug_assert!(!is_drained_event); - if let Some(sender) = self.alive_connections.get_mut(&connection_id) { - // We clone the sender to guarantee that there will be at least one - // free slot to send the event. - // The channel can not grow out of bound because an `event_back` is - // only sent if we previously received an event from the same connection. - // If the connection is busy, it won't sent us any more events to handle. - let _ = sender.clone().start_send(event_back); - } else { - log::error!("State mismatch: event for closed connection"); - } - } - } - - // Data needs to be sent on the UDP socket. - ToEndpoint::SendUdpPacket(transmit) => return ControlFlow::Continue(Some(transmit)), - ToEndpoint::Decoupled => self.handle_decoupling()?, - } - ControlFlow::Continue(None) - } - - /// Handle an UDP datagram received on the socket. - /// The datagram content was written into the `socket_recv_buffer`. - fn handle_datagram(&mut self, packet: BytesMut, packet_src: SocketAddr) -> ControlFlow<()> { - let local_ip = self.channel.socket_addr.ip(); - // TODO: ECN bits aren't handled - let (connec_id, event) = - match self - .endpoint - .handle(Instant::now(), packet_src, Some(local_ip), None, packet) - { - Some(event) => event, - None => return ControlFlow::Continue(()), - }; - match event { - quinn_proto::DatagramEvent::ConnectionEvent(event) => { - // `event` has type `quinn_proto::ConnectionEvent`, which has multiple - // variants. `quinn_proto::Endpoint::handle` however only ever returns - // `ConnectionEvent::Datagram`. - debug_assert!(format!("{event:?}").contains("Datagram")); - - // Redirect the datagram to its connection. - if let Some(sender) = self.alive_connections.get_mut(&connec_id) { - match sender.try_send(event) { - Ok(()) => {} - Err(err) if err.is_disconnected() => { - // Connection was dropped by the user. - // Inform the endpoint that this connection is drained. - self.endpoint - .handle_event(connec_id, quinn_proto::EndpointEvent::drained()); - self.alive_connections.remove(&connec_id); - } - Err(err) if err.is_full() => { - // Connection is too busy. Drop the datagram to back-pressure the remote. - log::debug!( - "Dropping packet for connection {:?} because the connection's channel is full.", - connec_id - ); - } - Err(_) => unreachable!("Error is either `Full` or `Disconnected`."), - } - } else { - log::error!("State mismatch: event for closed connection"); - } - } - quinn_proto::DatagramEvent::NewConnection(connec) => { - // A new connection has been received. `connec_id` is a newly-allocated - // identifier. - debug_assert_eq!(connec.side(), quinn_proto::Side::Server); - let connection_tx = match self.new_connection_tx.as_mut() { - Some(tx) => tx, - None => { - debug_assert!(false, "Endpoint reported a new connection even though server capabilities are disabled."); - return ControlFlow::Continue(()); - } - }; - - let (tx, rx) = mpsc::channel(CHANNEL_CAPACITY); - let connection = - Connection::from_quinn_connection(self.channel.clone(), connec, connec_id, rx); - match connection_tx.start_send(connection) { - Ok(()) => { - self.alive_connections.insert(connec_id, tx); - } - Err(e) if e.is_disconnected() => self.handle_decoupling()?, - Err(e) if e.is_full() => log::warn!( - "Dropping new incoming connection {:?} because the channel to the listener is full", - connec_id - ), - Err(_) => unreachable!("Error is either `Full` or `Disconnected`."), - } - } - } - ControlFlow::Continue(()) - } - - /// The transport dropped the channel to this [`Driver`]. - fn handle_decoupling(&mut self) -> ControlFlow<()> { - if self.alive_connections.is_empty() { - return ControlFlow::Break(()); - } - // Listener was closed. - self.endpoint.reject_new_connections(); - self.new_connection_tx = None; - self.is_decoupled = true; - ControlFlow::Continue(()) - } -} - -/// Future that runs until the [`Driver`] is decoupled and not active connections -/// remain -impl Future for Driver

{ - type Output = (); - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - loop { - // Flush any pending pocket so that the socket is reading to write an next - // packet. - match self.provider_socket.poll_send_flush(cx) { - // The pending packet was send or no packet was pending. - Poll::Ready(Ok(_)) => { - // Start sending a packet on the socket. - if let Some(transmit) = self.next_packet_out.take() { - self.provider_socket - .start_send(transmit.contents.into(), transmit.destination); - continue; - } - - // The endpoint might request packets to be sent out. This is handled in - // priority to avoid buffering up packets. - if let Some(transmit) = self.endpoint.poll_transmit() { - self.next_packet_out = Some(transmit); - continue; - } - - // Handle messages from transport and connections. - match self.rx.poll_next_unpin(cx) { - Poll::Ready(Some(to_endpoint)) => match self.handle_message(to_endpoint) { - ControlFlow::Continue(Some(transmit)) => { - self.next_packet_out = Some(transmit); - continue; - } - ControlFlow::Continue(None) => continue, - ControlFlow::Break(()) => break, - }, - Poll::Ready(None) => { - unreachable!("Sender side is never dropped or closed.") - } - Poll::Pending => {} - } - } - // Errors on the socket are expected to never happen, and we handle them by simply - // printing a log message. The packet gets discarded in case of error, but we are - // robust to packet losses and it is consequently not a logic error to proceed with - // normal operations. - Poll::Ready(Err(err)) => { - log::warn!("Error while sending on QUIC UDP socket: {:?}", err); - continue; - } - Poll::Pending => {} - } - - // Poll for new packets from the remote. - match self.provider_socket.poll_recv_from(cx) { - Poll::Ready(Ok((bytes, packet_src))) => { - let bytes_mut = bytes.as_slice().into(); - match self.handle_datagram(bytes_mut, packet_src) { - ControlFlow::Continue(()) => continue, - ControlFlow::Break(()) => break, - } - } - // Errors on the socket are expected to never happen, and we handle them by - // simply printing a log message. - Poll::Ready(Err(err)) => { - log::warn!("Error while receive on QUIC UDP socket: {:?}", err); - continue; - } - Poll::Pending => {} - } - - return Poll::Pending; - } - - Poll::Ready(()) - } -} diff --git a/transports/quic/src/hole_punching.rs b/transports/quic/src/hole_punching.rs index b9589dd17a0..874bc659b2e 100644 --- a/transports/quic/src/hole_punching.rs +++ b/transports/quic/src/hole_punching.rs @@ -1,19 +1,20 @@ -use std::{net::SocketAddr, time::Duration}; +use crate::{provider::Provider, Error}; use futures::future::Either; + use rand::{distributions, Rng}; -use crate::{ - endpoint::{self, ToEndpoint}, - Error, Provider, +use std::{ + net::{SocketAddr, UdpSocket}, + time::Duration, }; pub(crate) async fn hole_puncher( - endpoint_channel: endpoint::Channel, + socket: UdpSocket, remote_addr: SocketAddr, timeout_duration: Duration, ) -> Error { - let punch_holes_future = punch_holes::

(endpoint_channel, remote_addr); + let punch_holes_future = punch_holes::

(socket, remote_addr); futures::pin_mut!(punch_holes_future); match futures::future::select(P::sleep(timeout_duration), punch_holes_future).await { Either::Left(_) => Error::HandshakeTimedOut, @@ -21,27 +22,18 @@ pub(crate) async fn hole_puncher( } } -async fn punch_holes( - mut endpoint_channel: endpoint::Channel, - remote_addr: SocketAddr, -) -> Error { +async fn punch_holes(socket: UdpSocket, remote_addr: SocketAddr) -> Error { loop { let sleep_duration = Duration::from_millis(rand::thread_rng().gen_range(10..=200)); P::sleep(sleep_duration).await; - let random_udp_packet = ToEndpoint::SendUdpPacket(quinn_proto::Transmit { - destination: remote_addr, - ecn: None, - contents: rand::thread_rng() - .sample_iter(distributions::Standard) - .take(64) - .collect(), - segment_size: None, - src_ip: None, - }); + let contents: Vec = rand::thread_rng() + .sample_iter(distributions::Standard) + .take(64) + .collect(); - if endpoint_channel.send(random_udp_packet).await.is_err() { - return Error::EndpointDriverCrashed; + if let Err(e) = P::send_to(&socket, &contents, remote_addr).await { + return Error::Io(e); } } } diff --git a/transports/quic/src/lib.rs b/transports/quic/src/lib.rs index 945f5119c6e..494ecfdcddb 100644 --- a/transports/quic/src/lib.rs +++ b/transports/quic/src/lib.rs @@ -57,16 +57,17 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +mod config; mod connection; -mod endpoint; mod hole_punching; mod provider; mod transport; use std::net::SocketAddr; -pub use connection::{Connecting, Connection, Substream}; -pub use endpoint::Config; +pub use config::Config; +pub use connection::{Connecting, Connection, Stream}; + #[cfg(feature = "async-std")] pub use provider::async_std; #[cfg(feature = "tokio")] @@ -89,8 +90,7 @@ pub enum Error { #[error(transparent)] Io(#[from] std::io::Error), - /// The task spawned in [`Provider::spawn`] to drive - /// the quic endpoint has crashed. + /// The task to drive a quic endpoint has crashed. #[error("Endpoint driver crashed")] EndpointDriverCrashed, @@ -110,9 +110,9 @@ pub enum Error { /// Dialing a remote peer failed. #[derive(Debug, thiserror::Error)] #[error(transparent)] -pub struct ConnectError(#[from] quinn_proto::ConnectError); +pub struct ConnectError(quinn::ConnectError); /// Error on an established [`Connection`]. #[derive(Debug, thiserror::Error)] #[error(transparent)] -pub struct ConnectionError(#[from] quinn_proto::ConnectionError); +pub struct ConnectionError(quinn::ConnectionError); diff --git a/transports/quic/src/provider.rs b/transports/quic/src/provider.rs index c9401e9b99f..6f1122ee55f 100644 --- a/transports/quic/src/provider.rs +++ b/transports/quic/src/provider.rs @@ -18,11 +18,11 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use futures::{future::BoxFuture, Future}; +use futures::future::BoxFuture; use if_watch::IfEvent; use std::{ io, - net::SocketAddr, + net::{SocketAddr, UdpSocket}, task::{Context, Poll}, time::Duration, }; @@ -32,40 +32,20 @@ pub mod async_std; #[cfg(feature = "tokio")] pub mod tokio; -/// Size of the buffer for reading data 0x10000. -#[cfg(any(feature = "async-std", feature = "tokio"))] -const RECEIVE_BUFFER_SIZE: usize = 65536; +pub enum Runtime { + #[cfg(feature = "tokio")] + Tokio, + #[cfg(feature = "async-std")] + AsyncStd, + Dummy, +} -/// Provider for non-blocking receiving and sending on a [`std::net::UdpSocket`] -/// and spawning tasks. +/// Provider for a corresponding quinn runtime and spawning tasks. pub trait Provider: Unpin + Send + Sized + 'static { type IfWatcher: Unpin + Send; - /// Create a new providing that is wrapping the socket. - /// - /// Note: The socket must be set to non-blocking. - fn from_socket(socket: std::net::UdpSocket) -> io::Result; - - /// Receive a single packet. - /// - /// Returns the message and the address the message came from. - fn poll_recv_from(&mut self, cx: &mut Context<'_>) -> Poll, SocketAddr)>>; - - /// Set sending a packet on the socket. - /// - /// Since only one packet can be sent at a time, this may only be called if a preceding - /// call to [`Provider::poll_send_flush`] returned [`Poll::Ready`]. - fn start_send(&mut self, data: Vec, addr: SocketAddr); - - /// Flush a packet send in [`Provider::start_send`]. - /// - /// If [`Poll::Ready`] is returned the socket is ready for sending a new packet. - fn poll_send_flush(&mut self, cx: &mut Context<'_>) -> Poll>; - - /// Run the given future in the background until it ends. - /// - /// This is used to spawn the task that is driving the endpoint. - fn spawn(future: impl Future + Send + 'static); + /// Run the corresponding runtime + fn runtime() -> Runtime; /// Create a new [`if_watch`] watcher that reports [`IfEvent`]s for network interface changes. fn new_if_watcher() -> io::Result; @@ -78,4 +58,11 @@ pub trait Provider: Unpin + Send + Sized + 'static { /// Sleep for specified amount of time. fn sleep(duration: Duration) -> BoxFuture<'static, ()>; + + /// Sends data on the socket to the given address. On success, returns the number of bytes written. + fn send_to<'a>( + udp_socket: &'a UdpSocket, + buf: &'a [u8], + target: SocketAddr, + ) -> BoxFuture<'a, io::Result>; } diff --git a/transports/quic/src/provider/async_std.rs b/transports/quic/src/provider/async_std.rs index e593b2ed4f4..a110058108c 100644 --- a/transports/quic/src/provider/async_std.rs +++ b/transports/quic/src/provider/async_std.rs @@ -18,13 +18,10 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use async_std::{net::UdpSocket, task::spawn}; -use futures::{future::BoxFuture, ready, Future, FutureExt, Stream, StreamExt}; +use futures::{future::BoxFuture, FutureExt}; use std::{ io, - net::SocketAddr, - pin::Pin, - sync::Arc, + net::UdpSocket, task::{Context, Poll}, time::Duration, }; @@ -34,65 +31,14 @@ use crate::GenTransport; /// Transport with [`async-std`] runtime. pub type Transport = GenTransport; -/// Provider for reading / writing to a sockets and spawning -/// tasks using [`async-std`]. -pub struct Provider { - socket: Arc, - // Future for sending a packet. - // This is needed since [`async_Std::net::UdpSocket`] does not - // provide a poll-style interface for sending a packet. - send_packet: Option>>, - recv_stream: ReceiveStream, -} +/// Provider for quinn runtime and spawning tasks using [`async-std`]. +pub struct Provider; impl super::Provider for Provider { type IfWatcher = if_watch::smol::IfWatcher; - fn from_socket(socket: std::net::UdpSocket) -> io::Result { - let socket = Arc::new(socket.into()); - let recv_stream = ReceiveStream::new(Arc::clone(&socket)); - Ok(Provider { - socket, - send_packet: None, - recv_stream, - }) - } - - fn poll_recv_from(&mut self, cx: &mut Context<'_>) -> Poll, SocketAddr)>> { - match self.recv_stream.poll_next_unpin(cx) { - Poll::Ready(ready) => { - Poll::Ready(ready.expect("ReceiveStream::poll_next never returns None.")) - } - Poll::Pending => Poll::Pending, - } - } - - fn start_send(&mut self, data: Vec, addr: SocketAddr) { - let socket = self.socket.clone(); - let send = async move { - socket.send_to(&data, addr).await?; - Ok(()) - } - .boxed(); - self.send_packet = Some(send) - } - - fn poll_send_flush(&mut self, cx: &mut Context<'_>) -> Poll> { - let pending = match self.send_packet.as_mut() { - Some(pending) => pending, - None => return Poll::Ready(Ok(())), - }; - match pending.poll_unpin(cx) { - Poll::Ready(result) => { - self.send_packet = None; - Poll::Ready(result) - } - Poll::Pending => Poll::Pending, - } - } - - fn spawn(future: impl Future + Send + 'static) { - spawn(future); + fn runtime() -> super::Runtime { + super::Runtime::AsyncStd } fn new_if_watcher() -> io::Result { @@ -109,48 +55,16 @@ impl super::Provider for Provider { fn sleep(duration: Duration) -> BoxFuture<'static, ()> { async_std::task::sleep(duration).boxed() } -} - -type ReceiveStreamItem = ( - Result<(usize, SocketAddr), io::Error>, - Arc, - Vec, -); -/// Wrapper around the socket to implement `Stream` on it. -struct ReceiveStream { - /// Future for receiving a packet on the socket. - // This is needed since [`async_Std::net::UdpSocket`] does not - // provide a poll-style interface for receiving packets. - fut: BoxFuture<'static, ReceiveStreamItem>, -} - -impl ReceiveStream { - fn new(socket: Arc) -> Self { - let fut = ReceiveStream::next(socket, vec![0; super::RECEIVE_BUFFER_SIZE]).boxed(); - Self { fut: fut.boxed() } - } - - async fn next(socket: Arc, mut socket_recv_buffer: Vec) -> ReceiveStreamItem { - let recv = socket.recv_from(&mut socket_recv_buffer).await; - (recv, socket, socket_recv_buffer) - } -} - -impl Stream for ReceiveStream { - type Item = Result<(Vec, SocketAddr), io::Error>; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let (result, socket, buffer) = ready!(self.fut.poll_unpin(cx)); - - let result = result.map(|(packet_len, packet_src)| { - debug_assert!(packet_len <= buffer.len()); - // Copies the bytes from the `socket_recv_buffer` they were written into. - (buffer[..packet_len].into(), packet_src) - }); - // Set the future for receiving the next packet on the stream. - self.fut = ReceiveStream::next(socket, buffer).boxed(); - - Poll::Ready(Some(result)) + fn send_to<'a>( + udp_socket: &'a UdpSocket, + buf: &'a [u8], + target: std::net::SocketAddr, + ) -> BoxFuture<'a, io::Result> { + Box::pin(async move { + async_std::net::UdpSocket::from(udp_socket.try_clone()?) + .send_to(buf, target) + .await + }) } } diff --git a/transports/quic/src/provider/tokio.rs b/transports/quic/src/provider/tokio.rs index 77c9060e3c1..9cb148d6ef2 100644 --- a/transports/quic/src/provider/tokio.rs +++ b/transports/quic/src/provider/tokio.rs @@ -18,72 +18,27 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use futures::{future::BoxFuture, ready, Future, FutureExt}; +use futures::{future::BoxFuture, FutureExt}; use std::{ io, - net::SocketAddr, + net::{SocketAddr, UdpSocket}, task::{Context, Poll}, time::Duration, }; -use tokio::{io::ReadBuf, net::UdpSocket}; use crate::GenTransport; /// Transport with [`tokio`] runtime. pub type Transport = GenTransport; -/// Provider for reading / writing to a sockets and spawning -/// tasks using [`tokio`]. -pub struct Provider { - socket: UdpSocket, - socket_recv_buffer: Vec, - next_packet_out: Option<(Vec, SocketAddr)>, -} +/// Provider for quinn runtime and spawning tasks using [`tokio`]. +pub struct Provider; impl super::Provider for Provider { type IfWatcher = if_watch::tokio::IfWatcher; - fn from_socket(socket: std::net::UdpSocket) -> std::io::Result { - let socket = UdpSocket::from_std(socket)?; - Ok(Provider { - socket, - socket_recv_buffer: vec![0; super::RECEIVE_BUFFER_SIZE], - next_packet_out: None, - }) - } - - fn poll_send_flush(&mut self, cx: &mut Context<'_>) -> Poll> { - let (data, addr) = match self.next_packet_out.as_ref() { - Some(pending) => pending, - None => return Poll::Ready(Ok(())), - }; - match self.socket.poll_send_to(cx, data.as_slice(), *addr) { - Poll::Ready(result) => { - self.next_packet_out = None; - Poll::Ready(result.map(|_| ())) - } - Poll::Pending => Poll::Pending, - } - } - - fn poll_recv_from(&mut self, cx: &mut Context<'_>) -> Poll, SocketAddr)>> { - let Self { - socket, - socket_recv_buffer, - .. - } = self; - let mut read_buf = ReadBuf::new(socket_recv_buffer.as_mut_slice()); - let packet_src = ready!(socket.poll_recv_from(cx, &mut read_buf)?); - let bytes = read_buf.filled().to_vec(); - Poll::Ready(Ok((bytes, packet_src))) - } - - fn start_send(&mut self, data: Vec, addr: SocketAddr) { - self.next_packet_out = Some((data, addr)); - } - - fn spawn(future: impl Future + Send + 'static) { - tokio::spawn(future); + fn runtime() -> super::Runtime { + super::Runtime::Tokio } fn new_if_watcher() -> io::Result { @@ -100,4 +55,16 @@ impl super::Provider for Provider { fn sleep(duration: Duration) -> BoxFuture<'static, ()> { tokio::time::sleep(duration).boxed() } + + fn send_to<'a>( + udp_socket: &'a UdpSocket, + buf: &'a [u8], + target: SocketAddr, + ) -> BoxFuture<'a, io::Result> { + Box::pin(async move { + tokio::net::UdpSocket::from_std(udp_socket.try_clone()?)? + .send_to(buf, target) + .await + }) + } } diff --git a/transports/quic/src/transport.rs b/transports/quic/src/transport.rs index 84f9e479ee8..d4a1db35604 100644 --- a/transports/quic/src/transport.rs +++ b/transports/quic/src/transport.rs @@ -18,12 +18,12 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::endpoint::{Config, QuinnConfig, ToEndpoint}; +use crate::config::{Config, QuinnConfig}; use crate::hole_punching::hole_puncher; use crate::provider::Provider; -use crate::{endpoint, Connecting, Connection, Error}; +use crate::{ConnectError, Connecting, Connection, Error}; -use futures::channel::{mpsc, oneshot}; +use futures::channel::oneshot; use futures::future::{BoxFuture, Either}; use futures::ready; use futures::stream::StreamExt; @@ -38,10 +38,10 @@ use libp2p_core::{ }; use libp2p_identity::PeerId; use std::collections::hash_map::{DefaultHasher, Entry}; -use std::collections::{HashMap, VecDeque}; +use std::collections::HashMap; use std::fmt; use std::hash::{Hash, Hasher}; -use std::net::IpAddr; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket}; use std::time::Duration; use std::{ net::SocketAddr, @@ -62,7 +62,7 @@ use std::{ /// See . #[derive(Debug)] pub struct GenTransport { - /// Config for the inner [`quinn_proto`] structs. + /// Config for the inner [`quinn`] structs. quinn_config: QuinnConfig, /// Timeout for the [`Connecting`] future. handshake_timeout: Duration, @@ -71,7 +71,7 @@ pub struct GenTransport { /// Streams of active [`Listener`]s. listeners: SelectAll>, /// Dialer for each socket family if no matching listener exists. - dialer: HashMap, + dialer: HashMap, /// Waker to poll the transport again when a new dialer or listener is added. waker: Option, /// Holepunching attempts @@ -95,21 +95,57 @@ impl GenTransport

{ } } + /// Create a new [`quinn::Endpoint`] with the given configs. + fn new_endpoint( + endpoint_config: quinn::EndpointConfig, + server_config: Option, + socket: UdpSocket, + ) -> Result { + use crate::provider::Runtime; + match P::runtime() { + #[cfg(feature = "tokio")] + Runtime::Tokio => { + let runtime = std::sync::Arc::new(quinn::TokioRuntime); + let endpoint = + quinn::Endpoint::new(endpoint_config, server_config, socket, runtime)?; + Ok(endpoint) + } + #[cfg(feature = "async-std")] + Runtime::AsyncStd => { + let runtime = std::sync::Arc::new(quinn::AsyncStdRuntime); + let endpoint = + quinn::Endpoint::new(endpoint_config, server_config, socket, runtime)?; + Ok(endpoint) + } + Runtime::Dummy => { + let _ = endpoint_config; + let _ = server_config; + let _ = socket; + let err = std::io::Error::new(std::io::ErrorKind::Other, "no async runtime found"); + Err(Error::Io(err)) + } + } + } + + /// Extract the addr, quic version and peer id from the given [`Multiaddr`]. fn remote_multiaddr_to_socketaddr( &self, addr: Multiaddr, + check_unspecified_addr: bool, ) -> Result< (SocketAddr, ProtocolVersion, Option), TransportError<::Error>, > { let (socket_addr, version, peer_id) = multiaddr_to_socketaddr(&addr, self.support_draft_29) .ok_or_else(|| TransportError::MultiaddrNotSupported(addr.clone()))?; - if socket_addr.port() == 0 || socket_addr.ip().is_unspecified() { + if check_unspecified_addr && (socket_addr.port() == 0 || socket_addr.ip().is_unspecified()) + { return Err(TransportError::MultiaddrNotSupported(addr)); } Ok((socket_addr, version, peer_id)) } + /// Pick any listener to use for dialing. fn eligible_listener(&mut self, socket_addr: &SocketAddr) -> Option<&mut Listener

> { let mut listeners: Vec<_> = self .listeners @@ -118,7 +154,7 @@ impl GenTransport

{ if l.is_closed { return false; } - let listen_addr = l.endpoint_channel.socket_addr(); + let listen_addr = l.socket_addr(); SocketFamily::is_same(&listen_addr.ip(), &socket_addr.ip()) && listen_addr.ip().is_loopback() == socket_addr.ip().is_loopback() }) @@ -149,13 +185,16 @@ impl Transport for GenTransport

{ listener_id: ListenerId, addr: Multiaddr, ) -> Result<(), TransportError> { - let (socket_addr, version, _peer_id) = - multiaddr_to_socketaddr(&addr, self.support_draft_29) - .ok_or(TransportError::MultiaddrNotSupported(addr))?; + let (socket_addr, version, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, false)?; + let endpoint_config = self.quinn_config.endpoint_config.clone(); + let server_config = self.quinn_config.server_config.clone(); + let socket = UdpSocket::bind(socket_addr).map_err(Self::Error::from)?; + let socket_c = socket.try_clone().map_err(Self::Error::from)?; + let endpoint = Self::new_endpoint(endpoint_config, Some(server_config), socket)?; let listener = Listener::new( listener_id, - socket_addr, - self.quinn_config.clone(), + socket_c, + endpoint, self.handshake_timeout, version, )?; @@ -194,46 +233,68 @@ impl Transport for GenTransport

{ } fn dial(&mut self, addr: Multiaddr) -> Result> { - let (socket_addr, version, _peer_id) = self.remote_multiaddr_to_socketaddr(addr)?; - - let handshake_timeout = self.handshake_timeout; + let (socket_addr, version, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, true)?; - let dialer_state = match self.eligible_listener(&socket_addr) { + let endpoint = match self.eligible_listener(&socket_addr) { None => { // No listener. Get or create an explicit dialer. let socket_family = socket_addr.ip().into(); let dialer = match self.dialer.entry(socket_family) { - Entry::Occupied(occupied) => occupied.into_mut(), + Entry::Occupied(occupied) => occupied.get().clone(), Entry::Vacant(vacant) => { if let Some(waker) = self.waker.take() { waker.wake(); } - vacant.insert(Dialer::new::

(self.quinn_config.clone(), socket_family)?) + let listen_socket_addr = match socket_family { + SocketFamily::Ipv4 => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), + SocketFamily::Ipv6 => SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0), + }; + let socket = + UdpSocket::bind(listen_socket_addr).map_err(Self::Error::from)?; + let endpoint_config = self.quinn_config.endpoint_config.clone(); + let endpoint = Self::new_endpoint(endpoint_config, None, socket)?; + + vacant.insert(endpoint.clone()); + endpoint } }; - &mut dialer.state + dialer } - Some(listener) => &mut listener.dialer_state, + Some(listener) => listener.endpoint.clone(), }; - Ok(dialer_state.new_dial(socket_addr, handshake_timeout, version)) + let handshake_timeout = self.handshake_timeout; + let mut client_config = self.quinn_config.client_config.clone(); + if version == ProtocolVersion::Draft29 { + client_config.version(0xff00_001d); + } + Ok(Box::pin(async move { + // This `"l"` seems necessary because an empty string is an invalid domain + // name. While we don't use domain names, the underlying rustls library + // is based upon the assumption that we do. + let connecting = endpoint + .connect_with(client_config, socket_addr, "l") + .map_err(ConnectError)?; + Connecting::new(connecting, handshake_timeout).await + })) } fn dial_as_listener( &mut self, addr: Multiaddr, ) -> Result> { - let (socket_addr, _version, peer_id) = self.remote_multiaddr_to_socketaddr(addr.clone())?; + let (socket_addr, _version, peer_id) = + self.remote_multiaddr_to_socketaddr(addr.clone(), true)?; let peer_id = peer_id.ok_or(TransportError::MultiaddrNotSupported(addr))?; - let endpoint_channel = self + let socket = self .eligible_listener(&socket_addr) .ok_or(TransportError::Other( Error::NoActiveListenerForDialAsListener, ))? - .endpoint_channel - .clone(); + .try_clone_socket() + .map_err(Self::Error::from)?; - let hole_puncher = hole_puncher::

(endpoint_channel, socket_addr, self.handshake_timeout); + let hole_puncher = hole_puncher::

(socket, socket_addr, self.handshake_timeout); let (sender, receiver) = oneshot::channel(); @@ -274,19 +335,6 @@ impl Transport for GenTransport

{ mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - let mut errored = Vec::new(); - for (key, dialer) in &mut self.dialer { - if let Poll::Ready(_error) = dialer.poll(cx) { - errored.push(*key); - } - } - - for key in errored { - // Endpoint driver of dialer crashed. - // Drop dialer and all pending dials so that the connection receiver is notified. - self.dialer.remove(&key); - } - while let Poll::Ready(Some(ev)) = self.listeners.poll_next_unpin(cx) { match ev { TransportEvent::Incoming { @@ -331,112 +379,22 @@ impl From for TransportError { } } -/// Dialer for addresses if no matching listener exists. -#[derive(Debug)] -struct Dialer { - /// Channel to the [`crate::endpoint::Driver`] that - /// is driving the endpoint. - endpoint_channel: endpoint::Channel, - /// Queued dials for the endpoint. - state: DialerState, -} - -impl Dialer { - fn new( - config: QuinnConfig, - socket_family: SocketFamily, - ) -> Result> { - let endpoint_channel = endpoint::Channel::new_dialer::

(config, socket_family) - .map_err(TransportError::Other)?; - Ok(Dialer { - endpoint_channel, - state: DialerState::default(), - }) - } - - fn poll(&mut self, cx: &mut Context<'_>) -> Poll { - self.state.poll(&mut self.endpoint_channel, cx) - } -} - -impl Drop for Dialer { - fn drop(&mut self) { - self.endpoint_channel.send_on_drop(ToEndpoint::Decoupled); - } -} - -/// Pending dials to be sent to the endpoint was the [`endpoint::Channel`] -/// has capacity -#[derive(Default, Debug)] -struct DialerState { - pending_dials: VecDeque, - waker: Option, -} - -impl DialerState { - fn new_dial( - &mut self, - address: SocketAddr, - timeout: Duration, - version: ProtocolVersion, - ) -> BoxFuture<'static, Result<(PeerId, Connection), Error>> { - let (rx, tx) = oneshot::channel(); - - let message = ToEndpoint::Dial { - addr: address, - result: rx, - version, - }; - - self.pending_dials.push_back(message); - - if let Some(waker) = self.waker.take() { - waker.wake(); - } - - async move { - // Our oneshot getting dropped means the message didn't make it to the endpoint driver. - let connection = tx.await.map_err(|_| Error::EndpointDriverCrashed)??; - let (peer, connection) = Connecting::new(connection, timeout).await?; - - Ok((peer, connection)) - } - .boxed() - } - - /// Send all pending dials into the given [`endpoint::Channel`]. - /// - /// This only ever returns [`Poll::Pending`], or an error in case the channel is closed. - fn poll(&mut self, channel: &mut endpoint::Channel, cx: &mut Context<'_>) -> Poll { - while let Some(to_endpoint) = self.pending_dials.pop_front() { - match channel.try_send(to_endpoint, cx) { - Ok(Ok(())) => {} - Ok(Err(to_endpoint)) => { - self.pending_dials.push_front(to_endpoint); - break; - } - Err(endpoint::Disconnected {}) => return Poll::Ready(Error::EndpointDriverCrashed), - } - } - self.waker = Some(cx.waker().clone()); - Poll::Pending - } -} - /// Listener for incoming connections. struct Listener { /// Id of the listener. listener_id: ListenerId, + /// Version of the supported quic protocol. version: ProtocolVersion, - /// Channel to the endpoint to initiate dials. - endpoint_channel: endpoint::Channel, - /// Queued dials. - dialer_state: DialerState, + /// Endpoint + endpoint: quinn::Endpoint, - /// Channel where new connections are being sent. - new_connections_rx: mpsc::Receiver, + /// An underlying copy of the socket to be able to hole punch with + socket: UdpSocket, + + /// A future to poll new incoming connections. + accept: BoxFuture<'static, Option>, /// Timeout for connection establishment on inbound connections. handshake_timeout: Duration, @@ -458,38 +416,39 @@ struct Listener { impl Listener

{ fn new( listener_id: ListenerId, - socket_addr: SocketAddr, - config: QuinnConfig, + socket: UdpSocket, + endpoint: quinn::Endpoint, handshake_timeout: Duration, version: ProtocolVersion, ) -> Result { - let (endpoint_channel, new_connections_rx) = - endpoint::Channel::new_bidirectional::

(config, socket_addr)?; - let if_watcher; let pending_event; - if socket_addr.ip().is_unspecified() { + let local_addr = socket.local_addr()?; + if local_addr.ip().is_unspecified() { if_watcher = Some(P::new_if_watcher()?); pending_event = None; } else { if_watcher = None; - let ma = socketaddr_to_multiaddr(endpoint_channel.socket_addr(), version); + let ma = socketaddr_to_multiaddr(&local_addr, version); pending_event = Some(TransportEvent::NewAddress { listener_id, listen_addr: ma, }) } + let endpoint_c = endpoint.clone(); + let accept = async move { endpoint_c.accept().await }.boxed(); + Ok(Listener { - endpoint_channel, + endpoint, + socket, + accept, listener_id, version, - new_connections_rx, handshake_timeout, if_watcher, is_closed: false, pending_event, - dialer_state: DialerState::default(), close_listener_waker: None, }) } @@ -500,6 +459,7 @@ impl Listener

{ if self.is_closed { return; } + self.endpoint.close(From::from(0u32), &[]); self.pending_event = Some(TransportEvent::ListenerClosed { listener_id: self.listener_id, reason, @@ -512,8 +472,20 @@ impl Listener

{ } } + /// Clone underlying socket (for hole punching). + fn try_clone_socket(&self) -> std::io::Result { + self.socket.try_clone() + } + + fn socket_addr(&self) -> SocketAddr { + self.socket + .local_addr() + .expect("Cannot fail because the socket is bound") + } + /// Poll for a next If Event. fn poll_if_addr(&mut self, cx: &mut Context<'_>) -> Poll<::Item> { + let endpoint_addr = self.socket_addr(); let if_watcher = match self.if_watcher.as_mut() { Some(iw) => iw, None => return Poll::Pending, @@ -521,11 +493,9 @@ impl Listener

{ loop { match ready!(P::poll_if_event(if_watcher, cx)) { Ok(IfEvent::Up(inet)) => { - if let Some(listen_addr) = ip_to_listenaddr( - self.endpoint_channel.socket_addr(), - inet.addr(), - self.version, - ) { + if let Some(listen_addr) = + ip_to_listenaddr(&endpoint_addr, inet.addr(), self.version) + { log::debug!("New listen address: {}", listen_addr); return Poll::Ready(TransportEvent::NewAddress { listener_id: self.listener_id, @@ -534,11 +504,9 @@ impl Listener

{ } } Ok(IfEvent::Down(inet)) => { - if let Some(listen_addr) = ip_to_listenaddr( - self.endpoint_channel.socket_addr(), - inet.addr(), - self.version, - ) { + if let Some(listen_addr) = + ip_to_listenaddr(&endpoint_addr, inet.addr(), self.version) + { log::debug!("Expired listen address: {}", listen_addr); return Poll::Ready(TransportEvent::AddressExpired { listener_id: self.listener_id, @@ -555,21 +523,10 @@ impl Listener

{ } } } - - /// Poll [`DialerState`] to initiate requested dials. - fn poll_dialer(&mut self, cx: &mut Context<'_>) -> Poll { - let Self { - dialer_state, - endpoint_channel, - .. - } = self; - - dialer_state.poll(endpoint_channel, cx) - } } impl Stream for Listener

{ - type Item = TransportEvent; + type Item = TransportEvent< as Transport>::ListenerUpgrade, Error>; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { loop { if let Some(event) = self.pending_event.take() { @@ -581,17 +538,18 @@ impl Stream for Listener

{ if let Poll::Ready(event) = self.poll_if_addr(cx) { return Poll::Ready(Some(event)); } - if let Poll::Ready(error) = self.poll_dialer(cx) { - self.close(Err(error)); - continue; - } - match self.new_connections_rx.poll_next_unpin(cx) { - Poll::Ready(Some(connection)) => { - let local_addr = socketaddr_to_multiaddr(connection.local_addr(), self.version); - let send_back_addr = - socketaddr_to_multiaddr(&connection.remote_addr(), self.version); + + match self.accept.poll_unpin(cx) { + Poll::Ready(Some(connecting)) => { + let endpoint = self.endpoint.clone(); + self.accept = async move { endpoint.accept().await }.boxed(); + + let local_addr = socketaddr_to_multiaddr(&self.socket_addr(), self.version); + let remote_addr = connecting.remote_address(); + let send_back_addr = socketaddr_to_multiaddr(&remote_addr, self.version); + let event = TransportEvent::Incoming { - upgrade: Connecting::new(connection, self.handshake_timeout), + upgrade: Connecting::new(connecting, self.handshake_timeout), local_addr, send_back_addr, listener_id: self.listener_id, @@ -616,9 +574,6 @@ impl fmt::Debug for Listener

{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Listener") .field("listener_id", &self.listener_id) - .field("endpoint_channel", &self.endpoint_channel) - .field("dialer_state", &self.dialer_state) - .field("new_connections_rx", &self.new_connections_rx) .field("handshake_timeout", &self.handshake_timeout) .field("is_closed", &self.is_closed) .field("pending_event", &self.pending_event) @@ -626,12 +581,6 @@ impl fmt::Debug for Listener

{ } } -impl Drop for Listener

{ - fn drop(&mut self) { - self.endpoint_channel.send_on_drop(ToEndpoint::Decoupled); - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum ProtocolVersion { V1, // i.e. RFC9000 @@ -766,7 +715,6 @@ fn socketaddr_to_multiaddr(socket_addr: &SocketAddr, version: ProtocolVersion) - #[cfg(any(feature = "async-std", feature = "tokio"))] mod test { use futures::future::poll_fn; - use futures_timer::Delay; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use super::*; @@ -882,15 +830,6 @@ mod test { .listen_on(id, "/ip4/0.0.0.0/udp/0/quic-v1".parse().unwrap()) .unwrap(); - // Copy channel to use it later. - let mut channel = transport - .listeners - .iter() - .next() - .unwrap() - .endpoint_channel - .clone(); - match poll_fn(|cx| Pin::new(&mut transport).as_mut().poll(cx)).await { TransportEvent::NewAddress { listener_id, @@ -923,14 +862,6 @@ mod test { .now_or_never() .is_none()); assert!(transport.listeners.is_empty()); - - // Check that the [`Driver`] has shut down. - Delay::new(Duration::from_millis(10)).await; - poll_fn(|cx| { - assert!(channel.try_send(ToEndpoint::Decoupled, cx).is_err()); - Poll::Ready(()) - }) - .await; } } @@ -945,32 +876,9 @@ mod test { .dial("/ip4/123.45.67.8/udp/1234/quic-v1".parse().unwrap()) .unwrap(); - // Expect a dialer and its background task to exist. - let mut channel = transport - .dialer - .get(&SocketFamily::Ipv4) - .unwrap() - .endpoint_channel - .clone(); + assert!(transport.dialer.contains_key(&SocketFamily::Ipv4)); assert!(!transport.dialer.contains_key(&SocketFamily::Ipv6)); - // Send dummy dial to check that the endpoint driver is running. - poll_fn(|cx| { - let (tx, _) = oneshot::channel(); - let _ = channel - .try_send( - ToEndpoint::Dial { - addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0), - result: tx, - version: ProtocolVersion::V1, - }, - cx, - ) - .unwrap(); - Poll::Ready(()) - }) - .await; - // Start listening so that the dialer and driver are dropped. transport .listen_on( @@ -979,13 +887,5 @@ mod test { ) .unwrap(); assert!(!transport.dialer.contains_key(&SocketFamily::Ipv4)); - - // Check that the [`Driver`] has shut down. - Delay::new(Duration::from_millis(10)).await; - poll_fn(|cx| { - assert!(channel.try_send(ToEndpoint::Decoupled, cx).is_err()); - Poll::Ready(()) - }) - .await; } } diff --git a/transports/quic/tests/smoke.rs b/transports/quic/tests/smoke.rs index 8a6d689a7b0..93adfa68013 100644 --- a/transports/quic/tests/smoke.rs +++ b/transports/quic/tests/smoke.rs @@ -428,7 +428,7 @@ async fn smoke() { assert_eq!(b_connected, a_peer_id); } -async fn build_streams() -> (SubstreamBox, SubstreamBox) { +async fn build_streams() -> (SubstreamBox, SubstreamBox) { let (_, mut a_transport) = create_default_transport::

(); let (_, mut b_transport) = create_default_transport::

(); @@ -522,7 +522,7 @@ async fn start_listening(transport: &mut Boxed<(PeerId, StreamMuxerBox)>, addr: } } -fn prop( +fn prop( number_listeners: NonZeroU8, number_streams: NonZeroU8, ) -> quickcheck::TestResult { @@ -599,7 +599,7 @@ fn prop( quickcheck::TestResult::passed() } -async fn answer_inbound_streams( +async fn answer_inbound_streams( mut connection: StreamMuxerBox, ) { loop { @@ -634,7 +634,7 @@ async fn answer_inbound_streams( } } -async fn open_outbound_streams( +async fn open_outbound_streams( mut connection: StreamMuxerBox, number_streams: usize, completed_streams_tx: mpsc::Sender<()>, @@ -740,3 +740,22 @@ impl BlockOn for libp2p_quic::tokio::Provider { .unwrap() } } + +trait Spawn { + /// Run the given future in the background until it ends. + fn spawn(future: impl Future + Send + 'static); +} + +#[cfg(feature = "async-std")] +impl Spawn for libp2p_quic::async_std::Provider { + fn spawn(future: impl Future + Send + 'static) { + async_std::task::spawn(future); + } +} + +#[cfg(feature = "tokio")] +impl Spawn for libp2p_quic::tokio::Provider { + fn spawn(future: impl Future + Send + 'static) { + tokio::spawn(future); + } +} From 6121f23800ff6c315670428c9da899c9987969bf Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Fri, 28 Jul 2023 13:12:56 +0200 Subject: [PATCH 04/44] docs: add maintainer handbook This short document describes certain maintainer knowledge that IMO is good to have and should likely make on-boarding a bit easier too. Pull-Request: #4220. --- docs/maintainer-handbook.md | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 docs/maintainer-handbook.md diff --git a/docs/maintainer-handbook.md b/docs/maintainer-handbook.md new file mode 100644 index 00000000000..8ec6e6e8c6a --- /dev/null +++ b/docs/maintainer-handbook.md @@ -0,0 +1,60 @@ +# Maintainer handbook + +This document describes what ever maintainer of the repository should know. + +## GitHub settings + +All settings around GitHub like branch protection settings are managed through https://github.com/libp2p/github-mgmt. +For example, adding, removing or renaming a required CI job will need to be preceded by a PR that changes the configuration. + +To streamline things, it is good to _prepare_ such a PR together with the one that changes the CI workflows. +Take care to not merge the configuration change too early because it will block CI of all other PRs because GitHub now requires the new set of jobs (which will only be valid for the PR that actually changes the CI definition). + +## Mergify + +We utilize mergify as a merge-queue and overall automation bot on the repository. +The configuration file is [.github/mergify.yml](../.github/mergify.yml). + +The main feature is the `send-it` label. +Once a PR fulfills all merge requirements (approvals, passing CI, etc), applying the `send-it` labels activates mergify's merge-queue. + +- All branch protection rules, i.e. minimum number of reviews, green CI, etc are _implicit_ and thus do not need to be listed. +- Changing the mergify configuration file **always** requires the PR to be merged manually. + In other words, applying `send-it` to a PR that changes the mergify configuration has **no** effect. + This is a security feature of mergify to make sure changes to the automation are carefully reviewed. + +In case of a trivial code change, maintainers may choose to apply the `trivial` label. +This will have mergify approve your PR, thus fulfilling all requirements to automatically queue a PR for merging. + +## Dependencies + +We version our `Cargo.lock` file for better visibility into which dependencies are required for a functional build. +Additionally, this makes us resilient to semver-incompatible updates of our dependencies (which would otherwise result in a build error). + +As a consequence, we receive many dependency bump PRs from dependabot. +We have some automation in place to deal with those. + +1. semver-compatible updates (i.e. patch bumps for 0.x dependencies and minor bumps for 1.x dependencies) are approved automatically by mergify. +2. all approved dependabot PRs are queued for merging automatically + +The `send-it` label is not necessary (but also harmless) for dependabot PRs. + +## Issues vs discussions + +We typically use issues to handle bugs, feature-requests and track to-be-done work. +As a rule of thumb, we use issues for things that are fairly clear in nature. + +Broader ideas or brainstorming happens in GitHub's discussions. +Those allow for more fine-granular threading which is likely to happen for ideas that are not yet fleshed out. + +Unless specified otherwise, it is safe to assume that what is documented in issues represents the consensus of the maintainers. + +## Labels + +For the most part, the labels we use on issues are pretty self-explanatory. + +- `decision-pending`: Documents that the issue is blocked. + Maintainers are encouraged to provide their input on issues marked with this label. +- `need/author-input`: Integrates with our [.github/workflows/stale.yml](../.github/workflows/stale.yml) workflow. + Any issue tagged with this label will be auto-closed due to inactivity after a certain time. + From 1ebff97de74c8a4906bc0aafebbebe8ade2b5d2d Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 28 Jul 2023 14:01:15 +0200 Subject: [PATCH 05/44] docs(readme): rename iroh to beetle Pull-Request: #4265. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a268f319c05..9c151ade806 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). - [HotShot](https://github.com/EspressoSystems/HotShot) - Decentralized sequencer in Rust developed by [Espresso Systems](https://www.espressosys.com/). - [ipfs-embed](https://github.com/ipfs-rust/ipfs-embed) - A small embeddable ipfs implementation used and maintained by [Actyx](https://www.actyx.com). -- [iroh](https://github.com/n0-computer/iroh) - Next-generation implementation of IPFS for Cloud & Mobile platforms. +- [beetle](https://github.com/n0-computer/beetle) - Next-generation implementation of IPFS for Cloud & Mobile platforms. - [Lighthouse](https://github.com/sigp/lighthouse) - Ethereum consensus client in Rust. - [Locutus](https://github.com/freenet/locutus) - Global, observable, decentralized key-value store. - [rust-ipfs](https://github.com/rs-ipfs/rust-ipfs) - IPFS implementation in Rust. From fbfe0836a877baaadeda45635b92f58f550894c2 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 28 Jul 2023 16:07:00 +0200 Subject: [PATCH 06/44] docs(readme): add Mina project as notable user Pull-Request: #4263. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9c151ade806..4c7afa47e0c 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,7 @@ used and maintained by [Actyx](https://www.actyx.com). - [beetle](https://github.com/n0-computer/beetle) - Next-generation implementation of IPFS for Cloud & Mobile platforms. - [Lighthouse](https://github.com/sigp/lighthouse) - Ethereum consensus client in Rust. - [Locutus](https://github.com/freenet/locutus) - Global, observable, decentralized key-value store. +- [OpenMina](https://github.com/openmina/openmina) - In-browser Mina Rust implementation. - [rust-ipfs](https://github.com/rs-ipfs/rust-ipfs) - IPFS implementation in Rust. - [Starcoin](https://github.com/starcoinorg/starcoin) - A smart contract blockchain network that scales by layering. - [Subspace](https://github.com/subspace/subspace) - Subspace Network reference implementation From 6d3015a4aa41b539ccc91c7caea7c9f9dfc8042c Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 28 Jul 2023 22:41:46 +0200 Subject: [PATCH 07/44] docs(readme): add safe network to notable users Pull-Request: #4264. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4c7afa47e0c..da228391ff1 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ used and maintained by [Actyx](https://www.actyx.com). - [Locutus](https://github.com/freenet/locutus) - Global, observable, decentralized key-value store. - [OpenMina](https://github.com/openmina/openmina) - In-browser Mina Rust implementation. - [rust-ipfs](https://github.com/rs-ipfs/rust-ipfs) - IPFS implementation in Rust. +- [Safe Network](https://github.com/maidsafe/safe_network) - Safe Network implementation in Rust. - [Starcoin](https://github.com/starcoinorg/starcoin) - A smart contract blockchain network that scales by layering. - [Subspace](https://github.com/subspace/subspace) - Subspace Network reference implementation - [Substrate](https://github.com/paritytech/substrate) - Framework for blockchain innovation, From 5499333ff3f25a58e351a662c0396c15bff6063c Mon Sep 17 00:00:00 2001 From: Max Inden Date: Sat, 29 Jul 2023 21:56:11 +0200 Subject: [PATCH 08/44] fix(identity): use test fixture for ed25519 Use test fixture from https://github.com/libp2p/specs/pull/537/ for ed25519 roundtrip test. Pull-Request: #4228. --- identity/src/keypair.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs index f1d355cf2a0..d932528277a 100644 --- a/identity/src/keypair.rs +++ b/identity/src/keypair.rs @@ -766,16 +766,18 @@ mod tests { #[test] #[cfg(feature = "ed25519")] #[cfg(feature = "peerid")] - fn keypair_protobuf_roundtrip() { - let expected_keypair = Keypair::generate_ed25519(); - let expected_peer_id = expected_keypair.public().to_peer_id(); - - let encoded = expected_keypair.to_protobuf_encoding().unwrap(); + fn keypair_protobuf_roundtrip_ed25519() { + let priv_key = Keypair::from_protobuf_encoding(&hex_literal::hex!( + "080112407e0830617c4a7de83925dfb2694556b12936c477a0e1feb2e148ec9da60fee7d1ed1e8fae2c4a144b8be8fd4b47bf3d3b34b871c3cacf6010f0e42d474fce27e" + )) + .unwrap(); - let keypair = Keypair::from_protobuf_encoding(&encoded).unwrap(); - let peer_id = keypair.public().to_peer_id(); + let pub_key = PublicKey::try_decode_protobuf(&hex_literal::hex!( + "080112201ed1e8fae2c4a144b8be8fd4b47bf3d3b34b871c3cacf6010f0e42d474fce27e" + )) + .unwrap(); - assert_eq!(expected_peer_id, peer_id); + roundtrip_protobuf_encoding(&priv_key, &pub_key, KeyType::Ed25519); } #[test] From ceccb8e9c0e4b34ea651109c1b325f62ebdb69aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Oliveira?= Date: Mon, 31 Jul 2023 06:53:53 +0100 Subject: [PATCH 09/44] chore: fix clippy Pull-Request: #4267. --- Cargo.lock | 478 ++++++++++++++++---------------------- identity/src/keypair.rs | 4 - transports/tls/src/lib.rs | 2 +- 3 files changed, 206 insertions(+), 278 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de08f42e91b..0a0f8ec9c64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,9 +71,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" dependencies = [ "cfg-if 1.0.0", "cipher 0.4.4", @@ -82,14 +82,14 @@ dependencies = [ [[package]] name = "aes-gcm" -version = "0.9.4" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6" +checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f" dependencies = [ "aead 0.4.3", "aes 0.7.5", "cipher 0.3.0", - "ctr 0.8.0", + "ctr 0.7.0", "ghash 0.4.4", "subtle", ] @@ -101,7 +101,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" dependencies = [ "aead 0.5.2", - "aes 0.8.2", + "aes 0.8.3", "cipher 0.4.4", "ctr 0.9.2", "ghash 0.5.0", @@ -177,15 +177,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] @@ -196,7 +196,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -206,7 +206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -324,9 +324,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", @@ -388,7 +388,7 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.19", + "rustix 0.37.23", "slab", "socket2 0.4.9", "waker-fn", @@ -428,9 +428,9 @@ dependencies = [ "cfg-if 1.0.0", "event-listener", "futures-lite", - "rustix 0.37.19", + "rustix 0.37.23", "signal-hook", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -455,7 +455,7 @@ dependencies = [ "log", "memchr", "once_cell", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "pin-utils", "slab", "wasm-bindgen-futures", @@ -503,7 +503,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", ] [[package]] @@ -548,7 +548,7 @@ dependencies = [ "memchr", "mime", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "rustversion", "serde", "serde_json", @@ -631,9 +631,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "basic-toml" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c0de75129aa8d0cceaf750b89013f0e08804d6ec61416da787b35ad0d7cddf1" +checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6" dependencies = [ "serde", ] @@ -891,9 +891,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.12" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eab9e8ceb9afdade1ab3f0fd8dbce5b1b2f468ad653baf10e771781b2b67b73" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ "clap_builder", "clap_derive", @@ -902,9 +902,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.12" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f2763db829349bf00cfc06251268865ed4363b93a943174f638daf3ecdba2cd" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" dependencies = [ "anstream", "anstyle", @@ -945,7 +945,7 @@ dependencies = [ "bytes", "futures-core", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tokio", "tokio-util", ] @@ -971,9 +971,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" [[package]] name = "cookie" @@ -1013,9 +1013,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -1103,22 +1103,22 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "memoffset 0.8.0", + "memoffset 0.9.0", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if 1.0.0", ] @@ -1174,6 +1174,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "ctr" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481" +dependencies = [ + "cipher 0.3.0", +] + [[package]] name = "ctr" version = "0.8.0" @@ -1317,9 +1326,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17" +checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" dependencies = [ "const-oid", "pem-rfc7468 0.7.0", @@ -1430,9 +1439,9 @@ dependencies = [ [[package]] name = "dtoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "ecdsa" @@ -1448,15 +1457,15 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.7" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ - "der 0.7.6", + "der 0.7.7", "digest 0.10.7", "elliptic-curve 0.13.5", "rfc6979 0.4.0", - "signature 2.0.0", + "signature 2.1.0", "spki 0.7.2", ] @@ -1577,9 +1586,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" @@ -1589,7 +1598,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -1785,7 +1794,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "waker-fn", ] @@ -1818,7 +1827,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35bd3cf68c183738046838e300353e4716c674dc5e56890de4826801a6622a28" dependencies = [ "futures-io", - "rustls 0.21.2", + "rustls 0.21.5", ] [[package]] @@ -1867,7 +1876,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "pin-utils", "slab", ] @@ -1936,7 +1945,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" dependencies = [ "opaque-debug", - "polyval 0.6.0", + "polyval 0.6.1", ] [[package]] @@ -1987,9 +1996,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes", "fnv", @@ -2034,18 +2043,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -2134,14 +2134,14 @@ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", ] [[package]] name = "http-range-header" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" @@ -2177,7 +2177,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "socket2 0.4.9", "tokio", "tower-service", @@ -2380,9 +2380,9 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi", "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -2393,7 +2393,7 @@ checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ "socket2 0.5.3", "widestring", - "windows-sys 0.48.0", + "windows-sys", "winreg 0.50.0", ] @@ -2422,20 +2422,19 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix 0.37.19", - "windows-sys 0.48.0", + "hermit-abi", + "rustix 0.38.4", + "windows-sys", ] [[package]] @@ -2449,9 +2448,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" @@ -3060,7 +3059,7 @@ dependencies = [ "quickcheck", "quinn", "rand 0.8.5", - "rustls 0.21.2", + "rustls 0.21.5", "thiserror", "tokio", ] @@ -3241,7 +3240,7 @@ dependencies = [ "libp2p-yamux", "rcgen 0.10.0", "ring", - "rustls 0.21.2", + "rustls 0.21.5", "thiserror", "tokio", "webpki 0.22.0", @@ -3492,9 +3491,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "67827e6ea8ee8a7c4a72227ef4fc08957040acffdb5f122733b24fa12daff41b" [[package]] name = "md-5" @@ -3522,9 +3521,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -3581,7 +3580,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -3801,11 +3800,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] @@ -3921,7 +3920,7 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa 0.16.7", + "ecdsa 0.16.8", "elliptic-curve 0.13.5", "primeorder", "sha2 0.10.7", @@ -3979,9 +3978,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pem" @@ -4044,9 +4043,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -4080,7 +4079,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.6", + "der 0.7.7", "spki 0.7.2", ] @@ -4098,9 +4097,9 @@ checksum = "e3d7ddaed09e0eb771a79ab0fd64609ba0afb0a8366421957936ad14cbd13630" [[package]] name = "plotters" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", @@ -4111,15 +4110,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] @@ -4136,8 +4135,8 @@ dependencies = [ "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.9", - "windows-sys 0.48.0", + "pin-project-lite 0.2.10", + "windows-sys", ] [[package]] @@ -4148,7 +4147,7 @@ checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede" dependencies = [ "cpufeatures", "opaque-debug", - "universal-hash 0.4.1", + "universal-hash 0.4.0", ] [[package]] @@ -4160,14 +4159,14 @@ dependencies = [ "cfg-if 1.0.0", "cpufeatures", "opaque-debug", - "universal-hash 0.4.1", + "universal-hash 0.4.0", ] [[package]] name = "polyval" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6" +checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -4323,11 +4322,11 @@ dependencies = [ "async-std", "bytes", "futures-io", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.21.2", + "rustls 0.21.5", "thiserror", "tokio", "tracing", @@ -4343,7 +4342,7 @@ dependencies = [ "rand 0.8.5", "ring", "rustc-hash", - "rustls 0.21.2", + "rustls 0.21.5", "slab", "thiserror", "tinyvec", @@ -4360,7 +4359,7 @@ dependencies = [ "libc", "socket2 0.5.3", "tracing", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -4492,9 +4491,9 @@ dependencies = [ [[package]] name = "redis" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea8c51b5dc1d8e5fd3350ec8167f464ec0995e79f2e90a075b63371500d557f" +checksum = "ff5d95dd18a4d76650f0c2607ed8ebdbf63baf9cb934e1c233cd220c694db1d7" dependencies = [ "async-trait", "bytes", @@ -4502,7 +4501,7 @@ dependencies = [ "futures-util", "itoa", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "ryu", "tokio", "tokio-util", @@ -4526,8 +4525,8 @@ checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.2", - "regex-syntax 0.7.3", + "regex-automata 0.3.4", + "regex-syntax 0.7.4", ] [[package]] @@ -4541,13 +4540,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" +checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.3", + "regex-syntax 0.7.4", ] [[package]] @@ -4558,9 +4557,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "relay-server-example" @@ -4611,7 +4610,7 @@ dependencies = [ "native-tls", "once_cell", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "serde", "serde_json", "serde_urlencoded", @@ -4682,9 +4681,9 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" dependencies = [ "byteorder", "num-traits", @@ -4808,16 +4807,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags 1.3.2", "errno", "io-lifetimes", "libc", "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -4830,7 +4829,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.3", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -4860,21 +4859,21 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.2" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f" +checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" dependencies = [ "log", "ring", - "rustls-webpki 0.100.1", + "rustls-webpki", "sct 0.7.0", ] [[package]] name = "rustls-native-certs" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -4884,28 +4883,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ "base64 0.21.2", ] [[package]] name = "rustls-webpki" -version = "0.100.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.1" +version = "0.101.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" +checksum = "513722fd73ad80a71f72b61009ea1b584bcfa1483ca93949c8f290298837fa59" dependencies = [ "ring", "untrusted", @@ -4913,9 +4902,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rw-stream-sink" @@ -4929,9 +4918,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "salsa20" @@ -4953,11 +4942,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -4968,9 +4957,9 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" @@ -5025,7 +5014,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.6", + "der 0.7.7", "generic-array", "pkcs8 0.10.2", "subtle", @@ -5034,9 +5023,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -5047,9 +5036,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -5057,9 +5046,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "send_wrapper" @@ -5078,18 +5067,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.175" +version = "1.0.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" +checksum = "60363bdd39a7be0266a520dab25fdc9241d2f987b08a01e01f0ec6d06a981348" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.175" +version = "1.0.178" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" +checksum = "f28482318d6641454cb273da158647922d1be6b5a2fcc6165cd89ebdd7ed576b" dependencies = [ "proc-macro2", "quote", @@ -5098,9 +5087,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.100" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "indexmap 2.0.0", "itoa", @@ -5110,18 +5099,19 @@ dependencies = [ [[package]] name = "serde_path_to_error" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7f05c1d5476066defcdfacce1f52fc3cae3af1d3089727100c02ae92e5abbe0" +checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" dependencies = [ + "itoa", "serde", ] [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", @@ -5209,9 +5199,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" dependencies = [ "libc", "signal-hook-registry", @@ -5238,9 +5228,9 @@ dependencies = [ [[package]] name = "signature" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ "digest 0.10.7", "rand_core 0.6.4", @@ -5293,7 +5283,7 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ccba027ba85743e09d15c03296797cad56395089b832b48b5a5217880f57733" dependencies = [ - "aes-gcm 0.9.4", + "aes-gcm 0.9.2", "blake2", "chacha20poly1305", "curve25519-dalek 4.0.0-rc.1", @@ -5321,7 +5311,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -5362,7 +5352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", - "der 0.7.6", + "der 0.7.7", ] [[package]] @@ -5416,9 +5406,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" @@ -5491,7 +5481,7 @@ dependencies = [ "fastrand 2.0.0", "redox_syscall", "rustix 0.38.4", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -5573,9 +5563,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" dependencies = [ "itoa", "serde", @@ -5591,9 +5581,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" dependencies = [ "time-core", ] @@ -5636,11 +5626,11 @@ dependencies = [ "mio", "num_cpus", "parking_lot", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "signal-hook-registry", "socket2 0.4.9", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -5685,7 +5675,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tokio", "tracing", ] @@ -5699,7 +5689,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tokio", "tower-layer", "tower-service", @@ -5723,7 +5713,7 @@ dependencies = [ "mime", "mime_guess", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tokio", "tokio-util", "tower-layer", @@ -5751,16 +5741,16 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", @@ -5871,9 +5861,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "trybuild" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501dbdbb99861e4ab6b60eb6a7493956a9defb644fd034bc4a5ef27c693c8a3a" +checksum = "a84e0202ea606ba5ebee8507ab2bfbe89b98551ed9b8f0be198109275cff284b" dependencies = [ "basic-toml", "glob", @@ -5938,9 +5928,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -5965,9 +5955,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "universal-hash" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ "generic-array", "subtle", @@ -6018,9 +6008,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.3" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ "getrandom 0.2.10", ] @@ -6033,9 +6023,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d330786735ea358f3bc09eea4caa098569c1c93f342d9aca0514915022fe7e" +checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" [[package]] name = "vcpkg" @@ -6082,11 +6072,10 @@ dependencies = [ [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -6267,7 +6256,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" dependencies = [ - "rustls-webpki 0.101.1", + "rustls-webpki", ] [[package]] @@ -6550,21 +6539,6 @@ dependencies = [ "windows_x86_64_msvc 0.34.0", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -6576,25 +6550,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_gnullvm", "windows_aarch64_msvc 0.48.0", "windows_i686_gnu 0.48.0", "windows_i686_msvc 0.48.0", "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_gnullvm", "windows_x86_64_msvc 0.48.0", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" @@ -6607,12 +6575,6 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" @@ -6625,12 +6587,6 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" @@ -6643,12 +6599,6 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" @@ -6661,24 +6611,12 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" @@ -6691,12 +6629,6 @@ version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -6719,7 +6651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if 1.0.0", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] diff --git a/identity/src/keypair.rs b/identity/src/keypair.rs index d932528277a..ac6edec8936 100644 --- a/identity/src/keypair.rs +++ b/identity/src/keypair.rs @@ -758,10 +758,6 @@ impl From for PublicKey { #[cfg(test)] mod tests { use super::*; - #[cfg(feature = "peerid")] - use crate::PeerId; - use base64::prelude::*; - use std::str::FromStr; #[test] #[cfg(feature = "ed25519")] diff --git a/transports/tls/src/lib.rs b/transports/tls/src/lib.rs index 00a4878856d..1edd83e9807 100644 --- a/transports/tls/src/lib.rs +++ b/transports/tls/src/lib.rs @@ -54,7 +54,7 @@ pub fn make_client_config( .with_custom_certificate_verifier(Arc::new( verifier::Libp2pCertificateVerifier::with_remote_peer_id(remote_peer_id), )) - .with_single_cert(vec![certificate], private_key) + .with_client_auth_cert(vec![certificate], private_key) .expect("Client cert key DER is valid; qed"); crypto.alpn_protocols = vec![P2P_ALPN.to_vec()]; From 55f05aa6c8978070959e6a8a944b570b91cc0ee2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 09:00:23 +0000 Subject: [PATCH 10/44] deps: bump serde from 1.0.178 to 1.0.179 Pull-Request: #4271. --- Cargo.lock | 8 ++++---- misc/keygen/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a0f8ec9c64..9c0b2418b1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5067,18 +5067,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.178" +version = "1.0.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60363bdd39a7be0266a520dab25fdc9241d2f987b08a01e01f0ec6d06a981348" +checksum = "0a5bf42b8d227d4abf38a1ddb08602e229108a517cd4e5bb28f9c7eaafdce5c0" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.178" +version = "1.0.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28482318d6641454cb273da158647922d1be6b5a2fcc6165cd89ebdd7ed576b" +checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c" dependencies = [ "proc-macro2", "quote", diff --git a/misc/keygen/Cargo.toml b/misc/keygen/Cargo.toml index c7f8d080c12..4ad9df487a1 100644 --- a/misc/keygen/Cargo.toml +++ b/misc/keygen/Cargo.toml @@ -12,7 +12,7 @@ publish = false [dependencies] clap = { version = "4.3.12", features = ["derive"] } zeroize = "1" -serde = { version = "1.0.175", features = ["derive"] } +serde = { version = "1.0.179", features = ["derive"] } serde_json = "1.0.100" libp2p-core = { workspace = true } base64 = "0.21.2" From d566f45ae2e8eb83c01b99ac6e31487e1c98b156 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 09:17:09 +0000 Subject: [PATCH 11/44] deps: bump syn from 2.0.27 to 2.0.28 Pull-Request: #4273. --- Cargo.lock | 38 +++++++++++++++++++------------------- swarm-derive/Cargo.toml | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c0b2418b1c..7241436d3c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -490,7 +490,7 @@ checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -921,7 +921,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -1423,7 +1423,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -1806,7 +1806,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -3188,7 +3188,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -3876,7 +3876,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4032,7 +4032,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4221,7 +4221,7 @@ checksum = "70550716265d1ec349c41f70dd4f964b4fd88394efe4405f0c1da679c4799a07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -4761,7 +4761,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.27", + "syn 2.0.28", "walkdir", ] @@ -5082,7 +5082,7 @@ checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -5115,7 +5115,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -5423,9 +5423,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.27" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -5548,7 +5548,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -5641,7 +5641,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -5754,7 +5754,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] [[package]] @@ -6112,7 +6112,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", "wasm-bindgen-shared", ] @@ -6146,7 +6146,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6770,5 +6770,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn 2.0.28", ] diff --git a/swarm-derive/Cargo.toml b/swarm-derive/Cargo.toml index 87c3a2fec4a..3ec7b9efd5d 100644 --- a/swarm-derive/Cargo.toml +++ b/swarm-derive/Cargo.toml @@ -16,7 +16,7 @@ proc-macro = true [dependencies] heck = "0.4" quote = "1.0" -syn = { version = "2.0.27", default-features = false, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] } +syn = { version = "2.0.28", default-features = false, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] } proc-macro-warning = "0.4.0" proc-macro2 = "1.0" From 856d85f9b6d612378123f3669ea5b4260f92d2cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:41:14 +0000 Subject: [PATCH 12/44] deps: bump webpki-roots from 0.24.0 to 0.25.1 Pull-Request: #4272. --- Cargo.lock | 9 +++------ transports/websocket/Cargo.toml | 2 +- transports/websocket/src/tls.rs | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7241436d3c8..fdddd50c952 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3329,7 +3329,7 @@ dependencies = [ "rw-stream-sink", "soketto", "url", - "webpki-roots 0.24.0", + "webpki-roots 0.25.1", ] [[package]] @@ -6252,12 +6252,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" -dependencies = [ - "rustls-webpki", -] +checksum = "c9c6eda1c830a36f361e7721c87fd79ea84293b54f8c48c959f85ec636f0f196" [[package]] name = "webrtc" diff --git a/transports/websocket/Cargo.toml b/transports/websocket/Cargo.toml index 4ae420b6706..3ebeb83bc16 100644 --- a/transports/websocket/Cargo.toml +++ b/transports/websocket/Cargo.toml @@ -22,7 +22,7 @@ quicksink = "0.1" rw-stream-sink = { workspace = true } soketto = "0.7.0" url = "2.1" -webpki-roots = "0.24" +webpki-roots = "0.25" [dev-dependencies] libp2p-tcp = { workspace = true, features = ["async-io"] } diff --git a/transports/websocket/src/tls.rs b/transports/websocket/src/tls.rs index 260031ea850..63379db65cc 100644 --- a/transports/websocket/src/tls.rs +++ b/transports/websocket/src/tls.rs @@ -92,7 +92,7 @@ impl Config { /// Setup the rustls client configuration. fn client_root_store() -> rustls::RootCertStore { let mut client_root_store = rustls::RootCertStore::empty(); - client_root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| { + client_root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.iter().map(|ta| { rustls::OwnedTrustAnchor::from_subject_spki_name_constraints( ta.subject, ta.spki, From 3af3d5d23a891ff868e060ad4c042bed7d37d081 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 31 Jul 2023 13:11:57 +0200 Subject: [PATCH 13/44] chore(quic): prepare v0.9.0-alpha Pull-Request: #4262. --- transports/quic/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transports/quic/CHANGELOG.md b/transports/quic/CHANGELOG.md index 2012a3caf94..11ee1e63394 100644 --- a/transports/quic/CHANGELOG.md +++ b/transports/quic/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.9.0-alpha - unreleased +## 0.9.0-alpha - Use `quinn` instead of `quinn-proto`. See [PR 3454]. From 8ff2cf3a37ffdc425a8582934abeb7867d7753c6 Mon Sep 17 00:00:00 2001 From: Darius Clark Date: Mon, 31 Jul 2023 09:58:20 -0400 Subject: [PATCH 14/44] fix(relay): export `RateLimiter` type The `rate-limiter` module was not made publicly available. This change exports the `RateLimiter` trait defined within that module which allows users to define their own rate limiters. To make common usecases easy, we also provide a set of constructor functions for common rate limiters. Resolves #3741. Pull-Request: #3742. --- protocols/relay/CHANGELOG.md | 4 +++ protocols/relay/src/behaviour.rs | 34 +++++++++++++++++++ protocols/relay/src/behaviour/rate_limiter.rs | 12 +++---- protocols/relay/src/lib.rs | 2 +- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/protocols/relay/CHANGELOG.md b/protocols/relay/CHANGELOG.md index 1f8d57058bd..46e27bc7bf9 100644 --- a/protocols/relay/CHANGELOG.md +++ b/protocols/relay/CHANGELOG.md @@ -1,8 +1,12 @@ ## 0.16.1 - unreleased +- Export `RateLimiter` type. + See [PR 3742]. + - Add functions to access data within `Limit`. See [PR 4162]. +[PR 3742]: https://github.com/libp2p/rust-libp2p/pull/3742 [PR 4162]: https://github.com/libp2p/rust-libp2p/pull/4162 ## 0.16.0 diff --git a/protocols/relay/src/behaviour.rs b/protocols/relay/src/behaviour.rs index eb2f662581f..8fcfa103c4f 100644 --- a/protocols/relay/src/behaviour.rs +++ b/protocols/relay/src/behaviour.rs @@ -61,6 +61,40 @@ pub struct Config { pub circuit_src_rate_limiters: Vec>, } +impl Config { + pub fn reservation_rate_per_peer(mut self, limit: NonZeroU32, interval: Duration) -> Self { + self.reservation_rate_limiters + .push(rate_limiter::new_per_peer( + rate_limiter::GenericRateLimiterConfig { limit, interval }, + )); + self + } + + pub fn circuit_src_per_peer(mut self, limit: NonZeroU32, interval: Duration) -> Self { + self.circuit_src_rate_limiters + .push(rate_limiter::new_per_peer( + rate_limiter::GenericRateLimiterConfig { limit, interval }, + )); + self + } + + pub fn reservation_rate_per_ip(mut self, limit: NonZeroU32, interval: Duration) -> Self { + self.reservation_rate_limiters + .push(rate_limiter::new_per_ip( + rate_limiter::GenericRateLimiterConfig { limit, interval }, + )); + self + } + + pub fn circuit_src_per_ip(mut self, limit: NonZeroU32, interval: Duration) -> Self { + self.circuit_src_rate_limiters + .push(rate_limiter::new_per_ip( + rate_limiter::GenericRateLimiterConfig { limit, interval }, + )); + self + } +} + impl std::fmt::Debug for Config { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Config") diff --git a/protocols/relay/src/behaviour/rate_limiter.rs b/protocols/relay/src/behaviour/rate_limiter.rs index 31223c309f2..a4a127e1253 100644 --- a/protocols/relay/src/behaviour/rate_limiter.rs +++ b/protocols/relay/src/behaviour/rate_limiter.rs @@ -30,10 +30,10 @@ use std::time::Duration; /// Allows rate limiting access to some resource based on the [`PeerId`] and /// [`Multiaddr`] of a remote peer. -/// -/// See [`new_per_peer`] and [`new_per_ip`] for precast implementations. Use -/// [`GenericRateLimiter`] to build your own, e.g. based on the autonomous system -/// number of a peers IP address. +// +// See [`new_per_peer`] and [`new_per_ip`] for precast implementations. Use +// [`GenericRateLimiter`] to build your own, e.g. based on the autonomous system +// number of a peers IP address. pub trait RateLimiter: Send { fn try_next(&mut self, peer: PeerId, addr: &Multiaddr, now: Instant) -> bool; } @@ -80,9 +80,9 @@ pub(crate) struct GenericRateLimiter { /// Configuration for a [`GenericRateLimiter`]. #[derive(Debug, Clone, Copy)] pub(crate) struct GenericRateLimiterConfig { - /// The maximum number of tokens in the bucket at any point in time. + // The maximum number of tokens in the bucket at any point in time. pub(crate) limit: NonZeroU32, - /// The interval at which a single token is added to the bucket. + // The interval at which a single token is added to the bucket. pub(crate) interval: Duration, } diff --git a/protocols/relay/src/lib.rs b/protocols/relay/src/lib.rs index b411c650aeb..39ccd539838 100644 --- a/protocols/relay/src/lib.rs +++ b/protocols/relay/src/lib.rs @@ -39,7 +39,7 @@ mod proto { }; } -pub use behaviour::{Behaviour, CircuitId, Config, Event}; +pub use behaviour::{rate_limiter::RateLimiter, Behaviour, CircuitId, Config, Event}; pub use protocol::{HOP_PROTOCOL_NAME, STOP_PROTOCOL_NAME}; /// Types related to the relay protocol inbound. From 23d7d1a247eb3e5b9a40582f18cdb1a036b51d00 Mon Sep 17 00:00:00 2001 From: arsenron <33022971+arsenron@users.noreply.github.com> Date: Mon, 31 Jul 2023 17:23:45 +0300 Subject: [PATCH 15/44] feat(kad): implement common traits on `RoutingUpdate` A few weeks ago when I was debugging my wrong setup with kademlia, I could not conveniently debug `RoutingUpdate` after adding an address to the DHT. It would be nice to have a few derivable traits on a public enum. Pull-Request: #4270. --- Cargo.lock | 2 +- Cargo.toml | 2 +- protocols/kad/CHANGELOG.md | 9 ++++++++- protocols/kad/Cargo.toml | 2 +- protocols/kad/src/behaviour.rs | 1 + 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fdddd50c952..57bca1723d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2812,7 +2812,7 @@ dependencies = [ [[package]] name = "libp2p-kad" -version = "0.44.3" +version = "0.44.4" dependencies = [ "arrayvec", "async-std", diff --git a/Cargo.toml b/Cargo.toml index fa8c70eb4ea..0a23bc54815 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,7 @@ libp2p-floodsub = { version = "0.43.0", path = "protocols/floodsub" } libp2p-gossipsub = { version = "0.45.0", path = "protocols/gossipsub" } libp2p-identify = { version = "0.43.0", path = "protocols/identify" } libp2p-identity = { version = "0.2.2" } -libp2p-kad = { version = "0.44.3", path = "protocols/kad" } +libp2p-kad = { version = "0.44.4", path = "protocols/kad" } libp2p-mdns = { version = "0.44.0", path = "protocols/mdns" } libp2p-metrics = { version = "0.13.1", path = "misc/metrics" } libp2p-mplex = { version = "0.40.0", path = "muxers/mplex" } diff --git a/protocols/kad/CHANGELOG.md b/protocols/kad/CHANGELOG.md index 5389bda4592..c729e5ea0f9 100644 --- a/protocols/kad/CHANGELOG.md +++ b/protocols/kad/CHANGELOG.md @@ -1,4 +1,11 @@ -## 0.44.3 - unreleased +## 0.44.4 - unreleased + +- Implement common traits on `RoutingUpdate`. + See [PR 4270]. + +[PR 4270]: https://github.com/libp2p/rust-libp2p/pull/4270 + +## 0.44.3 - Prevent simultaneous dials to peers. See [PR 4224]. diff --git a/protocols/kad/Cargo.toml b/protocols/kad/Cargo.toml index 52a5ba4e188..80e8946f871 100644 --- a/protocols/kad/Cargo.toml +++ b/protocols/kad/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-kad" edition = "2021" rust-version = "1.65.0" description = "Kademlia protocol for libp2p" -version = "0.44.3" +version = "0.44.4" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" diff --git a/protocols/kad/src/behaviour.rs b/protocols/kad/src/behaviour.rs index e3651fa2b3d..c0a11a100ec 100644 --- a/protocols/kad/src/behaviour.rs +++ b/protocols/kad/src/behaviour.rs @@ -3289,6 +3289,7 @@ impl fmt::Display for NoKnownPeers { impl std::error::Error for NoKnownPeers {} /// The possible outcomes of [`Kademlia::add_address`]. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum RoutingUpdate { /// The given peer and address has been added to the routing /// table. From d20dec05bed4db7dd7d08ce1e7d6b3c12b384dbc Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Mon, 31 Jul 2023 20:31:43 +0200 Subject: [PATCH 16/44] chore(ci): bump `cargo semver-checks` to `0.22.1` Pull-Request: #4227. --- .github/actions/cargo-semver-checks/action.yml | 2 +- .github/workflows/ci.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/cargo-semver-checks/action.yml b/.github/actions/cargo-semver-checks/action.yml index 79151e6e98c..e9e6844f49c 100644 --- a/.github/actions/cargo-semver-checks/action.yml +++ b/.github/actions/cargo-semver-checks/action.yml @@ -7,7 +7,7 @@ inputs: runs: using: "composite" steps: - - run: wget -q -O- https://github.com/obi1kenobi/cargo-semver-checks/releases/download/v0.20.0/cargo-semver-checks-x86_64-unknown-linux-gnu.tar.gz | tar -xz -C ~/.cargo/bin + - run: wget -q -O- https://github.com/obi1kenobi/cargo-semver-checks/releases/download/v0.22.1/cargo-semver-checks-x86_64-unknown-linux-gnu.tar.gz | tar -xz -C ~/.cargo/bin shell: bash - name: Get released version diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89b756d1d72..14cd04f4299 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,9 +58,9 @@ jobs: echo "code=${RESPONSE_CODE}" >> $GITHUB_OUTPUT - uses: ./.github/actions/cargo-semver-checks - if: steps.check-released.outputs.code == 200 # Workaround until https://github.com/obi1kenobi/cargo-semver-check/issues/146 is shipped. + if: steps.check-released.outputs.code == 200 && !contains(fromJSON('["libp2p-swarm-derive"]'), env.CRATE) # Workaround until https://github.com/obi1kenobi/cargo-semver-check/issues/146 is shipped. with: - crate: env.CRATE + crate: ${{ env.CRATE }} - name: Enforce no dependency on meta crate run: | From c86b665a653626f5eca30c4f8811a2a08c3fbb20 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 31 Jul 2023 22:17:36 +0200 Subject: [PATCH 17/44] chore(roadmap): move QUIC quinn to done Done with https://github.com/libp2p/rust-libp2p/pull/3454. Pull-Request: #4277. --- ROADMAP.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index a148de5794e..fc0ad003f49 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -8,14 +8,6 @@ This is a living document. Input is always welcome e.g. via GitHub issues or pul This is the roadmap of the Rust implementation of libp2p. See also the [general libp2p project roadmap](https://github.com/libp2p/specs/blob/master/ROADMAP.md). -## QUIC - evaluate and move to quinn - -| Category | Status | Target Completion | Tracking | Dependencies | Dependents | -|--------------|--------|-------------------|---------------------------------------------------|--------------|------------| -| Connectivity | todo | Q3/2023 | https://github.com/libp2p/rust-libp2p/issues/2883 | | | - -We added alpha support for QUIC in Q4/2022 wrapping `quinn-proto`. Evaluate using `quinn` directly, replacing the wrapper. - ## Attempt to switch from webrtc-rs to str0m | Category | Status | Target Completion | Tracking | Dependencies | Dependents | @@ -180,3 +172,11 @@ QUIC](https://github.com/libp2p/specs/blob/master/relay/DCUtR.md#the-protocol). Kademlia client mode will enhance routing table health and thus have a positive impact on all Kademlia operations. + +## QUIC - evaluate and move to quinn + +| Category | Status | Target Completion | Tracking | Dependencies | Dependents | +|--------------|--------|-------------------|---------------------------------------------------|--------------|------------| +| Connectivity | done | Q3/2023 | https://github.com/libp2p/rust-libp2p/issues/2883 | | | + +We added alpha support for QUIC in Q4/2022 wrapping `quinn-proto`. Evaluate using `quinn` directly, replacing the wrapper. From fbf35e14cb1b5324e7c815b23532fce427d3ee30 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Tue, 1 Aug 2023 15:53:38 +0200 Subject: [PATCH 18/44] fix(examples/file-sharing): set Kademlia `Mode::Server` Explicitly set `libp2p-kad` `Kademlia::set_mode` to `Mode::Server` to reduce complexity of example, i.e. not having to explicitly set external addresses. Pull-Request: #4197. --- examples/file-sharing/src/network.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/examples/file-sharing/src/network.rs b/examples/file-sharing/src/network.rs index db781a27a93..7ddd0afb0cc 100644 --- a/examples/file-sharing/src/network.rs +++ b/examples/file-sharing/src/network.rs @@ -7,7 +7,8 @@ use libp2p::{ core::Multiaddr, identity, kad::{ - record::store::MemoryStore, GetProvidersOk, Kademlia, KademliaEvent, QueryId, QueryResult, + self, record::store::MemoryStore, GetProvidersOk, Kademlia, KademliaEvent, QueryId, + QueryResult, }, multiaddr::Protocol, noise, @@ -52,7 +53,7 @@ pub(crate) async fn new( // Build the Swarm, connecting the lower layer transport logic with the // higher layer network behaviour logic. - let swarm = SwarmBuilder::with_async_std_executor( + let mut swarm = SwarmBuilder::with_async_std_executor( transport, ComposedBehaviour { kademlia: Kademlia::new(peer_id, MemoryStore::new(peer_id)), @@ -68,6 +69,11 @@ pub(crate) async fn new( ) .build(); + swarm + .behaviour_mut() + .kademlia + .set_mode(Some(kad::Mode::Server)); + let (command_sender, command_receiver) = mpsc::channel(0); let (event_sender, event_receiver) = mpsc::channel(0); From 4d637aedb7e5c23895e3cb1cabadcc8a94d1d307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20S=C3=A9n=C3=A9chal?= <44696378+thomas-senechal@users.noreply.github.com> Date: Wed, 2 Aug 2023 12:43:37 +0200 Subject: [PATCH 19/44] docs: fix last OutboundQueryCompleted in kad doc `OutboundQueryCompleted` hasn't been fully replaced by `OutboundQueryProgressed` in kad doc. Pull-Request: #4257. --- protocols/kad/CHANGELOG.md | 5 +++++ protocols/kad/src/behaviour.rs | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/protocols/kad/CHANGELOG.md b/protocols/kad/CHANGELOG.md index c729e5ea0f9..e3da07294fb 100644 --- a/protocols/kad/CHANGELOG.md +++ b/protocols/kad/CHANGELOG.md @@ -12,6 +12,11 @@ [PR 4224]: https://github.com/libp2p/rust-libp2p/pull/4224 +- Rename missed `KademliaEvent::OutboundQueryCompleted` to `KademliaEvent::OutboundQueryProgressed` in documentation. + See [PR 4257]. + +[PR 4257]: https://github.com/libp2p/rust-libp2p/pull/4257 + ## 0.44.2 - Allow to explicitly set `Mode::{Client,Server}`. diff --git a/protocols/kad/src/behaviour.rs b/protocols/kad/src/behaviour.rs index c0a11a100ec..fa582496a9d 100644 --- a/protocols/kad/src/behaviour.rs +++ b/protocols/kad/src/behaviour.rs @@ -665,7 +665,7 @@ where /// Initiates an iterative query for the closest peers to the given key. /// /// The result of the query is delivered in a - /// [`KademliaEvent::OutboundQueryCompleted{QueryResult::GetClosestPeers}`]. + /// [`KademliaEvent::OutboundQueryProgressed{QueryResult::GetClosestPeers}`]. pub fn get_closest_peers(&mut self, key: K) -> QueryId where K: Into> + Into> + Clone, @@ -692,7 +692,7 @@ where /// Performs a lookup for a record in the DHT. /// /// The result of this operation is delivered in a - /// [`KademliaEvent::OutboundQueryCompleted{QueryResult::GetRecord}`]. + /// [`KademliaEvent::OutboundQueryProgressed{QueryResult::GetRecord}`]. pub fn get_record(&mut self, key: record_priv::Key) -> QueryId { let record = if let Some(record) = self.store.get(&key) { if record.is_expired(Instant::now()) { @@ -753,7 +753,7 @@ where /// Returns `Ok` if a record has been stored locally, providing the /// `QueryId` of the initial query that replicates the record in the DHT. /// The result of the query is eventually reported as a - /// [`KademliaEvent::OutboundQueryCompleted{QueryResult::PutRecord}`]. + /// [`KademliaEvent::OutboundQueryProgressed{QueryResult::PutRecord}`]. /// /// The record is always stored locally with the given expiration. If the record's /// expiration is `None`, the common case, it does not expire in local storage @@ -869,7 +869,7 @@ where /// /// Returns `Ok` if bootstrapping has been initiated with a self-lookup, providing the /// `QueryId` for the entire bootstrapping process. The progress of bootstrapping is - /// reported via [`KademliaEvent::OutboundQueryCompleted{QueryResult::Bootstrap}`] events, + /// reported via [`KademliaEvent::OutboundQueryProgressed{QueryResult::Bootstrap}`] events, /// with one such event per bootstrapping query. /// /// Returns `Err` if bootstrapping is impossible due an empty routing table. @@ -913,7 +913,7 @@ where /// of the libp2p Kademlia provider API. /// /// The results of the (repeated) provider announcements sent by this node are - /// reported via [`KademliaEvent::OutboundQueryCompleted{QueryResult::StartProviding}`]. + /// reported via [`KademliaEvent::OutboundQueryProgressed{QueryResult::StartProviding}`]. pub fn start_providing(&mut self, key: record_priv::Key) -> Result { // Note: We store our own provider records locally without local addresses // to avoid redundant storage and outdated addresses. Instead these are @@ -950,7 +950,7 @@ where /// Performs a lookup for providers of a value to the given key. /// /// The result of this operation is delivered in a - /// reported via [`KademliaEvent::OutboundQueryCompleted{QueryResult::GetProviders}`]. + /// reported via [`KademliaEvent::OutboundQueryProgressed{QueryResult::GetProviders}`]. pub fn get_providers(&mut self, key: record_priv::Key) -> QueryId { let providers: HashSet<_> = self .store From 37d57f41de59b2d978005cc717282a82a6af3f0e Mon Sep 17 00:00:00 2001 From: quininer Date: Wed, 2 Aug 2023 21:46:27 +0800 Subject: [PATCH 20/44] fix(relay): remove unconditional `async-std` dependency `libp2p-relay` crate specifies the `libp2p-swarm/async-std` feature, which causes an `async-std` dependency to always be introduced. Pull-Request: #4283. --- protocols/relay/CHANGELOG.md | 8 ++++++-- protocols/relay/Cargo.toml | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/protocols/relay/CHANGELOG.md b/protocols/relay/CHANGELOG.md index 46e27bc7bf9..c79034c24d4 100644 --- a/protocols/relay/CHANGELOG.md +++ b/protocols/relay/CHANGELOG.md @@ -1,15 +1,19 @@ ## 0.16.1 - unreleased -- Export `RateLimiter` type. +- Export `RateLimiter` type. See [PR 3742]. - Add functions to access data within `Limit`. See [PR 4162]. +- Remove unconditional `async-std` dependency. + See [PR 4283]. + [PR 3742]: https://github.com/libp2p/rust-libp2p/pull/3742 [PR 4162]: https://github.com/libp2p/rust-libp2p/pull/4162 +[PR 4283]: https://github.com/libp2p/rust-libp2p/pull/4283 -## 0.16.0 +## 0.16.0 - Raise MSRV to 1.65. See [PR 3715]. diff --git a/protocols/relay/Cargo.toml b/protocols/relay/Cargo.toml index a749e6f2483..31f6cc16d1e 100644 --- a/protocols/relay/Cargo.toml +++ b/protocols/relay/Cargo.toml @@ -18,7 +18,7 @@ futures = "0.3.28" futures-timer = "3" instant = "0.1.12" libp2p-core = { workspace = true } -libp2p-swarm = { workspace = true, features = ["async-std"] } +libp2p-swarm = { workspace = true } libp2p-identity = { workspace = true } log = "0.4" quick-protobuf = "0.8" @@ -32,7 +32,7 @@ void = "1" env_logger = "0.10.0" libp2p-ping = { workspace = true } libp2p-plaintext = { workspace = true } -libp2p-swarm = { workspace = true, features = ["macros"] } +libp2p-swarm = { workspace = true, features = ["macros", "async-std"] } libp2p-yamux = { workspace = true } quickcheck = { workspace = true } From cb8a92026a75c7547c28b287ea3d6644dc56b352 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 2 Aug 2023 17:02:54 +0200 Subject: [PATCH 21/44] deps(yamux): update yamux to `v0.12` Pull-Request: #3013. --- Cargo.lock | 7 +-- Cargo.toml | 2 +- interop-tests/Cargo.toml | 4 +- interop-tests/src/lib.rs | 10 +++- muxers/yamux/CHANGELOG.md | 8 +++ muxers/yamux/Cargo.toml | 4 +- muxers/yamux/src/lib.rs | 85 +++++++++++------------------- protocols/kad/tests/client_mode.rs | 4 +- 8 files changed, 57 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57bca1723d4..ed333712a62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3354,7 +3354,7 @@ dependencies = [ [[package]] name = "libp2p-yamux" -version = "0.44.0" +version = "0.44.1" dependencies = [ "async-std", "futures", @@ -6729,14 +6729,15 @@ dependencies = [ [[package]] name = "yamux" -version = "0.10.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d9ba232399af1783a58d8eb26f6b5006fbefe2dc9ef36bd283324792d03ea5" +checksum = "0329ef377816896f014435162bb3711ea7a07729c23d0960e6f8048b21b8fe91" dependencies = [ "futures", "log", "nohash-hasher", "parking_lot", + "pin-project", "rand 0.8.5", "static_assertions", ] diff --git a/Cargo.toml b/Cargo.toml index 0a23bc54815..42d4375cb1c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,7 +97,7 @@ libp2p-wasm-ext = { version = "0.40.0", path = "transports/wasm-ext" } libp2p-webrtc = { version = "0.6.0-alpha", path = "transports/webrtc" } libp2p-websocket = { version = "0.42.0", path = "transports/websocket" } libp2p-webtransport-websys = { version = "0.1.0", path = "transports/webtransport-websys" } -libp2p-yamux = { version = "0.44.0", path = "muxers/yamux" } +libp2p-yamux = { version = "0.44.1", path = "muxers/yamux" } multistream-select = { version = "0.13.0", path = "misc/multistream-select" } quick-protobuf-codec = { version = "0.2.0", path = "misc/quick-protobuf-codec" } quickcheck = { package = "quickcheck-ext", path = "misc/quickcheck-ext" } diff --git a/interop-tests/Cargo.toml b/interop-tests/Cargo.toml index a2e281dbb87..2d0d8ea25b7 100644 --- a/interop-tests/Cargo.toml +++ b/interop-tests/Cargo.toml @@ -19,7 +19,7 @@ rand = "0.8.5" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] axum = "0.6" -libp2p = { path = "../libp2p", features = ["ping", "noise", "tls", "rsa", "macros", "websocket", "tokio", "yamux", "tcp", "dns"] } +libp2p = { path = "../libp2p", features = ["ping", "noise", "tls", "rsa", "macros", "websocket", "tokio", "yamux", "tcp", "dns", "identify"] } libp2p-quic = { workspace = true, features = ["tokio"] } libp2p-webrtc = { workspace = true, features = ["tokio"] } libp2p-mplex = { path = "../muxers/mplex" } @@ -34,7 +34,7 @@ tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } [target.'cfg(target_arch = "wasm32")'.dependencies] -libp2p = { path = "../libp2p", features = ["ping", "macros", "webtransport-websys", "wasm-bindgen"] } +libp2p = { path = "../libp2p", features = ["ping", "macros", "webtransport-websys", "wasm-bindgen", "identify"] } wasm-bindgen = { version = "0.2" } wasm-bindgen-futures = { version = "0.4" } wasm-logger = { version = "0.2.0" } diff --git a/interop-tests/src/lib.rs b/interop-tests/src/lib.rs index beb7c91c63d..57ce636367b 100644 --- a/interop-tests/src/lib.rs +++ b/interop-tests/src/lib.rs @@ -4,7 +4,7 @@ use std::time::Duration; use anyhow::{bail, Context, Result}; use futures::{FutureExt, StreamExt}; use libp2p::swarm::{keep_alive, NetworkBehaviour, SwarmEvent}; -use libp2p::{identity, ping, Multiaddr, PeerId}; +use libp2p::{identify, identity, ping, Multiaddr, PeerId}; #[cfg(target_arch = "wasm32")] use wasm_bindgen::prelude::*; @@ -29,12 +29,17 @@ pub async fn run_test( let redis_client = RedisClient::new(redis_addr).context("Could not connect to redis")?; // Build the transport from the passed ENV var. - let (boxed_transport, local_addr) = build_transport(local_key, ip, transport)?; + let (boxed_transport, local_addr) = build_transport(local_key.clone(), ip, transport)?; let mut swarm = swarm_builder( boxed_transport, Behaviour { ping: ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(1))), keep_alive: keep_alive::Behaviour, + // Need to include identify until https://github.com/status-im/nim-libp2p/issues/924 is resolved. + identify: identify::Behaviour::new(identify::Config::new( + "/interop-tests".to_owned(), + local_key.public(), + )), }, local_peer_id, ) @@ -237,6 +242,7 @@ impl FromStr for SecProtocol { struct Behaviour { ping: ping::Behaviour, keep_alive: keep_alive::Behaviour, + identify: identify::Behaviour, } /// Helper function to get a ENV variable into an test parameter like `Transport`. diff --git a/muxers/yamux/CHANGELOG.md b/muxers/yamux/CHANGELOG.md index f0055c3fe4f..caea4e5359e 100644 --- a/muxers/yamux/CHANGELOG.md +++ b/muxers/yamux/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.44.1 - unreleased + +- Update to `yamux` `v0.12` which brings performance improvements and introduces an ACK backlog of 256 inbound streams. + When interacting with other libp2p nodes that are also running this or a newer version, the creation of inbound streams will be backpressured once the ACK backlog is hit. + See [PR 3013]. + +[PR 3013]: https://github.com/libp2p/rust-libp2p/pull/3013 + ## 0.44.0 - Raise MSRV to 1.65. diff --git a/muxers/yamux/Cargo.toml b/muxers/yamux/Cargo.toml index 50a9e97d1d0..11b94ac9738 100644 --- a/muxers/yamux/Cargo.toml +++ b/muxers/yamux/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-yamux" edition = "2021" rust-version = { workspace = true } description = "Yamux multiplexing protocol for libp2p" -version = "0.44.0" +version = "0.44.1" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" @@ -14,7 +14,7 @@ categories = ["network-programming", "asynchronous"] futures = "0.3.28" libp2p-core = { workspace = true } thiserror = "1.0" -yamux = "0.10.0" +yamux = "0.12" log = "0.4" [dev-dependencies] diff --git a/muxers/yamux/src/lib.rs b/muxers/yamux/src/lib.rs index b24c976ebf2..12e5dd8c1ff 100644 --- a/muxers/yamux/src/lib.rs +++ b/muxers/yamux/src/lib.rs @@ -22,14 +22,14 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -use futures::{future, prelude::*, ready, stream::BoxStream}; +use futures::{future, prelude::*, ready}; use libp2p_core::muxing::{StreamMuxer, StreamMuxerEvent}; use libp2p_core::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; use std::collections::VecDeque; use std::io::{IoSlice, IoSliceMut}; use std::task::Waker; use std::{ - fmt, io, iter, mem, + io, iter, pin::Pin, task::{Context, Poll}, }; @@ -37,14 +37,12 @@ use thiserror::Error; use yamux::ConnectionError; /// A Yamux connection. +#[derive(Debug)] pub struct Muxer { - /// The [`futures::stream::Stream`] of incoming substreams. - incoming: BoxStream<'static, Result>, - /// Handle to control the connection. - control: yamux::Control, + connection: yamux::Connection, /// Temporarily buffers inbound streams in case our node is performing backpressure on the remote. /// - /// The only way how yamux can make progress is by driving the stream. However, the + /// The only way how yamux can make progress is by calling [`yamux::Connection::poll_next_inbound`]. However, the /// [`StreamMuxer`] interface is designed to allow a caller to selectively make progress via /// [`StreamMuxer::poll_inbound`] and [`StreamMuxer::poll_outbound`] whilst the more general /// [`StreamMuxer::poll`] is designed to make progress on existing streams etc. @@ -54,17 +52,13 @@ pub struct Muxer { inbound_stream_buffer: VecDeque, /// Waker to be called when new inbound streams are available. inbound_stream_waker: Option, - - _phantom: std::marker::PhantomData, } -const MAX_BUFFERED_INBOUND_STREAMS: usize = 25; - -impl fmt::Debug for Muxer { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("Yamux") - } -} +/// How many streams to buffer before we start resetting them. +/// +/// This is equal to the ACK BACKLOG in `rust-yamux`. +/// Thus, for peers running on a recent version of `rust-libp2p`, we should never need to reset streams because they'll voluntarily stop opening them once they hit the ACK backlog. +const MAX_BUFFERED_INBOUND_STREAMS: usize = 256; impl Muxer where @@ -72,22 +66,17 @@ where { /// Create a new Yamux connection. fn new(io: C, cfg: yamux::Config, mode: yamux::Mode) -> Self { - let conn = yamux::Connection::new(io, cfg, mode); - let ctrl = conn.control(); - - Self { - incoming: yamux::into_stream(conn).err_into().boxed(), - control: ctrl, + Muxer { + connection: yamux::Connection::new(io, cfg, mode), inbound_stream_buffer: VecDeque::default(), inbound_stream_waker: None, - _phantom: Default::default(), } } } impl StreamMuxer for Muxer where - C: AsyncRead + AsyncWrite + Send + Unpin + 'static, + C: AsyncRead + AsyncWrite + Unpin + 'static, { type Substream = Stream; type Error = Error; @@ -112,10 +101,15 @@ where mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - Pin::new(&mut self.control) - .poll_open_stream(cx) - .map_ok(Stream) - .map_err(Error) + let stream = ready!(self.connection.poll_new_outbound(cx).map_err(Error)?); + + Poll::Ready(Ok(Stream(stream))) + } + + fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + ready!(self.connection.poll_close(cx).map_err(Error)?); + + Poll::Ready(Ok(())) } fn poll( @@ -141,23 +135,6 @@ where cx.waker().wake_by_ref(); Poll::Pending } - - fn poll_close(mut self: Pin<&mut Self>, c: &mut Context<'_>) -> Poll> { - if let Poll::Ready(()) = Pin::new(&mut self.control).poll_close(c).map_err(Error)? { - return Poll::Ready(Ok(())); - } - - while let Poll::Ready(maybe_inbound_stream) = - self.incoming.poll_next_unpin(c).map_err(Error)? - { - match maybe_inbound_stream { - Some(inbound_stream) => mem::drop(inbound_stream), - None => return Poll::Ready(Ok(())), - } - } - - Poll::Pending - } } /// A stream produced by the yamux multiplexer. @@ -210,18 +187,16 @@ impl AsyncWrite for Stream { impl Muxer where - C: AsyncRead + AsyncWrite + Send + Unpin + 'static, + C: AsyncRead + AsyncWrite + Unpin + 'static, { fn poll_inner(&mut self, cx: &mut Context<'_>) -> Poll> { - self.incoming.poll_next_unpin(cx).map(|maybe_stream| { - let stream = maybe_stream - .transpose() - .map_err(Error)? - .map(Stream) - .ok_or(Error(ConnectionError::Closed))?; - - Ok(stream) - }) + let stream = ready!(self.connection.poll_next_inbound(cx)) + .transpose() + .map_err(Error)? + .map(Stream) + .ok_or(Error(ConnectionError::Closed))?; + + Poll::Ready(Ok(stream)) } } diff --git a/protocols/kad/tests/client_mode.rs b/protocols/kad/tests/client_mode.rs index b2530569518..30fd4d972a8 100644 --- a/protocols/kad/tests/client_mode.rs +++ b/protocols/kad/tests/client_mode.rs @@ -59,11 +59,11 @@ async fn two_servers_add_each_other_to_routing_table() { match libp2p_swarm_test::drive(&mut server2, &mut server1).await { ( - [Identify(_), Kad(UnroutablePeer { .. }), Identify(_), Kad(RoutingUpdated { peer: peer2, .. }), Identify(_)], + [Identify(_), Kad(RoutingUpdated { peer: peer2, .. }), Identify(_)], [Identify(_), Identify(_)], ) | ( - [Identify(_), Kad(UnroutablePeer { .. }), Identify(_), Identify(_), Kad(RoutingUpdated { peer: peer2, .. })], + [Identify(_), Identify(_), Kad(RoutingUpdated { peer: peer2, .. })], [Identify(_), Identify(_)], ) => { assert_eq!(peer2, server1_peer_id); From 4b9c1e5e485729a60cbdba0969ef221ba0d6f575 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Aug 2023 09:22:47 +0000 Subject: [PATCH 22/44] deps: bump Swatinem/rust-cache from 2.5.1 to 2.6.0 Pull-Request: #4288. --- .github/workflows/cache-factory.yml | 2 +- .github/workflows/ci.yml | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/cache-factory.yml b/.github/workflows/cache-factory.yml index 56c42416005..8d25eb9acab 100644 --- a/.github/workflows/cache-factory.yml +++ b/.github/workflows/cache-factory.yml @@ -22,7 +22,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: shared-key: stable-cache diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14cd04f4299..c61e673b855 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: shared-key: stable-cache save-if: false @@ -136,7 +136,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: key: ${{ matrix.target }} save-if: ${{ github.ref == 'refs/heads/master' }} @@ -161,7 +161,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: save-if: ${{ github.ref == 'refs/heads/master' }} @@ -182,7 +182,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: key: ${{ matrix.features }} save-if: ${{ github.ref == 'refs/heads/master' }} @@ -199,7 +199,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: save-if: ${{ github.ref == 'refs/heads/master' }} @@ -225,7 +225,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: save-if: ${{ github.ref == 'refs/heads/master' }} @@ -242,7 +242,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: save-if: ${{ github.ref == 'refs/heads/master' }} @@ -258,7 +258,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: shared-key: stable-cache save-if: false @@ -326,7 +326,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 - run: cargo install --version 0.10.0 pb-rs --locked @@ -352,5 +352,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: Swatinem/rust-cache@dd05243424bd5c0e585e4b55eb2d7615cdd32f1f # v2.5.1 + - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 - run: cargo metadata --locked --format-version=1 > /dev/null From f95f39f634d08dad8df72d7ecf92312f9ad2d826 Mon Sep 17 00:00:00 2001 From: Akihito Nakano Date: Fri, 4 Aug 2023 00:19:25 +0900 Subject: [PATCH 23/44] feat(gossipsub): add getter function to obtain `TopicScoreParams` Added a getter function to obtain `TopicScoreParams`. I need this function for testing which checks if scoring parameters are updated as expected. Pull-Request: #4231. --- Cargo.lock | 2 +- Cargo.toml | 2 +- protocols/gossipsub/CHANGELOG.md | 9 ++++++++- protocols/gossipsub/Cargo.toml | 2 +- protocols/gossipsub/src/behaviour.rs | 5 +++++ protocols/gossipsub/src/peer_score.rs | 5 +++++ 6 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed333712a62..a311e0d1cbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2723,7 +2723,7 @@ dependencies = [ [[package]] name = "libp2p-gossipsub" -version = "0.45.0" +version = "0.45.1" dependencies = [ "async-std", "asynchronous-codec", diff --git a/Cargo.toml b/Cargo.toml index 42d4375cb1c..cf73ebc0056 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,7 +70,7 @@ libp2p-dcutr = { version = "0.10.0", path = "protocols/dcutr" } libp2p-deflate = { version = "0.40.0", path = "transports/deflate" } libp2p-dns = { version = "0.40.0", path = "transports/dns" } libp2p-floodsub = { version = "0.43.0", path = "protocols/floodsub" } -libp2p-gossipsub = { version = "0.45.0", path = "protocols/gossipsub" } +libp2p-gossipsub = { version = "0.45.1", path = "protocols/gossipsub" } libp2p-identify = { version = "0.43.0", path = "protocols/identify" } libp2p-identity = { version = "0.2.2" } libp2p-kad = { version = "0.44.4", path = "protocols/kad" } diff --git a/protocols/gossipsub/CHANGELOG.md b/protocols/gossipsub/CHANGELOG.md index cdcb2ea4105..ab483bdd8a1 100644 --- a/protocols/gossipsub/CHANGELOG.md +++ b/protocols/gossipsub/CHANGELOG.md @@ -1,4 +1,11 @@ -## 0.45.0 +## 0.45.1 - unreleased + +- Add getter function to obtain `TopicScoreParams`. + See [PR 4231]. + +[PR 4231]: https://github.com/libp2p/rust-libp2p/pull/4231 + +## 0.45.0 - Raise MSRV to 1.65. See [PR 3715]. diff --git a/protocols/gossipsub/Cargo.toml b/protocols/gossipsub/Cargo.toml index 4351a735e00..9989a0fae3e 100644 --- a/protocols/gossipsub/Cargo.toml +++ b/protocols/gossipsub/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-gossipsub" edition = "2021" rust-version = { workspace = true } description = "Gossipsub protocol for libp2p" -version = "0.45.0" +version = "0.45.1" authors = ["Age Manning "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" diff --git a/protocols/gossipsub/src/behaviour.rs b/protocols/gossipsub/src/behaviour.rs index db4ee58864f..7ca9f6df9da 100644 --- a/protocols/gossipsub/src/behaviour.rs +++ b/protocols/gossipsub/src/behaviour.rs @@ -930,6 +930,11 @@ where } } + /// Returns a scoring parameters for a topic if existent. + pub fn get_topic_params(&self, topic: &Topic) -> Option<&TopicScoreParams> { + self.peer_score.as_ref()?.0.get_topic_params(&topic.hash()) + } + /// Sets the application specific score for a peer. Returns true if scoring is active and /// the peer is connected or if the score of the peer is not yet expired, false otherwise. pub fn set_application_score(&mut self, peer_id: &PeerId, new_score: f64) -> bool { diff --git a/protocols/gossipsub/src/peer_score.rs b/protocols/gossipsub/src/peer_score.rs index 83f5a68eca1..ab92d536aba 100644 --- a/protocols/gossipsub/src/peer_score.rs +++ b/protocols/gossipsub/src/peer_score.rs @@ -780,6 +780,11 @@ impl PeerScore { } } + /// Returns a scoring parameters for a topic if existent. + pub(crate) fn get_topic_params(&self, topic_hash: &TopicHash) -> Option<&TopicScoreParams> { + self.params.topics.get(topic_hash) + } + /// Increments the "invalid message deliveries" counter for all scored topics the message /// is published in. fn mark_invalid_message_delivery(&mut self, peer_id: &PeerId, topic_hash: &TopicHash) { From 127816160358b5f5a8603f666f5da6eeae3472ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 08:35:57 +0000 Subject: [PATCH 24/44] deps: bump regex from 1.9.1 to 1.9.3 Pull-Request: #4295. --- Cargo.lock | 10 +++++----- protocols/gossipsub/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a311e0d1cbc..69ededfd8a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4519,13 +4519,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.4", + "regex-automata 0.3.6", "regex-syntax 0.7.4", ] @@ -4540,9 +4540,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", diff --git a/protocols/gossipsub/Cargo.toml b/protocols/gossipsub/Cargo.toml index 9989a0fae3e..a9cf8b2a2fe 100644 --- a/protocols/gossipsub/Cargo.toml +++ b/protocols/gossipsub/Cargo.toml @@ -32,7 +32,7 @@ log = "0.4.19" quick-protobuf = "0.8" quick-protobuf-codec = { workspace = true } rand = "0.8" -regex = "1.9.1" +regex = "1.9.3" serde = { version = "1", optional = true, features = ["derive"] } sha2 = "0.10.7" smallvec = "1.11.0" From 72fd50ae6c81e8278a273be373c706c437364008 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 09:14:58 +0000 Subject: [PATCH 25/44] deps: bump serde from 1.0.179 to 1.0.183 Pull-Request: #4294. --- Cargo.lock | 8 ++++---- misc/keygen/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69ededfd8a1..513ead5585e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5067,18 +5067,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.179" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5bf42b8d227d4abf38a1ddb08602e229108a517cd4e5bb28f9c7eaafdce5c0" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.179" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "741e124f5485c7e60c03b043f79f320bff3527f4bbf12cf3831750dc46a0ec2c" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", diff --git a/misc/keygen/Cargo.toml b/misc/keygen/Cargo.toml index 4ad9df487a1..49eee550319 100644 --- a/misc/keygen/Cargo.toml +++ b/misc/keygen/Cargo.toml @@ -12,7 +12,7 @@ publish = false [dependencies] clap = { version = "4.3.12", features = ["derive"] } zeroize = "1" -serde = { version = "1.0.179", features = ["derive"] } +serde = { version = "1.0.183", features = ["derive"] } serde_json = "1.0.100" libp2p-core = { workspace = true } base64 = "0.21.2" From e65155281e0acf62034775cb2238f092ec40df50 Mon Sep 17 00:00:00 2001 From: shamil-gadelshin Date: Mon, 7 Aug 2023 16:31:15 +0700 Subject: [PATCH 26/44] fix(kad): reduce noise of "remote supports our protocol" log This PR changes the logging of the Kademlia connection handler related to the remote Kademlia mode changes: - Downgrade log level for the remote kademlia protocol report from `info` to `debug`. - Introduce connection_id for the handler to improve logging. Pull-Request: #4278. --- Cargo.lock | 2 +- Cargo.toml | 2 +- protocols/kad/CHANGELOG.md | 3 +++ protocols/kad/src/behaviour.rs | 2 ++ protocols/kad/src/handler.rs | 21 ++++++++++++++------- swarm/CHANGELOG.md | 7 +++++++ swarm/Cargo.toml | 2 +- swarm/src/connection.rs | 7 +++++++ 8 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 513ead5585e..57f2d456f33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3149,7 +3149,7 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.43.2" +version = "0.43.3" dependencies = [ "async-std", "either", diff --git a/Cargo.toml b/Cargo.toml index cf73ebc0056..702a847b0c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,7 +87,7 @@ libp2p-quic = { version = "0.9.0-alpha", path = "transports/quic" } libp2p-relay = { version = "0.16.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" } -libp2p-swarm = { version = "0.43.2", path = "swarm" } +libp2p-swarm = { version = "0.43.3", path = "swarm" } libp2p-swarm-derive = { version = "0.33.0", path = "swarm-derive" } libp2p-swarm-test = { version = "0.2.0", path = "swarm-test" } libp2p-tcp = { version = "0.40.0", path = "transports/tcp" } diff --git a/protocols/kad/CHANGELOG.md b/protocols/kad/CHANGELOG.md index e3da07294fb..cd87a6448d0 100644 --- a/protocols/kad/CHANGELOG.md +++ b/protocols/kad/CHANGELOG.md @@ -2,8 +2,11 @@ - Implement common traits on `RoutingUpdate`. See [PR 4270]. +- Reduce noise of "remote supports our protocol" log. + See [PR 4278]. [PR 4270]: https://github.com/libp2p/rust-libp2p/pull/4270 +[PR 4278]: https://github.com/libp2p/rust-libp2p/pull/4278 ## 0.44.3 diff --git a/protocols/kad/src/behaviour.rs b/protocols/kad/src/behaviour.rs index fa582496a9d..340fefb276a 100644 --- a/protocols/kad/src/behaviour.rs +++ b/protocols/kad/src/behaviour.rs @@ -2081,6 +2081,7 @@ where connected_point, peer, self.mode, + connection_id, )) } @@ -2103,6 +2104,7 @@ where connected_point, peer, self.mode, + connection_id, )) } diff --git a/protocols/kad/src/handler.rs b/protocols/kad/src/handler.rs index 948f14f30eb..d695420ec2b 100644 --- a/protocols/kad/src/handler.rs +++ b/protocols/kad/src/handler.rs @@ -35,7 +35,7 @@ use libp2p_swarm::handler::{ ConnectionEvent, DialUpgradeError, FullyNegotiatedInbound, FullyNegotiatedOutbound, }; use libp2p_swarm::{ - ConnectionHandler, ConnectionHandlerEvent, KeepAlive, Stream, StreamUpgradeError, + ConnectionHandler, ConnectionHandlerEvent, ConnectionId, KeepAlive, Stream, StreamUpgradeError, SubstreamProtocol, SupportedProtocols, }; use log::trace; @@ -94,6 +94,9 @@ pub struct KademliaHandler { protocol_status: ProtocolStatus, remote_supported_protocols: SupportedProtocols, + + /// The ID of this connection. + connection_id: ConnectionId, } /// The states of protocol confirmation that a connection @@ -474,6 +477,7 @@ impl KademliaHandler { endpoint: ConnectedPoint, remote_peer_id: PeerId, mode: Mode, + connection_id: ConnectionId, ) -> Self { match &endpoint { ConnectedPoint::Dialer { .. } => { @@ -504,6 +508,7 @@ impl KademliaHandler { keep_alive, protocol_status: ProtocolStatus::Unknown, remote_supported_protocols: Default::default(), + connection_id, } } @@ -803,17 +808,19 @@ impl ConnectionHandler for KademliaHandler { match (remote_supports_our_kademlia_protocols, self.protocol_status) { (true, ProtocolStatus::Confirmed | ProtocolStatus::Reported) => {} (true, _) => { - log::info!( - "Remote {} now supports our kademlia protocol", - self.remote_peer_id + log::debug!( + "Remote {} now supports our kademlia protocol on connection {}", + self.remote_peer_id, + self.connection_id, ); self.protocol_status = ProtocolStatus::Confirmed; } (false, ProtocolStatus::Confirmed | ProtocolStatus::Reported) => { - log::info!( - "Remote {} no longer supports our kademlia protocol", - self.remote_peer_id + log::debug!( + "Remote {} no longer supports our kademlia protocol on connection {}", + self.remote_peer_id, + self.connection_id, ); self.protocol_status = ProtocolStatus::NotSupported; diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 1d4108ac92c..6a9808dd554 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.43.3 - unreleased + +- Implement `Display` for `ConnectionId`. + See [PR 4278]. + +[PR 4278]: https://github.com/libp2p/rust-libp2p/pull/4278 + ## 0.43.2 - Display the cause of a `ListenError::Denied`. See [PR 4232] diff --git a/swarm/Cargo.toml b/swarm/Cargo.toml index 752491cda7e..37d16d31497 100644 --- a/swarm/Cargo.toml +++ b/swarm/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-swarm" edition = "2021" rust-version = { workspace = true } description = "The libp2p swarm" -version = "0.43.2" +version = "0.43.3" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" diff --git a/swarm/src/connection.rs b/swarm/src/connection.rs index 6646967f590..3796d9a027d 100644 --- a/swarm/src/connection.rs +++ b/swarm/src/connection.rs @@ -53,6 +53,7 @@ use libp2p_core::upgrade::{NegotiationError, ProtocolError}; use libp2p_core::Endpoint; use libp2p_identity::PeerId; use std::collections::HashSet; +use std::fmt::{Display, Formatter}; use std::future::Future; use std::sync::atomic::{AtomicUsize, Ordering}; use std::task::Waker; @@ -82,6 +83,12 @@ impl ConnectionId { } } +impl Display for ConnectionId { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + /// Information about a successfully established connection. #[derive(Debug, Clone, PartialEq, Eq)] pub(crate) struct Connected { From 925243243c2398beebced569f8849737ae8fe526 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:31:38 +0000 Subject: [PATCH 27/44] deps: bump axum from 0.6.19 to 0.6.20 Pull-Request: #4301. --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57f2d456f33..b4b7adfcbf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -531,9 +531,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.6.19" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a1de45611fdb535bfde7b7de4fd54f4fd2b17b1737c0a59b69bf9b92074b8c" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", From 6478fafc70edfd9857daaacb9d8086f41a392d89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:47:47 +0000 Subject: [PATCH 28/44] deps: bump x509-parser from 0.15.0 to 0.15.1 Pull-Request: #4297. --- Cargo.lock | 6 +++--- transports/tls/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4b7adfcbf3..547efe4391a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3244,7 +3244,7 @@ dependencies = [ "thiserror", "tokio", "webpki 0.22.0", - "x509-parser 0.15.0", + "x509-parser 0.15.1", "yasna", ] @@ -6712,9 +6712,9 @@ dependencies = [ [[package]] name = "x509-parser" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab0c2f54ae1d92f4fcb99c0b7ccf0b1e3451cbd395e5f115ccbdbcb18d4f634" +checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" dependencies = [ "asn1-rs 0.5.2", "data-encoding", diff --git a/transports/tls/Cargo.toml b/transports/tls/Cargo.toml index 351fc7037f6..5275a9c07a6 100644 --- a/transports/tls/Cargo.toml +++ b/transports/tls/Cargo.toml @@ -17,7 +17,7 @@ rcgen = "0.10.0" ring = "0.16.20" thiserror = "1.0.44" webpki = { version = "0.22.0", features = ["std"] } -x509-parser = "0.15.0" +x509-parser = "0.15.1" yasna = "0.5.2" # Exposed dependencies. Breaking changes to these are breaking changes to us. From 8937105e07647dbd351f7a66601083e81fb10b22 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 7 Aug 2023 15:19:08 +0200 Subject: [PATCH 29/44] docs(roadmap): fix headings, update str0m, webtransport, autonatv2 & address pipeline Pull-Request: #4292. --- ROADMAP.md | 148 ++++++++++++++++++++++++++--------------------------- 1 file changed, 72 insertions(+), 76 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index fc0ad003f49..6758bf5a345 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,96 +1,93 @@ # rust-libp2p Roadmap -Below is a high level roadmap for the rust-libp2p project. Items are ordered by priority (high to -low). +Below is a high level roadmap for the rust-libp2p project. +Items are ordered by priority (high to low). -This is a living document. Input is always welcome e.g. via GitHub issues or pull requests. +This is a living document. +Input is always welcome e.g. via GitHub issues or pull requests. -This is the roadmap of the Rust implementation of libp2p. See also the [general libp2p project -roadmap](https://github.com/libp2p/specs/blob/master/ROADMAP.md). +This is the roadmap of the Rust implementation of libp2p. +See also the [general libp2p project roadmap](https://github.com/libp2p/specs/blob/master/ROADMAP.md). -## Attempt to switch from webrtc-rs to str0m +## In the works -| Category | Status | Target Completion | Tracking | Dependencies | Dependents | -|--------------|--------|-------------------|---------------------------------------------------|--------------|------------| -| Connectivity | todo | | https://github.com/libp2p/rust-libp2p/issues/3659 | | | +### WebTransport -Reduce maintenance burden and reduce dependency footprint. - -## Address pipeline - -| Category | Status | Target Completion | Tracking | Dependencies | Dependents | -|--------------|--------|-------------------|----------|--------------|------------| -| Connectivity | todo | Q4/2023 | | AutoNATv2 | AutoNATv2 | +| Category | Status | Target Completion | Tracking | Dependencies | Dependents | +|-----------------------------|--------|-------------------|---------------------------------------------------|------------------------------------|------------| +| Connectivity / optimization | todo | | https://github.com/libp2p/rust-libp2p/issues/2993 | [QUIC](#experimental-quic-support) | | -Be smart on address prioritization. go-libp2p made a lot of progress here. Lots to learn. See https://github.com/libp2p/go-libp2p/issues/2229 and https://github.com/libp2p/rust-libp2p/issues/1896#issuecomment-1537774383. +A WebTransport implementation in rust-libp2p will enable browsers to connect to rust-libp2p server nodes where the latter only have a self-signed TLS certificate. +Compared to WebRTC, this would likely be more stable and performant. -## AutoNATv2 +### AutoNATv2 | Category | Status | Target Completion | Tracking | Dependencies | Dependents | |--------------|--------|-------------------|----------|------------------|------------------| | Connectivity | todo | Q4/2023 | | Address pipeline | Address pipeline | -Implement the new AutoNAT v2 specification. See https://github.com/libp2p/specs/pull/538. +Implement the new AutoNAT v2 specification. +See https://github.com/libp2p/specs/pull/538. -## Optimize Hole punching +### Address pipeline + +| Category | Status | Target Completion | Tracking | Dependencies | Dependents | +|--------------|--------|-------------------|----------|--------------|------------| +| Connectivity | todo | Q4/2023 | | AutoNATv2 | AutoNATv2 | + +Be smart on address prioritization. +go-libp2p made a lot of progress here. +Lots to learn. +See https://github.com/libp2p/go-libp2p/issues/2229 and https://github.com/libp2p/rust-libp2p/issues/1896#issuecomment-1537774383. + +### Optimize Hole punching | Category | Status | Target Completion | Tracking | Dependencies | Dependents | |--------------|--------|-------------------|----------|--------------|------------| | Optimization | todo | | | | | -We released hole punching support with [rust-libp2p -`v0.43.0`](https://github.com/libp2p/rust-libp2p/releases/tag/v0.43.0), see also -https://github.com/libp2p/rust-libp2p/issues/2052. We are currently collecting data via the -[punchr](https://github.com/dennis-tra/punchr) project on the hole punching success rate. See also -[call for -action](https://discuss.libp2p.io/t/decentralized-nat-hole-punching-measurement-campaign/1616) in -case you want to help. Based on this data we will likely find many optimizations we can do to our -hole punching stack. +We released hole punching support with [rust-libp2p `v0.43.0`](https://github.com/libp2p/rust-libp2p/releases/tag/v0.43.0), see also https://github.com/libp2p/rust-libp2p/issues/2052. +We are currently collecting data via the [punchr](https://github.com/dennis-tra/punchr) project on the hole punching success rate. +See also [call for action](https://discuss.libp2p.io/t/decentralized-nat-hole-punching-measurement-campaign/1616) in case you want to help. +Based on this data we will likely find many optimizations we can do to our hole punching stack. -## Improved Wasm support +### Improved Wasm support | Category | Status | Target Completion | Tracking | Dependencies | Dependents | |----------------------|--------|-------------------|---------------------------------------------------|--------------|----------------------------------------------| | Developer ergonomics | todo | | https://github.com/libp2p/rust-libp2p/issues/2617 | | [WebRTC](#webrtc-support-browser-to-browser) | The project supports Wasm already today, though the developer experience is cumbersome at best. -Properly supporting Wasm opens rust-libp2p to a whole new set of use-cases. I would love for this to -happen earlier. Though (a) I think we should prioritize improving existing functionality over new -functionality and (b) we don't have high demand for this feature from the community. (One could -argue that that demand follows this roadmap item and not the other way round.) +Properly supporting Wasm opens rust-libp2p to a whole new set of use-cases. +I would love for this to happen earlier. +Though (a) I think we should prioritize improving existing functionality over new functionality and (b) we don't have high demand for this feature from the community. +(One could argue that that demand follows this roadmap item and not the other way round.) -## WebRTC in the browser via WASM +### WebRTC in the browser via WASM | Category | Status | Target Completion | Tracking | Dependencies | Dependents | |--------------|--------|-------------------|--------------------------------------------|-------------------------------------------------------------------------------------------|------------| | Connectivity | todo | | https://github.com/libp2p/specs/issues/475 | [Improved WASM support](#improved-wasm-support), https://github.com/libp2p/specs/pull/497 | | -Use the browser's WebRTC stack to support -[`/webrtc`](https://github.com/libp2p/specs/blob/master/webrtc/webrtc.md) and -[`/webrtc-direct`](https://github.com/libp2p/specs/blob/master/webrtc/webrtc-direct.md) from within -the browser using rust-libp2p compiled to WASM. This makes rust-libp2p a truly end-to-end solution, -enabling users to use rust-libp2p on both the client (browser) and server side. +Use the browser's WebRTC stack to support [`/webrtc`](https://github.com/libp2p/specs/blob/master/webrtc/webrtc.md) and [`/webrtc-direct`](https://github.com/libp2p/specs/blob/master/webrtc/webrtc-direct.md) from within the browser using rust-libp2p compiled to WASM. +This makes rust-libp2p a truly end-to-end solution, enabling users to use rust-libp2p on both the client (browser) and server side. -## WebTransport +### Attempt to switch from webrtc-rs to str0m -| Category | Status | Target Completion | Tracking | Dependencies | Dependents | -|-----------------------------|--------|-------------------|---------------------------------------------------|------------------------------------|------------| -| Connectivity / optimization | todo | | https://github.com/libp2p/rust-libp2p/issues/2993 | [QUIC](#experimental-quic-support) | | +| Category | Status | Target Completion | Tracking | Dependencies | Dependents | +|--------------|--------|-------------------|---------------------------------------------------|--------------|------------| +| Connectivity | todo | | https://github.com/libp2p/rust-libp2p/issues/3659 | | | -A WebTransport implementation in rust-libp2p will enable browsers to connect to rust-libp2p nodes -where the latter only have a self-signed TLS certificate. Compared to WebRTC, this would likely be -more performant. It is dependent on QUIC support in rust-libp2p. Given that we will support WebRTC -(browser-to-server) this is not a high priority. +Reduce maintenance burden and reduce dependency footprint. -## Automate port-forwarding e.g. via UPnP +### Automate port-forwarding e.g. via UPnP | Category | Status | Target Completion | Tracking | Dependencies | Dependents | |--------------|--------|-------------------|---------------------------------------------------|--------------|------------| | Connectivity | todo | | https://github.com/libp2p/rust-libp2p/issues/3903 | | | -Leverage protocols like UPnP to configure port-forwarding on ones router when behind NAT and/or -firewall. Another technique in addition to hole punching increasing the probability for a node to -become publicly reachable when behind a firewall and/or NAT. +Leverage protocols like UPnP to configure port-forwarding on ones router when behind NAT and/or firewall. +Another technique in addition to hole punching increasing the probability for a node to become publicly reachable when behind a firewall and/or NAT. ## Done @@ -100,9 +97,9 @@ become publicly reachable when behind a firewall and/or NAT. |--------------|--------|-------------------|---------------------------------------------------|------------------------------------------------|------------| | Connectivity | Done | Q4/2022 | https://github.com/libp2p/rust-libp2p/issues/2883 | https://github.com/libp2p/test-plans/issues/53 | | -QUIC has been on the roadmap for a long time. It enables various performance improvements as well as -higher hole punching success rates. We are close to finishing a first version with -https://github.com/libp2p/rust-libp2p/pull/2289. +QUIC has been on the roadmap for a long time. +It enables various performance improvements as well as higher hole punching success rates. +We are close to finishing a first version with https://github.com/libp2p/rust-libp2p/pull/2289. ### WebRTC support (browser-to-server) @@ -110,13 +107,13 @@ https://github.com/libp2p/rust-libp2p/pull/2289. |--------------|--------|-------------------|------------------------------------------|-----------------------------------------------|-------------------------------------------------------------------| | Connectivity | Done | Q4/2022 | https://github.com/libp2p/specs/pull/412 | https://github.com/libp2p/test-plans/pull/100 | [WebRTC (browser-to-browser)](#webrtc-support-browser-to-browser) | -We are currently implementing WebRTC for **browser-to-server** connectivity in -https://github.com/libp2p/rust-libp2p/pull/2622. More specifically the server side. This will enable -browser nodes to connect to rust-libp2p nodes where the latter only have self-signed TLS -certificates. See https://github.com/libp2p/specs/pull/412 for in-depth motivation. +We are currently implementing WebRTC for **browser-to-server** connectivity in https://github.com/libp2p/rust-libp2p/pull/2622. +More specifically the server side. +This will enable browser nodes to connect to rust-libp2p nodes where the latter only have self-signed TLS certificates. +See https://github.com/libp2p/specs/pull/412 for in-depth motivation. -Long term we should enable rust-libp2p running in the browser via Wasm to use the browser's WebRTC -stack. Though that should only happen after improved Wasm support, see below. +Long term we should enable rust-libp2p running in the browser via Wasm to use the browser's WebRTC stack. +Though that should only happen after improved Wasm support, see below. ### Kademlia efficient querying @@ -124,8 +121,8 @@ stack. Though that should only happen after improved Wasm support, see below. |--------------|-------------|-------------------|-------------------------------------------------|--------------|------------| | Optimization | done | Q1/2023 | https://github.com/libp2p/rust-libp2p/pull/2712 | | | -Users of rust-libp2p like [iroh](https://github.com/n0-computer/iroh) need this for low latency -usage of `libp2p-kad`. The rust-libp2p maintainers can pick this up unless iroh folks finish the +Users of rust-libp2p like [iroh](https://github.com/n0-computer/iroh) need this for low latency usage of `libp2p-kad`. +The rust-libp2p maintainers can pick this up unless iroh folks finish the work before that. ### Generic connection management @@ -134,9 +131,10 @@ work before that. |----------------------|--------|-------------------|---------------------------------------------------|--------------|------------| | Developer Ergonomics | done | Q1/2023 | https://github.com/libp2p/rust-libp2p/issues/2824 | | | -Today connection management functionality in rust-libp2p is limited. Building abstractions on top is -cumbersome and inefficient. See https://github.com/libp2p/rust-libp2p/issues/2824. Making connection -management generic allows users to build advanced and efficient abstractions on top of rust-libp2p. +Today connection management functionality in rust-libp2p is limited. +Building abstractions on top is cumbersome and inefficient. +See https://github.com/libp2p/rust-libp2p/issues/2824. +Making connection management generic allows users to build advanced and efficient abstractions on top of rust-libp2p. ### Cross Behaviour communication @@ -144,16 +142,13 @@ management generic allows users to build advanced and efficient abstractions on |----------------------|--------|-------------------|---------------------------------------------------|---------------------------------------------------|-----------------------------------------------| | Developer ergonomics | Done | Q1/2023 | https://github.com/libp2p/rust-libp2p/issues/2680 | https://github.com/libp2p/rust-libp2p/issues/2832 | [Kademlia client mode](#kademlia-client-mode) | -Today `NetworkBehaviour` implementations like Kademlia, GossipSub or Circuit Relay v2 can not -communicate with each other, i.e. cannot make use of information known by another -`NetworkBehaviour` implementation. Users need to write the wiring code by hand to e.g. enable -Kademlia to learn protocols supported by a remote peer from Identify. +Today `NetworkBehaviour` implementations like Kademlia, GossipSub or Circuit Relay v2 can not communicate with each other, i.e. cannot make use of information known by another `NetworkBehaviour` implementation. +Users need to write the wiring code by hand to e.g. enable Kademlia to learn protocols supported by a remote peer from Identify. -This roadmap item contains exchanging standard information about remote peers (e.g. supported -protocols) between `NetworkBehaviour` implementations. +This roadmap item contains exchanging standard information about remote peers (e.g. supported protocols) between `NetworkBehaviour` implementations. -Long term we might consider a generic approach for `NetworkBehaviours` to exchange data. Though that -would deserve its own roadmap item. +Long term we might consider a generic approach for `NetworkBehaviours` to exchange data. +Though that would deserve its own roadmap item. ## QUIC - implement hole punching @@ -161,8 +156,8 @@ would deserve its own roadmap item. |--------------|--------|-------------------|---------------------------------------------------|--------------|------------| | Connectivity | done | Q3/2023 | https://github.com/libp2p/rust-libp2p/issues/2883 | | | -Add hole punching support for QUIC. See also [DCUtR specification on usage with -QUIC](https://github.com/libp2p/specs/blob/master/relay/DCUtR.md#the-protocol). +Add hole punching support for QUIC. +See also [DCUtR specification on usage with QUIC](https://github.com/libp2p/specs/blob/master/relay/DCUtR.md#the-protocol). ## Kademlia client mode @@ -179,4 +174,5 @@ Kademlia operations. |--------------|--------|-------------------|---------------------------------------------------|--------------|------------| | Connectivity | done | Q3/2023 | https://github.com/libp2p/rust-libp2p/issues/2883 | | | -We added alpha support for QUIC in Q4/2022 wrapping `quinn-proto`. Evaluate using `quinn` directly, replacing the wrapper. +We added alpha support for QUIC in Q4/2022 wrapping `quinn-proto`. +Evaluate using `quinn` directly, replacing the wrapper. From 188b70eaf011d169ec691ae0d46fd2da64a06d70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Aug 2023 09:10:58 +0000 Subject: [PATCH 30/44] deps: bump r7kamura/rust-problem-matchers from 1.3.0 to 1.4.0 Pull-Request: #4303. --- .github/workflows/ci.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c61e673b855..710af087316 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - uses: dtolnay/rust-toolchain@stable @@ -134,7 +134,7 @@ jobs: with: target: ${{ matrix.target }} - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: @@ -159,7 +159,7 @@ jobs: with: toolchain: ${{ env.MSRV }} - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: @@ -180,7 +180,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: @@ -197,7 +197,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: @@ -223,7 +223,7 @@ jobs: toolchain: ${{ matrix.rust-version }} components: clippy - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: @@ -240,7 +240,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: @@ -256,7 +256,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 with: @@ -280,7 +280,7 @@ jobs: with: components: rustfmt - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - name: Check formatting run: cargo fmt -- --check @@ -292,7 +292,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: r7kamura/rust-problem-matchers@d58b70c4a13c4866d96436315da451d8106f8f08 #v1.3.0 + - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - name: Ensure `full` feature contains all features run: | From b5d993267f7d76353ede4ddb2879bfe757851b1e Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Wed, 9 Aug 2023 00:29:21 +0800 Subject: [PATCH 31/44] feat: memory based connection limits Implements memory-based connection limits where the user can specify an absolute or a relative limit of the process' memory usage in relation to the available system memory. Related: #4252. Pull-Request: #4281. --- Cargo.lock | 53 ++++ Cargo.toml | 2 + libp2p/CHANGELOG.md | 4 + libp2p/Cargo.toml | 3 + libp2p/src/lib.rs | 5 + misc/memory-connection-limits/CHANGELOG.md | 3 + misc/memory-connection-limits/Cargo.toml | 26 ++ misc/memory-connection-limits/src/lib.rs | 232 ++++++++++++++++++ .../tests/max_bytes.rs | 89 +++++++ .../tests/max_percentage.rs | 88 +++++++ misc/memory-connection-limits/tests/util.rs | 128 ++++++++++ 11 files changed, 633 insertions(+) create mode 100644 misc/memory-connection-limits/CHANGELOG.md create mode 100644 misc/memory-connection-limits/Cargo.toml create mode 100644 misc/memory-connection-limits/src/lib.rs create mode 100644 misc/memory-connection-limits/tests/max_bytes.rs create mode 100644 misc/memory-connection-limits/tests/max_percentage.rs create mode 100644 misc/memory-connection-limits/tests/util.rs diff --git a/Cargo.lock b/Cargo.lock index 547efe4391a..2cf8332a7cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2537,6 +2537,7 @@ dependencies = [ "libp2p-identity", "libp2p-kad", "libp2p-mdns", + "libp2p-memory-connection-limits", "libp2p-metrics", "libp2p-noise", "libp2p-ping", @@ -2870,6 +2871,24 @@ dependencies = [ "void", ] +[[package]] +name = "libp2p-memory-connection-limits" +version = "0.1.0" +dependencies = [ + "async-std", + "libp2p-core", + "libp2p-identify", + "libp2p-identity", + "libp2p-swarm", + "libp2p-swarm-derive", + "libp2p-swarm-test", + "log", + "memory-stats", + "rand 0.8.5", + "sysinfo", + "void", +] + [[package]] name = "libp2p-metrics" version = "0.13.1" @@ -3528,6 +3547,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memory-stats" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34f79cf9964c5c9545493acda1263f1912f8d2c56c8a2ffee2606cb960acaacc" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "metrics-example" version = "0.1.0" @@ -3758,6 +3787,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -5450,6 +5488,21 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "sysinfo" +version = "0.29.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "165d6d8539689e3d3bc8b98ac59541e1f21c7de7c85d60dc80e43ae0ed2113db" +dependencies = [ + "cfg-if 1.0.0", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + [[package]] name = "system-configuration" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 702a847b0c2..b2d30c9257d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ "misc/allow-block-list", "misc/connection-limits", "misc/keygen", + "misc/memory-connection-limits", "misc/metrics", "misc/multistream-select", "misc/quick-protobuf-codec", @@ -75,6 +76,7 @@ libp2p-identify = { version = "0.43.0", path = "protocols/identify" } libp2p-identity = { version = "0.2.2" } libp2p-kad = { version = "0.44.4", path = "protocols/kad" } libp2p-mdns = { version = "0.44.0", path = "protocols/mdns" } +libp2p-memory-connection-limits = { version = "0.1.0", path = "misc/memory-connection-limits" } libp2p-metrics = { version = "0.13.1", path = "misc/metrics" } libp2p-mplex = { version = "0.40.0", path = "muxers/mplex" } libp2p-muxer-test-harness = { path = "muxers/test-harness" } diff --git a/libp2p/CHANGELOG.md b/libp2p/CHANGELOG.md index 4161ed054c5..fc2b24bd6e6 100644 --- a/libp2p/CHANGELOG.md +++ b/libp2p/CHANGELOG.md @@ -6,8 +6,12 @@ - Add `json` feature which exposes `request_response::json`. See [PR 4188]. +- Add `libp2p-memory-connection-limits` providing memory usage based connection limit configurations. + See [PR 4281]. + [PR 4188]: https://github.com/libp2p/rust-libp2p/pull/4188 [PR 4217]: https://github.com/libp2p/rust-libp2p/pull/4217 +[PR 4281]: https://github.com/libp2p/rust-libp2p/pull/4281 ## 0.52.1 diff --git a/libp2p/Cargo.toml b/libp2p/Cargo.toml index fd9290cf506..e057c9e8dd4 100644 --- a/libp2p/Cargo.toml +++ b/libp2p/Cargo.toml @@ -27,6 +27,7 @@ full = [ "kad", "macros", "mdns", + "memory-connection-limits", "metrics", "noise", "ping", @@ -65,6 +66,7 @@ json = ["libp2p-request-response?/json"] kad = ["dep:libp2p-kad", "libp2p-metrics?/kad"] macros = ["libp2p-swarm/macros"] mdns = ["dep:libp2p-mdns"] +memory-connection-limits = ["dep:libp2p-memory-connection-limits"] metrics = ["dep:libp2p-metrics"] noise = ["dep:libp2p-noise"] ping = ["dep:libp2p-ping", "libp2p-metrics?/ping"] @@ -124,6 +126,7 @@ pin-project = "1.0.0" libp2p-deflate = { workspace = true, optional = true } libp2p-dns = { workspace = true, optional = true } libp2p-mdns = { workspace = true, optional = true } +libp2p-memory-connection-limits = { workspace = true, optional = true } libp2p-tcp = { workspace = true, optional = true } libp2p-tls = { workspace = true, optional = true } libp2p-uds = { workspace = true, optional = true } diff --git a/libp2p/src/lib.rs b/libp2p/src/lib.rs index d22e4c25d30..9ec1fe48af4 100644 --- a/libp2p/src/lib.rs +++ b/libp2p/src/lib.rs @@ -78,6 +78,11 @@ pub use libp2p_kad as kad; #[cfg_attr(docsrs, doc(cfg(feature = "mdns")))] #[doc(inline)] pub use libp2p_mdns as mdns; +#[cfg(feature = "memory-connection-limits")] +#[cfg(not(target_arch = "wasm32"))] +#[cfg_attr(docsrs, doc(cfg(feature = "memory-connection-limits")))] +#[doc(inline)] +pub use libp2p_memory_connection_limits as memory_connection_limits; #[cfg(feature = "metrics")] #[doc(inline)] pub use libp2p_metrics as metrics; diff --git a/misc/memory-connection-limits/CHANGELOG.md b/misc/memory-connection-limits/CHANGELOG.md new file mode 100644 index 00000000000..5dac7afbf35 --- /dev/null +++ b/misc/memory-connection-limits/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.1.0 - unreleased + +- Initial release. diff --git a/misc/memory-connection-limits/Cargo.toml b/misc/memory-connection-limits/Cargo.toml new file mode 100644 index 00000000000..6bfecfd2b0e --- /dev/null +++ b/misc/memory-connection-limits/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "libp2p-memory-connection-limits" +edition = "2021" +rust-version = { workspace = true } +description = "Memory usage based connection limits for libp2p." +version = "0.1.0" +license = "MIT" +repository = "https://github.com/libp2p/rust-libp2p" +keywords = ["peer-to-peer", "libp2p", "networking"] +categories = ["network-programming", "asynchronous"] + +[dependencies] +memory-stats = { version = "1", features = ["always_use_statm"] } +libp2p-core = { workspace = true } +libp2p-swarm = { workspace = true } +libp2p-identity = { workspace = true, features = ["peerid"] } +log = "0.4" +sysinfo = "0.29" +void = "1" + +[dev-dependencies] +async-std = { version = "1.12.0", features = ["attributes"] } +libp2p-identify = { workspace = true } +libp2p-swarm-derive = { path = "../../swarm-derive" } +libp2p-swarm-test = { path = "../../swarm-test" } +rand = "0.8.5" diff --git a/misc/memory-connection-limits/src/lib.rs b/misc/memory-connection-limits/src/lib.rs new file mode 100644 index 00000000000..33e40b11843 --- /dev/null +++ b/misc/memory-connection-limits/src/lib.rs @@ -0,0 +1,232 @@ +// Copyright 2023 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use libp2p_core::{Endpoint, Multiaddr}; +use libp2p_identity::PeerId; +use libp2p_swarm::{ + dummy, ConnectionDenied, ConnectionId, FromSwarm, NetworkBehaviour, PollParameters, THandler, + THandlerInEvent, THandlerOutEvent, ToSwarm, +}; +use void::Void; + +use std::{ + fmt, + task::{Context, Poll}, + time::{Duration, Instant}, +}; + +/// A [`NetworkBehaviour`] that enforces a set of memory usage based limits. +/// +/// For these limits to take effect, this needs to be composed into the behaviour tree of your application. +/// +/// If a connection is denied due to a limit, either a [`SwarmEvent::IncomingConnectionError`](libp2p_swarm::SwarmEvent::IncomingConnectionError) +/// or [`SwarmEvent::OutgoingConnectionError`](libp2p_swarm::SwarmEvent::OutgoingConnectionError) will be emitted. +/// The [`ListenError::Denied`](libp2p_swarm::ListenError::Denied) and respectively the [`DialError::Denied`](libp2p_swarm::DialError::Denied) variant +/// contain a [`ConnectionDenied`](libp2p_swarm::ConnectionDenied) type that can be downcast to [`MemoryUsageLimitExceeded`] error if (and only if) **this** +/// behaviour denied the connection. +/// +/// If you employ multiple [`NetworkBehaviour`]s that manage connections, it may also be a different error. +/// +/// [Behaviour::with_max_bytes] and [Behaviour::with_max_percentage] are mutually exclusive. +/// If you need to employ both of them, compose two instances of [Behaviour] into your custom behaviour. +/// +/// # Example +/// +/// ```rust +/// # use libp2p_identify as identify; +/// # use libp2p_swarm_derive::NetworkBehaviour; +/// # use libp2p_memory_connection_limits as memory_connection_limits; +/// +/// #[derive(NetworkBehaviour)] +/// # #[behaviour(prelude = "libp2p_swarm::derive_prelude")] +/// struct MyBehaviour { +/// identify: identify::Behaviour, +/// limits: memory_connection_limits::Behaviour +/// } +/// ``` +pub struct Behaviour { + max_allowed_bytes: usize, + process_physical_memory_bytes: usize, + last_refreshed: Instant, +} + +/// The maximum duration for which the retrieved memory-stats of the process are allowed to be stale. +/// +/// Once exceeded, we will retrieve new stats. +const MAX_STALE_DURATION: Duration = Duration::from_millis(100); + +impl Behaviour { + /// Sets the process memory usage threshold in absolute bytes. + /// + /// New inbound and outbound connections will be denied when the threshold is reached. + pub fn with_max_bytes(max_allowed_bytes: usize) -> Self { + Self { + max_allowed_bytes, + process_physical_memory_bytes: memory_stats::memory_stats() + .map(|s| s.physical_mem) + .unwrap_or_default(), + last_refreshed: Instant::now(), + } + } + + /// Sets the process memory usage threshold in the percentage of the total physical memory. + /// + /// New inbound and outbound connections will be denied when the threshold is reached. + pub fn with_max_percentage(percentage: f64) -> Self { + use sysinfo::{RefreshKind, SystemExt}; + + let system_memory_bytes = + sysinfo::System::new_with_specifics(RefreshKind::new().with_memory()).total_memory(); + + Self::with_max_bytes((system_memory_bytes as f64 * percentage).round() as usize) + } + + /// Gets the process memory usage threshold in bytes. + pub fn max_allowed_bytes(&self) -> usize { + self.max_allowed_bytes + } + + fn check_limit(&mut self) -> Result<(), ConnectionDenied> { + self.refresh_memory_stats_if_needed(); + + if self.process_physical_memory_bytes > self.max_allowed_bytes { + return Err(ConnectionDenied::new(MemoryUsageLimitExceeded { + process_physical_memory_bytes: self.process_physical_memory_bytes, + max_allowed_bytes: self.max_allowed_bytes, + })); + } + + Ok(()) + } + + fn refresh_memory_stats_if_needed(&mut self) { + let now = Instant::now(); + + if self.last_refreshed + MAX_STALE_DURATION > now { + // Memory stats are reasonably recent, don't refresh. + return; + } + + let stats = match memory_stats::memory_stats() { + Some(stats) => stats, + None => { + log::warn!("Failed to retrieve process memory stats"); + return; + } + }; + + self.last_refreshed = now; + self.process_physical_memory_bytes = stats.physical_mem; + } +} + +impl NetworkBehaviour for Behaviour { + type ConnectionHandler = dummy::ConnectionHandler; + type ToSwarm = Void; + + fn handle_pending_inbound_connection( + &mut self, + _: ConnectionId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result<(), ConnectionDenied> { + self.check_limit() + } + + fn handle_established_inbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result, ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn handle_pending_outbound_connection( + &mut self, + _: ConnectionId, + _: Option, + _: &[Multiaddr], + _: Endpoint, + ) -> Result, ConnectionDenied> { + self.check_limit()?; + Ok(vec![]) + } + + fn handle_established_outbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: Endpoint, + ) -> Result, ConnectionDenied> { + Ok(dummy::ConnectionHandler) + } + + fn on_swarm_event(&mut self, _: FromSwarm) {} + + fn on_connection_handler_event( + &mut self, + _id: PeerId, + _: ConnectionId, + event: THandlerOutEvent, + ) { + void::unreachable(event) + } + + fn poll( + &mut self, + _: &mut Context<'_>, + _: &mut impl PollParameters, + ) -> Poll>> { + Poll::Pending + } +} + +/// A connection limit has been exceeded. +#[derive(Debug, Clone, Copy)] +pub struct MemoryUsageLimitExceeded { + process_physical_memory_bytes: usize, + max_allowed_bytes: usize, +} + +impl MemoryUsageLimitExceeded { + pub fn process_physical_memory_bytes(&self) -> usize { + self.process_physical_memory_bytes + } + + pub fn max_allowed_bytes(&self) -> usize { + self.max_allowed_bytes + } +} + +impl std::error::Error for MemoryUsageLimitExceeded {} + +impl fmt::Display for MemoryUsageLimitExceeded { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "process physical memory usage limit exceeded: process memory: {} bytes, max allowed: {} bytes", + self.process_physical_memory_bytes, + self.max_allowed_bytes, + ) + } +} diff --git a/misc/memory-connection-limits/tests/max_bytes.rs b/misc/memory-connection-limits/tests/max_bytes.rs new file mode 100644 index 00000000000..af86b048785 --- /dev/null +++ b/misc/memory-connection-limits/tests/max_bytes.rs @@ -0,0 +1,89 @@ +// Copyright 2023 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +mod util; + +use libp2p_core::Multiaddr; +use libp2p_identity::PeerId; +use libp2p_memory_connection_limits::*; +use std::time::Duration; +use util::*; + +use libp2p_swarm::{dial_opts::DialOpts, DialError, Swarm}; +use libp2p_swarm_test::SwarmExt; + +#[test] +fn max_bytes() { + const CONNECTION_LIMIT: usize = 20; + let max_allowed_bytes = CONNECTION_LIMIT * 1024 * 1024; + + let mut network = Swarm::new_ephemeral(|_| TestBehaviour { + connection_limits: Behaviour::with_max_bytes(max_allowed_bytes), + mem_consumer: ConsumeMemoryBehaviour1MBPending0Established::default(), + }); + + let addr: Multiaddr = "/memory/1234".parse().unwrap(); + let target = PeerId::random(); + + // Exercise `dial` function to get more stable memory stats later + network + .dial( + DialOpts::peer_id(target) + .addresses(vec![addr.clone()]) + .build(), + ) + .expect("Unexpected connection limit."); + + // Adds current mem usage to the limit and update + let max_allowed_bytes_plus_base_usage = + max_allowed_bytes + memory_stats::memory_stats().unwrap().physical_mem; + network.behaviour_mut().connection_limits = + Behaviour::with_max_bytes(max_allowed_bytes_plus_base_usage); + + for _ in 0..CONNECTION_LIMIT { + network + .dial( + DialOpts::peer_id(target) + .addresses(vec![addr.clone()]) + .build(), + ) + .expect("Unexpected connection limit."); + } + + std::thread::sleep(Duration::from_millis(100)); // Memory stats are only updated every 100ms internally, ensure they are up-to-date when we try to exceed it. + + match network + .dial(DialOpts::peer_id(target).addresses(vec![addr]).build()) + .expect_err("Unexpected dialing success.") + { + DialError::Denied { cause } => { + let exceeded = cause + .downcast::() + .expect("connection denied because of limit"); + + assert_eq!( + exceeded.max_allowed_bytes(), + max_allowed_bytes_plus_base_usage + ); + assert!(exceeded.process_physical_memory_bytes() >= exceeded.max_allowed_bytes()); + } + e => panic!("Unexpected error: {e:?}"), + } +} diff --git a/misc/memory-connection-limits/tests/max_percentage.rs b/misc/memory-connection-limits/tests/max_percentage.rs new file mode 100644 index 00000000000..ea3f20e6cbc --- /dev/null +++ b/misc/memory-connection-limits/tests/max_percentage.rs @@ -0,0 +1,88 @@ +// Copyright 2023 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +mod util; + +use libp2p_core::Multiaddr; +use libp2p_identity::PeerId; +use libp2p_memory_connection_limits::*; +use std::time::Duration; +use sysinfo::{RefreshKind, SystemExt}; +use util::*; + +use libp2p_swarm::{dial_opts::DialOpts, DialError, Swarm}; +use libp2p_swarm_test::SwarmExt; + +#[test] +fn max_percentage() { + const CONNECTION_LIMIT: usize = 20; + let system_info = sysinfo::System::new_with_specifics(RefreshKind::new().with_memory()); + + let mut network = Swarm::new_ephemeral(|_| TestBehaviour { + connection_limits: Behaviour::with_max_percentage(0.1), + mem_consumer: ConsumeMemoryBehaviour1MBPending0Established::default(), + }); + + let addr: Multiaddr = "/memory/1234".parse().unwrap(); + let target = PeerId::random(); + + // Exercise `dial` function to get more stable memory stats later + network + .dial( + DialOpts::peer_id(target) + .addresses(vec![addr.clone()]) + .build(), + ) + .expect("Unexpected connection limit."); + + // Adds current mem usage to the limit and update + let current_mem = memory_stats::memory_stats().unwrap().physical_mem; + let max_allowed_bytes = current_mem + CONNECTION_LIMIT * 1024 * 1024; + network.behaviour_mut().connection_limits = Behaviour::with_max_percentage( + max_allowed_bytes as f64 / system_info.total_memory() as f64, + ); + + for _ in 0..CONNECTION_LIMIT { + network + .dial( + DialOpts::peer_id(target) + .addresses(vec![addr.clone()]) + .build(), + ) + .expect("Unexpected connection limit."); + } + + std::thread::sleep(Duration::from_millis(100)); // Memory stats are only updated every 100ms internally, ensure they are up-to-date when we try to exceed it. + + match network + .dial(DialOpts::peer_id(target).addresses(vec![addr]).build()) + .expect_err("Unexpected dialing success.") + { + DialError::Denied { cause } => { + let exceeded = cause + .downcast::() + .expect("connection denied because of limit"); + + assert_eq!(exceeded.max_allowed_bytes(), max_allowed_bytes); + assert!(exceeded.process_physical_memory_bytes() >= exceeded.max_allowed_bytes()); + } + e => panic!("Unexpected error: {e:?}"), + } +} diff --git a/misc/memory-connection-limits/tests/util.rs b/misc/memory-connection-limits/tests/util.rs new file mode 100644 index 00000000000..a2fd7c20fed --- /dev/null +++ b/misc/memory-connection-limits/tests/util.rs @@ -0,0 +1,128 @@ +// Copyright 2023 Protocol Labs. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use std::task::{Context, Poll}; + +use libp2p_core::{Endpoint, Multiaddr}; +use libp2p_identity::PeerId; +use libp2p_swarm::{ + dummy, ConnectionDenied, ConnectionId, FromSwarm, NetworkBehaviour, PollParameters, THandler, + THandlerInEvent, THandlerOutEvent, ToSwarm, +}; +use void::Void; + +#[derive(libp2p_swarm_derive::NetworkBehaviour)] +#[behaviour(prelude = "libp2p_swarm::derive_prelude")] +pub(crate) struct TestBehaviour { + pub(crate) connection_limits: libp2p_memory_connection_limits::Behaviour, + pub(crate) mem_consumer: ConsumeMemoryBehaviour1MBPending0Established, +} + +pub(crate) type ConsumeMemoryBehaviour1MBPending0Established = + ConsumeMemoryBehaviour<{ 1024 * 1024 }, 0>; + +#[derive(Default)] +pub(crate) struct ConsumeMemoryBehaviour { + mem_pending: Vec>, + mem_established: Vec>, +} + +impl + ConsumeMemoryBehaviour +{ + fn handle_pending(&mut self) { + // 1MB + self.mem_pending.push(vec![1; MEM_PENDING]); + } + + fn handle_established(&mut self) { + // 1MB + self.mem_established.push(vec![1; MEM_ESTABLISHED]); + } +} + +impl NetworkBehaviour + for ConsumeMemoryBehaviour +{ + type ConnectionHandler = dummy::ConnectionHandler; + type ToSwarm = Void; + + fn handle_pending_inbound_connection( + &mut self, + _: ConnectionId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result<(), ConnectionDenied> { + self.handle_pending(); + Ok(()) + } + + fn handle_pending_outbound_connection( + &mut self, + _: ConnectionId, + _: Option, + _: &[Multiaddr], + _: Endpoint, + ) -> Result, ConnectionDenied> { + self.handle_pending(); + Ok(vec![]) + } + + fn handle_established_inbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: &Multiaddr, + ) -> Result, ConnectionDenied> { + self.handle_established(); + Ok(dummy::ConnectionHandler) + } + + fn handle_established_outbound_connection( + &mut self, + _: ConnectionId, + _: PeerId, + _: &Multiaddr, + _: Endpoint, + ) -> Result, ConnectionDenied> { + self.handle_established(); + Ok(dummy::ConnectionHandler) + } + + fn on_swarm_event(&mut self, _: FromSwarm) {} + + fn on_connection_handler_event( + &mut self, + _id: PeerId, + _: ConnectionId, + event: THandlerOutEvent, + ) { + void::unreachable(event) + } + + fn poll( + &mut self, + _: &mut Context<'_>, + _: &mut impl PollParameters, + ) -> Poll>> { + Poll::Pending + } +} From 02dc432227ee1132b7fe8f0b849fc9d513c907d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Oliveira?= Date: Tue, 8 Aug 2023 17:48:08 +0100 Subject: [PATCH 32/44] fix(quic): allow listening on ipv4 and ipv6 separately Resolves #4165. Pull-Request: #4289. --- Cargo.lock | 3 ++- Cargo.toml | 2 +- transports/quic/CHANGELOG.md | 7 ++++++ transports/quic/Cargo.toml | 3 ++- transports/quic/src/transport.rs | 42 ++++++++++++++++++++++++++++++-- 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2cf8332a7cd..5f5026f1afc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3058,7 +3058,7 @@ dependencies = [ [[package]] name = "libp2p-quic" -version = "0.9.0-alpha" +version = "0.9.1-alpha" dependencies = [ "async-std", "bytes", @@ -3079,6 +3079,7 @@ dependencies = [ "quinn", "rand 0.8.5", "rustls 0.21.5", + "socket2 0.5.3", "thiserror", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index b2d30c9257d..6b4bd5ebe09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,7 +85,7 @@ libp2p-perf = { version = "0.2.0", path = "protocols/perf" } libp2p-ping = { version = "0.43.0", path = "protocols/ping" } libp2p-plaintext = { version = "0.40.0", path = "transports/plaintext" } libp2p-pnet = { version = "0.23.0", path = "transports/pnet" } -libp2p-quic = { version = "0.9.0-alpha", path = "transports/quic" } +libp2p-quic = { version = "0.9.1-alpha", path = "transports/quic" } libp2p-relay = { version = "0.16.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" } diff --git a/transports/quic/CHANGELOG.md b/transports/quic/CHANGELOG.md index 11ee1e63394..7e0c09a1511 100644 --- a/transports/quic/CHANGELOG.md +++ b/transports/quic/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.9.1-alpha - unreleased + +- Allow listening on ipv4 and ipv6 separately. + See [PR 4289]. + +[PR 4289]: https://github.com/libp2p/rust-libp2p/pull/4289 + ## 0.9.0-alpha - Use `quinn` instead of `quinn-proto`. diff --git a/transports/quic/Cargo.toml b/transports/quic/Cargo.toml index 5d810860912..67f131aeb31 100644 --- a/transports/quic/Cargo.toml +++ b/transports/quic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libp2p-quic" -version = "0.9.0-alpha" +version = "0.9.1-alpha" authors = ["Parity Technologies "] edition = "2021" rust-version = { workspace = true } @@ -24,6 +24,7 @@ rand = "0.8.5" rustls = { version = "0.21.2", default-features = false } thiserror = "1.0.44" tokio = { version = "1.29.1", default-features = false, features = ["net", "rt", "time"], optional = true } +socket2 = "0.5.3" [features] tokio = ["dep:tokio", "if-watch/tokio", "quinn/runtime-tokio"] diff --git a/transports/quic/src/transport.rs b/transports/quic/src/transport.rs index d4a1db35604..7e0a4a812f7 100644 --- a/transports/quic/src/transport.rs +++ b/transports/quic/src/transport.rs @@ -37,12 +37,13 @@ use libp2p_core::{ Transport, }; use libp2p_identity::PeerId; +use socket2::{Domain, Socket, Type}; use std::collections::hash_map::{DefaultHasher, Entry}; use std::collections::HashMap; -use std::fmt; use std::hash::{Hash, Hasher}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket}; use std::time::Duration; +use std::{fmt, io}; use std::{ net::SocketAddr, pin::Pin, @@ -172,6 +173,21 @@ impl GenTransport

{ } } } + + fn create_socket(&self, socket_addr: SocketAddr) -> io::Result { + let socket = Socket::new( + Domain::for_address(socket_addr), + Type::DGRAM, + Some(socket2::Protocol::UDP), + )?; + if socket_addr.is_ipv6() { + socket.set_only_v6(true)?; + } + + socket.bind(&socket_addr.into())?; + + Ok(socket.into()) + } } impl Transport for GenTransport

{ @@ -188,7 +204,8 @@ impl Transport for GenTransport

{ let (socket_addr, version, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, false)?; let endpoint_config = self.quinn_config.endpoint_config.clone(); let server_config = self.quinn_config.server_config.clone(); - let socket = UdpSocket::bind(socket_addr).map_err(Self::Error::from)?; + let socket = self.create_socket(socket_addr).map_err(Self::Error::from)?; + let socket_c = socket.try_clone().map_err(Self::Error::from)?; let endpoint = Self::new_endpoint(endpoint_config, Some(server_config), socket)?; let listener = Listener::new( @@ -888,4 +905,25 @@ mod test { .unwrap(); assert!(!transport.dialer.contains_key(&SocketFamily::Ipv4)); } + + #[cfg(feature = "tokio")] + #[tokio::test] + async fn test_listens_ipv4_ipv6_separately() { + let keypair = libp2p_identity::Keypair::generate_ed25519(); + let config = Config::new(&keypair); + let mut transport = crate::tokio::Transport::new(config); + + transport + .listen_on( + ListenerId::next(), + "/ip4/0.0.0.0/udp/4001/quic-v1".parse().unwrap(), + ) + .unwrap(); + transport + .listen_on( + ListenerId::next(), + "/ip6/::/udp/4001/quic-v1".parse().unwrap(), + ) + .unwrap(); + } } From da94dcb23b0d65a0e94965e6e8ddb14899053bd8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Aug 2023 13:48:20 +0000 Subject: [PATCH 33/44] chore(deps): bump github.com/libp2p/go-libp2p from 0.27.5 to 0.27.8 in /wasm-tests/webtransport-tests/echo-server Pull-Request: #4308. --- wasm-tests/webtransport-tests/echo-server/go.mod | 6 +++--- wasm-tests/webtransport-tests/echo-server/go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/wasm-tests/webtransport-tests/echo-server/go.mod b/wasm-tests/webtransport-tests/echo-server/go.mod index 5856827d798..669124e1f69 100644 --- a/wasm-tests/webtransport-tests/echo-server/go.mod +++ b/wasm-tests/webtransport-tests/echo-server/go.mod @@ -3,7 +3,7 @@ module echo-server go 1.20 require ( - github.com/libp2p/go-libp2p v0.27.5 + github.com/libp2p/go-libp2p v0.27.8 github.com/multiformats/go-multiaddr v0.9.0 ) @@ -44,8 +44,8 @@ require ( github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-19 v0.3.2 // indirect - github.com/quic-go/qtls-go1-20 v0.2.2 // indirect + github.com/quic-go/qtls-go1-19 v0.3.3 // indirect + github.com/quic-go/qtls-go1-20 v0.2.3 // indirect github.com/quic-go/quic-go v0.33.0 // indirect github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect diff --git a/wasm-tests/webtransport-tests/echo-server/go.sum b/wasm-tests/webtransport-tests/echo-server/go.sum index ab2832bce75..2e4b66d2ec0 100644 --- a/wasm-tests/webtransport-tests/echo-server/go.sum +++ b/wasm-tests/webtransport-tests/echo-server/go.sum @@ -97,8 +97,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-libp2p v0.27.5 h1:KwA7pXKXpz8hG6Cr1fMA7UkgleogcwQj0sxl5qquWRg= -github.com/libp2p/go-libp2p v0.27.5/go.mod h1:oMfQGTb9CHnrOuSM6yMmyK2lXz3qIhnkn2+oK3B1Y2g= +github.com/libp2p/go-libp2p v0.27.8 h1:IX5x/4yKwyPQeVS2AXHZ3J4YATM9oHBGH1gBc23jBAI= +github.com/libp2p/go-libp2p v0.27.8/go.mod h1:eCFFtd0s5i/EVKR7+5Ki8bM7qwkNW3TPTTSSW9sz8NE= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= @@ -158,10 +158,10 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= -github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= -github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE= +github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI= +github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= From 5a8eb793fea863073e45c6710b96bbf61dc45758 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 11 Aug 2023 12:10:42 +0200 Subject: [PATCH 34/44] chore: prepare libp2p v0.52.2 Pull-Request: #4312. --- libp2p/CHANGELOG.md | 2 +- misc/memory-connection-limits/CHANGELOG.md | 2 +- misc/metrics/CHANGELOG.md | 4 ++-- muxers/yamux/CHANGELOG.md | 4 ++-- protocols/gossipsub/CHANGELOG.md | 2 +- protocols/kad/CHANGELOG.md | 2 +- protocols/relay/CHANGELOG.md | 2 +- protocols/request-response/CHANGELOG.md | 2 +- swarm/CHANGELOG.md | 2 +- transports/quic/CHANGELOG.md | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libp2p/CHANGELOG.md b/libp2p/CHANGELOG.md index fc2b24bd6e6..50774aaa97f 100644 --- a/libp2p/CHANGELOG.md +++ b/libp2p/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.52.2 - unreleased +## 0.52.2 - Include gossipsub when compiling for wasm. See [PR 4217]. diff --git a/misc/memory-connection-limits/CHANGELOG.md b/misc/memory-connection-limits/CHANGELOG.md index 5dac7afbf35..951a5a3f138 100644 --- a/misc/memory-connection-limits/CHANGELOG.md +++ b/misc/memory-connection-limits/CHANGELOG.md @@ -1,3 +1,3 @@ -## 0.1.0 - unreleased +## 0.1.0 - Initial release. diff --git a/misc/metrics/CHANGELOG.md b/misc/metrics/CHANGELOG.md index cca9ced5ec7..5c3d3c140ba 100644 --- a/misc/metrics/CHANGELOG.md +++ b/misc/metrics/CHANGELOG.md @@ -1,11 +1,11 @@ -## 0.13.1 - unreleased +## 0.13.1 - Enable gossipsub related data-type fields when compiling for wasm. See [PR 4217]. [PR 4217]: https://github.com/libp2p/rust-libp2p/pull/4217 -## 0.13.0 +## 0.13.0 - Previously `libp2p-metrics::identify` would increase a counter / gauge / histogram on each received identify information. These metrics are misleading, as e.g. they depend on the identify diff --git a/muxers/yamux/CHANGELOG.md b/muxers/yamux/CHANGELOG.md index caea4e5359e..92e9fbebc02 100644 --- a/muxers/yamux/CHANGELOG.md +++ b/muxers/yamux/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.44.1 - unreleased +## 0.44.1 - Update to `yamux` `v0.12` which brings performance improvements and introduces an ACK backlog of 256 inbound streams. When interacting with other libp2p nodes that are also running this or a newer version, the creation of inbound streams will be backpressured once the ACK backlog is hit. @@ -6,7 +6,7 @@ [PR 3013]: https://github.com/libp2p/rust-libp2p/pull/3013 -## 0.44.0 +## 0.44.0 - Raise MSRV to 1.65. See [PR 3715]. diff --git a/protocols/gossipsub/CHANGELOG.md b/protocols/gossipsub/CHANGELOG.md index ab483bdd8a1..a1f4ef6c973 100644 --- a/protocols/gossipsub/CHANGELOG.md +++ b/protocols/gossipsub/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.45.1 - unreleased +## 0.45.1 - Add getter function to obtain `TopicScoreParams`. See [PR 4231]. diff --git a/protocols/kad/CHANGELOG.md b/protocols/kad/CHANGELOG.md index cd87a6448d0..a9cde76dd76 100644 --- a/protocols/kad/CHANGELOG.md +++ b/protocols/kad/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.44.4 - unreleased +## 0.44.4 - Implement common traits on `RoutingUpdate`. See [PR 4270]. diff --git a/protocols/relay/CHANGELOG.md b/protocols/relay/CHANGELOG.md index c79034c24d4..6af89e25d71 100644 --- a/protocols/relay/CHANGELOG.md +++ b/protocols/relay/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.16.1 - unreleased +## 0.16.1 - Export `RateLimiter` type. See [PR 3742]. diff --git a/protocols/request-response/CHANGELOG.md b/protocols/request-response/CHANGELOG.md index 292cb812103..693145c6f72 100644 --- a/protocols/request-response/CHANGELOG.md +++ b/protocols/request-response/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.25.1 - unreleased +## 0.25.1 - Replace unmaintained `serde_cbor` dependency with `cbor4ii`. See [PR 4187]. diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 6a9808dd554..37a5cbc6157 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.43.3 - unreleased +## 0.43.3 - Implement `Display` for `ConnectionId`. See [PR 4278]. diff --git a/transports/quic/CHANGELOG.md b/transports/quic/CHANGELOG.md index 7e0c09a1511..5fc4ccc1cdf 100644 --- a/transports/quic/CHANGELOG.md +++ b/transports/quic/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.9.1-alpha - unreleased +## 0.9.1-alpha - Allow listening on ipv4 and ipv6 separately. See [PR 4289]. From 79aca371d164be5b042c49e3a8899568f4b42151 Mon Sep 17 00:00:00 2001 From: Arsenii Ronzhyn <33022971+arsenron@users.noreply.github.com> Date: Fri, 11 Aug 2023 15:14:37 +0300 Subject: [PATCH 35/44] fix(quic): add support for reusing an existing socket for local dialing Tracked in #4259. Now if a listener supports loopback interfaces, when a remote address is also a loopback address, we reuse an existing listener. Pull-Request: #4304. --- Cargo.lock | 2 +- Cargo.toml | 2 +- transports/quic/CHANGELOG.md | 7 ++++++ transports/quic/Cargo.toml | 2 +- transports/quic/src/transport.rs | 28 +++++++++++++++------ transports/quic/tests/smoke.rs | 43 ++++++++++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f5026f1afc..979bc43d8d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3058,7 +3058,7 @@ dependencies = [ [[package]] name = "libp2p-quic" -version = "0.9.1-alpha" +version = "0.9.2-alpha" dependencies = [ "async-std", "bytes", diff --git a/Cargo.toml b/Cargo.toml index 6b4bd5ebe09..fb503a12e61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,7 +85,7 @@ libp2p-perf = { version = "0.2.0", path = "protocols/perf" } libp2p-ping = { version = "0.43.0", path = "protocols/ping" } libp2p-plaintext = { version = "0.40.0", path = "transports/plaintext" } libp2p-pnet = { version = "0.23.0", path = "transports/pnet" } -libp2p-quic = { version = "0.9.1-alpha", path = "transports/quic" } +libp2p-quic = { version = "0.9.2-alpha", path = "transports/quic" } libp2p-relay = { version = "0.16.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" } diff --git a/transports/quic/CHANGELOG.md b/transports/quic/CHANGELOG.md index 5fc4ccc1cdf..66a6dec3a2e 100644 --- a/transports/quic/CHANGELOG.md +++ b/transports/quic/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.9.2-alpha + +- Add support for reusing an existing socket when dialing localhost address. + See [PR 4304]. + +[PR 4304]: https://github.com/libp2p/rust-libp2p/pull/4304 + ## 0.9.1-alpha - Allow listening on ipv4 and ipv6 separately. diff --git a/transports/quic/Cargo.toml b/transports/quic/Cargo.toml index 67f131aeb31..9dba8c692c5 100644 --- a/transports/quic/Cargo.toml +++ b/transports/quic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libp2p-quic" -version = "0.9.1-alpha" +version = "0.9.2-alpha" authors = ["Parity Technologies "] edition = "2021" rust-version = { workspace = true } diff --git a/transports/quic/src/transport.rs b/transports/quic/src/transport.rs index 7e0a4a812f7..9f025cd63fc 100644 --- a/transports/quic/src/transport.rs +++ b/transports/quic/src/transport.rs @@ -39,7 +39,7 @@ use libp2p_core::{ use libp2p_identity::PeerId; use socket2::{Domain, Socket, Type}; use std::collections::hash_map::{DefaultHasher, Entry}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::hash::{Hash, Hasher}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket}; use std::time::Duration; @@ -155,9 +155,16 @@ impl GenTransport

{ if l.is_closed { return false; } - let listen_addr = l.socket_addr(); - SocketFamily::is_same(&listen_addr.ip(), &socket_addr.ip()) - && listen_addr.ip().is_loopback() == socket_addr.ip().is_loopback() + SocketFamily::is_same(&l.socket_addr().ip(), &socket_addr.ip()) + }) + .filter(|l| { + if socket_addr.ip().is_loopback() { + l.listening_addresses + .iter() + .any(|ip_addr| ip_addr.is_loopback()) + } else { + true + } }) .collect(); match listeners.len() { @@ -428,6 +435,8 @@ struct Listener { /// The stream must be awaken after it has been closed to deliver the last event. close_listener_waker: Option, + + listening_addresses: HashSet, } impl Listener

{ @@ -440,12 +449,14 @@ impl Listener

{ ) -> Result { let if_watcher; let pending_event; + let mut listening_addresses = HashSet::new(); let local_addr = socket.local_addr()?; if local_addr.ip().is_unspecified() { if_watcher = Some(P::new_if_watcher()?); pending_event = None; } else { if_watcher = None; + listening_addresses.insert(local_addr.ip()); let ma = socketaddr_to_multiaddr(&local_addr, version); pending_event = Some(TransportEvent::NewAddress { listener_id, @@ -467,6 +478,7 @@ impl Listener

{ is_closed: false, pending_event, close_listener_waker: None, + listening_addresses, }) } @@ -513,7 +525,8 @@ impl Listener

{ if let Some(listen_addr) = ip_to_listenaddr(&endpoint_addr, inet.addr(), self.version) { - log::debug!("New listen address: {}", listen_addr); + log::debug!("New listen address: {listen_addr}"); + self.listening_addresses.insert(inet.addr()); return Poll::Ready(TransportEvent::NewAddress { listener_id: self.listener_id, listen_addr, @@ -524,7 +537,8 @@ impl Listener

{ if let Some(listen_addr) = ip_to_listenaddr(&endpoint_addr, inet.addr(), self.version) { - log::debug!("Expired listen address: {}", listen_addr); + log::debug!("Expired listen address: {listen_addr}"); + self.listening_addresses.remove(&inet.addr()); return Poll::Ready(TransportEvent::AddressExpired { listener_id: self.listener_id, listen_addr, @@ -730,7 +744,7 @@ fn socketaddr_to_multiaddr(socket_addr: &SocketAddr, version: ProtocolVersion) - #[cfg(test)] #[cfg(any(feature = "async-std", feature = "tokio"))] -mod test { +mod tests { use futures::future::poll_fn; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; diff --git a/transports/quic/tests/smoke.rs b/transports/quic/tests/smoke.rs index 93adfa68013..a0c43b9ebdd 100644 --- a/transports/quic/tests/smoke.rs +++ b/transports/quic/tests/smoke.rs @@ -414,6 +414,49 @@ async fn write_after_peer_dropped_stream() { stream_b.close().await.expect("Close failed."); } +/// - A listens on 0.0.0.0:0 +/// - B listens on 127.0.0.1:0 +/// - A dials B +/// - Source port of A at B is the A's listen port +#[cfg(feature = "tokio")] +#[tokio::test] +async fn test_local_listener_reuse() { + let (_, mut a_transport) = create_default_transport::(); + let (_, mut b_transport) = create_default_transport::(); + + a_transport + .listen_on( + ListenerId::next(), + "/ip4/0.0.0.0/udp/0/quic-v1".parse().unwrap(), + ) + .unwrap(); + + // wait until a listener reports a loopback address + let a_listen_addr = 'outer: loop { + let ev = a_transport.next().await.unwrap(); + let listen_addr = ev.into_new_address().unwrap(); + for proto in listen_addr.iter() { + if let Protocol::Ip4(ip4) = proto { + if ip4.is_loopback() { + break 'outer listen_addr; + } + } + } + }; + // If we do not poll until the end, `NewAddress` events may be `Ready` and `connect` function + // below will panic due to an unexpected event. + poll_fn(|cx| { + let mut pinned = Pin::new(&mut a_transport); + while pinned.as_mut().poll(cx).is_ready() {} + Poll::Ready(()) + }) + .await; + + let b_addr = start_listening(&mut b_transport, "/ip4/127.0.0.1/udp/0/quic-v1").await; + let (_, send_back_addr, _) = connect(&mut b_transport, &mut a_transport, b_addr).await.0; + assert_eq!(send_back_addr, a_listen_addr); +} + async fn smoke() { let _ = env_logger::try_init(); From 8e00d1244ce255849b4165ab32762ff0f74d2cb3 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Fri, 11 Aug 2023 17:13:33 +0200 Subject: [PATCH 36/44] fix(swarm): import libp2p-yamux dev-dependency via path Follow-up to https://github.com/libp2p/rust-libp2p/pull/4091. Pull-Request: #4314. --- swarm/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swarm/Cargo.toml b/swarm/Cargo.toml index 37d16d31497..189fa5c52a4 100644 --- a/swarm/Cargo.toml +++ b/swarm/Cargo.toml @@ -48,9 +48,9 @@ libp2p-identity = { workspace = true, features = ["ed25519"] } libp2p-kad = { path = "../protocols/kad" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. libp2p-ping = { path = "../protocols/ping" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. libp2p-plaintext = { path = "../transports/plaintext" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -libp2p-swarm-derive = { path = "../swarm-derive" } +libp2p-swarm-derive = { path = "../swarm-derive" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. libp2p-swarm-test = { path = "../swarm-test" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. -libp2p-yamux = { workspace = true } +libp2p-yamux = { path = "../muxers/yamux" } # Using `path` here because this is a cyclic dev-dependency which otherwise breaks releasing. quickcheck = { workspace = true } void = "1" once_cell = "1.18.0" From 01e7353d047e82a6b036609ad65ec3b5b9ce0163 Mon Sep 17 00:00:00 2001 From: Doug A Date: Sat, 12 Aug 2023 06:02:47 -0300 Subject: [PATCH 37/44] docs(roadmap): update to reflect ongoing wasm browser work Update ROADMAP to reflect in-progress works Pull-Request: #4315. --- ROADMAP.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index 6758bf5a345..0d5533f91fa 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -67,7 +67,7 @@ Though (a) I think we should prioritize improving existing functionality over ne | Category | Status | Target Completion | Tracking | Dependencies | Dependents | |--------------|--------|-------------------|--------------------------------------------|-------------------------------------------------------------------------------------------|------------| -| Connectivity | todo | | https://github.com/libp2p/specs/issues/475 | [Improved WASM support](#improved-wasm-support), https://github.com/libp2p/specs/pull/497 | | +| Connectivity | In progress | | https://github.com/libp2p/specs/issues/475 | [Improved WASM support](#improved-wasm-support), https://github.com/libp2p/specs/pull/497 | https://github.com/libp2p/rust-libp2p/pull/4248 | Use the browser's WebRTC stack to support [`/webrtc`](https://github.com/libp2p/specs/blob/master/webrtc/webrtc.md) and [`/webrtc-direct`](https://github.com/libp2p/specs/blob/master/webrtc/webrtc-direct.md) from within the browser using rust-libp2p compiled to WASM. This makes rust-libp2p a truly end-to-end solution, enabling users to use rust-libp2p on both the client (browser) and server side. From b265ed2d03e2f3699b23e09897013f430adce14a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 08:21:15 +0000 Subject: [PATCH 38/44] deps: bump Swatinem/rust-cache from 2.6.0 to 2.6.1 Pull-Request: #4317. --- .github/workflows/cache-factory.yml | 2 +- .github/workflows/ci.yml | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/cache-factory.yml b/.github/workflows/cache-factory.yml index 8d25eb9acab..860f0a0de2c 100644 --- a/.github/workflows/cache-factory.yml +++ b/.github/workflows/cache-factory.yml @@ -22,7 +22,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: shared-key: stable-cache diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 710af087316..470016d68ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: shared-key: stable-cache save-if: false @@ -136,7 +136,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: key: ${{ matrix.target }} save-if: ${{ github.ref == 'refs/heads/master' }} @@ -161,7 +161,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: save-if: ${{ github.ref == 'refs/heads/master' }} @@ -182,7 +182,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: key: ${{ matrix.features }} save-if: ${{ github.ref == 'refs/heads/master' }} @@ -199,7 +199,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: save-if: ${{ github.ref == 'refs/heads/master' }} @@ -225,7 +225,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: save-if: ${{ github.ref == 'refs/heads/master' }} @@ -242,7 +242,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: save-if: ${{ github.ref == 'refs/heads/master' }} @@ -258,7 +258,7 @@ jobs: - uses: r7kamura/rust-problem-matchers@2c2f1016021a7455a6b5b4bbae31145f3b3cd83a #v1.4.0 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 with: shared-key: stable-cache save-if: false @@ -326,7 +326,7 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 - run: cargo install --version 0.10.0 pb-rs --locked @@ -352,5 +352,5 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: Swatinem/rust-cache@b8a6852b4f997182bdea832df3f9e153038b5191 # v2.6.0 + - uses: Swatinem/rust-cache@578b235f6e5f613f7727f1c17bd3305b4d4d4e1f # v2.6.1 - run: cargo metadata --locked --format-version=1 > /dev/null From a4b8ff4673c5fcef001b662cd5befa4653daa5bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 09:00:31 +0000 Subject: [PATCH 39/44] deps: bump tokio from 1.29.1 to 1.31.0 Pull-Request: #4318. --- Cargo.lock | 45 ++++++++++++++++----------------- examples/rendezvous/Cargo.toml | 2 +- interop-tests/Cargo.toml | 2 +- protocols/mdns/Cargo.toml | 4 +-- protocols/perf/Cargo.toml | 2 +- protocols/rendezvous/Cargo.toml | 2 +- swarm/Cargo.toml | 2 +- transports/pnet/Cargo.toml | 2 +- transports/quic/Cargo.toml | 4 +-- transports/tcp/Cargo.toml | 4 +-- transports/tls/Cargo.toml | 2 +- transports/uds/Cargo.toml | 2 +- transports/webrtc/Cargo.toml | 4 +-- 13 files changed, 38 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 979bc43d8d9..db69052abcb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -455,7 +455,7 @@ dependencies = [ "log", "memchr", "once_cell", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "pin-utils", "slab", "wasm-bindgen-futures", @@ -503,7 +503,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", ] [[package]] @@ -548,7 +548,7 @@ dependencies = [ "memchr", "mime", "percent-encoding", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "rustversion", "serde", "serde_json", @@ -945,7 +945,7 @@ dependencies = [ "bytes", "futures-core", "memchr", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "tokio", "tokio-util", ] @@ -1794,7 +1794,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "waker-fn", ] @@ -1876,7 +1876,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "pin-utils", "slab", ] @@ -2134,7 +2134,7 @@ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", ] [[package]] @@ -2177,7 +2177,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "socket2 0.4.9", "tokio", "tower-service", @@ -4082,9 +4082,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" [[package]] name = "pin-utils" @@ -4174,7 +4174,7 @@ dependencies = [ "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "windows-sys", ] @@ -4361,7 +4361,7 @@ dependencies = [ "async-std", "bytes", "futures-io", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "quinn-proto", "quinn-udp", "rustc-hash", @@ -4540,7 +4540,7 @@ dependencies = [ "futures-util", "itoa", "percent-encoding", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "ryu", "tokio", "tokio-util", @@ -4649,7 +4649,7 @@ dependencies = [ "native-tls", "once_cell", "percent-encoding", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "serde", "serde_json", "serde_urlencoded", @@ -5669,20 +5669,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "parking_lot", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "signal-hook-registry", - "socket2 0.4.9", + "socket2 0.5.3", "tokio-macros", "windows-sys", ] @@ -5729,7 +5728,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "tokio", "tracing", ] @@ -5743,7 +5742,7 @@ dependencies = [ "futures-core", "futures-util", "pin-project", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "tokio", "tower-layer", "tower-service", @@ -5767,7 +5766,7 @@ dependencies = [ "mime", "mime_guess", "percent-encoding", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "tokio", "tokio-util", "tower-layer", @@ -5795,7 +5794,7 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "log", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.12", "tracing-attributes", "tracing-core", ] diff --git a/examples/rendezvous/Cargo.toml b/examples/rendezvous/Cargo.toml index ffbde3fd7dc..e0cf39bafab 100644 --- a/examples/rendezvous/Cargo.toml +++ b/examples/rendezvous/Cargo.toml @@ -12,4 +12,4 @@ env_logger = "0.10.0" futures = "0.3.28" libp2p = { path = "../../libp2p", features = ["async-std", "identify", "macros", "noise", "ping", "rendezvous", "tcp", "tokio", "yamux"] } log = "0.4" -tokio = { version = "1.29", features = [ "rt-multi-thread", "macros", "time" ] } +tokio = { version = "1.31", features = [ "rt-multi-thread", "macros", "time" ] } diff --git a/interop-tests/Cargo.toml b/interop-tests/Cargo.toml index 2d0d8ea25b7..d03c0403f49 100644 --- a/interop-tests/Cargo.toml +++ b/interop-tests/Cargo.toml @@ -28,7 +28,7 @@ redis = { version = "0.23.0", default-features = false, features = ["tokio-comp" rust-embed = "6.8" serde_json = "1" thirtyfour = "=0.32.0-rc.8" # https://github.com/stevepryde/thirtyfour/issues/169 -tokio = { version = "1.29.1", features = ["full"] } +tokio = { version = "1.31.0", features = ["full"] } tower-http = { version = "0.4", features = ["cors", "fs", "trace"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } diff --git a/protocols/mdns/Cargo.toml b/protocols/mdns/Cargo.toml index 830547e7bbd..338e410b5b5 100644 --- a/protocols/mdns/Cargo.toml +++ b/protocols/mdns/Cargo.toml @@ -22,7 +22,7 @@ log = "0.4.19" rand = "0.8.3" smallvec = "1.11.0" socket2 = { version = "0.5.3", features = ["all"] } -tokio = { version = "1.29", default-features = false, features = ["net", "time"], optional = true} +tokio = { version = "1.31", default-features = false, features = ["net", "time"], optional = true} trust-dns-proto = { version = "0.22.0", default-features = false, features = ["mdns", "tokio-runtime"] } void = "1.0.2" @@ -37,7 +37,7 @@ libp2p-noise = { workspace = true } libp2p-swarm = { workspace = true, features = ["tokio", "async-std"] } libp2p-tcp = { workspace = true, features = ["tokio", "async-io"] } libp2p-yamux = { workspace = true } -tokio = { version = "1.29", default-features = false, features = ["macros", "rt", "rt-multi-thread", "time"] } +tokio = { version = "1.31", default-features = false, features = ["macros", "rt", "rt-multi-thread", "time"] } libp2p-swarm-test = { path = "../../swarm-test" } [[test]] diff --git a/protocols/perf/Cargo.toml b/protocols/perf/Cargo.toml index 5374c68ac9a..758b8a52c9e 100644 --- a/protocols/perf/Cargo.toml +++ b/protocols/perf/Cargo.toml @@ -30,7 +30,7 @@ log = "0.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" thiserror = "1.0" -tokio = { version = "1.29.1", features = ["full"] } +tokio = { version = "1.31.0", features = ["full"] } void = "1" [dev-dependencies] diff --git a/protocols/rendezvous/Cargo.toml b/protocols/rendezvous/Cargo.toml index b24781dcd74..7929d3c4a06 100644 --- a/protocols/rendezvous/Cargo.toml +++ b/protocols/rendezvous/Cargo.toml @@ -37,7 +37,7 @@ libp2p-identify = { workspace = true } libp2p-yamux = { workspace = true } libp2p-tcp = { workspace = true, features = ["tokio"] } rand = "0.8" -tokio = { version = "1.29", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] } +tokio = { version = "1.31", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] } libp2p-swarm-test = { path = "../../swarm-test" } # Passing arguments to the docsrs builder in order to properly document cfg's. diff --git a/swarm/Cargo.toml b/swarm/Cargo.toml index 189fa5c52a4..1290bfdddf4 100644 --- a/swarm/Cargo.toml +++ b/swarm/Cargo.toml @@ -30,7 +30,7 @@ multistream-select = { workspace = true } [target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies] async-std = { version = "1.6.2", optional = true } -tokio = { version = "1.29", features = ["rt"], optional = true } +tokio = { version = "1.31", features = ["rt"], optional = true } [features] macros = ["dep:libp2p-swarm-derive"] diff --git a/transports/pnet/Cargo.toml b/transports/pnet/Cargo.toml index b74c4ef29a7..11c27266057 100644 --- a/transports/pnet/Cargo.toml +++ b/transports/pnet/Cargo.toml @@ -27,7 +27,7 @@ libp2p-tcp = { workspace = true, features = ["tokio"] } libp2p-websocket = { workspace = true } libp2p-yamux = { workspace = true } quickcheck = { workspace = true } -tokio = { version = "1.29.1", features = ["full"] } +tokio = { version = "1.31.0", features = ["full"] } # Passing arguments to the docsrs builder in order to properly document cfg's. # More information: https://docs.rs/about/builds#cross-compiling diff --git a/transports/quic/Cargo.toml b/transports/quic/Cargo.toml index 9dba8c692c5..2500e5d7b6f 100644 --- a/transports/quic/Cargo.toml +++ b/transports/quic/Cargo.toml @@ -23,7 +23,7 @@ quinn = { version = "0.10.1", default-features = false, features = ["tls-rustls" rand = "0.8.5" rustls = { version = "0.21.2", default-features = false } thiserror = "1.0.44" -tokio = { version = "1.29.1", default-features = false, features = ["net", "rt", "time"], optional = true } +tokio = { version = "1.31.0", default-features = false, features = ["net", "rt", "time"], optional = true } socket2 = "0.5.3" [features] @@ -45,7 +45,7 @@ libp2p-noise = { workspace = true } libp2p-tcp = { workspace = true, features = ["async-io"] } libp2p-yamux = { workspace = true } quickcheck = "1" -tokio = { version = "1.29.1", features = ["macros", "rt-multi-thread", "time"] } +tokio = { version = "1.31.0", features = ["macros", "rt-multi-thread", "time"] } [[test]] name = "stream_compliance" diff --git a/transports/tcp/Cargo.toml b/transports/tcp/Cargo.toml index aaf409169dc..5103ee9576a 100644 --- a/transports/tcp/Cargo.toml +++ b/transports/tcp/Cargo.toml @@ -20,7 +20,7 @@ libp2p-core = { workspace = true } libp2p-identity = { workspace = true } log = "0.4.19" socket2 = { version = "0.5.3", features = ["all"] } -tokio = { version = "1.29.1", default-features = false, features = ["net"], optional = true } +tokio = { version = "1.31.0", default-features = false, features = ["net"], optional = true } [features] tokio = ["dep:tokio", "if-watch/tokio"] @@ -28,7 +28,7 @@ async-io = ["dep:async-io", "if-watch/smol"] [dev-dependencies] async-std = { version = "1.6.5", features = ["attributes"] } -tokio = { version = "1.29.1", default-features = false, features = ["full"] } +tokio = { version = "1.31.0", default-features = false, features = ["full"] } env_logger = "0.10.0" # Passing arguments to the docsrs builder in order to properly document cfg's. diff --git a/transports/tls/Cargo.toml b/transports/tls/Cargo.toml index 5275a9c07a6..191a24d6741 100644 --- a/transports/tls/Cargo.toml +++ b/transports/tls/Cargo.toml @@ -33,7 +33,7 @@ libp2p-core = { workspace = true } libp2p-identity = { workspace = true, features = ["ed25519", "rsa", "secp256k1", "ecdsa"] } libp2p-swarm = { workspace = true } libp2p-yamux = { workspace = true } -tokio = { version = "1.29.1", features = ["full"] } +tokio = { version = "1.31.0", features = ["full"] } # Passing arguments to the docsrs builder in order to properly document cfg's. # More information: https://docs.rs/about/builds#cross-compiling diff --git a/transports/uds/Cargo.toml b/transports/uds/Cargo.toml index be011b5ca8d..a01cc9c6916 100644 --- a/transports/uds/Cargo.toml +++ b/transports/uds/Cargo.toml @@ -15,7 +15,7 @@ async-std = { version = "1.6.2", optional = true } libp2p-core = { workspace = true } log = "0.4.19" futures = "0.3.28" -tokio = { version = "1.29", default-features = false, features = ["net"], optional = true } +tokio = { version = "1.31", default-features = false, features = ["net"], optional = true } [dev-dependencies] tempfile = "3.7" diff --git a/transports/webrtc/Cargo.toml b/transports/webrtc/Cargo.toml index 70d5553e293..05271951a33 100644 --- a/transports/webrtc/Cargo.toml +++ b/transports/webrtc/Cargo.toml @@ -32,7 +32,7 @@ serde = { version = "1.0", features = ["derive"] } stun = "0.4" thiserror = "1" tinytemplate = "1.2" -tokio = { version = "1.29", features = ["net"], optional = true} +tokio = { version = "1.31", features = ["net"], optional = true} tokio-util = { version = "0.7", features = ["compat"], optional = true } webrtc = { version = "0.8.0", optional = true } @@ -46,7 +46,7 @@ env_logger = "0.10" hex-literal = "0.4" libp2p-swarm = { workspace = true, features = ["macros", "tokio"] } libp2p-ping = { workspace = true } -tokio = { version = "1.29", features = ["full"] } +tokio = { version = "1.31", features = ["full"] } unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] } void = "1" quickcheck = "1.0.3" From 8022769dafd01d0833e98f933345a65a9d134637 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 09:20:07 +0000 Subject: [PATCH 40/44] deps: bump clap from 4.3.19 to 4.3.21 Pull-Request: #4319. --- Cargo.lock | 8 ++++---- examples/autonat/Cargo.toml | 2 +- examples/dcutr/Cargo.toml | 2 +- examples/file-sharing/Cargo.toml | 2 +- examples/relay-server/Cargo.toml | 2 +- misc/keygen/Cargo.toml | 2 +- protocols/dcutr/Cargo.toml | 2 +- protocols/perf/Cargo.toml | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db69052abcb..f84c97fd456 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -891,9 +891,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.19" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" dependencies = [ "clap_builder", "clap_derive", @@ -902,9 +902,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.19" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" dependencies = [ "anstream", "anstyle", diff --git a/examples/autonat/Cargo.toml b/examples/autonat/Cargo.toml index 9f40dbbc3f3..9ca936b638a 100644 --- a/examples/autonat/Cargo.toml +++ b/examples/autonat/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT" [dependencies] async-std = { version = "1.12", features = ["attributes"] } -clap = { version = "4.3.12", features = ["derive"] } +clap = { version = "4.3.21", features = ["derive"] } env_logger = "0.10.0" futures = "0.3.28" libp2p = { path = "../../libp2p", features = ["async-std", "tcp", "noise", "yamux", "autonat", "identify", "macros"] } diff --git a/examples/dcutr/Cargo.toml b/examples/dcutr/Cargo.toml index 5a6389f00c0..38394ee3e2c 100644 --- a/examples/dcutr/Cargo.toml +++ b/examples/dcutr/Cargo.toml @@ -6,7 +6,7 @@ publish = false license = "MIT" [dependencies] -clap = { version = "4.3.12", features = ["derive"] } +clap = { version = "4.3.21", features = ["derive"] } env_logger = "0.10.0" futures = "0.3.28" futures-timer = "3.0" diff --git a/examples/file-sharing/Cargo.toml b/examples/file-sharing/Cargo.toml index 348b62fd854..a2aa47cebb3 100644 --- a/examples/file-sharing/Cargo.toml +++ b/examples/file-sharing/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT" [dependencies] serde = { version = "1.0", features = ["derive"] } async-std = { version = "1.12", features = ["attributes"] } -clap = { version = "4.3.12", features = ["derive"] } +clap = { version = "4.3.21", features = ["derive"] } either = "1.9" env_logger = "0.10" futures = "0.3.28" diff --git a/examples/relay-server/Cargo.toml b/examples/relay-server/Cargo.toml index 263a25b34ba..296b50d31b9 100644 --- a/examples/relay-server/Cargo.toml +++ b/examples/relay-server/Cargo.toml @@ -6,7 +6,7 @@ publish = false license = "MIT" [dependencies] -clap = { version = "4.3.12", features = ["derive"] } +clap = { version = "4.3.21", features = ["derive"] } async-std = { version = "1.12", features = ["attributes"] } async-trait = "0.1" env_logger = "0.10.0" diff --git a/misc/keygen/Cargo.toml b/misc/keygen/Cargo.toml index 49eee550319..6de32895ccb 100644 --- a/misc/keygen/Cargo.toml +++ b/misc/keygen/Cargo.toml @@ -10,7 +10,7 @@ categories = ["network-programming", "asynchronous"] publish = false [dependencies] -clap = { version = "4.3.12", features = ["derive"] } +clap = { version = "4.3.21", features = ["derive"] } zeroize = "1" serde = { version = "1.0.183", features = ["derive"] } serde_json = "1.0.100" diff --git a/protocols/dcutr/Cargo.toml b/protocols/dcutr/Cargo.toml index 5ef81f0dcf3..2b9d3c3a669 100644 --- a/protocols/dcutr/Cargo.toml +++ b/protocols/dcutr/Cargo.toml @@ -27,7 +27,7 @@ void = "1" [dev-dependencies] async-std = { version = "1.12.0", features = ["attributes"] } -clap = { version = "4.3.12", features = ["derive"] } +clap = { version = "4.3.21", features = ["derive"] } env_logger = "0.10.0" libp2p-dns = { workspace = true, features = ["async-std"] } libp2p-identify = { workspace = true } diff --git a/protocols/perf/Cargo.toml b/protocols/perf/Cargo.toml index 758b8a52c9e..499cfd82834 100644 --- a/protocols/perf/Cargo.toml +++ b/protocols/perf/Cargo.toml @@ -13,7 +13,7 @@ categories = ["network-programming", "asynchronous"] [dependencies] anyhow = "1" async-trait = "0.1" -clap = { version = "4.3.12", features = ["derive"] } +clap = { version = "4.3.21", features = ["derive"] } env_logger = "0.10.0" futures = "0.3.28" instant = "0.1.12" From c2648d775ac0c25256738fda3cf94c3cd1ace093 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 09:38:56 +0000 Subject: [PATCH 41/44] deps: bump async-trait from 0.1.72 to 0.1.73 Pull-Request: #4321. --- Cargo.lock | 4 ++-- swarm-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f84c97fd456..137752fcb9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -484,9 +484,9 @@ checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" [[package]] name = "async-trait" -version = "0.1.72" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", diff --git a/swarm-test/Cargo.toml b/swarm-test/Cargo.toml index 69aa312b428..e762183b6be 100644 --- a/swarm-test/Cargo.toml +++ b/swarm-test/Cargo.toml @@ -12,7 +12,7 @@ categories = ["network-programming", "asynchronous"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -async-trait = "0.1.72" +async-trait = "0.1.73" libp2p-core = { workspace = true } libp2p-identity = { workspace = true } libp2p-plaintext = { workspace = true } From a648b273b244375c052db017d916d6ccf8171d1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 09:57:25 +0000 Subject: [PATCH 42/44] deps: bump webpki-roots from 0.25.1 to 0.25.2 Pull-Request: #4320. --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 137752fcb9d..079c4a93aa1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3349,7 +3349,7 @@ dependencies = [ "rw-stream-sink", "soketto", "url", - "webpki-roots 0.25.1", + "webpki-roots 0.25.2", ] [[package]] @@ -6305,9 +6305,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9c6eda1c830a36f361e7721c87fd79ea84293b54f8c48c959f85ec636f0f196" +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" [[package]] name = "webrtc" From 2c4c961d693414dccf338cbe8fe327bc57279609 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 10:16:13 +0000 Subject: [PATCH 43/44] deps: bump log from 0.4.19 to 0.4.20 Pull-Request: #4322. --- Cargo.lock | 4 ++-- examples/metrics/Cargo.toml | 2 +- protocols/gossipsub/Cargo.toml | 2 +- protocols/identify/Cargo.toml | 2 +- protocols/mdns/Cargo.toml | 2 +- protocols/ping/Cargo.toml | 2 +- protocols/request-response/Cargo.toml | 2 +- swarm-test/Cargo.toml | 2 +- transports/dns/Cargo.toml | 2 +- transports/plaintext/Cargo.toml | 2 +- transports/pnet/Cargo.toml | 2 +- transports/tcp/Cargo.toml | 2 +- transports/uds/Cargo.toml | 2 +- transports/websocket/Cargo.toml | 2 +- transports/webtransport-websys/Cargo.toml | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 079c4a93aa1..19c99e8d974 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3463,9 +3463,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" dependencies = [ "value-bag", ] diff --git a/examples/metrics/Cargo.toml b/examples/metrics/Cargo.toml index f883127ee25..b81c0142fd9 100644 --- a/examples/metrics/Cargo.toml +++ b/examples/metrics/Cargo.toml @@ -10,6 +10,6 @@ env_logger = "0.10.0" futures = "0.3.27" hyper = { version = "0.14", features = ["server", "tcp", "http1"] } libp2p = { path = "../../libp2p", features = ["async-std", "metrics", "ping", "noise", "identify", "tcp", "yamux", "macros"] } -log = "0.4.19" +log = "0.4.20" tokio = { version = "1", features = ["rt-multi-thread"] } prometheus-client = "0.21.2" diff --git a/protocols/gossipsub/Cargo.toml b/protocols/gossipsub/Cargo.toml index a9cf8b2a2fe..acbab0c82e9 100644 --- a/protocols/gossipsub/Cargo.toml +++ b/protocols/gossipsub/Cargo.toml @@ -28,7 +28,7 @@ instant = "0.1.12" libp2p-core = { workspace = true } libp2p-identity = { workspace = true } libp2p-swarm = { workspace = true } -log = "0.4.19" +log = "0.4.20" quick-protobuf = "0.8" quick-protobuf-codec = { workspace = true } rand = "0.8" diff --git a/protocols/identify/Cargo.toml b/protocols/identify/Cargo.toml index 61d38ede934..fb207dd7e8a 100644 --- a/protocols/identify/Cargo.toml +++ b/protocols/identify/Cargo.toml @@ -17,7 +17,7 @@ futures-timer = "3.0.2" libp2p-core = { workspace = true } libp2p-swarm = { workspace = true } libp2p-identity = { workspace = true } -log = "0.4.19" +log = "0.4.20" lru = "0.11.0" quick-protobuf-codec = { workspace = true } quick-protobuf = "0.8" diff --git a/protocols/mdns/Cargo.toml b/protocols/mdns/Cargo.toml index 338e410b5b5..14a30e6b923 100644 --- a/protocols/mdns/Cargo.toml +++ b/protocols/mdns/Cargo.toml @@ -18,7 +18,7 @@ if-watch = "3.0.1" libp2p-core = { workspace = true } libp2p-swarm = { workspace = true } libp2p-identity = { workspace = true } -log = "0.4.19" +log = "0.4.20" rand = "0.8.3" smallvec = "1.11.0" socket2 = { version = "0.5.3", features = ["all"] } diff --git a/protocols/ping/Cargo.toml b/protocols/ping/Cargo.toml index aebc473512b..f66222efff7 100644 --- a/protocols/ping/Cargo.toml +++ b/protocols/ping/Cargo.toml @@ -18,7 +18,7 @@ instant = "0.1.12" libp2p-core = { workspace = true } libp2p-swarm = { workspace = true } libp2p-identity = { workspace = true } -log = "0.4.19" +log = "0.4.20" rand = "0.8" void = "1.0" diff --git a/protocols/request-response/Cargo.toml b/protocols/request-response/Cargo.toml index ddb87316f86..40e65f1cccc 100644 --- a/protocols/request-response/Cargo.toml +++ b/protocols/request-response/Cargo.toml @@ -23,7 +23,7 @@ serde = { version = "1.0", optional = true} serde_json = { version = "1.0.100", optional = true } smallvec = "1.11.0" void = "1.0.2" -log = "0.4.19" +log = "0.4.20" [features] json = ["dep:serde", "dep:serde_json", "libp2p-swarm/macros"] diff --git a/swarm-test/Cargo.toml b/swarm-test/Cargo.toml index e762183b6be..7b3faa453f5 100644 --- a/swarm-test/Cargo.toml +++ b/swarm-test/Cargo.toml @@ -20,6 +20,6 @@ libp2p-swarm = { workspace = true } libp2p-tcp = { workspace = true, features = ["async-io"] } libp2p-yamux = { workspace = true } futures = "0.3.28" -log = "0.4.19" +log = "0.4.20" rand = "0.8.5" futures-timer = "3.0.2" diff --git a/transports/dns/Cargo.toml b/transports/dns/Cargo.toml index d1afd0411f9..a85307aad32 100644 --- a/transports/dns/Cargo.toml +++ b/transports/dns/Cargo.toml @@ -13,7 +13,7 @@ categories = ["network-programming", "asynchronous"] [dependencies] libp2p-core = { workspace = true } libp2p-identity = { workspace = true } -log = "0.4.19" +log = "0.4.20" futures = "0.3.28" async-std-resolver = { version = "0.22", optional = true } parking_lot = "0.12.0" diff --git a/transports/plaintext/Cargo.toml b/transports/plaintext/Cargo.toml index 6990a846c27..1f15004d3f4 100644 --- a/transports/plaintext/Cargo.toml +++ b/transports/plaintext/Cargo.toml @@ -16,7 +16,7 @@ bytes = "1" futures = "0.3.28" libp2p-core = { workspace = true } libp2p-identity = { workspace = true } -log = "0.4.19" +log = "0.4.20" quick-protobuf = "0.8" unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] } diff --git a/transports/pnet/Cargo.toml b/transports/pnet/Cargo.toml index 11c27266057..831b3f599e7 100644 --- a/transports/pnet/Cargo.toml +++ b/transports/pnet/Cargo.toml @@ -12,7 +12,7 @@ categories = ["network-programming", "asynchronous"] [dependencies] futures = "0.3.28" -log = "0.4.19" +log = "0.4.20" salsa20 = "0.10" sha3 = "0.10" rand = "0.8" diff --git a/transports/tcp/Cargo.toml b/transports/tcp/Cargo.toml index 5103ee9576a..5aa01133335 100644 --- a/transports/tcp/Cargo.toml +++ b/transports/tcp/Cargo.toml @@ -18,7 +18,7 @@ if-watch = "3.0.1" libc = "0.2.147" libp2p-core = { workspace = true } libp2p-identity = { workspace = true } -log = "0.4.19" +log = "0.4.20" socket2 = { version = "0.5.3", features = ["all"] } tokio = { version = "1.31.0", default-features = false, features = ["net"], optional = true } diff --git a/transports/uds/Cargo.toml b/transports/uds/Cargo.toml index a01cc9c6916..269eced5fa3 100644 --- a/transports/uds/Cargo.toml +++ b/transports/uds/Cargo.toml @@ -13,7 +13,7 @@ categories = ["network-programming", "asynchronous"] [dependencies] async-std = { version = "1.6.2", optional = true } libp2p-core = { workspace = true } -log = "0.4.19" +log = "0.4.20" futures = "0.3.28" tokio = { version = "1.31", default-features = false, features = ["net"], optional = true } diff --git a/transports/websocket/Cargo.toml b/transports/websocket/Cargo.toml index 3ebeb83bc16..39a96d69901 100644 --- a/transports/websocket/Cargo.toml +++ b/transports/websocket/Cargo.toml @@ -16,7 +16,7 @@ either = "1.9.0" futures = "0.3.28" libp2p-core = { workspace = true } libp2p-identity = { workspace = true } -log = "0.4.19" +log = "0.4.20" parking_lot = "0.12.0" quicksink = "0.1" rw-stream-sink = { workspace = true } diff --git a/transports/webtransport-websys/Cargo.toml b/transports/webtransport-websys/Cargo.toml index 21ca077fce9..695a62f4cde 100644 --- a/transports/webtransport-websys/Cargo.toml +++ b/transports/webtransport-websys/Cargo.toml @@ -19,7 +19,7 @@ js-sys = "0.3.64" libp2p-core = { workspace = true } libp2p-identity = { workspace = true } libp2p-noise = { workspace = true } -log = "0.4.19" +log = "0.4.20" multiaddr = { workspace = true } multihash = { workspace = true } send_wrapper = { version = "0.6.0", features = ["futures"] } From cbdbaa836e1159fb4e8b20e76c32f1af5ec66926 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Thu, 17 Aug 2023 09:54:29 +0200 Subject: [PATCH 44/44] feat(quic): promote to stable release - Cut a stable release of `libp2p-quic`. - Export `libp2p-quic` as `libp2p::quic`. - Update examples to use `libp2p-quic` through `libp2p`. Pull-Request: #4325. --- Cargo.lock | 9 +++------ Cargo.toml | 2 +- examples/chat-example/Cargo.toml | 3 +-- examples/chat-example/src/main.rs | 3 +-- examples/dcutr/Cargo.toml | 3 +-- examples/dcutr/src/main.rs | 3 +-- examples/relay-server/Cargo.toml | 3 +-- examples/relay-server/src/main.rs | 3 +-- interop-tests/Cargo.toml | 3 +-- interop-tests/src/arch.rs | 3 +-- libp2p/CHANGELOG.md | 4 ++++ libp2p/Cargo.toml | 9 ++++++--- libp2p/src/lib.rs | 3 +++ transports/quic/CHANGELOG.md | 4 ++++ transports/quic/Cargo.toml | 2 +- 15 files changed, 30 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19c99e8d974..459afe3ece5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -831,7 +831,6 @@ dependencies = [ "env_logger 0.10.0", "futures", "libp2p", - "libp2p-quic", ] [[package]] @@ -1309,7 +1308,6 @@ dependencies = [ "futures", "futures-timer", "libp2p", - "libp2p-quic", "log", ] @@ -2354,7 +2352,6 @@ dependencies = [ "instant", "libp2p", "libp2p-mplex", - "libp2p-quic", "libp2p-webrtc", "log", "mime_guess", @@ -2512,7 +2509,7 @@ checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" [[package]] name = "libp2p" -version = "0.52.2" +version = "0.52.3" dependencies = [ "async-std", "async-trait", @@ -2543,6 +2540,7 @@ dependencies = [ "libp2p-ping", "libp2p-plaintext", "libp2p-pnet", + "libp2p-quic", "libp2p-relay", "libp2p-rendezvous", "libp2p-request-response", @@ -3058,7 +3056,7 @@ dependencies = [ [[package]] name = "libp2p-quic" -version = "0.9.2-alpha" +version = "0.9.2" dependencies = [ "async-std", "bytes", @@ -4610,7 +4608,6 @@ dependencies = [ "env_logger 0.10.0", "futures", "libp2p", - "libp2p-quic", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index fb503a12e61..03b3833033b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,7 +85,7 @@ libp2p-perf = { version = "0.2.0", path = "protocols/perf" } libp2p-ping = { version = "0.43.0", path = "protocols/ping" } libp2p-plaintext = { version = "0.40.0", path = "transports/plaintext" } libp2p-pnet = { version = "0.23.0", path = "transports/pnet" } -libp2p-quic = { version = "0.9.2-alpha", path = "transports/quic" } +libp2p-quic = { version = "0.9.2", path = "transports/quic" } libp2p-relay = { version = "0.16.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" } diff --git a/examples/chat-example/Cargo.toml b/examples/chat-example/Cargo.toml index 1d865711ea8..cfc417cf3cb 100644 --- a/examples/chat-example/Cargo.toml +++ b/examples/chat-example/Cargo.toml @@ -10,5 +10,4 @@ async-std = { version = "1.12", features = ["attributes"] } async-trait = "0.1" env_logger = "0.10.0" futures = "0.3.28" -libp2p = { path = "../../libp2p", features = ["async-std", "gossipsub", "mdns", "noise", "macros", "tcp", "yamux"] } -libp2p-quic = { path = "../../transports/quic", features = ["async-std"] } +libp2p = { path = "../../libp2p", features = ["async-std", "gossipsub", "mdns", "noise", "macros", "tcp", "yamux", "quic"] } diff --git a/examples/chat-example/src/main.rs b/examples/chat-example/src/main.rs index 9dc2d92a56f..95a16f388d9 100644 --- a/examples/chat-example/src/main.rs +++ b/examples/chat-example/src/main.rs @@ -24,12 +24,11 @@ use async_std::io; use futures::{future::Either, prelude::*, select}; use libp2p::{ core::{muxing::StreamMuxerBox, transport::OrTransport, upgrade}, - gossipsub, identity, mdns, noise, + gossipsub, identity, mdns, noise, quic, swarm::NetworkBehaviour, swarm::{SwarmBuilder, SwarmEvent}, tcp, yamux, PeerId, Transport, }; -use libp2p_quic as quic; use std::collections::hash_map::DefaultHasher; use std::error::Error; use std::hash::{Hash, Hasher}; diff --git a/examples/dcutr/Cargo.toml b/examples/dcutr/Cargo.toml index 38394ee3e2c..7a13dd23910 100644 --- a/examples/dcutr/Cargo.toml +++ b/examples/dcutr/Cargo.toml @@ -10,6 +10,5 @@ clap = { version = "4.3.21", features = ["derive"] } env_logger = "0.10.0" futures = "0.3.28" futures-timer = "3.0" -libp2p = { path = "../../libp2p", features = ["async-std", "dns", "dcutr", "identify", "macros", "noise", "ping", "relay", "rendezvous", "tcp", "tokio", "yamux"] } -libp2p-quic = { path = "../../transports/quic", features = ["async-std"] } +libp2p = { path = "../../libp2p", features = ["async-std", "dns", "dcutr", "identify", "macros", "noise", "ping", "quic", "relay", "rendezvous", "tcp", "tokio", "yamux"] } log = "0.4" diff --git a/examples/dcutr/src/main.rs b/examples/dcutr/src/main.rs index 8359bb1902a..8837df783b4 100644 --- a/examples/dcutr/src/main.rs +++ b/examples/dcutr/src/main.rs @@ -35,11 +35,10 @@ use libp2p::{ }, dcutr, dns::DnsConfig, - identify, identity, noise, ping, relay, + identify, identity, noise, ping, quic, relay, swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent}, tcp, yamux, PeerId, }; -use libp2p_quic as quic; use log::info; use std::error::Error; use std::str::FromStr; diff --git a/examples/relay-server/Cargo.toml b/examples/relay-server/Cargo.toml index 296b50d31b9..62d3cc0a710 100644 --- a/examples/relay-server/Cargo.toml +++ b/examples/relay-server/Cargo.toml @@ -11,5 +11,4 @@ async-std = { version = "1.12", features = ["attributes"] } async-trait = "0.1" env_logger = "0.10.0" futures = "0.3.28" -libp2p = { path = "../../libp2p", features = ["async-std", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay"] } -libp2p-quic = { path = "../../transports/quic", features = ["async-std"] } +libp2p = { path = "../../libp2p", features = ["async-std", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay", "quic"] } diff --git a/examples/relay-server/src/main.rs b/examples/relay-server/src/main.rs index 6a1d956b5a5..7526a076e92 100644 --- a/examples/relay-server/src/main.rs +++ b/examples/relay-server/src/main.rs @@ -31,11 +31,10 @@ use libp2p::{ core::{Multiaddr, Transport}, identify, identity, identity::PeerId, - noise, ping, relay, + noise, ping, quic, relay, swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent}, tcp, }; -use libp2p_quic as quic; use std::error::Error; use std::net::{Ipv4Addr, Ipv6Addr}; diff --git a/interop-tests/Cargo.toml b/interop-tests/Cargo.toml index d03c0403f49..1c9ef732e7c 100644 --- a/interop-tests/Cargo.toml +++ b/interop-tests/Cargo.toml @@ -19,8 +19,7 @@ rand = "0.8.5" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] axum = "0.6" -libp2p = { path = "../libp2p", features = ["ping", "noise", "tls", "rsa", "macros", "websocket", "tokio", "yamux", "tcp", "dns", "identify"] } -libp2p-quic = { workspace = true, features = ["tokio"] } +libp2p = { path = "../libp2p", features = ["ping", "noise", "tls", "rsa", "macros", "websocket", "tokio", "yamux", "tcp", "dns", "identify", "quic"] } libp2p-webrtc = { workspace = true, features = ["tokio"] } libp2p-mplex = { path = "../muxers/mplex" } mime_guess = "2.0" diff --git a/interop-tests/src/arch.rs b/interop-tests/src/arch.rs index 2f4a7495a04..2b2181f2459 100644 --- a/interop-tests/src/arch.rs +++ b/interop-tests/src/arch.rs @@ -26,9 +26,8 @@ pub(crate) mod native { use libp2p::identity::Keypair; use libp2p::swarm::{NetworkBehaviour, SwarmBuilder}; use libp2p::websocket::WsConfig; - use libp2p::{noise, tcp, tls, yamux, PeerId, Transport as _}; + use libp2p::{noise, quic, tcp, tls, yamux, PeerId, Transport as _}; use libp2p_mplex as mplex; - use libp2p_quic as quic; use libp2p_webrtc as webrtc; use redis::AsyncCommands; diff --git a/libp2p/CHANGELOG.md b/libp2p/CHANGELOG.md index 50774aaa97f..642d4103729 100644 --- a/libp2p/CHANGELOG.md +++ b/libp2p/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.52.3 - unreleased + +- Add `libp2p-quic` stable release. + ## 0.52.2 - Include gossipsub when compiling for wasm. diff --git a/libp2p/Cargo.toml b/libp2p/Cargo.toml index e057c9e8dd4..f02ec1c6d8a 100644 --- a/libp2p/Cargo.toml +++ b/libp2p/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p" edition = "2021" rust-version = "1.65.0" description = "Peer-to-peer networking library" -version = "0.52.2" +version = "0.52.3" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" @@ -33,6 +33,7 @@ full = [ "ping", "plaintext", "pnet", + "quic", "relay", "rendezvous", "request-response", @@ -51,7 +52,7 @@ full = [ "yamux", ] -async-std = ["libp2p-swarm/async-std", "libp2p-mdns?/async-io", "libp2p-tcp?/async-io", "libp2p-dns?/async-std"] +async-std = ["libp2p-swarm/async-std", "libp2p-mdns?/async-io", "libp2p-tcp?/async-io", "libp2p-dns?/async-std", "libp2p-quic?/async-std"] autonat = ["dep:libp2p-autonat"] cbor = ["libp2p-request-response?/cbor"] dcutr = ["dep:libp2p-dcutr", "libp2p-metrics?/dcutr"] @@ -72,6 +73,7 @@ noise = ["dep:libp2p-noise"] ping = ["dep:libp2p-ping", "libp2p-metrics?/ping"] plaintext = ["dep:libp2p-plaintext"] pnet = ["dep:libp2p-pnet"] +quic = ["dep:libp2p-quic"] relay = ["dep:libp2p-relay", "libp2p-metrics?/relay"] rendezvous = ["dep:libp2p-rendezvous"] request-response = ["dep:libp2p-request-response"] @@ -80,7 +82,7 @@ secp256k1 = ["libp2p-identity/secp256k1"] serde = ["libp2p-core/serde", "libp2p-kad?/serde", "libp2p-gossipsub?/serde"] tcp = ["dep:libp2p-tcp"] tls = ["dep:libp2p-tls"] -tokio = ["libp2p-swarm/tokio", "libp2p-mdns?/tokio", "libp2p-tcp?/tokio", "libp2p-dns?/tokio"] +tokio = ["libp2p-swarm/tokio", "libp2p-mdns?/tokio", "libp2p-tcp?/tokio", "libp2p-dns?/tokio", "libp2p-quic?/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-ext = ["dep:libp2p-wasm-ext"] @@ -127,6 +129,7 @@ libp2p-deflate = { workspace = true, optional = true } libp2p-dns = { workspace = true, optional = true } libp2p-mdns = { workspace = true, optional = true } libp2p-memory-connection-limits = { workspace = true, optional = true } +libp2p-quic = { workspace = true, optional = true } libp2p-tcp = { workspace = true, optional = true } libp2p-tls = { workspace = true, optional = true } libp2p-uds = { workspace = true, optional = true } diff --git a/libp2p/src/lib.rs b/libp2p/src/lib.rs index 9ec1fe48af4..349427ffdfe 100644 --- a/libp2p/src/lib.rs +++ b/libp2p/src/lib.rs @@ -98,6 +98,9 @@ pub use libp2p_plaintext as plaintext; #[cfg(feature = "pnet")] #[doc(inline)] pub use libp2p_pnet as pnet; +#[cfg(feature = "quic")] +#[cfg(not(target_arch = "wasm32"))] +pub use libp2p_quic as quic; #[cfg(feature = "relay")] #[doc(inline)] pub use libp2p_relay as relay; diff --git a/transports/quic/CHANGELOG.md b/transports/quic/CHANGELOG.md index 66a6dec3a2e..c7da2895b58 100644 --- a/transports/quic/CHANGELOG.md +++ b/transports/quic/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.2 - unreleased + +- Cut stable release. + ## 0.9.2-alpha - Add support for reusing an existing socket when dialing localhost address. diff --git a/transports/quic/Cargo.toml b/transports/quic/Cargo.toml index 2500e5d7b6f..13fbe9bb3c5 100644 --- a/transports/quic/Cargo.toml +++ b/transports/quic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libp2p-quic" -version = "0.9.2-alpha" +version = "0.9.2" authors = ["Parity Technologies "] edition = "2021" rust-version = { workspace = true }