diff --git a/Cargo.lock b/Cargo.lock index f0b9391e2ab..4061e65ec67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2968,7 +2968,6 @@ name = "libp2p-mdns" version = "0.47.0" dependencies = [ "async-io", - "async-std", "futures", "hickory-proto", "if-watch", diff --git a/libp2p/Cargo.toml b/libp2p/Cargo.toml index 7ab4bdc5429..c0c326570b2 100644 --- a/libp2p/Cargo.toml +++ b/libp2p/Cargo.toml @@ -53,7 +53,7 @@ full = [ "upnp", ] -async-std = [ "libp2p-swarm/async-std", "libp2p-mdns?/async-io", "libp2p-tcp?/async-io", "libp2p-dns?/async-std", "libp2p-quic?/async-std",] +async-std = [ "libp2p-swarm/async-std", "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"] diff --git a/protocols/mdns/Cargo.toml b/protocols/mdns/Cargo.toml index dbf66abe61c..519458ec916 100644 --- a/protocols/mdns/Cargo.toml +++ b/protocols/mdns/Cargo.toml @@ -11,7 +11,6 @@ keywords = ["peer-to-peer", "libp2p", "networking"] categories = ["network-programming", "asynchronous"] [dependencies] -async-std = { version = "1.12.0", optional = true } async-io = { version = "2.3.3", optional = true } futures = { workspace = true } if-watch = { workspace = true } @@ -27,19 +26,13 @@ hickory-proto = { workspace = true, features = ["mdns"] } [features] tokio = ["dep:tokio", "if-watch/tokio"] -async-io = ["dep:async-io", "dep:async-std", "if-watch/smol"] [dev-dependencies] -async-std = { version = "1.9.0", features = ["attributes"] } -libp2p-swarm = { workspace = true, features = ["tokio", "async-std"] } +libp2p-swarm = { workspace = true, features = ["tokio"] } tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread", "time"] } libp2p-swarm-test = { path = "../../swarm-test" } tracing-subscriber = { workspace = true, features = ["env-filter"] } -[[test]] -name = "use-async-std" -required-features = ["async-io"] - [[test]] name = "use-tokio" required-features = ["tokio"] diff --git a/protocols/mdns/src/behaviour.rs b/protocols/mdns/src/behaviour.rs index 68e28cf3d63..82af16fe1be 100644 --- a/protocols/mdns/src/behaviour.rs +++ b/protocols/mdns/src/behaviour.rs @@ -78,44 +78,6 @@ pub trait Abort { fn abort(self); } -/// The type of a [`Behaviour`] using the `async-io` implementation. -#[cfg(feature = "async-io")] -pub mod async_io { - use std::future::Future; - - use async_std::task::JoinHandle; - use if_watch::smol::IfWatcher; - - use super::Provider; - use crate::behaviour::{socket::asio::AsyncUdpSocket, timer::asio::AsyncTimer, Abort}; - - #[doc(hidden)] - pub enum AsyncIo {} - - impl Provider for AsyncIo { - type Socket = AsyncUdpSocket; - type Timer = AsyncTimer; - type Watcher = IfWatcher; - type TaskHandle = JoinHandle<()>; - - fn new_watcher() -> Result { - IfWatcher::new() - } - - fn spawn(task: impl Future + Send + 'static) -> JoinHandle<()> { - async_std::task::spawn(task) - } - } - - impl Abort for JoinHandle<()> { - fn abort(self) { - async_std::task::spawn(self.cancel()); - } - } - - pub type Behaviour = super::Behaviour; -} - /// The type of a [`Behaviour`] using the `tokio` implementation. #[cfg(feature = "tokio")] pub mod tokio { diff --git a/protocols/mdns/src/behaviour/socket.rs b/protocols/mdns/src/behaviour/socket.rs index cf11450fb4b..02624c2ad03 100644 --- a/protocols/mdns/src/behaviour/socket.rs +++ b/protocols/mdns/src/behaviour/socket.rs @@ -50,49 +50,6 @@ pub trait AsyncSocket: Unpin + Send + 'static { ) -> Poll>; } -#[cfg(feature = "async-io")] -pub(crate) mod asio { - use async_io::Async; - use futures::FutureExt; - - use super::*; - - /// AsyncIo UdpSocket - pub(crate) type AsyncUdpSocket = Async; - impl AsyncSocket for AsyncUdpSocket { - fn from_std(socket: UdpSocket) -> std::io::Result { - Async::new(socket) - } - - fn poll_read( - &mut self, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - // Poll receive socket. - futures::ready!(self.poll_readable(cx))?; - match self.recv_from(buf).now_or_never() { - Some(data) => Poll::Ready(data), - None => Poll::Pending, - } - } - - fn poll_write( - &mut self, - cx: &mut Context, - packet: &[u8], - to: SocketAddr, - ) -> Poll> { - futures::ready!(self.poll_writable(cx))?; - match self.send_to(packet, to).now_or_never() { - Some(Ok(_)) => Poll::Ready(Ok(())), - Some(Err(err)) => Poll::Ready(Err(err)), - None => Poll::Pending, - } - } - } -} - #[cfg(feature = "tokio")] pub(crate) mod tokio { use ::tokio::{io::ReadBuf, net::UdpSocket as TkUdpSocket}; diff --git a/protocols/mdns/src/behaviour/timer.rs b/protocols/mdns/src/behaviour/timer.rs index 5fdb1beffae..cfc015adae8 100644 --- a/protocols/mdns/src/behaviour/timer.rs +++ b/protocols/mdns/src/behaviour/timer.rs @@ -22,7 +22,7 @@ use std::time::{Duration, Instant}; /// Simple wrapper for the different type of timers #[derive(Debug)] -#[cfg(any(feature = "async-io", feature = "tokio"))] +#[cfg(feature = "tokio")] pub struct Timer { inner: T, } @@ -40,49 +40,6 @@ pub trait Builder: Send + Unpin + 'static { fn interval_at(start: Instant, duration: Duration) -> Self; } -#[cfg(feature = "async-io")] -pub(crate) mod asio { - use std::{ - pin::Pin, - task::{Context, Poll}, - }; - - use async_io::Timer as AsioTimer; - use futures::Stream; - - use super::*; - - /// Async Timer - pub(crate) type AsyncTimer = Timer; - impl Builder for AsyncTimer { - fn at(instant: Instant) -> Self { - Self { - inner: AsioTimer::at(instant), - } - } - - fn interval(duration: Duration) -> Self { - Self { - inner: AsioTimer::interval(duration), - } - } - - fn interval_at(start: Instant, duration: Duration) -> Self { - Self { - inner: AsioTimer::interval_at(start, duration), - } - } - } - - impl Stream for AsyncTimer { - type Item = Instant; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.inner).poll_next(cx) - } - } -} - #[cfg(feature = "tokio")] pub(crate) mod tokio { use std::{ diff --git a/protocols/mdns/src/lib.rs b/protocols/mdns/src/lib.rs index a0086a0e2d5..836a6b2426a 100644 --- a/protocols/mdns/src/lib.rs +++ b/protocols/mdns/src/lib.rs @@ -28,8 +28,8 @@ //! //! # Usage //! -//! This crate provides a `Mdns` and `TokioMdns`, depending on the enabled features, which -//! implements the `NetworkBehaviour` trait. This struct will automatically discover other +//! This crate provides `TokioMdns` +//! which implements the `NetworkBehaviour` trait. This struct will automatically discover other //! libp2p nodes on the local network. #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] @@ -40,8 +40,6 @@ use std::{ }; mod behaviour; -#[cfg(feature = "async-io")] -pub use crate::behaviour::async_io; #[cfg(feature = "tokio")] pub use crate::behaviour::tokio; pub use crate::behaviour::{Behaviour, Event}; diff --git a/protocols/mdns/tests/use-async-std.rs b/protocols/mdns/tests/use-async-std.rs deleted file mode 100644 index df08b39af07..00000000000 --- a/protocols/mdns/tests/use-async-std.rs +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2018 Parity Technologies (UK) Ltd. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE.use futures::StreamExt; - -use std::time::Duration; - -use futures::future::Either; -use libp2p_mdns::{async_io::Behaviour, Config, Event}; -use libp2p_swarm::{Swarm, SwarmEvent}; -use libp2p_swarm_test::SwarmExt as _; -use tracing_subscriber::EnvFilter; - -#[async_std::test] -async fn test_discovery_async_std_ipv4() { - let _ = tracing_subscriber::fmt() - .with_env_filter(EnvFilter::from_default_env()) - .try_init(); - - run_discovery_test(Config::default()).await -} - -#[async_std::test] -async fn test_discovery_async_std_ipv6() { - let _ = tracing_subscriber::fmt() - .with_env_filter(EnvFilter::from_default_env()) - .try_init(); - - let config = Config { - enable_ipv6: true, - ..Default::default() - }; - run_discovery_test(config).await -} - -#[async_std::test] -async fn test_expired_async_std() { - let _ = tracing_subscriber::fmt() - .with_env_filter(EnvFilter::from_default_env()) - .try_init(); - - let config = Config { - ttl: Duration::from_secs(1), - query_interval: Duration::from_secs(10), - ..Default::default() - }; - - let mut a = create_swarm(config.clone()).await; - let a_peer_id = *a.local_peer_id(); - - let mut b = create_swarm(config).await; - let b_peer_id = *b.local_peer_id(); - - loop { - match futures::future::select(a.next_behaviour_event(), b.next_behaviour_event()).await { - Either::Left((Event::Expired(peers), _)) => { - if peers.into_iter().any(|(p, _)| p == b_peer_id) { - return; - } - } - Either::Right((Event::Expired(peers), _)) => { - if peers.into_iter().any(|(p, _)| p == a_peer_id) { - return; - } - } - _ => {} - } - } -} - -#[async_std::test] -async fn test_no_expiration_on_close_async_std() { - let _ = tracing_subscriber::fmt() - .with_env_filter(EnvFilter::from_default_env()) - .try_init(); - let config = Config { - ttl: Duration::from_secs(120), - query_interval: Duration::from_secs(10), - ..Default::default() - }; - - let mut a = create_swarm(config.clone()).await; - - let b = create_swarm(config).await; - let b_peer_id = *b.local_peer_id(); - async_std::task::spawn(b.loop_on_next()); - - // 1. Connect via address from mDNS event - loop { - if let Event::Discovered(peers) = a.next_behaviour_event().await { - if let Some((_, addr)) = peers.into_iter().find(|(p, _)| p == &b_peer_id) { - a.dial_and_wait(addr).await; - break; - } - } - } - - // 2. Close connection - let _ = a.disconnect_peer_id(b_peer_id); - a.wait(|event| { - matches!(event, SwarmEvent::ConnectionClosed { peer_id, .. } if peer_id == b_peer_id) - .then_some(()) - }) - .await; - - // 3. Ensure we can still dial via `PeerId`. - a.dial(b_peer_id).unwrap(); - a.wait(|event| { - matches!(event, SwarmEvent::ConnectionEstablished { peer_id, .. } if peer_id == b_peer_id) - .then_some(()) - }) - .await; -} - -async fn run_discovery_test(config: Config) { - let mut a = create_swarm(config.clone()).await; - let a_peer_id = *a.local_peer_id(); - - let mut b = create_swarm(config).await; - let b_peer_id = *b.local_peer_id(); - - let mut discovered_a = false; - let mut discovered_b = false; - - while !discovered_a && !discovered_b { - match futures::future::select(a.next_behaviour_event(), b.next_behaviour_event()).await { - Either::Left((Event::Discovered(peers), _)) => { - if peers.into_iter().any(|(p, _)| p == b_peer_id) { - discovered_b = true; - } - } - Either::Right((Event::Discovered(peers), _)) => { - if peers.into_iter().any(|(p, _)| p == a_peer_id) { - discovered_a = true; - } - } - _ => {} - } - } -} - -async fn create_swarm(config: Config) -> Swarm { - let mut swarm = - Swarm::new_ephemeral(|key| Behaviour::new(config, key.public().to_peer_id()).unwrap()); - - // Manually listen on all interfaces because mDNS only works for non-loopback addresses. - let expected_listener_id = swarm - .listen_on("/ip4/0.0.0.0/tcp/0".parse().unwrap()) - .unwrap(); - - swarm - .wait(|e| match e { - SwarmEvent::NewListenAddr { listener_id, .. } => { - (listener_id == expected_listener_id).then_some(()) - } - _ => None, - }) - .await; - - swarm -}