Remove Transport::nat_traversal and refactor multiaddr. (#1052)

The functionality is available through `Multiaddr::replace`.
What we currently call "nat_traversal" is merley a replacement of an IP
address prefix in a `Multiaddr`, hence it can be done directly on
`Multiaddr` values instead of having to go through a `Transport`.

In addition this PR consolidates changes made to `Multiaddr` in
previous commits which resulted in lots of deprecations. It adds some
more (see below for the complete list of API changes) and removes all
deprecated functionality, requiring a minor version bump.

Here are the changes to `multiaddr` compared to the currently published
version:

1.  Removed `into_bytes` (use `to_vec` instead).
2.  Renamed `to_bytes` to `to_vec`.
3.  Removed `from_bytes` (use the `TryFrom` impl instead).
4.  Added `with_capacity`.
5.  Added `len`.
6.  Removed `as_slice` (use `AsRef` impl instead).
7.  Removed `encapsulate` (use `push` or `with` instead).
8.  Removed `decapsulate` (use `pop` instead).
9.  Renamed `append` to `push`.
10. Added `with`.
11. Added `replace`.
12. Removed `ToMultiaddr` trait (use `TryFrom` instead).
This commit is contained in:
Toralf Wittner
2019-04-17 20:12:31 +02:00
committed by GitHub
parent a4173705db
commit ca58f8029c
33 changed files with 494 additions and 803 deletions

View File

@ -65,6 +65,7 @@ pub use multistream_select::Negotiated;
mod keys_proto; mod keys_proto;
mod peer_id; mod peer_id;
mod translation;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -78,14 +79,15 @@ pub mod swarm;
pub mod transport; pub mod transport;
pub mod upgrade; pub mod upgrade;
pub use self::multiaddr::Multiaddr; pub use multiaddr::Multiaddr;
pub use self::muxing::StreamMuxer; pub use muxing::StreamMuxer;
pub use self::peer_id::PeerId; pub use peer_id::PeerId;
pub use self::protocols_handler::{ProtocolsHandler, ProtocolsHandlerEvent}; pub use protocols_handler::{ProtocolsHandler, ProtocolsHandlerEvent};
pub use self::identity::PublicKey; pub use identity::PublicKey;
pub use self::swarm::Swarm; pub use swarm::Swarm;
pub use self::transport::Transport; pub use transport::Transport;
pub use self::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo, UpgradeError, ProtocolName}; pub use translation::address_translation;
pub use upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo, UpgradeError, ProtocolName};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Endpoint { pub enum Endpoint {

View File

@ -20,7 +20,7 @@
use crate::muxing::StreamMuxer; use crate::muxing::StreamMuxer;
use crate::{ use crate::{
Endpoint, Multiaddr, PeerId, Endpoint, Multiaddr, PeerId, address_translation,
nodes::{ nodes::{
collection::{ collection::{
CollectionEvent, CollectionEvent,
@ -38,8 +38,7 @@ use crate::{
node::Substream node::Substream
}, },
nodes::listeners::{ListenersEvent, ListenersStream}, nodes::listeners::{ListenersEvent, ListenersStream},
transport::Transport, transport::{Transport, TransportError}
transport::TransportError,
}; };
use fnv::FnvHashMap; use fnv::FnvHashMap;
use futures::{prelude::*, future}; use futures::{prelude::*, future};
@ -771,8 +770,7 @@ where
TMuxer: 'a, TMuxer: 'a,
THandler: 'a, THandler: 'a,
{ {
self.listen_addrs() self.listen_addrs().flat_map(move |server| address_translation(server, observed_addr))
.flat_map(move |server| self.transport().nat_traversal(server, observed_addr))
} }
/// Returns the peer id of the local node. /// Returns the peer id of the local node.

View File

@ -47,51 +47,6 @@ fn local_node_peer() {
assert_matches!(raw_swarm.peer(peer_id), Peer::LocalNode); assert_matches!(raw_swarm.peer(peer_id), Peer::LocalNode);
} }
#[test]
fn nat_traversal_transforms_the_observed_address_according_to_the_transport_used() {
let addr1 = "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
// An unrelated outside address is returned as-is, no transform
let outside_addr1 = "/memory/0".parse::<Multiaddr>().expect("bad multiaddr");
let addr2 = "/ip4/127.0.0.2/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
let outside_addr2 = "/ip4/127.0.0.2/tcp/1234".parse::<Multiaddr>().expect("bad multiaddr");
// the DummyTransport nat_traversal increments the port number by one for Ip4 addresses
let mut transport = DummyTransport::new();
let events = vec![
ListenerEvent::NewAddress(addr1.clone()),
ListenerEvent::NewAddress(addr2.clone())
];
transport.set_initial_listener_state(ListenerState::Events(events));
let mut raw_swarm = RawSwarm::<_, _, _, Handler, _>::new(transport, PeerId::random());
raw_swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse().unwrap()).unwrap();
let raw_swarm =
future::lazy(move || {
assert_matches!(raw_swarm.poll(), Async::Ready(RawSwarmEvent::NewListenerAddress {..}));
assert_matches!(raw_swarm.poll(), Async::Ready(RawSwarmEvent::NewListenerAddress {..}));
Ok::<_, void::Void>(raw_swarm)
})
.wait()
.unwrap();
let natted = raw_swarm
.nat_traversal(&outside_addr1)
.map(|a| a.to_string())
.collect::<Vec<_>>();
assert!(natted.is_empty());
let natted = raw_swarm
.nat_traversal(&outside_addr2)
.map(|a| a.to_string())
.collect::<Vec<_>>();
assert_eq!(natted, vec!["/ip4/127.0.0.2/tcp/1234"])
}
#[test] #[test]
fn successful_dial_reaches_a_node() { fn successful_dial_reaches_a_node() {
let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random()); let mut swarm = RawSwarm::<_, _, _, Handler, _>::new(DummyTransport::new(), PeerId::random());

View File

@ -294,13 +294,11 @@ where TBehaviour: NetworkBehaviour<ProtocolsHandler = THandler>,
} }
let behaviour_poll = { let behaviour_poll = {
let transport = self.raw_swarm.transport();
let mut parameters = PollParameters { let mut parameters = PollParameters {
local_peer_id: &mut self.raw_swarm.local_peer_id(), local_peer_id: &mut self.raw_swarm.local_peer_id(),
supported_protocols: &self.supported_protocols, supported_protocols: &self.supported_protocols,
listened_addrs: &self.listened_addrs, listened_addrs: &self.listened_addrs,
external_addrs: &self.external_addrs, external_addrs: &self.external_addrs
nat_traversal: &move |a, b| transport.nat_traversal(a, b),
}; };
self.behaviour.poll(&mut parameters) self.behaviour.poll(&mut parameters)
}; };
@ -341,8 +339,7 @@ pub struct PollParameters<'a: 'a> {
local_peer_id: &'a PeerId, local_peer_id: &'a PeerId,
supported_protocols: &'a [Vec<u8>], supported_protocols: &'a [Vec<u8>],
listened_addrs: &'a [Multiaddr], listened_addrs: &'a [Multiaddr],
external_addrs: &'a [Multiaddr], external_addrs: &'a [Multiaddr]
nat_traversal: &'a dyn Fn(&Multiaddr, &Multiaddr) -> Option<Multiaddr>,
} }
impl<'a> PollParameters<'a> { impl<'a> PollParameters<'a> {
@ -374,12 +371,6 @@ impl<'a> PollParameters<'a> {
pub fn local_peer_id(&self) -> &PeerId { pub fn local_peer_id(&self) -> &PeerId {
self.local_peer_id self.local_peer_id
} }
/// Calls the `nat_traversal` method on the underlying transport of the `Swarm`.
#[inline]
pub fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
(self.nat_traversal)(server, observed)
}
} }
pub struct SwarmBuilder<TTransport, TBehaviour> { pub struct SwarmBuilder<TTransport, TBehaviour> {

View File

@ -112,12 +112,4 @@ impl Transport for DummyTransport {
Ok(Box::new(fut)) Ok(Box::new(fut))
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
if server == observed {
Some(observed.clone())
} else {
None
}
}
} }

43
core/src/translation.rs Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use multiaddr::{Multiaddr, Protocol};
/// Perform IP address translation.
///
/// Given an `original` [`Multiaddr`] and some `observed` [`Multiaddr`], return
/// a translated [`Multiaddr`] which has the first IP address translated by the
/// corresponding one from `observed`.
///
/// This is a mixed-mode translation, i.e. an IPv4 address may be replaced by
/// an IPv6 address and vice versa.
///
/// If the first [`Protocol`]s are not IP addresses, `None` is returned instead.
pub fn address_translation(original: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
original.replace(0, move |proto| match proto {
Protocol::Ip4(_) | Protocol::Ip6(_) => match observed.iter().next() {
x@Some(Protocol::Ip4(_)) => x,
x@Some(Protocol::Ip6(_)) => x,
_ => None
}
_ => None
})
}
// TODO: add tests

View File

@ -68,10 +68,6 @@ where
}; };
Ok(future) Ok(future)
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.transport.nat_traversal(server, observed)
}
} }
/// Custom `Stream` to avoid boxing. /// Custom `Stream` to avoid boxing.

View File

