mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-26 16:21:39 +00:00
core/src/transport: Add Transport::dial_as_listener
(#2363)
Allows `NetworkBehaviour` implementations to dial a peer, but instruct the dialed connection to be upgraded as if it were the listening endpoint. This is needed when establishing direct connections through NATs and/or Firewalls (hole punching). When hole punching via TCP (QUIC is different but similar) both ends dial the other at the same time resulting in a simultaneously opened TCP connection. To disambiguate who is the dialer and who the listener there are two options: 1. Use the Simultaneous Open Extension of Multistream Select. See [sim-open] specification and [sim-open-rust] Rust implementation. 2. Disambiguate the role (dialer or listener) based on the role within the DCUtR [dcutr] protocol. More specifically the node initiating the DCUtR process will act as a listener and the other as a dialer. This commit enables (2), i.e. enables the DCUtR protocol to specify the role used once the connection is established. While on the positive side (2) requires one round trip less than (1), on the negative side (2) only works for coordinated simultaneous dials. I.e. when a simultaneous dial happens by chance, and not coordinated via DCUtR, the connection attempt fails when only (2) is in place. [sim-open]: https://github.com/libp2p/specs/blob/master/connections/simopen.md [sim-open-rust]: https://github.com/libp2p/rust-libp2p/pull/2066 [dcutr]: https://github.com/libp2p/specs/blob/master/relay/DCUtR.md
This commit is contained in:
@ -97,7 +97,10 @@ pub enum PendingPoint {
|
||||
/// There is no single address associated with the Dialer of a pending
|
||||
/// connection. Addresses are dialed in parallel. Only once the first dial
|
||||
/// is successful is the address of the connection known.
|
||||
Dialer,
|
||||
Dialer {
|
||||
/// Same as [`ConnectedPoint::Dialer`] `role_override`.
|
||||
role_override: Endpoint,
|
||||
},
|
||||
/// The socket comes from a listener.
|
||||
Listener {
|
||||
/// Local connection address.
|
||||
@ -110,7 +113,7 @@ pub enum PendingPoint {
|
||||
impl From<ConnectedPoint> for PendingPoint {
|
||||
fn from(endpoint: ConnectedPoint) -> Self {
|
||||
match endpoint {
|
||||
ConnectedPoint::Dialer { .. } => PendingPoint::Dialer,
|
||||
ConnectedPoint::Dialer { role_override, .. } => PendingPoint::Dialer { role_override },
|
||||
ConnectedPoint::Listener {
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
@ -129,6 +132,27 @@ pub enum ConnectedPoint {
|
||||
Dialer {
|
||||
/// Multiaddress that was successfully dialed.
|
||||
address: Multiaddr,
|
||||
/// Whether the role of the local node on the connection should be
|
||||
/// overriden. I.e. whether the local node should act as a listener on
|
||||
/// the outgoing connection.
|
||||
///
|
||||
/// This option is needed for NAT and firewall hole punching.
|
||||
///
|
||||
/// - [`Endpoint::Dialer`] represents the default non-overriding option.
|
||||
///
|
||||
/// - [`Endpoint::Listener`] represents the overriding option.
|
||||
/// Realization depends on the transport protocol. E.g. in the case of
|
||||
/// TCP, both endpoints dial each other, resulting in a _simultaneous
|
||||
/// open_ TCP connection. On this new connection both endpoints assume
|
||||
/// to be the dialer of the connection. This is problematic during the
|
||||
/// connection upgrade process where an upgrade assumes one side to be
|
||||
/// the listener. With the help of this option, both peers can
|
||||
/// negotiate the roles (dialer and listener) for the new connection
|
||||
/// ahead of time, through some external channel, e.g. the DCUtR
|
||||
/// protocol, and thus have one peer dial the other and upgrade the
|
||||
/// connection as a dialer and one peer dial the other and upgrade the
|
||||
/// connection _as a listener_ overriding its role.
|
||||
role_override: Endpoint,
|
||||
},
|
||||
/// We received the node.
|
||||
Listener {
|
||||
@ -179,7 +203,10 @@ impl ConnectedPoint {
|
||||
/// Returns true if the connection is relayed.
|
||||
pub fn is_relayed(&self) -> bool {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { address } => address,
|
||||
ConnectedPoint::Dialer {
|
||||
address,
|
||||
role_override: _,
|
||||
} => address,
|
||||
ConnectedPoint::Listener { local_addr, .. } => local_addr,
|
||||
}
|
||||
.iter()
|
||||
@ -194,7 +221,7 @@ impl ConnectedPoint {
|
||||
/// not be usable to establish new connections.
|
||||
pub fn get_remote_address(&self) -> &Multiaddr {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { address } => address,
|
||||
ConnectedPoint::Dialer { address, .. } => address,
|
||||
ConnectedPoint::Listener { send_back_addr, .. } => send_back_addr,
|
||||
}
|
||||
}
|
||||
@ -204,7 +231,7 @@ impl ConnectedPoint {
|
||||
/// For `Dialer`, this modifies `address`. For `Listener`, this modifies `send_back_addr`.
|
||||
pub fn set_remote_address(&mut self, new_address: Multiaddr) {
|
||||
match self {
|
||||
ConnectedPoint::Dialer { address } => *address = new_address,
|
||||
ConnectedPoint::Dialer { address, .. } => *address = new_address,
|
||||
ConnectedPoint::Listener { send_back_addr, .. } => *send_back_addr = new_address,
|
||||
}
|
||||
}
|
||||
|
@ -491,6 +491,13 @@ mod tests {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn dial_as_listener(
|
||||
self,
|
||||
_: Multiaddr,
|
||||
) -> Result<Self::Dial, transport::TransportError<Self::Error>> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> {
|
||||
None
|
||||
}
|
||||
@ -542,6 +549,13 @@ mod tests {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn dial_as_listener(
|
||||
self,
|
||||
_: Multiaddr,
|
||||
) -> Result<Self::Dial, transport::TransportError<Self::Error>> {
|
||||
panic!()
|
||||
}
|
||||
|
||||
fn address_translation(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> {
|
||||
None
|
||||
}
|
||||
|
@ -22,8 +22,8 @@
|
||||
use crate::{
|
||||
connection::{
|
||||
handler::{THandlerError, THandlerInEvent, THandlerOutEvent},
|
||||
Connected, ConnectionError, ConnectionHandler, ConnectionId, ConnectionLimit, IncomingInfo,
|
||||
IntoConnectionHandler, PendingConnectionError, PendingInboundConnectionError,
|
||||
Connected, ConnectionError, ConnectionHandler, ConnectionId, ConnectionLimit, Endpoint,
|
||||
IncomingInfo, IntoConnectionHandler, PendingConnectionError, PendingInboundConnectionError,
|
||||
PendingOutboundConnectionError, PendingPoint, Substream,
|
||||
},
|
||||
muxing::StreamMuxer,
|
||||
@ -460,7 +460,7 @@ where
|
||||
local_addr,
|
||||
send_back_addr,
|
||||
}),
|
||||
PendingPoint::Dialer => None,
|
||||
PendingPoint::Dialer { .. } => None,
|
||||
})
|
||||
}
|
||||
|
||||
@ -535,6 +535,7 @@ where
|
||||
addresses: impl Iterator<Item = Multiaddr> + Send + 'static,
|
||||
peer: Option<PeerId>,
|
||||
handler: THandler,
|
||||
role_override: Endpoint,
|
||||
dial_concurrency_factor_override: Option<NonZeroU8>,
|
||||
) -> Result<ConnectionId, DialError<THandler>>
|
||||
where
|
||||
@ -550,6 +551,7 @@ where
|
||||
peer,
|
||||
addresses,
|
||||
dial_concurrency_factor_override.unwrap_or(self.dial_concurrency_factor),
|
||||
role_override,
|
||||
);
|
||||
|
||||
let connection_id = self.next_connection_id();
|
||||
@ -566,13 +568,15 @@ where
|
||||
.boxed(),
|
||||
);
|
||||
|
||||
self.counters.inc_pending(&PendingPoint::Dialer);
|
||||
let endpoint = PendingPoint::Dialer { role_override };
|
||||
|
||||
self.counters.inc_pending(&endpoint);
|
||||
self.pending.insert(
|
||||
connection_id,
|
||||
PendingConnectionInfo {
|
||||
peer_id: peer,
|
||||
handler,
|
||||
endpoint: PendingPoint::Dialer,
|
||||
endpoint: endpoint,
|
||||
_drop_notifier: drop_notifier,
|
||||
},
|
||||
);
|
||||
@ -745,9 +749,13 @@ where
|
||||
self.counters.dec_pending(&endpoint);
|
||||
|
||||
let (endpoint, concurrent_dial_errors) = match (endpoint, outgoing) {
|
||||
(PendingPoint::Dialer, Some((address, errors))) => {
|
||||
(ConnectedPoint::Dialer { address }, Some(errors))
|
||||
}
|
||||
(PendingPoint::Dialer { role_override }, Some((address, errors))) => (
|
||||
ConnectedPoint::Dialer {
|
||||
address,
|
||||
role_override,
|
||||
},
|
||||
Some(errors),
|
||||
),
|
||||
(
|
||||
PendingPoint::Listener {
|
||||
local_addr,
|
||||
@ -761,7 +769,7 @@ where
|
||||
},
|
||||
None,
|
||||
),
|
||||
(PendingPoint::Dialer, None) => unreachable!(
|
||||
(PendingPoint::Dialer { .. }, None) => unreachable!(
|
||||
"Established incoming connection via pending outgoing connection."
|
||||
),
|
||||
(PendingPoint::Listener { .. }, Some(_)) => unreachable!(
|
||||
@ -910,7 +918,7 @@ where
|
||||
self.counters.dec_pending(&endpoint);
|
||||
|
||||
match (endpoint, error) {
|
||||
(PendingPoint::Dialer, Either::Left(error)) => {
|
||||
(PendingPoint::Dialer { .. }, Either::Left(error)) => {
|
||||
return Poll::Ready(PoolEvent::PendingOutboundConnectionError {
|
||||
id,
|
||||
error,
|
||||
@ -933,7 +941,7 @@ where
|
||||
local_addr,
|
||||
});
|
||||
}
|
||||
(PendingPoint::Dialer, Either::Right(_)) => {
|
||||
(PendingPoint::Dialer { .. }, Either::Right(_)) => {
|
||||
unreachable!("Inbound error for outbound connection.")
|
||||
}
|
||||
(PendingPoint::Listener { .. }, Either::Left(_)) => {
|
||||
@ -1176,7 +1184,7 @@ impl ConnectionCounters {
|
||||
|
||||
fn inc_pending(&mut self, endpoint: &PendingPoint) {
|
||||
match endpoint {
|
||||
PendingPoint::Dialer => {
|
||||
PendingPoint::Dialer { .. } => {
|
||||
self.pending_outgoing += 1;
|
||||
}
|
||||
PendingPoint::Listener { .. } => {
|
||||
@ -1191,7 +1199,7 @@ impl ConnectionCounters {
|
||||
|
||||
fn dec_pending(&mut self, endpoint: &PendingPoint) {
|
||||
match endpoint {
|
||||
PendingPoint::Dialer => {
|
||||
PendingPoint::Dialer { .. } => {
|
||||
self.pending_outgoing -= 1;
|
||||
}
|
||||
PendingPoint::Listener { .. } => {
|
||||
|
@ -18,9 +18,8 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
pub use crate::connection::{ConnectionCounters, ConnectionLimits};
|
||||
|
||||
use crate::{
|
||||
connection::Endpoint,
|
||||
transport::{Transport, TransportError},
|
||||
Multiaddr, PeerId,
|
||||
};
|
||||
@ -63,14 +62,21 @@ where
|
||||
peer: Option<PeerId>,
|
||||
addresses: impl Iterator<Item = Multiaddr> + Send + 'static,
|
||||
concurrency_factor: NonZeroU8,
|
||||
role_override: Endpoint,
|
||||
) -> Self {
|
||||
let mut pending_dials = addresses.map(move |address| match p2p_addr(peer, address) {
|
||||
Ok(address) => match transport.clone().dial(address.clone()) {
|
||||
Ok(fut) => fut
|
||||
.map(|r| (address, r.map_err(|e| TransportError::Other(e))))
|
||||
.boxed(),
|
||||
Err(err) => futures::future::ready((address, Err(err))).boxed(),
|
||||
},
|
||||
Ok(address) => {
|
||||
let dial = match role_override {
|
||||
Endpoint::Dialer => transport.clone().dial(address.clone()),
|
||||
Endpoint::Listener => transport.clone().dial_as_listener(address.clone()),
|
||||
};
|
||||
match dial {
|
||||
Ok(fut) => fut
|
||||
.map(|r| (address, r.map_err(|e| TransportError::Other(e))))
|
||||
.boxed(),
|
||||
Err(err) => futures::future::ready((address, Err(err))).boxed(),
|
||||
}
|
||||
}
|
||||
Err(address) => futures::future::ready((
|
||||
address.clone(),
|
||||
Err(TransportError::MultiaddrNotSupported(address)),
|
||||
|
@ -529,6 +529,25 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
use TransportError::*;
|
||||
match self {
|
||||
EitherTransport::Left(a) => match a.dial_as_listener(addr) {
|
||||
Ok(connec) => Ok(EitherFuture::First(connec)),
|
||||
Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)),
|
||||
Err(Other(err)) => Err(Other(EitherError::A(err))),
|
||||
},
|
||||
EitherTransport::Right(b) => match b.dial_as_listener(addr) {
|
||||
Ok(connec) => Ok(EitherFuture::Second(connec)),
|
||||
Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)),
|
||||
Err(Other(err)) => Err(Other(EitherError::B(err))),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
match self {
|
||||
EitherTransport::Left(a) => a.address_translation(server, observed),
|
||||
|
@ -21,7 +21,7 @@
|
||||
mod event;
|
||||
pub mod peer;
|
||||
|
||||
pub use crate::connection::{ConnectionCounters, ConnectionLimits};
|
||||
pub use crate::connection::{ConnectionCounters, ConnectionLimits, Endpoint};
|
||||
pub use event::{IncomingConnection, NetworkEvent};
|
||||
pub use peer::Peer;
|
||||
|
||||
@ -97,7 +97,7 @@ where
|
||||
self.pool
|
||||
.iter_pending_info()
|
||||
.filter(move |(_, endpoint, peer_id)| {
|
||||
matches!(endpoint, PendingPoint::Dialer) && peer_id.as_ref() == Some(&peer)
|
||||
matches!(endpoint, PendingPoint::Dialer { .. }) && peer_id.as_ref() == Some(&peer)
|
||||
})
|
||||
.map(|(connection_id, _, _)| connection_id)
|
||||
}
|
||||
@ -206,19 +206,24 @@ where
|
||||
{
|
||||
let opts = opts.into();
|
||||
|
||||
let (peer_id, addresses, dial_concurrency_factor_override) = match opts.0 {
|
||||
let (peer_id, addresses, dial_concurrency_factor_override, role_override) = match opts.0 {
|
||||
// Dial a known peer.
|
||||
Opts::WithPeerIdWithAddresses(WithPeerIdWithAddresses {
|
||||
peer_id,
|
||||
addresses,
|
||||
dial_concurrency_factor_override,
|
||||
role_override,
|
||||
}) => (
|
||||
Some(peer_id),
|
||||
Either::Left(addresses.into_iter()),
|
||||
dial_concurrency_factor_override,
|
||||
role_override,
|
||||
),
|
||||
// Dial an unknown peer.
|
||||
Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress { address }) => {
|
||||
Opts::WithoutPeerIdWithAddress(WithoutPeerIdWithAddress {
|
||||
address,
|
||||
role_override,
|
||||
}) => {
|
||||
// If the address ultimately encapsulates an expected peer ID, dial that peer
|
||||
// such that any mismatch is detected. We do not "pop off" the `P2p` protocol
|
||||
// from the address, because it may be used by the `Transport`, i.e. `P2p`
|
||||
@ -239,7 +244,12 @@ where
|
||||
Err(_) => return Err(DialError::InvalidPeerId { handler }),
|
||||
};
|
||||
|
||||
(peer_id, Either::Right(std::iter::once(address)), None)
|
||||
(
|
||||
peer_id,
|
||||
Either::Right(std::iter::once(address)),
|
||||
None,
|
||||
role_override,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
@ -248,6 +258,7 @@ where
|
||||
addresses,
|
||||
peer_id,
|
||||
handler,
|
||||
role_override,
|
||||
dial_concurrency_factor_override,
|
||||
)
|
||||
}
|
||||
@ -284,7 +295,7 @@ where
|
||||
pub fn dialing_peers(&self) -> impl Iterator<Item = &PeerId> {
|
||||
self.pool
|
||||
.iter_pending_info()
|
||||
.filter(|(_, endpoint, _)| matches!(endpoint, PendingPoint::Dialer))
|
||||
.filter(|(_, endpoint, _)| matches!(endpoint, PendingPoint::Dialer { .. }))
|
||||
.filter_map(|(_, _, peer)| peer.as_ref())
|
||||
}
|
||||
|
||||
@ -627,6 +638,7 @@ impl WithPeerId {
|
||||
peer_id: self.peer_id,
|
||||
addresses,
|
||||
dial_concurrency_factor_override: Default::default(),
|
||||
role_override: Endpoint::Dialer,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -636,6 +648,7 @@ pub struct WithPeerIdWithAddresses {
|
||||
pub(crate) peer_id: PeerId,
|
||||
pub(crate) addresses: Vec<Multiaddr>,
|
||||
pub(crate) dial_concurrency_factor_override: Option<NonZeroU8>,
|
||||
pub(crate) role_override: Endpoint,
|
||||
}
|
||||
|
||||
impl WithPeerIdWithAddresses {
|
||||
@ -645,6 +658,17 @@ impl WithPeerIdWithAddresses {
|
||||
self
|
||||
}
|
||||
|
||||
/// Override role of local node on connection. I.e. execute the dial _as a
|
||||
/// listener_.
|
||||
///
|
||||
/// See
|
||||
/// [`ConnectedPoint::Dialer`](crate::connection::ConnectedPoint::Dialer)
|
||||
/// for details.
|
||||
pub fn override_role(mut self, role: Endpoint) -> Self {
|
||||
self.role_override = role;
|
||||
self
|
||||
}
|
||||
|
||||
/// Build the final [`DialOpts`].
|
||||
pub fn build(self) -> DialOpts {
|
||||
DialOpts(Opts::WithPeerIdWithAddresses(self))
|
||||
@ -657,16 +681,31 @@ pub struct WithoutPeerId {}
|
||||
impl WithoutPeerId {
|
||||
/// Specify a single address to dial the unknown peer.
|
||||
pub fn address(self, address: Multiaddr) -> WithoutPeerIdWithAddress {
|
||||
WithoutPeerIdWithAddress { address }
|
||||
WithoutPeerIdWithAddress {
|
||||
address,
|
||||
role_override: Endpoint::Dialer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct WithoutPeerIdWithAddress {
|
||||
pub(crate) address: Multiaddr,
|
||||
pub(crate) role_override: Endpoint,
|
||||
}
|
||||
|
||||
impl WithoutPeerIdWithAddress {
|
||||
/// Override role of local node on connection. I.e. execute the dial _as a
|
||||
/// listener_.
|
||||
///
|
||||
/// See
|
||||
/// [`ConnectedPoint::Dialer`](crate::connection::ConnectedPoint::Dialer)
|
||||
/// for details.
|
||||
pub fn override_role(mut self, role: Endpoint) -> Self {
|
||||
self.role_override = role;
|
||||
self
|
||||
}
|
||||
|
||||
/// Build the final [`DialOpts`].
|
||||
pub fn build(self) -> DialOpts {
|
||||
DialOpts(Opts::WithoutPeerIdWithAddress(self))
|
||||
|
@ -25,7 +25,7 @@
|
||||
//! any desired protocols. The rest of the module defines combinators for
|
||||
//! modifying a transport through composition with other transports or protocol upgrades.
|
||||
|
||||
use crate::ConnectedPoint;
|
||||
use crate::connection::ConnectedPoint;
|
||||
use futures::prelude::*;
|
||||
use multiaddr::Multiaddr;
|
||||
use std::{error::Error, fmt};
|
||||
@ -130,6 +130,15 @@ pub trait Transport {
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// As [`Transport::dial`] but has the local node act as a listener on the outgoing connection.
|
||||
///
|
||||
/// This option is needed for NAT and firewall hole punching.
|
||||
///
|
||||
/// See [`ConnectedPoint::Dialer`](crate::connection::ConnectedPoint::Dialer) for related option.
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>>
|
||||
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.
|
||||
|
@ -19,9 +19,9 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
connection::{ConnectedPoint, Endpoint},
|
||||
either::EitherError,
|
||||
transport::{ListenerEvent, Transport, TransportError},
|
||||
ConnectedPoint,
|
||||
};
|
||||
use futures::{future::Either, prelude::*};
|
||||
use multiaddr::Multiaddr;
|
||||
@ -76,7 +76,32 @@ where
|
||||
.map_err(|err| err.map(EitherError::A))?;
|
||||
let future = AndThenFuture {
|
||||
inner: Either::Left(Box::pin(dialed_fut)),
|
||||
args: Some((self.fun, ConnectedPoint::Dialer { address: addr })),
|
||||
args: Some((
|
||||
self.fun,
|
||||
ConnectedPoint::Dialer {
|
||||
address: addr,
|
||||
role_override: Endpoint::Dialer,
|
||||
},
|
||||
)),
|
||||
_marker: PhantomPinned,
|
||||
};
|
||||
Ok(future)
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let dialed_fut = self
|
||||
.transport
|
||||
.dial_as_listener(addr.clone())
|
||||
.map_err(|err| err.map(EitherError::A))?;
|
||||
let future = AndThenFuture {
|
||||
inner: Either::Left(Box::pin(dialed_fut)),
|
||||
args: Some((
|
||||
self.fun,
|
||||
ConnectedPoint::Dialer {
|
||||
address: addr,
|
||||
role_override: Endpoint::Listener,
|
||||
},
|
||||
)),
|
||||
_marker: PhantomPinned,
|
||||
};
|
||||
Ok(future)
|
||||
|
@ -52,6 +52,7 @@ type ListenerUpgrade<O> = Pin<Box<dyn Future<Output = io::Result<O>> + Send>>;
|
||||
trait Abstract<O> {
|
||||
fn listen_on(&self, addr: Multiaddr) -> Result<Listener<O>, TransportError<io::Error>>;
|
||||
fn dial(&self, addr: Multiaddr) -> Result<Dial<O>, TransportError<io::Error>>;
|
||||
fn dial_as_listener(&self, addr: Multiaddr) -> Result<Dial<O>, TransportError<io::Error>>;
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr>;
|
||||
}
|
||||
|
||||
@ -85,6 +86,13 @@ where
|
||||
Ok(Box::pin(fut) as Dial<_>)
|
||||
}
|
||||
|
||||
fn dial_as_listener(&self, addr: Multiaddr) -> Result<Dial<O>, TransportError<io::Error>> {
|
||||
let fut = Transport::dial_as_listener(self.clone(), addr)
|
||||
.map(|r| r.map_err(box_err))
|
||||
.map_err(|e| e.map(box_err))?;
|
||||
Ok(Box::pin(fut) as Dial<_>)
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
Transport::address_translation(self, server, observed)
|
||||
}
|
||||
@ -119,6 +127,10 @@ impl<O> Transport for Boxed<O> {
|
||||
self.inner.dial(addr)
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
self.inner.dial_as_listener(addr)
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.inner.address_translation(server, observed)
|
||||
}
|
||||
|
@ -83,6 +83,26 @@ where
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let addr = match self.0.dial_as_listener(addr) {
|
||||
Ok(connec) => return Ok(EitherFuture::First(connec)),
|
||||
Err(TransportError::MultiaddrNotSupported(addr)) => addr,
|
||||
Err(TransportError::Other(err)) => {
|
||||
return Err(TransportError::Other(EitherError::A(err)))
|
||||
}
|
||||
};
|
||||
|
||||
let addr = match self.1.dial_as_listener(addr) {
|
||||
Ok(connec) => return Ok(EitherFuture::Second(connec)),
|
||||
Err(TransportError::MultiaddrNotSupported(addr)) => addr,
|
||||
Err(TransportError::Other(err)) => {
|
||||
return Err(TransportError::Other(EitherError::B(err)))
|
||||
}
|
||||
};
|
||||
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
if let Some(addr) = self.0.address_translation(server, observed) {
|
||||
Some(addr)
|
||||
|
@ -70,6 +70,10 @@ impl<TOut> Transport for DummyTransport<TOut> {
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
}
|
||||
|
||||
fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
None
|
||||
}
|
||||
|
@ -19,8 +19,8 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::{
|
||||
connection::{ConnectedPoint, Endpoint},
|
||||
transport::{ListenerEvent, Transport, TransportError},
|
||||
ConnectedPoint,
|
||||
};
|
||||
use futures::prelude::*;
|
||||
use multiaddr::Multiaddr;
|
||||
@ -60,7 +60,22 @@ where
|
||||
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let future = self.transport.dial(addr.clone())?;
|
||||
let p = ConnectedPoint::Dialer { address: addr };
|
||||
let p = ConnectedPoint::Dialer {
|
||||
address: addr,
|
||||
role_override: Endpoint::Dialer,
|
||||
};
|
||||
Ok(MapFuture {
|
||||
inner: future,
|
||||
args: Some((self.fun, p)),
|
||||
})
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let future = self.transport.dial_as_listener(addr.clone())?;
|
||||
let p = ConnectedPoint::Dialer {
|
||||
address: addr,
|
||||
role_override: Endpoint::Listener,
|
||||
};
|
||||
Ok(MapFuture {
|
||||
inner: future,
|
||||
args: Some((self.fun, p)),
|
||||
|
@ -68,6 +68,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let map = self.map;
|
||||
match self.transport.dial_as_listener(addr) {
|
||||
Ok(future) => Ok(MapErrDial {
|
||||
inner: future,
|
||||
map: Some(map),
|
||||
}),
|
||||
Err(err) => Err(err.map(map)),
|
||||
}
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.transport.address_translation(server, observed)
|
||||
}
|
||||
|
@ -205,6 +205,10 @@ impl Transport for MemoryTransport {
|
||||
DialFuture::new(port).ok_or(TransportError::Other(MemoryTransportError::Unreachable))
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<DialFuture, TransportError<Self::Error>> {
|
||||
self.dial(addr)
|
||||
}
|
||||
|
||||
fn address_translation(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
None
|
||||
}
|
||||
|
@ -75,6 +75,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
if let Some(inner) = self.0 {
|
||||
inner.dial_as_listener(addr)
|
||||
} else {
|
||||
Err(TransportError::MultiaddrNotSupported(addr))
|
||||
}
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
if let Some(inner) = &self.0 {
|
||||
inner.address_translation(server, observed)
|
||||
|
@ -109,6 +109,17 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let dial = self
|
||||
.inner
|
||||
.dial_as_listener(addr)
|
||||
.map_err(|err| err.map(TransportTimeoutError::Other))?;
|
||||
Ok(Timeout {
|
||||
inner: dial,
|
||||
timer: Delay::new(self.outgoing_timeout),
|
||||
})
|
||||
}
|
||||
|
||||
fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
self.inner.address_translation(server, observed)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
pub use crate::upgrade::Version;
|
||||
|
||||
use crate::{
|
||||
connection::ConnectedPoint,
|
||||
muxing::{StreamMuxer, StreamMuxerBox},
|
||||
transport::{
|
||||
and_then::AndThen, boxed::boxed, timeout::TransportTimeout, ListenerEvent, Transport,
|
||||
@ -32,7 +33,7 @@ use crate::{
|
||||
self, apply_inbound, apply_outbound, InboundUpgrade, InboundUpgradeApply, OutboundUpgrade,
|
||||
OutboundUpgradeApply, UpgradeError,
|
||||
},
|
||||
ConnectedPoint, Negotiated, PeerId,
|
||||
Negotiated, PeerId,
|
||||
};
|
||||
use futures::{prelude::*, ready};
|
||||
use multiaddr::Multiaddr;
|
||||
@ -340,6 +341,10 @@ where
|
||||
self.0.dial(addr)
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
self.0.dial_as_listener(addr)
|
||||
}
|
||||
|
||||
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||
self.0.listen_on(addr)
|
||||
}
|
||||
@ -393,6 +398,17 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
fn dial_as_listener(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
|
||||
let future = self
|
||||
.inner
|
||||
.dial_as_listener(addr)
|
||||
.map_err(|err| err.map(TransportUpgradeError::Transport))?;
|
||||
Ok(DialUpgradeFuture {
|
||||
future: Box::pin(future),
|
||||
upgrade: future::Either::Left(Some(self.upgrade)),
|
||||
})
|
||||
}
|
||||
|
||||
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
|
||||
let stream = self
|
||||
.inner
|
||||
|
@ -19,7 +19,7 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::upgrade::{InboundUpgrade, OutboundUpgrade, ProtocolName, UpgradeError};
|
||||
use crate::{ConnectedPoint, Negotiated};
|
||||
use crate::{connection::ConnectedPoint, Negotiated};
|
||||
use futures::{future::Either, prelude::*};
|
||||
use log::debug;
|
||||
use multistream_select::{self, DialerSelectFuture, ListenerSelectFuture};
|
||||
@ -27,6 +27,7 @@ use std::{iter, mem, pin::Pin, task::Context, task::Poll};
|
||||
|
||||
pub use multistream_select::Version;
|
||||
|
||||
// TODO: Still needed?
|
||||
/// Applies an upgrade to the inbound and outbound direction of a connection or substream.
|
||||
pub fn apply<C, U>(
|
||||
conn: C,
|
||||
@ -38,10 +39,11 @@ where
|
||||
C: AsyncRead + AsyncWrite + Unpin,
|
||||
U: InboundUpgrade<Negotiated<C>> + OutboundUpgrade<Negotiated<C>>,
|
||||
{
|
||||
if cp.is_listener() {
|
||||
Either::Left(apply_inbound(conn, up))
|
||||
} else {
|
||||
Either::Right(apply_outbound(conn, up, v))
|
||||
match cp {
|
||||
ConnectedPoint::Dialer { role_override, .. } if role_override.is_dialer() => {
|
||||
Either::Right(apply_outbound(conn, up, v))
|
||||
}
|
||||
_ => Either::Left(apply_inbound(conn, up)),
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user