From f134c8b0bddfa713e1e36e0b0d49eda33caf4aff Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 16 May 2022 01:36:54 +0200 Subject: [PATCH 01/47] core/transport: remove Transport::Listener Remove `Transport::Listener: Stream`. Instead require the Transport itself to implement a stream-like API with `Transport::poll`. In case of multiple listeners, transports are now required to handle the multiple listener streams themselves internally. --- core/src/connection.rs | 19 --- core/src/transport.rs | 330 +++++++++++++++++++++++++++-------------- 2 files changed, 217 insertions(+), 132 deletions(-) diff --git a/core/src/connection.rs b/core/src/connection.rs index 3a8d54d04a1..91008408fe2 100644 --- a/core/src/connection.rs +++ b/core/src/connection.rs @@ -43,25 +43,6 @@ impl std::ops::Add for ConnectionId { } } -/// The ID of a single listener. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ListenerId(u64); - -impl ListenerId { - /// Creates a `ListenerId` from a non-negative integer. - pub fn new(id: u64) -> Self { - Self(id) - } -} - -impl std::ops::Add for ListenerId { - type Output = Self; - - fn add(self, other: u64) -> Self { - Self(self.0 + other) - } -} - /// The endpoint roles associated with a peer-to-peer communication channel. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum Endpoint { diff --git a/core/src/transport.rs b/core/src/transport.rs index ce64f2dd923..e015734c287 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -25,27 +25,33 @@ //! any desired protocols. The rest of the module defines combinators for //! modifying a transport through composition with other transports or protocol upgrades. -use crate::connection::ConnectedPoint; use futures::prelude::*; use multiaddr::Multiaddr; -use std::{error::Error, fmt}; +use std::{ + error::Error, + fmt, + pin::Pin, + task::{Context, Poll}, +}; pub mod and_then; -pub mod choice; +// pub mod choice; pub mod dummy; pub mod map; -pub mod map_err; +// pub mod map_err; pub mod memory; pub mod timeout; pub mod upgrade; mod boxed; -mod optional; +// mod optional; + +use crate::ConnectedPoint; pub use self::boxed::Boxed; -pub use self::choice::OrTransport; +// pub use self::choice::OrTransport; pub use self::memory::MemoryTransport; -pub use self::optional::OptionalTransport; +// pub use self::optional::OptionalTransport; pub use self::upgrade::Upgrade; /// A transport provides connection-oriented communication between two peers @@ -87,19 +93,6 @@ pub trait Transport { /// An error that occurred during connection setup. type Error: Error; - /// A stream of [`Output`](Transport::Output)s for inbound connections. - /// - /// An item should be produced whenever a connection is received at the lowest level of the - /// transport stack. The item must be a [`ListenerUpgrade`](Transport::ListenerUpgrade) future - /// that resolves to an [`Output`](Transport::Output) value once all protocol upgrades - /// have been applied. - /// - /// If this stream produces an error, it is considered fatal and the listener is killed. It - /// is possible to report non-fatal errors by producing a [`ListenerEvent::Error`]. - type Listener: Stream< - Item = Result, Self::Error>, - >; - /// A pending [`Output`](Transport::Output) for an inbound connection, /// obtained from the [`Listener`](Transport::Listener) stream. /// @@ -115,12 +108,20 @@ pub trait Transport { /// obtained from [dialing](Transport::dial). type Dial: Future>; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> + where + Self: Sized; + /// Listens on the given [`Multiaddr`], producing a stream of pending, inbound connections - /// and addresses this transport is listening on (cf. [`ListenerEvent`]). + /// and addresses this transport is listening on (cf. [`TransportEvent`]). /// /// Returning an error from the stream is considered fatal. The listener can also report - /// non-fatal errors by producing a [`ListenerEvent::Error`]. - fn listen_on(&mut self, addr: Multiaddr) -> Result> + /// non-fatal errors by producing a [`TransportEvent::Error`]. + fn listen_on( + &mut self, + id: ListenerId, + addr: Multiaddr, + ) -> Result<(), TransportError> where Self: Sized; @@ -152,9 +153,8 @@ pub trait Transport { /// Boxes the transport, including custom transport errors. fn boxed(self) -> boxed::Boxed where - Self: Transport + Sized + Send + Sync + 'static, + Self: Transport + Sized + Send + Sync + Unpin + 'static, Self::Dial: Send + 'static, - Self::Listener: Send + 'static, Self::ListenerUpgrade: Send + 'static, Self::Error: Send + Sync, { @@ -170,28 +170,28 @@ pub trait Transport { map::Map::new(self, f) } - /// Applies a function on the errors generated by the futures of the transport. - fn map_err(self, f: F) -> map_err::MapErr - where - Self: Sized, - F: FnOnce(Self::Error) -> E, - { - map_err::MapErr::new(self, f) - } - - /// Adds a fallback transport that is used when encountering errors - /// while establishing inbound or outbound connections. - /// - /// The returned transport will act like `self`, except that if `listen_on` or `dial` - /// return an error then `other` will be tried. - fn or_transport(self, other: U) -> OrTransport - where - Self: Sized, - U: Transport, - ::Error: 'static, - { - OrTransport::new(self, other) - } + // /// Applies a function on the errors generated by the futures of the transport. + // fn map_err(self, f: F) -> map_err::MapErr + // where + // Self: Sized, + // F: FnOnce(Self::Error) -> E, + // { + // map_err::MapErr::new(self, f) + // } + + // /// Adds a fallback transport that is used when encountering errors + // /// while establishing inbound or outbound connections. + // /// + // /// The returned transport will act like `self`, except that if `listen_on` or `dial` + // /// return an error then `other` will be tried. + // fn or_transport(self, other: U) -> OrTransport + // where + // Self: Sized, + // U: Transport, + // ::Error: 'static, + // { + // OrTransport::new(self, other) + // } /// Applies a function producing an asynchronous result to every connection /// created by this transport. @@ -221,92 +221,144 @@ pub trait Transport { } } -/// Event produced by [`Transport::Listener`]s. +/// The ID of a single listener. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct ListenerId(u64); + +impl ListenerId { + /// Creates a `ListenerId` from a non-negative integer. + pub fn new(id: u64) -> Self { + Self(id) + } +} + +impl std::ops::Add for ListenerId { + type Output = Self; + + fn add(self, other: u64) -> Self { + Self(self.0 + other) + } +} + +/// Event produced by [`Transport`]s. /// -/// Transports are expected to produce `Upgrade` events only for +/// Transports are expected to produce `Incoming` events only for /// listen addresses which have previously been announced via /// a `NewAddress` event and which have not been invalidated by /// an `AddressExpired` event yet. -#[derive(Clone, Debug, PartialEq)] -pub enum ListenerEvent { - /// The transport is listening on a new additional [`Multiaddr`]. - NewAddress(Multiaddr), - /// An upgrade, consisting of the upgrade future, the listener address and the remote address. - Upgrade { - /// The upgrade. - upgrade: TUpgr, - /// The local address which produced this upgrade. +pub enum TransportEvent { + /// A new address is being listened on. + NewAddress { + /// The listener that is listening on the new address. + listener_id: ListenerId, + /// The new address that is being listened on. + listen_addr: Multiaddr, + }, + /// An address is no longer being listened on. + AddressExpired { + /// The listener that is no longer listening on the address. + listener_id: ListenerId, + /// The new address that is being listened on. + listen_addr: Multiaddr, + }, + /// A connection is incoming on one of the listeners. + Incoming { + /// The listener that produced the upgrade. + listener_id: ListenerId, + /// The produced upgrade. + upgrade: T::ListenerUpgrade, + /// Local connection address. local_addr: Multiaddr, - /// The remote address which produced this upgrade. - remote_addr: Multiaddr, + /// Address used to send back data to the incoming client. + send_back_addr: Multiaddr, + }, + /// A listener closed. + Closed { + /// The ID of the listener that closed. + listener_id: ListenerId, + /// The addresses that the listener was listening on. + addresses: Vec, + /// Reason for the closure. Contains `Ok(())` if the stream produced `None`, or `Err` + /// if the stream produced an error. + reason: Result<(), T::Error>, }, - /// A [`Multiaddr`] is no longer used for listening. - AddressExpired(Multiaddr), - /// A non-fatal error has happened on the listener. + /// A listener errored. /// - /// This event should be generated in order to notify the user that something wrong has - /// happened. The listener, however, continues to run. - Error(TErr), + /// The listener will continue to be polled for new events and the event + /// is for informational purposes only. + Error { + /// The ID of the listener that errored. + listener_id: ListenerId, + /// The error value. + error: T::Error, + }, } -impl ListenerEvent { - /// In case this [`ListenerEvent`] is an upgrade, apply the given function - /// to the upgrade and multiaddress and produce another listener event - /// based the the function's result. - pub fn map(self, f: impl FnOnce(TUpgr) -> U) -> ListenerEvent { +impl TransportEvent { + pub fn map( + self, + map: impl FnOnce(T::ListenerUpgrade) -> U::ListenerUpgrade, + map_err: impl FnOnce(T::Error) -> U::Error, + ) -> TransportEvent { match self { - ListenerEvent::Upgrade { + TransportEvent::Incoming { + listener_id, upgrade, local_addr, - remote_addr, - } => ListenerEvent::Upgrade { - upgrade: f(upgrade), + send_back_addr, + } => TransportEvent::Incoming { + listener_id, + upgrade: map(upgrade), local_addr, - remote_addr, + send_back_addr, }, - ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a), - ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a), - ListenerEvent::Error(e) => ListenerEvent::Error(e), - } - } - - /// In case this [`ListenerEvent`] is an [`Error`](ListenerEvent::Error), - /// apply the given function to the error and produce another listener event based on the - /// function's result. - pub fn map_err(self, f: impl FnOnce(TErr) -> U) -> ListenerEvent { - match self { - ListenerEvent::Upgrade { - upgrade, - local_addr, - remote_addr, - } => ListenerEvent::Upgrade { - upgrade, - local_addr, - remote_addr, + TransportEvent::NewAddress { + listen_addr, + listener_id, + } => TransportEvent::NewAddress { + listen_addr, + listener_id, + }, + TransportEvent::AddressExpired { + listen_addr, + listener_id, + } => TransportEvent::AddressExpired { + listen_addr, + listener_id, + }, + TransportEvent::Error { listener_id, error } => TransportEvent::Error { + listener_id, + error: map_err(error), + }, + TransportEvent::Closed { + listener_id, + addresses, + reason, + } => TransportEvent::Closed { + listener_id, + addresses, + reason: reason.map_err(map_err), }, - ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a), - ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a), - ListenerEvent::Error(e) => ListenerEvent::Error(f(e)), } } /// Returns `true` if this is an `Upgrade` listener event. pub fn is_upgrade(&self) -> bool { - matches!(self, ListenerEvent::Upgrade { .. }) + matches!(self, TransportEvent::Incoming { .. }) } /// Try to turn this listener event into upgrade parts. /// /// Returns `None` if the event is not actually an upgrade, /// otherwise the upgrade and the remote address. - pub fn into_upgrade(self) -> Option<(TUpgr, Multiaddr)> { - if let ListenerEvent::Upgrade { + pub fn into_upgrade(self) -> Option<(T::ListenerUpgrade, Multiaddr)> { + if let TransportEvent::Incoming { upgrade, - remote_addr, + send_back_addr, .. } = self { - Some((upgrade, remote_addr)) + Some((upgrade, send_back_addr)) } else { None } @@ -314,7 +366,7 @@ impl ListenerEvent { /// Returns `true` if this is a `NewAddress` listener event. pub fn is_new_address(&self) -> bool { - matches!(self, ListenerEvent::NewAddress(_)) + matches!(self, TransportEvent::NewAddress { .. }) } /// Try to turn this listener event into the `NewAddress` part. @@ -322,8 +374,8 @@ impl ListenerEvent { /// Returns `None` if the event is not actually a `NewAddress`, /// otherwise the address. pub fn into_new_address(self) -> Option { - if let ListenerEvent::NewAddress(a) = self { - Some(a) + if let TransportEvent::NewAddress { listen_addr, .. } = self { + Some(listen_addr) } else { None } @@ -331,7 +383,7 @@ impl ListenerEvent { /// Returns `true` if this is an `AddressExpired` listener event. pub fn is_address_expired(&self) -> bool { - matches!(self, ListenerEvent::AddressExpired(_)) + matches!(self, TransportEvent::AddressExpired { .. }) } /// Try to turn this listener event into the `AddressExpired` part. @@ -339,8 +391,8 @@ impl ListenerEvent { /// Returns `None` if the event is not actually a `AddressExpired`, /// otherwise the address. pub fn into_address_expired(self) -> Option { - if let ListenerEvent::AddressExpired(a) = self { - Some(a) + if let TransportEvent::AddressExpired { listen_addr, .. } = self { + Some(listen_addr) } else { None } @@ -348,22 +400,74 @@ impl ListenerEvent { /// Returns `true` if this is an `Error` listener event. pub fn is_error(&self) -> bool { - matches!(self, ListenerEvent::Error(_)) + matches!(self, TransportEvent::Error { .. }) } /// Try to turn this listener event into the `Error` part. /// /// Returns `None` if the event is not actually a `Error`, /// otherwise the error. - pub fn into_error(self) -> Option { - if let ListenerEvent::Error(err) = self { - Some(err) + pub fn into_error(self) -> Option { + if let TransportEvent::Error { error, .. } = self { + Some(error) } else { None } } } +impl fmt::Debug for TransportEvent +where + TTrans: Transport, + TTrans::Error: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + match self { + TransportEvent::NewAddress { + listener_id, + listen_addr, + } => f + .debug_struct("TransportEvent::NewAddress") + .field("listener_id", listener_id) + .field("listen_addr", listen_addr) + .finish(), + TransportEvent::AddressExpired { + listener_id, + listen_addr, + } => f + .debug_struct("TransportEvent::AddressExpired") + .field("listener_id", listener_id) + .field("listen_addr", listen_addr) + .finish(), + TransportEvent::Incoming { + listener_id, + local_addr, + .. + } => f + .debug_struct("TransportEvent::Incoming") + .field("listener_id", listener_id) + .field("local_addr", local_addr) + .finish(), + TransportEvent::Closed { + listener_id, + addresses, + reason, + } => f + .debug_struct("TransportEvent::Closed") + .field("listener_id", listener_id) + .field("addresses", addresses) + .field("reason", reason) + .finish(), + TransportEvent::Error { listener_id, error } => f + .debug_struct("TransportEvent::Error") + .field("listener_id", listener_id) + .field("error", error) + .finish(), + } + } +} + + /// An error during [dialing][Transport::dial] or [listening][Transport::listen_on] /// on a [`Transport`]. #[derive(Debug, Clone)] From aac9e1c15f972f40edc9436bf3dd1391768a04eb Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 16 May 2022 01:52:00 +0200 Subject: [PATCH 02/47] swarm: remove ListenerStream, poll Transport Remove ListenersStream, instead poll the boxed transport directly in the `Swarm` for `TransportEvent`s (which replace the former `ListenersEvent`s). --- swarm-derive/src/lib.rs | 2 +- swarm/src/behaviour.rs | 3 +- swarm/src/behaviour/either.rs | 3 +- swarm/src/behaviour/toggle.rs | 3 +- swarm/src/connection.rs | 2 - swarm/src/connection/listeners.rs | 554 ------------------------------ swarm/src/lib.rs | 86 ++--- swarm/src/test.rs | 4 +- 8 files changed, 53 insertions(+), 604 deletions(-) delete mode 100644 swarm/src/connection/listeners.rs diff --git a/swarm-derive/src/lib.rs b/swarm-derive/src/lib.rs index 2ee311057ec..803bcdb1c58 100644 --- a/swarm-derive/src/lib.rs +++ b/swarm-derive/src/lib.rs @@ -57,7 +57,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream { let connection_id = quote! {::libp2p::core::connection::ConnectionId}; let dial_errors = quote! {Option<&Vec<::libp2p::core::Multiaddr>>}; let connected_point = quote! {::libp2p::core::ConnectedPoint}; - let listener_id = quote! {::libp2p::core::connection::ListenerId}; + let listener_id = quote! {::libp2p::core::transport::ListenerId}; let dial_error = quote! {::libp2p::swarm::DialError}; let poll_parameters = quote! {::libp2p::swarm::PollParameters}; diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index d09427fbc6b..3dd6ddf9588 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -25,8 +25,7 @@ use crate::dial_opts::DialOpts; use crate::handler::{ConnectionHandler, IntoConnectionHandler}; use crate::{AddressRecord, AddressScore, DialError}; use libp2p_core::{ - connection::{ConnectionId, ListenerId}, - ConnectedPoint, Multiaddr, PeerId, + connection::ConnectionId, transport::ListenerId, ConnectedPoint, Multiaddr, PeerId, }; use std::{task::Context, task::Poll}; diff --git a/swarm/src/behaviour/either.rs b/swarm/src/behaviour/either.rs index 479534f6a8f..54e60e77b3a 100644 --- a/swarm/src/behaviour/either.rs +++ b/swarm/src/behaviour/either.rs @@ -25,8 +25,7 @@ use crate::{ }; use either::Either; use libp2p_core::{ - connection::{ConnectionId, ListenerId}, - ConnectedPoint, Multiaddr, PeerId, + connection::ConnectionId, transport::ListenerId, ConnectedPoint, Multiaddr, PeerId, }; use std::{task::Context, task::Poll}; diff --git a/swarm/src/behaviour/toggle.rs b/swarm/src/behaviour/toggle.rs index 70eec9665b2..f40c7c0e557 100644 --- a/swarm/src/behaviour/toggle.rs +++ b/swarm/src/behaviour/toggle.rs @@ -29,8 +29,9 @@ use crate::{ }; use either::Either; use libp2p_core::{ - connection::{ConnectionId, ListenerId}, + connection::ConnectionId, either::{EitherError, EitherOutput}, + transport::ListenerId, upgrade::{DeniedUpgrade, EitherUpgrade}, ConnectedPoint, Multiaddr, PeerId, }; diff --git a/swarm/src/connection.rs b/swarm/src/connection.rs index c058833d099..5cc2236d055 100644 --- a/swarm/src/connection.rs +++ b/swarm/src/connection.rs @@ -20,7 +20,6 @@ mod error; mod handler_wrapper; -mod listeners; mod substream; pub(crate) mod pool; @@ -29,7 +28,6 @@ pub use error::{ ConnectionError, PendingConnectionError, PendingInboundConnectionError, PendingOutboundConnectionError, }; -pub use listeners::{ListenersEvent, ListenersStream}; pub use pool::{ConnectionCounters, ConnectionLimits}; pub use pool::{EstablishedConnection, PendingConnection}; pub use substream::{Close, Substream, SubstreamEndpoint}; diff --git a/swarm/src/connection/listeners.rs b/swarm/src/connection/listeners.rs deleted file mode 100644 index 484a36dc15d..00000000000 --- a/swarm/src/connection/listeners.rs +++ /dev/null @@ -1,554 +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. - -//! Manage listening on multiple multiaddresses at once. - -use crate::{ - transport::{ListenerEvent, TransportError}, - Multiaddr, Transport, -}; -use futures::{prelude::*, task::Context, task::Poll}; -use libp2p_core::connection::ListenerId; -use log::debug; -use smallvec::SmallVec; -use std::{collections::VecDeque, fmt, mem, pin::Pin}; - -/// Implementation of `futures::Stream` that allows listening on multiaddresses. -/// -/// To start using a [`ListenersStream`], create one with [`ListenersStream::new`] by passing an -/// implementation of [`Transport`]. This [`Transport`] will be used to start listening, therefore -/// you want to pass a [`Transport`] that supports the protocols you wish you listen on. -/// -/// Then, call [`ListenersStream::listen_on`] for all addresses you want to start listening on. -/// -/// The [`ListenersStream`] never ends and never produces errors. If a listener errors or closes, an -/// event is generated on the stream and the listener is then dropped, but the [`ListenersStream`] -/// itself continues. -pub struct ListenersStream -where - TTrans: Transport, -{ - /// Transport used to spawn listeners. - transport: TTrans, - /// All the active listeners. - /// The `Listener` struct contains a stream that we want to be pinned. Since the `VecDeque` - /// can be resized, the only way is to use a `Pin>`. - listeners: VecDeque>>>, - /// The next listener ID to assign. - next_id: ListenerId, - /// Pending listeners events to return from [`ListenersStream::poll`]. - pending_events: VecDeque>, -} - -/// A single active listener. -#[pin_project::pin_project] -#[derive(Debug)] -struct Listener -where - TTrans: Transport, -{ - /// The ID of this listener. - id: ListenerId, - /// The object that actually listens. - #[pin] - listener: TTrans::Listener, - /// Addresses it is listening on. - addresses: SmallVec<[Multiaddr; 4]>, -} - -/// Event that can happen on the `ListenersStream`. -pub enum ListenersEvent -where - TTrans: Transport, -{ - /// A new address is being listened on. - NewAddress { - /// The listener that is listening on the new address. - listener_id: ListenerId, - /// The new address that is being listened on. - listen_addr: Multiaddr, - }, - /// An address is no longer being listened on. - AddressExpired { - /// The listener that is no longer listening on the address. - listener_id: ListenerId, - /// The new address that is being listened on. - listen_addr: Multiaddr, - }, - /// A connection is incoming on one of the listeners. - Incoming { - /// The listener that produced the upgrade. - listener_id: ListenerId, - /// The produced upgrade. - upgrade: TTrans::ListenerUpgrade, - /// Local connection address. - local_addr: Multiaddr, - /// Address used to send back data to the incoming client. - send_back_addr: Multiaddr, - }, - /// A listener closed. - Closed { - /// The ID of the listener that closed. - listener_id: ListenerId, - /// The addresses that the listener was listening on. - addresses: Vec, - /// Reason for the closure. Contains `Ok(())` if the stream produced `None`, or `Err` - /// if the stream produced an error. - reason: Result<(), TTrans::Error>, - }, - /// A listener errored. - /// - /// The listener will continue to be polled for new events and the event - /// is for informational purposes only. - Error { - /// The ID of the listener that errored. - listener_id: ListenerId, - /// The error value. - error: TTrans::Error, - }, -} - -impl ListenersStream -where - TTrans: Transport, -{ - /// Starts a new stream of listeners. - pub fn new(transport: TTrans) -> Self { - ListenersStream { - transport, - listeners: VecDeque::new(), - next_id: ListenerId::new(1), - pending_events: VecDeque::new(), - } - } - - /// Start listening on a multiaddress. - /// - /// Returns an error if the transport doesn't support the given multiaddress. - pub fn listen_on( - &mut self, - addr: Multiaddr, - ) -> Result> { - let listener = self.transport.listen_on(addr)?; - self.listeners.push_back(Box::pin(Listener { - id: self.next_id, - listener, - addresses: SmallVec::new(), - })); - let id = self.next_id; - self.next_id = self.next_id + 1; - Ok(id) - } - - /// Remove the listener matching the given `ListenerId`. - /// - /// Returns `true` if there was a listener with this ID, `false` - /// otherwise. - pub fn remove_listener(&mut self, id: ListenerId) -> bool { - if let Some(i) = self.listeners.iter().position(|l| l.id == id) { - let mut listener = self - .listeners - .remove(i) - .expect("Index can not be out of bounds."); - let listener_project = listener.as_mut().project(); - let addresses = mem::take(listener_project.addresses).into_vec(); - self.pending_events.push_back(ListenersEvent::Closed { - listener_id: *listener_project.id, - addresses, - reason: Ok(()), - }); - true - } else { - false - } - } - - /// Returns a reference to the transport passed when building this object. - pub fn transport(&self) -> &TTrans { - &self.transport - } - - /// Returns a mutable reference to the transport passed when building this object. - pub fn transport_mut(&mut self) -> &mut TTrans { - &mut self.transport - } - - /// Returns an iterator that produces the list of addresses we're listening on. - pub fn listen_addrs(&self) -> impl Iterator { - self.listeners.iter().flat_map(|l| l.addresses.iter()) - } - - /// Provides an API similar to `Stream`, except that it cannot end. - pub fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - // Return pending events from closed listeners. - if let Some(event) = self.pending_events.pop_front() { - return Poll::Ready(event); - } - // We remove each element from `listeners` one by one and add them back. - let mut remaining = self.listeners.len(); - while let Some(mut listener) = self.listeners.pop_back() { - let mut listener_project = listener.as_mut().project(); - match TryStream::try_poll_next(listener_project.listener.as_mut(), cx) { - Poll::Pending => { - self.listeners.push_front(listener); - remaining -= 1; - if remaining == 0 { - break; - } - } - Poll::Ready(Some(Ok(ListenerEvent::Upgrade { - upgrade, - local_addr, - remote_addr, - }))) => { - let id = *listener_project.id; - self.listeners.push_front(listener); - return Poll::Ready(ListenersEvent::Incoming { - listener_id: id, - upgrade, - local_addr, - send_back_addr: remote_addr, - }); - } - Poll::Ready(Some(Ok(ListenerEvent::NewAddress(a)))) => { - if listener_project.addresses.contains(&a) { - debug!("Transport has reported address {} multiple times", a) - } else { - listener_project.addresses.push(a.clone()); - } - let id = *listener_project.id; - self.listeners.push_front(listener); - return Poll::Ready(ListenersEvent::NewAddress { - listener_id: id, - listen_addr: a, - }); - } - Poll::Ready(Some(Ok(ListenerEvent::AddressExpired(a)))) => { - listener_project.addresses.retain(|x| x != &a); - let id = *listener_project.id; - self.listeners.push_front(listener); - return Poll::Ready(ListenersEvent::AddressExpired { - listener_id: id, - listen_addr: a, - }); - } - Poll::Ready(Some(Ok(ListenerEvent::Error(error)))) => { - let id = *listener_project.id; - self.listeners.push_front(listener); - return Poll::Ready(ListenersEvent::Error { - listener_id: id, - error, - }); - } - Poll::Ready(None) => { - let addresses = mem::take(listener_project.addresses).into_vec(); - return Poll::Ready(ListenersEvent::Closed { - listener_id: *listener_project.id, - addresses, - reason: Ok(()), - }); - } - Poll::Ready(Some(Err(err))) => { - let addresses = mem::take(listener_project.addresses).into_vec(); - return Poll::Ready(ListenersEvent::Closed { - listener_id: *listener_project.id, - addresses, - reason: Err(err), - }); - } - } - } - - // We register the current task to be woken up if a new listener is added. - Poll::Pending - } -} - -impl Stream for ListenersStream -where - TTrans: Transport, -{ - type Item = ListenersEvent; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - ListenersStream::poll(self, cx).map(Option::Some) - } -} - -impl Unpin for ListenersStream where TTrans: Transport {} - -impl fmt::Debug for ListenersStream -where - TTrans: Transport + fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.debug_struct("ListenersStream") - .field("transport", &self.transport) - .field("listen_addrs", &self.listen_addrs().collect::>()) - .finish() - } -} - -impl fmt::Debug for ListenersEvent -where - TTrans: Transport, - TTrans::Error: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - match self { - ListenersEvent::NewAddress { - listener_id, - listen_addr, - } => f - .debug_struct("ListenersEvent::NewAddress") - .field("listener_id", listener_id) - .field("listen_addr", listen_addr) - .finish(), - ListenersEvent::AddressExpired { - listener_id, - listen_addr, - } => f - .debug_struct("ListenersEvent::AddressExpired") - .field("listener_id", listener_id) - .field("listen_addr", listen_addr) - .finish(), - ListenersEvent::Incoming { - listener_id, - local_addr, - .. - } => f - .debug_struct("ListenersEvent::Incoming") - .field("listener_id", listener_id) - .field("local_addr", local_addr) - .finish(), - ListenersEvent::Closed { - listener_id, - addresses, - reason, - } => f - .debug_struct("ListenersEvent::Closed") - .field("listener_id", listener_id) - .field("addresses", addresses) - .field("reason", reason) - .finish(), - ListenersEvent::Error { listener_id, error } => f - .debug_struct("ListenersEvent::Error") - .field("listener_id", listener_id) - .field("error", error) - .finish(), - } - } -} - -#[cfg(test)] -mod tests { - use futures::{future::BoxFuture, stream::BoxStream}; - - use super::*; - use crate::transport; - - #[test] - fn incoming_event() { - async_std::task::block_on(async move { - let mut mem_transport = transport::MemoryTransport::default(); - - let mut listeners = ListenersStream::new(mem_transport); - listeners.listen_on("/memory/0".parse().unwrap()).unwrap(); - - let address = { - let event = listeners.next().await.unwrap(); - if let ListenersEvent::NewAddress { listen_addr, .. } = event { - listen_addr - } else { - panic!("Was expecting the listen address to be reported") - } - }; - - let address2 = address.clone(); - async_std::task::spawn(async move { - mem_transport.dial(address2).unwrap().await.unwrap(); - }); - - match listeners.next().await.unwrap() { - ListenersEvent::Incoming { - local_addr, - send_back_addr, - .. - } => { - assert_eq!(local_addr, address); - assert!(send_back_addr != address); - } - _ => panic!(), - } - }); - } - - #[test] - fn listener_event_error_isnt_fatal() { - // Tests that a listener continues to be polled even after producing - // a `ListenerEvent::Error`. - - #[derive(Clone)] - struct DummyTrans; - impl transport::Transport for DummyTrans { - type Output = (); - type Error = std::io::Error; - type Listener = BoxStream< - 'static, - Result, std::io::Error>, - >; - type ListenerUpgrade = BoxFuture<'static, Result>; - type Dial = BoxFuture<'static, Result>; - - fn listen_on( - &mut self, - _: Multiaddr, - ) -> Result> { - Ok(Box::pin(stream::unfold((), |()| async move { - Some(( - Ok(ListenerEvent::Error(std::io::Error::from( - std::io::ErrorKind::Other, - ))), - (), - )) - }))) - } - - fn dial( - &mut self, - _: Multiaddr, - ) -> Result> { - panic!() - } - - fn dial_as_listener( - &mut self, - _: Multiaddr, - ) -> Result> { - panic!() - } - - fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option { - None - } - } - - async_std::task::block_on(async move { - let transport = DummyTrans; - let mut listeners = ListenersStream::new(transport); - listeners.listen_on("/memory/0".parse().unwrap()).unwrap(); - - for _ in 0..10 { - match listeners.next().await.unwrap() { - ListenersEvent::Error { .. } => {} - _ => panic!(), - } - } - }); - } - - #[test] - fn listener_error_is_fatal() { - // Tests that a listener stops after producing an error on the stream itself. - - #[derive(Clone)] - struct DummyTrans; - impl transport::Transport for DummyTrans { - type Output = (); - type Error = std::io::Error; - type Listener = BoxStream< - 'static, - Result, std::io::Error>, - >; - type ListenerUpgrade = BoxFuture<'static, Result>; - type Dial = BoxFuture<'static, Result>; - - fn listen_on( - &mut self, - _: Multiaddr, - ) -> Result> { - Ok(Box::pin(stream::unfold((), |()| async move { - Some((Err(std::io::Error::from(std::io::ErrorKind::Other)), ())) - }))) - } - - fn dial( - &mut self, - _: Multiaddr, - ) -> Result> { - panic!() - } - - fn dial_as_listener( - &mut self, - _: Multiaddr, - ) -> Result> { - panic!() - } - - fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option { - None - } - } - - async_std::task::block_on(async move { - let transport = DummyTrans; - let mut listeners = ListenersStream::new(transport); - listeners.listen_on("/memory/0".parse().unwrap()).unwrap(); - - match listeners.next().await.unwrap() { - ListenersEvent::Closed { .. } => {} - _ => panic!(), - } - }); - } - - #[test] - fn listener_closed() { - async_std::task::block_on(async move { - let mem_transport = transport::MemoryTransport::default(); - - let mut listeners = ListenersStream::new(mem_transport); - let id = listeners.listen_on("/memory/0".parse().unwrap()).unwrap(); - - let event = listeners.next().await.unwrap(); - let addr; - if let ListenersEvent::NewAddress { listen_addr, .. } = event { - addr = listen_addr - } else { - panic!("Was expecting the listen address to be reported") - } - - assert!(listeners.remove_listener(id)); - - match listeners.next().await.unwrap() { - ListenersEvent::Closed { - listener_id, - addresses, - reason: Ok(()), - } => { - assert_eq!(listener_id, id); - assert!(addresses.contains(&addr)); - } - other => panic!("Unexpected listeners event: {:?}", other), - } - }); - } -} diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 461e8c7d13f..add93f8c8d3 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -79,17 +79,17 @@ pub use handler::{ pub use registry::{AddAddressResult, AddressRecord, AddressScore}; use connection::pool::{Pool, PoolConfig, PoolEvent}; -use connection::{EstablishedConnection, IncomingInfo, ListenersEvent, ListenersStream, Substream}; +use connection::{EstablishedConnection, IncomingInfo, Substream}; use dial_opts::{DialOpts, PeerCondition}; use either::Either; use futures::{executor::ThreadPoolBuilder, prelude::*, stream::FusedStream}; use libp2p_core::connection::{ConnectionId, PendingPoint}; use libp2p_core::{ - connection::{ConnectedPoint, ListenerId}, + connection::ConnectedPoint, multiaddr::Protocol, multihash::Multihash, muxing::StreamMuxerBox, - transport::{self, TransportError}, + transport::{self, TransportEvent, ListenerId, TransportError}, upgrade::ProtocolName, Endpoint, Executor, Multiaddr, Negotiated, PeerId, Transport, }; @@ -258,7 +258,9 @@ where TBehaviour: NetworkBehaviour, { /// Listeners for incoming connections. - listeners: ListenersStream>, + transport: transport::Boxed<(PeerId, StreamMuxerBox)>, + + next_listener_id: ListenerId, /// The nodes currently active. pool: Pool, transport::Boxed<(PeerId, StreamMuxerBox)>>, @@ -326,7 +328,9 @@ where /// Listeners report their new listening addresses as [`SwarmEvent::NewListenAddr`]. /// Depending on the underlying transport, one listener may have multiple listening addresses. pub fn listen_on(&mut self, addr: Multiaddr) -> Result> { - let id = self.listeners.listen_on(addr)?; + let id = self.next_listener_id; + self.next_listener_id = self.next_listener_id + 1; + self.transport.listen_on(id, addr)?; self.behaviour.inject_new_listener(id); Ok(id) } @@ -335,8 +339,10 @@ where /// /// Returns `true` if there was a listener with this ID, `false` /// otherwise. - pub fn remove_listener(&mut self, id: ListenerId) -> bool { - self.listeners.remove_listener(id) + pub fn remove_listener(&mut self, _id: ListenerId) -> bool { + // TODO + false + // self.transport.remove_listener(id) } /// Dial a known or unknown peer. @@ -506,11 +512,8 @@ where .map(|a| match p2p_addr(peer_id, a) { Ok(address) => { let dial = match role_override { - Endpoint::Dialer => self.listeners.transport_mut().dial(address.clone()), - Endpoint::Listener => self - .listeners - .transport_mut() - .dial_as_listener(address.clone()), + Endpoint::Dialer => self.transport.dial(address.clone()), + Endpoint::Listener => self.transport.dial_as_listener(address.clone()), }; match dial { Ok(fut) => fut @@ -545,7 +548,9 @@ where /// Returns an iterator that produces the list of addresses we're listening on. pub fn listeners(&self) -> impl Iterator { - self.listeners.listen_addrs() + // TODO + vec![].into_iter() + // self.transport.listen_addrs() } /// Returns the peer ID of the swarm passed as parameter. @@ -831,10 +836,10 @@ where fn handle_listeners_event( &mut self, - event: ListenersEvent>, + event: TransportEvent>, ) -> Option>> { match event { - ListenersEvent::Incoming { + TransportEvent::Incoming { listener_id: _, upgrade, local_addr, @@ -862,7 +867,7 @@ where } }; } - ListenersEvent::NewAddress { + TransportEvent::NewAddress { listener_id, listen_addr, } => { @@ -877,7 +882,7 @@ where address: listen_addr, }); } - ListenersEvent::AddressExpired { + TransportEvent::AddressExpired { listener_id, listen_addr, } => { @@ -894,7 +899,7 @@ where address: listen_addr, }); } - ListenersEvent::Closed { + TransportEvent::Closed { listener_id, addresses, reason, @@ -916,7 +921,7 @@ where reason, }); } - ListenersEvent::Error { listener_id, error } => { + TransportEvent::Error { listener_id, error } => { self.behaviour.inject_listener_error(listener_id, &error); return Some(SwarmEvent::ListenerError { listener_id, error }); } @@ -959,7 +964,7 @@ where self.pending_event = Some((peer_id, handler, event)); } - NetworkBehaviourAction::ReportObservedAddr { address, score } => { + NetworkBehaviourAction::ReportObservedAddr { address: _, score } => { // Maps the given `observed_addr`, representing an address of the local // node observed by a remote peer, onto the locally known listen addresses // to yield one or more addresses of the local node that may be publicly @@ -973,12 +978,12 @@ where // // The translation is transport-specific. See [`Transport::address_translation`]. let translated_addresses = { - let transport = self.listeners.transport(); - let mut addrs: Vec<_> = self - .listeners - .listen_addrs() - .filter_map(move |server| transport.address_translation(server, &address)) - .collect(); + let mut addrs = vec![Multiaddr::empty()]; + // let mut addrs: Vec<_> = self + // .transport + // .listen_addrs() + // .filter_map(move |server| transport.address_translation(server, &address)) + // .collect(); // remove duplicates addrs.sort_unstable(); @@ -1092,7 +1097,7 @@ where }; // Poll the listener(s) for new connections. - match ListenersStream::poll(Pin::new(&mut this.listeners), cx) { + match Pin::new(&mut this.transport).poll(cx) { Poll::Pending => {} Poll::Ready(listeners_event) => { if let Some(swarm_event) = this.handle_listeners_event(listeners_event) { @@ -1392,7 +1397,8 @@ where Swarm { local_peer_id: self.local_peer_id, - listeners: ListenersStream::new(self.transport), + next_listener_id: ListenerId::new(1), + transport: self.transport, pool: Pool::new(self.local_peer_id, pool_config, self.connection_limits), behaviour: self.behaviour, supported_protocols, @@ -1609,7 +1615,7 @@ mod tests { use libp2p::plaintext; use libp2p::yamux; use libp2p_core::multiaddr::multiaddr; - use libp2p_core::transport::ListenerEvent; + use libp2p_core::transport::TransportEvent; use libp2p_core::Endpoint; use quickcheck::{quickcheck, Arbitrary, Gen, QuickCheck}; use rand::prelude::SliceRandom; @@ -2058,20 +2064,21 @@ mod tests { // `+ 2` to ensure a subset of addresses is dialed by network_2. let num_listen_addrs = concurrency_factor.0.get() + 2; let mut listen_addresses = Vec::new(); - let mut listeners = Vec::new(); + let mut transports = Vec::new(); for _ in 0..num_listen_addrs { - let mut listener = transport::MemoryTransport {} - .listen_on("/memory/0".parse().unwrap()) + let mut transport = transport::MemoryTransport::default(); + transport + .listen_on(ListenerId::new(1), "/memory/0".parse().unwrap()) .unwrap(); - match listener.next().await.unwrap().unwrap() { - ListenerEvent::NewAddress(address) => { - listen_addresses.push(address); + match poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await { + TransportEvent::NewAddress { listen_addr, .. } => { + listen_addresses.push(listen_addr); } _ => panic!("Expected `NewListenAddr` event."), } - listeners.push(listener); + transports.push(transport); } // Have swarm dial each listener and wait for each listener to receive the incoming @@ -2083,10 +2090,11 @@ mod tests { .build(), ) .unwrap(); - for mut listener in listeners.into_iter() { + for mut transport in transports.into_iter() { + let poll_transport = poll_fn(|cx| Pin::new(&mut transport).poll(cx)); loop { - match futures::future::select(listener.next(), swarm.next()).await { - Either::Left((Some(Ok(ListenerEvent::Upgrade { .. })), _)) => { + match futures::future::select(poll_transport, swarm.next()).await { + Either::Left((TransportEvent::Incoming { .. }, _)) => { break; } Either::Left(_) => { diff --git a/swarm/src/test.rs b/swarm/src/test.rs index e201432ec39..166e9185a47 100644 --- a/swarm/src/test.rs +++ b/swarm/src/test.rs @@ -23,9 +23,7 @@ use crate::{ PollParameters, }; use libp2p_core::{ - connection::{ConnectionId, ListenerId}, - multiaddr::Multiaddr, - ConnectedPoint, PeerId, + connection::ConnectionId, multiaddr::Multiaddr, transport::ListenerId, ConnectedPoint, PeerId, }; use std::collections::HashMap; use std::task::{Context, Poll}; From 68663fd95a524b1914c5eef8178aabf8d2ddff77 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 16 May 2022 01:56:00 +0200 Subject: [PATCH 03/47] transports/tcp: handle transport changes Add new struct `GenTcpTransport` as wrapper for `GenTcpConfig` to manage multiple listener streams. This is essentially the old ListenerStream logic from swarm/connection. --- transports/tcp/Cargo.toml | 2 + transports/tcp/src/lib.rs | 374 ++++++++++++++++++++++++++------------ 2 files changed, 258 insertions(+), 118 deletions(-) diff --git a/transports/tcp/Cargo.toml b/transports/tcp/Cargo.toml index 67e28b35ff7..c919d633fb5 100644 --- a/transports/tcp/Cargo.toml +++ b/transports/tcp/Cargo.toml @@ -20,6 +20,8 @@ ipnet = "2.0.0" libc = "0.2.80" libp2p-core = { version = "0.33.0", path = "../../core", default-features = false } log = "0.4.11" +pin-project = "1.0.0" +smallvec = "1.6.1" socket2 = { version = "0.4.0", features = ["all"] } tokio-crate = { package = "tokio", version = "1.0.1", default-features = false, features = ["net"], optional = true } diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 6e6eb771d06..89752e95ee9 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -33,14 +33,14 @@ pub use provider::async_io; /// The type of a [`GenTcpConfig`] using the `async-io` implementation. #[cfg(feature = "async-io")] -pub type TcpConfig = GenTcpConfig; +pub type TcpConfig = GenTcpTransport; #[cfg(feature = "tokio")] pub use provider::tokio; /// The type of a [`GenTcpConfig`] using the `tokio` implementation. #[cfg(feature = "tokio")] -pub type TokioTcpConfig = GenTcpConfig; +pub type TokioTcpConfig = GenTcpTransport; use futures::{ future::{self, BoxFuture, Ready}, @@ -51,12 +51,14 @@ use futures_timer::Delay; use libp2p_core::{ address_translation, multiaddr::{Multiaddr, Protocol}, - transport::{ListenerEvent, Transport, TransportError}, + transport::{TransportEvent, ListenerId, Transport, TransportError}, }; +use log::debug; +use smallvec::SmallVec; use socket2::{Domain, Socket, Type}; use std::{ - collections::HashSet, - io, + collections::{HashSet, VecDeque}, + io, mem, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener}, pin::Pin, task::{Context, Poll}, @@ -65,11 +67,68 @@ use std::{ use provider::{IfEvent, Provider}; +pub struct GenTcpTransport +where + T: Provider + Send, +{ + config: GenTcpConfig, + /// All the active listeners. + /// The `Listener` struct contains a stream that we want to be pinned. Since the `VecDeque` + /// can be resized, the only way is to use a `Pin>`. + listeners: VecDeque>>>, + /// Pending listeners events to return from [`ListenersStream::poll`]. + pending_events: VecDeque>, +} + +impl GenTcpTransport +where + T: Provider + Send, +{ + + pub fn new(config: GenTcpConfig) -> Self { + GenTcpTransport { config, listeners:Default::default(), pending_events: Default::default() } + } + + fn create_socket(&self, socket_addr: &SocketAddr) -> io::Result { + let domain = if socket_addr.is_ipv4() { + Domain::IPV4 + } else { + Domain::IPV6 + }; + let socket = Socket::new(domain, Type::STREAM, Some(socket2::Protocol::TCP))?; + if socket_addr.is_ipv6() { + socket.set_only_v6(true)?; + } + if let Some(ttl) = self.config.ttl { + socket.set_ttl(ttl)?; + } + if let Some(nodelay) = self.config.nodelay { + socket.set_nodelay(nodelay)?; + } + socket.set_reuse_address(true)?; + #[cfg(unix)] + if let PortReuse::Enabled { .. } = &self.config.port_reuse { + socket.set_reuse_port(true)?; + } + Ok(socket) + } + + fn do_listen( + &mut self, + id: ListenerId, + socket_addr: SocketAddr, + ) -> io::Result> { + let socket = self.create_socket(&socket_addr)?; + socket.bind(&socket_addr.into())?; + socket.listen(self.config.backlog as _)?; + socket.set_nonblocking(true)?; + TcpListenStream::::new(id, socket.into(), self.config.port_reuse.clone()) + } +} + /// The configuration for a TCP/IP transport capability for libp2p. #[derive(Clone, Debug)] -pub struct GenTcpConfig { - /// The type of the I/O provider. - _impl: std::marker::PhantomData, +pub struct GenTcpConfig { /// TTL to set for opened sockets, or `None` to keep default. ttl: Option, /// `TCP_NODELAY` to set for opened sockets, or `None` to keep default. @@ -148,10 +207,7 @@ impl PortReuse { } } -impl GenTcpConfig -where - T: Provider + Send, -{ +impl GenTcpConfig { /// Creates a new configuration for a TCP/IP transport: /// /// * Nagle's algorithm, i.e. `TCP_NODELAY`, is _enabled_. @@ -168,7 +224,6 @@ where nodelay: None, backlog: 1024, port_reuse: PortReuse::Disabled, - _impl: std::marker::PhantomData, } } @@ -235,21 +290,22 @@ where /// following example: /// /// ```no_run - /// # use libp2p_core::transport::ListenerEvent; + /// # use libp2p_core::transport::{ListenerId, TransportEvent}; /// # use libp2p_core::{Multiaddr, Transport}; - /// # use futures::stream::StreamExt; + /// # use futures::{stream::StreamExt, future::poll_fn}; + /// # use std::pin::Pin; /// #[cfg(feature = "async-io")] /// #[async_std::main] /// async fn main() -> std::io::Result<()> { - /// use libp2p_tcp::TcpConfig; + /// use libp2p_tcp::{GenTcpConfig, TcpConfig}; /// /// let listen_addr1: Multiaddr = "/ip4/127.0.0.1/tcp/9001".parse().unwrap(); /// let listen_addr2: Multiaddr = "/ip4/127.0.0.1/tcp/9002".parse().unwrap(); /// - /// let mut tcp1 = TcpConfig::new().port_reuse(true); - /// let mut listener1 = tcp1.clone().listen_on(listen_addr1.clone()).expect("listener"); - /// match listener1.next().await.expect("event")? { - /// ListenerEvent::NewAddress(listen_addr) => { + /// let mut tcp1 = TcpConfig::new(GenTcpConfig::new().port_reuse(true)); + /// tcp1.listen_on(ListenerId::new(1), listen_addr1.clone()).expect("listener"); + /// match poll_fn(|cx| Pin::new(&mut tcp1).poll(cx)).await { + /// TransportEvent::NewAddress { listen_addr, .. } => { /// println!("Listening on {:?}", listen_addr); /// let mut stream = tcp1.dial(listen_addr2.clone()).unwrap().await?; /// // `stream` has `listen_addr1` as its local socket address. @@ -257,10 +313,10 @@ where /// _ => {} /// } /// - /// let mut tcp2 = TcpConfig::new().port_reuse(true); - /// let mut listener2 = tcp2.clone().listen_on(listen_addr2).expect("listener"); - /// match listener2.next().await.expect("event")? { - /// ListenerEvent::NewAddress(listen_addr) => { + /// let mut tcp2 = TcpConfig::new(GenTcpConfig::new().port_reuse(true)); + /// tcp2.listen_on(ListenerId::new(1), listen_addr2).expect("listener"); + /// match poll_fn(|cx| Pin::new(&mut tcp2).poll(cx)).await { + /// TransportEvent::NewAddress { listen_addr, .. } => { /// println!("Listening on {:?}", listen_addr); /// let mut socket = tcp2.dial(listen_addr1).unwrap().await?; /// // `stream` has `listen_addr2` as its local socket address. @@ -294,47 +350,15 @@ where self } - - fn create_socket(&self, socket_addr: &SocketAddr) -> io::Result { - let domain = if socket_addr.is_ipv4() { - Domain::IPV4 - } else { - Domain::IPV6 - }; - let socket = Socket::new(domain, Type::STREAM, Some(socket2::Protocol::TCP))?; - if socket_addr.is_ipv6() { - socket.set_only_v6(true)?; - } - if let Some(ttl) = self.ttl { - socket.set_ttl(ttl)?; - } - if let Some(nodelay) = self.nodelay { - socket.set_nodelay(nodelay)?; - } - socket.set_reuse_address(true)?; - #[cfg(unix)] - if let PortReuse::Enabled { .. } = &self.port_reuse { - socket.set_reuse_port(true)?; - } - Ok(socket) - } - - fn do_listen(&mut self, socket_addr: SocketAddr) -> io::Result> { - let socket = self.create_socket(&socket_addr)?; - socket.bind(&socket_addr.into())?; - socket.listen(self.backlog as _)?; - socket.set_nonblocking(true)?; - TcpListenStream::::new(socket.into(), self.port_reuse.clone()) - } } -impl Default for GenTcpConfig { +impl Default for GenTcpConfig { fn default() -> Self { Self::new() } } -impl Transport for GenTcpConfig +impl Transport for GenTcpTransport where T: Provider + Send + 'static, T::Listener: Unpin, @@ -344,20 +368,107 @@ where type Output = T::Stream; type Error = io::Error; type Dial = Pin> + Send>>; - type Listener = TcpListenStream; type ListenerUpgrade = Ready>; + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + // Return pending events from closed listeners. + if let Some(event) = self.pending_events.pop_front() { + return Poll::Ready(event); + } + // We remove each element from `listeners` one by one and add them back. + let mut remaining = self.listeners.len(); + while let Some(mut listener) = self.listeners.pop_back() { + match TryStream::try_poll_next(listener.as_mut(), cx) { + Poll::Pending => { + self.listeners.push_front(listener); + remaining -= 1; + if remaining == 0 { + break; + } + } + Poll::Ready(Some(Ok(TcpTransportEvent::Upgrade { + upgrade, + local_addr, + remote_addr, + }))) => { + let id = listener.listener_id; + self.listeners.push_front(listener); + return Poll::Ready(TransportEvent::Incoming { + listener_id: id, + upgrade, + local_addr, + send_back_addr: remote_addr, + }); + } + Poll::Ready(Some(Ok(TcpTransportEvent::NewAddress(a)))) => { + if listener.addresses.contains(&a) { + debug!("Transport has reported address {} multiple times", a) + } else { + listener.addresses.push(a.clone()); + } + let id = listener.listener_id; + self.listeners.push_front(listener); + return Poll::Ready(TransportEvent::NewAddress { + listener_id: id, + listen_addr: a, + }); + } + Poll::Ready(Some(Ok(TcpTransportEvent::AddressExpired(a)))) => { + listener.addresses.retain(|x| x != &a); + let id = listener.listener_id; + self.listeners.push_front(listener); + return Poll::Ready(TransportEvent::AddressExpired { + listener_id: id, + listen_addr: a, + }); + } + Poll::Ready(Some(Ok(TcpTransportEvent::Error(error)))) => { + let id = listener.listener_id; + self.listeners.push_front(listener); + return Poll::Ready(TransportEvent::Error { + listener_id: id, + error, + }); + } + Poll::Ready(None) => { + let addresses = mem::take(&mut listener.addresses).into_vec(); + return Poll::Ready(TransportEvent::Closed { + listener_id: listener.listener_id, + addresses, + reason: Ok(()), + }); + } + Poll::Ready(Some(Err(err))) => { + let addresses = mem::take(&mut listener.addresses).into_vec(); + return Poll::Ready(TransportEvent::Closed { + listener_id: listener.listener_id, + addresses, + reason: Err(err), + }); + } + } + } + + // We register the current task to be woken up if a new listener is added. + Poll::Pending + } + fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { + ) -> Result<(), TransportError> { let socket_addr = if let Ok(sa) = multiaddr_to_socketaddr(addr.clone()) { sa } else { return Err(TransportError::MultiaddrNotSupported(addr)); }; log::debug!("listening on {}", socket_addr); - self.do_listen(socket_addr).map_err(TransportError::Other) + let listener = self + .do_listen(id, socket_addr) + .map_err(TransportError::Other)?; + self.listeners.push_back(Box::pin(listener)); + Ok(()) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -375,7 +486,7 @@ where .create_socket(&socket_addr) .map_err(TransportError::Other)?; - if let Some(addr) = self.port_reuse.local_dial_addr(&socket_addr.ip()) { + if let Some(addr) = self.config.port_reuse.local_dial_addr(&socket_addr.ip()) { log::trace!("Binding dial socket to listen socket {}", addr); socket.bind(&addr.into()).map_err(TransportError::Other)?; } @@ -425,14 +536,34 @@ where /// `None` is returned if one of the given addresses is not a TCP/IP /// address. fn address_translation(&self, listen: &Multiaddr, observed: &Multiaddr) -> Option { - match &self.port_reuse { + match &self.config.port_reuse { PortReuse::Disabled => address_translation(listen, observed), PortReuse::Enabled { .. } => Some(observed.clone()), } } } -type TcpListenerEvent = ListenerEvent>, io::Error>; +#[derive(Debug)] +pub enum TcpTransportEvent { + /// The transport is listening on a new additional [`Multiaddr`]. + NewAddress(Multiaddr), + /// An upgrade, consisting of the upgrade future, the listener address and the remote address. + Upgrade { + /// The upgrade. + upgrade: Ready>, + /// The local address which produced this upgrade. + local_addr: Multiaddr, + /// The remote address which produced this upgrade. + remote_addr: Multiaddr, + }, + /// A [`Multiaddr`] is no longer used for listening. + AddressExpired(Multiaddr), + /// A non-fatal error has happened on the listener. + /// + /// This event should be generated in order to notify the user that something wrong has + /// happened. The listener, however, continues to run. + Error(io::Error), +} enum IfWatch { Pending(BoxFuture<'static, io::Result>), @@ -458,10 +589,14 @@ pub struct TcpListenStream where T: Provider, { + /// The ID of this listener. + listener_id: ListenerId, /// The socket address that the listening socket is bound to, /// which may be a "wildcard address" like `INADDR_ANY` or `IN6ADDR_ANY` /// when listening on all interfaces for IPv4 respectively IPv6 connections. listen_addr: SocketAddr, + /// Addresses it is listening on. + addresses: SmallVec<[Multiaddr; 4]>, /// The async listening socket for incoming connections. listener: T::Listener, /// The IP addresses of network interfaces on which the listening socket @@ -490,7 +625,11 @@ where { /// Constructs a `TcpListenStream` for incoming connections around /// the given `TcpListener`. - fn new(listener: TcpListener, port_reuse: PortReuse) -> io::Result { + fn new( + listener_id: ListenerId, + listener: TcpListener, + port_reuse: PortReuse, + ) -> io::Result { let listen_addr = listener.local_addr()?; let in_addr = if match &listen_addr { @@ -515,7 +654,9 @@ where Ok(TcpListenStream { port_reuse, listener, + listener_id, listen_addr, + addresses: Default::default(), in_addr, pause: None, sleep_on_error: Duration::from_millis(100), @@ -558,7 +699,7 @@ where T::Stream: Unpin, T::IfWatcher: Unpin, { - type Item = Result, io::Error>; + type Item = Result, io::Error>; fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { let me = Pin::into_inner(self); @@ -579,7 +720,7 @@ where }; *if_watch = IfWatch::Pending(T::if_watcher()); me.pause = Some(Delay::new(me.sleep_on_error)); - return Poll::Ready(Some(Ok(ListenerEvent::Error(err)))); + return Poll::Ready(Some(Ok(TcpTransportEvent::Error(err)))); } }, // Consume all events for up/down interface changes. @@ -593,9 +734,9 @@ where let ma = ip_to_multiaddr(ip, me.listen_addr.port()); log::debug!("New listen address: {}", ma); me.port_reuse.register(ip, me.listen_addr.port()); - return Poll::Ready(Some(Ok(ListenerEvent::NewAddress( - ma, - )))); + return Poll::Ready(Some(Ok( + TcpTransportEvent::NewAddress(ma), + ))); } } Ok(IfEvent::Down(inet)) => { @@ -606,7 +747,7 @@ where log::debug!("Expired listen address: {}", ma); me.port_reuse.unregister(ip, me.listen_addr.port()); return Poll::Ready(Some(Ok( - ListenerEvent::AddressExpired(ma), + TcpTransportEvent::AddressExpired(ma), ))); } } @@ -616,7 +757,7 @@ where err }; me.pause = Some(Delay::new(me.sleep_on_error)); - return Poll::Ready(Some(Ok(ListenerEvent::Error(err)))); + return Poll::Ready(Some(Ok(TcpTransportEvent::Error(err)))); } } } @@ -627,7 +768,7 @@ where InAddr::One { addr, out } => { if let Some(multiaddr) = out.take() { me.port_reuse.register(*addr, me.listen_addr.port()); - return Poll::Ready(Some(Ok(ListenerEvent::NewAddress(multiaddr)))); + return Poll::Ready(Some(Ok(TcpTransportEvent::NewAddress(multiaddr)))); } } } @@ -650,7 +791,7 @@ where // These errors are non-fatal for the listener stream. log::error!("error accepting incoming connection: {}", e); me.pause = Some(Delay::new(me.sleep_on_error)); - return Poll::Ready(Some(Ok(ListenerEvent::Error(e)))); + return Poll::Ready(Some(Ok(TcpTransportEvent::Error(e)))); } }; @@ -660,7 +801,7 @@ where log::debug!("Incoming connection from {} at {}", remote_addr, local_addr); - return Poll::Ready(Some(Ok(ListenerEvent::Upgrade { + return Poll::Ready(Some(Ok(TcpTransportEvent::Upgrade { upgrade: future::ok(incoming.stream), local_addr, remote_addr, @@ -707,7 +848,7 @@ fn ip_to_multiaddr(ip: IpAddr, port: u16) -> Multiaddr { #[cfg(test)] mod tests { use super::*; - use futures::channel::mpsc; + use futures::{channel::mpsc, future::poll_fn}; #[test] fn multiaddr_to_tcp_conversion() { @@ -763,14 +904,14 @@ mod tests { env_logger::try_init().ok(); async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { - let mut tcp = GenTcpConfig::::new(); - let mut listener = tcp.listen_on(addr).unwrap(); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); + tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { - match listener.next().await.unwrap().unwrap() { - ListenerEvent::NewAddress(listen_addr) => { + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + TransportEvent::NewAddress { listen_addr, .. } => { ready_tx.send(listen_addr).await.unwrap(); } - ListenerEvent::Upgrade { upgrade, .. } => { + TransportEvent::Incoming { upgrade, .. } => { let mut upgrade = upgrade.await.unwrap(); let mut buf = [0u8; 3]; upgrade.read_exact(&mut buf).await.unwrap(); @@ -785,7 +926,7 @@ mod tests { async fn dialer(mut ready_rx: mpsc::Receiver) { let addr = ready_rx.next().await.unwrap(); - let mut tcp = GenTcpConfig::::new(); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); // Obtain a future socket through dialing let mut socket = tcp.dial(addr.clone()).unwrap().await.unwrap(); @@ -832,13 +973,13 @@ mod tests { env_logger::try_init().ok(); async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { - let mut tcp = GenTcpConfig::::new(); - let mut listener = tcp.listen_on(addr).unwrap(); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); + tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { - match listener.next().await.unwrap().unwrap() { - ListenerEvent::NewAddress(a) => { - let mut iter = a.iter(); + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + TransportEvent::NewAddress { listen_addr, .. } => { + let mut iter = listen_addr.iter(); match iter.next().expect("ip address") { Protocol::Ip4(ip) => assert!(!ip.is_unspecified()), Protocol::Ip6(ip) => assert!(!ip.is_unspecified()), @@ -847,11 +988,11 @@ mod tests { if let Protocol::Tcp(port) = iter.next().expect("port") { assert_ne!(0, port) } else { - panic!("No TCP port in address: {}", a) + panic!("No TCP port in address: {}", listen_addr) } - ready_tx.send(a).await.ok(); + ready_tx.send(listen_addr).await.ok(); } - ListenerEvent::Upgrade { .. } => { + TransportEvent::Incoming { .. } => { return; } _ => {} @@ -861,7 +1002,7 @@ mod tests { async fn dialer(mut ready_rx: mpsc::Receiver) { let dest_addr = ready_rx.next().await.unwrap(); - let mut tcp = GenTcpConfig::::new(); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); tcp.dial(dest_addr).unwrap().await.unwrap(); } @@ -901,14 +1042,14 @@ mod tests { env_logger::try_init().ok(); async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { - let mut tcp = GenTcpConfig::::new(); - let mut listener = tcp.listen_on(addr).unwrap(); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); + tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { - match listener.next().await.unwrap().unwrap() { - ListenerEvent::NewAddress(listen_addr) => { + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + TransportEvent::NewAddress { listen_addr, .. } => { ready_tx.send(listen_addr).await.ok(); } - ListenerEvent::Upgrade { upgrade, .. } => { + TransportEvent::Incoming { upgrade, .. } => { let mut upgrade = upgrade.await.unwrap(); let mut buf = [0u8; 3]; upgrade.read_exact(&mut buf).await.unwrap(); @@ -923,10 +1064,10 @@ mod tests { async fn dialer(addr: Multiaddr, mut ready_rx: mpsc::Receiver) { let dest_addr = ready_rx.next().await.unwrap(); - let mut tcp = GenTcpConfig::::new().port_reuse(true); - let mut listener = tcp.clone().listen_on(addr).unwrap(); - match listener.next().await.unwrap().unwrap() { - ListenerEvent::NewAddress(_) => { + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); + tcp.listen_on(ListenerId::new(1), addr).unwrap(); + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + TransportEvent::NewAddress { .. } => { // Obtain a future socket through dialing let mut socket = tcp.dial(dest_addr).unwrap().await.unwrap(); socket.write_all(&[0x1, 0x2, 0x3]).await.unwrap(); @@ -975,14 +1116,14 @@ mod tests { env_logger::try_init().ok(); async fn listen_twice(addr: Multiaddr) { - let tcp = GenTcpConfig::::new().port_reuse(true); - let mut listener1 = tcp.clone().listen_on(addr).unwrap(); - match listener1.next().await.unwrap().unwrap() { - ListenerEvent::NewAddress(addr1) => { + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); + tcp.listen_on(ListenerId::new(1), addr).unwrap(); + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + TransportEvent::NewAddress { listen_addr: addr1, .. } => { // Listen on the same address a second time. - let mut listener2 = tcp.clone().listen_on(addr1.clone()).unwrap(); - match listener2.next().await.unwrap().unwrap() { - ListenerEvent::NewAddress(addr2) => { + tcp.listen_on(ListenerId::new(1), addr1.clone()).unwrap(); + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + TransportEvent::NewAddress { listen_addr: addr2, .. } => { assert_eq!(addr1, addr2); return; } @@ -1019,13 +1160,10 @@ mod tests { env_logger::try_init().ok(); async fn listen(addr: Multiaddr) -> Multiaddr { - GenTcpConfig::::new() - .listen_on(addr) - .unwrap() - .next() - .await - .expect("some event") - .expect("no error") + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); + tcp.listen_on(ListenerId::new(1), addr) + .unwrap(); + poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await .into_new_address() .expect("listen address") } @@ -1059,14 +1197,14 @@ mod tests { fn test(addr: Multiaddr) { #[cfg(feature = "async-io")] { - let mut tcp = TcpConfig::new(); - assert!(tcp.listen_on(addr.clone()).is_err()); + let mut tcp = TcpConfig::new(GenTcpConfig::new()); + assert!(tcp.listen_on(ListenerId::new(1), addr.clone()).is_err()); } #[cfg(feature = "tokio")] { - let mut tcp = TokioTcpConfig::new(); - assert!(tcp.listen_on(addr.clone()).is_err()); + let mut tcp = TokioTcpConfig::new(GenTcpConfig::new()); + assert!(tcp.listen_on(ListenerId::new(1), addr.clone()).is_err()); } } From 72c76f01047409f9a294c259fa40d553d3ca9d27 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 16 May 2022 02:03:07 +0200 Subject: [PATCH 04/47] *: adapt majority of other transports Adapt majority of helper transports to the new Transport trait. For most transports this just removes the extra *Listener type and instead implements that logic in `Transport::poll`. To adapt the `Boxed` transport the restriction had to be added that transport is `Unpin`. TODO: check if we can solve polling `Boxed` without the inner Transport being unpin. --- core/src/either.rs | 86 ++++------- core/src/transport.rs | 1 - core/src/transport/and_then.rs | 112 +++++--------- core/src/transport/boxed.rs | 71 ++++++--- core/src/transport/dummy.rs | 14 +- core/src/transport/map.rs | 88 ++++------- core/src/transport/map_err.rs | 4 +- core/src/transport/memory.rs | 195 ++++++++++++++---------- core/src/transport/timeout.rs | 74 +++------ core/src/transport/upgrade.rs | 97 +++++------- core/tests/transport_upgrade.rs | 14 +- muxers/mplex/benches/split_send_size.rs | 4 +- protocols/identify/src/identify.rs | 5 +- protocols/ping/src/protocol.rs | 4 +- src/bandwidth.rs | 64 +++----- swarm/src/lib.rs | 2 +- transports/tcp/src/lib.rs | 23 ++- 17 files changed, 394 insertions(+), 464 deletions(-) diff --git a/core/src/either.rs b/core/src/either.rs index df7caf600bd..4efd9e5103e 100644 --- a/core/src/either.rs +++ b/core/src/either.rs @@ -20,7 +20,7 @@ use crate::{ muxing::{StreamMuxer, StreamMuxerEvent}, - transport::{ListenerEvent, Transport, TransportError}, + transport::{ListenerId, Transport, TransportError, TransportEvent}, Multiaddr, ProtocolName, }; use futures::{ @@ -368,48 +368,6 @@ pub enum EitherOutbound { B(B::OutboundSubstream), } -/// Implements `Stream` and dispatches all method calls to either `First` or `Second`. -#[pin_project(project = EitherListenStreamProj)] -#[derive(Debug, Copy, Clone)] -#[must_use = "futures do nothing unless polled"] -pub enum EitherListenStream { - First(#[pin] A), - Second(#[pin] B), -} - -impl Stream - for EitherListenStream -where - AStream: TryStream, Error = AError>, - BStream: TryStream, Error = BError>, -{ - type Item = Result< - ListenerEvent, EitherError>, - EitherError, - >; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match self.project() { - EitherListenStreamProj::First(a) => match TryStream::try_poll_next(a, cx) { - Poll::Pending => Poll::Pending, - Poll::Ready(None) => Poll::Ready(None), - Poll::Ready(Some(Ok(le))) => Poll::Ready(Some(Ok(le - .map(EitherFuture::First) - .map_err(EitherError::A)))), - Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(EitherError::A(err)))), - }, - EitherListenStreamProj::Second(a) => match TryStream::try_poll_next(a, cx) { - Poll::Pending => Poll::Pending, - Poll::Ready(None) => Poll::Ready(None), - Poll::Ready(Some(Ok(le))) => Poll::Ready(Some(Ok(le - .map(EitherFuture::Second) - .map_err(EitherError::B)))), - Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(EitherError::B(err)))), - }, - } - } -} - /// Implements `Future` and dispatches all method calls to either `First` or `Second`. #[pin_project(project = EitherFutureProj)] #[derive(Debug, Copy, Clone)] @@ -479,11 +437,12 @@ impl ProtocolName for EitherName { } } } - +#[pin_project(project = EitherTransportProj)] #[derive(Debug, Copy, Clone)] +#[must_use = "futures do nothing unless polled"] pub enum EitherTransport { - Left(A), - Right(B), + Left(#[pin] A), + Right(#[pin] B), } impl Transport for EitherTransport @@ -493,26 +452,37 @@ where { type Output = EitherOutput; type Error = EitherError; - type Listener = EitherListenStream; type ListenerUpgrade = EitherFuture; type Dial = EitherFuture; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.project() { + EitherTransportProj::Left(a) => match a.poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(event) => Poll::Ready(event.map(EitherFuture::First, EitherError::A)), + }, + EitherTransportProj::Right(b) => match b.poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(event) => Poll::Ready(event.map(EitherFuture::Second, EitherError::B)), + }, + } + } + fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { + ) -> Result<(), TransportError> { use TransportError::*; match self { - EitherTransport::Left(a) => match a.listen_on(addr) { - Ok(listener) => Ok(EitherListenStream::First(listener)), - Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)), - Err(Other(err)) => Err(Other(EitherError::A(err))), - }, - EitherTransport::Right(b) => match b.listen_on(addr) { - Ok(listener) => Ok(EitherListenStream::Second(listener)), - Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)), - Err(Other(err)) => Err(Other(EitherError::B(err))), - }, + EitherTransport::Left(a) => a.listen_on(id, addr).map_err(|e| match e { + MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr), + Other(err) => Other(EitherError::A(err)), + }), + EitherTransport::Right(b) => b.listen_on(id, addr).map_err(|e| match e { + MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr), + Other(err) => Other(EitherError::B(err)), + }), } } diff --git a/core/src/transport.rs b/core/src/transport.rs index e015734c287..3745ffb90a6 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -467,7 +467,6 @@ where } } - /// An error during [dialing][Transport::dial] or [listening][Transport::listen_on] /// on a [`Transport`]. #[derive(Debug, Clone)] diff --git a/core/src/transport/and_then.rs b/core/src/transport/and_then.rs index f73a0caf8e6..0b114048917 100644 --- a/core/src/transport/and_then.rs +++ b/core/src/transport/and_then.rs @@ -21,15 +21,19 @@ use crate::{ connection::{ConnectedPoint, Endpoint}, either::EitherError, - transport::{ListenerEvent, Transport, TransportError}, + transport::{Transport, TransportError, TransportEvent}, }; use futures::{future::Either, prelude::*}; use multiaddr::Multiaddr; use std::{error, marker::PhantomPinned, pin::Pin, task::Context, task::Poll}; +use super::ListenerId; + /// See the `Transport::and_then` method. +#[pin_project::pin_project] #[derive(Debug, Clone)] pub struct AndThen { + #[pin] transport: T, fun: C, } @@ -49,27 +53,17 @@ where { type Output = O; type Error = EitherError; - type Listener = AndThenStream; type ListenerUpgrade = AndThenFuture; type Dial = AndThenFuture; fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - let listener = self - .transport - .listen_on(addr) - .map_err(|err| err.map(EitherError::A))?; - // Try to negotiate the protocol. - // Note that failing to negotiate a protocol will never produce a future with an error. - // Instead the `stream` will produce `Ok(Err(...))`. - // `stream` can only produce an `Err` if `listening_stream` produces an `Err`. - let stream = AndThenStream { - stream: listener, - fun: self.fun.clone(), - }; - Ok(stream) + ) -> Result<(), TransportError> { + self.transport + .listen_on(id, addr) + .map_err(|err| err.map(EitherError::A)) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -116,68 +110,38 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.transport.address_translation(server, observed) } -} - -/// Custom `Stream` to avoid boxing. -/// -/// Applies a function to every stream item. -#[pin_project::pin_project] -#[derive(Debug, Clone)] -pub struct AndThenStream { - #[pin] - stream: TListener, - fun: TMap, -} - -impl Stream - for AndThenStream -where - TListener: TryStream, Error = TTransErr>, - TListUpgr: TryFuture, - TMap: FnOnce(TTransOut, ConnectedPoint) -> TMapOut + Clone, - TMapOut: TryFuture, -{ - type Item = Result< - ListenerEvent< - AndThenFuture, - EitherError, - >, - EitherError, - >; - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); - match TryStream::try_poll_next(this.stream, cx) { - Poll::Ready(Some(Ok(event))) => { - let event = match event { - ListenerEvent::Upgrade { - upgrade, - local_addr, - remote_addr, - } => { - let point = ConnectedPoint::Listener { - local_addr: local_addr.clone(), - send_back_addr: remote_addr.clone(), - }; - ListenerEvent::Upgrade { - upgrade: AndThenFuture { - inner: Either::Left(Box::pin(upgrade)), - args: Some((this.fun.clone(), point)), - _marker: PhantomPinned, - }, - local_addr, - remote_addr, - } - } - ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a), - ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a), - ListenerEvent::Error(e) => ListenerEvent::Error(EitherError::A(e)), + match this.transport.poll(cx) { + Poll::Ready(TransportEvent::Incoming { + listener_id, + upgrade, + local_addr, + send_back_addr, + }) => { + let point = ConnectedPoint::Listener { + local_addr: local_addr.clone(), + send_back_addr: send_back_addr.clone(), }; - - Poll::Ready(Some(Ok(event))) + Poll::Ready(TransportEvent::Incoming { + listener_id, + upgrade: AndThenFuture { + inner: Either::Left(Box::pin(upgrade)), + args: Some((this.fun.clone(), point)), + _marker: PhantomPinned, + }, + local_addr, + send_back_addr, + }) + } + Poll::Ready(other) => { + let mapped = other.map( + |_upgrade| unreachable!("case already matched"), + EitherError::A, + ); + Poll::Ready(mapped) } - Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(EitherError::A(err)))), - Poll::Ready(None) => Poll::Ready(None), Poll::Pending => Poll::Pending, } } diff --git a/core/src/transport/boxed.rs b/core/src/transport/boxed.rs index 6ddf34ad950..060a2e47bf0 100644 --- a/core/src/transport/boxed.rs +++ b/core/src/transport/boxed.rs @@ -18,18 +18,24 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::transport::{ListenerEvent, Transport, TransportError}; +use crate::transport::{Transport, TransportError}; use futures::prelude::*; use multiaddr::Multiaddr; -use std::{error::Error, fmt, io, pin::Pin}; +use std::{ + error::Error, + fmt, io, + pin::Pin, + task::{Context, Poll}, +}; + +use super::{ListenerId, TransportEvent}; /// Creates a new [`Boxed`] transport from the given transport. pub fn boxed(transport: T) -> Boxed where - T: Transport + Send + Sync + 'static, + T: Transport + Send + Sync + Unpin + 'static, T::Error: Send + Sync, T::Dial: Send + 'static, - T::Listener: Send + 'static, T::ListenerUpgrade: Send + 'static, { Boxed { @@ -41,19 +47,22 @@ where /// and `ListenerUpgrade` futures are `Box`ed and only the `Output` /// and `Error` types are captured in type variables. pub struct Boxed { - inner: Box + Send + Sync>, + inner: Box + Send + Sync + Unpin>, } type Dial = Pin> + Send>>; -type Listener = - Pin, io::Error>>> + Send>>; type ListenerUpgrade = Pin> + Send>>; trait Abstract { - fn listen_on(&mut self, addr: Multiaddr) -> Result, TransportError>; + fn listen_on( + &mut self, + id: ListenerId, + addr: Multiaddr, + ) -> Result<(), TransportError>; fn dial(&mut self, addr: Multiaddr) -> Result, TransportError>; fn dial_as_listener(&mut self, addr: Multiaddr) -> Result, TransportError>; fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>>; } impl Abstract for T @@ -61,22 +70,14 @@ where T: Transport + 'static, T::Error: Send + Sync, T::Dial: Send + 'static, - T::Listener: Send + 'static, T::ListenerUpgrade: Send + 'static, { - fn listen_on(&mut self, addr: Multiaddr) -> Result, TransportError> { - let listener = Transport::listen_on(self, addr).map_err(|e| e.map(box_err))?; - let fut = listener - .map_ok(|event| { - event - .map(|upgrade| { - let up = upgrade.map_err(box_err); - Box::pin(up) as ListenerUpgrade - }) - .map_err(box_err) - }) - .map_err(box_err); - Ok(Box::pin(fut)) + fn listen_on( + &mut self, + id: ListenerId, + addr: Multiaddr, + ) -> Result<(), TransportError> { + Transport::listen_on(self, id, addr).map_err(|e| e.map(box_err)) } fn dial(&mut self, addr: Multiaddr) -> Result, TransportError> { @@ -96,6 +97,22 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { Transport::address_translation(self, server, observed) } + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>> { + match self.poll(cx) { + Poll::Ready(event) => { + let event = event.map( + |upgrade| { + let up = upgrade.map_err(box_err); + Box::pin(up) as ListenerUpgrade + }, + box_err, + ); + Poll::Ready(event) + } + Poll::Pending => Poll::Pending, + } + } } impl fmt::Debug for Boxed { @@ -107,15 +124,19 @@ impl fmt::Debug for Boxed { impl Transport for Boxed { type Output = O; type Error = io::Error; - type Listener = Listener; type ListenerUpgrade = ListenerUpgrade; type Dial = Dial; + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(self.inner.as_mut()).poll(cx) + } + fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - self.inner.listen_on(addr) + ) -> Result<(), TransportError> { + self.inner.listen_on(id, addr) } fn dial(&mut self, addr: Multiaddr) -> Result> { diff --git a/core/src/transport/dummy.rs b/core/src/transport/dummy.rs index 5862348b0d4..d21f7e48eb0 100644 --- a/core/src/transport/dummy.rs +++ b/core/src/transport/dummy.rs @@ -18,11 +18,13 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::transport::{ListenerEvent, Transport, TransportError}; +use crate::transport::{Transport, TransportError, TransportEvent}; use crate::Multiaddr; use futures::{prelude::*, task::Context, task::Poll}; use std::{fmt, io, marker::PhantomData, pin::Pin}; +use super::ListenerId; + /// Implementation of `Transport` that doesn't support any multiaddr. /// /// Useful for testing purposes, or as a fallback implementation when no protocol is available. @@ -56,16 +58,14 @@ impl Clone for DummyTransport { impl Transport for DummyTransport { type Output = TOut; type Error = io::Error; - type Listener = futures::stream::Pending< - Result, Self::Error>, - >; type ListenerUpgrade = futures::future::Pending>; type Dial = futures::future::Pending>; fn listen_on( &mut self, + _id: ListenerId, addr: Multiaddr, - ) -> Result> { + ) -> Result<(), TransportError> { Err(TransportError::MultiaddrNotSupported(addr)) } @@ -83,6 +83,10 @@ impl Transport for DummyTransport { fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option { None } + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + Poll::Pending + } } /// Implementation of `AsyncRead` and `AsyncWrite`. Not meant to be instanciated. diff --git a/core/src/transport/map.rs b/core/src/transport/map.rs index 703e1ea430b..321552f0ddd 100644 --- a/core/src/transport/map.rs +++ b/core/src/transport/map.rs @@ -20,15 +20,19 @@ use crate::{ connection::{ConnectedPoint, Endpoint}, - transport::{ListenerEvent, Transport, TransportError}, + transport::{Transport, TransportError, TransportEvent}, }; use futures::prelude::*; use multiaddr::Multiaddr; use std::{pin::Pin, task::Context, task::Poll}; +use super::ListenerId; + /// See `Transport::map`. #[derive(Debug, Copy, Clone)] +#[pin_project::pin_project] pub struct Map { + #[pin] transport: T, fun: F, } @@ -54,19 +58,15 @@ where { type Output = D; type Error = T::Error; - type Listener = MapStream; type ListenerUpgrade = MapFuture; type Dial = MapFuture; fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - let stream = self.transport.listen_on(addr)?; - Ok(MapStream { - stream, - fun: self.fun.clone(), - }) + ) -> Result<(), TransportError> { + self.transport.listen_on(id, addr) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -99,58 +99,34 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.transport.address_translation(server, observed) } -} - -/// Custom `Stream` implementation to avoid boxing. -/// -/// Maps a function over every stream item. -#[pin_project::pin_project] -#[derive(Clone, Debug)] -pub struct MapStream { - #[pin] - stream: T, - fun: F, -} -impl Stream for MapStream -where - T: TryStream, Error = E>, - X: TryFuture, - F: FnOnce(A, ConnectedPoint) -> B + Clone, -{ - type Item = Result, E>, E>; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); - match TryStream::try_poll_next(this.stream, cx) { - Poll::Ready(Some(Ok(event))) => { - let event = match event { - ListenerEvent::Upgrade { - upgrade, - local_addr, - remote_addr, - } => { - let point = ConnectedPoint::Listener { - local_addr: local_addr.clone(), - send_back_addr: remote_addr.clone(), - }; - ListenerEvent::Upgrade { - upgrade: MapFuture { - inner: upgrade, - args: Some((this.fun.clone(), point)), - }, - local_addr, - remote_addr, - } - } - ListenerEvent::NewAddress(a) => ListenerEvent::NewAddress(a), - ListenerEvent::AddressExpired(a) => ListenerEvent::AddressExpired(a), - ListenerEvent::Error(e) => ListenerEvent::Error(e), + match this.transport.poll(cx) { + Poll::Ready(TransportEvent::Incoming { + listener_id, + upgrade, + local_addr, + send_back_addr, + }) => { + let point = ConnectedPoint::Listener { + local_addr: local_addr.clone(), + send_back_addr: send_back_addr.clone(), }; - Poll::Ready(Some(Ok(event))) + Poll::Ready(TransportEvent::Incoming { + listener_id, + upgrade: MapFuture { + inner: upgrade, + args: Some((this.fun.clone(), point)), + }, + local_addr, + send_back_addr, + }) + } + Poll::Ready(other) => { + let mapped = other.map(|_upgrade| unreachable!("case already matched"), |e| e); + Poll::Ready(mapped) } - Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err(err))), - Poll::Ready(None) => Poll::Ready(None), Poll::Pending => Poll::Pending, } } diff --git a/core/src/transport/map_err.rs b/core/src/transport/map_err.rs index 6cc2c5c3662..1c4bfb29080 100644 --- a/core/src/transport/map_err.rs +++ b/core/src/transport/map_err.rs @@ -18,7 +18,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::transport::{ListenerEvent, Transport, TransportError}; +use crate::transport::{TransportEvent, Transport, TransportError}; use futures::prelude::*; use multiaddr::Multiaddr; use std::{error, pin::Pin, task::Context, task::Poll}; @@ -104,7 +104,7 @@ where F: FnOnce(T::Error) -> TErr + Clone, TErr: error::Error, { - type Item = Result, TErr>, TErr>; + type Item = Result, TErr>, TErr>; fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 40bc5d3da15..255fff0b042 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -19,7 +19,7 @@ // DEALINGS IN THE SOFTWARE. use crate::{ - transport::{ListenerEvent, TransportError}, + transport::{TransportError, TransportEvent}, Transport, }; use fnv::FnvHashMap; @@ -34,7 +34,14 @@ use lazy_static::lazy_static; use multiaddr::{Multiaddr, Protocol}; use parking_lot::Mutex; use rw_stream_sink::RwStreamSink; -use std::{collections::hash_map::Entry, error, fmt, io, num::NonZeroU64, pin::Pin}; +use std::{ + collections::{hash_map::Entry, VecDeque}, + error, fmt, io, + num::NonZeroU64, + pin::Pin, +}; + +use super::ListenerId; lazy_static! { static ref HUB: Hub = Hub(Mutex::new(FnvHashMap::default())); @@ -91,8 +98,10 @@ impl Hub { } /// Transport that supports `/memory/N` multiaddresses. -#[derive(Debug, Copy, Clone, Default)] -pub struct MemoryTransport; +#[derive(Default)] +pub struct MemoryTransport { + listeners: VecDeque>>, +} /// Connection to a `MemoryTransport` currently being opened. pub struct DialFuture { @@ -168,14 +177,55 @@ impl Future for DialFuture { impl Transport for MemoryTransport { type Output = Channel>; type Error = MemoryTransportError; - type Listener = Listener; type ListenerUpgrade = Ready>; type Dial = DialFuture; + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> + where + Self: Sized, + { + let mut remaining = self.listeners.len(); + while let Some(mut listener) = self.listeners.pop_back() { + if listener.tell_listen_addr { + listener.tell_listen_addr = false; + let listen_addr = listener.addr.clone(); + let listener_id = listener.id; + self.listeners.push_back(listener); + return Poll::Ready(TransportEvent::NewAddress { + listen_addr, + listener_id, + }); + } + + let event = match Stream::poll_next(Pin::new(&mut listener.receiver), cx) { + Poll::Pending => None, + Poll::Ready(None) => panic!("Alive listeners always have a sender."), + Poll::Ready(Some((channel, dial_port))) => Some(TransportEvent::Incoming { + listener_id: listener.id, + upgrade: future::ready(Ok(channel)), + local_addr: listener.addr.clone(), + send_back_addr: Protocol::Memory(dial_port.get()).into(), + }), + }; + + self.listeners.push_back(listener); + if let Some(event) = event { + return Poll::Ready(event); + } else { + remaining -= 1; + if remaining == 0 { + break; + } + } + } + Poll::Pending + } + fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { + ) -> Result<(), TransportError> { let port = if let Ok(port) = parse_memory_addr(&addr) { port } else { @@ -188,13 +238,15 @@ impl Transport for MemoryTransport { }; let listener = Listener { + id, port, addr: Protocol::Memory(port.get()).into(), receiver: rx, tell_listen_addr: true, }; + self.listeners.push_back(Box::pin(listener)); - Ok(listener) + Ok(()) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -245,44 +297,17 @@ impl error::Error for MemoryTransportError {} /// Listener for memory connections. pub struct Listener { + id: ListenerId, /// Port we're listening on. port: NonZeroU64, /// The address we are listening on. addr: Multiaddr, /// Receives incoming connections. receiver: ChannelReceiver, - /// Generate `ListenerEvent::NewAddress` to inform about our listen address. + /// Generate `TransportEvent::NewAddress` to inform about our listen address. tell_listen_addr: bool, } -impl Stream for Listener { - type Item = Result< - ListenerEvent>, MemoryTransportError>>, MemoryTransportError>, - MemoryTransportError, - >; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.tell_listen_addr { - self.tell_listen_addr = false; - return Poll::Ready(Some(Ok(ListenerEvent::NewAddress(self.addr.clone())))); - } - - let (channel, dial_port) = match Stream::poll_next(Pin::new(&mut self.receiver), cx) { - Poll::Pending => return Poll::Pending, - Poll::Ready(None) => panic!("Alive listeners always have a sender."), - Poll::Ready(Some(v)) => v, - }; - - let event = ListenerEvent::Upgrade { - upgrade: future::ready(Ok(channel)), - local_addr: self.addr.clone(), - remote_addr: Protocol::Memory(dial_port.get()).into(), - }; - - Poll::Ready(Some(Ok(event))) - } -} - impl Drop for Listener { fn drop(&mut self) { let val_in = HUB.unregister_port(&self.port); @@ -378,6 +403,8 @@ impl Drop for Chan { #[cfg(test)] mod tests { + use futures::future::poll_fn; + use super::*; #[test] @@ -415,32 +442,33 @@ mod tests { ); } - #[test] - fn listening_twice() { - let mut transport = MemoryTransport::default(); - assert!(transport - .listen_on("/memory/1639174018481".parse().unwrap()) - .is_ok()); - assert!(transport - .listen_on("/memory/1639174018481".parse().unwrap()) - .is_ok()); - let _listener = transport - .listen_on("/memory/1639174018481".parse().unwrap()) - .unwrap(); - assert!(transport - .listen_on("/memory/1639174018481".parse().unwrap()) - .is_err()); - assert!(transport - .listen_on("/memory/1639174018481".parse().unwrap()) - .is_err()); - drop(_listener); - assert!(transport - .listen_on("/memory/1639174018481".parse().unwrap()) - .is_ok()); - assert!(transport - .listen_on("/memory/1639174018481".parse().unwrap()) - .is_ok()); - } + // TODO: test once remove_listener is implemented + // #[test] + // fn listening_twice() { + // let mut transport = MemoryTransport::default(); + // assert!(transport + // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) + // .is_ok()); + // assert!(transport + // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) + // .is_ok()); + // let _listener = transport + // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) + // .unwrap(); + // assert!(transport + // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) + // .is_err()); + // assert!(transport + // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) + // .is_err()); + // drop(_listener); + // assert!(transport + // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) + // .is_ok()); + // assert!(transport + // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) + // .is_ok()); + // } #[test] fn port_not_in_use() { @@ -449,7 +477,10 @@ mod tests { .dial("/memory/810172461024613".parse().unwrap()) .is_err()); let _listener = transport - .listen_on("/memory/810172461024613".parse().unwrap()) + .listen_on( + ListenerId::new(1), + "/memory/810172461024613".parse().unwrap(), + ) .unwrap(); assert!(transport .dial("/memory/810172461024613".parse().unwrap()) @@ -469,13 +500,13 @@ mod tests { let mut t1 = MemoryTransport::default(); let listener = async move { - let listener = t1.listen_on(t1_addr.clone()).unwrap(); - - let upgrade = listener - .filter_map(|ev| futures::future::ready(ListenerEvent::into_upgrade(ev.unwrap()))) - .next() - .await - .unwrap(); + t1.listen_on(ListenerId::new(1), t1_addr.clone()).unwrap(); + let upgrade = loop { + let event = poll_fn(|cx| Pin::new(&mut t1).poll(cx)).await; + if let Some(upgrade) = event.into_upgrade() { + break upgrade; + } + }; let mut socket = upgrade.0.await.unwrap(); @@ -507,11 +538,15 @@ mod tests { let mut listener_transport = MemoryTransport::default(); let listener = async move { - let mut listener = listener_transport.listen_on(listener_addr.clone()).unwrap(); - while let Some(ev) = listener.next().await { - if let ListenerEvent::Upgrade { remote_addr, .. } = ev.unwrap() { + listener_transport + .listen_on(ListenerId::new(1), listener_addr.clone()) + .unwrap(); + loop { + if let TransportEvent::Incoming { send_back_addr, .. } = + poll_fn(|cx| Pin::new(&mut listener_transport).poll(cx)).await + { assert!( - remote_addr != listener_addr, + send_back_addr != listener_addr, "Expect dialer address not to equal listener address." ); return; @@ -542,11 +577,15 @@ mod tests { let mut listener_transport = MemoryTransport::default(); let listener = async move { - let mut listener = listener_transport.listen_on(listener_addr.clone()).unwrap(); - while let Some(ev) = listener.next().await { - if let ListenerEvent::Upgrade { remote_addr, .. } = ev.unwrap() { + listener_transport + .listen_on(ListenerId::new(1), listener_addr.clone()) + .unwrap(); + loop { + if let TransportEvent::Incoming { send_back_addr, .. } = + poll_fn(|cx| Pin::new(&mut listener_transport).poll(cx)).await + { let dialer_port = - NonZeroU64::new(parse_memory_addr(&remote_addr).unwrap()).unwrap(); + NonZeroU64::new(parse_memory_addr(&send_back_addr).unwrap()).unwrap(); assert!( HUB.get(&dialer_port).is_some(), diff --git a/core/src/transport/timeout.rs b/core/src/transport/timeout.rs index bb413cf8909..71bf8cb7716 100644 --- a/core/src/transport/timeout.rs +++ b/core/src/transport/timeout.rs @@ -25,20 +25,24 @@ // TODO: add example use crate::{ - transport::{ListenerEvent, TransportError}, + transport::{TransportError, TransportEvent}, Multiaddr, Transport, }; use futures::prelude::*; use futures_timer::Delay; use std::{error, fmt, io, pin::Pin, task::Context, task::Poll, time::Duration}; +use super::ListenerId; + /// A `TransportTimeout` is a `Transport` that wraps another `Transport` and adds /// timeouts to all inbound and outbound connection attempts. /// /// **Note**: `listen_on` is never subject to a timeout, only the setup of each /// individual accepted connection. #[derive(Debug, Copy, Clone)] +#[pin_project::pin_project] pub struct TransportTimeout { + #[pin] inner: InnerTrans, outgoing_timeout: Duration, incoming_timeout: Duration, @@ -80,25 +84,17 @@ where { type Output = InnerTrans::Output; type Error = TransportTimeoutError; - type Listener = TimeoutListener; type ListenerUpgrade = Timeout; type Dial = Timeout; fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - let listener = self - .inner - .listen_on(addr) - .map_err(|err| err.map(TransportTimeoutError::Other))?; - - let listener = TimeoutListener { - inner: listener, - timeout: self.incoming_timeout, - }; - - Ok(listener) + ) -> Result<(), TransportError> { + self.inner + .listen_on(id, addr) + .map_err(|err| err.map(TransportTimeoutError::Other)) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -129,45 +125,23 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.inner.address_translation(server, observed) } -} - -// TODO: can be removed and replaced with an `impl Stream` once impl Trait is fully stable -// in Rust (https://github.com/rust-lang/rust/issues/34511) -#[pin_project::pin_project] -pub struct TimeoutListener { - #[pin] - inner: InnerStream, - timeout: Duration, -} -impl Stream for TimeoutListener -where - InnerStream: TryStream, Error = E>, -{ - type Item = - Result, TransportTimeoutError>, TransportTimeoutError>; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); - - let poll_out = match TryStream::try_poll_next(this.inner, cx) { - Poll::Ready(Some(Err(err))) => { - return Poll::Ready(Some(Err(TransportTimeoutError::Other(err)))) + let timeout = *this.incoming_timeout; + match this.inner.poll(cx) { + Poll::Ready(event) => { + let event = event.map( + move |inner_fut| Timeout { + inner: inner_fut, + timer: Delay::new(timeout), + }, + TransportTimeoutError::Other, + ); + Poll::Ready(event) } - Poll::Ready(Some(Ok(v))) => v, - Poll::Ready(None) => return Poll::Ready(None), - Poll::Pending => return Poll::Pending, - }; - - let timeout = *this.timeout; - let event = poll_out - .map(move |inner_fut| Timeout { - inner: inner_fut, - timer: Delay::new(timeout), - }) - .map_err(TransportTimeoutError::Other); - - Poll::Ready(Some(Ok(event))) + Poll::Pending => Poll::Pending, + } } } diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index c72859eb57d..0e4009139a8 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -26,8 +26,8 @@ use crate::{ connection::ConnectedPoint, muxing::{StreamMuxer, StreamMuxerBox}, transport::{ - and_then::AndThen, boxed::boxed, timeout::TransportTimeout, ListenerEvent, Transport, - TransportError, + and_then::AndThen, boxed::boxed, timeout::TransportTimeout, Transport, TransportError, + TransportEvent, }, upgrade::{ self, apply_inbound, apply_outbound, InboundUpgrade, InboundUpgradeApply, OutboundUpgrade, @@ -45,6 +45,8 @@ use std::{ time::Duration, }; +use super::ListenerId; + /// A `Builder` facilitates upgrading of a [`Transport`] for use with /// a `Swarm`. /// @@ -287,16 +289,16 @@ where /// A authenticated and multiplexed transport, obtained from /// [`Authenticated::multiplex`]. #[derive(Clone)] -pub struct Multiplexed(T); +#[pin_project::pin_project] +pub struct Multiplexed(#[pin] T); impl Multiplexed { /// Boxes the authenticated, multiplexed transport, including /// the [`StreamMuxer`] and custom transport errors. pub fn boxed(self) -> super::Boxed<(PeerId, StreamMuxerBox)> where - T: Transport + Sized + Send + Sync + 'static, + T: Transport + Sized + Send + Sync + Unpin + 'static, T::Dial: Send + 'static, - T::Listener: Send + 'static, T::ListenerUpgrade: Send + 'static, T::Error: Send + Sync, M: StreamMuxer + Send + Sync + 'static, @@ -331,10 +333,16 @@ where { type Output = T::Output; type Error = T::Error; - type Listener = T::Listener; type ListenerUpgrade = T::ListenerUpgrade; type Dial = T::Dial; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.project().0.poll(cx) { + Poll::Ready(ev) => Poll::Ready(ev.map(|u| u, |e| e)), + Poll::Pending => Poll::Pending, + } + } + fn dial(&mut self, addr: Multiaddr) -> Result> { self.0.dial(addr) } @@ -348,9 +356,10 @@ where fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - self.0.listen_on(addr) + ) -> Result<(), TransportError> { + self.0.listen_on(id, addr) } fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { @@ -365,7 +374,9 @@ type EitherUpgrade = future::Either, OutboundUpg /// /// See [`Transport::upgrade`] #[derive(Debug, Copy, Clone)] +#[pin_project::pin_project] pub struct Upgrade { + #[pin] inner: T, upgrade: U, } @@ -387,7 +398,6 @@ where { type Output = (PeerId, D); type Error = TransportUpgradeError; - type Listener = ListenerStream; type ListenerUpgrade = ListenerUpgradeFuture; type Dial = DialUpgradeFuture; @@ -418,21 +428,35 @@ where fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - let stream = self - .inner - .listen_on(addr) - .map_err(|err| err.map(TransportUpgradeError::Transport))?; - Ok(ListenerStream { - stream: Box::pin(stream), - upgrade: self.upgrade.clone(), - }) + ) -> Result<(), TransportError> { + self.inner + .listen_on(id, addr) + .map_err(|err| err.map(TransportUpgradeError::Transport)) } fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.inner.address_translation(server, observed) } + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + let upgrade = this.upgrade.clone(); + match this.inner.poll(cx) { + Poll::Ready(event) => { + let event = event.map( + move |future| ListenerUpgradeFuture { + future: Box::pin(future), + upgrade: future::Either::Left(Some(upgrade)), + }, + TransportUpgradeError::Transport, + ); + Poll::Ready(event) + } + Poll::Pending => Poll::Pending, + } + } } /// Errors produced by a transport upgrade. @@ -532,43 +556,6 @@ where { } -/// The [`Transport::Listener`] stream of an [`Upgrade`]d transport. -pub struct ListenerStream { - stream: Pin>, - upgrade: U, -} - -impl Stream for ListenerStream -where - S: TryStream, Error = E>, - F: TryFuture, - C: AsyncRead + AsyncWrite + Unpin, - U: InboundUpgrade, Output = D> + Clone, -{ - type Item = Result< - ListenerEvent, TransportUpgradeError>, - TransportUpgradeError, - >; - - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match ready!(TryStream::try_poll_next(self.stream.as_mut(), cx)) { - Some(Ok(event)) => { - let event = event - .map(move |future| ListenerUpgradeFuture { - future: Box::pin(future), - upgrade: future::Either::Left(Some(self.upgrade.clone())), - }) - .map_err(TransportUpgradeError::Transport); - Poll::Ready(Some(Ok(event))) - } - Some(Err(err)) => Poll::Ready(Some(Err(TransportUpgradeError::Transport(err)))), - None => Poll::Ready(None), - } - } -} - -impl Unpin for ListenerStream {} - /// The [`Transport::ListenerUpgrade`] future of an [`Upgrade`]d transport. pub struct ListenerUpgradeFuture where diff --git a/core/tests/transport_upgrade.rs b/core/tests/transport_upgrade.rs index 9fd1e8eaabb..277eb6ba3a0 100644 --- a/core/tests/transport_upgrade.rs +++ b/core/tests/transport_upgrade.rs @@ -20,9 +20,10 @@ mod util; +use futures::future::poll_fn; use futures::prelude::*; use libp2p_core::identity; -use libp2p_core::transport::{MemoryTransport, Transport}; +use libp2p_core::transport::{ListenerId, MemoryTransport, Transport}; use libp2p_core::upgrade::{self, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; use libp2p_mplex::MplexConfig; use libp2p_noise as noise; @@ -118,12 +119,17 @@ fn upgrade_pipeline() { let listen_addr1 = Multiaddr::from(Protocol::Memory(random::())); let listen_addr2 = listen_addr1.clone(); - let mut listener = listener_transport.listen_on(listen_addr1).unwrap(); + listener_transport + .listen_on(ListenerId::new(1), listen_addr1) + .unwrap(); let server = async move { loop { - let (upgrade, _remote_addr) = - match listener.next().await.unwrap().unwrap().into_upgrade() { + let (upgrade, _send_back_addr) = + match poll_fn(|cx| Pin::new(&mut listener_transport).poll(cx)) + .await + .into_upgrade() + { Some(u) => u, None => continue, }; diff --git a/muxers/mplex/benches/split_send_size.rs b/muxers/mplex/benches/split_send_size.rs index a9704b8e767..c483a8a9466 100644 --- a/muxers/mplex/benches/split_send_size.rs +++ b/muxers/mplex/benches/split_send_size.rs @@ -99,10 +99,10 @@ fn run(transport: &mut BenchTransport, payload: &Vec, listen_addr: &Multiadd let receiver = task::spawn(async move { loop { match listener.next().await.unwrap().unwrap() { - transport::ListenerEvent::NewAddress(a) => { + transport::TransportEvent::NewAddress(a) => { addr_sender.take().unwrap().send(a).unwrap(); } - transport::ListenerEvent::Upgrade { upgrade, .. } => { + transport::TransportEvent::Upgrade { upgrade, .. } => { let (_peer, conn) = upgrade.await.unwrap(); match poll_fn(|cx| conn.poll_event(cx)).await { Ok(muxing::StreamMuxerEvent::InboundSubstream(mut s)) => { diff --git a/protocols/identify/src/identify.rs b/protocols/identify/src/identify.rs index 5f5e468365f..904ff5a65a5 100644 --- a/protocols/identify/src/identify.rs +++ b/protocols/identify/src/identify.rs @@ -22,9 +22,8 @@ use crate::handler::{IdentifyHandler, IdentifyHandlerEvent, IdentifyPush}; use crate::protocol::{IdentifyInfo, ReplySubstream, UpgradeError}; use futures::prelude::*; use libp2p_core::{ - connection::{ConnectionId, ListenerId}, - multiaddr::Protocol, - ConnectedPoint, Multiaddr, PeerId, PublicKey, + connection::ConnectionId, multiaddr::Protocol, transport::ListenerId, ConnectedPoint, + Multiaddr, PeerId, PublicKey, }; use libp2p_swarm::{ dial_opts::{self, DialOpts}, diff --git a/protocols/ping/src/protocol.rs b/protocols/ping/src/protocol.rs index ae60f67a858..b081ad2a443 100644 --- a/protocols/ping/src/protocol.rs +++ b/protocols/ping/src/protocol.rs @@ -117,7 +117,7 @@ mod tests { use super::*; use libp2p_core::{ multiaddr::multiaddr, - transport::{memory::MemoryTransport, ListenerEvent, Transport}, + transport::{memory::MemoryTransport, Transport, TransportEvent}, }; use rand::{thread_rng, Rng}; use std::time::Duration; @@ -128,7 +128,7 @@ mod tests { let mut listener = MemoryTransport.listen_on(mem_addr).unwrap(); let listener_addr = - if let Some(Some(Ok(ListenerEvent::NewAddress(a)))) = listener.next().now_or_never() { + if let Some(Some(Ok(TransportEvent::NewAddress(a)))) = listener.next().now_or_never() { a } else { panic!("MemoryTransport not listening on an address!"); diff --git a/src/bandwidth.rs b/src/bandwidth.rs index 2e22d73b163..1b810f5a0a9 100644 --- a/src/bandwidth.rs +++ b/src/bandwidth.rs @@ -20,7 +20,7 @@ use crate::{ core::{ - transport::{ListenerEvent, TransportError}, + transport::{TransportError, TransportEvent}, Transport, }, Multiaddr, @@ -31,6 +31,7 @@ use futures::{ prelude::*, ready, }; +use libp2p_core::transport::ListenerId; use std::{ convert::TryFrom as _, io, @@ -45,7 +46,9 @@ use std::{ /// Wraps around a `Transport` and counts the number of bytes that go through all the opened /// connections. #[derive(Clone)] +#[pin_project::pin_project] pub struct BandwidthLogging { + #[pin] inner: TInner, sinks: Arc, } @@ -73,18 +76,32 @@ where { type Output = BandwidthConnecLogging; type Error = TInner::Error; - type Listener = BandwidthListener; type ListenerUpgrade = BandwidthFuture; type Dial = BandwidthFuture; + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + match this.inner.poll(cx) { + Poll::Ready(event) => { + let event = event.map( + { + let sinks = this.sinks.clone(); + |inner| BandwidthFuture { inner, sinks } + }, + |e| e, + ); + Poll::Ready(event) + } + Poll::Pending => Poll::Pending, + } + } + fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - let sinks = self.sinks.clone(); - self.inner - .listen_on(addr) - .map(move |inner| BandwidthListener { inner, sinks }) + ) -> Result<(), TransportError> { + self.inner.listen_on(id, addr) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -109,39 +126,6 @@ where } } -/// Wraps around a `Stream` that produces connections. Wraps each connection around a bandwidth -/// counter. -#[pin_project::pin_project] -pub struct BandwidthListener { - #[pin] - inner: TInner, - sinks: Arc, -} - -impl Stream for BandwidthListener -where - TInner: TryStream, Error = TErr>, -{ - type Item = Result, TErr>, TErr>; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - let this = self.project(); - - let event = if let Some(event) = ready!(this.inner.try_poll_next(cx)?) { - event - } else { - return Poll::Ready(None); - }; - - let event = event.map({ - let sinks = this.sinks.clone(); - |inner| BandwidthFuture { inner, sinks } - }); - - Poll::Ready(Some(Ok(event))) - } -} - /// Wraps around a `Future` that produces a connection. Wraps the connection around a bandwidth /// counter. #[pin_project::pin_project] diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index add93f8c8d3..f4ba6318676 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -89,7 +89,7 @@ use libp2p_core::{ multiaddr::Protocol, multihash::Multihash, muxing::StreamMuxerBox, - transport::{self, TransportEvent, ListenerId, TransportError}, + transport::{self, ListenerId, TransportError, TransportEvent}, upgrade::ProtocolName, Endpoint, Executor, Multiaddr, Negotiated, PeerId, Transport, }; diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 89752e95ee9..8f4c88096c8 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -51,7 +51,7 @@ use futures_timer::Delay; use libp2p_core::{ address_translation, multiaddr::{Multiaddr, Protocol}, - transport::{TransportEvent, ListenerId, Transport, TransportError}, + transport::{ListenerId, Transport, TransportError, TransportEvent}, }; use log::debug; use smallvec::SmallVec; @@ -84,9 +84,12 @@ impl GenTcpTransport where T: Provider + Send, { - pub fn new(config: GenTcpConfig) -> Self { - GenTcpTransport { config, listeners:Default::default(), pending_events: Default::default() } + GenTcpTransport { + config, + listeners: Default::default(), + pending_events: Default::default(), + } } fn create_socket(&self, socket_addr: &SocketAddr) -> io::Result { @@ -1119,11 +1122,15 @@ mod tests { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); tcp.listen_on(ListenerId::new(1), addr).unwrap(); match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { - TransportEvent::NewAddress { listen_addr: addr1, .. } => { + TransportEvent::NewAddress { + listen_addr: addr1, .. + } => { // Listen on the same address a second time. tcp.listen_on(ListenerId::new(1), addr1.clone()).unwrap(); match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { - TransportEvent::NewAddress { listen_addr: addr2, .. } => { + TransportEvent::NewAddress { + listen_addr: addr2, .. + } => { assert_eq!(addr1, addr2); return; } @@ -1161,9 +1168,9 @@ mod tests { async fn listen(addr: Multiaddr) -> Multiaddr { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); - tcp.listen_on(ListenerId::new(1), addr) - .unwrap(); - poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await + tcp.listen_on(ListenerId::new(1), addr).unwrap(); + poll_fn(|cx| Pin::new(&mut tcp).poll(cx)) + .await .into_new_address() .expect("listen address") } From 945c4a08c3e5454c36e9d5f291607ac845688835 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sat, 21 May 2022 16:14:59 +0200 Subject: [PATCH 05/47] transports/tcp: rename *TcpConfig to *TcpTransport --- examples/chat-tokio.rs | 6 +++--- examples/ipfs-private.rs | 4 ++-- muxers/mplex/benches/split_send_size.rs | 2 +- muxers/mplex/tests/async_write.rs | 6 +++--- muxers/mplex/tests/two_peers.rs | 14 +++++++------- protocols/dcutr/examples/client.rs | 4 ++-- protocols/identify/src/identify.rs | 4 ++-- protocols/identify/src/protocol.rs | 6 +++--- protocols/kad/src/protocol.rs | 6 +++--- protocols/ping/tests/ping.rs | 4 ++-- protocols/relay/examples/relay_v2.rs | 4 ++-- protocols/request-response/tests/ping.rs | 4 ++-- src/lib.rs | 4 ++-- transports/deflate/tests/test.rs | 4 ++-- transports/noise/src/lib.rs | 4 ++-- transports/noise/tests/smoke.rs | 20 ++++++++++---------- transports/tcp/src/lib.rs | 16 ++++++++-------- transports/websocket/src/lib.rs | 2 +- 18 files changed, 57 insertions(+), 57 deletions(-) diff --git a/examples/chat-tokio.rs b/examples/chat-tokio.rs index 2400c8a98a5..eb79198bfc4 100644 --- a/examples/chat-tokio.rs +++ b/examples/chat-tokio.rs @@ -45,8 +45,8 @@ use libp2p::{ mplex, noise, swarm::{dial_opts::DialOpts, NetworkBehaviourEventProcess, SwarmBuilder, SwarmEvent}, - // `TokioTcpConfig` is available through the `tcp-tokio` feature. - tcp::TokioTcpConfig, + // `TokioTcpTransport` is available through the `tcp-tokio` feature. + tcp::TokioTcpTransport, Multiaddr, NetworkBehaviour, PeerId, @@ -72,7 +72,7 @@ async fn main() -> Result<(), Box> { // Create a tokio-based TCP transport use noise for authenticated // encryption and Mplex for multiplexing of substreams on a TCP stream. - let transport = TokioTcpConfig::new() + let transport = TokioTcpTransport::new() .nodelay(true) .upgrade(upgrade::Version::V1) .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) diff --git a/examples/ipfs-private.rs b/examples/ipfs-private.rs index fdeed494141..3a4766e382f 100644 --- a/examples/ipfs-private.rs +++ b/examples/ipfs-private.rs @@ -44,7 +44,7 @@ use libp2p::{ noise, ping, pnet::{PnetConfig, PreSharedKey}, swarm::{NetworkBehaviourEventProcess, SwarmEvent}, - tcp::TcpConfig, + tcp::TcpTransport, yamux::YamuxConfig, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport, }; @@ -61,7 +61,7 @@ pub fn build_transport( let noise_config = noise::NoiseConfig::xx(noise_keys).into_authenticated(); let yamux_config = YamuxConfig::default(); - let base_transport = TcpConfig::new().nodelay(true); + let base_transport = TcpTransport::new().nodelay(true); let maybe_encrypted = match psk { Some(psk) => EitherTransport::Left( base_transport.and_then(move |socket, _| PnetConfig::new(psk).handshake(socket)), diff --git a/muxers/mplex/benches/split_send_size.rs b/muxers/mplex/benches/split_send_size.rs index c483a8a9466..38d4e84ee02 100644 --- a/muxers/mplex/benches/split_send_size.rs +++ b/muxers/mplex/benches/split_send_size.rs @@ -165,7 +165,7 @@ fn tcp_transport(split_send_size: usize) -> BenchTransport { let mut mplex = mplex::MplexConfig::default(); mplex.set_split_send_size(split_send_size); - libp2p_tcp::TcpConfig::new() + libp2p_tcp::TcpTransport::new() .nodelay(true) .upgrade(upgrade::Version::V1) .authenticate(PlainText2Config { local_public_key }) diff --git a/muxers/mplex/tests/async_write.rs b/muxers/mplex/tests/async_write.rs index 96b608a68ad..74be06aee6a 100644 --- a/muxers/mplex/tests/async_write.rs +++ b/muxers/mplex/tests/async_write.rs @@ -20,7 +20,7 @@ use futures::{channel::oneshot, prelude::*}; use libp2p_core::{muxing, upgrade, Transport}; -use libp2p_tcp::TcpConfig; +use libp2p_tcp::TcpTransport; use std::sync::Arc; #[test] @@ -32,7 +32,7 @@ fn async_write() { let bg_thread = async_std::task::spawn(async move { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpConfig::new() + let mut transport = TcpTransport::new() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); let mut listener = transport @@ -71,7 +71,7 @@ fn async_write() { async_std::task::block_on(async { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpConfig::new() + let mut transport = TcpTransport::new() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap()); diff --git a/muxers/mplex/tests/two_peers.rs b/muxers/mplex/tests/two_peers.rs index 77e1a09997b..1d422f05b96 100644 --- a/muxers/mplex/tests/two_peers.rs +++ b/muxers/mplex/tests/two_peers.rs @@ -20,7 +20,7 @@ use futures::{channel::oneshot, prelude::*}; use libp2p_core::{muxing, upgrade, Transport}; -use libp2p_tcp::TcpConfig; +use libp2p_tcp::TcpTransport; use std::sync::Arc; #[test] @@ -32,7 +32,7 @@ fn client_to_server_outbound() { let bg_thread = async_std::task::spawn(async move { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpConfig::new() + let mut transport = TcpTransport::new() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); let mut listener = transport @@ -71,7 +71,7 @@ fn client_to_server_outbound() { async_std::task::block_on(async { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpConfig::new() + let mut transport = TcpTransport::new() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap()); @@ -100,7 +100,7 @@ fn client_to_server_inbound() { let bg_thread = async_std::task::spawn(async move { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpConfig::new() + let mut transport = TcpTransport::new() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); let mut listener = transport @@ -147,7 +147,7 @@ fn client_to_server_inbound() { async_std::task::block_on(async { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpConfig::new() + let mut transport = TcpTransport::new() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); let client = transport.dial(rx.await.unwrap()).unwrap().await.unwrap(); @@ -168,7 +168,7 @@ fn protocol_not_match() { let _bg_thread = async_std::task::spawn(async move { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpConfig::new() + let mut transport = TcpTransport::new() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); let mut listener = transport @@ -209,7 +209,7 @@ fn protocol_not_match() { // Make sure they do not connect when protocols do not match let mut mplex = libp2p_mplex::MplexConfig::new(); mplex.set_protocol_name(b"/mplextest/1.0.0"); - let mut transport = TcpConfig::new() + let mut transport = TcpTransport::new() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); match transport.dial(rx.await.unwrap()).unwrap().await { Ok(_) => { diff --git a/protocols/dcutr/examples/client.rs b/protocols/dcutr/examples/client.rs index d8cbe4aaeab..c4c250f8054 100644 --- a/protocols/dcutr/examples/client.rs +++ b/protocols/dcutr/examples/client.rs @@ -32,7 +32,7 @@ use libp2p::noise; use libp2p::ping::{Ping, PingConfig, PingEvent}; use libp2p::relay::v2::client::{self, Client}; use libp2p::swarm::{SwarmBuilder, SwarmEvent}; -use libp2p::tcp::TcpConfig; +use libp2p::tcp::TcpTransport; use libp2p::Transport; use libp2p::{identity, NetworkBehaviour, PeerId}; use log::info; @@ -95,7 +95,7 @@ fn main() -> Result<(), Box> { let transport = OrTransport::new( relay_transport, - block_on(DnsConfig::system(TcpConfig::new().port_reuse(true))).unwrap(), + block_on(DnsConfig::system(TcpTransport::new().port_reuse(true))).unwrap(), ) .upgrade(upgrade::Version::V1) .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) diff --git a/protocols/identify/src/identify.rs b/protocols/identify/src/identify.rs index 904ff5a65a5..5ea5e5f8a87 100644 --- a/protocols/identify/src/identify.rs +++ b/protocols/identify/src/identify.rs @@ -516,7 +516,7 @@ mod tests { use libp2p_mplex::MplexConfig; use libp2p_noise as noise; use libp2p_swarm::{Swarm, SwarmEvent}; - use libp2p_tcp::TcpConfig; + use libp2p_tcp::TcpTransport; fn transport() -> ( identity::PublicKey, @@ -527,7 +527,7 @@ mod tests { .into_authentic(&id_keys) .unwrap(); let pubkey = id_keys.public(); - let transport = TcpConfig::new() + let transport = TcpTransport::new() .nodelay(true) .upgrade(upgrade::Version::V1) .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) diff --git a/protocols/identify/src/protocol.rs b/protocols/identify/src/protocol.rs index 439412d5ca2..379a2477780 100644 --- a/protocols/identify/src/protocol.rs +++ b/protocols/identify/src/protocol.rs @@ -290,7 +290,7 @@ mod tests { upgrade::{self, apply_inbound, apply_outbound}, Transport, }; - use libp2p_tcp::TcpConfig; + use libp2p_tcp::TcpTransport; #[test] fn correct_transfer() { @@ -302,7 +302,7 @@ mod tests { let (tx, rx) = oneshot::channel(); let bg_task = async_std::task::spawn(async move { - let mut transport = TcpConfig::new(); + let mut transport = TcpTransport::new(); let mut listener = transport .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) @@ -347,7 +347,7 @@ mod tests { }); async_std::task::block_on(async move { - let mut transport = TcpConfig::new(); + let mut transport = TcpTransport::new(); let socket = transport.dial(rx.await.unwrap()).unwrap().await.unwrap(); let info = apply_outbound(socket, IdentifyProtocol, upgrade::Version::V1) diff --git a/protocols/kad/src/protocol.rs b/protocols/kad/src/protocol.rs index 648f7fc9e07..d5b20691648 100644 --- a/protocols/kad/src/protocol.rs +++ b/protocols/kad/src/protocol.rs @@ -603,7 +603,7 @@ where mod tests { /*// TODO: restore - use self::libp2p_tcp::TcpConfig; + use self::libp2p_tcp::TcpTransport; use self::tokio::runtime::current_thread::Runtime; use futures::{Future, Sink, Stream}; use libp2p_core::{PeerId, PublicKey, Transport}; @@ -658,7 +658,7 @@ mod tests { let (tx, rx) = mpsc::channel(); let bg_thread = thread::spawn(move || { - let transport = TcpConfig::new().with_upgrade(KademliaProtocolConfig); + let transport = TcpTransport::new().with_upgrade(KademliaProtocolConfig); let (listener, addr) = transport .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) @@ -678,7 +678,7 @@ mod tests { let _ = rt.block_on(future).unwrap(); }); - let transport = TcpConfig::new().with_upgrade(KademliaProtocolConfig); + let transport = TcpTransport::new().with_upgrade(KademliaProtocolConfig); let future = transport .dial(rx.recv().unwrap()) diff --git a/protocols/ping/tests/ping.rs b/protocols/ping/tests/ping.rs index dbde7db608d..352c77ef95b 100644 --- a/protocols/ping/tests/ping.rs +++ b/protocols/ping/tests/ping.rs @@ -31,7 +31,7 @@ use libp2p_mplex as mplex; use libp2p_noise as noise; use libp2p_ping as ping; use libp2p_swarm::{DummyBehaviour, KeepAlive, Swarm, SwarmEvent}; -use libp2p_tcp::TcpConfig; +use libp2p_tcp::TcpTransport; use libp2p_yamux as yamux; use quickcheck::*; use rand::prelude::*; @@ -248,7 +248,7 @@ fn mk_transport(muxer: MuxerChoice) -> (PeerId, transport::Boxed<(PeerId, Stream .unwrap(); ( peer_id, - TcpConfig::new() + TcpTransport::new() .nodelay(true) .upgrade(upgrade::Version::V1) .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) diff --git a/protocols/relay/examples/relay_v2.rs b/protocols/relay/examples/relay_v2.rs index 8a4ee914fce..fa44879220f 100644 --- a/protocols/relay/examples/relay_v2.rs +++ b/protocols/relay/examples/relay_v2.rs @@ -28,7 +28,7 @@ use libp2p::multiaddr::Protocol; use libp2p::ping::{Ping, PingConfig, PingEvent}; use libp2p::relay::v2::relay::{self, Relay}; use libp2p::swarm::{Swarm, SwarmEvent}; -use libp2p::tcp::TcpConfig; +use libp2p::tcp::TcpTransport; use libp2p::Transport; use libp2p::{identity, NetworkBehaviour, PeerId}; use libp2p::{noise, Multiaddr}; @@ -46,7 +46,7 @@ fn main() -> Result<(), Box> { let local_peer_id = PeerId::from(local_key.public()); println!("Local peer id: {:?}", local_peer_id); - let tcp_transport = TcpConfig::new(); + let tcp_transport = TcpTransport::new(); let noise_keys = noise::Keypair::::new() .into_authentic(&local_key) diff --git a/protocols/request-response/tests/ping.rs b/protocols/request-response/tests/ping.rs index 6cd6a732d4e..ee985b60b61 100644 --- a/protocols/request-response/tests/ping.rs +++ b/protocols/request-response/tests/ping.rs @@ -32,7 +32,7 @@ use libp2p_core::{ use libp2p_noise::{Keypair, NoiseConfig, X25519Spec}; use libp2p_request_response::*; use libp2p_swarm::{Swarm, SwarmEvent}; -use libp2p_tcp::TcpConfig; +use libp2p_tcp::TcpTransport; use rand::{self, Rng}; use std::{io, iter}; @@ -300,7 +300,7 @@ fn mk_transport() -> (PeerId, transport::Boxed<(PeerId, StreamMuxerBox)>) { .unwrap(); ( peer_id, - TcpConfig::new() + TcpTransport::new() .nodelay(true) .upgrade(upgrade::Version::V1) .authenticate(NoiseConfig::xx(noise_keys).into_authenticated()) diff --git a/src/lib.rs b/src/lib.rs index 9060d39c517..835d3f14d74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,7 +201,7 @@ pub async fn development_transport( keypair: identity::Keypair, ) -> std::io::Result> { let transport = { - let tcp = tcp::TcpConfig::new().nodelay(true); + let tcp = tcp::TcpTransport::new().nodelay(true); let dns_tcp = dns::DnsConfig::system(tcp).await?; let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone()); dns_tcp.or_transport(ws_dns_tcp) @@ -258,7 +258,7 @@ pub fn tokio_development_transport( keypair: identity::Keypair, ) -> std::io::Result> { let transport = { - let tcp = tcp::TokioTcpConfig::new().nodelay(true); + let tcp = tcp::TokioTcpTransport::new().nodelay(true); let dns_tcp = dns::TokioDnsConfig::system(tcp)?; let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone()); dns_tcp.or_transport(ws_dns_tcp) diff --git a/transports/deflate/tests/test.rs b/transports/deflate/tests/test.rs index 0bb27ed8d85..48bec03906f 100644 --- a/transports/deflate/tests/test.rs +++ b/transports/deflate/tests/test.rs @@ -21,7 +21,7 @@ use futures::{future, prelude::*}; use libp2p_core::{transport::Transport, upgrade}; use libp2p_deflate::DeflateConfig; -use libp2p_tcp::TcpConfig; +use libp2p_tcp::TcpTransport; use quickcheck::{QuickCheck, RngCore, TestResult}; #[test] @@ -44,7 +44,7 @@ fn lot_of_data() { } async fn run(message1: Vec) { - let mut transport = TcpConfig::new().and_then(|conn, endpoint| { + let mut transport = TcpTransport::new().and_then(|conn, endpoint| { upgrade::apply( conn, DeflateConfig::default(), diff --git a/transports/noise/src/lib.rs b/transports/noise/src/lib.rs index f4cc85dea4a..0b76fd048a7 100644 --- a/transports/noise/src/lib.rs +++ b/transports/noise/src/lib.rs @@ -40,14 +40,14 @@ //! //! ``` //! use libp2p_core::{identity, Transport, upgrade}; -//! use libp2p_tcp::TcpConfig; +//! use libp2p_tcp::TcpTransport; //! use libp2p_noise::{Keypair, X25519Spec, NoiseConfig}; //! //! # fn main() { //! let id_keys = identity::Keypair::generate_ed25519(); //! let dh_keys = Keypair::::new().into_authentic(&id_keys).unwrap(); //! let noise = NoiseConfig::xx(dh_keys).into_authenticated(); -//! let builder = TcpConfig::new().upgrade(upgrade::Version::V1).authenticate(noise); +//! let builder = TcpTransport::new().upgrade(upgrade::Version::V1).authenticate(noise); //! // let transport = builder.multiplex(...); //! # } //! ``` diff --git a/transports/noise/tests/smoke.rs b/transports/noise/tests/smoke.rs index 5c745c9463c..9a68c65c6ce 100644 --- a/transports/noise/tests/smoke.rs +++ b/transports/noise/tests/smoke.rs @@ -29,7 +29,7 @@ use libp2p_core::upgrade::{self, apply_inbound, apply_outbound, Negotiated}; use libp2p_noise::{ Keypair, NoiseConfig, NoiseError, NoiseOutput, RemoteIdentity, X25519Spec, X25519, }; -use libp2p_tcp::TcpConfig; +use libp2p_tcp::TcpTransport; use log::info; use quickcheck::QuickCheck; use std::{convert::TryInto, io, net::TcpStream}; @@ -41,7 +41,7 @@ fn core_upgrade_compat() { let id_keys = identity::Keypair::generate_ed25519(); let dh_keys = Keypair::::new().into_authentic(&id_keys).unwrap(); let noise = NoiseConfig::xx(dh_keys).into_authenticated(); - let _ = TcpConfig::new() + let _ = TcpTransport::new() .upgrade(upgrade::Version::V1) .authenticate(noise); } @@ -60,7 +60,7 @@ fn xx_spec() { let server_dh = Keypair::::new() .into_authentic(&server_id) .unwrap(); - let server_transport = TcpConfig::new() + let server_transport = TcpTransport::new() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -74,7 +74,7 @@ fn xx_spec() { let client_dh = Keypair::::new() .into_authentic(&client_id) .unwrap(); - let client_transport = TcpConfig::new() + let client_transport = TcpTransport::new() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -105,7 +105,7 @@ fn xx() { let client_id_public = client_id.public(); let server_dh = Keypair::::new().into_authentic(&server_id).unwrap(); - let server_transport = TcpConfig::new() + let server_transport = TcpTransport::new() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -117,7 +117,7 @@ fn xx() { .and_then(move |out, _| expect_identity(out, &client_id_public)); let client_dh = Keypair::::new().into_authentic(&client_id).unwrap(); - let client_transport = TcpConfig::new() + let client_transport = TcpTransport::new() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -148,7 +148,7 @@ fn ix() { let client_id_public = client_id.public(); let server_dh = Keypair::::new().into_authentic(&server_id).unwrap(); - let server_transport = TcpConfig::new() + let server_transport = TcpTransport::new() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -160,7 +160,7 @@ fn ix() { .and_then(move |out, _| expect_identity(out, &client_id_public)); let client_dh = Keypair::::new().into_authentic(&client_id).unwrap(); - let client_transport = TcpConfig::new() + let client_transport = TcpTransport::new() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -192,7 +192,7 @@ fn ik_xx() { let server_dh = Keypair::::new().into_authentic(&server_id).unwrap(); let server_dh_public = server_dh.public().clone(); - let server_transport = TcpConfig::new() + let server_transport = TcpTransport::new() .and_then(move |output, endpoint| { if endpoint.is_listener() { Either::Left(apply_inbound(output, NoiseConfig::ik_listener(server_dh))) @@ -208,7 +208,7 @@ fn ik_xx() { let client_dh = Keypair::::new().into_authentic(&client_id).unwrap(); let server_id_public2 = server_id_public.clone(); - let client_transport = TcpConfig::new() + let client_transport = TcpTransport::new() .and_then(move |output, endpoint| { if endpoint.is_dialer() { Either::Left(apply_outbound( diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 8f4c88096c8..74f12d219fd 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -22,7 +22,7 @@ //! //! # Usage //! -//! This crate provides a `TcpConfig` and `TokioTcpConfig`, depending on +//! This crate provides a `TcpTransport` and `TokioTcpTransport`, depending on //! the enabled features, which implement the `Transport` trait for use as a //! transport with `libp2p-core` or `libp2p-swarm`. @@ -33,14 +33,14 @@ pub use provider::async_io; /// The type of a [`GenTcpConfig`] using the `async-io` implementation. #[cfg(feature = "async-io")] -pub type TcpConfig = GenTcpTransport; +pub type TcpTransport = GenTcpTransport; #[cfg(feature = "tokio")] pub use provider::tokio; /// The type of a [`GenTcpConfig`] using the `tokio` implementation. #[cfg(feature = "tokio")] -pub type TokioTcpConfig = GenTcpTransport; +pub type TokioTcpTransport = GenTcpTransport; use futures::{ future::{self, BoxFuture, Ready}, @@ -300,12 +300,12 @@ impl GenTcpConfig { /// #[cfg(feature = "async-io")] /// #[async_std::main] /// async fn main() -> std::io::Result<()> { - /// use libp2p_tcp::{GenTcpConfig, TcpConfig}; + /// use libp2p_tcp::{GenTcpConfig, TcpTransport}; /// /// let listen_addr1: Multiaddr = "/ip4/127.0.0.1/tcp/9001".parse().unwrap(); /// let listen_addr2: Multiaddr = "/ip4/127.0.0.1/tcp/9002".parse().unwrap(); /// - /// let mut tcp1 = TcpConfig::new(GenTcpConfig::new().port_reuse(true)); + /// let mut tcp1 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)); /// tcp1.listen_on(ListenerId::new(1), listen_addr1.clone()).expect("listener"); /// match poll_fn(|cx| Pin::new(&mut tcp1).poll(cx)).await { /// TransportEvent::NewAddress { listen_addr, .. } => { @@ -316,7 +316,7 @@ impl GenTcpConfig { /// _ => {} /// } /// - /// let mut tcp2 = TcpConfig::new(GenTcpConfig::new().port_reuse(true)); + /// let mut tcp2 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)); /// tcp2.listen_on(ListenerId::new(1), listen_addr2).expect("listener"); /// match poll_fn(|cx| Pin::new(&mut tcp2).poll(cx)).await { /// TransportEvent::NewAddress { listen_addr, .. } => { @@ -1204,13 +1204,13 @@ mod tests { fn test(addr: Multiaddr) { #[cfg(feature = "async-io")] { - let mut tcp = TcpConfig::new(GenTcpConfig::new()); + let mut tcp = TcpTransport::new(GenTcpConfig::new()); assert!(tcp.listen_on(ListenerId::new(1), addr.clone()).is_err()); } #[cfg(feature = "tokio")] { - let mut tcp = TokioTcpConfig::new(GenTcpConfig::new()); + let mut tcp = TokioTcpTransport::new(GenTcpConfig::new()); assert!(tcp.listen_on(ListenerId::new(1), addr.clone()).is_err()); } } diff --git a/transports/websocket/src/lib.rs b/transports/websocket/src/lib.rs index a6a1c0971c1..4549ad7a760 100644 --- a/transports/websocket/src/lib.rs +++ b/transports/websocket/src/lib.rs @@ -237,7 +237,7 @@ mod tests { } async fn connect(listen_addr: Multiaddr) { - let ws_config = || WsConfig::new(tcp::TcpConfig::new()); + let ws_config = || WsConfig::new(tcp::TcpTransport::new()); let mut listener = ws_config().listen_on(listen_addr).expect("listener"); From d6f0e75ba4045915c2a6c6214a3ea090cfefa9cb Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 22 May 2022 17:18:21 +0200 Subject: [PATCH 06/47] core/transport: adapt remaining transports --- core/src/transport.rs | 78 ++++++++++++++++++++++------------ core/src/transport/choice.rs | 41 ++++++++++++------ core/src/transport/map.rs | 2 +- core/src/transport/map_err.rs | 61 +++++++++----------------- core/src/transport/optional.rs | 24 +++++++++-- core/src/transport/upgrade.rs | 5 +-- 6 files changed, 121 insertions(+), 90 deletions(-) diff --git a/core/src/transport.rs b/core/src/transport.rs index 3745ffb90a6..a6d0b4a6c64 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -35,23 +35,23 @@ use std::{ }; pub mod and_then; -// pub mod choice; +pub mod choice; pub mod dummy; pub mod map; -// pub mod map_err; +pub mod map_err; pub mod memory; pub mod timeout; pub mod upgrade; mod boxed; -// mod optional; +mod optional; use crate::ConnectedPoint; pub use self::boxed::Boxed; -// pub use self::choice::OrTransport; +pub use self::choice::OrTransport; pub use self::memory::MemoryTransport; -// pub use self::optional::OptionalTransport; +pub use self::optional::OptionalTransport; pub use self::upgrade::Upgrade; /// A transport provides connection-oriented communication between two peers @@ -170,28 +170,28 @@ pub trait Transport { map::Map::new(self, f) } - // /// Applies a function on the errors generated by the futures of the transport. - // fn map_err(self, f: F) -> map_err::MapErr - // where - // Self: Sized, - // F: FnOnce(Self::Error) -> E, - // { - // map_err::MapErr::new(self, f) - // } - - // /// Adds a fallback transport that is used when encountering errors - // /// while establishing inbound or outbound connections. - // /// - // /// The returned transport will act like `self`, except that if `listen_on` or `dial` - // /// return an error then `other` will be tried. - // fn or_transport(self, other: U) -> OrTransport - // where - // Self: Sized, - // U: Transport, - // ::Error: 'static, - // { - // OrTransport::new(self, other) - // } + /// Applies a function on the errors generated by the futures of the transport. + fn map_err(self, f: F) -> map_err::MapErr + where + Self: Sized, + F: FnOnce(Self::Error) -> E, + { + map_err::MapErr::new(self, f) + } + + /// Adds a fallback transport that is used when encountering errors + /// while establishing inbound or outbound connections. + /// + /// The returned transport will act like `self`, except that if `listen_on` or `dial` + /// return an error then `other` will be tried. + fn or_transport(self, other: U) -> OrTransport + where + Self: Sized, + U: Transport, + ::Error: 'static, + { + OrTransport::new(self, other) + } /// Applies a function producing an asynchronous result to every connection /// created by this transport. @@ -295,6 +295,30 @@ pub enum TransportEvent { } impl TransportEvent { + pub fn into(self) -> TransportEvent + where + U: Transport, + { + self.map(|u| u, |e| e) + } + + pub fn map_upgrade( + self, + map: impl FnOnce(T::ListenerUpgrade) -> U::ListenerUpgrade, + ) -> TransportEvent + where + U: Transport, + { + self.map(map, |e| e) + } + + pub fn map_error(self, map_err: impl FnOnce(T::Error) -> U::Error) -> TransportEvent + where + U: Transport, + { + self.map(|u| u, map_err) + } + pub fn map( self, map: impl FnOnce(T::ListenerUpgrade) -> U::ListenerUpgrade, diff --git a/core/src/transport/choice.rs b/core/src/transport/choice.rs index f1d21cfa30c..9098133aef0 100644 --- a/core/src/transport/choice.rs +++ b/core/src/transport/choice.rs @@ -18,13 +18,19 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::either::{EitherError, EitherFuture, EitherListenStream, EitherOutput}; +use std::pin::Pin; +use std::task::{Context, Poll}; + +use crate::either::{EitherError, EitherFuture, EitherOutput}; use crate::transport::{Transport, TransportError}; use multiaddr::Multiaddr; +use super::{ListenerId, TransportEvent}; + /// Struct returned by `or_transport()`. #[derive(Debug, Copy, Clone)] -pub struct OrTransport(A, B); +#[pin_project::pin_project] +pub struct OrTransport(#[pin] A, #[pin] B); impl OrTransport { pub fn new(a: A, b: B) -> OrTransport { @@ -39,28 +45,22 @@ where { type Output = EitherOutput; type Error = EitherError; - type Listener = EitherListenStream; type ListenerUpgrade = EitherFuture; type Dial = EitherFuture; fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - let addr = match self.0.listen_on(addr) { - Ok(listener) => return Ok(EitherListenStream::First(listener)), + ) -> Result<(), TransportError> { + let addr = match self.0.listen_on(id, addr) { Err(TransportError::MultiaddrNotSupported(addr)) => addr, - Err(TransportError::Other(err)) => { - return Err(TransportError::Other(EitherError::A(err))) - } + res => return res.map_err(|err| err.map(EitherError::A)), }; - let addr = match self.1.listen_on(addr) { - Ok(listener) => return Ok(EitherListenStream::Second(listener)), + let addr = match self.1.listen_on(id, addr) { Err(TransportError::MultiaddrNotSupported(addr)) => addr, - Err(TransportError::Other(err)) => { - return Err(TransportError::Other(EitherError::B(err))) - } + res => return res.map_err(|err| err.map(EitherError::B)), }; Err(TransportError::MultiaddrNotSupported(addr)) @@ -116,4 +116,17 @@ where self.1.address_translation(server, observed) } } + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + let this = self.project(); + match this.0.poll(cx) { + Poll::Ready(ev) => return Poll::Ready(ev.map(EitherFuture::First, EitherError::A)), + Poll::Pending => {} + } + match this.1.poll(cx) { + Poll::Ready(ev) => return Poll::Ready(ev.map(EitherFuture::Second, EitherError::B)), + Poll::Pending => {} + } + Poll::Pending + } } diff --git a/core/src/transport/map.rs b/core/src/transport/map.rs index 321552f0ddd..ac2ef7986e5 100644 --- a/core/src/transport/map.rs +++ b/core/src/transport/map.rs @@ -124,7 +124,7 @@ where }) } Poll::Ready(other) => { - let mapped = other.map(|_upgrade| unreachable!("case already matched"), |e| e); + let mapped = other.map_upgrade(|_upgrade| unreachable!("case already matched")); Poll::Ready(mapped) } Poll::Pending => Poll::Pending, diff --git a/core/src/transport/map_err.rs b/core/src/transport/map_err.rs index 1c4bfb29080..6690f0c7688 100644 --- a/core/src/transport/map_err.rs +++ b/core/src/transport/map_err.rs @@ -18,14 +18,18 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::transport::{TransportEvent, Transport, TransportError}; +use crate::transport::{Transport, TransportError, TransportEvent}; use futures::prelude::*; use multiaddr::Multiaddr; use std::{error, pin::Pin, task::Context, task::Poll}; +use super::ListenerId; + /// See `Transport::map_err`. #[derive(Debug, Copy, Clone)] +#[pin_project::pin_project] pub struct MapErr { + #[pin] transport: T, map: F, } @@ -45,19 +49,18 @@ where { type Output = T::Output; type Error = TErr; - type Listener = MapErrListener; type ListenerUpgrade = MapErrListenerUpgrade; type Dial = MapErrDial; fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { + ) -> Result<(), TransportError> { let map = self.map.clone(); - match self.transport.listen_on(addr) { - Ok(stream) => Ok(MapErrListener { inner: stream, map }), - Err(err) => Err(err.map(map)), - } + self.transport + .listen_on(id, addr) + .map_err(|err| err.map(map)) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -88,41 +91,19 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.transport.address_translation(server, observed) } -} - -/// Listening stream for `MapErr`. -#[pin_project::pin_project] -pub struct MapErrListener { - #[pin] - inner: T::Listener, - map: F, -} - -impl Stream for MapErrListener -where - T: Transport, - F: FnOnce(T::Error) -> TErr + Clone, - TErr: error::Error, -{ - type Item = Result, TErr>, TErr>; - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); - match TryStream::try_poll_next(this.inner, cx) { - Poll::Ready(Some(Ok(event))) => { - let map = &*this.map; - let event = event - .map(move |value| MapErrListenerUpgrade { - inner: value, - map: Some(map.clone()), - }) - .map_err(|err| (map.clone())(err)); - Poll::Ready(Some(Ok(event))) - } - Poll::Ready(None) => Poll::Ready(None), - Poll::Pending => Poll::Pending, - Poll::Ready(Some(Err(err))) => Poll::Ready(Some(Err((this.map.clone())(err)))), - } + let map = &*this.map; + this.transport.poll(cx).map(|ev| { + ev.map( + move |value| MapErrListenerUpgrade { + inner: value, + map: Some(map.clone()), + }, + |err| (map.clone())(err), + ) + }) } } diff --git a/core/src/transport/optional.rs b/core/src/transport/optional.rs index cb10c35e133..02d358fa4df 100644 --- a/core/src/transport/optional.rs +++ b/core/src/transport/optional.rs @@ -18,9 +18,16 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +use std::{ + pin::Pin, + task::{Context, Poll}, +}; + use crate::transport::{Transport, TransportError}; use multiaddr::Multiaddr; +use super::{ListenerId, TransportEvent}; + /// Transport that is possibly disabled. /// /// An `OptionalTransport` is a wrapper around an `Option`. If it is disabled (read: contains @@ -28,7 +35,8 @@ use multiaddr::Multiaddr; /// enabled (read: contains `Some`), then dialing and listening will be handled by the inner /// transport. #[derive(Debug, Copy, Clone)] -pub struct OptionalTransport(Option); +#[pin_project::pin_project] +pub struct OptionalTransport(#[pin] Option); impl OptionalTransport { /// Builds an `OptionalTransport` with the given transport in an enabled @@ -55,16 +63,16 @@ where { type Output = T::Output; type Error = T::Error; - type Listener = T::Listener; type ListenerUpgrade = T::ListenerUpgrade; type Dial = T::Dial; fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { + ) -> Result<(), TransportError> { if let Some(inner) = self.0.as_mut() { - inner.listen_on(addr) + inner.listen_on(id, addr) } else { Err(TransportError::MultiaddrNotSupported(addr)) } @@ -96,4 +104,12 @@ where None } } + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if let Some(inner) = self.project().0.as_pin_mut() { + inner.poll(cx).map(|ev| ev.into()) + } else { + Poll::Pending + } + } } diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index 0e4009139a8..d47de40b44b 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -337,10 +337,7 @@ where type Dial = T::Dial; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - match self.project().0.poll(cx) { - Poll::Ready(ev) => Poll::Ready(ev.map(|u| u, |e| e)), - Poll::Pending => Poll::Pending, - } + self.project().0.poll(cx).map(|ev| ev.into()) } fn dial(&mut self, addr: Multiaddr) -> Result> { From 858590f60529183d1d295d4ee1254ae3edc0af1e Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 22 May 2022 17:36:30 +0200 Subject: [PATCH 07/47] core/transports: unify imports, clean code --- core/src/transport.rs | 9 ++-- core/src/transport/and_then.rs | 4 +- core/src/transport/boxed.rs | 34 ++++++------- core/src/transport/choice.rs | 8 +-- core/src/transport/dummy.rs | 4 +- core/src/transport/map_err.rs | 4 +- core/src/transport/memory.rs | 89 ++++++++++++++++------------------ core/src/transport/optional.rs | 10 +--- core/src/transport/timeout.rs | 26 ++++------ core/src/transport/upgrade.rs | 28 +++++------ 10 files changed, 89 insertions(+), 127 deletions(-) diff --git a/core/src/transport.rs b/core/src/transport.rs index a6d0b4a6c64..a86ef0f2783 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -108,10 +108,6 @@ pub trait Transport { /// obtained from [dialing](Transport::dial). type Dial: Future>; - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> - where - Self: Sized; - /// Listens on the given [`Multiaddr`], producing a stream of pending, inbound connections /// and addresses this transport is listening on (cf. [`TransportEvent`]). /// @@ -145,6 +141,11 @@ pub trait Transport { where Self: Sized; + // TODO: Add docs + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> + where + Self: Sized; + /// Performs a transport-specific mapping of an address `observed` by /// a remote onto a local `listen` address to yield an address for /// the local node that may be reachable for other peers. diff --git a/core/src/transport/and_then.rs b/core/src/transport/and_then.rs index 0b114048917..9ce31109a42 100644 --- a/core/src/transport/and_then.rs +++ b/core/src/transport/and_then.rs @@ -21,14 +21,12 @@ use crate::{ connection::{ConnectedPoint, Endpoint}, either::EitherError, - transport::{Transport, TransportError, TransportEvent}, + transport::{ListenerId, Transport, TransportError, TransportEvent}, }; use futures::{future::Either, prelude::*}; use multiaddr::Multiaddr; use std::{error, marker::PhantomPinned, pin::Pin, task::Context, task::Poll}; -use super::ListenerId; - /// See the `Transport::and_then` method. #[pin_project::pin_project] #[derive(Debug, Clone)] diff --git a/core/src/transport/boxed.rs b/core/src/transport/boxed.rs index 060a2e47bf0..07d27b17e71 100644 --- a/core/src/transport/boxed.rs +++ b/core/src/transport/boxed.rs @@ -18,7 +18,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::transport::{Transport, TransportError}; +use crate::transport::{ListenerId, Transport, TransportError, TransportEvent}; use futures::prelude::*; use multiaddr::Multiaddr; use std::{ @@ -28,8 +28,6 @@ use std::{ task::{Context, Poll}, }; -use super::{ListenerId, TransportEvent}; - /// Creates a new [`Boxed`] transport from the given transport. pub fn boxed(transport: T) -> Boxed where @@ -99,19 +97,15 @@ where } fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>> { - match self.poll(cx) { - Poll::Ready(event) => { - let event = event.map( - |upgrade| { - let up = upgrade.map_err(box_err); - Box::pin(up) as ListenerUpgrade - }, - box_err, - ); - Poll::Ready(event) - } - Poll::Pending => Poll::Pending, - } + self.poll(cx).map(|event| { + event.map( + |upgrade| { + let up = upgrade.map_err(box_err); + Box::pin(up) as ListenerUpgrade + }, + box_err, + ) + }) } } @@ -127,10 +121,6 @@ impl Transport for Boxed { type ListenerUpgrade = ListenerUpgrade; type Dial = Dial; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(self.inner.as_mut()).poll(cx) - } - fn listen_on( &mut self, id: ListenerId, @@ -153,6 +143,10 @@ impl Transport for Boxed { fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.inner.address_translation(server, observed) } + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Pin::new(self.inner.as_mut()).poll(cx) + } } fn box_err(e: E) -> io::Error { diff --git a/core/src/transport/choice.rs b/core/src/transport/choice.rs index 9098133aef0..bd9cbacd3d2 100644 --- a/core/src/transport/choice.rs +++ b/core/src/transport/choice.rs @@ -18,14 +18,10 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use std::pin::Pin; -use std::task::{Context, Poll}; - use crate::either::{EitherError, EitherFuture, EitherOutput}; -use crate::transport::{Transport, TransportError}; +use crate::transport::{ListenerId, Transport, TransportError, TransportEvent}; use multiaddr::Multiaddr; - -use super::{ListenerId, TransportEvent}; +use std::{pin::Pin, task::Context, task::Poll}; /// Struct returned by `or_transport()`. #[derive(Debug, Copy, Clone)] diff --git a/core/src/transport/dummy.rs b/core/src/transport/dummy.rs index d21f7e48eb0..4c6f6fd10f7 100644 --- a/core/src/transport/dummy.rs +++ b/core/src/transport/dummy.rs @@ -18,13 +18,11 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::transport::{Transport, TransportError, TransportEvent}; +use crate::transport::{ListenerId, Transport, TransportError, TransportEvent}; use crate::Multiaddr; use futures::{prelude::*, task::Context, task::Poll}; use std::{fmt, io, marker::PhantomData, pin::Pin}; -use super::ListenerId; - /// Implementation of `Transport` that doesn't support any multiaddr. /// /// Useful for testing purposes, or as a fallback implementation when no protocol is available. diff --git a/core/src/transport/map_err.rs b/core/src/transport/map_err.rs index 6690f0c7688..097b3939977 100644 --- a/core/src/transport/map_err.rs +++ b/core/src/transport/map_err.rs @@ -18,13 +18,11 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::transport::{Transport, TransportError, TransportEvent}; +use crate::transport::{ListenerId, Transport, TransportError, TransportEvent}; use futures::prelude::*; use multiaddr::Multiaddr; use std::{error, pin::Pin, task::Context, task::Poll}; -use super::ListenerId; - /// See `Transport::map_err`. #[derive(Debug, Copy, Clone)] #[pin_project::pin_project] diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 255fff0b042..5b69452b2a9 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -18,10 +18,7 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use crate::{ - transport::{TransportError, TransportEvent}, - Transport, -}; +use crate::transport::{ListenerId, Transport, TransportError, TransportEvent}; use fnv::FnvHashMap; use futures::{ channel::mpsc, @@ -41,8 +38,6 @@ use std::{ pin::Pin, }; -use super::ListenerId; - lazy_static! { static ref HUB: Hub = Hub(Mutex::new(FnvHashMap::default())); } @@ -180,47 +175,6 @@ impl Transport for MemoryTransport { type ListenerUpgrade = Ready>; type Dial = DialFuture; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> - where - Self: Sized, - { - let mut remaining = self.listeners.len(); - while let Some(mut listener) = self.listeners.pop_back() { - if listener.tell_listen_addr { - listener.tell_listen_addr = false; - let listen_addr = listener.addr.clone(); - let listener_id = listener.id; - self.listeners.push_back(listener); - return Poll::Ready(TransportEvent::NewAddress { - listen_addr, - listener_id, - }); - } - - let event = match Stream::poll_next(Pin::new(&mut listener.receiver), cx) { - Poll::Pending => None, - Poll::Ready(None) => panic!("Alive listeners always have a sender."), - Poll::Ready(Some((channel, dial_port))) => Some(TransportEvent::Incoming { - listener_id: listener.id, - upgrade: future::ready(Ok(channel)), - local_addr: listener.addr.clone(), - send_back_addr: Protocol::Memory(dial_port.get()).into(), - }), - }; - - self.listeners.push_back(listener); - if let Some(event) = event { - return Poll::Ready(event); - } else { - remaining -= 1; - if remaining == 0 { - break; - } - } - } - Poll::Pending - } - fn listen_on( &mut self, id: ListenerId, @@ -273,6 +227,47 @@ impl Transport for MemoryTransport { fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option { None } + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> + where + Self: Sized, + { + let mut remaining = self.listeners.len(); + while let Some(mut listener) = self.listeners.pop_back() { + if listener.tell_listen_addr { + listener.tell_listen_addr = false; + let listen_addr = listener.addr.clone(); + let listener_id = listener.id; + self.listeners.push_back(listener); + return Poll::Ready(TransportEvent::NewAddress { + listen_addr, + listener_id, + }); + } + + let event = match Stream::poll_next(Pin::new(&mut listener.receiver), cx) { + Poll::Pending => None, + Poll::Ready(None) => panic!("Alive listeners always have a sender."), + Poll::Ready(Some((channel, dial_port))) => Some(TransportEvent::Incoming { + listener_id: listener.id, + upgrade: future::ready(Ok(channel)), + local_addr: listener.addr.clone(), + send_back_addr: Protocol::Memory(dial_port.get()).into(), + }), + }; + + self.listeners.push_back(listener); + if let Some(event) = event { + return Poll::Ready(event); + } else { + remaining -= 1; + if remaining == 0 { + break; + } + } + } + Poll::Pending + } } /// Error that can be produced from the `MemoryTransport`. diff --git a/core/src/transport/optional.rs b/core/src/transport/optional.rs index 02d358fa4df..48fc81e899c 100644 --- a/core/src/transport/optional.rs +++ b/core/src/transport/optional.rs @@ -18,15 +18,9 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use std::{ - pin::Pin, - task::{Context, Poll}, -}; - -use crate::transport::{Transport, TransportError}; +use crate::transport::{ListenerId, Transport, TransportError, TransportEvent}; use multiaddr::Multiaddr; - -use super::{ListenerId, TransportEvent}; +use std::{pin::Pin, task::Context, task::Poll}; /// Transport that is possibly disabled. /// diff --git a/core/src/transport/timeout.rs b/core/src/transport/timeout.rs index 71bf8cb7716..813f8073d49 100644 --- a/core/src/transport/timeout.rs +++ b/core/src/transport/timeout.rs @@ -25,15 +25,13 @@ // TODO: add example use crate::{ - transport::{TransportError, TransportEvent}, + transport::{ListenerId, TransportError, TransportEvent}, Multiaddr, Transport, }; use futures::prelude::*; use futures_timer::Delay; use std::{error, fmt, io, pin::Pin, task::Context, task::Poll, time::Duration}; -use super::ListenerId; - /// A `TransportTimeout` is a `Transport` that wraps another `Transport` and adds /// timeouts to all inbound and outbound connection attempts. /// @@ -129,19 +127,15 @@ where fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let timeout = *this.incoming_timeout; - match this.inner.poll(cx) { - Poll::Ready(event) => { - let event = event.map( - move |inner_fut| Timeout { - inner: inner_fut, - timer: Delay::new(timeout), - }, - TransportTimeoutError::Other, - ); - Poll::Ready(event) - } - Poll::Pending => Poll::Pending, - } + this.inner.poll(cx).map(|event| { + event.map( + move |inner_fut| Timeout { + inner: inner_fut, + timer: Delay::new(timeout), + }, + TransportTimeoutError::Other, + ) + }) } } diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index d47de40b44b..504b4aa055c 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -26,8 +26,8 @@ use crate::{ connection::ConnectedPoint, muxing::{StreamMuxer, StreamMuxerBox}, transport::{ - and_then::AndThen, boxed::boxed, timeout::TransportTimeout, Transport, TransportError, - TransportEvent, + and_then::AndThen, boxed::boxed, timeout::TransportTimeout, ListenerId, Transport, + TransportError, TransportEvent, }, upgrade::{ self, apply_inbound, apply_outbound, InboundUpgrade, InboundUpgradeApply, OutboundUpgrade, @@ -45,8 +45,6 @@ use std::{ time::Duration, }; -use super::ListenerId; - /// A `Builder` facilitates upgrading of a [`Transport`] for use with /// a `Swarm`. /// @@ -440,19 +438,15 @@ where fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { let this = self.project(); let upgrade = this.upgrade.clone(); - match this.inner.poll(cx) { - Poll::Ready(event) => { - let event = event.map( - move |future| ListenerUpgradeFuture { - future: Box::pin(future), - upgrade: future::Either::Left(Some(upgrade)), - }, - TransportUpgradeError::Transport, - ); - Poll::Ready(event) - } - Poll::Pending => Poll::Pending, - } + this.inner.poll(cx).map(|event| { + event.map( + move |future| ListenerUpgradeFuture { + future: Box::pin(future), + upgrade: future::Either::Left(Some(upgrade)), + }, + TransportUpgradeError::Transport, + ) + }) } } From 45f9c96d3360ff856990d5b0cca72e7f890163e4 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 22 May 2022 18:13:49 +0200 Subject: [PATCH 08/47] core/transport: split TransportEvent generics --- core/src/either.rs | 17 +++- core/src/transport.rs | 95 ++++++++++-------- core/src/transport/and_then.rs | 12 ++- core/src/transport/boxed.rs | 24 +++-- core/src/transport/choice.rs | 13 ++- core/src/transport/dummy.rs | 5 +- core/src/transport/map.rs | 5 +- core/src/transport/map_err.rs | 17 ++-- core/src/transport/memory.rs | 5 +- core/src/transport/optional.rs | 7 +- core/src/transport/timeout.rs | 14 +-- core/src/transport/upgrade.rs | 25 +++-- src/bandwidth.rs | 16 +-- swarm/src/lib.rs | 5 +- transports/tcp/src/lib.rs | 172 +++++++++++++++++---------------- 15 files changed, 250 insertions(+), 182 deletions(-) diff --git a/core/src/either.rs b/core/src/either.rs index 4efd9e5103e..66607f5cb36 100644 --- a/core/src/either.rs +++ b/core/src/either.rs @@ -455,15 +455,26 @@ where type ListenerUpgrade = EitherFuture; type Dial = EitherFuture; - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { match self.project() { EitherTransportProj::Left(a) => match a.poll(cx) { Poll::Pending => Poll::Pending, - Poll::Ready(event) => Poll::Ready(event.map(EitherFuture::First, EitherError::A)), + Poll::Ready(event) => Poll::Ready( + event + .map_upgrade(EitherFuture::First) + .map_err(EitherError::A), + ), }, EitherTransportProj::Right(b) => match b.poll(cx) { Poll::Pending => Poll::Pending, - Poll::Ready(event) => Poll::Ready(event.map(EitherFuture::Second, EitherError::B)), + Poll::Ready(event) => Poll::Ready( + event + .map_upgrade(EitherFuture::Second) + .map_err(EitherError::B), + ), }, } } diff --git a/core/src/transport.rs b/core/src/transport.rs index a86ef0f2783..2e39280b6aa 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -142,7 +142,10 @@ pub trait Transport { Self: Sized; // TODO: Add docs - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> where Self: Sized; @@ -247,7 +250,7 @@ impl std::ops::Add for ListenerId { /// listen addresses which have previously been announced via /// a `NewAddress` event and which have not been invalidated by /// an `AddressExpired` event yet. -pub enum TransportEvent { +pub enum TransportEvent { /// A new address is being listened on. NewAddress { /// The listener that is listening on the new address. @@ -267,7 +270,7 @@ pub enum TransportEvent { /// The listener that produced the upgrade. listener_id: ListenerId, /// The produced upgrade. - upgrade: T::ListenerUpgrade, + upgrade: TUpgr, /// Local connection address. local_addr: Multiaddr, /// Address used to send back data to the incoming client. @@ -281,7 +284,7 @@ pub enum TransportEvent { addresses: Vec, /// Reason for the closure. Contains `Ok(())` if the stream produced `None`, or `Err` /// if the stream produced an error. - reason: Result<(), T::Error>, + reason: Result<(), TErr>, }, /// A listener errored. /// @@ -291,40 +294,54 @@ pub enum TransportEvent { /// The ID of the listener that errored. listener_id: ListenerId, /// The error value. - error: T::Error, + error: TErr, }, } -impl TransportEvent { - pub fn into(self) -> TransportEvent - where - U: Transport, - { - self.map(|u| u, |e| e) - } - - pub fn map_upgrade( - self, - map: impl FnOnce(T::ListenerUpgrade) -> U::ListenerUpgrade, - ) -> TransportEvent - where - U: Transport, - { - self.map(map, |e| e) - } - - pub fn map_error(self, map_err: impl FnOnce(T::Error) -> U::Error) -> TransportEvent - where - U: Transport, - { - self.map(|u| u, map_err) +impl TransportEvent { + pub fn map_upgrade(self, map: impl FnOnce(TUpgr) -> U) -> TransportEvent { + match self { + TransportEvent::Incoming { + listener_id, + upgrade, + local_addr, + send_back_addr, + } => TransportEvent::Incoming { + listener_id, + upgrade: map(upgrade), + local_addr, + send_back_addr, + }, + TransportEvent::NewAddress { + listen_addr, + listener_id, + } => TransportEvent::NewAddress { + listen_addr, + listener_id, + }, + TransportEvent::AddressExpired { + listen_addr, + listener_id, + } => TransportEvent::AddressExpired { + listen_addr, + listener_id, + }, + TransportEvent::Error { listener_id, error } => { + TransportEvent::Error { listener_id, error } + } + TransportEvent::Closed { + listener_id, + addresses, + reason, + } => TransportEvent::Closed { + listener_id, + addresses, + reason, + }, + } } - pub fn map( - self, - map: impl FnOnce(T::ListenerUpgrade) -> U::ListenerUpgrade, - map_err: impl FnOnce(T::Error) -> U::Error, - ) -> TransportEvent { + pub fn map_err(self, map_err: impl FnOnce(TErr) -> E) -> TransportEvent { match self { TransportEvent::Incoming { listener_id, @@ -333,7 +350,7 @@ impl TransportEvent { send_back_addr, } => TransportEvent::Incoming { listener_id, - upgrade: map(upgrade), + upgrade, local_addr, send_back_addr, }, @@ -376,7 +393,7 @@ impl TransportEvent { /// /// Returns `None` if the event is not actually an upgrade, /// otherwise the upgrade and the remote address. - pub fn into_upgrade(self) -> Option<(T::ListenerUpgrade, Multiaddr)> { + pub fn into_upgrade(self) -> Option<(TUpgr, Multiaddr)> { if let TransportEvent::Incoming { upgrade, send_back_addr, @@ -432,7 +449,7 @@ impl TransportEvent { /// /// Returns `None` if the event is not actually a `Error`, /// otherwise the error. - pub fn into_error(self) -> Option { + pub fn into_error(self) -> Option { if let TransportEvent::Error { error, .. } = self { Some(error) } else { @@ -441,11 +458,7 @@ impl TransportEvent { } } -impl fmt::Debug for TransportEvent -where - TTrans: Transport, - TTrans::Error: fmt::Debug, -{ +impl fmt::Debug for TransportEvent { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match self { TransportEvent::NewAddress { diff --git a/core/src/transport/and_then.rs b/core/src/transport/and_then.rs index 9ce31109a42..e7e4f04a446 100644 --- a/core/src/transport/and_then.rs +++ b/core/src/transport/and_then.rs @@ -109,7 +109,10 @@ where self.transport.address_translation(server, observed) } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { let this = self.project(); match this.transport.poll(cx) { Poll::Ready(TransportEvent::Incoming { @@ -134,10 +137,9 @@ where }) } Poll::Ready(other) => { - let mapped = other.map( - |_upgrade| unreachable!("case already matched"), - EitherError::A, - ); + let mapped = other + .map_upgrade(|_upgrade| unreachable!("case already matched")) + .map_err(EitherError::A); Poll::Ready(mapped) } Poll::Pending => Poll::Pending, diff --git a/core/src/transport/boxed.rs b/core/src/transport/boxed.rs index 07d27b17e71..20e757ec8c7 100644 --- a/core/src/transport/boxed.rs +++ b/core/src/transport/boxed.rs @@ -60,7 +60,10 @@ trait Abstract { fn dial(&mut self, addr: Multiaddr) -> Result, TransportError>; fn dial_as_listener(&mut self, addr: Multiaddr) -> Result, TransportError>; fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option; - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>>; + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll, io::Error>>; } impl Abstract for T @@ -96,15 +99,17 @@ where Transport::address_translation(self, server, observed) } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll>> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll, io::Error>> { self.poll(cx).map(|event| { - event.map( - |upgrade| { + event + .map_upgrade(|upgrade| { let up = upgrade.map_err(box_err); Box::pin(up) as ListenerUpgrade - }, - box_err, - ) + }) + .map_err(box_err) }) } } @@ -144,7 +149,10 @@ impl Transport for Boxed { self.inner.address_translation(server, observed) } - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { Pin::new(self.inner.as_mut()).poll(cx) } } diff --git a/core/src/transport/choice.rs b/core/src/transport/choice.rs index bd9cbacd3d2..66765a55a36 100644 --- a/core/src/transport/choice.rs +++ b/core/src/transport/choice.rs @@ -113,14 +113,21 @@ where } } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { let this = self.project(); match this.0.poll(cx) { - Poll::Ready(ev) => return Poll::Ready(ev.map(EitherFuture::First, EitherError::A)), + Poll::Ready(ev) => { + return Poll::Ready(ev.map_upgrade(EitherFuture::First).map_err(EitherError::A)) + } Poll::Pending => {} } match this.1.poll(cx) { - Poll::Ready(ev) => return Poll::Ready(ev.map(EitherFuture::Second, EitherError::B)), + Poll::Ready(ev) => { + return Poll::Ready(ev.map_upgrade(EitherFuture::Second).map_err(EitherError::B)) + } Poll::Pending => {} } Poll::Pending diff --git a/core/src/transport/dummy.rs b/core/src/transport/dummy.rs index 4c6f6fd10f7..d96e54a54e0 100644 --- a/core/src/transport/dummy.rs +++ b/core/src/transport/dummy.rs @@ -82,7 +82,10 @@ impl Transport for DummyTransport { None } - fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + _: &mut Context<'_>, + ) -> Poll> { Poll::Pending } } diff --git a/core/src/transport/map.rs b/core/src/transport/map.rs index ac2ef7986e5..5be8bf27bc1 100644 --- a/core/src/transport/map.rs +++ b/core/src/transport/map.rs @@ -100,7 +100,10 @@ where self.transport.address_translation(server, observed) } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { let this = self.project(); match this.transport.poll(cx) { Poll::Ready(TransportEvent::Incoming { diff --git a/core/src/transport/map_err.rs b/core/src/transport/map_err.rs index 097b3939977..c71370458fd 100644 --- a/core/src/transport/map_err.rs +++ b/core/src/transport/map_err.rs @@ -90,17 +90,18 @@ where self.transport.address_translation(server, observed) } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { let this = self.project(); let map = &*this.map; this.transport.poll(cx).map(|ev| { - ev.map( - move |value| MapErrListenerUpgrade { - inner: value, - map: Some(map.clone()), - }, - |err| (map.clone())(err), - ) + ev.map_upgrade(move |value| MapErrListenerUpgrade { + inner: value, + map: Some(map.clone()), + }) + .map_err(map.clone()) }) } } diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 5b69452b2a9..76bebe583c9 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -228,7 +228,10 @@ impl Transport for MemoryTransport { None } - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> where Self: Sized, { diff --git a/core/src/transport/optional.rs b/core/src/transport/optional.rs index 48fc81e899c..ad6bc83411a 100644 --- a/core/src/transport/optional.rs +++ b/core/src/transport/optional.rs @@ -99,9 +99,12 @@ where } } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { if let Some(inner) = self.project().0.as_pin_mut() { - inner.poll(cx).map(|ev| ev.into()) + inner.poll(cx) } else { Poll::Pending } diff --git a/core/src/transport/timeout.rs b/core/src/transport/timeout.rs index 813f8073d49..eec184ea46d 100644 --- a/core/src/transport/timeout.rs +++ b/core/src/transport/timeout.rs @@ -124,17 +124,19 @@ where self.inner.address_translation(server, observed) } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { let this = self.project(); let timeout = *this.incoming_timeout; this.inner.poll(cx).map(|event| { - event.map( - move |inner_fut| Timeout { + event + .map_upgrade(move |inner_fut| Timeout { inner: inner_fut, timer: Delay::new(timeout), - }, - TransportTimeoutError::Other, - ) + }) + .map_err(TransportTimeoutError::Other) }) } } diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index 504b4aa055c..689b584b631 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -334,10 +334,6 @@ where type ListenerUpgrade = T::ListenerUpgrade; type Dial = T::Dial; - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - self.project().0.poll(cx).map(|ev| ev.into()) - } - fn dial(&mut self, addr: Multiaddr) -> Result> { self.0.dial(addr) } @@ -360,6 +356,13 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.0.address_translation(server, observed) } + + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + self.project().0.poll(cx) + } } /// An inbound or outbound upgrade. @@ -435,17 +438,19 @@ where self.inner.address_translation(server, observed) } - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { let this = self.project(); let upgrade = this.upgrade.clone(); this.inner.poll(cx).map(|event| { - event.map( - move |future| ListenerUpgradeFuture { + event + .map_upgrade(move |future| ListenerUpgradeFuture { future: Box::pin(future), upgrade: future::Either::Left(Some(upgrade)), - }, - TransportUpgradeError::Transport, - ) + }) + .map_err(TransportUpgradeError::Transport) }) } } diff --git a/src/bandwidth.rs b/src/bandwidth.rs index 1b810f5a0a9..e248f506730 100644 --- a/src/bandwidth.rs +++ b/src/bandwidth.rs @@ -79,17 +79,17 @@ where type ListenerUpgrade = BandwidthFuture; type Dial = BandwidthFuture; - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { let this = self.project(); match this.inner.poll(cx) { Poll::Ready(event) => { - let event = event.map( - { - let sinks = this.sinks.clone(); - |inner| BandwidthFuture { inner, sinks } - }, - |e| e, - ); + let event = event.map_upgrade( { + let sinks = this.sinks.clone(); + |inner| BandwidthFuture { inner, sinks } + }); Poll::Ready(event) } Poll::Pending => Poll::Pending, diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index f4ba6318676..011ed0ab3f9 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -836,7 +836,10 @@ where fn handle_listeners_event( &mut self, - event: TransportEvent>, + event: TransportEvent< + as Transport>::ListenerUpgrade, + io::Error, + >, ) -> Option>> { match event { TransportEvent::Incoming { diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 74f12d219fd..4a3696bee61 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -77,7 +77,7 @@ where /// can be resized, the only way is to use a `Pin>`. listeners: VecDeque>>>, /// Pending listeners events to return from [`ListenersStream::poll`]. - pending_events: VecDeque>, + pending_events: VecDeque::ListenerUpgrade, io::Error>>, } impl GenTcpTransport @@ -373,89 +373,6 @@ where type Dial = Pin> + Send>>; type ListenerUpgrade = Ready>; - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - // Return pending events from closed listeners. - if let Some(event) = self.pending_events.pop_front() { - return Poll::Ready(event); - } - // We remove each element from `listeners` one by one and add them back. - let mut remaining = self.listeners.len(); - while let Some(mut listener) = self.listeners.pop_back() { - match TryStream::try_poll_next(listener.as_mut(), cx) { - Poll::Pending => { - self.listeners.push_front(listener); - remaining -= 1; - if remaining == 0 { - break; - } - } - Poll::Ready(Some(Ok(TcpTransportEvent::Upgrade { - upgrade, - local_addr, - remote_addr, - }))) => { - let id = listener.listener_id; - self.listeners.push_front(listener); - return Poll::Ready(TransportEvent::Incoming { - listener_id: id, - upgrade, - local_addr, - send_back_addr: remote_addr, - }); - } - Poll::Ready(Some(Ok(TcpTransportEvent::NewAddress(a)))) => { - if listener.addresses.contains(&a) { - debug!("Transport has reported address {} multiple times", a) - } else { - listener.addresses.push(a.clone()); - } - let id = listener.listener_id; - self.listeners.push_front(listener); - return Poll::Ready(TransportEvent::NewAddress { - listener_id: id, - listen_addr: a, - }); - } - Poll::Ready(Some(Ok(TcpTransportEvent::AddressExpired(a)))) => { - listener.addresses.retain(|x| x != &a); - let id = listener.listener_id; - self.listeners.push_front(listener); - return Poll::Ready(TransportEvent::AddressExpired { - listener_id: id, - listen_addr: a, - }); - } - Poll::Ready(Some(Ok(TcpTransportEvent::Error(error)))) => { - let id = listener.listener_id; - self.listeners.push_front(listener); - return Poll::Ready(TransportEvent::Error { - listener_id: id, - error, - }); - } - Poll::Ready(None) => { - let addresses = mem::take(&mut listener.addresses).into_vec(); - return Poll::Ready(TransportEvent::Closed { - listener_id: listener.listener_id, - addresses, - reason: Ok(()), - }); - } - Poll::Ready(Some(Err(err))) => { - let addresses = mem::take(&mut listener.addresses).into_vec(); - return Poll::Ready(TransportEvent::Closed { - listener_id: listener.listener_id, - addresses, - reason: Err(err), - }); - } - } - } - - // We register the current task to be woken up if a new listener is added. - Poll::Pending - } - fn listen_on( &mut self, id: ListenerId, @@ -544,6 +461,93 @@ where PortReuse::Enabled { .. } => Some(observed.clone()), } } + + // TODO: docs + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + // Return pending events from closed listeners. + if let Some(event) = self.pending_events.pop_front() { + return Poll::Ready(event); + } + // We remove each element from `listeners` one by one and add them back. + let mut remaining = self.listeners.len(); + while let Some(mut listener) = self.listeners.pop_back() { + match TryStream::try_poll_next(listener.as_mut(), cx) { + Poll::Pending => { + self.listeners.push_front(listener); + remaining -= 1; + if remaining == 0 { + break; + } + } + Poll::Ready(Some(Ok(TcpTransportEvent::Upgrade { + upgrade, + local_addr, + remote_addr, + }))) => { + let id = listener.listener_id; + self.listeners.push_front(listener); + return Poll::Ready(TransportEvent::Incoming { + listener_id: id, + upgrade, + local_addr, + send_back_addr: remote_addr, + }); + } + Poll::Ready(Some(Ok(TcpTransportEvent::NewAddress(a)))) => { + if listener.addresses.contains(&a) { + debug!("Transport has reported address {} multiple times", a) + } else { + listener.addresses.push(a.clone()); + } + let id = listener.listener_id; + self.listeners.push_front(listener); + return Poll::Ready(TransportEvent::NewAddress { + listener_id: id, + listen_addr: a, + }); + } + Poll::Ready(Some(Ok(TcpTransportEvent::AddressExpired(a)))) => { + listener.addresses.retain(|x| x != &a); + let id = listener.listener_id; + self.listeners.push_front(listener); + return Poll::Ready(TransportEvent::AddressExpired { + listener_id: id, + listen_addr: a, + }); + } + Poll::Ready(Some(Ok(TcpTransportEvent::Error(error)))) => { + let id = listener.listener_id; + self.listeners.push_front(listener); + return Poll::Ready(TransportEvent::Error { + listener_id: id, + error, + }); + } + Poll::Ready(None) => { + let addresses = mem::take(&mut listener.addresses).into_vec(); + return Poll::Ready(TransportEvent::Closed { + listener_id: listener.listener_id, + addresses, + reason: Ok(()), + }); + } + Poll::Ready(Some(Err(err))) => { + let addresses = mem::take(&mut listener.addresses).into_vec(); + return Poll::Ready(TransportEvent::Closed { + listener_id: listener.listener_id, + addresses, + reason: Err(err), + }); + } + } + } + + // We register the current task to be woken up if a new listener is added. + Poll::Pending + } } #[derive(Debug)] From bfd5fb0f73498cca3de2bb8f5051ad32c3e27193 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 22 May 2022 20:30:55 +0200 Subject: [PATCH 09/47] core/transport: impl Stream for transport::Boxed --- core/src/transport/boxed.rs | 16 +++++++++++++++- core/src/transport/memory.rs | 16 ++++++---------- core/tests/transport_upgrade.rs | 18 +++++++----------- src/bandwidth.rs | 2 +- swarm/src/lib.rs | 7 +++---- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/core/src/transport/boxed.rs b/core/src/transport/boxed.rs index 20e757ec8c7..6ae4005972f 100644 --- a/core/src/transport/boxed.rs +++ b/core/src/transport/boxed.rs @@ -19,7 +19,7 @@ // DEALINGS IN THE SOFTWARE. use crate::transport::{ListenerId, Transport, TransportError, TransportEvent}; -use futures::prelude::*; +use futures::{prelude::*, stream::FusedStream}; use multiaddr::Multiaddr; use std::{ error::Error, @@ -157,6 +157,20 @@ impl Transport for Boxed { } } +impl Stream for Boxed { + type Item = TransportEvent, io::Error>; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Transport::poll(self, cx).map(Some) + } +} + +impl FusedStream for Boxed { + fn is_terminated(&self) -> bool { + false + } +} + fn box_err(e: E) -> io::Error { io::Error::new(io::ErrorKind::Other, e) } diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 76bebe583c9..08cc5b64878 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -401,8 +401,6 @@ impl Drop for Chan { #[cfg(test)] mod tests { - use futures::future::poll_fn; - use super::*; #[test] @@ -495,12 +493,12 @@ mod tests { let t1_addr: Multiaddr = format!("/memory/{}", rand_port).parse().unwrap(); let cloned_t1_addr = t1_addr.clone(); - let mut t1 = MemoryTransport::default(); + let mut t1 = MemoryTransport::default().boxed(); let listener = async move { t1.listen_on(ListenerId::new(1), t1_addr.clone()).unwrap(); let upgrade = loop { - let event = poll_fn(|cx| Pin::new(&mut t1).poll(cx)).await; + let event = t1.select_next_some().await; if let Some(upgrade) = event.into_upgrade() { break upgrade; } @@ -533,16 +531,14 @@ mod tests { Protocol::Memory(rand::random::().saturating_add(1)).into(); let listener_addr_cloned = listener_addr.clone(); - let mut listener_transport = MemoryTransport::default(); + let mut listener_transport = MemoryTransport::default().boxed(); let listener = async move { listener_transport .listen_on(ListenerId::new(1), listener_addr.clone()) .unwrap(); loop { - if let TransportEvent::Incoming { send_back_addr, .. } = - poll_fn(|cx| Pin::new(&mut listener_transport).poll(cx)).await - { + if let TransportEvent::Incoming { send_back_addr, .. } = listener_transport.select_next_some().await { assert!( send_back_addr != listener_addr, "Expect dialer address not to equal listener address." @@ -572,7 +568,7 @@ mod tests { Protocol::Memory(rand::random::().saturating_add(1)).into(); let listener_addr_cloned = listener_addr.clone(); - let mut listener_transport = MemoryTransport::default(); + let mut listener_transport = MemoryTransport::default().boxed(); let listener = async move { listener_transport @@ -580,7 +576,7 @@ mod tests { .unwrap(); loop { if let TransportEvent::Incoming { send_back_addr, .. } = - poll_fn(|cx| Pin::new(&mut listener_transport).poll(cx)).await + listener_transport.select_next_some().await { let dialer_port = NonZeroU64::new(parse_memory_addr(&send_back_addr).unwrap()).unwrap(); diff --git a/core/tests/transport_upgrade.rs b/core/tests/transport_upgrade.rs index 277eb6ba3a0..89106666af8 100644 --- a/core/tests/transport_upgrade.rs +++ b/core/tests/transport_upgrade.rs @@ -20,7 +20,6 @@ mod util; -use futures::future::poll_fn; use futures::prelude::*; use libp2p_core::identity; use libp2p_core::transport::{ListenerId, MemoryTransport, Transport}; @@ -96,7 +95,7 @@ fn upgrade_pipeline() { // Gracefully close the connection to allow protocol // negotiation to complete. util::CloseMuxer::new(mplex).map_ok(move |mplex| (peer, mplex)) - }); + }).boxed(); let dialer_keys = identity::Keypair::generate_ed25519(); let dialer_id = dialer_keys.public().to_peer_id(); @@ -114,7 +113,8 @@ fn upgrade_pipeline() { // Gracefully close the connection to allow protocol // negotiation to complete. util::CloseMuxer::new(mplex).map_ok(move |mplex| (peer, mplex)) - }); + }) + .boxed(); let listen_addr1 = Multiaddr::from(Protocol::Memory(random::())); let listen_addr2 = listen_addr1.clone(); @@ -125,14 +125,10 @@ fn upgrade_pipeline() { let server = async move { loop { - let (upgrade, _send_back_addr) = - match poll_fn(|cx| Pin::new(&mut listener_transport).poll(cx)) - .await - .into_upgrade() - { - Some(u) => u, - None => continue, - }; + let (upgrade, _send_back_addr) = match listener_transport.select_next_some().await.into_upgrade() { + Some(u) => u, + None => continue, + }; let (peer, _mplex) = upgrade.await.unwrap(); assert_eq!(peer, dialer_id); } diff --git a/src/bandwidth.rs b/src/bandwidth.rs index e248f506730..1482c7a7cb1 100644 --- a/src/bandwidth.rs +++ b/src/bandwidth.rs @@ -86,7 +86,7 @@ where let this = self.project(); match this.inner.poll(cx) { Poll::Ready(event) => { - let event = event.map_upgrade( { + let event = event.map_upgrade({ let sinks = this.sinks.clone(); |inner| BandwidthFuture { inner, sinks } }); diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 011ed0ab3f9..0fe42ce622b 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -2069,12 +2069,12 @@ mod tests { let mut listen_addresses = Vec::new(); let mut transports = Vec::new(); for _ in 0..num_listen_addrs { - let mut transport = transport::MemoryTransport::default(); + let mut transport = transport::MemoryTransport::default().boxed(); transport .listen_on(ListenerId::new(1), "/memory/0".parse().unwrap()) .unwrap(); - match poll_fn(|cx| Pin::new(&mut transport).poll(cx)).await { + match transport.select_next_some().await { TransportEvent::NewAddress { listen_addr, .. } => { listen_addresses.push(listen_addr); } @@ -2094,9 +2094,8 @@ mod tests { ) .unwrap(); for mut transport in transports.into_iter() { - let poll_transport = poll_fn(|cx| Pin::new(&mut transport).poll(cx)); loop { - match futures::future::select(poll_transport, swarm.next()).await { + match futures::future::select(transport.select_next_some(), swarm.next()).await { Either::Left((TransportEvent::Incoming { .. }, _)) => { break; } From 90721b91bf151a0e4f4c5fc47931de1987f92121 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 22 May 2022 20:38:38 +0200 Subject: [PATCH 10/47] transports/tcp: impl Stream for GenTcpTransport --- transports/tcp/src/lib.rs | 67 +++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 4a3696bee61..9aff4bc98d0 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -45,7 +45,7 @@ pub type TokioTcpTransport = GenTcpTransport; use futures::{ future::{self, BoxFuture, Ready}, prelude::*, - ready, + ready, stream::FusedStream, }; use futures_timer::Delay; use libp2p_core::{ @@ -293,9 +293,9 @@ impl GenTcpConfig { /// following example: /// /// ```no_run + /// # use futures::StreamExt; /// # use libp2p_core::transport::{ListenerId, TransportEvent}; /// # use libp2p_core::{Multiaddr, Transport}; - /// # use futures::{stream::StreamExt, future::poll_fn}; /// # use std::pin::Pin; /// #[cfg(feature = "async-io")] /// #[async_std::main] @@ -307,7 +307,7 @@ impl GenTcpConfig { /// /// let mut tcp1 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)); /// tcp1.listen_on(ListenerId::new(1), listen_addr1.clone()).expect("listener"); - /// match poll_fn(|cx| Pin::new(&mut tcp1).poll(cx)).await { + /// match tcp1.select_next_some().await { /// TransportEvent::NewAddress { listen_addr, .. } => { /// println!("Listening on {:?}", listen_addr); /// let mut stream = tcp1.dial(listen_addr2.clone()).unwrap().await?; @@ -318,7 +318,7 @@ impl GenTcpConfig { /// /// let mut tcp2 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)); /// tcp2.listen_on(ListenerId::new(1), listen_addr2).expect("listener"); - /// match poll_fn(|cx| Pin::new(&mut tcp2).poll(cx)).await { + /// match tcp2.select_next_some().await { /// TransportEvent::NewAddress { listen_addr, .. } => { /// println!("Listening on {:?}", listen_addr); /// let mut socket = tcp2.dial(listen_addr1).unwrap().await?; @@ -550,6 +550,32 @@ where } } +impl Stream for GenTcpTransport +where + T: Provider + Send + 'static, + T::Listener: Unpin, + T::IfWatcher: Unpin, + T::Stream: Unpin, +{ + type Item = TransportEvent<::ListenerUpgrade, ::Error>; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + Transport::poll(self, cx).map(Some) + } +} +impl FusedStream for GenTcpTransport +where + T: Provider + Send + 'static, + T::Listener: Unpin, + T::IfWatcher: Unpin, + T::Stream: Unpin, +{ + fn is_terminated(&self) -> bool { + false + } +} + + #[derive(Debug)] pub enum TcpTransportEvent { /// The transport is listening on a new additional [`Multiaddr`]. @@ -855,7 +881,7 @@ fn ip_to_multiaddr(ip: IpAddr, port: u16) -> Multiaddr { #[cfg(test)] mod tests { use super::*; - use futures::{channel::mpsc, future::poll_fn}; + use futures::channel::mpsc; #[test] fn multiaddr_to_tcp_conversion() { @@ -914,7 +940,7 @@ mod tests { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { - match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr, .. } => { ready_tx.send(listen_addr).await.unwrap(); } @@ -984,7 +1010,7 @@ mod tests { tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { - match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr, .. } => { let mut iter = listen_addr.iter(); match iter.next().expect("ip address") { @@ -1052,7 +1078,7 @@ mod tests { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { - match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr, .. } => { ready_tx.send(listen_addr).await.ok(); } @@ -1073,7 +1099,7 @@ mod tests { let dest_addr = ready_rx.next().await.unwrap(); let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); tcp.listen_on(ListenerId::new(1), addr).unwrap(); - match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + match tcp.select_next_some().await { TransportEvent::NewAddress { .. } => { // Obtain a future socket through dialing let mut socket = tcp.dial(dest_addr).unwrap().await.unwrap(); @@ -1122,16 +1148,22 @@ mod tests { fn port_reuse_listening() { env_logger::try_init().ok(); - async fn listen_twice(addr: Multiaddr) { + async fn listen_twice(addr: Multiaddr) + where + T: Provider + Sized + Send + Sync + Unpin + 'static, + T::Listener: Sync, + T::IfWatcher: Sync, + T::Stream: Sync, + { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); tcp.listen_on(ListenerId::new(1), addr).unwrap(); - match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr: addr1, .. } => { // Listen on the same address a second time. tcp.listen_on(ListenerId::new(1), addr1.clone()).unwrap(); - match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { + match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr: addr2, .. } => { @@ -1170,13 +1202,14 @@ mod tests { fn listen_port_0() { env_logger::try_init().ok(); - async fn listen(addr: Multiaddr) -> Multiaddr { + async fn listen(addr: Multiaddr) -> Multiaddr + where + T: Provider, + T::IfWatcher: Sync + { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); tcp.listen_on(ListenerId::new(1), addr).unwrap(); - poll_fn(|cx| Pin::new(&mut tcp).poll(cx)) - .await - .into_new_address() - .expect("listen address") + tcp.select_next_some().await.into_new_address().expect("listen address") } fn test(addr: Multiaddr) { From 80c3da12d265ffc86f50d9e5b8754a8de3e94e1c Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Fri, 27 May 2022 00:09:13 +0200 Subject: [PATCH 11/47] *: format --- core/src/transport/memory.rs | 4 +++- core/tests/transport_upgrade.rs | 12 +++++++----- swarm/src/lib.rs | 4 +++- transports/tcp/src/lib.rs | 19 +++++++++++-------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 08cc5b64878..6e7da33a7c8 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -538,7 +538,9 @@ mod tests { .listen_on(ListenerId::new(1), listener_addr.clone()) .unwrap(); loop { - if let TransportEvent::Incoming { send_back_addr, .. } = listener_transport.select_next_some().await { + if let TransportEvent::Incoming { send_back_addr, .. } = + listener_transport.select_next_some().await + { assert!( send_back_addr != listener_addr, "Expect dialer address not to equal listener address." diff --git a/core/tests/transport_upgrade.rs b/core/tests/transport_upgrade.rs index 89106666af8..e59005cdf19 100644 --- a/core/tests/transport_upgrade.rs +++ b/core/tests/transport_upgrade.rs @@ -95,7 +95,8 @@ fn upgrade_pipeline() { // Gracefully close the connection to allow protocol // negotiation to complete. util::CloseMuxer::new(mplex).map_ok(move |mplex| (peer, mplex)) - }).boxed(); + }) + .boxed(); let dialer_keys = identity::Keypair::generate_ed25519(); let dialer_id = dialer_keys.public().to_peer_id(); @@ -125,10 +126,11 @@ fn upgrade_pipeline() { let server = async move { loop { - let (upgrade, _send_back_addr) = match listener_transport.select_next_some().await.into_upgrade() { - Some(u) => u, - None => continue, - }; + let (upgrade, _send_back_addr) = + match listener_transport.select_next_some().await.into_upgrade() { + Some(u) => u, + None => continue, + }; let (peer, _mplex) = upgrade.await.unwrap(); assert_eq!(peer, dialer_id); } diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 0fe42ce622b..66c3cc4174c 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -2095,7 +2095,9 @@ mod tests { .unwrap(); for mut transport in transports.into_iter() { loop { - match futures::future::select(transport.select_next_some(), swarm.next()).await { + match futures::future::select(transport.select_next_some(), swarm.next()) + .await + { Either::Left((TransportEvent::Incoming { .. }, _)) => { break; } diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 9aff4bc98d0..be2f235deaf 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -45,7 +45,8 @@ pub type TokioTcpTransport = GenTcpTransport; use futures::{ future::{self, BoxFuture, Ready}, prelude::*, - ready, stream::FusedStream, + ready, + stream::FusedStream, }; use futures_timer::Delay; use libp2p_core::{ @@ -550,7 +551,7 @@ where } } -impl Stream for GenTcpTransport +impl Stream for GenTcpTransport where T: Provider + Send + 'static, T::Listener: Unpin, @@ -563,7 +564,7 @@ where Transport::poll(self, cx).map(Some) } } -impl FusedStream for GenTcpTransport +impl FusedStream for GenTcpTransport where T: Provider + Send + 'static, T::Listener: Unpin, @@ -574,7 +575,6 @@ where false } } - #[derive(Debug)] pub enum TcpTransportEvent { @@ -1202,14 +1202,17 @@ mod tests { fn listen_port_0() { env_logger::try_init().ok(); - async fn listen(addr: Multiaddr) -> Multiaddr - where + async fn listen(addr: Multiaddr) -> Multiaddr + where T: Provider, - T::IfWatcher: Sync + T::IfWatcher: Sync, { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); tcp.listen_on(ListenerId::new(1), addr).unwrap(); - tcp.select_next_some().await.into_new_address().expect("listen address") + tcp.select_next_some() + .await + .into_new_address() + .expect("listen address") } fn test(addr: Multiaddr) { From bcb71a107eaf346893f148b18658afdef17dac79 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Fri, 27 May 2022 00:09:35 +0200 Subject: [PATCH 12/47] transports/dns: adapt dns transport --- transports/dns/src/lib.rs | 78 +++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/transports/dns/src/lib.rs b/transports/dns/src/lib.rs index c5b605720ea..9bf1e6e8183 100644 --- a/transports/dns/src/lib.rs +++ b/transports/dns/src/lib.rs @@ -60,15 +60,23 @@ use futures::{future::BoxFuture, prelude::*}; use libp2p_core::{ connection::Endpoint, multiaddr::{Multiaddr, Protocol}, - transport::{ListenerEvent, TransportError}, + transport::{ListenerId, TransportError, TransportEvent}, Transport, }; use parking_lot::Mutex; use smallvec::SmallVec; #[cfg(any(feature = "async-std", feature = "tokio"))] use std::io; -use std::sync::Arc; -use std::{convert::TryFrom, error, fmt, iter, net::IpAddr, str}; +use std::{ + convert::TryFrom, + error, fmt, iter, + net::IpAddr, + ops::DerefMut, + pin::Pin, + str, + sync::Arc, + task::{Context, Poll}, +}; #[cfg(any(feature = "async-std", feature = "tokio"))] use trust_dns_resolver::system_conf; use trust_dns_resolver::{proto::xfer::dns_handle::DnsHandle, AsyncResolver, ConnectionProvider}; @@ -175,7 +183,7 @@ where impl Transport for GenDnsConfig where - T: Transport + Clone + Send + 'static, + T: Transport + Clone + Send + Unpin + 'static, T::Error: Send, T::Dial: Send, C: DnsHandle, @@ -183,15 +191,6 @@ where { type Output = T::Output; type Error = DnsErr; - type Listener = stream::MapErr< - stream::MapOk< - T::Listener, - fn( - ListenerEvent, - ) -> ListenerEvent, - >, - fn(T::Error) -> Self::Error, - >; type ListenerUpgrade = future::MapErr Self::Error>; type Dial = future::Either< future::MapErr Self::Error>, @@ -200,21 +199,13 @@ where fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - let listener = self - .inner + ) -> Result<(), TransportError> { + self.inner .lock() - .listen_on(addr) - .map_err(|err| err.map(DnsErr::Transport))?; - let listener = listener - .map_ok::<_, fn(_) -> _>(|event| { - event - .map(|upgr| upgr.map_err::<_, fn(_) -> _>(DnsErr::Transport)) - .map_err(DnsErr::Transport) - }) - .map_err::<_, fn(_) -> _>(DnsErr::Transport); - Ok(listener) + .listen_on(id, addr) + .map_err(|e| e.map(DnsErr::Transport)) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -231,11 +222,23 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.inner.lock().address_translation(server, observed) } + + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + let mut inner = self.inner.lock(); + Transport::poll(Pin::new(inner.deref_mut()), cx).map(|event| { + event + .map_upgrade(|upgr| upgr.map_err::<_, fn(_) -> _>(DnsErr::Transport)) + .map_err(DnsErr::Transport) + }) + } } impl GenDnsConfig where - T: Transport + Clone + Send + 'static, + T: Transport + Clone + Send + Unpin + 'static, T::Error: Send, T::Dial: Send, C: DnsHandle, @@ -572,11 +575,10 @@ fn invalid_data(e: impl Into>) -> io::E #[cfg(test)] mod tests { use super::*; - use futures::{future::BoxFuture, stream::BoxStream}; + use futures::future::BoxFuture; use libp2p_core::{ multiaddr::{Multiaddr, Protocol}, - transport::ListenerEvent, - transport::TransportError, + transport::{TransportError, TransportEvent}, PeerId, Transport, }; @@ -590,17 +592,14 @@ mod tests { impl Transport for CustomTransport { type Output = (); type Error = std::io::Error; - type Listener = BoxStream< - 'static, - Result, Self::Error>, - >; type ListenerUpgrade = BoxFuture<'static, Result>; type Dial = BoxFuture<'static, Result>; fn listen_on( &mut self, + _: ListenerId, _: Multiaddr, - ) -> Result> { + ) -> Result<(), TransportError> { unreachable!() } @@ -626,13 +625,20 @@ mod tests { fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option { None } + + fn poll( + self: Pin<&mut Self>, + _: &mut Context<'_>, + ) -> Poll> { + unreachable!() + } } async fn run(transport: GenDnsConfig) where C: DnsHandle, P: ConnectionProvider, - T: Transport + Clone + Send + 'static, + T: Transport + Clone + Send + Unpin + 'static, T::Error: Send, T::Dial: Send, { From 38a2b7825d0506df53eedd8d51b1d5de51a56ebf Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Fri, 27 May 2022 00:09:52 +0200 Subject: [PATCH 13/47] transports/dns: adapt websocket transport --- transports/websocket/Cargo.toml | 1 + transports/websocket/src/framed.rs | 357 +++++++++++++++++------------ transports/websocket/src/lib.rs | 58 ++--- 3 files changed, 247 insertions(+), 169 deletions(-) diff --git a/transports/websocket/Cargo.toml b/transports/websocket/Cargo.toml index bc93facae9b..77614564a65 100644 --- a/transports/websocket/Cargo.toml +++ b/transports/websocket/Cargo.toml @@ -17,6 +17,7 @@ futures = "0.3.1" libp2p-core = { version = "0.33.0", path = "../../core", default-features = false } log = "0.4.8" parking_lot = "0.12.0" +pin-project = "1.0.10" quicksink = "0.1" rw-stream-sink = "0.2.0" soketto = { version = "0.7.0", features = ["deflate"] } diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index c04e7354587..4ed726a7a8e 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -26,7 +26,7 @@ use libp2p_core::{ connection::Endpoint, either::EitherOutput, multiaddr::{Multiaddr, Protocol}, - transport::{ListenerEvent, TransportError}, + transport::{ListenerId, TransportError, TransportEvent}, Transport, }; use log::{debug, trace}; @@ -36,7 +36,7 @@ use soketto::{ extension::deflate::Deflate, handshake, }; -use std::sync::Arc; +use std::{collections::HashMap, ops::DerefMut, sync::Arc}; use std::{convert::TryInto, fmt, io, mem, pin::Pin, task::Context, task::Poll}; use url::Url; @@ -53,18 +53,7 @@ pub struct WsConfig { tls_config: tls::Config, max_redirects: u8, use_deflate: bool, -} - -impl Clone for WsConfig { - fn clone(&self) -> Self { - Self { - transport: self.transport.clone(), - max_data_size: self.max_data_size, - tls_config: self.tls_config.clone(), - max_redirects: self.max_redirects, - use_deflate: self.use_deflate, - } - } + listener_protos: HashMap>, } impl WsConfig { @@ -76,6 +65,7 @@ impl WsConfig { tls_config: tls::Config::client(), max_redirects: 0, use_deflate: false, + listener_protos: HashMap::new(), } } @@ -118,149 +108,43 @@ type TlsOrPlain = EitherOutput, server::Tls impl Transport for WsConfig where - T: Transport + Send + 'static, + T: Transport + Send + Unpin + 'static, T::Error: Send + 'static, T::Dial: Send + 'static, - T::Listener: Send + 'static, T::ListenerUpgrade: Send + 'static, T::Output: AsyncRead + AsyncWrite + Unpin + Send + 'static, { type Output = Connection; type Error = Error; - type Listener = - BoxStream<'static, Result, Self::Error>>; type ListenerUpgrade = BoxFuture<'static, Result>; type Dial = BoxFuture<'static, Result>; fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { + ) -> Result<(), TransportError> { let mut inner_addr = addr.clone(); - - let (use_tls, proto) = match inner_addr.pop() { + let proto = match inner_addr.pop() { Some(p @ Protocol::Wss(_)) => { if self.tls_config.server.is_some() { - (true, p) + p } else { debug!("/wss address but TLS server support is not configured"); return Err(TransportError::MultiaddrNotSupported(addr)); } } - Some(p @ Protocol::Ws(_)) => (false, p), + Some(p @ Protocol::Ws(_)) => p, _ => { debug!("{} is not a websocket multiaddr", addr); return Err(TransportError::MultiaddrNotSupported(addr)); } }; - - let tls_config = self.tls_config.clone(); - let max_size = self.max_data_size; - let use_deflate = self.use_deflate; - let transport = self - .transport + self.listener_protos.insert(id, proto); + self.transport .lock() - .listen_on(inner_addr) - .map_err(|e| e.map(Error::Transport))?; - let listen = transport - .map_err(Error::Transport) - .map_ok(move |event| match event { - ListenerEvent::NewAddress(mut a) => { - a = a.with(proto.clone()); - debug!("Listening on {}", a); - ListenerEvent::NewAddress(a) - } - ListenerEvent::AddressExpired(mut a) => { - a = a.with(proto.clone()); - ListenerEvent::AddressExpired(a) - } - ListenerEvent::Error(err) => ListenerEvent::Error(Error::Transport(err)), - ListenerEvent::Upgrade { - upgrade, - mut local_addr, - mut remote_addr, - } => { - local_addr = local_addr.with(proto.clone()); - remote_addr = remote_addr.with(proto.clone()); - let remote1 = remote_addr.clone(); // used for logging - let remote2 = remote_addr.clone(); // used for logging - let tls_config = tls_config.clone(); - - let upgrade = async move { - let stream = upgrade.map_err(Error::Transport).await?; - trace!("incoming connection from {}", remote1); - - let stream = if use_tls { - // begin TLS session - let server = tls_config - .server - .expect("for use_tls we checked server is not none"); - - trace!("awaiting TLS handshake with {}", remote1); - - let stream = server - .accept(stream) - .map_err(move |e| { - debug!("TLS handshake with {} failed: {}", remote1, e); - Error::Tls(tls::Error::from(e)) - }) - .await?; - - let stream: TlsOrPlain<_> = - EitherOutput::First(EitherOutput::Second(stream)); - - stream - } else { - // continue with plain stream - EitherOutput::Second(stream) - }; - - trace!("receiving websocket handshake request from {}", remote2); - - let mut server = handshake::Server::new(stream); - - if use_deflate { - server.add_extension(Box::new(Deflate::new(connection::Mode::Server))); - } - - let ws_key = { - let request = server - .receive_request() - .map_err(|e| Error::Handshake(Box::new(e))) - .await?; - request.key() - }; - - trace!("accepting websocket handshake request from {}", remote2); - - let response = handshake::server::Response::Accept { - key: ws_key, - protocol: None, - }; - - server - .send_response(&response) - .map_err(|e| Error::Handshake(Box::new(e))) - .await?; - - let conn = { - let mut builder = server.into_builder(); - builder.set_max_message_size(max_size); - builder.set_max_frame_size(max_size); - Connection::new(builder) - }; - - Ok(conn) - }; - - ListenerEvent::Upgrade { - upgrade: Box::pin(upgrade) as BoxFuture<'static, _>, - local_addr, - remote_addr, - } - } - }); - Ok(Box::pin(listen)) + .listen_on(id, inner_addr) + .map_err(|e| e.map(Error::Transport)) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -277,14 +161,106 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.transport.lock().address_translation(server, observed) } + + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + let mut transport = self.transport.lock(); + let inner_event = match Transport::poll(Pin::new(transport.deref_mut()), cx) { + Poll::Ready(ev) => ev, + Poll::Pending => return Poll::Pending, + }; + drop(transport); + + let event = match inner_event { + TransportEvent::NewAddress { + listener_id, + mut listen_addr, + } => { + let proto = self + .listener_protos + .get(&listener_id) + .expect("Protocol was inserted in Transport::listen_on."); + listen_addr.push(proto.clone()); + debug!("Listening on {}", listen_addr); + TransportEvent::NewAddress { + listener_id, + listen_addr, + } + } + TransportEvent::AddressExpired { + listener_id, + mut listen_addr, + } => { + let proto = self + .listener_protos + .get(&listener_id) + .expect("Protocol was inserted in Transport::listen_on."); + listen_addr.push(proto.clone()); + TransportEvent::AddressExpired { + listener_id, + listen_addr, + } + } + TransportEvent::Error { listener_id, error } => TransportEvent::Error { + listener_id, + error: Error::Transport(error), + }, + TransportEvent::Closed { + listener_id, + mut addresses, + reason, + } => { + let proto = self + .listener_protos + .remove(&listener_id) + .expect("Protocol was inserted in Transport::listen_on."); + addresses = addresses + .into_iter() + .map(|a| a.with(proto.clone())) + .collect(); + TransportEvent::Closed { + listener_id, + addresses, + reason: reason.map_err(Error::Transport), + } + } + TransportEvent::Incoming { + listener_id, + upgrade, + mut local_addr, + mut send_back_addr, + } => { + let proto = self + .listener_protos + .get(&listener_id) + .expect("Protocol was inserted in Transport::listen_on."); + let use_tls = match proto { + Protocol::Wss(_) => true, + Protocol::Ws(_) => false, + _ => unreachable!("Map contains only ws and wss protocols."), + }; + local_addr.push(proto.clone()); + send_back_addr.push(proto.clone()); + let upgrade = self.map_upgrade(upgrade, send_back_addr.clone(), use_tls); + TransportEvent::Incoming { + listener_id, + upgrade, + local_addr, + send_back_addr, + } + } + }; + Poll::Ready(event) + } } impl WsConfig where - T: Transport + Send + 'static, + T: Transport + Send + Unpin + 'static, T::Error: Send + 'static, T::Dial: Send + 'static, - T::Listener: Send + 'static, T::ListenerUpgrade: Send + 'static, T::Output: AsyncRead + AsyncWrite + Unpin + Send + 'static, { @@ -304,13 +280,25 @@ where // We are looping here in order to follow redirects (if any): let mut remaining_redirects = self.max_redirects; - let mut this = self.clone(); + let transport = self.transport.clone(); + let tls_config = self.tls_config.clone(); + let use_deflate = self.use_deflate.clone(); + let max_redirects = self.max_redirects.clone(); + let future = async move { loop { - match this.dial_once(addr, role_override).await { + match Self::dial_once( + transport.clone(), + addr, + tls_config.clone(), + use_deflate, + role_override, + ) + .await + { Ok(Either::Left(redirect)) => { if remaining_redirects == 0 { - debug!("Too many redirects (> {})", this.max_redirects); + debug!("Too many redirects (> {})", max_redirects); return Err(Error::TooManyRedirects); } remaining_redirects -= 1; @@ -324,17 +312,20 @@ where Ok(Box::pin(future)) } + /// Attempts to dial the given address and perform a websocket handshake. async fn dial_once( - &mut self, + transport: Arc>, addr: WsAddress, + tls_config: tls::Config, + use_deflate: bool, role_override: Endpoint, ) -> Result>, Error> { trace!("Dialing websocket address: {:?}", addr); let dial = match role_override { - Endpoint::Dialer => self.transport.lock().dial(addr.tcp_addr), - Endpoint::Listener => self.transport.lock().dial_as_listener(addr.tcp_addr), + Endpoint::Dialer => transport.lock().dial(addr.tcp_addr), + Endpoint::Listener => transport.lock().dial_as_listener(addr.tcp_addr), } .map_err(|e| match e { TransportError::MultiaddrNotSupported(a) => Error::InvalidMultiaddr(a), @@ -350,8 +341,7 @@ where .dns_name .expect("for use_tls we have checked that dns_name is some"); trace!("Starting TLS handshake with {:?}", dns_name); - let stream = self - .tls_config + let stream = tls_config .client .connect(dns_name.clone(), stream) .map_err(|e| { @@ -371,7 +361,7 @@ where let mut client = handshake::Client::new(stream, &addr.host_port, addr.path.as_ref()); - if self.use_deflate { + if use_deflate { client.add_extension(Box::new(Deflate::new(connection::Mode::Client))); } @@ -400,6 +390,91 @@ where } } } + + fn map_upgrade( + &self, + upgrade: T::ListenerUpgrade, + remote_addr: Multiaddr, + use_tls: bool, + ) -> ::ListenerUpgrade { + let remote_addr2 = remote_addr.clone(); // used for logging + let tls_config = self.tls_config.clone(); + let max_size = self.max_data_size; + let use_deflate = self.use_deflate; + + async move { + let stream = upgrade.map_err(Error::Transport).await?; + trace!("incoming connection from {}", remote_addr); + + let stream = if use_tls { + // begin TLS session + let server = tls_config + .server + .expect("for use_tls we checked server is not none"); + + trace!("awaiting TLS handshake with {}", remote_addr); + + let stream = server + .accept(stream) + .map_err(move |e| { + debug!("TLS handshake with {} failed: {}", remote_addr, e); + Error::Tls(tls::Error::from(e)) + }) + .await?; + + let stream: TlsOrPlain<_> = EitherOutput::First(EitherOutput::Second(stream)); + + stream + } else { + // continue with plain stream + EitherOutput::Second(stream) + }; + + trace!( + "receiving websocket handshake request from {}", + remote_addr2 + ); + + let mut server = handshake::Server::new(stream); + + if use_deflate { + server.add_extension(Box::new(Deflate::new(connection::Mode::Server))); + } + + let ws_key = { + let request = server + .receive_request() + .map_err(|e| Error::Handshake(Box::new(e))) + .await?; + request.key() + }; + + trace!( + "accepting websocket handshake request from {}", + remote_addr2 + ); + + let response = handshake::server::Response::Accept { + key: ws_key, + protocol: None, + }; + + server + .send_response(&response) + .map_err(|e| Error::Handshake(Box::new(e))) + .await?; + + let conn = { + let mut builder = server.into_builder(); + builder.set_max_message_size(max_size); + builder.set_max_frame_size(max_size); + Connection::new(builder) + }; + + Ok(conn) + } + .boxed() + } } #[derive(Debug)] diff --git a/transports/websocket/src/lib.rs b/transports/websocket/src/lib.rs index 4549ad7a760..41e14719934 100644 --- a/transports/websocket/src/lib.rs +++ b/transports/websocket/src/lib.rs @@ -26,14 +26,11 @@ pub mod tls; use error::Error; use framed::{Connection, Incoming}; -use futures::{future::BoxFuture, prelude::*, ready, stream::BoxStream}; +use futures::{future::BoxFuture, prelude::*, ready}; use libp2p_core::{ connection::ConnectedPoint, multiaddr::Multiaddr, - transport::{ - map::{MapFuture, MapStream}, - ListenerEvent, TransportError, - }, + transport::{map::MapFuture, ListenerId, TransportError, TransportEvent}, Transport, }; use rw_stream_sink::RwStreamSink; @@ -44,21 +41,22 @@ use std::{ }; /// A Websocket transport. -#[derive(Debug, Clone)] +#[derive(Debug)] +#[pin_project::pin_project] pub struct WsConfig where T: Transport, T::Output: AsyncRead + AsyncWrite + Send + Unpin + 'static, { + #[pin] transport: libp2p_core::transport::map::Map, WrapperFn>, } impl WsConfig where - T: Transport + Send + 'static, + T: Transport + Send + Unpin + 'static, T::Error: Send + 'static, T::Dial: Send + 'static, - T::Listener: Send + 'static, T::ListenerUpgrade: Send + 'static, T::Output: AsyncRead + AsyncWrite + Send + Unpin + 'static, { @@ -114,24 +112,23 @@ where impl Transport for WsConfig where - T: Transport + Send + 'static, + T: Transport + Send + Unpin + 'static, T::Error: Send + 'static, T::Dial: Send + 'static, - T::Listener: Send + 'static, T::ListenerUpgrade: Send + 'static, T::Output: AsyncRead + AsyncWrite + Unpin + Send + 'static, { type Output = RwStreamSink>; type Error = Error; - type Listener = MapStream, WrapperFn>; type ListenerUpgrade = MapFuture, WrapperFn>; type Dial = MapFuture, WrapperFn>; fn listen_on( &mut self, + id: ListenerId, addr: Multiaddr, - ) -> Result> { - self.transport.listen_on(addr) + ) -> Result<(), TransportError> { + self.transport.listen_on(id, addr) } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -148,11 +145,14 @@ where fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { self.transport.address_translation(server, observed) } -} -/// Type alias corresponding to `framed::WsConfig::Listener`. -pub type InnerStream = - BoxStream<'static, Result, Error>, Error>>; + fn poll( + self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + self.project().transport.poll(cx) + } +} /// Type alias corresponding to `framed::WsConfig::Dial` and `framed::WsConfig::ListenerUpgrade`. pub type InnerFuture = BoxFuture<'static, Result, Error>>; @@ -221,7 +221,7 @@ where mod tests { use super::WsConfig; use futures::prelude::*; - use libp2p_core::{multiaddr::Protocol, Multiaddr, PeerId, Transport}; + use libp2p_core::{multiaddr::Protocol, transport::ListenerId, Multiaddr, PeerId, Transport}; use libp2p_tcp as tcp; #[test] @@ -237,14 +237,17 @@ mod tests { } async fn connect(listen_addr: Multiaddr) { - let ws_config = || WsConfig::new(tcp::TcpTransport::new()); + let new_ws_config = + || WsConfig::new(tcp::TcpTransport::new(tcp::GenTcpConfig::default())).boxed(); - let mut listener = ws_config().listen_on(listen_addr).expect("listener"); + let mut ws_config = new_ws_config(); + ws_config + .listen_on(ListenerId::new(1), listen_addr) + .expect("listener"); - let addr = listener - .try_next() + let addr = ws_config + .next() .await - .expect("some event") .expect("no error") .into_new_address() .expect("listen address"); @@ -253,16 +256,15 @@ mod tests { assert_ne!(Some(Protocol::Tcp(0)), addr.iter().nth(1)); let inbound = async move { - let (conn, _addr) = listener - .try_filter_map(|e| future::ready(Ok(e.into_upgrade()))) - .try_next() + let (conn, _addr) = ws_config + .select_next_some() + .map(|ev| ev.into_upgrade()) .await - .unwrap() .unwrap(); conn.await }; - let outbound = ws_config() + let outbound = new_ws_config() .dial(addr.with(Protocol::P2p(PeerId::random().into()))) .unwrap(); From d7f5019b722b94f717e7ade281086577a86ad061 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Thu, 19 May 2022 12:38:18 +0200 Subject: [PATCH 14/47] Remove various `Sync` bounds With `Transport` becoming non-Clone and having `&mut` self receivers, the `Sync` requirement no longer makes any sense and we can thus remove it. --- core/src/transport.rs | 2 +- core/src/transport/boxed.rs | 4 ++-- core/src/transport/upgrade.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/transport.rs b/core/src/transport.rs index 2e39280b6aa..4b4ca825ec7 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -157,7 +157,7 @@ pub trait Transport { /// Boxes the transport, including custom transport errors. fn boxed(self) -> boxed::Boxed where - Self: Transport + Sized + Send + Sync + Unpin + 'static, + Self: Transport + Sized + Send + Unpin + 'static, Self::Dial: Send + 'static, Self::ListenerUpgrade: Send + 'static, Self::Error: Send + Sync, diff --git a/core/src/transport/boxed.rs b/core/src/transport/boxed.rs index 6ae4005972f..6e2ac4d27ee 100644 --- a/core/src/transport/boxed.rs +++ b/core/src/transport/boxed.rs @@ -31,7 +31,7 @@ use std::{ /// Creates a new [`Boxed`] transport from the given transport. pub fn boxed(transport: T) -> Boxed where - T: Transport + Send + Sync + Unpin + 'static, + T: Transport + Send + Unpin + 'static, T::Error: Send + Sync, T::Dial: Send + 'static, T::ListenerUpgrade: Send + 'static, @@ -45,7 +45,7 @@ where /// and `ListenerUpgrade` futures are `Box`ed and only the `Output` /// and `Error` types are captured in type variables. pub struct Boxed { - inner: Box + Send + Sync + Unpin>, + inner: Box + Send + Unpin>, } type Dial = Pin> + Send>>; diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index 689b584b631..338f8b92aed 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -295,7 +295,7 @@ impl Multiplexed { /// the [`StreamMuxer`] and custom transport errors. pub fn boxed(self) -> super::Boxed<(PeerId, StreamMuxerBox)> where - T: Transport + Sized + Send + Sync + Unpin + 'static, + T: Transport + Sized + Send + Unpin + 'static, T::Dial: Send + 'static, T::ListenerUpgrade: Send + 'static, T::Error: Send + Sync, From b4164e8372b05563c8440825f5a3f1eb26a46388 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 10:58:59 +0200 Subject: [PATCH 15/47] transports/tcp: revert Stream impl for GenTcpTransport With PR #2667 the `Sync` trait bound for transport::Boxed is removed. If a tcp transport should be polled as a stream we can now do this via `TcpTransport::new(..)::boxed` and do not need a separate impl of `Stream` for it. --- transports/tcp/src/lib.rs | 42 ++++++++------------------------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index be2f235deaf..3a9c6c31fce 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -46,7 +46,6 @@ use futures::{ future::{self, BoxFuture, Ready}, prelude::*, ready, - stream::FusedStream, }; use futures_timer::Delay; use libp2p_core::{ @@ -306,7 +305,7 @@ impl GenTcpConfig { /// let listen_addr1: Multiaddr = "/ip4/127.0.0.1/tcp/9001".parse().unwrap(); /// let listen_addr2: Multiaddr = "/ip4/127.0.0.1/tcp/9002".parse().unwrap(); /// - /// let mut tcp1 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)); + /// let mut tcp1 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)).boxed(); /// tcp1.listen_on(ListenerId::new(1), listen_addr1.clone()).expect("listener"); /// match tcp1.select_next_some().await { /// TransportEvent::NewAddress { listen_addr, .. } => { @@ -317,7 +316,7 @@ impl GenTcpConfig { /// _ => {} /// } /// - /// let mut tcp2 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)); + /// let mut tcp2 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)).boxed(); /// tcp2.listen_on(ListenerId::new(1), listen_addr2).expect("listener"); /// match tcp2.select_next_some().await { /// TransportEvent::NewAddress { listen_addr, .. } => { @@ -551,31 +550,6 @@ where } } -impl Stream for GenTcpTransport -where - T: Provider + Send + 'static, - T::Listener: Unpin, - T::IfWatcher: Unpin, - T::Stream: Unpin, -{ - type Item = TransportEvent<::ListenerUpgrade, ::Error>; - - fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Transport::poll(self, cx).map(Some) - } -} -impl FusedStream for GenTcpTransport -where - T: Provider + Send + 'static, - T::Listener: Unpin, - T::IfWatcher: Unpin, - T::Stream: Unpin, -{ - fn is_terminated(&self) -> bool { - false - } -} - #[derive(Debug)] pub enum TcpTransportEvent { /// The transport is listening on a new additional [`Multiaddr`]. @@ -937,7 +911,7 @@ mod tests { env_logger::try_init().ok(); async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { - let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { match tcp.select_next_some().await { @@ -1006,7 +980,7 @@ mod tests { env_logger::try_init().ok(); async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { - let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { @@ -1075,7 +1049,7 @@ mod tests { env_logger::try_init().ok(); async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { - let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); tcp.listen_on(ListenerId::new(1), addr).unwrap(); loop { match tcp.select_next_some().await { @@ -1097,7 +1071,7 @@ mod tests { async fn dialer(addr: Multiaddr, mut ready_rx: mpsc::Receiver) { let dest_addr = ready_rx.next().await.unwrap(); - let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)).boxed(); tcp.listen_on(ListenerId::new(1), addr).unwrap(); match tcp.select_next_some().await { TransportEvent::NewAddress { .. } => { @@ -1155,7 +1129,7 @@ mod tests { T::IfWatcher: Sync, T::Stream: Sync, { - let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)).boxed(); tcp.listen_on(ListenerId::new(1), addr).unwrap(); match tcp.select_next_some().await { TransportEvent::NewAddress { @@ -1207,7 +1181,7 @@ mod tests { T: Provider, T::IfWatcher: Sync, { - let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); tcp.listen_on(ListenerId::new(1), addr).unwrap(); tcp.select_next_some() .await From a7766cdcb19aeb99b46d50c658433bba473ca00d Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 11:16:35 +0200 Subject: [PATCH 16/47] core/transport/memory: fix listener polling --- core/src/transport/memory.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 6e7da33a7c8..9c95b149c48 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -241,7 +241,7 @@ impl Transport for MemoryTransport { listener.tell_listen_addr = false; let listen_addr = listener.addr.clone(); let listener_id = listener.id; - self.listeners.push_back(listener); + self.listeners.push_front(listener); return Poll::Ready(TransportEvent::NewAddress { listen_addr, listener_id, @@ -259,7 +259,7 @@ impl Transport for MemoryTransport { }), }; - self.listeners.push_back(listener); + self.listeners.push_front(listener); if let Some(event) = event { return Poll::Ready(event); } else { From 9824acd15464fe9d0541031133737f4105df6afa Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 11:31:39 +0200 Subject: [PATCH 17/47] transports/uds: adapt uds transport --- transports/uds/src/lib.rs | 238 ++++++++++++++++++++++++-------------- 1 file changed, 150 insertions(+), 88 deletions(-) diff --git a/transports/uds/src/lib.rs b/transports/uds/src/lib.rs index 472fd1c607c..d8b988f01df 100644 --- a/transports/uds/src/lib.rs +++ b/transports/uds/src/lib.rs @@ -39,113 +39,176 @@ use futures::{ future::{BoxFuture, Ready}, prelude::*, }; +use libp2p_core::transport::ListenerId; use libp2p_core::{ multiaddr::{Multiaddr, Protocol}, - transport::{ListenerEvent, TransportError}, + transport::{TransportError, TransportEvent}, Transport, }; use log::debug; +use std::collections::VecDeque; +use std::pin::Pin; +use std::task::{Context, Poll}; use std::{io, path::PathBuf}; +pub type Listener = + BoxStream<'static, Result, TransportEvent>>; + macro_rules! codegen { ($feature_name:expr, $uds_config:ident, $build_listener:expr, $unix_stream:ty, $($mut_or_not:tt)*) => { + /// Represents the configuration for a Unix domain sockets transport capability for libp2p. + #[cfg_attr(docsrs, doc(cfg(feature = $feature_name)))] + pub struct $uds_config { + listeners: VecDeque< + Listener<::ListenerUpgrade, ::Error>, + >, + } -/// Represents the configuration for a Unix domain sockets transport capability for libp2p. -#[cfg_attr(docsrs, doc(cfg(feature = $feature_name)))] -#[derive(Debug, Clone)] -pub struct $uds_config { -} - -impl $uds_config { - /// Creates a new configuration object for Unix domain sockets. - pub fn new() -> $uds_config { - $uds_config {} - } -} + impl $uds_config { + /// Creates a new configuration object for Unix domain sockets. + pub fn new() -> $uds_config { + $uds_config { + listeners: VecDeque::new(), + } + } + } -impl Default for $uds_config { - fn default() -> Self { - Self::new() - } -} + impl Default for $uds_config { + fn default() -> Self { + Self::new() + } + } -impl Transport for $uds_config { - type Output = $unix_stream; - type Error = io::Error; - type Listener = BoxStream<'static, Result, Self::Error>>; - type ListenerUpgrade = Ready>; - type Dial = BoxFuture<'static, Result>; + impl Transport for $uds_config { + type Output = $unix_stream; + type Error = io::Error; + type ListenerUpgrade = Ready>; + type Dial = BoxFuture<'static, Result>; - fn listen_on(&mut self, addr: Multiaddr) -> Result> { - if let Ok(path) = multiaddr_to_path(&addr) { - Ok(async move { $build_listener(&path).await } - .map_ok(move |listener| { - stream::once({ - let addr = addr.clone(); - async move { - debug!("Now listening on {}", addr); - Ok(ListenerEvent::NewAddress(addr)) - } - }).chain(stream::unfold(listener, move |$($mut_or_not)* listener| { - let addr = addr.clone(); - async move { - let (stream, _) = match listener.accept().await { - Ok(v) => v, - Err(err) => return Some((Err(err), listener)) - }; - debug!("incoming connection on {}", addr); - let event = ListenerEvent::Upgrade { - upgrade: future::ok(stream), - local_addr: addr.clone(), - remote_addr: addr.clone() - }; - Some((Ok(event), listener)) - } - })) - }) - .try_flatten_stream() - .boxed()) - } else { - Err(TransportError::MultiaddrNotSupported(addr)) - } - } + fn listen_on( + &mut self, + id: ListenerId, + addr: Multiaddr, + ) -> Result<(), TransportError> { + if let Ok(path) = multiaddr_to_path(&addr) { + let addr_clone = addr.clone(); + let listener = async move { + $build_listener(path) + .await + .map_err(|e| TransportEvent::Closed { + listener_id: id, + addresses: vec![addr_clone], + reason: Err(e), + }) + } + .map_ok(move |listener| { + stream::once({ + let addr = addr.clone(); + async move { + debug!("Now listening on {}", addr); + Ok(TransportEvent::NewAddress { + listener_id: id, + listen_addr: addr, + }) + } + }) + .chain(stream::unfold(listener, move |listener| { + let addr = addr.clone(); + async move { + let event = match listener.accept().await { + Ok((stream, _)) => { + debug!("incoming connection on {}", addr); + TransportEvent::Incoming { + upgrade: future::ok(stream), + local_addr: addr.clone(), + send_back_addr: addr.clone(), + listener_id: id, + } + } + Err(error) => TransportEvent::Error { + listener_id: id, + error, + }, + }; + Some((Ok(event), listener)) + } + })) + }) + .try_flatten_stream() + .boxed(); + self.listeners.push_back(listener); + Ok(()) + } else { + Err(TransportError::MultiaddrNotSupported(addr)) + } + } - fn dial(&mut self, addr: Multiaddr) -> Result> { - // TODO: Should we dial at all? - if let Ok(path) = multiaddr_to_path(&addr) { - debug!("Dialing {}", addr); - Ok(async move { <$unix_stream>::connect(&path).await }.boxed()) - } else { - Err(TransportError::MultiaddrNotSupported(addr)) - } - } + fn dial(&mut self, addr: Multiaddr) -> Result> { + // TODO: Should we dial at all? + if let Ok(path) = multiaddr_to_path(&addr) { + debug!("Dialing {}", addr); + Ok(async move { <$unix_stream>::connect(&path).await }.boxed()) + } else { + Err(TransportError::MultiaddrNotSupported(addr)) + } + } - fn dial_as_listener(&mut self, addr: Multiaddr) -> Result> { - self.dial(addr) - } + fn dial_as_listener( + &mut self, + addr: Multiaddr, + ) -> Result> { + self.dial(addr) + } - fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option { - None - } -} + fn address_translation( + &self, + _server: &Multiaddr, + _observed: &Multiaddr, + ) -> Option { + None + } -}; + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + let mut remaining = self.listeners.len(); + while let Some(mut listener) = self.listeners.pop_back() { + let event = match Stream::poll_next(Pin::new(&mut listener), cx) { + Poll::Pending => None, + Poll::Ready(None) => panic!("Alive listeners always have a sender."), + Poll::Ready(Some(Ok(event))) => Some(event), + Poll::Ready(Some(Err(event))) => return Poll::Ready(event), + }; + self.listeners.push_front(listener); + if let Some(event) = event { + return Poll::Ready(event); + } else { + remaining -= 1; + if remaining == 0 { + break; + } + } + } + Poll::Pending + } + } + }; } #[cfg(feature = "async-std")] codegen!( "async-std", UdsConfig, - |addr| async move { async_std::os::unix::net::UnixListener::bind(addr).await }, + |addr| async move { async_std::os::unix::net::UnixListener::bind(&addr).await }, async_std::os::unix::net::UnixStream, ); #[cfg(feature = "tokio")] codegen!( "tokio", TokioUdsConfig, - |addr| async move { tokio::net::UnixListener::bind(addr) }, + |addr| async move { tokio::net::UnixListener::bind(&addr) }, tokio::net::UnixStream, - mut ); /// Turns a `Multiaddr` containing a single `Unix` component into a path. @@ -176,6 +239,7 @@ mod tests { use futures::{channel::oneshot, prelude::*}; use libp2p_core::{ multiaddr::{Multiaddr, Protocol}, + transport::ListenerId, Transport, }; use std::{self, borrow::Cow, path::Path}; @@ -208,24 +272,22 @@ mod tests { let (tx, rx) = oneshot::channel(); async_std::task::spawn(async move { - let mut listener = UdsConfig::new().listen_on(addr).unwrap(); + let mut transport = UdsConfig::new().boxed(); + transport.listen_on(ListenerId::new(1), addr).unwrap(); - let listen_addr = listener - .try_next() + let listen_addr = transport + .select_next_some() .await - .unwrap() - .expect("some event") .into_new_address() .expect("listen address"); tx.send(listen_addr).unwrap(); - let (sock, _addr) = listener - .try_filter_map(|e| future::ok(e.into_upgrade())) - .try_next() + let (sock, _addr) = transport + .select_next_some() .await - .unwrap() - .expect("some event"); + .into_upgrade() + .expect("incoming stream"); let mut sock = sock.await.unwrap(); let mut buf = [0u8; 3]; @@ -247,7 +309,7 @@ mod tests { let mut uds = UdsConfig::new(); let addr = "/unix//foo/bar".parse::().unwrap(); - assert!(uds.listen_on(addr).is_err()); + assert!(uds.listen_on(ListenerId::new(1), addr).is_err()); } #[test] From a2988b507c0a106ea6df1fbd0a16fcc53857c1de Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 15:15:56 +0200 Subject: [PATCH 18/47] transports/tcp: impl Default for GenTcpTransport --- transports/tcp/src/lib.rs | 137 +++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 62 deletions(-) diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 3a9c6c31fce..46bc2c39e50 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -67,68 +67,6 @@ use std::{ use provider::{IfEvent, Provider}; -pub struct GenTcpTransport -where - T: Provider + Send, -{ - config: GenTcpConfig, - /// All the active listeners. - /// The `Listener` struct contains a stream that we want to be pinned. Since the `VecDeque` - /// can be resized, the only way is to use a `Pin>`. - listeners: VecDeque>>>, - /// Pending listeners events to return from [`ListenersStream::poll`]. - pending_events: VecDeque::ListenerUpgrade, io::Error>>, -} - -impl GenTcpTransport -where - T: Provider + Send, -{ - pub fn new(config: GenTcpConfig) -> Self { - GenTcpTransport { - config, - listeners: Default::default(), - pending_events: Default::default(), - } - } - - fn create_socket(&self, socket_addr: &SocketAddr) -> io::Result { - let domain = if socket_addr.is_ipv4() { - Domain::IPV4 - } else { - Domain::IPV6 - }; - let socket = Socket::new(domain, Type::STREAM, Some(socket2::Protocol::TCP))?; - if socket_addr.is_ipv6() { - socket.set_only_v6(true)?; - } - if let Some(ttl) = self.config.ttl { - socket.set_ttl(ttl)?; - } - if let Some(nodelay) = self.config.nodelay { - socket.set_nodelay(nodelay)?; - } - socket.set_reuse_address(true)?; - #[cfg(unix)] - if let PortReuse::Enabled { .. } = &self.config.port_reuse { - socket.set_reuse_port(true)?; - } - Ok(socket) - } - - fn do_listen( - &mut self, - id: ListenerId, - socket_addr: SocketAddr, - ) -> io::Result> { - let socket = self.create_socket(&socket_addr)?; - socket.bind(&socket_addr.into())?; - socket.listen(self.config.backlog as _)?; - socket.set_nonblocking(true)?; - TcpListenStream::::new(id, socket.into(), self.config.port_reuse.clone()) - } -} - /// The configuration for a TCP/IP transport capability for libp2p. #[derive(Clone, Debug)] pub struct GenTcpConfig { @@ -361,6 +299,81 @@ impl Default for GenTcpConfig { } } +pub struct GenTcpTransport +where + T: Provider + Send, +{ + config: GenTcpConfig, + /// All the active listeners. + /// The `Listener` struct contains a stream that we want to be pinned. Since the `VecDeque` + /// can be resized, the only way is to use a `Pin>`. + listeners: VecDeque>>>, + /// Pending listeners events to return from [`ListenersStream::poll`]. + pending_events: VecDeque::ListenerUpgrade, io::Error>>, +} + +impl GenTcpTransport +where + T: Provider + Send, +{ + pub fn new(config: GenTcpConfig) -> Self { + GenTcpTransport { + config, + listeners: Default::default(), + pending_events: Default::default(), + } + } + + fn create_socket(&self, socket_addr: &SocketAddr) -> io::Result { + let domain = if socket_addr.is_ipv4() { + Domain::IPV4 + } else { + Domain::IPV6 + }; + let socket = Socket::new(domain, Type::STREAM, Some(socket2::Protocol::TCP))?; + if socket_addr.is_ipv6() { + socket.set_only_v6(true)?; + } + if let Some(ttl) = self.config.ttl { + socket.set_ttl(ttl)?; + } + if let Some(nodelay) = self.config.nodelay { + socket.set_nodelay(nodelay)?; + } + socket.set_reuse_address(true)?; + #[cfg(unix)] + if let PortReuse::Enabled { .. } = &self.config.port_reuse { + socket.set_reuse_port(true)?; + } + Ok(socket) + } + + fn do_listen( + &mut self, + id: ListenerId, + socket_addr: SocketAddr, + ) -> io::Result> { + let socket = self.create_socket(&socket_addr)?; + socket.bind(&socket_addr.into())?; + socket.listen(self.config.backlog as _)?; + socket.set_nonblocking(true)?; + TcpListenStream::::new(id, socket.into(), self.config.port_reuse.clone()) + } +} + +impl Default for GenTcpTransport +where + T: Provider + Send, +{ + fn default() -> Self { + GenTcpTransport { + config: GenTcpConfig::default(), + listeners: VecDeque::new(), + pending_events: VecDeque::new(), + } + } +} + impl Transport for GenTcpTransport where T: Provider + Send + 'static, From 2edb0cdab569a6cc5c1797dd3c005c016448952e Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 15:21:37 +0200 Subject: [PATCH 19/47] core/transport/memory: add MemoryTransport::new --- core/src/transport/memory.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 9c95b149c48..a6524ffc9b4 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -98,6 +98,14 @@ pub struct MemoryTransport { listeners: VecDeque>>, } +impl MemoryTransport { + pub fn new() -> Self { + MemoryTransport { + listeners: VecDeque::new(), + } + } +} + /// Connection to a `MemoryTransport` currently being opened. pub struct DialFuture { /// Ephemeral source port. From 907a5aba49db30c75ee0a1d001d32df6b75644a3 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 15:21:55 +0200 Subject: [PATCH 20/47] protocols/*: adapt network behaviour protocols --- protocols/autonat/src/behaviour.rs | 5 ++-- protocols/dcutr/examples/client.rs | 7 ++++-- protocols/identify/src/identify.rs | 5 ++-- protocols/identify/src/protocol.rs | 19 ++++++++-------- protocols/kad/src/behaviour.rs | 3 +-- protocols/kad/src/protocol.rs | 6 ++--- protocols/mdns/src/behaviour.rs | 2 +- protocols/ping/src/protocol.rs | 29 +++++++++++++++--------- protocols/ping/tests/ping.rs | 5 ++-- protocols/relay/examples/relay_v2.rs | 2 +- protocols/request-response/tests/ping.rs | 5 ++-- 11 files changed, 47 insertions(+), 41 deletions(-) diff --git a/protocols/autonat/src/behaviour.rs b/protocols/autonat/src/behaviour.rs index 86c65bb3416..f98bf5af532 100644 --- a/protocols/autonat/src/behaviour.rs +++ b/protocols/autonat/src/behaviour.rs @@ -29,9 +29,8 @@ pub use as_server::{InboundProbeError, InboundProbeEvent}; use futures_timer::Delay; use instant::Instant; use libp2p_core::{ - connection::{ConnectionId, ListenerId}, - multiaddr::Protocol, - ConnectedPoint, Endpoint, Multiaddr, PeerId, + connection::ConnectionId, multiaddr::Protocol, transport::ListenerId, ConnectedPoint, Endpoint, + Multiaddr, PeerId, }; use libp2p_request_response::{ handler::RequestResponseHandlerEvent, ProtocolSupport, RequestId, RequestResponse, diff --git a/protocols/dcutr/examples/client.rs b/protocols/dcutr/examples/client.rs index ebaf12d18bc..dd73b7d3ac3 100644 --- a/protocols/dcutr/examples/client.rs +++ b/protocols/dcutr/examples/client.rs @@ -32,7 +32,7 @@ use libp2p::noise; use libp2p::ping::{Ping, PingConfig, PingEvent}; use libp2p::relay::v2::client::{self, Client}; use libp2p::swarm::{SwarmBuilder, SwarmEvent}; -use libp2p::tcp::TcpTransport; +use libp2p::tcp::{GenTcpConfig, TcpTransport}; use libp2p::Transport; use libp2p::{identity, NetworkBehaviour, PeerId}; use log::info; @@ -95,7 +95,10 @@ fn main() -> Result<(), Box> { let transport = OrTransport::new( relay_transport, - block_on(DnsConfig::system(TcpTransport::new().port_reuse(true))).unwrap(), + block_on(DnsConfig::system(TcpTransport::new( + GenTcpConfig::default().port_reuse(true), + ))) + .unwrap(), ) .upgrade(upgrade::Version::V1) .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) diff --git a/protocols/identify/src/identify.rs b/protocols/identify/src/identify.rs index 5ea5e5f8a87..a6665b36cd7 100644 --- a/protocols/identify/src/identify.rs +++ b/protocols/identify/src/identify.rs @@ -516,7 +516,7 @@ mod tests { use libp2p_mplex::MplexConfig; use libp2p_noise as noise; use libp2p_swarm::{Swarm, SwarmEvent}; - use libp2p_tcp::TcpTransport; + use libp2p_tcp::{GenTcpConfig, TcpTransport}; fn transport() -> ( identity::PublicKey, @@ -527,8 +527,7 @@ mod tests { .into_authentic(&id_keys) .unwrap(); let pubkey = id_keys.public(); - let transport = TcpTransport::new() - .nodelay(true) + let transport = TcpTransport::new(GenTcpConfig::default().nodelay(true)) .upgrade(upgrade::Version::V1) .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) .multiplex(MplexConfig::new()) diff --git a/protocols/identify/src/protocol.rs b/protocols/identify/src/protocol.rs index 379a2477780..f54163113b3 100644 --- a/protocols/identify/src/protocol.rs +++ b/protocols/identify/src/protocol.rs @@ -302,26 +302,27 @@ mod tests { let (tx, rx) = oneshot::channel(); let bg_task = async_std::task::spawn(async move { - let mut transport = TcpTransport::new(); + let mut transport = TcpTransport::default().boxed(); - let mut listener = transport - .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) + transport + .listen_on( + libp2p_core::transport::ListenerId::new(1), + "/ip4/127.0.0.1/tcp/0".parse().unwrap(), + ) .unwrap(); - let addr = listener + let addr = transport .next() .await .expect("some event") - .expect("no error") .into_new_address() .expect("listen address"); tx.send(addr).unwrap(); - let socket = listener + let socket = transport .next() .await - .unwrap() - .unwrap() + .expect("some event") .into_upgrade() .unwrap() .0 @@ -347,7 +348,7 @@ mod tests { }); async_std::task::block_on(async move { - let mut transport = TcpTransport::new(); + let mut transport = TcpTransport::default(); let socket = transport.dial(rx.await.unwrap()).unwrap().await.unwrap(); let info = apply_outbound(socket, IdentifyProtocol, upgrade::Version::V1) diff --git a/protocols/kad/src/behaviour.rs b/protocols/kad/src/behaviour.rs index d5b322e096a..59d63b36e9d 100644 --- a/protocols/kad/src/behaviour.rs +++ b/protocols/kad/src/behaviour.rs @@ -40,8 +40,7 @@ use crate::K_VALUE; use fnv::{FnvHashMap, FnvHashSet}; use instant::Instant; use libp2p_core::{ - connection::{ConnectionId, ListenerId}, - ConnectedPoint, Multiaddr, PeerId, + connection::ConnectionId, transport::ListenerId, ConnectedPoint, Multiaddr, PeerId, }; use libp2p_swarm::{ dial_opts::{self, DialOpts}, diff --git a/protocols/kad/src/protocol.rs b/protocols/kad/src/protocol.rs index d5b20691648..d556606e0e0 100644 --- a/protocols/kad/src/protocol.rs +++ b/protocols/kad/src/protocol.rs @@ -658,10 +658,10 @@ mod tests { let (tx, rx) = mpsc::channel(); let bg_thread = thread::spawn(move || { - let transport = TcpTransport::new().with_upgrade(KademliaProtocolConfig); + let transport = TcpTransport::default().with_upgrade(KademliaProtocolConfig); let (listener, addr) = transport - .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) + .listen_on(libp2p_core::transport::ListenerId::new(1), "/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); tx.send(addr).unwrap(); @@ -678,7 +678,7 @@ mod tests { let _ = rt.block_on(future).unwrap(); }); - let transport = TcpTransport::new().with_upgrade(KademliaProtocolConfig); + let transport = TcpTransport::default().with_upgrade(KademliaProtocolConfig); let future = transport .dial(rx.recv().unwrap()) diff --git a/protocols/mdns/src/behaviour.rs b/protocols/mdns/src/behaviour.rs index c844f742af9..244b2b784dd 100644 --- a/protocols/mdns/src/behaviour.rs +++ b/protocols/mdns/src/behaviour.rs @@ -25,7 +25,7 @@ use crate::MdnsConfig; use async_io::Timer; use futures::prelude::*; use if_watch::{IfEvent, IfWatcher}; -use libp2p_core::connection::ListenerId; +use libp2p_core::transport::ListenerId; use libp2p_core::{Multiaddr, PeerId}; use libp2p_swarm::{ handler::DummyConnectionHandler, ConnectionHandler, NetworkBehaviour, NetworkBehaviourAction, diff --git a/protocols/ping/src/protocol.rs b/protocols/ping/src/protocol.rs index b081ad2a443..d89b9932f10 100644 --- a/protocols/ping/src/protocol.rs +++ b/protocols/ping/src/protocol.rs @@ -115,9 +115,10 @@ where #[cfg(test)] mod tests { use super::*; + use futures::StreamExt; use libp2p_core::{ multiaddr::multiaddr, - transport::{memory::MemoryTransport, Transport, TransportEvent}, + transport::{memory::MemoryTransport, Transport}, }; use rand::{thread_rng, Rng}; use std::time::Duration; @@ -125,24 +126,30 @@ mod tests { #[test] fn ping_pong() { let mem_addr = multiaddr![Memory(thread_rng().gen::())]; - let mut listener = MemoryTransport.listen_on(mem_addr).unwrap(); + let mut transport = MemoryTransport::new().boxed(); + transport + .listen_on(libp2p_core::transport::ListenerId::new(0), mem_addr) + .unwrap(); - let listener_addr = - if let Some(Some(Ok(TransportEvent::NewAddress(a)))) = listener.next().now_or_never() { - a - } else { - panic!("MemoryTransport not listening on an address!"); - }; + let listener_addr = transport + .select_next_some() + .now_or_never() + .and_then(|ev| ev.into_new_address()) + .expect("MemoryTransport not listening on an address!"); async_std::task::spawn(async move { - let listener_event = listener.next().await.unwrap(); - let (listener_upgrade, _) = listener_event.unwrap().into_upgrade().unwrap(); + let listener_event = transport.next().await.unwrap(); + let (listener_upgrade, _) = listener_event.into_upgrade().unwrap(); let conn = listener_upgrade.await.unwrap(); recv_ping(conn).await.unwrap(); }); async_std::task::block_on(async move { - let c = MemoryTransport.dial(listener_addr).unwrap().await.unwrap(); + let c = MemoryTransport::new() + .dial(listener_addr) + .unwrap() + .await + .unwrap(); let (_, rtt) = send_ping(c).await.unwrap(); assert!(rtt > Duration::from_secs(0)); }); diff --git a/protocols/ping/tests/ping.rs b/protocols/ping/tests/ping.rs index 352c77ef95b..ac45949ced7 100644 --- a/protocols/ping/tests/ping.rs +++ b/protocols/ping/tests/ping.rs @@ -31,7 +31,7 @@ use libp2p_mplex as mplex; use libp2p_noise as noise; use libp2p_ping as ping; use libp2p_swarm::{DummyBehaviour, KeepAlive, Swarm, SwarmEvent}; -use libp2p_tcp::TcpTransport; +use libp2p_tcp::{GenTcpConfig, TcpTransport}; use libp2p_yamux as yamux; use quickcheck::*; use rand::prelude::*; @@ -248,8 +248,7 @@ fn mk_transport(muxer: MuxerChoice) -> (PeerId, transport::Boxed<(PeerId, Stream .unwrap(); ( peer_id, - TcpTransport::new() - .nodelay(true) + TcpTransport::new(GenTcpConfig::default().nodelay(true)) .upgrade(upgrade::Version::V1) .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) .multiplex(match muxer { diff --git a/protocols/relay/examples/relay_v2.rs b/protocols/relay/examples/relay_v2.rs index fa44879220f..25d0bb7fc94 100644 --- a/protocols/relay/examples/relay_v2.rs +++ b/protocols/relay/examples/relay_v2.rs @@ -46,7 +46,7 @@ fn main() -> Result<(), Box> { let local_peer_id = PeerId::from(local_key.public()); println!("Local peer id: {:?}", local_peer_id); - let tcp_transport = TcpTransport::new(); + let tcp_transport = TcpTransport::default(); let noise_keys = noise::Keypair::::new() .into_authentic(&local_key) diff --git a/protocols/request-response/tests/ping.rs b/protocols/request-response/tests/ping.rs index ee985b60b61..8cbc06e7444 100644 --- a/protocols/request-response/tests/ping.rs +++ b/protocols/request-response/tests/ping.rs @@ -32,7 +32,7 @@ use libp2p_core::{ use libp2p_noise::{Keypair, NoiseConfig, X25519Spec}; use libp2p_request_response::*; use libp2p_swarm::{Swarm, SwarmEvent}; -use libp2p_tcp::TcpTransport; +use libp2p_tcp::{GenTcpConfig, TcpTransport}; use rand::{self, Rng}; use std::{io, iter}; @@ -300,8 +300,7 @@ fn mk_transport() -> (PeerId, transport::Boxed<(PeerId, StreamMuxerBox)>) { .unwrap(); ( peer_id, - TcpTransport::new() - .nodelay(true) + TcpTransport::new(GenTcpConfig::default().nodelay(true)) .upgrade(upgrade::Version::V1) .authenticate(NoiseConfig::xx(noise_keys).into_authenticated()) .multiplex(libp2p_yamux::YamuxConfig::default()) From 1924c12824f84272b50440efa00746a8a8f4da7f Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 15:22:33 +0200 Subject: [PATCH 21/47] muxers/mplex: adapt tests and benches --- muxers/mplex/benches/split_send_size.rs | 50 +++++++++------- muxers/mplex/tests/async_write.rs | 22 +++---- muxers/mplex/tests/two_peers.rs | 77 ++++++++++++++----------- 3 files changed, 85 insertions(+), 64 deletions(-) diff --git a/muxers/mplex/benches/split_send_size.rs b/muxers/mplex/benches/split_send_size.rs index 38d4e84ee02..465ac18bec5 100644 --- a/muxers/mplex/benches/split_send_size.rs +++ b/muxers/mplex/benches/split_send_size.rs @@ -23,15 +23,16 @@ use async_std::task; use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; -use futures::channel::oneshot; use futures::future::poll_fn; use futures::prelude::*; +use futures::{channel::oneshot, future::join}; use libp2p_core::{ identity, multiaddr::multiaddr, muxing, transport, upgrade, Multiaddr, PeerId, StreamMuxer, Transport, }; use libp2p_mplex as mplex; use libp2p_plaintext::PlainText2Config; +use libp2p_tcp::GenTcpConfig; use std::time::Duration; type BenchTransport = transport::Boxed<(PeerId, muxing::StreamMuxerBox)>; @@ -57,11 +58,13 @@ fn prepare(c: &mut Criterion) { let tcp_addr = multiaddr![Ip4(std::net::Ipv4Addr::new(127, 0, 0, 1)), Tcp(0u16)]; for &size in BENCH_SIZES.iter() { tcp.throughput(Throughput::Bytes(payload.len() as u64)); - let mut trans = tcp_transport(size); + let mut receiver_trans = tcp_transport(size); + let mut sender_trans = tcp_transport(size); tcp.bench_function(format!("{}", size), |b| { b.iter(|| { run( - black_box(&mut trans), + black_box(&mut receiver_trans), + black_box(&mut sender_trans), black_box(&payload), black_box(&tcp_addr), ) @@ -74,11 +77,13 @@ fn prepare(c: &mut Criterion) { let mem_addr = multiaddr![Memory(0u64)]; for &size in BENCH_SIZES.iter() { mem.throughput(Throughput::Bytes(payload.len() as u64)); - let mut trans = mem_transport(size); + let mut receiver_trans = mem_transport(size); + let mut sender_trans = mem_transport(size); mem.bench_function(format!("{}", size), |b| { b.iter(|| { run( - black_box(&mut trans), + black_box(&mut receiver_trans), + black_box(&mut sender_trans), black_box(&payload), black_box(&mem_addr), ) @@ -89,20 +94,26 @@ fn prepare(c: &mut Criterion) { } /// Transfers the given payload between two nodes using the given transport. -fn run(transport: &mut BenchTransport, payload: &Vec, listen_addr: &Multiaddr) { - let mut listener = transport.listen_on(listen_addr.clone()).unwrap(); +fn run( + receiver_trans: &mut BenchTransport, + sender_trans: &mut BenchTransport, + payload: &Vec, + listen_addr: &Multiaddr, +) { + receiver_trans + .listen_on(transport::ListenerId::new(1), listen_addr.clone()) + .unwrap(); let (addr_sender, addr_receiver) = oneshot::channel(); let mut addr_sender = Some(addr_sender); let payload_len = payload.len(); - // Spawn the receiver. - let receiver = task::spawn(async move { + let receiver = async move { loop { - match listener.next().await.unwrap().unwrap() { - transport::TransportEvent::NewAddress(a) => { - addr_sender.take().unwrap().send(a).unwrap(); + match receiver_trans.next().await.unwrap() { + transport::TransportEvent::NewAddress { listen_addr, .. } => { + addr_sender.take().unwrap().send(listen_addr).unwrap(); } - transport::TransportEvent::Upgrade { upgrade, .. } => { + transport::TransportEvent::Incoming { upgrade, .. } => { let (_peer, conn) = upgrade.await.unwrap(); match poll_fn(|cx| conn.poll_event(cx)).await { Ok(muxing::StreamMuxerEvent::InboundSubstream(mut s)) => { @@ -129,12 +140,12 @@ fn run(transport: &mut BenchTransport, payload: &Vec, listen_addr: &Multiadd _ => panic!("Unexpected listener event"), } } - }); + }; // Spawn and block on the sender, i.e. until all data is sent. - task::block_on(async move { + let sender = async move { let addr = addr_receiver.await.unwrap(); - let (_peer, conn) = transport.dial(addr).unwrap().await.unwrap(); + let (_peer, conn) = sender_trans.dial(addr).unwrap().await.unwrap(); let mut handle = conn.open_outbound(); let mut stream = poll_fn(|cx| conn.poll_outbound(cx, &mut handle)) .await @@ -152,10 +163,10 @@ fn run(transport: &mut BenchTransport, payload: &Vec, listen_addr: &Multiadd return; } } - }); + }; // Wait for all data to be received. - task::block_on(receiver); + task::block_on(join(sender, receiver)); } fn tcp_transport(split_send_size: usize) -> BenchTransport { @@ -165,8 +176,7 @@ fn tcp_transport(split_send_size: usize) -> BenchTransport { let mut mplex = mplex::MplexConfig::default(); mplex.set_split_send_size(split_send_size); - libp2p_tcp::TcpTransport::new() - .nodelay(true) + libp2p_tcp::TcpTransport::new(GenTcpConfig::default().nodelay(true)) .upgrade(upgrade::Version::V1) .authenticate(PlainText2Config { local_public_key }) .multiplex(mplex) diff --git a/muxers/mplex/tests/async_write.rs b/muxers/mplex/tests/async_write.rs index 74be06aee6a..c0adf177b81 100644 --- a/muxers/mplex/tests/async_write.rs +++ b/muxers/mplex/tests/async_write.rs @@ -32,28 +32,30 @@ fn async_write() { let bg_thread = async_std::task::spawn(async move { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpTransport::new() - .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); + let mut transport = TcpTransport::default() + .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)) + .boxed(); - let mut listener = transport - .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) + transport + .listen_on( + libp2p_core::transport::ListenerId::new(1), + "/ip4/127.0.0.1/tcp/0".parse().unwrap(), + ) .unwrap(); - let addr = listener + let addr = transport .next() .await .expect("some event") - .expect("no error") .into_new_address() .expect("listen address"); tx.send(addr).unwrap(); - let client = listener + let client = transport .next() .await - .unwrap() - .unwrap() + .expect("some event") .into_upgrade() .unwrap() .0 @@ -71,7 +73,7 @@ fn async_write() { async_std::task::block_on(async { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpTransport::new() + let mut transport = TcpTransport::default() .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap()); diff --git a/muxers/mplex/tests/two_peers.rs b/muxers/mplex/tests/two_peers.rs index 1d422f05b96..851467f0dbc 100644 --- a/muxers/mplex/tests/two_peers.rs +++ b/muxers/mplex/tests/two_peers.rs @@ -32,28 +32,30 @@ fn client_to_server_outbound() { let bg_thread = async_std::task::spawn(async move { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpTransport::new() - .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); - - let mut listener = transport - .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) + let mut transport = TcpTransport::default() + .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)) + .boxed(); + + transport + .listen_on( + libp2p_core::transport::ListenerId::new(1), + "/ip4/127.0.0.1/tcp/0".parse().unwrap(), + ) .unwrap(); - let addr = listener + let addr = transport .next() .await .expect("some event") - .expect("no error") .into_new_address() .expect("listen address"); tx.send(addr).unwrap(); - let client = listener + let client = transport .next() .await - .unwrap() - .unwrap() + .expect("some event") .into_upgrade() .unwrap() .0 @@ -71,8 +73,9 @@ fn client_to_server_outbound() { async_std::task::block_on(async { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpTransport::new() - .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); + let mut transport = TcpTransport::default() + .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)) + .boxed(); let client = Arc::new(transport.dial(rx.await.unwrap()).unwrap().await.unwrap()); let mut inbound = loop { @@ -100,29 +103,31 @@ fn client_to_server_inbound() { let bg_thread = async_std::task::spawn(async move { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpTransport::new() - .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); + let mut transport = TcpTransport::default() + .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)) + .boxed(); - let mut listener = transport - .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) + transport + .listen_on( + libp2p_core::transport::ListenerId::new(1), + "/ip4/127.0.0.1/tcp/0".parse().unwrap(), + ) .unwrap(); - let addr = listener + let addr = transport .next() .await .expect("some event") - .expect("no error") .into_new_address() .expect("listen address"); tx.send(addr).unwrap(); let client = Arc::new( - listener + transport .next() .await - .unwrap() - .unwrap() + .expect("some event") .into_upgrade() .unwrap() .0 @@ -147,8 +152,9 @@ fn client_to_server_inbound() { async_std::task::block_on(async { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpTransport::new() - .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); + let mut transport = TcpTransport::default() + .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)) + .boxed(); let client = transport.dial(rx.await.unwrap()).unwrap().await.unwrap(); let mut outbound = muxing::outbound_from_ref_and_wrap(Arc::new(client)) @@ -168,28 +174,30 @@ fn protocol_not_match() { let _bg_thread = async_std::task::spawn(async move { let mplex = libp2p_mplex::MplexConfig::new(); - let mut transport = TcpTransport::new() - .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); + let mut transport = TcpTransport::default() + .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)) + .boxed(); - let mut listener = transport - .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) + transport + .listen_on( + libp2p_core::transport::ListenerId::new(1), + "/ip4/127.0.0.1/tcp/0".parse().unwrap(), + ) .unwrap(); - let addr = listener + let addr = transport .next() .await .expect("some event") - .expect("no error") .into_new_address() .expect("listen address"); tx.send(addr).unwrap(); - let client = listener + let client = transport .next() .await - .unwrap() - .unwrap() + .expect("some event") .into_upgrade() .unwrap() .0 @@ -209,8 +217,9 @@ fn protocol_not_match() { // Make sure they do not connect when protocols do not match let mut mplex = libp2p_mplex::MplexConfig::new(); mplex.set_protocol_name(b"/mplextest/1.0.0"); - let mut transport = TcpTransport::new() - .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)); + let mut transport = TcpTransport::default() + .and_then(move |c, e| upgrade::apply(c, mplex, e, upgrade::Version::V1)) + .boxed(); match transport.dial(rx.await.unwrap()).unwrap().await { Ok(_) => { assert!(false, "Dialing should fail here as protocols do not match") From 8ba3c20209657eb17b5e38e578caad7664c944e4 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 15:23:02 +0200 Subject: [PATCH 22/47] transports/*: adapt tests in upgrade transports --- transports/deflate/tests/test.rs | 45 +++++++++-------- transports/noise/src/lib.rs | 2 +- transports/noise/tests/smoke.rs | 75 +++++++++++++++-------------- transports/plaintext/tests/smoke.rs | 43 +++++++++-------- 4 files changed, 87 insertions(+), 78 deletions(-) diff --git a/transports/deflate/tests/test.rs b/transports/deflate/tests/test.rs index 48bec03906f..646f8df59a3 100644 --- a/transports/deflate/tests/test.rs +++ b/transports/deflate/tests/test.rs @@ -19,7 +19,10 @@ // DEALINGS IN THE SOFTWARE. use futures::{future, prelude::*}; -use libp2p_core::{transport::Transport, upgrade}; +use libp2p_core::{ + transport::{ListenerId, Transport}, + upgrade, +}; use libp2p_deflate::DeflateConfig; use libp2p_tcp::TcpTransport; use quickcheck::{QuickCheck, RngCore, TestResult}; @@ -44,38 +47,41 @@ fn lot_of_data() { } async fn run(message1: Vec) { - let mut transport = TcpTransport::new().and_then(|conn, endpoint| { - upgrade::apply( - conn, - DeflateConfig::default(), - endpoint, - upgrade::Version::V1, + let new_transport = || { + TcpTransport::default() + .and_then(|conn, endpoint| { + upgrade::apply( + conn, + DeflateConfig::default(), + endpoint, + upgrade::Version::V1, + ) + }) + .boxed() + }; + let mut listener_trans = new_transport(); + listener_trans + .listen_on( + ListenerId::new(1), + "/ip4/0.0.0.0/tcp/0".parse().expect("multiaddr"), ) - }); - - let mut listener = transport - .clone() - .listen_on("/ip4/0.0.0.0/tcp/0".parse().expect("multiaddr")) .expect("listener"); - let listen_addr = listener - .by_ref() + let listen_addr = listener_trans .next() .await .expect("some event") - .expect("no error") .into_new_address() .expect("new address"); let message2 = message1.clone(); let listener_task = async_std::task::spawn(async move { - let mut conn = listener - .filter(|e| future::ready(e.as_ref().map(|e| e.is_upgrade()).unwrap_or(false))) + let mut conn = listener_trans + .filter(|e| future::ready(e.is_upgrade())) .next() .await .expect("some event") - .expect("no error") .into_upgrade() .expect("upgrade") .0 @@ -90,7 +96,8 @@ async fn run(message1: Vec) { conn.close().await.expect("close") }); - let mut conn = transport + let mut dialer_trans = new_transport(); + let mut conn = dialer_trans .dial(listen_addr) .expect("dialer") .await diff --git a/transports/noise/src/lib.rs b/transports/noise/src/lib.rs index 0b76fd048a7..ee609fd028d 100644 --- a/transports/noise/src/lib.rs +++ b/transports/noise/src/lib.rs @@ -47,7 +47,7 @@ //! let id_keys = identity::Keypair::generate_ed25519(); //! let dh_keys = Keypair::::new().into_authentic(&id_keys).unwrap(); //! let noise = NoiseConfig::xx(dh_keys).into_authenticated(); -//! let builder = TcpTransport::new().upgrade(upgrade::Version::V1).authenticate(noise); +//! let builder = TcpTransport::default().upgrade(upgrade::Version::V1).authenticate(noise); //! // let transport = builder.multiplex(...); //! # } //! ``` diff --git a/transports/noise/tests/smoke.rs b/transports/noise/tests/smoke.rs index 9a68c65c6ce..7e6fa1a7508 100644 --- a/transports/noise/tests/smoke.rs +++ b/transports/noise/tests/smoke.rs @@ -24,7 +24,7 @@ use futures::{ prelude::*, }; use libp2p_core::identity; -use libp2p_core::transport::{ListenerEvent, Transport}; +use libp2p_core::transport::{self, ListenerId, Transport}; use libp2p_core::upgrade::{self, apply_inbound, apply_outbound, Negotiated}; use libp2p_noise::{ Keypair, NoiseConfig, NoiseError, NoiseOutput, RemoteIdentity, X25519Spec, X25519, @@ -41,7 +41,7 @@ fn core_upgrade_compat() { let id_keys = identity::Keypair::generate_ed25519(); let dh_keys = Keypair::::new().into_authentic(&id_keys).unwrap(); let noise = NoiseConfig::xx(dh_keys).into_authenticated(); - let _ = TcpTransport::new() + let _ = TcpTransport::default() .upgrade(upgrade::Version::V1) .authenticate(noise); } @@ -60,7 +60,7 @@ fn xx_spec() { let server_dh = Keypair::::new() .into_authentic(&server_id) .unwrap(); - let server_transport = TcpTransport::new() + let server_transport = TcpTransport::default() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -69,12 +69,13 @@ fn xx_spec() { upgrade::Version::V1, ) }) - .and_then(move |out, _| expect_identity(out, &client_id_public)); + .and_then(move |out, _| expect_identity(out, &client_id_public)) + .boxed(); let client_dh = Keypair::::new() .into_authentic(&client_id) .unwrap(); - let client_transport = TcpTransport::new() + let client_transport = TcpTransport::default() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -83,7 +84,8 @@ fn xx_spec() { upgrade::Version::V1, ) }) - .and_then(move |out, _| expect_identity(out, &server_id_public)); + .and_then(move |out, _| expect_identity(out, &server_id_public)) + .boxed(); run(server_transport, client_transport, messages); true @@ -105,7 +107,7 @@ fn xx() { let client_id_public = client_id.public(); let server_dh = Keypair::::new().into_authentic(&server_id).unwrap(); - let server_transport = TcpTransport::new() + let server_transport = TcpTransport::default() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -114,10 +116,11 @@ fn xx() { upgrade::Version::V1, ) }) - .and_then(move |out, _| expect_identity(out, &client_id_public)); + .and_then(move |out, _| expect_identity(out, &client_id_public)) + .boxed(); let client_dh = Keypair::::new().into_authentic(&client_id).unwrap(); - let client_transport = TcpTransport::new() + let client_transport = TcpTransport::default() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -126,7 +129,8 @@ fn xx() { upgrade::Version::V1, ) }) - .and_then(move |out, _| expect_identity(out, &server_id_public)); + .and_then(move |out, _| expect_identity(out, &server_id_public)) + .boxed(); run(server_transport, client_transport, messages); true @@ -148,7 +152,7 @@ fn ix() { let client_id_public = client_id.public(); let server_dh = Keypair::::new().into_authentic(&server_id).unwrap(); - let server_transport = TcpTransport::new() + let server_transport = TcpTransport::default() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -157,10 +161,11 @@ fn ix() { upgrade::Version::V1, ) }) - .and_then(move |out, _| expect_identity(out, &client_id_public)); + .and_then(move |out, _| expect_identity(out, &client_id_public)) + .boxed(); let client_dh = Keypair::::new().into_authentic(&client_id).unwrap(); - let client_transport = TcpTransport::new() + let client_transport = TcpTransport::default() .and_then(move |output, endpoint| { upgrade::apply( output, @@ -169,7 +174,8 @@ fn ix() { upgrade::Version::V1, ) }) - .and_then(move |out, _| expect_identity(out, &server_id_public)); + .and_then(move |out, _| expect_identity(out, &server_id_public)) + .boxed(); run(server_transport, client_transport, messages); true @@ -192,7 +198,7 @@ fn ik_xx() { let server_dh = Keypair::::new().into_authentic(&server_id).unwrap(); let server_dh_public = server_dh.public().clone(); - let server_transport = TcpTransport::new() + let server_transport = TcpTransport::default() .and_then(move |output, endpoint| { if endpoint.is_listener() { Either::Left(apply_inbound(output, NoiseConfig::ik_listener(server_dh))) @@ -204,11 +210,12 @@ fn ik_xx() { )) } }) - .and_then(move |out, _| expect_identity(out, &client_id_public)); + .and_then(move |out, _| expect_identity(out, &client_id_public)) + .boxed(); let client_dh = Keypair::::new().into_authentic(&client_id).unwrap(); let server_id_public2 = server_id_public.clone(); - let client_transport = TcpTransport::new() + let client_transport = TcpTransport::default() .and_then(move |output, endpoint| { if endpoint.is_dialer() { Either::Left(apply_outbound( @@ -220,7 +227,8 @@ fn ik_xx() { Either::Right(apply_inbound(output, NoiseConfig::xx(client_dh))) } }) - .and_then(move |out, _| expect_identity(out, &server_id_public2)); + .and_then(move |out, _| expect_identity(out, &server_id_public2)) + .boxed(); run(server_transport, client_transport, messages); true @@ -232,34 +240,28 @@ fn ik_xx() { type Output = (RemoteIdentity, NoiseOutput>>); -fn run(mut server_transport: T, mut client_transport: U, messages: I) -where - T: Transport>, - T::Dial: Send + 'static, - T::Listener: Send + Unpin + 'static, - T::ListenerUpgrade: Send + 'static, - U: Transport>, - U::Dial: Send + 'static, - U::Listener: Send + 'static, - U::ListenerUpgrade: Send + 'static, +fn run( + mut server: transport::Boxed>, + mut client: transport::Boxed>, + messages: I, +) where I: IntoIterator + Clone, { futures::executor::block_on(async { - let mut server: T::Listener = server_transport - .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) + server + .listen_on(ListenerId::new(1), "/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); let server_address = server - .try_next() + .next() .await .expect("some event") - .expect("no error") .into_new_address() .expect("listen address"); let outbound_msgs = messages.clone(); let client_fut = async { - let mut client_session = client_transport + let mut client_session = client .dial(server_address.clone()) .unwrap() .await @@ -276,13 +278,12 @@ where let server_fut = async { let mut server_session = server - .try_next() + .next() .await .expect("some event") - .map(ListenerEvent::into_upgrade) - .expect("no error") - .map(|client| client.0) + .into_upgrade() .expect("listener upgrade") + .0 .await .map(|(_, session)| session) .expect("no error"); diff --git a/transports/plaintext/tests/smoke.rs b/transports/plaintext/tests/smoke.rs index ec20e8ff20e..5f599d05269 100644 --- a/transports/plaintext/tests/smoke.rs +++ b/transports/plaintext/tests/smoke.rs @@ -18,12 +18,14 @@ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -use futures::io::{AsyncReadExt, AsyncWriteExt}; -use futures::stream::TryStreamExt; +use futures::{ + io::{AsyncReadExt, AsyncWriteExt}, + StreamExt, +}; use libp2p_core::{ identity, multiaddr::Multiaddr, - transport::{ListenerEvent, Transport}, + transport::{ListenerId, Transport}, upgrade, }; use libp2p_plaintext::PlainText2Config; @@ -45,8 +47,8 @@ fn variable_msg_length() { let client_id_public = client_id.public(); futures::executor::block_on(async { - let mut server_transport = - libp2p_core::transport::MemoryTransport {}.and_then(move |output, endpoint| { + let mut server = libp2p_core::transport::MemoryTransport::new() + .and_then(move |output, endpoint| { upgrade::apply( output, PlainText2Config { @@ -55,10 +57,11 @@ fn variable_msg_length() { endpoint, libp2p_core::upgrade::Version::V1, ) - }); + }) + .boxed(); - let mut client_transport = - libp2p_core::transport::MemoryTransport {}.and_then(move |output, endpoint| { + let mut client = libp2p_core::transport::MemoryTransport::new() + .and_then(move |output, endpoint| { upgrade::apply( output, PlainText2Config { @@ -67,31 +70,30 @@ fn variable_msg_length() { endpoint, libp2p_core::upgrade::Version::V1, ) - }); + }) + .boxed(); let server_address: Multiaddr = format!("/memory/{}", std::cmp::Ord::max(1, rand::random::())) .parse() .unwrap(); - let mut server = server_transport.listen_on(server_address.clone()).unwrap(); + server + .listen_on(ListenerId::new(1), server_address.clone()) + .unwrap(); // Ignore server listen address event. let _ = server - .try_next() + .next() .await .expect("some event") - .expect("no error") .into_new_address() .expect("listen address"); let client_fut = async { debug!("dialing {:?}", server_address); - let (received_server_id, mut client_channel) = client_transport - .dial(server_address) - .unwrap() - .await - .unwrap(); + let (received_server_id, mut client_channel) = + client.dial(server_address).unwrap().await.unwrap(); assert_eq!(received_server_id, server_id.public().to_peer_id()); debug!("Client: writing message."); @@ -105,13 +107,12 @@ fn variable_msg_length() { let server_fut = async { let mut server_channel = server - .try_next() + .next() .await .expect("some event") - .map(ListenerEvent::into_upgrade) + .into_upgrade() .expect("no error") - .map(|client| client.0) - .expect("listener upgrade xyz") + .0 .await .map(|(_, session)| session) .expect("no error"); From 96ae97bb9cac3f40843dc5fcd7a54e98d94b749c Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 15:23:43 +0200 Subject: [PATCH 23/47] src/lib: adapt development transports --- src/lib.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 835d3f14d74..2a7d80a25e3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -201,10 +201,13 @@ pub async fn development_transport( keypair: identity::Keypair, ) -> std::io::Result> { let transport = { - let tcp = tcp::TcpTransport::new().nodelay(true); - let dns_tcp = dns::DnsConfig::system(tcp).await?; - let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone()); - dns_tcp.or_transport(ws_dns_tcp) + let dns_tcp = || { + let tcp_config = tcp::GenTcpConfig::default().nodelay(true); + let tcp = tcp::TcpTransport::new(tcp_config); + dns::DnsConfig::system(tcp) + }; + let ws_dns_tcp = websocket::WsConfig::new(dns_tcp().await?); + dns_tcp().await?.or_transport(ws_dns_tcp) }; let noise_keys = noise::Keypair::::new() @@ -258,10 +261,13 @@ pub fn tokio_development_transport( keypair: identity::Keypair, ) -> std::io::Result> { let transport = { - let tcp = tcp::TokioTcpTransport::new().nodelay(true); - let dns_tcp = dns::TokioDnsConfig::system(tcp)?; - let ws_dns_tcp = websocket::WsConfig::new(dns_tcp.clone()); - dns_tcp.or_transport(ws_dns_tcp) + let dns_tcp = || { + let tcp_config = tcp::GenTcpConfig::default().nodelay(true); + let tcp = tcp::TokioTcpTransport::new(tcp_config); + dns::TokioDnsConfig::system(tcp) + }; + let ws_dns_tcp = websocket::WsConfig::new(dns_tcp().await?); + dns_tcp().await?.or_transport(ws_dns_tcp) }; let noise_keys = noise::Keypair::::new() From c686b5a9c24c7eec6eeef1e0e19537ec4ae008af Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 15:24:15 +0200 Subject: [PATCH 24/47] examples: adapt exmaples to tcp transport changes --- examples/chat-tokio.rs | 4 ++-- examples/ipfs-private.rs | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/chat-tokio.rs b/examples/chat-tokio.rs index eb79198bfc4..66c25205246 100644 --- a/examples/chat-tokio.rs +++ b/examples/chat-tokio.rs @@ -52,6 +52,7 @@ use libp2p::{ PeerId, Transport, }; +use libp2p_tcp::GenTcpConfig; use std::error::Error; use tokio::io::{self, AsyncBufReadExt}; @@ -72,8 +73,7 @@ async fn main() -> Result<(), Box> { // Create a tokio-based TCP transport use noise for authenticated // encryption and Mplex for multiplexing of substreams on a TCP stream. - let transport = TokioTcpTransport::new() - .nodelay(true) + let transport = TokioTcpTransport::new(GenTcpConfig::default().nodelay(true)) .upgrade(upgrade::Version::V1) .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated()) .multiplex(mplex::MplexConfig::new()) diff --git a/examples/ipfs-private.rs b/examples/ipfs-private.rs index 3a4766e382f..113bdf988f2 100644 --- a/examples/ipfs-private.rs +++ b/examples/ipfs-private.rs @@ -48,6 +48,7 @@ use libp2p::{ yamux::YamuxConfig, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport, }; +use libp2p_tcp::GenTcpConfig; use std::{env, error::Error, fs, path::Path, str::FromStr, time::Duration}; /// Builds the transport that serves as a common ground for all connections. @@ -61,7 +62,7 @@ pub fn build_transport( let noise_config = noise::NoiseConfig::xx(noise_keys).into_authenticated(); let yamux_config = YamuxConfig::default(); - let base_transport = TcpTransport::new().nodelay(true); + let base_transport = TcpTransport::new(GenTcpConfig::default().nodelay(true)); let maybe_encrypted = match psk { Some(psk) => EitherTransport::Left( base_transport.and_then(move |socket, _| PnetConfig::new(psk).handshake(socket)), From 354d2f058f76307dded4ae550495ea0f652f318d Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 19:23:49 +0200 Subject: [PATCH 25/47] *: add Transport::remove_listener --- core/src/either.rs | 7 ++ core/src/transport.rs | 27 +++---- core/src/transport/and_then.rs | 4 + core/src/transport/boxed.rs | 9 +++ core/src/transport/choice.rs | 4 + core/src/transport/dummy.rs | 4 + core/src/transport/map.rs | 4 + core/src/transport/map_err.rs | 4 + core/src/transport/memory.rs | 116 ++++++++++++++++++--------- core/src/transport/optional.rs | 8 ++ core/src/transport/timeout.rs | 4 + core/src/transport/upgrade.rs | 8 ++ src/bandwidth.rs | 4 + swarm/src/lib.rs | 60 +++++++------- transports/dns/src/lib.rs | 4 + transports/tcp/src/lib.rs | 35 ++++----- transports/uds/src/lib.rs | 122 +++++++++++++++++------------ transports/websocket/src/framed.rs | 17 ++-- transports/websocket/src/lib.rs | 4 + 19 files changed, 286 insertions(+), 159 deletions(-) diff --git a/core/src/either.rs b/core/src/either.rs index 66607f5cb36..dbb73b470d6 100644 --- a/core/src/either.rs +++ b/core/src/either.rs @@ -479,6 +479,13 @@ where } } + fn remove_listener(&mut self, id: ListenerId) -> bool { + match self { + EitherTransport::Left(t) => t.remove_listener(id), + EitherTransport::Right(t) => t.remove_listener(id), + } + } + fn listen_on( &mut self, id: ListenerId, diff --git a/core/src/transport.rs b/core/src/transport.rs index 4b4ca825ec7..dfbf4fce6bd 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -108,6 +108,7 @@ pub trait Transport { /// obtained from [dialing](Transport::dial). type Dial: Future>; + // TODO: fix docs /// Listens on the given [`Multiaddr`], producing a stream of pending, inbound connections /// and addresses this transport is listening on (cf. [`TransportEvent`]). /// @@ -121,6 +122,12 @@ pub trait Transport { where Self: Sized; + /// Remove a listener. + /// + /// Return `true` if there was a listener with this Id, `false` + /// otherwise. + fn remove_listener(&mut self, id: ListenerId) -> bool; + /// Dials the given [`Multiaddr`], returning a future for a pending outbound connection. /// /// If [`TransportError::MultiaddrNotSupported`] is returned, it may be desirable to @@ -277,11 +284,9 @@ pub enum TransportEvent { send_back_addr: Multiaddr, }, /// A listener closed. - Closed { + ListenerClosed { /// The ID of the listener that closed. listener_id: ListenerId, - /// The addresses that the listener was listening on. - addresses: Vec, /// Reason for the closure. Contains `Ok(())` if the stream produced `None`, or `Err` /// if the stream produced an error. reason: Result<(), TErr>, @@ -329,13 +334,11 @@ impl TransportEvent { TransportEvent::Error { listener_id, error } => { TransportEvent::Error { listener_id, error } } - TransportEvent::Closed { + TransportEvent::ListenerClosed { listener_id, - addresses, reason, - } => TransportEvent::Closed { + } => TransportEvent::ListenerClosed { listener_id, - addresses, reason, }, } @@ -372,13 +375,11 @@ impl TransportEvent { listener_id, error: map_err(error), }, - TransportEvent::Closed { + TransportEvent::ListenerClosed { listener_id, - addresses, reason, - } => TransportEvent::Closed { + } => TransportEvent::ListenerClosed { listener_id, - addresses, reason: reason.map_err(map_err), }, } @@ -486,14 +487,12 @@ impl fmt::Debug for TransportEvent { .field("listener_id", listener_id) .field("local_addr", local_addr) .finish(), - TransportEvent::Closed { + TransportEvent::ListenerClosed { listener_id, - addresses, reason, } => f .debug_struct("TransportEvent::Closed") .field("listener_id", listener_id) - .field("addresses", addresses) .field("reason", reason) .finish(), TransportEvent::Error { listener_id, error } => f diff --git a/core/src/transport/and_then.rs b/core/src/transport/and_then.rs index e7e4f04a446..00be2dddc09 100644 --- a/core/src/transport/and_then.rs +++ b/core/src/transport/and_then.rs @@ -64,6 +64,10 @@ where .map_err(|err| err.map(EitherError::A)) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.transport.remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { let dialed_fut = self .transport diff --git a/core/src/transport/boxed.rs b/core/src/transport/boxed.rs index 6e2ac4d27ee..523e5472653 100644 --- a/core/src/transport/boxed.rs +++ b/core/src/transport/boxed.rs @@ -57,6 +57,7 @@ trait Abstract { id: ListenerId, addr: Multiaddr, ) -> Result<(), TransportError>; + fn remove_listener(&mut self, id: ListenerId) -> bool; fn dial(&mut self, addr: Multiaddr) -> Result, TransportError>; fn dial_as_listener(&mut self, addr: Multiaddr) -> Result, TransportError>; fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option; @@ -81,6 +82,10 @@ where Transport::listen_on(self, id, addr).map_err(|e| e.map(box_err)) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + Transport::remove_listener(self, id) + } + fn dial(&mut self, addr: Multiaddr) -> Result, TransportError> { let fut = Transport::dial(self, addr) .map(|r| r.map_err(box_err)) @@ -134,6 +139,10 @@ impl Transport for Boxed { self.inner.listen_on(id, addr) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.inner.remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { self.inner.dial(addr) } diff --git a/core/src/transport/choice.rs b/core/src/transport/choice.rs index 66765a55a36..42e41dc44b9 100644 --- a/core/src/transport/choice.rs +++ b/core/src/transport/choice.rs @@ -62,6 +62,10 @@ where Err(TransportError::MultiaddrNotSupported(addr)) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.0.remove_listener(id) || self.1.remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { let addr = match self.0.dial(addr) { Ok(connec) => return Ok(EitherFuture::First(connec)), diff --git a/core/src/transport/dummy.rs b/core/src/transport/dummy.rs index d96e54a54e0..951d1039328 100644 --- a/core/src/transport/dummy.rs +++ b/core/src/transport/dummy.rs @@ -67,6 +67,10 @@ impl Transport for DummyTransport { Err(TransportError::MultiaddrNotSupported(addr)) } + fn remove_listener(&mut self, _id: ListenerId) -> bool { + false + } + fn dial(&mut self, addr: Multiaddr) -> Result> { Err(TransportError::MultiaddrNotSupported(addr)) } diff --git a/core/src/transport/map.rs b/core/src/transport/map.rs index 5be8bf27bc1..553f3e6338d 100644 --- a/core/src/transport/map.rs +++ b/core/src/transport/map.rs @@ -69,6 +69,10 @@ where self.transport.listen_on(id, addr) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.transport.remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { let future = self.transport.dial(addr.clone())?; let p = ConnectedPoint::Dialer { diff --git a/core/src/transport/map_err.rs b/core/src/transport/map_err.rs index c71370458fd..56e1ebf2929 100644 --- a/core/src/transport/map_err.rs +++ b/core/src/transport/map_err.rs @@ -61,6 +61,10 @@ where .map_err(|err| err.map(map)) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.transport.remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { let map = self.map.clone(); match self.transport.dial(addr) { diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index a6524ffc9b4..a0b9c6bfe51 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -211,6 +211,18 @@ impl Transport for MemoryTransport { Ok(()) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + if let Some(index) = self.listeners.iter().position(|listener| listener.id == id) { + let listener = self.listeners.get_mut(index).unwrap(); + let val_in = HUB.unregister_port(&listener.port); + debug_assert!(val_in.is_some()); + listener.receiver.close(); + true + } else { + false + } + } + fn dial(&mut self, addr: Multiaddr) -> Result> { let port = if let Ok(port) = parse_memory_addr(&addr) { if let Some(port) = NonZeroU64::new(port) { @@ -258,13 +270,19 @@ impl Transport for MemoryTransport { let event = match Stream::poll_next(Pin::new(&mut listener.receiver), cx) { Poll::Pending => None, - Poll::Ready(None) => panic!("Alive listeners always have a sender."), Poll::Ready(Some((channel, dial_port))) => Some(TransportEvent::Incoming { listener_id: listener.id, upgrade: future::ready(Ok(channel)), local_addr: listener.addr.clone(), send_back_addr: Protocol::Memory(dial_port.get()).into(), }), + Poll::Ready(None) => { + // Listener was closed. + return Poll::Ready(TransportEvent::ListenerClosed { + listener_id: listener.id, + reason: Ok(()), + }); + } }; self.listeners.push_front(listener); @@ -314,13 +332,6 @@ pub struct Listener { tell_listen_addr: bool, } -impl Drop for Listener { - fn drop(&mut self) { - let val_in = HUB.unregister_port(&self.port); - debug_assert!(val_in.is_some()); - } -} - /// If the address is `/memory/n`, returns the value of `n`. fn parse_memory_addr(a: &Multiaddr) -> Result { let mut protocols = a.iter(); @@ -446,33 +457,38 @@ mod tests { ); } - // TODO: test once remove_listener is implemented - // #[test] - // fn listening_twice() { - // let mut transport = MemoryTransport::default(); - // assert!(transport - // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) - // .is_ok()); - // assert!(transport - // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) - // .is_ok()); - // let _listener = transport - // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) - // .unwrap(); - // assert!(transport - // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) - // .is_err()); - // assert!(transport - // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) - // .is_err()); - // drop(_listener); - // assert!(transport - // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) - // .is_ok()); - // assert!(transport - // .listen_on(ListenerId::new(1), "/memory/1639174018481".parse().unwrap()) - // .is_ok()); - // } + #[test] + fn listening_twice() { + let mut transport = MemoryTransport::default(); + let listener_id_1 = ListenerId::new(1); + + let addr_1: Multiaddr = "/memory/1639174018481".parse().unwrap(); + let addr_2: Multiaddr = "/memory/8459375923478".parse().unwrap(); + + assert!(transport.listen_on(listener_id_1, addr_1.clone()).is_ok()); + assert!(transport.remove_listener(listener_id_1)); + + let listener_id_2 = ListenerId::new(2); + assert!(transport.listen_on(listener_id_2, addr_1.clone()).is_ok()); + let listener_id_3 = ListenerId::new(3); + assert!(transport.listen_on(listener_id_3, addr_2.clone()).is_ok()); + + assert!(transport + .listen_on(ListenerId::new(4), addr_1.clone()) + .is_err()); + assert!(transport + .listen_on(ListenerId::new(4), addr_2.clone()) + .is_err()); + + assert!(transport.remove_listener(listener_id_2)); + assert!(transport.listen_on(ListenerId::new(4), addr_1).is_ok()); + assert!(transport + .listen_on(ListenerId::new(4), addr_2.clone()) + .is_err()); + + assert!(transport.remove_listener(listener_id_3)); + assert!(transport.listen_on(ListenerId::new(4), addr_2).is_ok()); + } #[test] fn port_not_in_use() { @@ -491,6 +507,36 @@ mod tests { .is_ok()); } + #[test] + fn stop_listening() { + let rand_port = rand::random::().saturating_add(1); + let addr: Multiaddr = format!("/memory/{}", rand_port).parse().unwrap(); + + let mut transport = MemoryTransport::default().boxed(); + futures::executor::block_on(async { + let listener_id = ListenerId::new(1); + transport.listen_on(listener_id, addr.clone()).unwrap(); + let reported_addr = transport + .select_next_some() + .await + .into_new_address() + .expect("new address"); + assert_eq!(addr, reported_addr); + assert!(transport.remove_listener(listener_id)); + match transport.select_next_some().await { + TransportEvent::ListenerClosed { + listener_id: id, + reason, + } => { + assert_eq!(id, listener_id); + assert!(reason.is_ok()) + } + other => panic!("Unexpected transport event: {:?}", other), + } + assert!(!transport.remove_listener(listener_id)); + }) + } + #[test] fn communicating_between_dialer_and_listener() { let msg = [1, 2, 3]; diff --git a/core/src/transport/optional.rs b/core/src/transport/optional.rs index ad6bc83411a..839f55a4000 100644 --- a/core/src/transport/optional.rs +++ b/core/src/transport/optional.rs @@ -72,6 +72,14 @@ where } } + fn remove_listener(&mut self, id: ListenerId) -> bool { + if let Some(inner) = self.0.as_mut() { + inner.remove_listener(id) + } else { + false + } + } + fn dial(&mut self, addr: Multiaddr) -> Result> { if let Some(inner) = self.0.as_mut() { inner.dial(addr) diff --git a/core/src/transport/timeout.rs b/core/src/transport/timeout.rs index eec184ea46d..144f369c140 100644 --- a/core/src/transport/timeout.rs +++ b/core/src/transport/timeout.rs @@ -95,6 +95,10 @@ where .map_err(|err| err.map(TransportTimeoutError::Other)) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.inner.remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { let dial = self .inner diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index 338f8b92aed..9ca62dc8873 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -338,6 +338,10 @@ where self.0.dial(addr) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.0.remove_listener(id) + } + fn dial_as_listener( &mut self, addr: Multiaddr, @@ -410,6 +414,10 @@ where }) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.inner.remove_listener(id) + } + fn dial_as_listener( &mut self, addr: Multiaddr, diff --git a/src/bandwidth.rs b/src/bandwidth.rs index 1482c7a7cb1..3d33e910304 100644 --- a/src/bandwidth.rs +++ b/src/bandwidth.rs @@ -104,6 +104,10 @@ where self.inner.listen_on(id, addr) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.inner.remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { let sinks = self.sinks.clone(); self.inner diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 66c3cc4174c..dcef95863cc 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -95,7 +95,7 @@ use libp2p_core::{ }; use registry::{AddressIntoIter, Addresses}; use smallvec::SmallVec; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use std::iter; use std::num::{NonZeroU32, NonZeroU8, NonZeroUsize}; use std::{ @@ -276,7 +276,7 @@ where supported_protocols: SmallVec<[Vec; 16]>, /// List of multiaddresses we're listening on. - listened_addrs: SmallVec<[Multiaddr; 8]>, + listened_addrs: HashMap>, /// List of multiaddresses we're listening on, after account for external IP addresses and /// similar mechanisms. @@ -339,10 +339,8 @@ where /// /// Returns `true` if there was a listener with this ID, `false` /// otherwise. - pub fn remove_listener(&mut self, _id: ListenerId) -> bool { - // TODO - false - // self.transport.remove_listener(id) + pub fn remove_listener(&mut self, listener_id: ListenerId) -> bool { + self.transport.remove_listener(listener_id) } /// Dial a known or unknown peer. @@ -451,8 +449,9 @@ where }; let mut unique_addresses = HashSet::new(); - addresses.retain(|a| { - !self.listened_addrs.contains(a) && unique_addresses.insert(a.clone()) + addresses.retain(|addr| { + !self.listened_addrs.values().flatten().any(|a| a == addr) + && unique_addresses.insert(addr.clone()) }); if addresses.is_empty() { @@ -548,9 +547,7 @@ where /// Returns an iterator that produces the list of addresses we're listening on. pub fn listeners(&self) -> impl Iterator { - // TODO - vec![].into_iter() - // self.transport.listen_addrs() + self.listened_addrs.values().flatten() } /// Returns the peer ID of the swarm passed as parameter. @@ -875,8 +872,9 @@ where listen_addr, } => { log::debug!("Listener {:?}; New address: {:?}", listener_id, listen_addr); - if !self.listened_addrs.contains(&listen_addr) { - self.listened_addrs.push(listen_addr.clone()) + let addrs = self.listened_addrs.entry(listener_id).or_default(); + if !addrs.contains(&listen_addr) { + addrs.push(listen_addr.clone()) } self.behaviour .inject_new_listen_addr(listener_id, &listen_addr); @@ -894,7 +892,9 @@ where listener_id, listen_addr ); - self.listened_addrs.retain(|a| a != &listen_addr); + if let Some(addrs) = self.listened_addrs.get_mut(&listener_id) { + addrs.retain(|a| a != &listen_addr); + } self.behaviour .inject_expired_listen_addr(listener_id, &listen_addr); return Some(SwarmEvent::ExpiredListenAddr { @@ -902,13 +902,13 @@ where address: listen_addr, }); } - TransportEvent::Closed { + TransportEvent::ListenerClosed { listener_id, - addresses, reason, } => { log::debug!("Listener {:?}; Closed by {:?}.", listener_id, reason); - for addr in addresses.iter() { + let addrs = self.listened_addrs.remove(&listener_id).unwrap_or_default(); + for addr in addrs.iter() { self.behaviour.inject_expired_listen_addr(listener_id, addr); } self.behaviour.inject_listener_closed( @@ -920,7 +920,7 @@ where ); return Some(SwarmEvent::ListenerClosed { listener_id, - addresses, + addresses: addrs.to_vec(), reason, }); } @@ -967,7 +967,7 @@ where self.pending_event = Some((peer_id, handler, event)); } - NetworkBehaviourAction::ReportObservedAddr { address: _, score } => { + NetworkBehaviourAction::ReportObservedAddr { address, score } => { // Maps the given `observed_addr`, representing an address of the local // node observed by a remote peer, onto the locally known listen addresses // to yield one or more addresses of the local node that may be publicly @@ -981,12 +981,12 @@ where // // The translation is transport-specific. See [`Transport::address_translation`]. let translated_addresses = { - let mut addrs = vec![Multiaddr::empty()]; - // let mut addrs: Vec<_> = self - // .transport - // .listen_addrs() - // .filter_map(move |server| transport.address_translation(server, &address)) - // .collect(); + let mut addrs: Vec<_> = self + .listened_addrs + .values() + .flatten() + .filter_map(|server| self.transport.address_translation(server, &address)) + .collect(); // remove duplicates addrs.sort_unstable(); @@ -1067,7 +1067,7 @@ where let mut parameters = SwarmPollParameters { local_peer_id: &this.local_peer_id, supported_protocols: &this.supported_protocols, - listened_addrs: &this.listened_addrs, + listened_addrs: this.listened_addrs.values().flatten().collect(), external_addrs: &this.external_addrs, }; this.behaviour.poll(cx, &mut parameters) @@ -1238,13 +1238,13 @@ where pub struct SwarmPollParameters<'a> { local_peer_id: &'a PeerId, supported_protocols: &'a [Vec], - listened_addrs: &'a [Multiaddr], + listened_addrs: Vec<&'a Multiaddr>, external_addrs: &'a Addresses, } impl<'a> PollParameters for SwarmPollParameters<'a> { type SupportedProtocolsIter = std::iter::Cloned>>; - type ListenedAddressesIter = std::iter::Cloned>; + type ListenedAddressesIter = std::iter::Cloned>; type ExternalAddressesIter = AddressIntoIter; fn supported_protocols(&self) -> Self::SupportedProtocolsIter { @@ -1252,7 +1252,7 @@ impl<'a> PollParameters for SwarmPollParameters<'a> { } fn listened_addresses(&self) -> Self::ListenedAddressesIter { - self.listened_addrs.iter().cloned() + self.listened_addrs.clone().into_iter().cloned() } fn external_addresses(&self) -> Self::ExternalAddressesIter { @@ -1405,7 +1405,7 @@ where pool: Pool::new(self.local_peer_id, pool_config, self.connection_limits), behaviour: self.behaviour, supported_protocols, - listened_addrs: SmallVec::new(), + listened_addrs: HashMap::new(), external_addrs: Addresses::default(), banned_peers: HashSet::new(), banned_peer_connections: HashSet::new(), diff --git a/transports/dns/src/lib.rs b/transports/dns/src/lib.rs index 5e7da92dcf0..827da12ab13 100644 --- a/transports/dns/src/lib.rs +++ b/transports/dns/src/lib.rs @@ -208,6 +208,10 @@ where .map_err(|e| e.map(DnsErr::Transport)) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.inner.lock().remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { self.do_dial(addr, Endpoint::Dialer) } diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 46bc2c39e50..77622b01884 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -53,12 +53,10 @@ use libp2p_core::{ multiaddr::{Multiaddr, Protocol}, transport::{ListenerId, Transport, TransportError, TransportEvent}, }; -use log::debug; -use smallvec::SmallVec; use socket2::{Domain, Socket, Type}; use std::{ collections::{HashSet, VecDeque}, - io, mem, + io, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener}, pin::Pin, task::{Context, Poll}, @@ -404,6 +402,20 @@ where Ok(()) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + if let Some(index) = self.listeners.iter().position(|l| l.listener_id != id) { + self.listeners.remove(index); + self.pending_events + .push_back(TransportEvent::ListenerClosed { + listener_id: id, + reason: Ok(()), + }); + true + } else { + false + } + } + fn dial(&mut self, addr: Multiaddr) -> Result> { let socket_addr = if let Ok(socket_addr) = multiaddr_to_socketaddr(addr.clone()) { if socket_addr.port() == 0 || socket_addr.ip().is_unspecified() { @@ -510,11 +522,6 @@ where }); } Poll::Ready(Some(Ok(TcpTransportEvent::NewAddress(a)))) => { - if listener.addresses.contains(&a) { - debug!("Transport has reported address {} multiple times", a) - } else { - listener.addresses.push(a.clone()); - } let id = listener.listener_id; self.listeners.push_front(listener); return Poll::Ready(TransportEvent::NewAddress { @@ -523,7 +530,6 @@ where }); } Poll::Ready(Some(Ok(TcpTransportEvent::AddressExpired(a)))) => { - listener.addresses.retain(|x| x != &a); let id = listener.listener_id; self.listeners.push_front(listener); return Poll::Ready(TransportEvent::AddressExpired { @@ -540,18 +546,14 @@ where }); } Poll::Ready(None) => { - let addresses = mem::take(&mut listener.addresses).into_vec(); - return Poll::Ready(TransportEvent::Closed { + return Poll::Ready(TransportEvent::ListenerClosed { listener_id: listener.listener_id, - addresses, reason: Ok(()), }); } Poll::Ready(Some(Err(err))) => { - let addresses = mem::take(&mut listener.addresses).into_vec(); - return Poll::Ready(TransportEvent::Closed { + return Poll::Ready(TransportEvent::ListenerClosed { listener_id: listener.listener_id, - addresses, reason: Err(err), }); } @@ -615,8 +617,6 @@ where /// which may be a "wildcard address" like `INADDR_ANY` or `IN6ADDR_ANY` /// when listening on all interfaces for IPv4 respectively IPv6 connections. listen_addr: SocketAddr, - /// Addresses it is listening on. - addresses: SmallVec<[Multiaddr; 4]>, /// The async listening socket for incoming connections. listener: T::Listener, /// The IP addresses of network interfaces on which the listening socket @@ -676,7 +676,6 @@ where listener, listener_id, listen_addr, - addresses: Default::default(), in_addr, pause: None, sleep_on_error: Duration::from_millis(100), diff --git a/transports/uds/src/lib.rs b/transports/uds/src/lib.rs index d8b988f01df..87e840059e3 100644 --- a/transports/uds/src/lib.rs +++ b/transports/uds/src/lib.rs @@ -51,17 +51,20 @@ use std::pin::Pin; use std::task::{Context, Poll}; use std::{io, path::PathBuf}; -pub type Listener = - BoxStream<'static, Result, TransportEvent>>; +pub type Listener = BoxStream< + 'static, + Result< + TransportEvent<::ListenerUpgrade, ::Error>, + Result<(), ::Error>, + >, +>; macro_rules! codegen { ($feature_name:expr, $uds_config:ident, $build_listener:expr, $unix_stream:ty, $($mut_or_not:tt)*) => { /// Represents the configuration for a Unix domain sockets transport capability for libp2p. #[cfg_attr(docsrs, doc(cfg(feature = $feature_name)))] pub struct $uds_config { - listeners: VecDeque< - Listener<::ListenerUpgrade, ::Error>, - >, + listeners: VecDeque<(ListenerId, Listener)>, } impl $uds_config { @@ -91,58 +94,68 @@ macro_rules! codegen { addr: Multiaddr, ) -> Result<(), TransportError> { if let Ok(path) = multiaddr_to_path(&addr) { - let addr_clone = addr.clone(); - let listener = async move { - $build_listener(path) - .await - .map_err(|e| TransportEvent::Closed { - listener_id: id, - addresses: vec![addr_clone], - reason: Err(e), + let listener = $build_listener(path) + .map_err(Err) + .map_ok(move |listener| { + stream::once({ + let addr = addr.clone(); + async move { + debug!("Now listening on {}", addr); + Ok(TransportEvent::NewAddress { + listener_id: id, + listen_addr: addr, + }) + } }) - } - .map_ok(move |listener| { - stream::once({ - let addr = addr.clone(); - async move { - debug!("Now listening on {}", addr); - Ok(TransportEvent::NewAddress { - listener_id: id, - listen_addr: addr, - }) - } - }) - .chain(stream::unfold(listener, move |listener| { - let addr = addr.clone(); - async move { - let event = match listener.accept().await { - Ok((stream, _)) => { - debug!("incoming connection on {}", addr); - TransportEvent::Incoming { - upgrade: future::ok(stream), - local_addr: addr.clone(), - send_back_addr: addr.clone(), - listener_id: id, - } + .chain(stream::unfold( + listener, + move |listener| { + let addr = addr.clone(); + async move { + let event = match listener.accept().await { + Ok((stream, _)) => { + debug!("incoming connection on {}", addr); + TransportEvent::Incoming { + upgrade: future::ok(stream), + local_addr: addr.clone(), + send_back_addr: addr.clone(), + listener_id: id, + } + } + Err(error) => TransportEvent::Error { + listener_id: id, + error, + }, + }; + Some((Ok(event), listener)) } - Err(error) => TransportEvent::Error { - listener_id: id, - error, - }, - }; - Some((Ok(event), listener)) - } - })) - }) - .try_flatten_stream() - .boxed(); - self.listeners.push_back(listener); + }, + )) + }) + .try_flatten_stream() + .boxed(); + self.listeners.push_back((id, listener)); Ok(()) } else { Err(TransportError::MultiaddrNotSupported(addr)) } } + fn remove_listener(&mut self, id: ListenerId) -> bool { + if let Some(index) = self + .listeners + .iter() + .position(|(listener_id, _)| listener_id == &id) + { + let listener_stream = self.listeners.get_mut(index).unwrap(); + let report_closed_stream = stream::once(async { Err(Ok(())) }).boxed(); + *listener_stream = (id, report_closed_stream); + true + } else { + false + } + } + fn dial(&mut self, addr: Multiaddr) -> Result> { // TODO: Should we dial at all? if let Ok(path) = multiaddr_to_path(&addr) { @@ -173,14 +186,19 @@ macro_rules! codegen { cx: &mut Context<'_>, ) -> Poll> { let mut remaining = self.listeners.len(); - while let Some(mut listener) = self.listeners.pop_back() { + while let Some((id, mut listener)) = self.listeners.pop_back() { let event = match Stream::poll_next(Pin::new(&mut listener), cx) { Poll::Pending => None, Poll::Ready(None) => panic!("Alive listeners always have a sender."), Poll::Ready(Some(Ok(event))) => Some(event), - Poll::Ready(Some(Err(event))) => return Poll::Ready(event), + Poll::Ready(Some(Err(reason))) => { + return Poll::Ready(TransportEvent::ListenerClosed { + listener_id: id, + reason, + }) + } }; - self.listeners.push_front(listener); + self.listeners.push_front((id, listener)); if let Some(event) = event { return Poll::Ready(event); } else { diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index 4ed726a7a8e..995814f8549 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -147,6 +147,10 @@ where .map_err(|e| e.map(Error::Transport)) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.transport.lock().remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { self.do_dial(addr, Endpoint::Dialer) } @@ -207,22 +211,15 @@ where listener_id, error: Error::Transport(error), }, - TransportEvent::Closed { + TransportEvent::ListenerClosed { listener_id, - mut addresses, reason, } => { - let proto = self - .listener_protos + self.listener_protos .remove(&listener_id) .expect("Protocol was inserted in Transport::listen_on."); - addresses = addresses - .into_iter() - .map(|a| a.with(proto.clone())) - .collect(); - TransportEvent::Closed { + TransportEvent::ListenerClosed { listener_id, - addresses, reason: reason.map_err(Error::Transport), } } diff --git a/transports/websocket/src/lib.rs b/transports/websocket/src/lib.rs index 41e14719934..b7b50b66b7f 100644 --- a/transports/websocket/src/lib.rs +++ b/transports/websocket/src/lib.rs @@ -131,6 +131,10 @@ where self.transport.listen_on(id, addr) } + fn remove_listener(&mut self, id: ListenerId) -> bool { + self.transport.remove_listener(id) + } + fn dial(&mut self, addr: Multiaddr) -> Result> { self.transport.dial(addr) } From 2226092f232cc51fca2816e72180dc7ed7c06ff0 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 29 May 2022 21:56:15 +0200 Subject: [PATCH 26/47] core/transport: create ListenerId within Transport Return a ListenerId in Transport::listen_on instead of getting it injected from the outside. Namespace ListenerIds with the Transport's TypeId to avoid clashing IDs when transport generate their ListenerIds independenlty. --- Cargo.toml | 24 ++++---- core/src/either.rs | 10 +--- core/src/transport.rs | 76 ++++++++++++++++++++----- core/src/transport/and_then.rs | 8 +-- core/src/transport/boxed.rs | 22 ++----- core/src/transport/choice.rs | 10 +--- core/src/transport/dummy.rs | 6 +- core/src/transport/map.rs | 8 +-- core/src/transport/map_err.rs | 10 +--- core/src/transport/memory.rs | 65 +++++++++------------ core/src/transport/optional.rs | 8 +-- core/src/transport/timeout.rs | 8 +-- core/src/transport/upgrade.rs | 16 ++---- core/tests/transport_upgrade.rs | 6 +- misc/metrics/Cargo.toml | 8 +-- muxers/mplex/benches/split_send_size.rs | 4 +- muxers/mplex/tests/async_write.rs | 5 +- muxers/mplex/tests/two_peers.rs | 15 +---- protocols/identify/src/protocol.rs | 5 +- protocols/kad/src/protocol.rs | 2 +- protocols/ping/src/protocol.rs | 4 +- src/bandwidth.rs | 8 +-- swarm/src/lib.rs | 11 +--- transports/deflate/tests/test.rs | 10 +--- transports/dns/src/lib.rs | 17 +++--- transports/noise/tests/smoke.rs | 4 +- transports/plaintext/tests/smoke.rs | 11 +--- transports/tcp/src/lib.rs | 37 ++++++------ transports/uds/src/lib.rs | 13 +++-- transports/websocket/src/framed.rs | 21 ++++--- transports/websocket/src/lib.rs | 16 ++---- 31 files changed, 200 insertions(+), 268 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9f3fe5f495e..a1671c99199 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,18 +25,18 @@ default = [ "ping", "plaintext", "pnet", - "relay", + # "relay", "request-response", "rendezvous", "secp256k1", "tcp-async-io", "uds", - "wasm-ext", + # "wasm-ext", "websocket", "yamux", ] autonat = ["libp2p-autonat"] -dcutr = ["libp2p-dcutr", "libp2p-metrics/dcutr"] +# dcutr = ["libp2p-dcutr", "libp2p-metrics/dcutr"] deflate = ["libp2p-deflate"] dns-async-std = ["libp2p-dns", "libp2p-dns/async-std"] dns-tokio = ["libp2p-dns", "libp2p-dns/tokio"] @@ -51,15 +51,15 @@ noise = ["libp2p-noise"] ping = ["libp2p-ping", "libp2p-metrics/ping"] plaintext = ["libp2p-plaintext"] pnet = ["libp2p-pnet"] -relay = ["libp2p-relay", "libp2p-metrics/relay"] +# relay = ["libp2p-relay", "libp2p-metrics/relay"] request-response = ["libp2p-request-response"] rendezvous = ["libp2p-rendezvous"] tcp-async-io = ["libp2p-tcp", "libp2p-tcp/async-io"] tcp-tokio = ["libp2p-tcp", "libp2p-tcp/tokio"] uds = ["libp2p-uds"] wasm-bindgen = ["futures-timer/wasm-bindgen", "instant/wasm-bindgen", "getrandom/js", "rand/wasm-bindgen"] -wasm-ext = ["libp2p-wasm-ext"] -wasm-ext-websocket = ["wasm-ext", "libp2p-wasm-ext/websocket"] +# wasm-ext = ["libp2p-wasm-ext"] +# wasm-ext-websocket = ["wasm-ext", "libp2p-wasm-ext/websocket"] websocket = ["libp2p-websocket"] yamux = ["libp2p-yamux"] secp256k1 = ["libp2p-core/secp256k1"] @@ -78,7 +78,7 @@ lazy_static = "1.2" libp2p-autonat = { version = "0.4.0", path = "protocols/autonat", optional = true } libp2p-core = { version = "0.33.0", path = "core", default-features = false } -libp2p-dcutr = { version = "0.3.0", path = "protocols/dcutr", optional = true } +# libp2p-dcutr = { version = "0.3.0", path = "protocols/dcutr", optional = true } libp2p-floodsub = { version = "0.36.0", path = "protocols/floodsub", optional = true } libp2p-identify = { version = "0.36.0", path = "protocols/identify", optional = true } libp2p-kad = { version = "0.37.0", path = "protocols/kad", optional = true } @@ -88,13 +88,13 @@ libp2p-noise = { version = "0.36.0", path = "transports/noise", optional = true libp2p-ping = { version = "0.36.0", path = "protocols/ping", optional = true } libp2p-plaintext = { version = "0.33.0", path = "transports/plaintext", optional = true } libp2p-pnet = { version = "0.22.0", path = "transports/pnet", optional = true } -libp2p-relay = { version = "0.9.0", path = "protocols/relay", optional = true } +# libp2p-relay = { version = "0.9.0", path = "protocols/relay", optional = true } libp2p-rendezvous = { version = "0.6.0", path = "protocols/rendezvous", optional = true } libp2p-request-response = { version = "0.18.0", path = "protocols/request-response", optional = true } libp2p-swarm = { version = "0.36.0", path = "swarm" } libp2p-swarm-derive = { version = "0.27.0", path = "swarm-derive" } libp2p-uds = { version = "0.32.0", path = "transports/uds", optional = true } -libp2p-wasm-ext = { version = "0.33.0", path = "transports/wasm-ext", default-features = false, optional = true } +# libp2p-wasm-ext = { version = "0.33.0", path = "transports/wasm-ext", default-features = false, optional = true } libp2p-yamux = { version = "0.37.0", path = "muxers/yamux", optional = true } multiaddr = { version = "0.14.0" } parking_lot = "0.12.0" @@ -129,7 +129,7 @@ members = [ "misc/prost-codec", "muxers/mplex", "muxers/yamux", - "protocols/dcutr", + # "protocols/dcutr", "protocols/autonat", "protocols/floodsub", "protocols/gossipsub", @@ -138,7 +138,7 @@ members = [ "protocols/kad", "protocols/mdns", "protocols/ping", - "protocols/relay", + # "protocols/relay", "protocols/request-response", "swarm", "swarm-derive", @@ -150,7 +150,7 @@ members = [ "transports/tcp", "transports/uds", "transports/websocket", - "transports/wasm-ext" + # "transports/wasm-ext" ] [[example]] diff --git a/core/src/either.rs b/core/src/either.rs index dbb73b470d6..ac3975b019f 100644 --- a/core/src/either.rs +++ b/core/src/either.rs @@ -486,18 +486,14 @@ where } } - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { use TransportError::*; match self { - EitherTransport::Left(a) => a.listen_on(id, addr).map_err(|e| match e { + EitherTransport::Left(a) => a.listen_on(addr).map_err(|e| match e { MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr), Other(err) => Other(EitherError::A(err)), }), - EitherTransport::Right(b) => b.listen_on(id, addr).map_err(|e| match e { + EitherTransport::Right(b) => b.listen_on(addr).map_err(|e| match e { MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr), Other(err) => Other(EitherError::B(err)), }), diff --git a/core/src/transport.rs b/core/src/transport.rs index dfbf4fce6bd..cc5dccc6e60 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -28,6 +28,7 @@ use futures::prelude::*; use multiaddr::Multiaddr; use std::{ + any::{Any, TypeId}, error::Error, fmt, pin::Pin, @@ -114,11 +115,7 @@ pub trait Transport { /// /// Returning an error from the stream is considered fatal. The listener can also report /// non-fatal errors by producing a [`TransportEvent::Error`]. - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> + fn listen_on(&mut self, addr: Multiaddr) -> Result> where Self: Sized; @@ -234,20 +231,30 @@ pub trait Transport { /// The ID of a single listener. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ListenerId(u64); +pub struct ListenerId { + id: u64, + transport_id: TypeId, +} impl ListenerId { - /// Creates a `ListenerId` from a non-negative integer. - pub fn new(id: u64) -> Self { - Self(id) + /// Creates a new `ListenerId`. + pub fn new(id: u64) -> Self { + Self { + id, + transport_id: TypeId::of::(), + } } -} -impl std::ops::Add for ListenerId { - type Output = Self; + /// Returns the next id + pub fn next_id(&mut self) -> Self { + let current = *self; + self.id += 1; + current + } - fn add(self, other: u64) -> Self { - Self(self.0 + other) + pub fn map_type(mut self) -> Self { + self.transport_id = TypeId::of::(); + self } } @@ -385,6 +392,47 @@ impl TransportEvent { } } + pub fn map_transport_type(self) -> Self { + match self { + TransportEvent::Incoming { + listener_id, + upgrade, + local_addr, + send_back_addr, + } => TransportEvent::Incoming { + listener_id: listener_id.map_type::(), + upgrade, + local_addr, + send_back_addr, + }, + TransportEvent::NewAddress { + listen_addr, + listener_id, + } => TransportEvent::NewAddress { + listen_addr, + listener_id: listener_id.map_type::(), + }, + TransportEvent::AddressExpired { + listen_addr, + listener_id, + } => TransportEvent::AddressExpired { + listen_addr, + listener_id: listener_id.map_type::(), + }, + TransportEvent::Error { listener_id, error } => TransportEvent::Error { + listener_id: listener_id.map_type::(), + error, + }, + TransportEvent::ListenerClosed { + listener_id, + reason, + } => TransportEvent::ListenerClosed { + listener_id: listener_id.map_type::(), + reason, + }, + } + } + /// Returns `true` if this is an `Upgrade` listener event. pub fn is_upgrade(&self) -> bool { matches!(self, TransportEvent::Incoming { .. }) diff --git a/core/src/transport/and_then.rs b/core/src/transport/and_then.rs index 00be2dddc09..b4f9c92186f 100644 --- a/core/src/transport/and_then.rs +++ b/core/src/transport/and_then.rs @@ -54,13 +54,9 @@ where type ListenerUpgrade = AndThenFuture; type Dial = AndThenFuture; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { self.transport - .listen_on(id, addr) + .listen_on(addr) .map_err(|err| err.map(EitherError::A)) } diff --git a/core/src/transport/boxed.rs b/core/src/transport/boxed.rs index 523e5472653..b2560c4a662 100644 --- a/core/src/transport/boxed.rs +++ b/core/src/transport/boxed.rs @@ -52,11 +52,7 @@ type Dial = Pin> + Send>>; type ListenerUpgrade = Pin> + Send>>; trait Abstract { - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError>; + fn listen_on(&mut self, addr: Multiaddr) -> Result>; fn remove_listener(&mut self, id: ListenerId) -> bool; fn dial(&mut self, addr: Multiaddr) -> Result, TransportError>; fn dial_as_listener(&mut self, addr: Multiaddr) -> Result, TransportError>; @@ -74,12 +70,8 @@ where T::Dial: Send + 'static, T::ListenerUpgrade: Send + 'static, { - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { - Transport::listen_on(self, id, addr).map_err(|e| e.map(box_err)) + fn listen_on(&mut self, addr: Multiaddr) -> Result> { + Transport::listen_on(self, addr).map_err(|e| e.map(box_err)) } fn remove_listener(&mut self, id: ListenerId) -> bool { @@ -131,12 +123,8 @@ impl Transport for Boxed { type ListenerUpgrade = ListenerUpgrade; type Dial = Dial; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { - self.inner.listen_on(id, addr) + fn listen_on(&mut self, addr: Multiaddr) -> Result> { + self.inner.listen_on(addr) } fn remove_listener(&mut self, id: ListenerId) -> bool { diff --git a/core/src/transport/choice.rs b/core/src/transport/choice.rs index 42e41dc44b9..17528c1d4a8 100644 --- a/core/src/transport/choice.rs +++ b/core/src/transport/choice.rs @@ -44,17 +44,13 @@ where type ListenerUpgrade = EitherFuture; type Dial = EitherFuture; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { - let addr = match self.0.listen_on(id, addr) { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { + let addr = match self.0.listen_on(addr) { Err(TransportError::MultiaddrNotSupported(addr)) => addr, res => return res.map_err(|err| err.map(EitherError::A)), }; - let addr = match self.1.listen_on(id, addr) { + let addr = match self.1.listen_on(addr) { Err(TransportError::MultiaddrNotSupported(addr)) => addr, res => return res.map_err(|err| err.map(EitherError::B)), }; diff --git a/core/src/transport/dummy.rs b/core/src/transport/dummy.rs index 951d1039328..a7d1cab9089 100644 --- a/core/src/transport/dummy.rs +++ b/core/src/transport/dummy.rs @@ -59,11 +59,7 @@ impl Transport for DummyTransport { type ListenerUpgrade = futures::future::Pending>; type Dial = futures::future::Pending>; - fn listen_on( - &mut self, - _id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { Err(TransportError::MultiaddrNotSupported(addr)) } diff --git a/core/src/transport/map.rs b/core/src/transport/map.rs index 553f3e6338d..50f7b826d36 100644 --- a/core/src/transport/map.rs +++ b/core/src/transport/map.rs @@ -61,12 +61,8 @@ where type ListenerUpgrade = MapFuture; type Dial = MapFuture; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { - self.transport.listen_on(id, addr) + fn listen_on(&mut self, addr: Multiaddr) -> Result> { + self.transport.listen_on(addr) } fn remove_listener(&mut self, id: ListenerId) -> bool { diff --git a/core/src/transport/map_err.rs b/core/src/transport/map_err.rs index 56e1ebf2929..99f2912447f 100644 --- a/core/src/transport/map_err.rs +++ b/core/src/transport/map_err.rs @@ -50,15 +50,9 @@ where type ListenerUpgrade = MapErrListenerUpgrade; type Dial = MapErrDial; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { let map = self.map.clone(); - self.transport - .listen_on(id, addr) - .map_err(|err| err.map(map)) + self.transport.listen_on(addr).map_err(|err| err.map(map)) } fn remove_listener(&mut self, id: ListenerId) -> bool { diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index a0b9c6bfe51..2056002f6dc 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -93,19 +93,26 @@ impl Hub { } /// Transport that supports `/memory/N` multiaddresses. -#[derive(Default)] pub struct MemoryTransport { listeners: VecDeque>>, + next_listener_id: ListenerId, } -impl MemoryTransport { - pub fn new() -> Self { +impl Default for MemoryTransport { + fn default() -> Self { MemoryTransport { listeners: VecDeque::new(), + next_listener_id: ListenerId::new::(1), } } } +impl MemoryTransport { + pub fn new() -> Self { + Self::default() + } +} + /// Connection to a `MemoryTransport` currently being opened. pub struct DialFuture { /// Ephemeral source port. @@ -183,11 +190,7 @@ impl Transport for MemoryTransport { type ListenerUpgrade = Ready>; type Dial = DialFuture; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { let port = if let Ok(port) = parse_memory_addr(&addr) { port } else { @@ -199,6 +202,7 @@ impl Transport for MemoryTransport { None => return Err(TransportError::Other(MemoryTransportError::Unreachable)), }; + let id = self.next_listener_id.next_id(); let listener = Listener { id, port, @@ -208,7 +212,7 @@ impl Transport for MemoryTransport { }; self.listeners.push_back(Box::pin(listener)); - Ok(()) + Ok(id) } fn remove_listener(&mut self, id: ListenerId) -> bool { @@ -460,34 +464,25 @@ mod tests { #[test] fn listening_twice() { let mut transport = MemoryTransport::default(); - let listener_id_1 = ListenerId::new(1); let addr_1: Multiaddr = "/memory/1639174018481".parse().unwrap(); let addr_2: Multiaddr = "/memory/8459375923478".parse().unwrap(); - assert!(transport.listen_on(listener_id_1, addr_1.clone()).is_ok()); + let listener_id_1 = transport.listen_on(addr_1.clone()).unwrap(); assert!(transport.remove_listener(listener_id_1)); - let listener_id_2 = ListenerId::new(2); - assert!(transport.listen_on(listener_id_2, addr_1.clone()).is_ok()); - let listener_id_3 = ListenerId::new(3); - assert!(transport.listen_on(listener_id_3, addr_2.clone()).is_ok()); + let listener_id_2 = transport.listen_on(addr_1.clone()).unwrap(); + let listener_id_3 = transport.listen_on(addr_2.clone()).unwrap(); - assert!(transport - .listen_on(ListenerId::new(4), addr_1.clone()) - .is_err()); - assert!(transport - .listen_on(ListenerId::new(4), addr_2.clone()) - .is_err()); + assert!(transport.listen_on(addr_1.clone()).is_err()); + assert!(transport.listen_on(addr_2.clone()).is_err()); assert!(transport.remove_listener(listener_id_2)); - assert!(transport.listen_on(ListenerId::new(4), addr_1).is_ok()); - assert!(transport - .listen_on(ListenerId::new(4), addr_2.clone()) - .is_err()); + assert!(transport.listen_on(addr_1).is_ok()); + assert!(transport.listen_on(addr_2.clone()).is_err()); assert!(transport.remove_listener(listener_id_3)); - assert!(transport.listen_on(ListenerId::new(4), addr_2).is_ok()); + assert!(transport.listen_on(addr_2).is_ok()); } #[test] @@ -497,10 +492,7 @@ mod tests { .dial("/memory/810172461024613".parse().unwrap()) .is_err()); let _listener = transport - .listen_on( - ListenerId::new(1), - "/memory/810172461024613".parse().unwrap(), - ) + .listen_on("/memory/810172461024613".parse().unwrap()) .unwrap(); assert!(transport .dial("/memory/810172461024613".parse().unwrap()) @@ -514,8 +506,7 @@ mod tests { let mut transport = MemoryTransport::default().boxed(); futures::executor::block_on(async { - let listener_id = ListenerId::new(1); - transport.listen_on(listener_id, addr.clone()).unwrap(); + let listener_id = transport.listen_on(addr.clone()).unwrap(); let reported_addr = transport .select_next_some() .await @@ -550,7 +541,7 @@ mod tests { let mut t1 = MemoryTransport::default().boxed(); let listener = async move { - t1.listen_on(ListenerId::new(1), t1_addr.clone()).unwrap(); + t1.listen_on(t1_addr.clone()).unwrap(); let upgrade = loop { let event = t1.select_next_some().await; if let Some(upgrade) = event.into_upgrade() { @@ -588,9 +579,7 @@ mod tests { let mut listener_transport = MemoryTransport::default().boxed(); let listener = async move { - listener_transport - .listen_on(ListenerId::new(1), listener_addr.clone()) - .unwrap(); + listener_transport.listen_on(listener_addr.clone()).unwrap(); loop { if let TransportEvent::Incoming { send_back_addr, .. } = listener_transport.select_next_some().await @@ -627,9 +616,7 @@ mod tests { let mut listener_transport = MemoryTransport::default().boxed(); let listener = async move { - listener_transport - .listen_on(ListenerId::new(1), listener_addr.clone()) - .unwrap(); + listener_transport.listen_on(listener_addr.clone()).unwrap(); loop { if let TransportEvent::Incoming { send_back_addr, .. } = listener_transport.select_next_some().await diff --git a/core/src/transport/optional.rs b/core/src/transport/optional.rs index 839f55a4000..2d93077659c 100644 --- a/core/src/transport/optional.rs +++ b/core/src/transport/optional.rs @@ -60,13 +60,9 @@ where type ListenerUpgrade = T::ListenerUpgrade; type Dial = T::Dial; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { if let Some(inner) = self.0.as_mut() { - inner.listen_on(id, addr) + inner.listen_on(addr) } else { Err(TransportError::MultiaddrNotSupported(addr)) } diff --git a/core/src/transport/timeout.rs b/core/src/transport/timeout.rs index 144f369c140..5c3867b3c01 100644 --- a/core/src/transport/timeout.rs +++ b/core/src/transport/timeout.rs @@ -85,13 +85,9 @@ where type ListenerUpgrade = Timeout; type Dial = Timeout; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { self.inner - .listen_on(id, addr) + .listen_on(addr) .map_err(|err| err.map(TransportTimeoutError::Other)) } diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index 9ca62dc8873..e2c1a9bc7e6 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -349,12 +349,8 @@ where self.0.dial_as_listener(addr) } - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { - self.0.listen_on(id, addr) + fn listen_on(&mut self, addr: Multiaddr) -> Result> { + self.0.listen_on(addr) } fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option { @@ -432,13 +428,9 @@ where }) } - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { self.inner - .listen_on(id, addr) + .listen_on(addr) .map_err(|err| err.map(TransportUpgradeError::Transport)) } diff --git a/core/tests/transport_upgrade.rs b/core/tests/transport_upgrade.rs index e59005cdf19..f52cf2cb3d6 100644 --- a/core/tests/transport_upgrade.rs +++ b/core/tests/transport_upgrade.rs @@ -22,7 +22,7 @@ mod util; use futures::prelude::*; use libp2p_core::identity; -use libp2p_core::transport::{ListenerId, MemoryTransport, Transport}; +use libp2p_core::transport::{MemoryTransport, Transport}; use libp2p_core::upgrade::{self, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; use libp2p_mplex::MplexConfig; use libp2p_noise as noise; @@ -120,9 +120,7 @@ fn upgrade_pipeline() { let listen_addr1 = Multiaddr::from(Protocol::Memory(random::())); let listen_addr2 = listen_addr1.clone(); - listener_transport - .listen_on(ListenerId::new(1), listen_addr1) - .unwrap(); + listener_transport.listen_on(listen_addr1).unwrap(); let server = async move { loop { diff --git a/misc/metrics/Cargo.toml b/misc/metrics/Cargo.toml index f539ce3105d..c402b1e6eef 100644 --- a/misc/metrics/Cargo.toml +++ b/misc/metrics/Cargo.toml @@ -15,16 +15,16 @@ gossipsub = ["libp2p-gossipsub"] identify = ["libp2p-identify"] kad = ["libp2p-kad"] ping = ["libp2p-ping"] -relay = ["libp2p-relay"] -dcutr = ["libp2p-dcutr"] +# relay = ["libp2p-relay"] +# dcutr = ["libp2p-dcutr"] [dependencies] libp2p-core = { version = "0.33.0", path = "../../core", default-features = false } -libp2p-dcutr = { version = "0.3.0", path = "../../protocols/dcutr", optional = true } +# libp2p-dcutr = { version = "0.3.0", path = "../../protocols/dcutr", optional = true } libp2p-identify = { version = "0.36.0", path = "../../protocols/identify", optional = true } libp2p-kad = { version = "0.37.0", path = "../../protocols/kad", optional = true } libp2p-ping = { version = "0.36.0", path = "../../protocols/ping", optional = true } -libp2p-relay = { version = "0.9.0", path = "../../protocols/relay", optional = true } +# libp2p-relay = { version = "0.9.0", path = "../../protocols/relay", optional = true } libp2p-swarm = { version = "0.36.0", path = "../../swarm" } prometheus-client = "0.16.0" diff --git a/muxers/mplex/benches/split_send_size.rs b/muxers/mplex/benches/split_send_size.rs index 465ac18bec5..887f171989e 100644 --- a/muxers/mplex/benches/split_send_size.rs +++ b/muxers/mplex/benches/split_send_size.rs @@ -100,9 +100,7 @@ fn run( payload: &Vec, listen_addr: &Multiaddr, ) { - receiver_trans - .listen_on(transport::ListenerId::new(1), listen_addr.clone()) - .unwrap(); + receiver_trans.listen_on(listen_addr.clone()).unwrap(); let (addr_sender, addr_receiver) = oneshot::channel(); let mut addr_sender = Some(addr_sender); let payload_len = payload.len(); diff --git a/muxers/mplex/tests/async_write.rs b/muxers/mplex/tests/async_write.rs index c0adf177b81..59ef10feef4 100644 --- a/muxers/mplex/tests/async_write.rs +++ b/muxers/mplex/tests/async_write.rs @@ -37,10 +37,7 @@ fn async_write() { .boxed(); transport - .listen_on( - libp2p_core::transport::ListenerId::new(1), - "/ip4/127.0.0.1/tcp/0".parse().unwrap(), - ) + .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); let addr = transport diff --git a/muxers/mplex/tests/two_peers.rs b/muxers/mplex/tests/two_peers.rs index 851467f0dbc..72051f0632c 100644 --- a/muxers/mplex/tests/two_peers.rs +++ b/muxers/mplex/tests/two_peers.rs @@ -37,10 +37,7 @@ fn client_to_server_outbound() { .boxed(); transport - .listen_on( - libp2p_core::transport::ListenerId::new(1), - "/ip4/127.0.0.1/tcp/0".parse().unwrap(), - ) + .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); let addr = transport @@ -108,10 +105,7 @@ fn client_to_server_inbound() { .boxed(); transport - .listen_on( - libp2p_core::transport::ListenerId::new(1), - "/ip4/127.0.0.1/tcp/0".parse().unwrap(), - ) + .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); let addr = transport @@ -179,10 +173,7 @@ fn protocol_not_match() { .boxed(); transport - .listen_on( - libp2p_core::transport::ListenerId::new(1), - "/ip4/127.0.0.1/tcp/0".parse().unwrap(), - ) + .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); let addr = transport diff --git a/protocols/identify/src/protocol.rs b/protocols/identify/src/protocol.rs index f54163113b3..148cd64fc80 100644 --- a/protocols/identify/src/protocol.rs +++ b/protocols/identify/src/protocol.rs @@ -305,10 +305,7 @@ mod tests { let mut transport = TcpTransport::default().boxed(); transport - .listen_on( - libp2p_core::transport::ListenerId::new(1), - "/ip4/127.0.0.1/tcp/0".parse().unwrap(), - ) + .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); let addr = transport diff --git a/protocols/kad/src/protocol.rs b/protocols/kad/src/protocol.rs index d556606e0e0..656917b54f6 100644 --- a/protocols/kad/src/protocol.rs +++ b/protocols/kad/src/protocol.rs @@ -661,7 +661,7 @@ mod tests { let transport = TcpTransport::default().with_upgrade(KademliaProtocolConfig); let (listener, addr) = transport - .listen_on(libp2p_core::transport::ListenerId::new(1), "/ip4/127.0.0.1/tcp/0".parse().unwrap()) + .listen_on( "/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); tx.send(addr).unwrap(); diff --git a/protocols/ping/src/protocol.rs b/protocols/ping/src/protocol.rs index d89b9932f10..f452936de9d 100644 --- a/protocols/ping/src/protocol.rs +++ b/protocols/ping/src/protocol.rs @@ -127,9 +127,7 @@ mod tests { fn ping_pong() { let mem_addr = multiaddr![Memory(thread_rng().gen::())]; let mut transport = MemoryTransport::new().boxed(); - transport - .listen_on(libp2p_core::transport::ListenerId::new(0), mem_addr) - .unwrap(); + transport.listen_on(mem_addr).unwrap(); let listener_addr = transport .select_next_some() diff --git a/src/bandwidth.rs b/src/bandwidth.rs index 3d33e910304..a58eec95ddb 100644 --- a/src/bandwidth.rs +++ b/src/bandwidth.rs @@ -96,12 +96,8 @@ where } } - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { - self.inner.listen_on(id, addr) + fn listen_on(&mut self, addr: Multiaddr) -> Result> { + self.inner.listen_on(addr) } fn remove_listener(&mut self, id: ListenerId) -> bool { diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index dcef95863cc..82adaf40e36 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -260,8 +260,6 @@ where /// Listeners for incoming connections. transport: transport::Boxed<(PeerId, StreamMuxerBox)>, - next_listener_id: ListenerId, - /// The nodes currently active. pool: Pool, transport::Boxed<(PeerId, StreamMuxerBox)>>, @@ -328,9 +326,7 @@ where /// Listeners report their new listening addresses as [`SwarmEvent::NewListenAddr`]. /// Depending on the underlying transport, one listener may have multiple listening addresses. pub fn listen_on(&mut self, addr: Multiaddr) -> Result> { - let id = self.next_listener_id; - self.next_listener_id = self.next_listener_id + 1; - self.transport.listen_on(id, addr)?; + let id = self.transport.listen_on(addr)?; self.behaviour.inject_new_listener(id); Ok(id) } @@ -1400,7 +1396,6 @@ where Swarm { local_peer_id: self.local_peer_id, - next_listener_id: ListenerId::new(1), transport: self.transport, pool: Pool::new(self.local_peer_id, pool_config, self.connection_limits), behaviour: self.behaviour, @@ -2070,9 +2065,7 @@ mod tests { let mut transports = Vec::new(); for _ in 0..num_listen_addrs { let mut transport = transport::MemoryTransport::default().boxed(); - transport - .listen_on(ListenerId::new(1), "/memory/0".parse().unwrap()) - .unwrap(); + transport.listen_on("/memory/0".parse().unwrap()).unwrap(); match transport.select_next_some().await { TransportEvent::NewAddress { listen_addr, .. } => { diff --git a/transports/deflate/tests/test.rs b/transports/deflate/tests/test.rs index 646f8df59a3..e718fc0075d 100644 --- a/transports/deflate/tests/test.rs +++ b/transports/deflate/tests/test.rs @@ -19,10 +19,7 @@ // DEALINGS IN THE SOFTWARE. use futures::{future, prelude::*}; -use libp2p_core::{ - transport::{ListenerId, Transport}, - upgrade, -}; +use libp2p_core::{transport::Transport, upgrade}; use libp2p_deflate::DeflateConfig; use libp2p_tcp::TcpTransport; use quickcheck::{QuickCheck, RngCore, TestResult}; @@ -61,10 +58,7 @@ async fn run(message1: Vec) { }; let mut listener_trans = new_transport(); listener_trans - .listen_on( - ListenerId::new(1), - "/ip4/0.0.0.0/tcp/0".parse().expect("multiaddr"), - ) + .listen_on("/ip4/0.0.0.0/tcp/0".parse().expect("multiaddr")) .expect("listener"); let listen_addr = listener_trans diff --git a/transports/dns/src/lib.rs b/transports/dns/src/lib.rs index 827da12ab13..ba14c772229 100644 --- a/transports/dns/src/lib.rs +++ b/transports/dns/src/lib.rs @@ -197,14 +197,11 @@ where BoxFuture<'static, Result>, >; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { self.inner .lock() - .listen_on(id, addr) + .listen_on(addr) + .map(ListenerId::map_type::) .map_err(|e| e.map(DnsErr::Transport)) } @@ -234,6 +231,7 @@ where let mut inner = self.inner.lock(); Transport::poll(Pin::new(inner.deref_mut()), cx).map(|event| { event + .map_transport_type::() .map_upgrade(|upgr| upgr.map_err::<_, fn(_) -> _>(DnsErr::Transport)) .map_err(DnsErr::Transport) }) @@ -601,12 +599,15 @@ mod tests { fn listen_on( &mut self, - _: ListenerId, _: Multiaddr, - ) -> Result<(), TransportError> { + ) -> Result> { unreachable!() } + fn remove_listener(&mut self, _: ListenerId) -> bool { + false + } + fn dial(&mut self, addr: Multiaddr) -> Result> { // Check that all DNS components have been resolved, i.e. replaced. assert!(!addr.iter().any(|p| match p { diff --git a/transports/noise/tests/smoke.rs b/transports/noise/tests/smoke.rs index 7e6fa1a7508..0945105d211 100644 --- a/transports/noise/tests/smoke.rs +++ b/transports/noise/tests/smoke.rs @@ -24,7 +24,7 @@ use futures::{ prelude::*, }; use libp2p_core::identity; -use libp2p_core::transport::{self, ListenerId, Transport}; +use libp2p_core::transport::{self, Transport}; use libp2p_core::upgrade::{self, apply_inbound, apply_outbound, Negotiated}; use libp2p_noise::{ Keypair, NoiseConfig, NoiseError, NoiseOutput, RemoteIdentity, X25519Spec, X25519, @@ -249,7 +249,7 @@ fn run( { futures::executor::block_on(async { server - .listen_on(ListenerId::new(1), "/ip4/127.0.0.1/tcp/0".parse().unwrap()) + .listen_on("/ip4/127.0.0.1/tcp/0".parse().unwrap()) .unwrap(); let server_address = server diff --git a/transports/plaintext/tests/smoke.rs b/transports/plaintext/tests/smoke.rs index 5f599d05269..0f14f4f2ae6 100644 --- a/transports/plaintext/tests/smoke.rs +++ b/transports/plaintext/tests/smoke.rs @@ -22,12 +22,7 @@ use futures::{ io::{AsyncReadExt, AsyncWriteExt}, StreamExt, }; -use libp2p_core::{ - identity, - multiaddr::Multiaddr, - transport::{ListenerId, Transport}, - upgrade, -}; +use libp2p_core::{identity, multiaddr::Multiaddr, transport::Transport, upgrade}; use libp2p_plaintext::PlainText2Config; use log::debug; use quickcheck::QuickCheck; @@ -78,9 +73,7 @@ fn variable_msg_length() { .parse() .unwrap(); - server - .listen_on(ListenerId::new(1), server_address.clone()) - .unwrap(); + server.listen_on(server_address.clone()).unwrap(); // Ignore server listen address event. let _ = server diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 77622b01884..d906d328694 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -242,7 +242,7 @@ impl GenTcpConfig { /// let listen_addr2: Multiaddr = "/ip4/127.0.0.1/tcp/9002".parse().unwrap(); /// /// let mut tcp1 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)).boxed(); - /// tcp1.listen_on(ListenerId::new(1), listen_addr1.clone()).expect("listener"); + /// tcp1.listen_on( listen_addr1.clone()).expect("listener"); /// match tcp1.select_next_some().await { /// TransportEvent::NewAddress { listen_addr, .. } => { /// println!("Listening on {:?}", listen_addr); @@ -253,7 +253,7 @@ impl GenTcpConfig { /// } /// /// let mut tcp2 = TcpTransport::new(GenTcpConfig::new().port_reuse(true)).boxed(); - /// tcp2.listen_on(ListenerId::new(1), listen_addr2).expect("listener"); + /// tcp2.listen_on( listen_addr2).expect("listener"); /// match tcp2.select_next_some().await { /// TransportEvent::NewAddress { listen_addr, .. } => { /// println!("Listening on {:?}", listen_addr); @@ -302,6 +302,8 @@ where T: Provider + Send, { config: GenTcpConfig, + + next_listener_id: ListenerId, /// All the active listeners. /// The `Listener` struct contains a stream that we want to be pinned. Since the `VecDeque` /// can be resized, the only way is to use a `Pin>`. @@ -317,8 +319,7 @@ where pub fn new(config: GenTcpConfig) -> Self { GenTcpTransport { config, - listeners: Default::default(), - pending_events: Default::default(), + ..Default::default() } } @@ -365,6 +366,7 @@ where { fn default() -> Self { GenTcpTransport { + next_listener_id: ListenerId::new::(1), config: GenTcpConfig::default(), listeners: VecDeque::new(), pending_events: VecDeque::new(), @@ -384,22 +386,19 @@ where type Dial = Pin> + Send>>; type ListenerUpgrade = Ready>; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { let socket_addr = if let Ok(sa) = multiaddr_to_socketaddr(addr.clone()) { sa } else { return Err(TransportError::MultiaddrNotSupported(addr)); }; + let id = self.next_listener_id.next_id(); log::debug!("listening on {}", socket_addr); let listener = self .do_listen(id, socket_addr) .map_err(TransportError::Other)?; self.listeners.push_back(Box::pin(listener)); - Ok(()) + Ok(id) } fn remove_listener(&mut self, id: ListenerId) -> bool { @@ -924,7 +923,7 @@ mod tests { async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); - tcp.listen_on(ListenerId::new(1), addr).unwrap(); + tcp.listen_on(addr).unwrap(); loop { match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr, .. } => { @@ -993,7 +992,7 @@ mod tests { async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); - tcp.listen_on(ListenerId::new(1), addr).unwrap(); + tcp.listen_on(addr).unwrap(); loop { match tcp.select_next_some().await { @@ -1062,7 +1061,7 @@ mod tests { async fn listener(addr: Multiaddr, mut ready_tx: mpsc::Sender) { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); - tcp.listen_on(ListenerId::new(1), addr).unwrap(); + tcp.listen_on(addr).unwrap(); loop { match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr, .. } => { @@ -1084,7 +1083,7 @@ mod tests { async fn dialer(addr: Multiaddr, mut ready_rx: mpsc::Receiver) { let dest_addr = ready_rx.next().await.unwrap(); let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)).boxed(); - tcp.listen_on(ListenerId::new(1), addr).unwrap(); + tcp.listen_on(addr).unwrap(); match tcp.select_next_some().await { TransportEvent::NewAddress { .. } => { // Obtain a future socket through dialing @@ -1142,13 +1141,13 @@ mod tests { T::Stream: Sync, { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)).boxed(); - tcp.listen_on(ListenerId::new(1), addr).unwrap(); + tcp.listen_on(addr).unwrap(); match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr: addr1, .. } => { // Listen on the same address a second time. - tcp.listen_on(ListenerId::new(1), addr1.clone()).unwrap(); + tcp.listen_on(addr1.clone()).unwrap(); match tcp.select_next_some().await { TransportEvent::NewAddress { listen_addr: addr2, .. @@ -1194,7 +1193,7 @@ mod tests { T::IfWatcher: Sync, { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); - tcp.listen_on(ListenerId::new(1), addr).unwrap(); + tcp.listen_on(addr).unwrap(); tcp.select_next_some() .await .into_new_address() @@ -1231,13 +1230,13 @@ mod tests { #[cfg(feature = "async-io")] { let mut tcp = TcpTransport::new(GenTcpConfig::new()); - assert!(tcp.listen_on(ListenerId::new(1), addr.clone()).is_err()); + assert!(tcp.listen_on(addr.clone()).is_err()); } #[cfg(feature = "tokio")] { let mut tcp = TokioTcpTransport::new(GenTcpConfig::new()); - assert!(tcp.listen_on(ListenerId::new(1), addr.clone()).is_err()); + assert!(tcp.listen_on(addr.clone()).is_err()); } } diff --git a/transports/uds/src/lib.rs b/transports/uds/src/lib.rs index 87e840059e3..4576bf4bae4 100644 --- a/transports/uds/src/lib.rs +++ b/transports/uds/src/lib.rs @@ -65,6 +65,7 @@ macro_rules! codegen { #[cfg_attr(docsrs, doc(cfg(feature = $feature_name)))] pub struct $uds_config { listeners: VecDeque<(ListenerId, Listener)>, + next_listener_id: ListenerId, } impl $uds_config { @@ -72,6 +73,7 @@ macro_rules! codegen { pub fn new() -> $uds_config { $uds_config { listeners: VecDeque::new(), + next_listener_id: ListenerId::new::(1), } } } @@ -90,10 +92,10 @@ macro_rules! codegen { fn listen_on( &mut self, - id: ListenerId, addr: Multiaddr, - ) -> Result<(), TransportError> { + ) -> Result> { if let Ok(path) = multiaddr_to_path(&addr) { + let id = self.next_listener_id.next_id(); let listener = $build_listener(path) .map_err(Err) .map_ok(move |listener| { @@ -135,7 +137,7 @@ macro_rules! codegen { .try_flatten_stream() .boxed(); self.listeners.push_back((id, listener)); - Ok(()) + Ok(id) } else { Err(TransportError::MultiaddrNotSupported(addr)) } @@ -257,7 +259,6 @@ mod tests { use futures::{channel::oneshot, prelude::*}; use libp2p_core::{ multiaddr::{Multiaddr, Protocol}, - transport::ListenerId, Transport, }; use std::{self, borrow::Cow, path::Path}; @@ -291,7 +292,7 @@ mod tests { async_std::task::spawn(async move { let mut transport = UdsConfig::new().boxed(); - transport.listen_on(ListenerId::new(1), addr).unwrap(); + transport.listen_on(addr).unwrap(); let listen_addr = transport .select_next_some() @@ -327,7 +328,7 @@ mod tests { let mut uds = UdsConfig::new(); let addr = "/unix//foo/bar".parse::().unwrap(); - assert!(uds.listen_on(ListenerId::new(1), addr).is_err()); + assert!(uds.listen_on(addr).is_err()); } #[test] diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index 995814f8549..2ac0c1a6845 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -119,11 +119,7 @@ where type ListenerUpgrade = BoxFuture<'static, Result>; type Dial = BoxFuture<'static, Result>; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { let mut inner_addr = addr.clone(); let proto = match inner_addr.pop() { Some(p @ Protocol::Wss(_)) => { @@ -140,11 +136,14 @@ where return Err(TransportError::MultiaddrNotSupported(addr)); } }; - self.listener_protos.insert(id, proto); - self.transport - .lock() - .listen_on(id, inner_addr) - .map_err(|e| e.map(Error::Transport)) + match self.transport.lock().listen_on(inner_addr) { + Ok(id) => { + let id = id.map_type::(); + self.listener_protos.insert(id, proto); + Ok(id) + } + Err(e) => Err(e.map(Error::Transport)), + } } fn remove_listener(&mut self, id: ListenerId) -> bool { @@ -177,7 +176,7 @@ where }; drop(transport); - let event = match inner_event { + let event = match inner_event.map_transport_type::() { TransportEvent::NewAddress { listener_id, mut listen_addr, diff --git a/transports/websocket/src/lib.rs b/transports/websocket/src/lib.rs index b7b50b66b7f..93fa42abf4d 100644 --- a/transports/websocket/src/lib.rs +++ b/transports/websocket/src/lib.rs @@ -123,12 +123,10 @@ where type ListenerUpgrade = MapFuture, WrapperFn>; type Dial = MapFuture, WrapperFn>; - fn listen_on( - &mut self, - id: ListenerId, - addr: Multiaddr, - ) -> Result<(), TransportError> { - self.transport.listen_on(id, addr) + fn listen_on(&mut self, addr: Multiaddr) -> Result> { + self.transport + .listen_on(addr) + .map(ListenerId::map_type::) } fn remove_listener(&mut self, id: ListenerId) -> bool { @@ -225,7 +223,7 @@ where mod tests { use super::WsConfig; use futures::prelude::*; - use libp2p_core::{multiaddr::Protocol, transport::ListenerId, Multiaddr, PeerId, Transport}; + use libp2p_core::{multiaddr::Protocol, Multiaddr, PeerId, Transport}; use libp2p_tcp as tcp; #[test] @@ -245,9 +243,7 @@ mod tests { || WsConfig::new(tcp::TcpTransport::new(tcp::GenTcpConfig::default())).boxed(); let mut ws_config = new_ws_config(); - ws_config - .listen_on(ListenerId::new(1), listen_addr) - .expect("listener"); + ws_config.listen_on(listen_addr).expect("listener"); let addr = ws_config .next() From 5f9ebb7091bca174daec02a8fd0074488c94d65b Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 30 May 2022 00:57:01 +0200 Subject: [PATCH 27/47] *: fix CI --- src/lib.rs | 4 ++-- transports/websocket/src/framed.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2a7d80a25e3..aaa52e030dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -266,8 +266,8 @@ pub fn tokio_development_transport( let tcp = tcp::TokioTcpTransport::new(tcp_config); dns::TokioDnsConfig::system(tcp) }; - let ws_dns_tcp = websocket::WsConfig::new(dns_tcp().await?); - dns_tcp().await?.or_transport(ws_dns_tcp) + let ws_dns_tcp = websocket::WsConfig::new(dns_tcp()?); + dns_tcp()?.or_transport(ws_dns_tcp) }; let noise_keys = noise::Keypair::::new() diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index 2ac0c1a6845..8dc4daff84b 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -278,8 +278,8 @@ where let transport = self.transport.clone(); let tls_config = self.tls_config.clone(); - let use_deflate = self.use_deflate.clone(); - let max_redirects = self.max_redirects.clone(); + let use_deflate = self.use_deflate; + let max_redirects = self.max_redirects; let future = async move { loop { From 27ee9ca240ef9808af5739d6a025a4e5c4f49657 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sat, 11 Jun 2022 22:28:14 +0200 Subject: [PATCH 28/47] transports/tcp: fix port-reuse tests --- transports/tcp/src/lib.rs | 73 ++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index bd7ce0e2a48..cc50187746b 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -890,7 +890,10 @@ fn ip_to_multiaddr(ip: IpAddr, port: u16) -> Multiaddr { #[cfg(test)] mod tests { use super::*; - use futures::channel::{mpsc, oneshot}; + use futures::{ + channel::{mpsc, oneshot}, + future::poll_fn, + }; #[test] fn multiaddr_to_tcp_conversion() { @@ -1086,7 +1089,7 @@ mod tests { async fn listener( addr: Multiaddr, mut ready_tx: mpsc::Sender, - _port_reuse_rx: oneshot::Receiver>, + port_reuse_rx: oneshot::Receiver>, ) { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); tcp.listen_on(addr).unwrap(); @@ -1097,14 +1100,13 @@ mod tests { } TransportEvent::Incoming { upgrade, - // mut send_back_addr, + mut send_back_addr, .. } => { - // TODO - // // Receive the dialer tcp port reuse - // let remote_port_reuse = port_reuse_rx.await.unwrap(); - // // And check it is the same as the remote port used for upgrade - // assert_eq!(send_back_addr.pop().unwrap(), remote_port_reuse); + // Receive the dialer tcp port reuse + let remote_port_reuse = port_reuse_rx.await.unwrap(); + // And check it is the same as the remote port used for upgrade + assert_eq!(send_back_addr.pop().unwrap(), remote_port_reuse); let mut upgrade = upgrade.await.unwrap(); let mut buf = [0u8; 3]; @@ -1121,26 +1123,26 @@ mod tests { async fn dialer( addr: Multiaddr, mut ready_rx: mpsc::Receiver, - _port_reuse_tx: oneshot::Sender>, + port_reuse_tx: oneshot::Sender>, ) { let dest_addr = ready_rx.next().await.unwrap(); - let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)).boxed(); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); tcp.listen_on(addr).unwrap(); - match tcp.select_next_some().await { + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { TransportEvent::NewAddress { .. } => { - // TODO - // // Check that tcp and listener share the same port reuse SocketAddr - // let port_reuse_tcp = tcp.port_reuse.local_dial_addr(&listener.listen_addr.ip()); - // let port_reuse_listener = listener - // .port_reuse - // .local_dial_addr(&listener.listen_addr.ip()); - // assert!(port_reuse_tcp.is_some()); - // assert_eq!(port_reuse_tcp, port_reuse_listener); - - // // Send the dialer tcp port reuse to the listener - // port_reuse_tx - // .send(Protocol::Tcp(port_reuse_tcp.unwrap().port())) - // .ok(); + // Check that tcp and listener share the same port reuse SocketAddr + let listener = tcp.listeners.front().unwrap(); + let port_reuse_tcp = tcp.port_reuse.local_dial_addr(&listener.listen_addr.ip()); + let port_reuse_listener = listener + .port_reuse + .local_dial_addr(&listener.listen_addr.ip()); + assert!(port_reuse_tcp.is_some()); + assert_eq!(port_reuse_tcp, port_reuse_listener); + + // Send the dialer tcp port reuse to the listener + port_reuse_tx + .send(Protocol::Tcp(port_reuse_tcp.unwrap().port())) + .ok(); // Obtain a future socket through dialing let mut socket = tcp.dial(dest_addr).unwrap().await.unwrap(); @@ -1198,25 +1200,24 @@ mod tests { T::IfWatcher: Sync, T::Stream: Sync, { - let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)).boxed(); + let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); tcp.listen_on(addr).unwrap(); - match tcp.select_next_some().await { + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { TransportEvent::NewAddress { listen_addr: addr1, .. } => { - // TODO - // // Check that tcp and listener share the same port reuse SocketAddr - // let port_reuse_tcp = - // tcp.port_reuse.local_dial_addr(&listener1.listen_addr.ip()); - // let port_reuse_listener1 = listener1 - // .port_reuse - // .local_dial_addr(&listener1.listen_addr.ip()); - // assert!(port_reuse_tcp.is_some()); - // assert_eq!(port_reuse_tcp, port_reuse_listener1); + let listener1 = tcp.listeners.front().unwrap(); + let port_reuse_tcp = + tcp.port_reuse.local_dial_addr(&listener1.listen_addr.ip()); + let port_reuse_listener1 = listener1 + .port_reuse + .local_dial_addr(&listener1.listen_addr.ip()); + assert!(port_reuse_tcp.is_some()); + assert_eq!(port_reuse_tcp, port_reuse_listener1); // Listen on the same address a second time. tcp.listen_on(addr1.clone()).unwrap(); - match tcp.select_next_some().await { + match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { TransportEvent::NewAddress { listen_addr: addr2, .. } => { From 08f4f80c6c0dbb4e69072fd3a385d6b97ab199af Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sat, 11 Jun 2022 22:39:49 +0200 Subject: [PATCH 29/47] *: fix intra-doc links --- core/src/transport.rs | 2 +- transports/tcp/src/lib.rs | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/core/src/transport.rs b/core/src/transport.rs index cc5dccc6e60..3b6ac30e66b 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -95,7 +95,7 @@ pub trait Transport { type Error: Error; /// A pending [`Output`](Transport::Output) for an inbound connection, - /// obtained from the [`Listener`](Transport::Listener) stream. + /// obtained from the [`Transport`] stream. /// /// After a connection has been accepted by the transport, it may need to go through /// asynchronous post-processing (i.e. protocol upgrade negotiations). Such diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index cc50187746b..dc540821f50 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -31,14 +31,14 @@ mod provider; #[cfg(feature = "async-io")] pub use provider::async_io; -/// The type of a [`GenTcpConfig`] using the `async-io` implementation. +/// The type of a [`GenTcpTransport`] using the `async-io` implementation. #[cfg(feature = "async-io")] pub type TcpTransport = GenTcpTransport; #[cfg(feature = "tokio")] pub use provider::tokio; -/// The type of a [`GenTcpConfig`] using the `tokio` implementation. +/// The type of a [`GenTcpTransport`] using the `tokio` implementation. #[cfg(feature = "tokio")] pub type TokioTcpTransport = GenTcpTransport; @@ -232,11 +232,10 @@ impl GenTcpConfig { /// > a single outgoing connection to a particular address and port /// > of a peer per local listening socket address. /// - /// `GenTcpConfig` keeps track of the listen socket addresses as they - /// are reported by polling [`TcpListenStream`]s obtained from - /// [`GenTcpConfig::listen_on()`]. It is possible to listen on multiple + /// [`GenTcpTransport`] keeps track of the listen socket addresses as they + /// are reported by polling it. It is possible to listen on multiple /// addresses, enabling port reuse for each, knowing exactly which listen - /// address is reused when dialing with a specific `GenTcpConfig`, as in the + /// address is reused when dialing with a specific `GenTcpTransport`, as in the /// following example: /// /// ```no_run @@ -282,7 +281,7 @@ impl GenTcpConfig { /// case, one is chosen whose IP protocol version and loopback status is the /// same as that of the remote address. Consequently, for maximum control of /// the local listening addresses and ports that are used for outgoing - /// connections, a new `GenTcpConfig` should be created for each listening + /// connections, a new `GenTcpTransport` should be created for each listening /// socket, avoiding the use of wildcard addresses which bind a socket to /// all network interfaces. /// @@ -312,10 +311,10 @@ where next_listener_id: ListenerId, /// All the active listeners. - /// The `Listener` struct contains a stream that we want to be pinned. Since the `VecDeque` + /// The `TcpListenStream` struct contains a stream that we want to be pinned. Since the `VecDeque` /// can be resized, the only way is to use a `Pin>`. listeners: VecDeque>>>, - /// Pending listeners events to return from [`ListenersStream::poll`]. + /// Pending listeners events to return from [`GenTcpTransport::poll`]. pending_events: VecDeque::ListenerUpgrade, io::Error>>, } @@ -667,7 +666,7 @@ where T: Provider, { /// Constructs a `TcpListenStream` for incoming connections around - /// the given `TcpListener`. + /// the given listener. fn new( listener_id: ListenerId, listener: TcpListener, From f92c2a41dc8d89f21dab75d957abf5afc5b83502 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sat, 11 Jun 2022 22:42:42 +0200 Subject: [PATCH 30/47] transports/tcp: rm unneeded trait-bounds in tests --- transports/tcp/src/lib.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index dc540821f50..22340bf4fc4 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -1192,13 +1192,7 @@ mod tests { fn port_reuse_listening() { env_logger::try_init().ok(); - async fn listen_twice(addr: Multiaddr) - where - T: Provider + Sized + Send + Sync + Unpin + 'static, - T::Listener: Sync, - T::IfWatcher: Sync, - T::Stream: Sync, - { + async fn listen_twice(addr: Multiaddr) { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new().port_reuse(true)); tcp.listen_on(addr).unwrap(); match poll_fn(|cx| Pin::new(&mut tcp).poll(cx)).await { @@ -1255,11 +1249,7 @@ mod tests { fn listen_port_0() { env_logger::try_init().ok(); - async fn listen(addr: Multiaddr) -> Multiaddr - where - T: Provider, - T::IfWatcher: Sync, - { + async fn listen(addr: Multiaddr) -> Multiaddr { let mut tcp = GenTcpTransport::::new(GenTcpConfig::new()).boxed(); tcp.listen_on(addr).unwrap(); tcp.select_next_some() From a357d71e24c4c116fc9d8373263dd88b0041d7d6 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 20 Jun 2022 17:48:26 +0200 Subject: [PATCH 31/47] *: use random ListenerIds instead of namespaced --- core/src/transport.rs | 68 +++--------------------------- core/src/transport/memory.rs | 13 +----- transports/dns/src/lib.rs | 2 - transports/tcp/src/lib.rs | 5 +-- transports/uds/src/lib.rs | 4 +- transports/websocket/src/framed.rs | 3 +- transports/websocket/src/lib.rs | 4 +- 7 files changed, 13 insertions(+), 86 deletions(-) diff --git a/core/src/transport.rs b/core/src/transport.rs index 3b6ac30e66b..8a7b3e2478a 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -28,7 +28,6 @@ use futures::prelude::*; use multiaddr::Multiaddr; use std::{ - any::{Any, TypeId}, error::Error, fmt, pin::Pin, @@ -231,30 +230,18 @@ pub trait Transport { /// The ID of a single listener. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub struct ListenerId { - id: u64, - transport_id: TypeId, -} +pub struct ListenerId(u64); impl ListenerId { /// Creates a new `ListenerId`. - pub fn new(id: u64) -> Self { - Self { - id, - transport_id: TypeId::of::(), - } - } - - /// Returns the next id - pub fn next_id(&mut self) -> Self { - let current = *self; - self.id += 1; - current + pub fn new() -> Self { + ListenerId(rand::random()) } +} - pub fn map_type(mut self) -> Self { - self.transport_id = TypeId::of::(); - self +impl Default for ListenerId { + fn default() -> Self { + Self::new() } } @@ -392,47 +379,6 @@ impl TransportEvent { } } - pub fn map_transport_type(self) -> Self { - match self { - TransportEvent::Incoming { - listener_id, - upgrade, - local_addr, - send_back_addr, - } => TransportEvent::Incoming { - listener_id: listener_id.map_type::(), - upgrade, - local_addr, - send_back_addr, - }, - TransportEvent::NewAddress { - listen_addr, - listener_id, - } => TransportEvent::NewAddress { - listen_addr, - listener_id: listener_id.map_type::(), - }, - TransportEvent::AddressExpired { - listen_addr, - listener_id, - } => TransportEvent::AddressExpired { - listen_addr, - listener_id: listener_id.map_type::(), - }, - TransportEvent::Error { listener_id, error } => TransportEvent::Error { - listener_id: listener_id.map_type::(), - error, - }, - TransportEvent::ListenerClosed { - listener_id, - reason, - } => TransportEvent::ListenerClosed { - listener_id: listener_id.map_type::(), - reason, - }, - } - } - /// Returns `true` if this is an `Upgrade` listener event. pub fn is_upgrade(&self) -> bool { matches!(self, TransportEvent::Incoming { .. }) diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 2056002f6dc..6bd1b054325 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -93,18 +93,9 @@ impl Hub { } /// Transport that supports `/memory/N` multiaddresses. +#[derive(Default)] pub struct MemoryTransport { listeners: VecDeque>>, - next_listener_id: ListenerId, -} - -impl Default for MemoryTransport { - fn default() -> Self { - MemoryTransport { - listeners: VecDeque::new(), - next_listener_id: ListenerId::new::(1), - } - } } impl MemoryTransport { @@ -202,7 +193,7 @@ impl Transport for MemoryTransport { None => return Err(TransportError::Other(MemoryTransportError::Unreachable)), }; - let id = self.next_listener_id.next_id(); + let id = ListenerId::new(); let listener = Listener { id, port, diff --git a/transports/dns/src/lib.rs b/transports/dns/src/lib.rs index 95fd96ca2e9..0ee89f78373 100644 --- a/transports/dns/src/lib.rs +++ b/transports/dns/src/lib.rs @@ -200,7 +200,6 @@ where self.inner .lock() .listen_on(addr) - .map(ListenerId::map_type::) .map_err(|e| e.map(DnsErr::Transport)) } @@ -230,7 +229,6 @@ where let mut inner = self.inner.lock(); Transport::poll(Pin::new(inner.deref_mut()), cx).map(|event| { event - .map_transport_type::() .map_upgrade(|upgr| upgr.map_err::<_, fn(_) -> _>(DnsErr::Transport)) .map_err(DnsErr::Transport) }) diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 22340bf4fc4..57255b9e044 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -308,8 +308,6 @@ where /// The configuration of port reuse when dialing. port_reuse: PortReuse, - - next_listener_id: ListenerId, /// All the active listeners. /// The `TcpListenStream` struct contains a stream that we want to be pinned. Since the `VecDeque` /// can be resized, the only way is to use a `Pin>`. @@ -388,7 +386,6 @@ where PortReuse::Disabled }; GenTcpTransport { - next_listener_id: ListenerId::new::(1), port_reuse, config, listeners: VecDeque::new(), @@ -415,7 +412,7 @@ where } else { return Err(TransportError::MultiaddrNotSupported(addr)); }; - let id = self.next_listener_id.next_id(); + let id = ListenerId::new(); log::debug!("listening on {}", socket_addr); let listener = self .do_listen(id, socket_addr) diff --git a/transports/uds/src/lib.rs b/transports/uds/src/lib.rs index e1e4b9c7f5f..e85d625ed1e 100644 --- a/transports/uds/src/lib.rs +++ b/transports/uds/src/lib.rs @@ -69,7 +69,6 @@ macro_rules! codegen { #[cfg_attr(docsrs, doc(cfg(feature = $feature_name)))] pub struct $uds_config { listeners: VecDeque<(ListenerId, Listener)>, - next_listener_id: ListenerId, } impl $uds_config { @@ -77,7 +76,6 @@ macro_rules! codegen { pub fn new() -> $uds_config { $uds_config { listeners: VecDeque::new(), - next_listener_id: ListenerId::new::(1), } } } @@ -99,7 +97,7 @@ macro_rules! codegen { addr: Multiaddr, ) -> Result> { if let Ok(path) = multiaddr_to_path(&addr) { - let id = self.next_listener_id.next_id(); + let id = ListenerId::new(); let listener = $build_listener(path) .map_err(Err) .map_ok(move |listener| { diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index 8dc4daff84b..3ca57a0c0db 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -138,7 +138,6 @@ where }; match self.transport.lock().listen_on(inner_addr) { Ok(id) => { - let id = id.map_type::(); self.listener_protos.insert(id, proto); Ok(id) } @@ -176,7 +175,7 @@ where }; drop(transport); - let event = match inner_event.map_transport_type::() { + let event = match inner_event { TransportEvent::NewAddress { listener_id, mut listen_addr, diff --git a/transports/websocket/src/lib.rs b/transports/websocket/src/lib.rs index 93fa42abf4d..1897b64a2a0 100644 --- a/transports/websocket/src/lib.rs +++ b/transports/websocket/src/lib.rs @@ -124,9 +124,7 @@ where type Dial = MapFuture, WrapperFn>; fn listen_on(&mut self, addr: Multiaddr) -> Result> { - self.transport - .listen_on(addr) - .map(ListenerId::map_type::) + self.transport.listen_on(addr) } fn remove_listener(&mut self, id: ListenerId) -> bool { From a4a745e3ef18164c99148f01d3fbd3cc70aafce1 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 20 Jun 2022 17:54:44 +0200 Subject: [PATCH 32/47] core/transport: remove (Partial)Ord for ListenerId --- core/src/transport.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/transport.rs b/core/src/transport.rs index 8a7b3e2478a..d94056b33cc 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -229,7 +229,7 @@ pub trait Transport { } /// The ID of a single listener. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct ListenerId(u64); impl ListenerId { From 1c2b9e5b2ddd1223bd36177ac0ce534ea7984316 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 26 Jun 2022 02:11:05 +0200 Subject: [PATCH 33/47] transports/relay: adapt ClientTransport --- Cargo.toml | 14 +- misc/metrics/Cargo.toml | 8 +- protocols/relay/src/v2/client/transport.rs | 160 ++++++++++++++------- 3 files changed, 116 insertions(+), 66 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1a2afa190b6..72839864fc6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ default = [ "ping", "plaintext", "pnet", - # "relay", + "relay", "request-response", "rendezvous", "secp256k1", @@ -37,7 +37,7 @@ default = [ ] autonat = ["dep:libp2p-autonat"] -# dcutr = ["dep:libp2p-dcutr", "libp2p-metrics?/dcutr"] +dcutr = ["dep:libp2p-dcutr", "libp2p-metrics?/dcutr"] deflate = ["dep:libp2p-deflate"] dns-async-std = ["dep:libp2p-dns", "libp2p-dns?/async-std"] dns-tokio = ["dep:libp2p-dns", "libp2p-dns?/tokio"] @@ -52,7 +52,7 @@ noise = ["dep:libp2p-noise"] ping = ["dep:libp2p-ping", "libp2p-metrics?/ping"] plaintext = ["dep:libp2p-plaintext"] pnet = ["dep:libp2p-pnet"] -# relay = ["dep:libp2p-relay", "libp2p-metrics?/relay"] +relay = ["dep:libp2p-relay", "libp2p-metrics?/relay"] request-response = ["dep:libp2p-request-response"] rendezvous = ["dep:libp2p-rendezvous"] tcp-async-io = ["dep:libp2p-tcp", "libp2p-tcp?/async-io"] @@ -79,7 +79,7 @@ lazy_static = "1.2" libp2p-autonat = { version = "0.4.0", path = "protocols/autonat", optional = true } libp2p-core = { version = "0.33.0", path = "core", default-features = false } -# libp2p-dcutr = { version = "0.3.1", path = "protocols/dcutr", optional = true } +libp2p-dcutr = { version = "0.3.1", path = "protocols/dcutr", optional = true } libp2p-floodsub = { version = "0.36.0", path = "protocols/floodsub", optional = true } libp2p-identify = { version = "0.36.1", path = "protocols/identify", optional = true } libp2p-kad = { version = "0.37.1", path = "protocols/kad", optional = true } @@ -89,7 +89,7 @@ libp2p-noise = { version = "0.36.0", path = "transports/noise", optional = true libp2p-ping = { version = "0.36.0", path = "protocols/ping", optional = true } libp2p-plaintext = { version = "0.33.0", path = "transports/plaintext", optional = true } libp2p-pnet = { version = "0.22.0", path = "transports/pnet", optional = true } -# libp2p-relay = { version = "0.9.1", path = "protocols/relay", optional = true } +libp2p-relay = { version = "0.9.1", path = "protocols/relay", optional = true } libp2p-rendezvous = { version = "0.6.0", path = "protocols/rendezvous", optional = true } libp2p-request-response = { version = "0.18.0", path = "protocols/request-response", optional = true } libp2p-swarm = { version = "0.36.1", path = "swarm" } @@ -130,7 +130,7 @@ members = [ "misc/prost-codec", "muxers/mplex", "muxers/yamux", - # "protocols/dcutr", + "protocols/dcutr", "protocols/autonat", "protocols/floodsub", "protocols/gossipsub", @@ -139,7 +139,7 @@ members = [ "protocols/kad", "protocols/mdns", "protocols/ping", - # "protocols/relay", + "protocols/relay", "protocols/request-response", "swarm", "swarm-derive", diff --git a/misc/metrics/Cargo.toml b/misc/metrics/Cargo.toml index c402b1e6eef..f539ce3105d 100644 --- a/misc/metrics/Cargo.toml +++ b/misc/metrics/Cargo.toml @@ -15,16 +15,16 @@ gossipsub = ["libp2p-gossipsub"] identify = ["libp2p-identify"] kad = ["libp2p-kad"] ping = ["libp2p-ping"] -# relay = ["libp2p-relay"] -# dcutr = ["libp2p-dcutr"] +relay = ["libp2p-relay"] +dcutr = ["libp2p-dcutr"] [dependencies] libp2p-core = { version = "0.33.0", path = "../../core", default-features = false } -# libp2p-dcutr = { version = "0.3.0", path = "../../protocols/dcutr", optional = true } +libp2p-dcutr = { version = "0.3.0", path = "../../protocols/dcutr", optional = true } libp2p-identify = { version = "0.36.0", path = "../../protocols/identify", optional = true } libp2p-kad = { version = "0.37.0", path = "../../protocols/kad", optional = true } libp2p-ping = { version = "0.36.0", path = "../../protocols/ping", optional = true } -# libp2p-relay = { version = "0.9.0", path = "../../protocols/relay", optional = true } +libp2p-relay = { version = "0.9.0", path = "../../protocols/relay", optional = true } libp2p-swarm = { version = "0.36.0", path = "../../swarm" } prometheus-client = "0.16.0" diff --git a/protocols/relay/src/v2/client/transport.rs b/protocols/relay/src/v2/client/transport.rs index 5414353786c..d5a71e54b3e 100644 --- a/protocols/relay/src/v2/client/transport.rs +++ b/protocols/relay/src/v2/client/transport.rs @@ -23,12 +23,13 @@ use crate::v2::client::RelayedConnection; use crate::v2::RequestId; use futures::channel::mpsc; use futures::channel::oneshot; -use futures::future::{ready, BoxFuture, Future, FutureExt, Ready}; +use futures::future::{ready, BoxFuture, FutureExt, Ready}; use futures::ready; use futures::sink::SinkExt; +use futures::stream::SelectAll; use futures::stream::{Stream, StreamExt}; use libp2p_core::multiaddr::{Multiaddr, Protocol}; -use libp2p_core::transport::{ListenerEvent, TransportError}; +use libp2p_core::transport::{ListenerId, TransportError, TransportEvent}; use libp2p_core::{PeerId, Transport}; use std::collections::VecDeque; use std::pin::Pin; @@ -85,9 +86,10 @@ use thiserror::Error; /// .with(Protocol::P2pCircuit); // Signal to listen via remote relay node. /// transport.listen_on(relay_addr).unwrap(); /// ``` -#[derive(Clone)] pub struct ClientTransport { to_behaviour: mpsc::Sender, + pending_to_behaviour: VecDeque, + listeners: SelectAll, } impl ClientTransport { @@ -112,22 +114,22 @@ impl ClientTransport { /// ``` pub(crate) fn new() -> (Self, mpsc::Receiver) { let (to_behaviour, from_transport) = mpsc::channel(0); - - (ClientTransport { to_behaviour }, from_transport) + let transport = ClientTransport { + to_behaviour, + pending_to_behaviour: VecDeque::new(), + listeners: SelectAll::new(), + }; + (transport, from_transport) } } impl Transport for ClientTransport { type Output = RelayedConnection; type Error = RelayError; - type Listener = RelayListener; type ListenerUpgrade = Ready>; type Dial = RelayedDial; - fn listen_on( - &mut self, - addr: Multiaddr, - ) -> Result> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { let (relay_peer_id, relay_addr) = match parse_relayed_multiaddr(addr)? { RelayedMultiaddr { relay_peer_id: None, @@ -147,25 +149,31 @@ impl Transport for ClientTransport { }; let (to_listener, from_behaviour) = mpsc::channel(0); - let mut to_behaviour = self.to_behaviour.clone(); - let msg_to_behaviour = Some( - async move { - to_behaviour - .send(TransportToBehaviourMsg::ListenReq { - relay_peer_id, - relay_addr, - to_listener, - }) - .await - } - .boxed(), - ); - - Ok(RelayListener { - queued_new_addresses: Default::default(), + self.pending_to_behaviour + .push_back(TransportToBehaviourMsg::ListenReq { + relay_peer_id, + relay_addr, + to_listener, + }); + + let listener_id = ListenerId::new(); + let listener = RelayListener { + listener_id, + queued_events: Default::default(), from_behaviour, - msg_to_behaviour, - }) + is_closed: false, + }; + self.listeners.push(listener); + Ok(listener_id) + } + + fn remove_listener(&mut self, id: ListenerId) -> bool { + if let Some(listener) = self.listeners.iter_mut().find(|l| l.listener_id == id) { + listener.close(Ok(())); + true + } else { + false + } } fn dial(&mut self, addr: Multiaddr) -> Result> { @@ -217,6 +225,35 @@ impl Transport for ClientTransport { fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option { None } + + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> + where + Self: Sized, + { + loop { + if !self.pending_to_behaviour.is_empty() { + match self.to_behaviour.poll_ready(cx) { + Poll::Ready(Ok(())) => { + let msg = self + .pending_to_behaviour + .pop_front() + .expect("Called !is_empty()."); + let _ = self.to_behaviour.start_send(msg); + continue; + } + Poll::Ready(Err(_)) => unreachable!("Receiver is never dropped."), + Poll::Pending => {} + } + } + match self.listeners.poll_next_unpin(cx) { + Poll::Ready(Some(event)) => return Poll::Ready(event), + _ => return Poll::Pending, + } + } + } } #[derive(Default)] @@ -282,64 +319,77 @@ fn parse_relayed_multiaddr( } pub struct RelayListener { - queued_new_addresses: VecDeque, + listener_id: ListenerId, + queued_events: VecDeque<::Item>, from_behaviour: mpsc::Receiver, - msg_to_behaviour: Option>>, + is_closed: bool, } -impl Unpin for RelayListener {} +impl RelayListener { + fn close(&mut self, reason: Result<(), RelayError>) { + self.queued_events + .push_back(TransportEvent::ListenerClosed { + listener_id: self.listener_id, + reason, + }); + self.is_closed = true; + } +} impl Stream for RelayListener { - type Item = - Result>, RelayError>, RelayError>; + type Item = TransportEvent<::ListenerUpgrade, RelayError>; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { loop { - if let Some(msg) = &mut self.msg_to_behaviour { - match Future::poll(msg.as_mut(), cx) { - Poll::Ready(Ok(())) => self.msg_to_behaviour = None, - Poll::Ready(Err(e)) => return Poll::Ready(Some(Err(e.into()))), - Poll::Pending => {} - } + if let Some(event) = self.queued_events.pop_front() { + return Poll::Ready(Some(event)); } - if let Some(addr) = self.queued_new_addresses.pop_front() { - return Poll::Ready(Some(Ok(ListenerEvent::NewAddress(addr)))); + if self.is_closed { + return Poll::Ready(None); } let msg = match ready!(self.from_behaviour.poll_next_unpin(cx)) { Some(msg) => msg, None => { // Sender of `from_behaviour` has been dropped, signaling listener to close. - return Poll::Ready(None); + self.close(Ok(())); + continue; } }; - let result = match msg { + match msg { ToListenerMsg::Reservation(Ok(Reservation { addrs })) => { debug_assert!( - self.queued_new_addresses.is_empty(), + self.queued_events.is_empty(), "Assert empty due to previous `pop_front` attempt." ); // Returned as [`ListenerEvent::NewAddress`] in next iteration of loop. - self.queued_new_addresses = addrs.into(); - - continue; + self.queued_events = addrs + .into_iter() + .map(|listen_addr| TransportEvent::NewAddress { + listener_id: self.listener_id, + listen_addr, + }) + .collect(); } ToListenerMsg::IncomingRelayedConnection { stream, src_peer_id, relay_addr, relay_peer_id: _, - } => Ok(ListenerEvent::Upgrade { - upgrade: ready(Ok(stream)), - local_addr: relay_addr.with(Protocol::P2pCircuit), - remote_addr: Protocol::P2p(src_peer_id.into()).into(), - }), - ToListenerMsg::Reservation(Err(())) => Err(RelayError::Reservation), + } => { + let listener_id = self.listener_id; + + self.queued_events.push_back(TransportEvent::Incoming { + upgrade: ready(Ok(stream)), + listener_id, + local_addr: relay_addr.with(Protocol::P2pCircuit), + send_back_addr: Protocol::P2p(src_peer_id.into()).into(), + }) + } + ToListenerMsg::Reservation(Err(())) => self.close(Err(RelayError::Reservation)), }; - - return Poll::Ready(Some(result)); } } } From b19e11a684e111ecbe8028821f60dd557df7def5 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 26 Jun 2022 02:25:46 +0200 Subject: [PATCH 34/47] *: apply comments from review --- core/src/transport/memory.rs | 15 ++++++++++++--- protocols/ping/src/protocol.rs | 4 ++-- swarm/src/lib.rs | 6 +++--- transports/websocket/src/framed.rs | 12 ++++++------ 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 6bd1b054325..933ecb1b0df 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -460,7 +460,10 @@ mod tests { let addr_2: Multiaddr = "/memory/8459375923478".parse().unwrap(); let listener_id_1 = transport.listen_on(addr_1.clone()).unwrap(); - assert!(transport.remove_listener(listener_id_1)); + assert!( + transport.remove_listener(listener_id_1), + "Listener doesn't exist." + ); let listener_id_2 = transport.listen_on(addr_1.clone()).unwrap(); let listener_id_3 = transport.listen_on(addr_2.clone()).unwrap(); @@ -468,11 +471,17 @@ mod tests { assert!(transport.listen_on(addr_1.clone()).is_err()); assert!(transport.listen_on(addr_2.clone()).is_err()); - assert!(transport.remove_listener(listener_id_2)); + assert!( + transport.remove_listener(listener_id_2), + "Listener doesn't exist." + ); assert!(transport.listen_on(addr_1).is_ok()); assert!(transport.listen_on(addr_2.clone()).is_err()); - assert!(transport.remove_listener(listener_id_3)); + assert!( + transport.remove_listener(listener_id_3), + "Listener doesn't exist." + ); assert!(transport.listen_on(addr_2).is_ok()); } diff --git a/protocols/ping/src/protocol.rs b/protocols/ping/src/protocol.rs index f452936de9d..390823ec412 100644 --- a/protocols/ping/src/protocol.rs +++ b/protocols/ping/src/protocol.rs @@ -136,8 +136,8 @@ mod tests { .expect("MemoryTransport not listening on an address!"); async_std::task::spawn(async move { - let listener_event = transport.next().await.unwrap(); - let (listener_upgrade, _) = listener_event.into_upgrade().unwrap(); + let transport_event = transport.next().await.unwrap(); + let (listener_upgrade, _) = transport_event.into_upgrade().unwrap(); let conn = listener_upgrade.await.unwrap(); recv_ping(conn).await.unwrap(); }); diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 64bf1feffd9..f728634ae09 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -827,7 +827,7 @@ where None } - fn handle_listeners_event( + fn handle_transport_event( &mut self, event: TransportEvent< as Transport>::ListenerUpgrade, @@ -1098,8 +1098,8 @@ where // Poll the listener(s) for new connections. match Pin::new(&mut this.transport).poll(cx) { Poll::Pending => {} - Poll::Ready(listeners_event) => { - if let Some(swarm_event) = this.handle_listeners_event(listeners_event) { + Poll::Ready(transport_event) => { + if let Some(swarm_event) = this.handle_transport_event(transport_event) { return Poll::Ready(swarm_event); } diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index 3ca57a0c0db..1261d46f1c3 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -168,13 +168,13 @@ where mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - let mut transport = self.transport.lock(); - let inner_event = match Transport::poll(Pin::new(transport.deref_mut()), cx) { - Poll::Ready(ev) => ev, - Poll::Pending => return Poll::Pending, + let inner_event = { + let mut transport = self.transport.lock(); + match Transport::poll(Pin::new(transport.deref_mut()), cx) { + Poll::Ready(ev) => ev, + Poll::Pending => return Poll::Pending, + } }; - drop(transport); - let event = match inner_event { TransportEvent::NewAddress { listener_id, From c95c97cd27d9be29df4a75852007746d5b84b7fe Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Sun, 26 Jun 2022 22:58:03 +0200 Subject: [PATCH 35/47] transport/wasm-ext: adapt wasm-ext transport --- Cargo.toml | 10 +-- transports/wasm-ext/src/lib.rs | 134 ++++++++++++++++++++++++--------- 2 files changed, 105 insertions(+), 39 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 72839864fc6..32361ff83cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ default = [ "secp256k1", "tcp-async-io", "uds", - # "wasm-ext", + "wasm-ext", "websocket", "yamux", ] @@ -59,8 +59,8 @@ tcp-async-io = ["dep:libp2p-tcp", "libp2p-tcp?/async-io"] tcp-tokio = ["dep:libp2p-tcp", "libp2p-tcp?/tokio"] uds = ["dep:libp2p-uds"] wasm-bindgen = ["futures-timer/wasm-bindgen", "instant/wasm-bindgen", "getrandom/js", "rand/wasm-bindgen"] -# wasm-ext = ["dep:libp2p-wasm-ext"] -# wasm-ext-websocket = ["wasm-ext", "libp2p-wasm-ext?/websocket"] +wasm-ext = ["dep:libp2p-wasm-ext"] +wasm-ext-websocket = ["wasm-ext", "libp2p-wasm-ext?/websocket"] websocket = ["dep:libp2p-websocket"] yamux = ["dep:libp2p-yamux"] secp256k1 = ["libp2p-core/secp256k1"] @@ -95,7 +95,7 @@ libp2p-request-response = { version = "0.18.0", path = "protocols/request-respon libp2p-swarm = { version = "0.36.1", path = "swarm" } libp2p-swarm-derive = { version = "0.27.0", path = "swarm-derive" } libp2p-uds = { version = "0.32.0", path = "transports/uds", optional = true } -# libp2p-wasm-ext = { version = "0.33.0", path = "transports/wasm-ext", default-features = false, optional = true } +libp2p-wasm-ext = { version = "0.33.0", path = "transports/wasm-ext", default-features = false, optional = true } libp2p-yamux = { version = "0.37.0", path = "muxers/yamux", optional = true } multiaddr = { version = "0.14.0" } parking_lot = "0.12.0" @@ -151,7 +151,7 @@ members = [ "transports/tcp", "transports/uds", "transports/websocket", - # "transports/wasm-ext" + "transports/wasm-ext" ] [[example]] diff --git a/transports/wasm-ext/src/lib.rs b/transports/wasm-ext/src/lib.rs index 64deb877858..a8e715291c1 100644 --- a/transports/wasm-ext/src/lib.rs +++ b/transports/wasm-ext/src/lib.rs @@ -32,10 +32,10 @@ //! module. //! -use futures::{future::Ready, prelude::*}; +use futures::{future::Ready, prelude::*, ready, stream::SelectAll}; use libp2p_core::{ connection::Endpoint, - transport::{ListenerEvent, TransportError}, + transport::{ListenerId, TransportError, TransportEvent}, Multiaddr, Transport, }; use parity_send_wrapper::SendWrapper; @@ -147,6 +147,7 @@ pub mod ffi { /// Implementation of `Transport` whose implementation is handled by some FFI. pub struct ExtTransport { inner: SendWrapper, + listeners: SelectAll, } impl ExtTransport { @@ -154,8 +155,10 @@ impl ExtTransport { pub fn new(transport: ffi::Transport) -> Self { ExtTransport { inner: SendWrapper::new(transport), + listeners: SelectAll::new(), } } + fn do_dial( &mut self, addr: Multiaddr, @@ -187,25 +190,13 @@ impl fmt::Debug for ExtTransport { } } -impl Clone for ExtTransport { - fn clone(&self) -> Self { - ExtTransport { - inner: SendWrapper::new(self.inner.clone().into()), - } - } -} - impl Transport for ExtTransport { type Output = Connection; type Error = JsErr; - type Listener = Listen; type ListenerUpgrade = Ready>; type Dial = Dial; - fn listen_on( - &mut self, - addr: Multiaddr, - ) -> Result> { + fn listen_on(&mut self, addr: Multiaddr) -> Result> { let iter = self.inner.listen_on(&addr.to_string()).map_err(|err| { if is_not_supported_error(&err) { TransportError::MultiaddrNotSupported(addr) @@ -213,12 +204,26 @@ impl Transport for ExtTransport { TransportError::Other(JsErr::from(err)) } })?; - - Ok(Listen { + let listener_id = ListenerId::new(); + let listen = Listen { + listener_id, iterator: SendWrapper::new(iter), next_event: None, pending_events: VecDeque::new(), - }) + is_closed: false, + }; + self.listeners.push(listen); + Ok(listener_id) + } + + fn remove_listener(&mut self, id: ListenerId) -> bool { + match self.listeners.iter_mut().find(|l| l.listener_id == id) { + Some(listener) => { + listener.close(Ok(())); + true + } + None => false, + } } fn dial(&mut self, addr: Multiaddr) -> Result> @@ -241,6 +246,16 @@ impl Transport for ExtTransport { fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option { None } + + fn poll( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll> { + match ready!(self.listeners.poll_next_unpin(cx)) { + Some(event) => return Poll::Ready(event), + None => Poll::Pending, + } + } } /// Future that dial a remote through an external transport. @@ -271,27 +286,47 @@ impl Future for Dial { /// Stream that listens for incoming connections through an external transport. #[must_use = "futures do nothing unless polled"] pub struct Listen { + listener_id: ListenerId, /// Iterator of `ListenEvent`s. iterator: SendWrapper, /// Promise that will yield the next `ListenEvent`. next_event: Option>, /// List of events that we are waiting to propagate. - pending_events: VecDeque>, JsErr>>, + pending_events: VecDeque<::Item>, + /// If the iterator is done close the listener. + is_closed: bool, +} + +impl Listen { + /// Report the listener as closed as terminate its stream. + fn close(&mut self, reason: Result<(), JsErr>) { + self.pending_events + .push_back(TransportEvent::ListenerClosed { + listener_id: self.listener_id, + reason, + }); + self.is_closed = true; + } } impl fmt::Debug for Listen { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Listen").finish() + f.debug_tuple("Listen").field(&self.listener_id).finish() } } impl Stream for Listen { - type Item = Result>, JsErr>, JsErr>; + type Item = TransportEvent<::ListenerUpgrade, JsErr>; fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { loop { if let Some(ev) = self.pending_events.pop_front() { - return Poll::Ready(Some(Ok(ev))); + return Poll::Ready(Some(ev)); + } + + if self.is_closed { + // Terminate the stream if the listener closed and all remaining events have been reported. + return Poll::Ready(None); } // Try to fill `self.next_event` if necessary and possible. If we fail, then @@ -309,30 +344,55 @@ impl Stream for Listen { let e = match Future::poll(Pin::new(&mut **next_event), cx) { Poll::Ready(Ok(ev)) => ffi::ListenEvent::from(ev), Poll::Pending => return Poll::Pending, - Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err.into()))), + Poll::Ready(Err(err)) => { + self.close(Err(err.into())); + continue; + } }; self.next_event = None; e } else { - return Poll::Ready(None); + self.close(Ok(())); + continue; }; + let listener_id = self.listener_id; + if let Some(addrs) = event.new_addrs() { for addr in addrs.iter() { - let addr = js_value_to_addr(addr)?; - self.pending_events - .push_back(ListenerEvent::NewAddress(addr)); + match js_value_to_addr(addr) { + Ok(addr) => self.pending_events.push_back(TransportEvent::NewAddress { + listener_id, + listen_addr: addr, + }), + Err(err) => self.pending_events.push_back(TransportEvent::Error { + listener_id, + error: err, + }), + }; } } if let Some(upgrades) = event.new_connections() { for upgrade in upgrades.iter().cloned() { let upgrade: ffi::ConnectionEvent = upgrade.into(); - self.pending_events.push_back(ListenerEvent::Upgrade { - local_addr: upgrade.local_addr().parse()?, - remote_addr: upgrade.observed_addr().parse()?, - upgrade: futures::future::ok(Connection::new(upgrade.connection())), - }); + match upgrade.local_addr().parse().and_then(|local| { + let observed = upgrade.observed_addr().parse()?; + Ok((local, observed)) + }) { + Ok((local_addr, send_back_addr)) => { + self.pending_events.push_back(TransportEvent::Incoming { + listener_id, + local_addr, + send_back_addr, + upgrade: futures::future::ok(Connection::new(upgrade.connection())), + }) + } + Err(err) => self.pending_events.push_back(TransportEvent::Error { + listener_id, + error: err.into(), + }), + } } } @@ -341,8 +401,14 @@ impl Stream for Listen { match js_value_to_addr(addr) { Ok(addr) => self .pending_events - .push_back(ListenerEvent::NewAddress(addr)), - Err(err) => self.pending_events.push_back(ListenerEvent::Error(err)), + .push_back(TransportEvent::AddressExpired { + listener_id, + listen_addr: addr, + }), + Err(err) => self.pending_events.push_back(TransportEvent::Error { + listener_id, + error: err, + }), } } } From eb0397b4a8a1acfac1bfc573784bef1af293c769 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 27 Jun 2022 12:39:24 +0200 Subject: [PATCH 36/47] transports/wasm-ext: fix clippy --- transports/wasm-ext/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transports/wasm-ext/src/lib.rs b/transports/wasm-ext/src/lib.rs index a8e715291c1..e9d57e343b5 100644 --- a/transports/wasm-ext/src/lib.rs +++ b/transports/wasm-ext/src/lib.rs @@ -252,7 +252,7 @@ impl Transport for ExtTransport { cx: &mut Context<'_>, ) -> Poll> { match ready!(self.listeners.poll_next_unpin(cx)) { - Some(event) => return Poll::Ready(event), + Some(event) => Poll::Ready(event), None => Poll::Pending, } } From f28cdb1b93f087dc57ad3e11a38f8fc290374d04 Mon Sep 17 00:00:00 2001 From: Elena Frank Date: Mon, 27 Jun 2022 17:23:20 +0200 Subject: [PATCH 37/47] *: use intra-doc links Co-authored-by: Max Inden --- core/src/either.rs | 2 +- core/src/transport.rs | 6 +++--- core/src/transport/and_then.rs | 2 +- core/src/transport/memory.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/either.rs b/core/src/either.rs index b7f9304a76c..542aa276870 100644 --- a/core/src/either.rs +++ b/core/src/either.rs @@ -345,7 +345,7 @@ impl ProtocolName for EitherName { } #[pin_project(project = EitherTransportProj)] #[derive(Debug, Copy, Clone)] -#[must_use = "futures do nothing unless polled"] +#[must_use = "transports do nothing unless polled"] pub enum EitherTransport { Left(#[pin] A), Right(#[pin] B), diff --git a/core/src/transport.rs b/core/src/transport.rs index d94056b33cc..0d5f7c550b4 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -247,10 +247,10 @@ impl Default for ListenerId { /// Event produced by [`Transport`]s. /// -/// Transports are expected to produce `Incoming` events only for +/// Transports are expected to produce [`TransportEvent::Incoming`] events only for /// listen addresses which have previously been announced via -/// a `NewAddress` event and which have not been invalidated by -/// an `AddressExpired` event yet. +/// a [`TransportEvent::NewAddress`] event and which have not been invalidated by +/// an [`TransportEvent::AddressExpired`] event yet. pub enum TransportEvent { /// A new address is being listened on. NewAddress { diff --git a/core/src/transport/and_then.rs b/core/src/transport/and_then.rs index b4f9c92186f..561a2f281ff 100644 --- a/core/src/transport/and_then.rs +++ b/core/src/transport/and_then.rs @@ -27,7 +27,7 @@ use futures::{future::Either, prelude::*}; use multiaddr::Multiaddr; use std::{error, marker::PhantomPinned, pin::Pin, task::Context, task::Poll}; -/// See the `Transport::and_then` method. +/// See the [`Transport::and_then`] method. #[pin_project::pin_project] #[derive(Debug, Clone)] pub struct AndThen { diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 933ecb1b0df..9113ff2f761 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -323,7 +323,7 @@ pub struct Listener { addr: Multiaddr, /// Receives incoming connections. receiver: ChannelReceiver, - /// Generate `TransportEvent::NewAddress` to inform about our listen address. + /// Generate [`TransportEvent::NewAddress`] to inform about our listen address. tell_listen_addr: bool, } From 4841d81488aae854ad31b1d1b2d9af02af44afdd Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 27 Jun 2022 17:27:21 +0200 Subject: [PATCH 38/47] core/transport: remove unnecessary trait bounds --- core/src/transport.rs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/core/src/transport.rs b/core/src/transport.rs index 0d5f7c550b4..a8864ebddd4 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -114,9 +114,7 @@ pub trait Transport { /// /// Returning an error from the stream is considered fatal. The listener can also report /// non-fatal errors by producing a [`TransportEvent::Error`]. - fn listen_on(&mut self, addr: Multiaddr) -> Result> - where - Self: Sized; + fn listen_on(&mut self, addr: Multiaddr) -> Result>; /// Remove a listener. /// @@ -128,9 +126,7 @@ pub trait Transport { /// /// If [`TransportError::MultiaddrNotSupported`] is returned, it may be desirable to /// try an alternative [`Transport`], if available. - fn dial(&mut self, addr: Multiaddr) -> Result> - where - Self: Sized; + fn dial(&mut self, addr: Multiaddr) -> Result>; /// As [`Transport::dial`] but has the local node act as a listener on the outgoing connection. /// @@ -140,17 +136,13 @@ pub trait Transport { fn dial_as_listener( &mut self, addr: Multiaddr, - ) -> Result> - where - Self: Sized; + ) -> Result>; // TODO: Add docs fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, - ) -> Poll> - where - Self: Sized; + ) -> Poll>; /// Performs a transport-specific mapping of an address `observed` by /// a remote onto a local `listen` address to yield an address for @@ -160,7 +152,7 @@ pub trait Transport { /// Boxes the transport, including custom transport errors. fn boxed(self) -> boxed::Boxed where - Self: Transport + Sized + Send + Unpin + 'static, + Self: Sized + Send + Unpin + 'static, Self::Dial: Send + 'static, Self::ListenerUpgrade: Send + 'static, Self::Error: Send + Sync, From 4e74407d1b1e0d9efcf6cf59727fab0b193eb31d Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 27 Jun 2022 18:03:58 +0200 Subject: [PATCH 39/47] *: rename TransportEvent::Error -> ::ListenerError --- core/src/transport.rs | 18 +++++++++--------- swarm/src/lib.rs | 2 +- transports/tcp/src/lib.rs | 2 +- transports/uds/src/lib.rs | 2 +- transports/wasm-ext/src/lib.rs | 30 ++++++++++++++++++------------ transports/websocket/src/framed.rs | 2 +- 6 files changed, 31 insertions(+), 25 deletions(-) diff --git a/core/src/transport.rs b/core/src/transport.rs index a8864ebddd4..7697d63acd2 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -113,7 +113,7 @@ pub trait Transport { /// and addresses this transport is listening on (cf. [`TransportEvent`]). /// /// Returning an error from the stream is considered fatal. The listener can also report - /// non-fatal errors by producing a [`TransportEvent::Error`]. + /// non-fatal errors by producing a [`TransportEvent::ListenerError`]. fn listen_on(&mut self, addr: Multiaddr) -> Result>; /// Remove a listener. @@ -281,7 +281,7 @@ pub enum TransportEvent { /// /// The listener will continue to be polled for new events and the event /// is for informational purposes only. - Error { + ListenerError { /// The ID of the listener that errored. listener_id: ListenerId, /// The error value. @@ -317,8 +317,8 @@ impl TransportEvent { listen_addr, listener_id, }, - TransportEvent::Error { listener_id, error } => { - TransportEvent::Error { listener_id, error } + TransportEvent::ListenerError { listener_id, error } => { + TransportEvent::ListenerError { listener_id, error } } TransportEvent::ListenerClosed { listener_id, @@ -357,7 +357,7 @@ impl TransportEvent { listen_addr, listener_id, }, - TransportEvent::Error { listener_id, error } => TransportEvent::Error { + TransportEvent::ListenerError { listener_id, error } => TransportEvent::ListenerError { listener_id, error: map_err(error), }, @@ -429,7 +429,7 @@ impl TransportEvent { /// Returns `true` if this is an `Error` listener event. pub fn is_error(&self) -> bool { - matches!(self, TransportEvent::Error { .. }) + matches!(self, TransportEvent::ListenerError { .. }) } /// Try to turn this listener event into the `Error` part. @@ -437,7 +437,7 @@ impl TransportEvent { /// Returns `None` if the event is not actually a `Error`, /// otherwise the error. pub fn into_error(self) -> Option { - if let TransportEvent::Error { error, .. } = self { + if let TransportEvent::ListenerError { error, .. } = self { Some(error) } else { None @@ -481,8 +481,8 @@ impl fmt::Debug for TransportEvent { .field("listener_id", listener_id) .field("reason", reason) .finish(), - TransportEvent::Error { listener_id, error } => f - .debug_struct("TransportEvent::Error") + TransportEvent::ListenerError { listener_id, error } => f + .debug_struct("TransportEvent::ListenerError") .field("listener_id", listener_id) .field("error", error) .finish(), diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 00b3f7a96ff..fa77ab25d33 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -921,7 +921,7 @@ where reason, }); } - TransportEvent::Error { listener_id, error } => { + TransportEvent::ListenerError { listener_id, error } => { self.behaviour.inject_listener_error(listener_id, &error); return Some(SwarmEvent::ListenerError { listener_id, error }); } diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 57255b9e044..57009f6910f 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -559,7 +559,7 @@ where Poll::Ready(Some(Ok(TcpTransportEvent::Error(error)))) => { let id = listener.listener_id; self.listeners.push_front(listener); - return Poll::Ready(TransportEvent::Error { + return Poll::Ready(TransportEvent::ListenerError { listener_id: id, error, }); diff --git a/transports/uds/src/lib.rs b/transports/uds/src/lib.rs index e85d625ed1e..cef165c87df 100644 --- a/transports/uds/src/lib.rs +++ b/transports/uds/src/lib.rs @@ -126,7 +126,7 @@ macro_rules! codegen { listener_id: id, } } - Err(error) => TransportEvent::Error { + Err(error) => TransportEvent::ListenerError { listener_id: id, error, }, diff --git a/transports/wasm-ext/src/lib.rs b/transports/wasm-ext/src/lib.rs index e9d57e343b5..000a633b338 100644 --- a/transports/wasm-ext/src/lib.rs +++ b/transports/wasm-ext/src/lib.rs @@ -365,10 +365,12 @@ impl Stream for Listen { listener_id, listen_addr: addr, }), - Err(err) => self.pending_events.push_back(TransportEvent::Error { - listener_id, - error: err, - }), + Err(err) => self + .pending_events + .push_back(TransportEvent::ListenerError { + listener_id, + error: err, + }), }; } } @@ -388,10 +390,12 @@ impl Stream for Listen { upgrade: futures::future::ok(Connection::new(upgrade.connection())), }) } - Err(err) => self.pending_events.push_back(TransportEvent::Error { - listener_id, - error: err.into(), - }), + Err(err) => self + .pending_events + .push_back(TransportEvent::ListenerError { + listener_id, + error: err.into(), + }), } } } @@ -405,10 +409,12 @@ impl Stream for Listen { listener_id, listen_addr: addr, }), - Err(err) => self.pending_events.push_back(TransportEvent::Error { - listener_id, - error: err, - }), + Err(err) => self + .pending_events + .push_back(TransportEvent::ListenerError { + listener_id, + error: err, + }), } } } diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index 1261d46f1c3..b6b0b663b4b 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -205,7 +205,7 @@ where listen_addr, } } - TransportEvent::Error { listener_id, error } => TransportEvent::Error { + TransportEvent::ListenerError { listener_id, error } => TransportEvent::ListenerError { listener_id, error: Error::Transport(error), }, From b4107244a7a5b498e3319ad81dc996195adca1b0 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Mon, 27 Jun 2022 18:13:28 +0200 Subject: [PATCH 40/47] transport/upgrade: remove unecessary Option --- core/src/transport/upgrade.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/core/src/transport/upgrade.rs b/core/src/transport/upgrade.rs index 6d738af5b99..c872ec955e4 100644 --- a/core/src/transport/upgrade.rs +++ b/core/src/transport/upgrade.rs @@ -498,7 +498,7 @@ where C: AsyncRead + AsyncWrite + Unpin, { future: Pin>, - upgrade: future::Either, (Option, OutboundUpgradeApply)>, + upgrade: future::Either, (PeerId, OutboundUpgradeApply)>, } impl Future for DialUpgradeFuture @@ -527,18 +527,15 @@ where let u = up .take() .expect("DialUpgradeFuture is constructed with Either::Left(Some)."); - future::Either::Right((Some(i), apply_outbound(c, u, upgrade::Version::V1))) + future::Either::Right((i, apply_outbound(c, u, upgrade::Version::V1))) } - future::Either::Right((ref mut i, ref mut up)) => { + future::Either::Right((i, ref mut up)) => { let d = match ready!( Future::poll(Pin::new(up), cx).map_err(TransportUpgradeError::Upgrade) ) { Ok(d) => d, Err(err) => return Poll::Ready(Err(err)), }; - let i = i - .take() - .expect("DialUpgradeFuture polled after completion."); return Poll::Ready(Ok((i, d))); } } @@ -560,7 +557,7 @@ where U: InboundUpgrade>, { future: Pin>, - upgrade: future::Either, (Option, InboundUpgradeApply)>, + upgrade: future::Either, (PeerId, InboundUpgradeApply)>, } impl Future for ListenerUpgradeFuture @@ -589,18 +586,15 @@ where let u = up .take() .expect("ListenerUpgradeFuture is constructed with Either::Left(Some)."); - future::Either::Right((Some(i), apply_inbound(c, u))) + future::Either::Right((i, apply_inbound(c, u))) } - future::Either::Right((ref mut i, ref mut up)) => { + future::Either::Right((i, ref mut up)) => { let d = match ready!(TryFuture::try_poll(Pin::new(up), cx) .map_err(TransportUpgradeError::Upgrade)) { Ok(v) => v, Err(err) => return Poll::Ready(Err(err)), }; - let i = i - .take() - .expect("ListenerUpgradeFuture polled after completion."); return Poll::Ready(Ok((i, d))); } } From 71885ad7415fc4f1265fdc79eaa3c7f715fdbacc Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Tue, 28 Jun 2022 00:41:43 +0200 Subject: [PATCH 41/47] *: clean code, fix docs --- core/src/either.rs | 2 +- core/src/transport.rs | 60 ++++++++++++---------- core/src/transport/memory.rs | 2 +- muxers/mplex/benches/split_send_size.rs | 18 +++---- protocols/ping/src/protocol.rs | 2 +- protocols/relay/src/v2/client/transport.rs | 10 ++++ swarm/src/lib.rs | 6 +-- transports/deflate/tests/test.rs | 4 +- transports/noise/tests/smoke.rs | 2 +- transports/tcp/src/lib.rs | 46 ++++++++--------- transports/uds/src/lib.rs | 2 +- transports/wasm-ext/src/lib.rs | 2 +- transports/websocket/Cargo.toml | 1 - transports/websocket/src/framed.rs | 5 ++ transports/websocket/src/lib.rs | 18 +++---- 15 files changed, 100 insertions(+), 80 deletions(-) diff --git a/core/src/either.rs b/core/src/either.rs index 542aa276870..bce6e05aadf 100644 --- a/core/src/either.rs +++ b/core/src/either.rs @@ -344,7 +344,7 @@ impl ProtocolName for EitherName { } } #[pin_project(project = EitherTransportProj)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug)] #[must_use = "transports do nothing unless polled"] pub enum EitherTransport { Left(#[pin] A), diff --git a/core/src/transport.rs b/core/src/transport.rs index 7697d63acd2..df6e094ed80 100644 --- a/core/src/transport.rs +++ b/core/src/transport.rs @@ -108,12 +108,7 @@ pub trait Transport { /// obtained from [dialing](Transport::dial). type Dial: Future>; - // TODO: fix docs - /// Listens on the given [`Multiaddr`], producing a stream of pending, inbound connections - /// and addresses this transport is listening on (cf. [`TransportEvent`]). - /// - /// Returning an error from the stream is considered fatal. The listener can also report - /// non-fatal errors by producing a [`TransportEvent::ListenerError`]. + /// Listens on the given [`Multiaddr`] for inbound connections. fn listen_on(&mut self, addr: Multiaddr) -> Result>; /// Remove a listener. @@ -138,7 +133,17 @@ pub trait Transport { addr: Multiaddr, ) -> Result>; - // TODO: Add docs + /// Poll for [`TransportEvent`]s. + /// + /// A [`TransportEvent::Incoming`] should be produced whenever a connection is received at the lowest + /// level of the transport stack. The item must be a [`ListenerUpgrade`](Transport::ListenerUpgrade) + /// future that resolves to an [`Output`](Transport::Output) value once all protocol upgrades have + /// been applied. + /// + /// Transports are expected to produce [`TransportEvent::Incoming`] events only for + /// listen addresses which have previously been announced via + /// a [`TransportEvent::NewAddress`] event and which have not been invalidated by + /// an [`TransportEvent::AddressExpired`] event yet. fn poll( self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -238,11 +243,6 @@ impl Default for ListenerId { } /// Event produced by [`Transport`]s. -/// -/// Transports are expected to produce [`TransportEvent::Incoming`] events only for -/// listen addresses which have previously been announced via -/// a [`TransportEvent::NewAddress`] event and which have not been invalidated by -/// an [`TransportEvent::AddressExpired`] event yet. pub enum TransportEvent { /// A new address is being listened on. NewAddress { @@ -290,6 +290,8 @@ pub enum TransportEvent { } impl TransportEvent { + /// In case this [`TransportEvent`] is an upgrade, apply the given function + /// to the upgrade and produce another transport event based the the function's result. pub fn map_upgrade(self, map: impl FnOnce(TUpgr) -> U) -> TransportEvent { match self { TransportEvent::Incoming { @@ -330,6 +332,9 @@ impl TransportEvent { } } + /// In case this [`TransportEvent`] is an [`ListenerError`](TransportEvent::ListenerError), + /// or [`ListenerClosed`](TransportEvent::ListenerClosed) apply the given function to the + /// error and produce another transport event based on the function's result. pub fn map_err(self, map_err: impl FnOnce(TErr) -> E) -> TransportEvent { match self { TransportEvent::Incoming { @@ -371,16 +376,17 @@ impl TransportEvent { } } - /// Returns `true` if this is an `Upgrade` listener event. + /// Returns `true` if this is an [`Incoming`](TransportEvent::Incoming) transport event. pub fn is_upgrade(&self) -> bool { matches!(self, TransportEvent::Incoming { .. }) } - /// Try to turn this listener event into upgrade parts. + /// Try to turn this transport event into the upgrade parts of the + /// incoming connection. /// - /// Returns `None` if the event is not actually an upgrade, + /// Returns `None` if the event is not actually an incoming connection, /// otherwise the upgrade and the remote address. - pub fn into_upgrade(self) -> Option<(TUpgr, Multiaddr)> { + pub fn into_incoming(self) -> Option<(TUpgr, Multiaddr)> { if let TransportEvent::Incoming { upgrade, send_back_addr, @@ -393,14 +399,14 @@ impl TransportEvent { } } - /// Returns `true` if this is a `NewAddress` listener event. + /// Returns `true` if this is a [`TransportEvent::NewAddress`]. pub fn is_new_address(&self) -> bool { matches!(self, TransportEvent::NewAddress { .. }) } - /// Try to turn this listener event into the `NewAddress` part. + /// Try to turn this transport event into the new `Multiaddr`. /// - /// Returns `None` if the event is not actually a `NewAddress`, + /// Returns `None` if the event is not actually a [`TransportEvent::NewAddress`], /// otherwise the address. pub fn into_new_address(self) -> Option { if let TransportEvent::NewAddress { listen_addr, .. } = self { @@ -410,14 +416,14 @@ impl TransportEvent { } } - /// Returns `true` if this is an `AddressExpired` listener event. + /// Returns `true` if this is an [`TransportEvent::AddressExpired`]. pub fn is_address_expired(&self) -> bool { matches!(self, TransportEvent::AddressExpired { .. }) } - /// Try to turn this listener event into the `AddressExpired` part. + /// Try to turn this transport event into the expire `Multiaddr`. /// - /// Returns `None` if the event is not actually a `AddressExpired`, + /// Returns `None` if the event is not actually a [`TransportEvent::AddressExpired`], /// otherwise the address. pub fn into_address_expired(self) -> Option { if let TransportEvent::AddressExpired { listen_addr, .. } = self { @@ -427,16 +433,16 @@ impl TransportEvent { } } - /// Returns `true` if this is an `Error` listener event. - pub fn is_error(&self) -> bool { + /// Returns `true` if this is an [`TransportEvent::ListenerError`] transport event. + pub fn is_listener_error(&self) -> bool { matches!(self, TransportEvent::ListenerError { .. }) } - /// Try to turn this listener event into the `Error` part. + /// Try to turn this transport event into the listener error. /// - /// Returns `None` if the event is not actually a `Error`, + /// Returns `None` if the event is not actually a [`TransportEvent::ListenerError`]`, /// otherwise the error. - pub fn into_error(self) -> Option { + pub fn into_listener_error(self) -> Option { if let TransportEvent::ListenerError { error, .. } = self { Some(error) } else { diff --git a/core/src/transport/memory.rs b/core/src/transport/memory.rs index 9113ff2f761..8121bfc895a 100644 --- a/core/src/transport/memory.rs +++ b/core/src/transport/memory.rs @@ -544,7 +544,7 @@ mod tests { t1.listen_on(t1_addr.clone()).unwrap(); let upgrade = loop { let event = t1.select_next_some().await; - if let Some(upgrade) = event.into_upgrade() { + if let Some(upgrade) = event.into_incoming() { break upgrade; } }; diff --git a/muxers/mplex/benches/split_send_size.rs b/muxers/mplex/benches/split_send_size.rs index 7e3dab51b53..f5bf771d1ab 100644 --- a/muxers/mplex/benches/split_send_size.rs +++ b/muxers/mplex/benches/split_send_size.rs @@ -59,13 +59,13 @@ fn prepare(c: &mut Criterion) { let tcp_addr = multiaddr![Ip4(std::net::Ipv4Addr::new(127, 0, 0, 1)), Tcp(0u16)]; for &size in BENCH_SIZES.iter() { tcp.throughput(Throughput::Bytes(payload.len() as u64)); - let mut receiver_trans = tcp_transport(size); - let mut sender_trans = tcp_transport(size); + let mut receiver_transport = tcp_transport(size); + let mut sender_transport = tcp_transport(size); tcp.bench_function(format!("{}", size), |b| { b.iter(|| { run( - black_box(&mut receiver_trans), - black_box(&mut sender_trans), + black_box(&mut receiver_transport), + black_box(&mut sender_transport), black_box(&payload), black_box(&tcp_addr), ) @@ -78,13 +78,13 @@ fn prepare(c: &mut Criterion) { let mem_addr = multiaddr![Memory(0u64)]; for &size in BENCH_SIZES.iter() { mem.throughput(Throughput::Bytes(payload.len() as u64)); - let mut receiver_trans = mem_transport(size); - let mut sender_trans = mem_transport(size); + let mut receiver_transport = mem_transport(size); + let mut sender_transport = mem_transport(size); mem.bench_function(format!("{}", size), |b| { b.iter(|| { run( - black_box(&mut receiver_trans), - black_box(&mut sender_trans), + black_box(&mut receiver_transport), + black_box(&mut sender_transport), black_box(&payload), black_box(&mem_addr), ) @@ -134,7 +134,7 @@ fn run( } } } - _ => panic!("Unexpected listener event"), + _ => panic!("Unexpected transport event"), } } }; diff --git a/protocols/ping/src/protocol.rs b/protocols/ping/src/protocol.rs index 390823ec412..499c5ad4a0f 100644 --- a/protocols/ping/src/protocol.rs +++ b/protocols/ping/src/protocol.rs @@ -137,7 +137,7 @@ mod tests { async_std::task::spawn(async move { let transport_event = transport.next().await.unwrap(); - let (listener_upgrade, _) = transport_event.into_upgrade().unwrap(); + let (listener_upgrade, _) = transport_event.into_incoming().unwrap(); let conn = listener_upgrade.await.unwrap(); recv_ping(conn).await.unwrap(); }); diff --git a/protocols/relay/src/v2/client/transport.rs b/protocols/relay/src/v2/client/transport.rs index d5a71e54b3e..18e4a989597 100644 --- a/protocols/relay/src/v2/client/transport.rs +++ b/protocols/relay/src/v2/client/transport.rs @@ -320,12 +320,21 @@ fn parse_relayed_multiaddr( pub struct RelayListener { listener_id: ListenerId, + /// Queue of events to report when polled. queued_events: VecDeque<::Item>, + /// Channel for messages from the behaviour [`Handler`][super::handler::Handler]. from_behaviour: mpsc::Receiver, + /// The listener can be closed either manually with [`Transport::remove_listener`] or if + /// the sender side of the `from_behaviour` channel is dropped. is_closed: bool, } impl RelayListener { + /// Close the listener. + /// + /// This will create a [`TransportEvent::ListenerClosed`] event + /// and terminate the stream once all remaining events in queue have + /// been reported. fn close(&mut self, reason: Result<(), RelayError>) { self.queued_events .push_back(TransportEvent::ListenerClosed { @@ -346,6 +355,7 @@ impl Stream for RelayListener { } if self.is_closed { + // Terminate the stream if the listener closed and all remaining events have been reported. return Poll::Ready(None); } diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index fa77ab25d33..f32c2df56bf 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -258,7 +258,7 @@ pub struct Swarm where TBehaviour: NetworkBehaviour, { - /// Listeners for incoming connections. + /// [`Transport`] for dialing remote peers and listening for incoming connection. transport: transport::Boxed<(PeerId, StreamMuxerBox)>, /// The nodes currently active. @@ -274,7 +274,7 @@ where /// List of protocols that the behaviour says it supports. supported_protocols: SmallVec<[Vec; 16]>, - /// List of multiaddresses we're listening on. + /// Multiaddresses that our listeners are listening on, listened_addrs: HashMap>, /// List of multiaddresses we're listening on, after account for external IP addresses and @@ -2104,7 +2104,7 @@ mod tests { break; } Either::Left(_) => { - panic!("Unexpected listener event.") + panic!("Unexpected transport event.") } Either::Right((e, _)) => { panic!("Expect swarm to not emit any event {:?}", e) diff --git a/transports/deflate/tests/test.rs b/transports/deflate/tests/test.rs index e718fc0075d..af5ffc3529a 100644 --- a/transports/deflate/tests/test.rs +++ b/transports/deflate/tests/test.rs @@ -56,7 +56,7 @@ async fn run(message1: Vec) { }) .boxed() }; - let mut listener_trans = new_transport(); + let mut listener_transport = new_transport(); listener_trans .listen_on("/ip4/0.0.0.0/tcp/0".parse().expect("multiaddr")) .expect("listener"); @@ -90,7 +90,7 @@ async fn run(message1: Vec) { conn.close().await.expect("close") }); - let mut dialer_trans = new_transport(); + let mut dialer_transport = new_transport(); let mut conn = dialer_trans .dial(listen_addr) .expect("dialer") diff --git a/transports/noise/tests/smoke.rs b/transports/noise/tests/smoke.rs index 0945105d211..0148d03b4d6 100644 --- a/transports/noise/tests/smoke.rs +++ b/transports/noise/tests/smoke.rs @@ -281,7 +281,7 @@ fn run( .next() .await .expect("some event") - .into_upgrade() + .into_incoming() .expect("listener upgrade") .0 .await diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 57009f6910f..df981cec3b2 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -312,7 +312,7 @@ where /// The `TcpListenStream` struct contains a stream that we want to be pinned. Since the `VecDeque` /// can be resized, the only way is to use a `Pin>`. listeners: VecDeque>>>, - /// Pending listeners events to return from [`GenTcpTransport::poll`]. + /// Pending transport events to return from [`GenTcpTransport::poll`]. pending_events: VecDeque::ListenerUpgrade, io::Error>>, } @@ -506,7 +506,7 @@ where } } - // TODO: docs + /// Poll all listeners. fn poll( mut self: Pin<&mut Self>, cx: &mut Context<'_>, @@ -526,7 +526,7 @@ where break; } } - Poll::Ready(Some(Ok(TcpTransportEvent::Upgrade { + Poll::Ready(Some(Ok(TcpListenerEvent::Upgrade { upgrade, local_addr, remote_addr, @@ -540,7 +540,7 @@ where send_back_addr: remote_addr, }); } - Poll::Ready(Some(Ok(TcpTransportEvent::NewAddress(a)))) => { + Poll::Ready(Some(Ok(TcpListenerEvent::NewAddress(a)))) => { let id = listener.listener_id; self.listeners.push_front(listener); return Poll::Ready(TransportEvent::NewAddress { @@ -548,7 +548,7 @@ where listen_addr: a, }); } - Poll::Ready(Some(Ok(TcpTransportEvent::AddressExpired(a)))) => { + Poll::Ready(Some(Ok(TcpListenerEvent::AddressExpired(a)))) => { let id = listener.listener_id; self.listeners.push_front(listener); return Poll::Ready(TransportEvent::AddressExpired { @@ -556,7 +556,7 @@ where listen_addr: a, }); } - Poll::Ready(Some(Ok(TcpTransportEvent::Error(error)))) => { + Poll::Ready(Some(Ok(TcpListenerEvent::Error(error)))) => { let id = listener.listener_id; self.listeners.push_front(listener); return Poll::Ready(TransportEvent::ListenerError { @@ -578,15 +578,15 @@ where } } } - // We register the current task to be woken up if a new listener is added. Poll::Pending } } +/// Event produced by a [`TcpListenStream`]. #[derive(Debug)] -pub enum TcpTransportEvent { - /// The transport is listening on a new additional [`Multiaddr`]. +pub enum TcpListenerEvent { + /// The listener is listening on a new additional [`Multiaddr`]. NewAddress(Multiaddr), /// An upgrade, consisting of the upgrade future, the listener address and the remote address. Upgrade { @@ -662,8 +662,8 @@ impl TcpListenStream where T: Provider, { - /// Constructs a `TcpListenStream` for incoming connections around - /// the given listener. + /// Constructs a [`TcpListenStream`] for incoming connections around + /// the given [`TcpListener`]. fn new( listener_id: ListenerId, listener: TcpListener, @@ -737,7 +737,7 @@ where T::Stream: Unpin, T::IfWatcher: Unpin, { - type Item = Result, io::Error>; + type Item = Result, io::Error>; fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { let me = Pin::into_inner(self); @@ -758,7 +758,7 @@ where }; *if_watch = IfWatch::Pending(T::if_watcher()); me.pause = Some(Delay::new(me.sleep_on_error)); - return Poll::Ready(Some(Ok(TcpTransportEvent::Error(err)))); + return Poll::Ready(Some(Ok(TcpListenerEvent::Error(err)))); } }, // Consume all events for up/down interface changes. @@ -773,7 +773,7 @@ where log::debug!("New listen address: {}", ma); me.port_reuse.register(ip, me.listen_addr.port()); return Poll::Ready(Some(Ok( - TcpTransportEvent::NewAddress(ma), + TcpListenerEvent::NewAddress(ma), ))); } } @@ -785,7 +785,7 @@ where log::debug!("Expired listen address: {}", ma); me.port_reuse.unregister(ip, me.listen_addr.port()); return Poll::Ready(Some(Ok( - TcpTransportEvent::AddressExpired(ma), + TcpListenerEvent::AddressExpired(ma), ))); } } @@ -795,7 +795,7 @@ where err }; me.pause = Some(Delay::new(me.sleep_on_error)); - return Poll::Ready(Some(Ok(TcpTransportEvent::Error(err)))); + return Poll::Ready(Some(Ok(TcpListenerEvent::Error(err)))); } } } @@ -806,7 +806,7 @@ where InAddr::One { addr, out } => { if let Some(multiaddr) = out.take() { me.port_reuse.register(*addr, me.listen_addr.port()); - return Poll::Ready(Some(Ok(TcpTransportEvent::NewAddress(multiaddr)))); + return Poll::Ready(Some(Ok(TcpListenerEvent::NewAddress(multiaddr)))); } } } @@ -829,7 +829,7 @@ where // These errors are non-fatal for the listener stream. log::error!("error accepting incoming connection: {}", e); me.pause = Some(Delay::new(me.sleep_on_error)); - return Poll::Ready(Some(Ok(TcpTransportEvent::Error(e)))); + return Poll::Ready(Some(Ok(TcpListenerEvent::Error(e)))); } }; @@ -839,7 +839,7 @@ where log::debug!("Incoming connection from {} at {}", remote_addr, local_addr); - return Poll::Ready(Some(Ok(TcpTransportEvent::Upgrade { + return Poll::Ready(Some(Ok(TcpListenerEvent::Upgrade { upgrade: future::ok(incoming.stream), local_addr, remote_addr, @@ -960,7 +960,7 @@ mod tests { upgrade.write_all(&[4, 5, 6]).await.unwrap(); return; } - e => panic!("Unexpected listener event: {:?}", e), + e => panic!("Unexpected transport event: {:?}", e), } } } @@ -1148,7 +1148,7 @@ mod tests { socket.read_exact(&mut buf).await.unwrap(); assert_eq!(buf, [4, 5, 6]); } - e => panic!("Unexpected listener event: {:?}", e), + e => panic!("Unexpected transport event: {:?}", e), } } @@ -1214,10 +1214,10 @@ mod tests { assert_eq!(addr1, addr2); return; } - e => panic!("Unexpected listener event: {:?}", e), + e => panic!("Unexpected transport event: {:?}", e), } } - e => panic!("Unexpected listener event: {:?}", e), + e => panic!("Unexpected transport event: {:?}", e), } } diff --git a/transports/uds/src/lib.rs b/transports/uds/src/lib.rs index cef165c87df..492f1afb029 100644 --- a/transports/uds/src/lib.rs +++ b/transports/uds/src/lib.rs @@ -307,7 +307,7 @@ mod tests { let (sock, _addr) = transport .select_next_some() .await - .into_upgrade() + .into_incoming() .expect("incoming stream"); let mut sock = sock.await.unwrap(); diff --git a/transports/wasm-ext/src/lib.rs b/transports/wasm-ext/src/lib.rs index 000a633b338..820c35c36c8 100644 --- a/transports/wasm-ext/src/lib.rs +++ b/transports/wasm-ext/src/lib.rs @@ -298,7 +298,7 @@ pub struct Listen { } impl Listen { - /// Report the listener as closed as terminate its stream. + /// Report the listener as closed and terminate its stream. fn close(&mut self, reason: Result<(), JsErr>) { self.pending_events .push_back(TransportEvent::ListenerClosed { diff --git a/transports/websocket/Cargo.toml b/transports/websocket/Cargo.toml index a12a0dee353..624fc0cbe4f 100644 --- a/transports/websocket/Cargo.toml +++ b/transports/websocket/Cargo.toml @@ -17,7 +17,6 @@ futures = "0.3.1" libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } log = "0.4.8" parking_lot = "0.12.0" -pin-project = "1.0.10" quicksink = "0.1" rw-stream-sink = { version = "0.3.0", path = "../../misc/rw-stream-sink" } soketto = { version = "0.7.0", features = ["deflate"] } diff --git a/transports/websocket/src/framed.rs b/transports/websocket/src/framed.rs index b6b0b663b4b..65b4db93fd6 100644 --- a/transports/websocket/src/framed.rs +++ b/transports/websocket/src/framed.rs @@ -53,6 +53,10 @@ pub struct WsConfig { tls_config: tls::Config, max_redirects: u8, use_deflate: bool, + /// Websocket protocol of the inner listener. + /// + /// This is the suffix of the address provided in `listen_on`. + /// Can only be [`Protocol::Ws`] or [`Protocol::Wss`]. listener_protos: HashMap>, } @@ -180,6 +184,7 @@ where listener_id, mut listen_addr, } => { + // Append the ws / wss protocol back to the inner address. let proto = self .listener_protos .get(&listener_id) diff --git a/transports/websocket/src/lib.rs b/transports/websocket/src/lib.rs index 1897b64a2a0..bf75e389648 100644 --- a/transports/websocket/src/lib.rs +++ b/transports/websocket/src/lib.rs @@ -42,13 +42,11 @@ use std::{ /// A Websocket transport. #[derive(Debug)] -#[pin_project::pin_project] pub struct WsConfig where T: Transport, T::Output: AsyncRead + AsyncWrite + Send + Unpin + 'static, { - #[pin] transport: libp2p_core::transport::map::Map, WrapperFn>, } @@ -147,10 +145,10 @@ where } fn poll( - self: Pin<&mut Self>, + mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - self.project().transport.poll(cx) + Pin::new(&mut self.transport).poll(cx) } } @@ -236,11 +234,12 @@ mod tests { futures::executor::block_on(connect(a)) } - async fn connect(listen_addr: Multiaddr) { - let new_ws_config = - || WsConfig::new(tcp::TcpTransport::new(tcp::GenTcpConfig::default())).boxed(); + fn new_ws_config() -> WsConfig { + WsConfig::new(tcp::TcpTransport::new(tcp::GenTcpConfig::default())) + } - let mut ws_config = new_ws_config(); + async fn connect(listen_addr: Multiaddr) { + let mut ws_config = new_ws_config().boxed(); ws_config.listen_on(listen_addr).expect("listener"); let addr = ws_config @@ -256,13 +255,14 @@ mod tests { let inbound = async move { let (conn, _addr) = ws_config .select_next_some() - .map(|ev| ev.into_upgrade()) + .map(|ev| ev.into_incoming()) .await .unwrap(); conn.await }; let outbound = new_ws_config() + .boxed() .dial(addr.with(Protocol::P2p(PeerId::random().into()))) .unwrap(); From 2b3402c39b6465096e070a24e9422a943868cb80 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Tue, 28 Jun 2022 00:58:13 +0200 Subject: [PATCH 42/47] transports/wasm-ext: rm leftover Self: Sized bound --- transports/wasm-ext/src/lib.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/transports/wasm-ext/src/lib.rs b/transports/wasm-ext/src/lib.rs index 820c35c36c8..bb1e3ea0653 100644 --- a/transports/wasm-ext/src/lib.rs +++ b/transports/wasm-ext/src/lib.rs @@ -226,20 +226,14 @@ impl Transport for ExtTransport { } } - fn dial(&mut self, addr: Multiaddr) -> Result> - where - Self: Sized, - { + fn dial(&mut self, addr: Multiaddr) -> Result> { self.do_dial(addr, Endpoint::Dialer) } fn dial_as_listener( &mut self, addr: Multiaddr, - ) -> Result> - where - Self: Sized, - { + ) -> Result> { self.do_dial(addr, Endpoint::Listener) } From 469515e656865201af142aead86289bde3cd1e74 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Tue, 28 Jun 2022 01:08:59 +0200 Subject: [PATCH 43/47] *: fix missing renames --- core/tests/transport_upgrade.rs | 2 +- muxers/mplex/tests/async_write.rs | 2 +- muxers/mplex/tests/two_peers.rs | 6 +++--- protocols/identify/src/protocol.rs | 2 +- transports/deflate/tests/test.rs | 10 +++++----- transports/plaintext/tests/smoke.rs | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/tests/transport_upgrade.rs b/core/tests/transport_upgrade.rs index f52cf2cb3d6..ecba64dfb2f 100644 --- a/core/tests/transport_upgrade.rs +++ b/core/tests/transport_upgrade.rs @@ -125,7 +125,7 @@ fn upgrade_pipeline() { let server = async move { loop { let (upgrade, _send_back_addr) = - match listener_transport.select_next_some().await.into_upgrade() { + match listener_transport.select_next_some().await.into_incoming() { Some(u) => u, None => continue, }; diff --git a/muxers/mplex/tests/async_write.rs b/muxers/mplex/tests/async_write.rs index 9c395f21c0e..9dbda1a198d 100644 --- a/muxers/mplex/tests/async_write.rs +++ b/muxers/mplex/tests/async_write.rs @@ -54,7 +54,7 @@ fn async_write() { .next() .await .expect("some event") - .into_upgrade() + .into_incoming() .unwrap() .0 .await diff --git a/muxers/mplex/tests/two_peers.rs b/muxers/mplex/tests/two_peers.rs index 5f75f6d0a25..4283452fe07 100644 --- a/muxers/mplex/tests/two_peers.rs +++ b/muxers/mplex/tests/two_peers.rs @@ -54,7 +54,7 @@ fn client_to_server_outbound() { .next() .await .expect("some event") - .into_upgrade() + .into_incoming() .unwrap() .0 .await @@ -124,7 +124,7 @@ fn client_to_server_inbound() { .next() .await .expect("some event") - .into_upgrade() + .into_incoming() .unwrap() .0 .await @@ -193,7 +193,7 @@ fn protocol_not_match() { .next() .await .expect("some event") - .into_upgrade() + .into_incoming() .unwrap() .0 .await diff --git a/protocols/identify/src/protocol.rs b/protocols/identify/src/protocol.rs index 3b86baded51..bf543af47a3 100644 --- a/protocols/identify/src/protocol.rs +++ b/protocols/identify/src/protocol.rs @@ -322,7 +322,7 @@ mod tests { .next() .await .expect("some event") - .into_upgrade() + .into_incoming() .unwrap() .0 .await diff --git a/transports/deflate/tests/test.rs b/transports/deflate/tests/test.rs index af5ffc3529a..06d91ddd808 100644 --- a/transports/deflate/tests/test.rs +++ b/transports/deflate/tests/test.rs @@ -57,11 +57,11 @@ async fn run(message1: Vec) { .boxed() }; let mut listener_transport = new_transport(); - listener_trans + listener_transport .listen_on("/ip4/0.0.0.0/tcp/0".parse().expect("multiaddr")) .expect("listener"); - let listen_addr = listener_trans + let listen_addr = listener_transport .next() .await .expect("some event") @@ -71,12 +71,12 @@ async fn run(message1: Vec) { let message2 = message1.clone(); let listener_task = async_std::task::spawn(async move { - let mut conn = listener_trans + let mut conn = listener_transport .filter(|e| future::ready(e.is_upgrade())) .next() .await .expect("some event") - .into_upgrade() + .into_incoming() .expect("upgrade") .0 .await @@ -91,7 +91,7 @@ async fn run(message1: Vec) { }); let mut dialer_transport = new_transport(); - let mut conn = dialer_trans + let mut conn = dialer_transport .dial(listen_addr) .expect("dialer") .await diff --git a/transports/plaintext/tests/smoke.rs b/transports/plaintext/tests/smoke.rs index 0f14f4f2ae6..ea62f0a9dfa 100644 --- a/transports/plaintext/tests/smoke.rs +++ b/transports/plaintext/tests/smoke.rs @@ -103,7 +103,7 @@ fn variable_msg_length() { .next() .await .expect("some event") - .into_upgrade() + .into_incoming() .expect("no error") .0 .await From 83a13dded6dcaee1d1e8cbb958689a2fd9dcfd09 Mon Sep 17 00:00:00 2001 From: Elena Frank Date: Tue, 28 Jun 2022 10:19:09 +0200 Subject: [PATCH 44/47] transports/tcp: rm unneeded dependencies, fix docs Co-authored-by: Max Inden --- transports/tcp/Cargo.toml | 2 -- transports/tcp/src/lib.rs | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/transports/tcp/Cargo.toml b/transports/tcp/Cargo.toml index 7e1f009e3c9..e72f3eaee56 100644 --- a/transports/tcp/Cargo.toml +++ b/transports/tcp/Cargo.toml @@ -20,8 +20,6 @@ ipnet = "2.0.0" libc = "0.2.80" libp2p-core = { version = "0.34.0", path = "../../core", default-features = false } log = "0.4.11" -pin-project = "1.0.0" -smallvec = "1.6.1" socket2 = { version = "0.4.0", features = ["all"] } tokio-crate = { package = "tokio", version = "1.19.0", default-features = false, features = ["net"], optional = true } diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index df981cec3b2..52012d49259 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -235,7 +235,7 @@ impl GenTcpConfig { /// [`GenTcpTransport`] keeps track of the listen socket addresses as they /// are reported by polling it. It is possible to listen on multiple /// addresses, enabling port reuse for each, knowing exactly which listen - /// address is reused when dialing with a specific `GenTcpTransport`, as in the + /// address is reused when dialing with a specific [`GenTcpTransport`], as in the /// following example: /// /// ```no_run @@ -281,7 +281,7 @@ impl GenTcpConfig { /// case, one is chosen whose IP protocol version and loopback status is the /// same as that of the remote address. Consequently, for maximum control of /// the local listening addresses and ports that are used for outgoing - /// connections, a new `GenTcpTransport` should be created for each listening + /// connections, a new [`GenTcpTransport`] should be created for each listening /// socket, avoiding the use of wildcard addresses which bind a socket to /// all network interfaces. /// From 3d4e0aa5bd0ab0786c466a753002c7553182f493 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Tue, 28 Jun 2022 10:20:24 +0200 Subject: [PATCH 45/47] transports/tcp: remove oudated comment --- transports/tcp/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/transports/tcp/src/lib.rs b/transports/tcp/src/lib.rs index 52012d49259..981c896bcb5 100644 --- a/transports/tcp/src/lib.rs +++ b/transports/tcp/src/lib.rs @@ -578,7 +578,6 @@ where } } } - // We register the current task to be woken up if a new listener is added. Poll::Pending } } From 8600be7236022794212b72a9acbf6fada34450c9 Mon Sep 17 00:00:00 2001 From: elenaf9 Date: Tue, 28 Jun 2022 10:59:08 +0200 Subject: [PATCH 46/47] *: add changelog entries --- core/CHANGELOG.md | 5 +++++ protocols/relay/CHANGELOG.md | 4 ++++ swarm/CHANGELOG.md | 3 +++ transports/tcp/CHANGELOG.md | 7 +++++++ transports/uds/CHANGELOG.md | 4 ++++ transports/wasm-ext/CHANGELOG.md | 4 ++++ transports/websocket/CHANGELOG.md | 4 ++++ 7 files changed, 31 insertions(+) diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md index 7bea0f3f35a..a3d91a680e1 100644 --- a/core/CHANGELOG.md +++ b/core/CHANGELOG.md @@ -5,9 +5,14 @@ in favor of forcing `StreamMuxer::Substream` to implement `AsyncRead + AsyncWrite`. See [PR 2707]. - Replace `Into` bound on `StreamMuxer::Error` with `std::error::Error`. See [PR 2710]. +- Remove the concept of individual `Transport::Listener` streams from `Transport`. + Instead the `Transport` is polled directly via `Transport::poll`. The + `Transport` is now responsible for driving its listeners. See [PR 2652]. + [PR 2691]: https://github.com/libp2p/rust-libp2p/pull/2691 [PR 2707]: https://github.com/libp2p/rust-libp2p/pull/2707 [PR 2710]: https://github.com/libp2p/rust-libp2p/pull/2710 +[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 # 0.33.0 diff --git a/protocols/relay/CHANGELOG.md b/protocols/relay/CHANGELOG.md index 2f5930201aa..50f6a771f40 100644 --- a/protocols/relay/CHANGELOG.md +++ b/protocols/relay/CHANGELOG.md @@ -6,7 +6,11 @@ - Do not duplicate the p2p/xxx component with the relay PeerId when a client requests a reservation. See [PR 2701]. +- Drive the `RelayListener`s within the `ClientTransport`. Add `Transport::poll` and `Transport::remove_listener` + for `ClientTransport`. See [PR 2652]. + [PR 2701]: https://github.com/libp2p/rust-libp2p/pull/2701/ +[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 # 0.9.1 diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 463d406add7..300e4e96a09 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -4,7 +4,10 @@ - Extend log message when exceeding inbound negotiating streams with peer ID and limit. See [PR 2716]. +- Remove `connection::ListenersStream` and poll the `Transport` directly. See [PR 2652]. + [PR 2716]: https://github.com/libp2p/rust-libp2p/pull/2716/ +[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 # 0.36.1 diff --git a/transports/tcp/CHANGELOG.md b/transports/tcp/CHANGELOG.md index 1d119005696..dadec7b0377 100644 --- a/transports/tcp/CHANGELOG.md +++ b/transports/tcp/CHANGELOG.md @@ -6,6 +6,13 @@ establishment errors early. See also [PR 2458] for the related async-io change. +- Split `GenTcpConfig` into `GenTcpConfig` and `GenTcpTransport`. Drive the `TcpListenStream`s + within the `GenTcpTransport`. Add `Transport::poll` and `Transport::remove_listener` + for `GenTcpTransport`. See [PR 2652]. + +[PR 2701]: https://github.com/libp2p/rust-libp2p/pull/2701/ +[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 + # 0.33.0 - Update to `libp2p-core` `v0.33.0`. diff --git a/transports/uds/CHANGELOG.md b/transports/uds/CHANGELOG.md index affbd60a156..e122885226f 100644 --- a/transports/uds/CHANGELOG.md +++ b/transports/uds/CHANGELOG.md @@ -2,6 +2,10 @@ - Update dependencies. - Update to `libp2p-core` `v0.34.0`. +- Add `Transport::poll` and `Transport::remove_listener` and remove `Transport::Listener` for + `UdsConfig` Drive listener streams in `UdsConfig` directly. See [PR 2652]. + +[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 # 0.32.0 [2022-01-27] diff --git a/transports/wasm-ext/CHANGELOG.md b/transports/wasm-ext/CHANGELOG.md index af2c271a42d..05a188697d6 100644 --- a/transports/wasm-ext/CHANGELOG.md +++ b/transports/wasm-ext/CHANGELOG.md @@ -1,6 +1,10 @@ # 0.34.0 [unreleased] - Update to `libp2p-core` `v0.34.0`. +- Add `Transport::poll` and `Transport::remove_listener` and remove `Transport::Listener` + for `ExtTransport`. Drive the `Listen` streams within `ExtTransport`. See [PR 2652]. + +[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 # 0.33.0 diff --git a/transports/websocket/CHANGELOG.md b/transports/websocket/CHANGELOG.md index 1594580f119..9eca77aa0ce 100644 --- a/transports/websocket/CHANGELOG.md +++ b/transports/websocket/CHANGELOG.md @@ -1,6 +1,10 @@ # 0.36.0 [unreleased] - Update to `libp2p-core` `v0.34.0`. +- Add `Transport::poll` and `Transport::remove_listener` and remove `Transport::Listener` + for `WsConfig`. See [PR 2652]. + +[PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 # 0.35.0 From 03c5170a505f71a29d513df6bd7f1a930faf6102 Mon Sep 17 00:00:00 2001 From: Elena Frank Date: Fri, 1 Jul 2022 15:30:37 +0200 Subject: [PATCH 47/47] transports/tcp/CHANGELOG: remove wrong PR ref --- transports/tcp/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/transports/tcp/CHANGELOG.md b/transports/tcp/CHANGELOG.md index dadec7b0377..f479cdef9e4 100644 --- a/transports/tcp/CHANGELOG.md +++ b/transports/tcp/CHANGELOG.md @@ -10,7 +10,6 @@ within the `GenTcpTransport`. Add `Transport::poll` and `Transport::remove_listener` for `GenTcpTransport`. See [PR 2652]. -[PR 2701]: https://github.com/libp2p/rust-libp2p/pull/2701/ [PR 2652]: https://github.com/libp2p/rust-libp2p/pull/2652 # 0.33.0