@ -44,7 +44,6 @@ pub type ListenerUpgrade<O, E> = Box<dyn Future<Item = O, Error = E> + Send>;
trait Abstract<O, E> { trait Abstract<O, E> {
fn listen_on(&self, addr: Multiaddr) -> Result<Listener<O, E>, TransportError<E>>; fn listen_on(&self, addr: Multiaddr) -> Result<Listener<O, E>, TransportError<E>>;
fn dial(&self, addr: Multiaddr) -> Result<Dial<O, E>, TransportError<E>>; fn dial(&self, addr: Multiaddr) -> Result<Dial<O, E>, TransportError<E>>;
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr>;
} }
impl<T, O, E> Abstract<O, E> for T impl<T, O, E> Abstract<O, E> for T
@ -67,10 +66,6 @@ where
let fut = Transport::dial(self.clone(), addr)?; let fut = Transport::dial(self.clone(), addr)?;
Ok(Box::new(fut) as Box<_>) Ok(Box::new(fut) as Box<_>)
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
Transport::nat_traversal(self, server, observed)
}
} }
/// See the `Transport::boxed` method. /// See the `Transport::boxed` method.
@ -108,8 +103,4 @@ where E: error::Error,
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> { fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
self.inner.dial(addr) self.inner.dial(addr)
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.inner.nat_traversal(server, observed)
}
} }

View File

@ -74,14 +74,4 @@ where
Err(TransportError::MultiaddrNotSupported(addr)) Err(TransportError::MultiaddrNotSupported(addr))
} }
#[inline]
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
let first = self.0.nat_traversal(server, observed);
if let Some(first) = first {
return Some(first);
}
self.1.nat_traversal(server, observed)
}
} }

View File

@ -59,20 +59,13 @@ impl<TOut> Transport for DummyTransport<TOut> {
type ListenerUpgrade = futures::future::Empty<Self::Output, io::Error>; type ListenerUpgrade = futures::future::Empty<Self::Output, io::Error>;
type Dial = futures::future::Empty<Self::Output, io::Error>; type Dial = futures::future::Empty<Self::Output, io::Error>;
#[inline]
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> { fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
Err(TransportError::MultiaddrNotSupported(addr)) Err(TransportError::MultiaddrNotSupported(addr))
} }
#[inline]
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> { fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
Err(TransportError::MultiaddrNotSupported(addr)) Err(TransportError::MultiaddrNotSupported(addr))
} }
#[inline]
fn nat_traversal(&self, _server: &Multiaddr, _observed: &Multiaddr) -> Option<Multiaddr> {
None
}
} }
/// Implementation of `Read` and `Write`. Not meant to be instanciated. /// Implementation of `Read` and `Write`. Not meant to be instanciated.

View File

@ -56,10 +56,6 @@ where
let p = ConnectedPoint::Dialer { address: addr }; let p = ConnectedPoint::Dialer { address: addr };
Ok(MapFuture { inner: future, args: Some((self.fun, p)) }) Ok(MapFuture { inner: future, args: Some((self.fun, p)) })
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.transport.nat_traversal(server, observed)
}
} }
/// Custom `Stream` implementation to avoid boxing. /// Custom `Stream` implementation to avoid boxing.

View File

@ -64,10 +64,6 @@ where
Err(err) => Err(err.map(map)), Err(err) => Err(err.map(map)),
} }
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.transport.nat_traversal(server, observed)
}
} }
/// Listening stream for `MapErr`. /// Listening stream for `MapErr`.

View File

@ -140,15 +140,6 @@ impl Transport for MemoryTransport {
Err(TransportError::Other(MemoryTransportError::Unreachable)) Err(TransportError::Other(MemoryTransportError::Unreachable))
} }
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
// TODO: NAT traversal for `/memory` addresses? how does that make sense?
if server == observed {
Some(server.clone())
} else {
None
}
}
} }
/// Error that can be produced from the `MemoryTransport`. /// Error that can be produced from the `MemoryTransport`.

View File

