mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-20 21:36:31 +00:00
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:
@ -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 {
|
||||||
|
@ -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.
|
||||||
|
@ -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());
|
||||||
|
@ -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> {
|
||||||
|
@ -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
43
core/src/translation.rs
Normal 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
|
@ -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.
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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`.
|
||||||
|
@ -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`.
|
||||||
|
@ -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),
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
38
misc/multiaddr/src/util.rs
Normal file
38
misc/multiaddr/src/util.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -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())
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -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`.
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
11
src/lib.rs
11
src/lib.rs
@ -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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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 {
|
||||||
|
@ -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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user