@ -124,26 +124,7 @@ pub trait Transport {
where where
Self: Sized; Self: Sized;
/// Takes a [`Multiaddr`] that represents a listening address together with an
/// an address observed by another node and tries to incoporate information
/// from the observed address into the listening address, yielding an
/// externally-visible address.
///
/// In order to do so, `observed` must be an address that a remote node observes on an
/// inbound connection from the local node. Each [`Transport`] implementation is only
/// responsible for handling the protocols it supports and should only consider the
/// prefix of `observed` necessary to perform the address translation
/// (e.g. `/ip4/80.81.82.83`) but should otherwise preserve `server` as is. For example,
/// if `server` is the address `/ip4/0.0.0.0/tcp/3000` and `observed` is the address
/// `/ip4/80.81.82.83/tcp/29601`, then the address `/ip4/80.81.82.83/tcp/3000` should be
/// returned.
///
/// Returns `None` if the transport does not recognize a protocol, or if `server` and
/// `observed` are unrelated addresses.
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr>;
/// Turns this `Transport` into an abstract boxed transport. /// Turns this `Transport` into an abstract boxed transport.
#[inline]
fn boxed(self) -> boxed::Boxed<Self::Output, Self::Error> fn boxed(self) -> boxed::Boxed<Self::Output, Self::Error>
where Self: Sized + Clone + Send + Sync + 'static, where Self: Sized + Clone + Send + Sync + 'static,
Self::Dial: Send + 'static, Self::Dial: Send + 'static,
@ -154,7 +135,6 @@ pub trait Transport {
} }
/// Applies a function on the connections created by the transport. /// Applies a function on the connections created by the transport.
#[inline]
fn map<F, O>(self, map: F) -> map::Map<Self, F> fn map<F, O>(self, map: F) -> map::Map<Self, F>
where where
Self: Sized, Self: Sized,
@ -164,7 +144,6 @@ pub trait Transport {
} }
/// Applies a function on the errors generated by the futures of the transport. /// Applies a function on the errors generated by the futures of the transport.
#[inline]
fn map_err<F, TNewErr>(self, map_err: F) -> map_err::MapErr<Self, F> fn map_err<F, TNewErr>(self, map_err: F) -> map_err::MapErr<Self, F>
where where
Self: Sized, Self: Sized,
@ -178,7 +157,6 @@ pub trait Transport {
/// ///
/// The returned transport will act like `self`, except that if `listen_on` or `dial` /// The returned transport will act like `self`, except that if `listen_on` or `dial`
/// return an error then `other` will be tried. /// return an error then `other` will be tried.
#[inline]
fn or_transport<T>(self, other: T) -> OrTransport<Self, T> fn or_transport<T>(self, other: T) -> OrTransport<Self, T>
where where
Self: Sized, Self: Sized,
@ -193,7 +171,6 @@ pub trait Transport {
/// connection (which may have already gone through previous upgrades) /// connection (which may have already gone through previous upgrades)
/// as an [`upgrade::InboundUpgrade`] or [`upgrade::OutboundUpgrade`], /// as an [`upgrade::InboundUpgrade`] or [`upgrade::OutboundUpgrade`],
/// respectively. /// respectively.
#[inline]
fn with_upgrade<U, O, E>(self, upgrade: U) -> Upgrade<Self, U> fn with_upgrade<U, O, E>(self, upgrade: U) -> Upgrade<Self, U>
where where
Self: Sized, Self: Sized,
@ -210,7 +187,6 @@ pub trait Transport {
/// This function can be used for ad-hoc protocol upgrades on a transport or /// This function can be used for ad-hoc protocol upgrades on a transport or
/// for processing or adapting the output of an earlier upgrade before /// for processing or adapting the output of an earlier upgrade before
/// applying the next upgrade. /// applying the next upgrade.
#[inline]
fn and_then<C, F, O>(self, upgrade: C) -> and_then::AndThen<Self, C> fn and_then<C, F, O>(self, upgrade: C) -> and_then::AndThen<Self, C>
where where
Self: Sized, Self: Sized,
@ -222,7 +198,6 @@ pub trait Transport {
/// Adds a timeout to the connection setup (including upgrades) for all inbound /// Adds a timeout to the connection setup (including upgrades) for all inbound
/// and outbound connection attempts. /// and outbound connection attempts.
#[inline]
fn with_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self> fn with_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
where where
Self: Sized, Self: Sized,
@ -232,7 +207,6 @@ pub trait Transport {
/// Adds a timeout to the connection setup (including upgrades) for all outbound /// Adds a timeout to the connection setup (including upgrades) for all outbound
/// connection attempts. /// connection attempts.
#[inline]
fn with_outbound_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self> fn with_outbound_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
where where
Self: Sized, Self: Sized,
@ -242,7 +216,6 @@ pub trait Transport {
/// Adds a timeout to the connection setup (including upgrades) for all inbound /// Adds a timeout to the connection setup (including upgrades) for all inbound
/// connection attempts. /// connection attempts.
#[inline]
fn with_inbound_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self> fn with_inbound_timeout(self, timeout: Duration) -> timeout::TransportTimeout<Self>
where where
Self: Sized, Self: Sized,
@ -367,7 +340,6 @@ pub enum TransportError<TErr> {
impl<TErr> TransportError<TErr> { impl<TErr> TransportError<TErr> {
/// Applies a function to the the error in [`TransportError::Other`]. /// Applies a function to the the error in [`TransportError::Other`].
#[inline]
pub fn map<TNewErr>(self, map: impl FnOnce(TErr) -> TNewErr) -> TransportError<TNewErr> { pub fn map<TNewErr>(self, map: impl FnOnce(TErr) -> TNewErr) -> TransportError<TNewErr> {
match self { match self {
TransportError::MultiaddrNotSupported(addr) => TransportError::MultiaddrNotSupported(addr), TransportError::MultiaddrNotSupported(addr) => TransportError::MultiaddrNotSupported(addr),

View File

@ -45,7 +45,6 @@ pub struct TransportTimeout<InnerTrans> {
impl<InnerTrans> TransportTimeout<InnerTrans> { impl<InnerTrans> TransportTimeout<InnerTrans> {
/// Wraps around a `Transport` to add timeouts to all the sockets created by it. /// Wraps around a `Transport` to add timeouts to all the sockets created by it.
#[inline]
pub fn new(trans: InnerTrans, timeout: Duration) -> Self { pub fn new(trans: InnerTrans, timeout: Duration) -> Self {
TransportTimeout { TransportTimeout {
inner: trans, inner: trans,
@ -55,7 +54,6 @@ impl<InnerTrans> TransportTimeout<InnerTrans> {
} }
/// Wraps around a `Transport` to add timeouts to the outgoing connections. /// Wraps around a `Transport` to add timeouts to the outgoing connections.
#[inline]
pub fn with_outgoing_timeout(trans: InnerTrans, timeout: Duration) -> Self { pub fn with_outgoing_timeout(trans: InnerTrans, timeout: Duration) -> Self {
TransportTimeout { TransportTimeout {
inner: trans, inner: trans,
@ -65,7 +63,6 @@ impl<InnerTrans> TransportTimeout<InnerTrans> {
} }
/// Wraps around a `Transport` to add timeouts to the ingoing connections. /// Wraps around a `Transport` to add timeouts to the ingoing connections.
#[inline]
pub fn with_ingoing_timeout(trans: InnerTrans, timeout: Duration) -> Self { pub fn with_ingoing_timeout(trans: InnerTrans, timeout: Duration) -> Self {
TransportTimeout { TransportTimeout {
inner: trans, inner: trans,
@ -105,11 +102,6 @@ where
inner: Timeout::new(dial, self.outgoing_timeout), inner: Timeout::new(dial, self.outgoing_timeout),
}) })
} }
#[inline]
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.inner.nat_traversal(server, observed)
}
} }
// TODO: can be removed and replaced with an `impl Stream` once impl Trait is fully stable // TODO: can be removed and replaced with an `impl Stream` once impl Trait is fully stable

View File

@ -73,10 +73,6 @@ where
.map_err(|err| err.map(TransportUpgradeError::Transport))?; .map_err(|err| err.map(TransportUpgradeError::Transport))?;
Ok(ListenerStream { stream: inbound, upgrade: self.upgrade }) Ok(ListenerStream { stream: inbound, upgrade: self.upgrade })
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.inner.nat_traversal(server, observed)
}
} }
/// Error produced by a transport upgrade. /// Error produced by a transport upgrade.

View File

@ -23,7 +23,7 @@ use futures::prelude::*;
use log::warn; use log::warn;
use libp2p_core::protocols_handler::{DummyProtocolsHandler, ProtocolsHandler}; use libp2p_core::protocols_handler::{DummyProtocolsHandler, ProtocolsHandler};
use libp2p_core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters}; use libp2p_core::swarm::{ConnectedPoint, NetworkBehaviour, NetworkBehaviourAction, PollParameters};
use libp2p_core::{Multiaddr, PeerId, multiaddr::Protocol}; use libp2p_core::{address_translation, Multiaddr, PeerId, multiaddr::Protocol};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{cmp, fmt, io, iter, marker::PhantomData, time::Duration, time::Instant}; use std::{cmp, fmt, io, iter, marker::PhantomData, time::Duration, time::Instant};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
@ -219,7 +219,7 @@ where
); );
}, },
MdnsPacket::Response(response) => { MdnsPacket::Response(response) => {
// We perform a call to `nat_traversal()` with the address we observe the // We replace the IP address with the address we observe the
// remote as and the address they listen on. // remote as and the address they listen on.
let obs_ip = Protocol::from(response.remote_addr().ip()); let obs_ip = Protocol::from(response.remote_addr().ip());
let obs_port = Protocol::Udp(response.remote_addr().port()); let obs_port = Protocol::Udp(response.remote_addr().port());
@ -237,10 +237,10 @@ where
let mut addrs = Vec::new(); let mut addrs = Vec::new();
for addr in peer.addresses() { for addr in peer.addresses() {
if let Some(new_addr) = params.nat_traversal(&addr, &observed) { if let Some(new_addr) = address_translation(&addr, &observed) {
addrs.push(new_addr); addrs.push(new_addr)
} }
addrs.push(addr); addrs.push(addr)
} }
for addr in addrs { for addr in addrs {
@ -283,3 +283,4 @@ impl<TSubstream> fmt::Debug for Mdns<TSubstream> {
.finish() .finish()
} }
} }

View File

@ -1,14 +1,12 @@
///! # multiaddr ///! Implementation of [multiaddr](https://github.com/jbenet/multiaddr) in Rust.
///!
///! Implementation of [multiaddr](https://github.com/jbenet/multiaddr)
///! in Rust.
pub use multihash; pub use multihash;
mod protocol; mod protocol;
mod errors; mod errors;
mod util;
use bytes::Bytes; use bytes::{Bytes, BytesMut};
use serde::{ use serde::{
Deserialize, Deserialize,
Deserializer, Deserializer,
@ -17,9 +15,10 @@ use serde::{
de::{self, Error as DeserializerError} de::{self, Error as DeserializerError}
}; };
use std::{ use std::{
convert::TryFrom,
fmt, fmt,
iter::FromIterator, iter::FromIterator,
net::{SocketAddr, SocketAddrV4, SocketAddrV6, IpAddr, Ipv4Addr, Ipv6Addr}, net::{IpAddr, Ipv4Addr, Ipv6Addr},
result::Result as StdResult, result::Result as StdResult,
str::FromStr str::FromStr
}; };
@ -30,6 +29,309 @@ pub use self::protocol::Protocol;
#[derive(PartialEq, Eq, Clone, Hash)] #[derive(PartialEq, Eq, Clone, Hash)]
pub struct Multiaddr { bytes: Bytes } pub struct Multiaddr { bytes: Bytes }
impl Multiaddr {
/// Create a new, empty multiaddress.
pub fn empty() -> Self {
Self { bytes: Bytes::new() }
}
/// Create a new, empty multiaddress with the given capacity.
pub fn with_capacity(n: usize) -> Self {
Self { bytes: Bytes::with_capacity(n) }
}
/// Return the length in bytes of this multiaddress.
pub fn len(&self) -> usize {
self.bytes.len()
}
/// Return a copy of this [`Multiaddr`]'s byte representation.
pub fn to_vec(&self) -> Vec<u8> {
Vec::from(&self.bytes[..])
}
/// Adds an already-parsed address component to the end of this multiaddr.
///
/// # Examples
///
/// ```
/// use parity_multiaddr::{Multiaddr, Protocol};
///
/// let mut address: Multiaddr = "/ip4/127.0.0.1".parse().unwrap();
/// address.push(Protocol::Tcp(10000));
/// assert_eq!(address, "/ip4/127.0.0.1/tcp/10000".parse().unwrap());
/// ```
///
pub fn push(&mut self, p: Protocol<'_>) {
let mut w = Vec::new();
p.write_bytes(&mut w).expect("Writing to a `Vec` never fails.");
self.bytes.extend_from_slice(&w);
}
/// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty.
/// ```
/// use parity_multiaddr::{Multiaddr, Protocol};
///
/// let mut address: Multiaddr = "/ip4/127.0.0.1/udt/sctp/5678".parse().unwrap();
///
/// assert_eq!(address.pop().unwrap(), Protocol::Sctp(5678));
/// assert_eq!(address.pop().unwrap(), Protocol::Udt);
/// ```
///
pub fn pop<'a>(&mut self) -> Option<Protocol<'a>> {
let mut slice = &self.bytes[..]; // the remaining multiaddr slice
if slice.is_empty() {
return None
}
let protocol = loop {
let (p, s) = Protocol::from_bytes(slice).expect("`slice` is a valid `Protocol`.");
if s.is_empty() {
break p.acquire()
}
slice = s
};
let remaining_len = self.bytes.len() - slice.len();
self.bytes.truncate(remaining_len);
Some(protocol)
}
/// Like [`push`] but more efficient if this `Multiaddr` has no living clones.
pub fn with(self, p: Protocol<'_>) -> Self {
match self.bytes.try_mut() {
Ok(bytes) => {
let mut w = util::BytesWriter(bytes);
p.write_bytes(&mut w).expect("Writing to a `BytesWriter` never fails.");
Multiaddr { bytes: w.0.freeze() }
}
Err(mut bytes) => {
let mut w = Vec::new();
p.write_bytes(&mut w).expect("Writing to a `Vec` never fails.");
bytes.extend_from_slice(&w);
Multiaddr { bytes }
}
}
}
/// Returns the components of this multiaddress.
///
/// ```
/// use std::net::Ipv4Addr;
/// use parity_multiaddr::{Multiaddr, Protocol};
///
/// let address: Multiaddr = "/ip4/127.0.0.1/udt/sctp/5678".parse().unwrap();
///
/// let components = address.iter().collect::<Vec<_>>();
/// assert_eq!(components[0], Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)));
/// assert_eq!(components[1], Protocol::Udt);
/// assert_eq!(components[2], Protocol::Sctp(5678));
/// ```
///
pub fn iter(&self) -> Iter<'_> {
Iter(&self.bytes)
}
/// Replace a [`Protocol`] at some position in this `Multiaddr`.
///
/// The parameter `at` denotes the index of the protocol at which the function
/// `by` will be applied to the current protocol, returning an optional replacement.
///
/// If `at` is out of bounds or `by` does not yield a replacement value,
/// `None` will be returned. Otherwise a copy of this `Multiaddr` with the
/// updated `Protocol` at position `at` will be returned.
pub fn replace<'a, F>(&self, at: usize, by: F) -> Option<Multiaddr>
where
F: FnOnce(&Protocol) -> Option<Protocol<'a>>
{
let mut address = Multiaddr::with_capacity(self.len());
let mut fun = Some(by);
let mut replaced = false;
for (i, p) in self.iter().enumerate() {
if i == at {
let f = fun.take().expect("i == at only happens once");
if let Some(q) = f(&p) {
address = address.with(q);
replaced = true;
continue
}
return None
}
address = address.with(p)
}
if replaced { Some(address) } else { None }
}
}
impl fmt::Debug for Multiaddr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.to_string().fmt(f)
}
}
impl fmt::Display for Multiaddr {
/// Convert a Multiaddr to a string
///
/// # Examples
///
/// ```
/// use parity_multiaddr::Multiaddr;
///
/// let address: Multiaddr = "/ip4/127.0.0.1/udt".parse().unwrap();
/// assert_eq!(address.to_string(), "/ip4/127.0.0.1/udt");
/// ```
///
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for s in self.iter() {
s.to_string().fmt(f)?;
}
Ok(())
}
}
impl AsRef<[u8]> for Multiaddr {
fn as_ref(&self) -> &[u8] {
self.bytes.as_ref()
}
}
impl<'a> IntoIterator for &'a Multiaddr {
type Item = Protocol<'a>;
type IntoIter = Iter<'a>;
fn into_iter(self) -> Iter<'a> {
Iter(&self.bytes)
}
}
impl<'a> FromIterator<Protocol<'a>> for Multiaddr {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = Protocol<'a>>,
{
let mut writer = Vec::new();
for cmp in iter {
cmp.write_bytes(&mut writer).expect("Writing to a `Vec` never fails.");
}
Multiaddr { bytes: writer.into() }
}
}
impl FromStr for Multiaddr {
type Err = Error;
fn from_str(input: &str) -> Result<Self> {
let mut writer = Vec::new();
let mut parts = input.split('/').peekable();
if Some("") != parts.next() {
// A multiaddr must start with `/`
return Err(Error::InvalidMultiaddr)
}
while parts.peek().is_some() {
let p = Protocol::from_str_parts(&mut parts)?;
p.write_bytes(&mut writer).expect("Writing to a `Vec` never fails.");
}
Ok(Multiaddr { bytes: writer.into() })
}
}
/// Iterator over `Multiaddr` [`Protocol`]s.
pub struct Iter<'a>(&'a [u8]);
impl<'a> Iterator for Iter<'a> {
type Item = Protocol<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.0.is_empty() {
return None;
}
let (p, next_data) =
Protocol::from_bytes(self.0).expect("`Multiaddr` is known to be valid.");
self.0 = next_data;
Some(p)
}
}
impl<'a> From<Protocol<'a>> for Multiaddr {
fn from(p: Protocol<'a>) -> Multiaddr {
let mut w = Vec::new();
p.write_bytes(&mut w).expect("Writing to a `Vec` never fails.");
Multiaddr { bytes: w.into() }
}
}
impl From<IpAddr> for Multiaddr {
fn from(v: IpAddr) -> Multiaddr {
match v {
IpAddr::V4(a) => a.into(),
IpAddr::V6(a) => a.into()
}
}
}
impl From<Ipv4Addr> for Multiaddr {
fn from(v: Ipv4Addr) -> Multiaddr {
Protocol::Ip4(v).into()
}
}
impl From<Ipv6Addr> for Multiaddr {
fn from(v: Ipv6Addr) -> Multiaddr {
Protocol::Ip6(v).into()
}
}
impl TryFrom<Bytes> for Multiaddr {
type Error = Error;
fn try_from(v: Bytes) -> Result<Self> {
// Check if the argument is a valid `Multiaddr` by reading its protocols.
let mut slice = &v[..];
while !slice.is_empty() {
let (_, s) = Protocol::from_bytes(slice)?;
slice = s
}
Ok(Multiaddr { bytes: v.into() })
}
}
impl TryFrom<BytesMut> for Multiaddr {
type Error = Error;
fn try_from(v: BytesMut) -> Result<Self> {
Multiaddr::try_from(v.freeze())
}
}
impl TryFrom<Vec<u8>> for Multiaddr {
type Error = Error;
fn try_from(v: Vec<u8>) -> Result<Self> {
Multiaddr::try_from(Bytes::from(v))
}
}
impl TryFrom<String> for Multiaddr {
type Error = Error;
fn try_from(s: String) -> Result<Multiaddr> {
s.parse()
}
}
impl<'a> TryFrom<&'a str> for Multiaddr {
type Error = Error;
fn try_from(s: &'a str) -> Result<Multiaddr> {
s.parse()
}
}
impl Serialize for Multiaddr { impl Serialize for Multiaddr {
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
where where
@ -38,7 +340,7 @@ impl Serialize for Multiaddr {
if serializer.is_human_readable() { if serializer.is_human_readable() {
serializer.serialize_str(&self.to_string()) serializer.serialize_str(&self.to_string())
} else { } else {
serializer.serialize_bytes(self.as_slice()) serializer.serialize_bytes(self.as_ref())
} }
} }
} }
@ -63,7 +365,7 @@ impl<'de> Deserialize<'de> for Multiaddr {
let s = String::from_utf8(buf).map_err(DeserializerError::custom)?; let s = String::from_utf8(buf).map_err(DeserializerError::custom)?;
s.parse().map_err(DeserializerError::custom) s.parse().map_err(DeserializerError::custom)
} else { } else {
Multiaddr::try_from_vec(buf).map_err(DeserializerError::custom) Multiaddr::try_from(buf).map_err(DeserializerError::custom)
} }
} }
fn visit_str<E: de::Error>(self, v: &str) -> StdResult<Self::Value, E> { fn visit_str<E: de::Error>(self, v: &str) -> StdResult<Self::Value, E> {
@ -82,7 +384,7 @@ impl<'de> Deserialize<'de> for Multiaddr {
self.visit_byte_buf(v.into()) self.visit_byte_buf(v.into())
} }
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> StdResult<Self::Value, E> { fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> StdResult<Self::Value, E> {
Multiaddr::try_from_vec(v).map_err(DeserializerError::custom) Multiaddr::try_from(v).map_err(DeserializerError::custom)
} }
} }
@ -94,384 +396,17 @@ impl<'de> Deserialize<'de> for Multiaddr {
} }
} }
impl fmt::Debug for Multiaddr {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.to_string().fmt(f)
}
}
impl fmt::Display for Multiaddr {
/// Convert a Multiaddr to a string
///
/// # Examples
///
/// ```
/// use parity_multiaddr::Multiaddr;
///
/// let address: Multiaddr = "/ip4/127.0.0.1/udt".parse().unwrap();
/// assert_eq!(address.to_string(), "/ip4/127.0.0.1/udt");
/// ```
///
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for s in self.iter() {
s.to_string().fmt(f)?;
}
Ok(())
}
}
impl Multiaddr {
#[deprecated(since = "0.2.1", note = "Use `Multiaddr::to_vec` instead.")]
pub fn into_bytes(self) -> Vec<u8> {
self.to_vec()
}
#[deprecated(since = "0.2.1", note = "Use `Multiaddr::to_vec` instead.")]
pub fn to_bytes(&self) -> Vec<u8> {
self.to_vec()
}
#[deprecated(since = "0.2.1", note = "Use `Multiaddr::try_from_vec` instead.")]
pub fn from_bytes(bytes: Vec<u8>) -> Result<Multiaddr> {
Self::try_from_vec(bytes)
}
/// Create a new, empty multiaddress.
pub fn empty() -> Multiaddr {
Multiaddr { bytes: Bytes::new() }
}
/// Return a copy to disallow changing the bytes directly
pub fn to_vec(&self) -> Vec<u8> {
Vec::from(&self.bytes[..])
}
/// Produces a `Multiaddr` from its bytes representation.
pub fn try_from_vec(v: Vec<u8>) -> Result<Multiaddr> {
// Check if the argument is a valid `Multiaddr`
// by reading its protocols.
let mut ptr = &v[..];
while !ptr.is_empty() {
let (_, new_ptr) = Protocol::from_bytes(ptr)?;
ptr = new_ptr;
}
Ok(Multiaddr { bytes: v.into() })
}
/// Extracts a slice containing the entire underlying vector.
pub fn as_slice(&self) -> &[u8] {
&self.bytes
}
/// Wrap a given Multiaddr and return the combination.
///
/// # Examples
///
/// ```
/// use parity_multiaddr::Multiaddr;
///
/// let address: Multiaddr = "/ip4/127.0.0.1".parse().unwrap();
/// let nested = address.encapsulate("/udt").unwrap();
/// assert_eq!(nested, "/ip4/127.0.0.1/udt".parse().unwrap());
/// ```
///
pub fn encapsulate<T: ToMultiaddr>(&self, input: T) -> Result<Multiaddr> {
let new = input.to_multiaddr()?;
let mut bytes = self.bytes.clone();
bytes.extend_from_slice(&new.bytes);
Ok(Multiaddr { bytes })
}
/// Adds an already-parsed address component to the end of this multiaddr.
///
/// # Examples
///
/// ```
/// use parity_multiaddr::{Multiaddr, Protocol};
///
/// let mut address: Multiaddr = "/ip4/127.0.0.1".parse().unwrap();
/// address.append(Protocol::Tcp(10000));
/// assert_eq!(address, "/ip4/127.0.0.1/tcp/10000".parse().unwrap());
/// ```
///
pub fn append(&mut self, p: Protocol<'_>) {
let mut w = Vec::new();
p.write_bytes(&mut w).expect("writing to a Vec never fails");
self.bytes.extend_from_slice(&w);
}
/// Remove the outermost address.
///
/// # Examples
///
/// ```
/// use parity_multiaddr::{Multiaddr, ToMultiaddr};
///
/// let address: Multiaddr = "/ip4/127.0.0.1/udt/sctp/5678".parse().unwrap();
/// let unwrapped = address.decapsulate("/udt").unwrap();
/// assert_eq!(unwrapped, "/ip4/127.0.0.1".parse().unwrap());
///
/// assert_eq!(
/// address.decapsulate("/udt").unwrap(),
/// "/ip4/127.0.0.1".to_multiaddr().unwrap()
/// );
/// ```
///
/// Returns the original if the passed in address is not found
///
/// ```
/// use parity_multiaddr::ToMultiaddr;
///
/// let address = "/ip4/127.0.0.1/udt/sctp/5678".to_multiaddr().unwrap();
/// let unwrapped = address.decapsulate("/ip4/127.0.1.1").unwrap();
/// assert_eq!(unwrapped, address);
/// ```
///
pub fn decapsulate<T: ToMultiaddr>(&self, input: T) -> Result<Multiaddr> {
let input = input.to_multiaddr()?.to_vec();
let bytes_len = self.bytes.len();
let input_length = input.len();
let mut input_pos = 0;
let mut matches = false;
for (i, _) in self.bytes.iter().enumerate() {
let next = i + input_length;
if next > bytes_len {
continue;
}
if self.bytes[i..next] == input[..] {
matches = true;
input_pos = i;
break;
}
}
if !matches {
return Ok(self.clone())
}
let mut bytes = self.bytes.clone();
bytes.truncate(input_pos);
Ok(Multiaddr { bytes })
}
/// Returns the components of this multiaddress.
///
/// ```
/// use std::net::Ipv4Addr;
/// use parity_multiaddr::{Multiaddr, Protocol};
///
/// let address: Multiaddr = "/ip4/127.0.0.1/udt/sctp/5678".parse().unwrap();
///
/// let components = address.iter().collect::<Vec<_>>();
/// assert_eq!(components[0], Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1)));
/// assert_eq!(components[1], Protocol::Udt);
/// assert_eq!(components[2], Protocol::Sctp(5678));
/// ```
///
#[inline]
pub fn iter(&self) -> Iter<'_> {
Iter(&self.bytes)
}
/// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty.
/// ```
/// use parity_multiaddr::{Multiaddr, Protocol};
///
/// let mut address: Multiaddr = "/ip4/127.0.0.1/udt/sctp/5678".parse().unwrap();
///
/// assert_eq!(address.pop().unwrap(), Protocol::Sctp(5678));
/// assert_eq!(address.pop().unwrap(), Protocol::Udt);
/// ```
///
pub fn pop<'a>(&mut self) -> Option<Protocol<'a>> {
// Note: could be more optimized
let mut list = self.iter().map(|p| p.acquire()).collect::<Vec<_>>();
let last_elem = list.pop();
*self = list.into_iter().collect();
last_elem
}
}
impl<'a> From<Protocol<'a>> for Multiaddr {
fn from(p: Protocol<'a>) -> Multiaddr {
let mut w = Vec::new();
p.write_bytes(&mut w).expect("writing to a Vec never fails");
Multiaddr { bytes: w.into() }
}
}
impl<'a> IntoIterator for &'a Multiaddr {
type Item = Protocol<'a>;
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Iter<'a> {
Iter(&self.bytes)
}
}
impl<'a> FromIterator<Protocol<'a>> for Multiaddr {
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = Protocol<'a>>,
{
let mut writer = Vec::new();
for cmp in iter {
cmp.write_bytes(&mut writer).expect("writing to a Vec never fails");
}
Multiaddr { bytes: writer.into() }
}
}
impl FromStr for Multiaddr {
type Err = Error;
#[inline]
fn from_str(input: &str) -> Result<Self> {
let mut writer = Vec::new();
let mut parts = input.split('/').peekable();
if Some("") != parts.next() {
// A multiaddr must start with `/`
return Err(Error::InvalidMultiaddr)
}
while parts.peek().is_some() {
let p = Protocol::from_str_parts(&mut parts)?;
p.write_bytes(&mut writer).expect("writing to a Vec never fails");
}
Ok(Multiaddr { bytes: writer.into() })
}
}
/// Iterator for the address components in a multiaddr.
pub struct Iter<'a>(&'a [u8]);
impl<'a> Iterator for Iter<'a> {
type Item = Protocol<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.0.is_empty() {
return None;
}
let (p, next_data) =
Protocol::from_bytes(self.0).expect("multiaddr is known to be valid");
self.0 = next_data;
Some(p)
}
}
/// A trait for objects which can be converted to a
/// Multiaddr.
///
/// This trait is implemented by default for
///
/// * `SocketAddr`, `SocketAddrV4` and `SocketAddrV6`, assuming that the
/// the given port is a tcp port.
///
/// * `Ipv4Addr`, `Ipv6Addr`
///
/// * `String` and `&str`, requiring the default string format for a Multiaddr.
///
pub trait ToMultiaddr {
/// Converts this object to a Multiaddr
///
/// # Errors
///
/// Any errors encountered during parsing will be returned
/// as an `Err`.
fn to_multiaddr(&self) -> Result<Multiaddr>;
}
impl ToMultiaddr for SocketAddr {
fn to_multiaddr(&self) -> Result<Multiaddr> {
match *self {
SocketAddr::V4(ref a) => (*a).to_multiaddr(),
SocketAddr::V6(ref a) => (*a).to_multiaddr(),
}
}
}
impl ToMultiaddr for SocketAddrV4 {
fn to_multiaddr(&self) -> Result<Multiaddr> {
let mut m = self.ip().to_multiaddr()?;
m.append(Protocol::Tcp(self.port()));
Ok(m)
}
}
impl ToMultiaddr for SocketAddrV6 {
fn to_multiaddr(&self) -> Result<Multiaddr> {
// TODO: Should we handle `flowinfo` and `scope_id`?
let mut m = self.ip().to_multiaddr()?;
m.append(Protocol::Tcp(self.port()));
Ok(m)
}
}
impl ToMultiaddr for IpAddr {
fn to_multiaddr(&self) -> Result<Multiaddr> {
match *self {
IpAddr::V4(ref a) => (*a).to_multiaddr(),
IpAddr::V6(ref a) => (*a).to_multiaddr(),
}
}
}
impl ToMultiaddr for Ipv4Addr {
fn to_multiaddr(&self) -> Result<Multiaddr> {
Ok(Protocol::Ip4(*self).into())
}
}
impl ToMultiaddr for Ipv6Addr {
fn to_multiaddr(&self) -> Result<Multiaddr> {
Ok(Protocol::Ip6(*self).into())
}
}
impl ToMultiaddr for String {
fn to_multiaddr(&self) -> Result<Multiaddr> {
self.parse()
}
}
impl<'a> ToMultiaddr for &'a str {
fn to_multiaddr(&self) -> Result<Multiaddr> {
self.parse()
}
}
impl ToMultiaddr for Multiaddr {
fn to_multiaddr(&self) -> Result<Multiaddr> {
Ok(self.clone())
}
}
/// Easy way for a user to create a `Multiaddr`. /// Easy way for a user to create a `Multiaddr`.
/// ///
/// Example: /// Example:
/// ///
/// ```rust /// ```rust
/// # use parity_multiaddr::multiaddr; /// # use parity_multiaddr::multiaddr;
/// # fn main() { /// let addr = multiaddr!(Ip4([127, 0, 0, 1]), Tcp(10500u16));
/// let _addr = multiaddr![Ip4([127, 0, 0, 1]), Tcp(10500u16)];
/// # }
/// ``` /// ```
/// ///
/// Each element passed to `multiaddr![]` should be a variant of the `Protocol` enum. The /// Each element passed to `multiaddr!` should be a variant of the `Protocol` enum. The
/// optional parameter is casted into the proper type with the `Into` trait. /// optional parameter is turned into the proper type with the `Into` trait.
/// ///
/// For example, `Ip4([127, 0, 0, 1])` works because `Ipv4Addr` implements `From<[u8; 4]>`. /// For example, `Ip4([127, 0, 0, 1])` works because `Ipv4Addr` implements `From<[u8; 4]>`.
#[macro_export] #[macro_export]
@ -490,3 +425,4 @@ macro_rules! multiaddr {
} }
} }
} }

View File

@ -0,0 +1,38 @@
use bytes::{BufMut, BytesMut};
/// An [`io::Write`] impl for [`BytesMut`].
///
/// In contrast to [`bytes::buf::Writer`] this [`io::Write] implementation
/// transparently reserves enough space for [`io::Write::write_all`] to
/// succeed, i.e. it does not require upfront reservation of space.
pub(crate) struct BytesWriter(pub(crate) BytesMut);
impl std::io::Write for BytesWriter {
fn write(&mut self, src: &[u8]) -> std::io::Result<usize> {
let n = std::cmp::min(self.0.remaining_mut(), src.len());
self.0.put(&src[.. n]);
Ok(n)
}
fn write_all(&mut self, mut buf: &[u8]) -> std::io::Result<()> {
if self.0.remaining_mut() < buf.len() {
self.0.reserve(buf.len() - self.0.remaining_mut());
}
while !buf.is_empty() {
match self.write(buf) {
Ok(0) => return Err(std::io::ErrorKind::WriteZero.into()),
Ok(n) => buf = &buf[n ..],
Err(e) => if e.kind() != std::io::ErrorKind::Interrupted {
return Err(e)
}
}
}
Ok(())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}

View File

@ -6,8 +6,9 @@ use quickcheck::{Arbitrary, Gen, QuickCheck};
use rand::Rng; use rand::Rng;
use std::{ use std::{
borrow::Cow, borrow::Cow,
convert::TryFrom,
iter::FromIterator, iter::FromIterator,
net::{SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr}, net::{Ipv4Addr, Ipv6Addr},
str::FromStr str::FromStr
}; };
@ -17,7 +18,7 @@ use std::{
fn to_from_bytes_identity() { fn to_from_bytes_identity() {
fn prop(a: Ma) -> bool { fn prop(a: Ma) -> bool {
let b = a.0.to_vec(); let b = a.0.to_vec();
Some(a) == Multiaddr::try_from_vec(b).ok().map(Ma) Some(a) == Multiaddr::try_from(b).ok().map(Ma)
} }
QuickCheck::new().quickcheck(prop as fn(Ma) -> bool) QuickCheck::new().quickcheck(prop as fn(Ma) -> bool)
} }
@ -31,6 +32,26 @@ fn to_from_str_identity() {
QuickCheck::new().quickcheck(prop as fn(Ma) -> bool) QuickCheck::new().quickcheck(prop as fn(Ma) -> bool)
} }
#[test]
fn byteswriter() {
fn prop(a: Ma, p: Proto) -> bool {
a.0.with(p.clone().0).pop() == Some(p.0)
}
QuickCheck::new().quickcheck(prop as fn(Ma, Proto) -> bool)
}
#[test]
fn push_pop_identity() {
fn prop(a: Ma, p: Proto) -> bool {
let mut b = a.clone();
let q = p.clone();
b.0.push(q.0);
assert_ne!(a.0, b.0);
Some(p.0) == b.0.pop() && a.0 == b.0
}
QuickCheck::new().quickcheck(prop as fn(Ma, Proto) -> bool)
}
// Arbitrary impls // Arbitrary impls
@ -105,7 +126,7 @@ fn ma_valid(source: &str, target: &str, protocols: Vec<Protocol<'_>>) {
assert_eq!(HEXUPPER.encode(&parsed.to_vec()[..]), target); assert_eq!(HEXUPPER.encode(&parsed.to_vec()[..]), target);
assert_eq!(parsed.iter().collect::<Vec<_>>(), protocols); assert_eq!(parsed.iter().collect::<Vec<_>>(), protocols);
assert_eq!(source.parse::<Multiaddr>().unwrap().to_string(), source); assert_eq!(source.parse::<Multiaddr>().unwrap().to_string(), source);
assert_eq!(Multiaddr::try_from_vec(HEXUPPER.decode(target.as_bytes()).unwrap()).unwrap(), parsed); assert_eq!(Multiaddr::try_from(HEXUPPER.decode(target.as_bytes()).unwrap()).unwrap(), parsed);
} }
fn multihash(s: &str) -> Multihash { fn multihash(s: &str) -> Multihash {
@ -221,38 +242,24 @@ fn construct_fail() {
#[test] #[test]
fn to_multiaddr() { fn to_multiaddr() {
assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_multiaddr().unwrap(), assert_eq!(Multiaddr::from(Ipv4Addr::new(127, 0, 0, 1)), "/ip4/127.0.0.1".parse().unwrap());
"/ip4/127.0.0.1".parse::<Multiaddr>().unwrap()); assert_eq!(Multiaddr::from(Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21)),
assert_eq!(Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21) "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse().unwrap());
.to_multiaddr() assert_eq!(Multiaddr::try_from("/ip4/127.0.0.1/tcp/1234".to_string()).unwrap(),
.unwrap(),
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap());
assert_eq!("/ip4/127.0.0.1/tcp/1234".to_string().to_multiaddr().unwrap(),
"/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap()); "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap());
assert_eq!("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".to_multiaddr().unwrap(), assert_eq!(Multiaddr::try_from("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21").unwrap(),
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap()); "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse::<Multiaddr>().unwrap());
assert_eq!(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 1234).to_multiaddr().unwrap(), assert_eq!(Multiaddr::from(Ipv4Addr::new(127, 0, 0, 1)).with(Protocol::Tcp(1234)),
"/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap()); "/ip4/127.0.0.1/tcp/1234".parse::<Multiaddr>().unwrap());
assert_eq!(SocketAddrV6::new(Ipv6Addr::new(0x2601, assert_eq!(Multiaddr::from(Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21))
0x9, .with(Protocol::Tcp(1234)),
0x4f81,
0x9700,
0x803e,
0xca65,
0x66e8,
0xc21),
1234,
0,
0)
.to_multiaddr()
.unwrap(),
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/tcp/1234".parse::<Multiaddr>().unwrap()); "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/tcp/1234".parse::<Multiaddr>().unwrap());
} }
#[test] #[test]
fn from_bytes_fail() { fn from_bytes_fail() {
let bytes = vec![1, 2, 3, 4]; let bytes = vec![1, 2, 3, 4];
assert!(Multiaddr::try_from_vec(bytes).is_err()); assert!(Multiaddr::try_from(bytes).is_err());
} }
@ -279,8 +286,8 @@ fn ser_and_deser_bincode() {
#[test] #[test]
fn append() { fn append() {
let mut a: Multiaddr = Protocol::Ip4(Ipv4Addr::new(1, 2, 3, 4)).into(); let mut a: Multiaddr = Protocol::Ip4(Ipv4Addr::new(1, 2, 3, 4)).into();
a.append(Protocol::Tcp(80)); a.push(Protocol::Tcp(80));
a.append(Protocol::Http); a.push(Protocol::Http);
let mut i = a.iter(); let mut i = a.iter();
assert_eq!(Some(Protocol::Ip4(Ipv4Addr::new(1, 2, 3, 4))), i.next()); assert_eq!(Some(Protocol::Ip4(Ipv4Addr::new(1, 2, 3, 4))), i.next());
@ -288,3 +295,32 @@ fn append() {
assert_eq!(Some(Protocol::Http), i.next()); assert_eq!(Some(Protocol::Http), i.next());
assert_eq!(None, i.next()) assert_eq!(None, i.next())
} }
fn replace_ip_addr(a: &Multiaddr, p: Protocol) -> Option<Multiaddr> {
a.replace(0, move |x| match x {
Protocol::Ip4(_) | Protocol::Ip6(_) => Some(p),
_ => None
})
}
#[test]
fn replace_ip4_with_ip4() {
let server = multiaddr!(Ip4(Ipv4Addr::LOCALHOST), Tcp(10000u16));
let result = replace_ip_addr(&server, Protocol::Ip4([80, 81, 82, 83].into())).unwrap();
assert_eq!(result, multiaddr!(Ip4([80, 81, 82, 83]), Tcp(10000u16)))
}
#[test]
fn replace_ip6_with_ip4() {
let server = multiaddr!(Ip6(Ipv6Addr::LOCALHOST), Tcp(10000u16));
let result = replace_ip_addr(&server, Protocol::Ip4([80, 81, 82, 83].into())).unwrap();
assert_eq!(result, multiaddr!(Ip4([80, 81, 82, 83]), Tcp(10000u16)))
}
#[test]
fn replace_ip4_with_ip6() {
let server = multiaddr!(Ip4(Ipv4Addr::LOCALHOST), Tcp(10000u16));
let result = replace_ip_addr(&server, "2001:db8::1".parse::<Ipv6Addr>().unwrap().into());
assert_eq!(result.unwrap(), "/ip6/2001:db8::1/tcp/10000".parse::<Multiaddr>().unwrap())
}

View File

@ -74,12 +74,10 @@ where
fn(TMuxer) -> MapErr<IdRetriever<TMuxer>, fn(UpgradeError<IoError>) -> Self::Error> fn(TMuxer) -> MapErr<IdRetriever<TMuxer>, fn(UpgradeError<IoError>) -> Self::Error>
>; >;
#[inline]
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> { fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
Err(TransportError::MultiaddrNotSupported(addr)) Err(TransportError::MultiaddrNotSupported(addr))
} }
#[inline]
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> { fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
// We dial a first time the node. // We dial a first time the node.
let dial = self.transport.dial(addr) let dial = self.transport.dial(addr)
@ -88,11 +86,6 @@ where
IdRetriever::new(muxer, IdentifyProtocolConfig).map_err(TransportUpgradeError::Upgrade) IdRetriever::new(muxer, IdentifyProtocolConfig).map_err(TransportUpgradeError::Upgrade)
})) }))
} }
#[inline]
fn nat_traversal(&self, a: &Multiaddr, b: &Multiaddr) -> Option<Multiaddr> {
self.transport.nat_traversal(a, b)
}
} }
/// Implementation of `Future` that asks the remote of its `PeerId`. /// Implementation of `Future` that asks the remote of its `PeerId`.

View File

@ -30,6 +30,7 @@ use log::{debug, trace};
use protobuf::Message as ProtobufMessage; use protobuf::Message as ProtobufMessage;
use protobuf::parse_from_bytes as protobuf_parse_from_bytes; use protobuf::parse_from_bytes as protobuf_parse_from_bytes;
use protobuf::RepeatedField; use protobuf::RepeatedField;
use std::convert::TryFrom;
use std::io::{Error as IoError, ErrorKind as IoErrorKind}; use std::io::{Error as IoError, ErrorKind as IoErrorKind};
use std::iter; use std::iter;
use tokio_codec::Framed; use tokio_codec::Framed;
@ -234,7 +235,7 @@ fn parse_proto_msg(msg: BytesMut) -> Result<(IdentifyInfo, Multiaddr), IoError>
// Turn a `Vec<u8>` into a `Multiaddr`. If something bad happens, turn it into // Turn a `Vec<u8>` into a `Multiaddr`. If something bad happens, turn it into
// an `IoError`. // an `IoError`.
fn bytes_to_multiaddr(bytes: Vec<u8>) -> Result<Multiaddr, IoError> { fn bytes_to_multiaddr(bytes: Vec<u8>) -> Result<Multiaddr, IoError> {
Multiaddr::try_from_vec(bytes) Multiaddr::try_from(bytes)
.map_err(|err| IoError::new(IoErrorKind::InvalidData, err)) .map_err(|err| IoError::new(IoErrorKind::InvalidData, err))
} }

View File

@ -214,10 +214,7 @@ fn unresponsive_not_returned_direct() {
// Add fake addresses. // Add fake addresses.
for _ in 0 .. 10 { for _ in 0 .. 10 {
swarms[0].add_not_connected_address( swarms[0].add_not_connected_address(&PeerId::random(), Protocol::Udp(10u16).into());
&PeerId::random(),
libp2p_core::multiaddr::multiaddr![Udp(10u16)]
);
} }
// Ask first to search a random value. // Ask first to search a random value.

View File

@ -32,6 +32,7 @@ use futures::{future, sink, stream, Sink, Stream};
use libp2p_core::{InboundUpgrade, Multiaddr, OutboundUpgrade, PeerId, UpgradeInfo, upgrade::Negotiated}; use libp2p_core::{InboundUpgrade, Multiaddr, OutboundUpgrade, PeerId, UpgradeInfo, upgrade::Negotiated};
use multihash::Multihash; use multihash::Multihash;
use protobuf::{self, Message}; use protobuf::{self, Message};
use std::convert::TryFrom;
use std::io::{Error as IoError, ErrorKind as IoErrorKind}; use std::io::{Error as IoError, ErrorKind as IoErrorKind};
use std::iter; use std::iter;
use tokio_codec::Framed; use tokio_codec::Framed;
@ -103,7 +104,7 @@ impl KadPeer {
let mut addrs = Vec::with_capacity(peer.get_addrs().len()); let mut addrs = Vec::with_capacity(peer.get_addrs().len());
for addr in peer.take_addrs().into_iter() { for addr in peer.take_addrs().into_iter() {
let as_ma = Multiaddr::try_from_vec(addr) let as_ma = Multiaddr::try_from(addr)
.map_err(|err| IoError::new(IoErrorKind::InvalidData, err))?; .map_err(|err| IoError::new(IoErrorKind::InvalidData, err))?;
addrs.push(as_ma); addrs.push(as_ma);
} }

View File

@ -24,7 +24,7 @@
use bytes::Bytes; use bytes::Bytes;
use futures::{future, prelude::*}; use futures::{future, prelude::*};
use libp2p_core::{Multiaddr, upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo, Negotiated}}; use libp2p_core::{Multiaddr, upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo, Negotiated}};
use std::{io, iter}; use std::{convert::TryFrom, io, iter};
use tokio_codec::{FramedRead, FramedWrite}; use tokio_codec::{FramedRead, FramedWrite};
use tokio_io::{AsyncRead, AsyncWrite}; use tokio_io::{AsyncRead, AsyncWrite};
use unsigned_varint::codec::UviBytes; use unsigned_varint::codec::UviBytes;
@ -75,7 +75,7 @@ where
.map_err(|(e, _): (io::Error, FramedRead<Negotiated<C>, UviBytes>)| e) .map_err(|(e, _): (io::Error, FramedRead<Negotiated<C>, UviBytes>)| e)
.and_then(move |(bytes, _)| { .and_then(move |(bytes, _)| {
if let Some(b) = bytes { if let Some(b) = bytes {
let ma = Multiaddr::try_from_vec(b.to_vec()) let ma = Multiaddr::try_from(b)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
Ok(ma) Ok(ma)
} else { } else {

View File

@ -78,10 +78,6 @@ where
.dial(addr) .dial(addr)
.map(move |fut| BandwidthFuture { inner: fut, sinks }) .map(move |fut| BandwidthFuture { inner: fut, sinks })
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.inner.nat_traversal(server, observed)
}
} }
/// Wraps around a `Stream` that produces connections. Wraps each connection around a bandwidth /// Wraps around a `Stream` that produces connections. Wraps each connection around a bandwidth

View File

@ -222,7 +222,6 @@ use std::{error, time::Duration};
/// ///
/// > **Note**: This `Transport` is not suitable for production usage, as its implementation /// > **Note**: This `Transport` is not suitable for production usage, as its implementation
/// > reserves the right to support additional protocols or remove deprecated protocols. /// > reserves the right to support additional protocols or remove deprecated protocols.
#[inline]
pub fn build_development_transport(keypair: identity::Keypair) pub fn build_development_transport(keypair: identity::Keypair)
-> impl Transport<Output = (PeerId, impl core::muxing::StreamMuxer<OutboundSubstream = impl Send, Substream = impl Send> + Send + Sync), Error = impl error::Error + Send, Listener = impl Send, Dial = impl Send, ListenerUpgrade = impl Send> + Clone -> impl Transport<Output = (PeerId, impl core::muxing::StreamMuxer<OutboundSubstream = impl Send, Substream = impl Send> + Send + Sync), Error = impl error::Error + Send, Listener = impl Send, Dial = impl Send, ListenerUpgrade = impl Send> + Clone
{ {
@ -280,7 +279,6 @@ struct CommonTransportInner {
impl CommonTransport { impl CommonTransport {
/// Initializes the `CommonTransport`. /// Initializes the `CommonTransport`.
#[inline]
#[cfg(not(any(target_os = "emscripten", target_os = "unknown")))] #[cfg(not(any(target_os = "emscripten", target_os = "unknown")))]
pub fn new() -> CommonTransport { pub fn new() -> CommonTransport {
let tcp = tcp::TcpConfig::new().nodelay(true); let tcp = tcp::TcpConfig::new().nodelay(true);
@ -297,7 +295,6 @@ impl CommonTransport {
} }
/// Initializes the `CommonTransport`. /// Initializes the `CommonTransport`.
#[inline]
#[cfg(all(any(target_os = "emscripten", target_os = "unknown"), feature = "libp2p-websocket"))] #[cfg(all(any(target_os = "emscripten", target_os = "unknown"), feature = "libp2p-websocket"))]
pub fn new() -> CommonTransport { pub fn new() -> CommonTransport {
let inner = websocket::BrowserWsConfig::new(); let inner = websocket::BrowserWsConfig::new();
@ -307,7 +304,6 @@ impl CommonTransport {
} }
/// Initializes the `CommonTransport`. /// Initializes the `CommonTransport`.
#[inline]
#[cfg(all(any(target_os = "emscripten", target_os = "unknown"), not(feature = "libp2p-websocket")))] #[cfg(all(any(target_os = "emscripten", target_os = "unknown"), not(feature = "libp2p-websocket")))]
pub fn new() -> CommonTransport { pub fn new() -> CommonTransport {
let inner = core::transport::dummy::DummyTransport::new(); let inner = core::transport::dummy::DummyTransport::new();
@ -324,18 +320,11 @@ impl Transport for CommonTransport {
type ListenerUpgrade = <InnerImplementation as Transport>::ListenerUpgrade; type ListenerUpgrade = <InnerImplementation as Transport>::ListenerUpgrade;
type Dial = <InnerImplementation as Transport>::Dial; type Dial = <InnerImplementation as Transport>::Dial;
#[inline]
fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> { fn listen_on(self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
self.inner.inner.listen_on(addr) self.inner.inner.listen_on(addr)
} }
#[inline]
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> { fn dial(self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
self.inner.inner.dial(addr) self.inner.inner.dial(addr)
} }
#[inline]
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.inner.inner.nat_traversal(server, observed)
}
} }

View File

@ -55,13 +55,11 @@ pub struct DnsConfig<T> {
impl<T> DnsConfig<T> { impl<T> DnsConfig<T> {
/// Creates a new configuration object for DNS. /// Creates a new configuration object for DNS.
#[inline]
pub fn new(inner: T) -> DnsConfig<T> { pub fn new(inner: T) -> DnsConfig<T> {
DnsConfig::with_resolve_threads(inner, 1) DnsConfig::with_resolve_threads(inner, 1)
} }
/// Same as `new`, but allows specifying a number of threads for the resolving. /// Same as `new`, but allows specifying a number of threads for the resolving.
#[inline]
pub fn with_resolve_threads(inner: T, num_threads: usize) -> DnsConfig<T> { pub fn with_resolve_threads(inner: T, num_threads: usize) -> DnsConfig<T> {
trace!("Created a CpuPoolResolver"); trace!("Created a CpuPoolResolver");
@ -76,7 +74,6 @@ impl<T> fmt::Debug for DnsConfig<T>
where where
T: fmt::Debug, T: fmt::Debug,
{ {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_tuple("DnsConfig").field(&self.inner).finish() fmt.debug_tuple("DnsConfig").field(&self.inner).finish()
} }
@ -159,13 +156,6 @@ where
let new_addr = JoinFuture { addr, future: future::join_all(resolve_iters) }; let new_addr = JoinFuture { addr, future: future::join_all(resolve_iters) };
Ok(Either::B(DialFuture { trans: Some(self.inner), future: Either::A(new_addr) })) Ok(Either::B(DialFuture { trans: Some(self.inner), future: Either::A(new_addr) }))
} }
#[inline]
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
// Since `listen_on` doesn't perform any resolution, we just pass through `nat_traversal`
// as well.
self.inner.nat_traversal(server, observed)
}
} }
/// Error that can be generated by the DNS layer. /// Error that can be generated by the DNS layer.
@ -324,6 +314,7 @@ mod tests {
fn basic_resolve() { fn basic_resolve() {
#[derive(Clone)] #[derive(Clone)]
struct CustomTransport; struct CustomTransport;
impl Transport for CustomTransport { impl Transport for CustomTransport {
type Output = <TcpConfig as Transport>::Output; type Output = <TcpConfig as Transport>::Output;
type Error = <TcpConfig as Transport>::Error; type Error = <TcpConfig as Transport>::Error;
@ -331,11 +322,7 @@ mod tests {
type ListenerUpgrade = <TcpConfig as Transport>::ListenerUpgrade; type ListenerUpgrade = <TcpConfig as Transport>::ListenerUpgrade;
type Dial = future::Empty<Self::Output, Self::Error>; type Dial = future::Empty<Self::Output, Self::Error>;
#[inline] fn listen_on(self, _: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
fn listen_on(
self,
_addr: Multiaddr,
) -> Result<Self::Listener, TransportError<Self::Error>> {
unreachable!() unreachable!()
} }
@ -353,11 +340,6 @@ mod tests {
}; };
Ok(future::empty()) Ok(future::empty())
} }
#[inline]
fn nat_traversal(&self, _: &Multiaddr, _: &Multiaddr) -> Option<Multiaddr> {
panic!()
}
} }
let transport = DnsConfig::new(CustomTransport); let transport = DnsConfig::new(CustomTransport);

View File

@ -209,10 +209,6 @@ where
let dial = self.value.dial(addr).map_err(|err| err.map(RateLimitedErr::Underlying))?; let dial = self.value.dial(addr).map_err(|err| err.map(RateLimitedErr::Underlying))?;
Ok(DialFuture { r, w, f: dial }) Ok(DialFuture { r, w, f: dial })
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.value.nat_traversal(server, observed)
}
} }
/// Future to avoid boxing. /// Future to avoid boxing.

View File

@ -209,26 +209,6 @@ impl Transport for TcpConfig {
Ok(future) Ok(future)
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
let mut address = Multiaddr::empty();
// Use the observed IP address.
match server.iter().zip(observed.iter()).next() {
Some((Protocol::Ip4(_), x @ Protocol::Ip4(_))) => address.append(x),
Some((Protocol::Ip6(_), x @ Protocol::Ip4(_))) => address.append(x),
Some((Protocol::Ip4(_), x @ Protocol::Ip6(_))) => address.append(x),
Some((Protocol::Ip6(_), x @ Protocol::Ip6(_))) => address.append(x),
_ => return None
}
// Carry over everything else from the server address.
for proto in server.iter().skip(1) {
address.append(proto)
}
Some(address)
}
} }
// This type of logic should probably be moved into the multiaddr package // This type of logic should probably be moved into the multiaddr package
@ -702,46 +682,4 @@ mod tests {
.unwrap(); .unwrap();
assert!(tcp.listen_on(addr).is_err()); assert!(tcp.listen_on(addr).is_err());
} }
#[test]
fn nat_traversal() {
let tcp = TcpConfig::new();
let server = "/ip4/127.0.0.1/tcp/10000".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000".parse::<Multiaddr>().unwrap();
let out = tcp.nat_traversal(&server, &observed);
assert_eq!(
out.unwrap(),
"/ip4/80.81.82.83/tcp/10000".parse::<Multiaddr>().unwrap()
);
}
#[test]
fn nat_traversal_ipv6_to_ipv4() {
let tcp = TcpConfig::new();
let server = "/ip6/::1/tcp/10000".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000".parse::<Multiaddr>().unwrap();
let out = tcp.nat_traversal(&server, &observed);
assert_eq!(
out.unwrap(),
"/ip4/80.81.82.83/tcp/10000".parse::<Multiaddr>().unwrap()
);
}
#[test]
fn nat_traversal_ipv4_to_ipv6() {
let tcp = TcpConfig::new();
let server = "/ip4/127.0.0.1/tcp/10000".parse::<Multiaddr>().unwrap();
let observed = "/ip6/2001:db8::1/tcp/25000".parse::<Multiaddr>().unwrap();
let out = tcp.nat_traversal(&server, &observed);
assert_eq!(
out.unwrap(),
"/ip6/2001:db8::1/tcp/10000".parse::<Multiaddr>().unwrap()
);
}
} }

View File

@ -107,14 +107,6 @@ impl Transport for UdsConfig {
Err(TransportError::MultiaddrNotSupported(addr)) Err(TransportError::MultiaddrNotSupported(addr))
} }
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
if server == observed {
Some(observed.clone())
} else {
None
}
}
} }
/// Turns a `Multiaddr` containing a single `Unix` component into a path. /// Turns a `Multiaddr` containing a single `Unix` component into a path.

View File

@ -59,7 +59,6 @@ impl Transport for BrowserWsConfig {
type ListenerUpgrade = future::Empty<Self::Output, IoError>; type ListenerUpgrade = future::Empty<Self::Output, IoError>;
type Dial = Box<Future<Item = Self::Output, Error = IoError> + Send>; type Dial = Box<Future<Item = Self::Output, Error = IoError> + Send>;
#[inline]
fn listen_on(self, a: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> { fn listen_on(self, a: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>> {
// Listening is never supported. // Listening is never supported.
Err(TransportError::MultiaddrNotSupported(a)) Err(TransportError::MultiaddrNotSupported(a))
@ -208,43 +207,6 @@ impl Transport for BrowserWsConfig {
} }
})) as Box<_>) })) as Box<_>)
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
let mut address = Multiaddr::empty();
let mut iter = server.iter().zip(observed.iter());
// Use the observed IP address.
match iter.next() {
Some((Protocol::Ip4(_), x@Protocol::Ip4(_))) => address.append(x),
Some((Protocol::Ip6(_), x@Protocol::Ip6(_))) => address.append(x),
_ => return None
}
// Skip over next protocol (assumed to contain port information).
if iter.next().is_none() {
return None
}
// Check for WS/WSS.
//
// Note that it will still work if the server uses WSS while the client uses
// WS, or vice-versa.
match iter.next() {
Some((x@Protocol::Ws, Protocol::Ws)) => address.append(x),
Some((x@Protocol::Ws, Protocol::Wss)) => address.append(x),
Some((x@Protocol::Wss, Protocol::Ws)) => address.append(x),
Some((x@Protocol::Wss, Protocol::Wss)) => address.append(x),
_ => return None
}
// Carry over everything else from the server address.
for proto in server.iter().skip(3) {
address.append(proto)
}
Some(address)
}
} }
pub struct BrowserWsConn { pub struct BrowserWsConn {

View File

@ -87,17 +87,17 @@ where
let listen = inner_listen.map_err(WsError::Underlying).map(|event| { let listen = inner_listen.map_err(WsError::Underlying).map(|event| {
match event { match event {
ListenerEvent::NewAddress(mut a) => { ListenerEvent::NewAddress(mut a) => {
a.append(Protocol::Ws); a = a.with(Protocol::Ws);
debug!("Listening on {}", a); debug!("Listening on {}", a);
ListenerEvent::NewAddress(a) ListenerEvent::NewAddress(a)
} }
ListenerEvent::AddressExpired(mut a) => { ListenerEvent::AddressExpired(mut a) => {
a.append(Protocol::Ws); a = a.with(Protocol::Ws);
ListenerEvent::AddressExpired(a) ListenerEvent::AddressExpired(a)
} }
ListenerEvent::Upgrade { upgrade, mut listen_addr, mut remote_addr } => { ListenerEvent::Upgrade { upgrade, mut listen_addr, mut remote_addr } => {
listen_addr.append(Protocol::Ws); listen_addr = listen_addr.with(Protocol::Ws);
remote_addr.append(Protocol::Ws); remote_addr = remote_addr.with(Protocol::Ws);
// Upgrade the listener to websockets like the websockets library requires us to do. // Upgrade the listener to websockets like the websockets library requires us to do.
let upgraded = upgrade.map_err(WsError::Underlying).and_then(move |stream| { let upgraded = upgrade.map_err(WsError::Underlying).and_then(move |stream| {
@ -206,10 +206,6 @@ where
Ok(Box::new(dial) as Box<_>) Ok(Box::new(dial) as Box<_>)
} }
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
self.transport.nat_traversal(server, observed)
}
} }
/// Error in WebSockets. /// Error in WebSockets.
@ -352,61 +348,4 @@ mod tests {
let mut rt = Runtime::new().unwrap(); let mut rt = Runtime::new().unwrap();
let _ = rt.block_on(future).unwrap(); let _ = rt.block_on(future).unwrap();
} }
#[test]
fn nat_traversal() {
let ws_config = WsConfig::new(tcp::TcpConfig::new());
{
let server = "/ip4/127.0.0.1/tcp/10000/ws".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000/ws"
.parse::<Multiaddr>()
.unwrap();
assert_eq!(
ws_config.nat_traversal(&server, &observed).unwrap(),
"/ip4/80.81.82.83/tcp/10000/ws"
.parse::<Multiaddr>()
.unwrap()
);
}
{
let server = "/ip4/127.0.0.1/tcp/10000/wss".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000/wss"
.parse::<Multiaddr>()
.unwrap();
assert_eq!(
ws_config.nat_traversal(&server, &observed).unwrap(),
"/ip4/80.81.82.83/tcp/10000/wss"
.parse::<Multiaddr>()
.unwrap()
);
}
{
let server = "/ip4/127.0.0.1/tcp/10000/ws".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000/wss"
.parse::<Multiaddr>()
.unwrap();
assert_eq!(
ws_config.nat_traversal(&server, &observed).unwrap(),
"/ip4/80.81.82.83/tcp/10000/ws"
.parse::<Multiaddr>()
.unwrap()
);
}
{
let server = "/ip4/127.0.0.1/tcp/10000/wss".parse::<Multiaddr>().unwrap();
let observed = "/ip4/80.81.82.83/tcp/25000/ws"
.parse::<Multiaddr>()
.unwrap();
assert_eq!(
ws_config.nat_traversal(&server, &observed).unwrap(),
"/ip4/80.81.82.83/tcp/10000/wss"
.parse::<Multiaddr>()
.unwrap()
);
}
}
} }