mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-04-25 11:02:12 +00:00
Refactor multiaddr crate. (#498)
Refactor multiaddr crate. - Remove `AddrComponent`. Instead `Protocol` directly contains its associated data. - Various smaller changes around conversions to Multiaddr from other types, e.g. socket addresses. - Expand tests to include property tests which test encoding/decoding identity.
This commit is contained in:
parent
1969bde4fe
commit
84b089cacc
@ -253,7 +253,7 @@ pub mod transport;
|
||||
pub mod upgrade;
|
||||
|
||||
pub use self::connection_reuse::ConnectionReuse;
|
||||
pub use self::multiaddr::{AddrComponent, Multiaddr};
|
||||
pub use self::multiaddr::Multiaddr;
|
||||
pub use self::muxing::StreamMuxer;
|
||||
pub use self::peer_id::PeerId;
|
||||
pub use self::public_key::PublicKey;
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
use bytes::{Bytes, IntoBuf};
|
||||
use futures::{future::{self, FutureResult}, prelude::*, stream, sync::mpsc};
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use parking_lot::Mutex;
|
||||
use rw_stream_sink::RwStreamSink;
|
||||
use std::{io, sync::Arc};
|
||||
@ -132,7 +132,7 @@ impl<T: IntoBuf + Send + 'static> Transport for Listener<T> {
|
||||
/// Returns `true` if and only if the address is `/memory`.
|
||||
fn is_memory_addr(a: &Multiaddr) -> bool {
|
||||
let mut iter = a.iter();
|
||||
if iter.next() != Some(AddrComponent::Memory) {
|
||||
if iter.next() != Some(Protocol::Memory) {
|
||||
return false;
|
||||
}
|
||||
if iter.next().is_some() {
|
||||
|
@ -197,7 +197,7 @@ fn main() {
|
||||
|
||||
let finish_enum = kad_system
|
||||
.find_node(my_peer_id.clone(), |peer| {
|
||||
let addr = Multiaddr::from(libp2p::multiaddr::AddrComponent::P2P(peer.clone().into()));
|
||||
let addr = Multiaddr::from(libp2p::multiaddr::Protocol::P2p(peer.clone().into()));
|
||||
active_kad_connections.lock().unwrap().entry(peer.clone())
|
||||
.or_insert_with(Default::default)
|
||||
.dial(&swarm_controller, &addr, transport.clone().with_upgrade(KadConnecConfig::new()))
|
||||
@ -249,7 +249,7 @@ fn p2p_multiaddr_to_node_id(client_addr: Multiaddr) -> PeerId {
|
||||
second = iter.next();
|
||||
}
|
||||
match (first, second) {
|
||||
(Some(libp2p::multiaddr::AddrComponent::P2P(node_id)), None) =>
|
||||
(Some(libp2p::multiaddr::Protocol::P2p(node_id)), None) =>
|
||||
PeerId::from_multihash(node_id).expect("libp2p always reports a valid node id"),
|
||||
_ => panic!("Reported multiaddress is in the wrong format ; programmer error")
|
||||
}
|
||||
@ -274,7 +274,7 @@ where
|
||||
|
||||
let p2p_component = multiaddr.pop().expect("hard-coded multiaddr is empty");
|
||||
let peer = match p2p_component {
|
||||
libp2p::multiaddr::AddrComponent::P2P(key) => {
|
||||
libp2p::multiaddr::Protocol::P2p(key) => {
|
||||
PeerId::from_multihash(key).expect("invalid peer id")
|
||||
}
|
||||
_ => panic!("hard-coded multiaddr didn't end with /p2p/"),
|
||||
|
@ -10,12 +10,16 @@ version = "0.3.0"
|
||||
|
||||
[dependencies]
|
||||
bs58 = "0.2.0"
|
||||
byteorder = "~0.4"
|
||||
byteorder = "0.4"
|
||||
multihash = { path = "../multihash" }
|
||||
serde = "1.0.70"
|
||||
unsigned-varint = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
data-encoding = "~1.1.2"
|
||||
serde_json = "1.0"
|
||||
bincode = "1.0.1"
|
||||
bincode = "1"
|
||||
bs58 = "0.2.0"
|
||||
data-encoding = "2"
|
||||
multihash = { path = "../multihash" }
|
||||
quickcheck = "0.7"
|
||||
rand = "0.5"
|
||||
serde_json = "1.0"
|
@ -9,23 +9,25 @@ pub type Result<T> = ::std::result::Result<T, Error>;
|
||||
/// Error types
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
UnknownProtocol,
|
||||
UnknownProtocolString,
|
||||
DataLessThanLen,
|
||||
InvalidMultiaddr,
|
||||
MissingAddress,
|
||||
ParsingError(Box<error::Error + Send + Sync>),
|
||||
InvalidUvar(decode::Error)
|
||||
InvalidProtocolString,
|
||||
InvalidUvar(decode::Error),
|
||||
ParsingError(Box<dyn error::Error + Send + Sync>),
|
||||
UnknownProtocolId(u32),
|
||||
UnknownProtocolString
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Error::UnknownProtocol => f.write_str("unknown protocol"),
|
||||
Error::UnknownProtocolString => f.write_str("unknown protocol string"),
|
||||
Error::DataLessThanLen => f.write_str("we have less data than indicated by length"),
|
||||
Error::InvalidMultiaddr => f.write_str("invalid multiaddr"),
|
||||
Error::MissingAddress => f.write_str("protocol requires address, none given"),
|
||||
Error::InvalidProtocolString => f.write_str("invalid protocol string"),
|
||||
Error::InvalidUvar(e) => write!(f, "failed to decode unsigned varint: {}", e),
|
||||
Error::ParsingError(e) => write!(f, "failed to parse: {}", e),
|
||||
Error::InvalidUvar(e) => write!(f, "failed to decode unsigned varint: {}", e)
|
||||
Error::UnknownProtocolId(id) => write!(f, "unknown protocol id: {}", id),
|
||||
Error::UnknownProtocolString => f.write_str("unknown protocol string")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,22 +12,26 @@ pub extern crate multihash;
|
||||
mod protocol;
|
||||
mod errors;
|
||||
|
||||
use serde::{
|
||||
Deserialize,
|
||||
Deserializer,
|
||||
Serialize,
|
||||
Serializer,
|
||||
de::{self, Error as DeserializerError}
|
||||
};
|
||||
use std::{
|
||||
fmt,
|
||||
iter::FromIterator,
|
||||
net::{SocketAddr, SocketAddrV4, SocketAddrV6, IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
result::Result as StdResult,
|
||||
str::FromStr
|
||||
};
|
||||
pub use errors::{Result, Error};
|
||||
pub use protocol::{Protocol, ProtocolArgSize, AddrComponent};
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeserializerError};
|
||||
|
||||
use std::fmt;
|
||||
use std::result::Result as StdResult;
|
||||
use std::iter::FromIterator;
|
||||
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6, IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use std::str::FromStr;
|
||||
pub use protocol::Protocol;
|
||||
|
||||
/// Representation of a Multiaddr.
|
||||
#[derive(PartialEq, Eq, Clone, Hash)]
|
||||
pub struct Multiaddr {
|
||||
bytes: Vec<u8>,
|
||||
}
|
||||
pub struct Multiaddr { bytes: Vec<u8> }
|
||||
|
||||
impl Serialize for Multiaddr {
|
||||
fn serialize<S>(&self, serializer: S) -> StdResult<S::Ok, S::Error>
|
||||
@ -35,7 +39,6 @@ impl Serialize for Multiaddr {
|
||||
S: Serializer,
|
||||
{
|
||||
if serializer.is_human_readable() {
|
||||
// Serialize to a human-readable string "2015-05-15T17:01:00Z".
|
||||
self.to_string().serialize(serializer)
|
||||
} else {
|
||||
self.to_bytes().serialize(serializer)
|
||||
@ -48,12 +51,38 @@ impl<'de> Deserialize<'de> for Multiaddr {
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct Visitor;
|
||||
|
||||
impl<'de> de::Visitor<'de> for Visitor {
|
||||
type Value = Multiaddr;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("multiaddress")
|
||||
}
|
||||
fn visit_str<E: de::Error>(self, v: &str) -> StdResult<Self::Value, E> {
|
||||
v.parse().map_err(DeserializerError::custom)
|
||||
}
|
||||
fn visit_borrowed_str<E: de::Error>(self, v: &'de str) -> StdResult<Self::Value, E> {
|
||||
self.visit_str(v)
|
||||
}
|
||||
fn visit_string<E: de::Error>(self, v: String) -> StdResult<Self::Value, E> {
|
||||
self.visit_str(&v)
|
||||
}
|
||||
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> StdResult<Self::Value, E> {
|
||||
self.visit_byte_buf(v.into())
|
||||
}
|
||||
fn visit_borrowed_bytes<E: de::Error>(self, v: &'de [u8]) -> StdResult<Self::Value, E> {
|
||||
self.visit_byte_buf(v.into())
|
||||
}
|
||||
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> StdResult<Self::Value, E> {
|
||||
Multiaddr::from_bytes(v).map_err(DeserializerError::custom)
|
||||
}
|
||||
}
|
||||
|
||||
if deserializer.is_human_readable() {
|
||||
let addr: String = Deserialize::deserialize(deserializer)?;
|
||||
addr.parse::<Multiaddr>().map_err(|err| DeserializerError::custom(err))
|
||||
deserializer.deserialize_str(Visitor)
|
||||
} else {
|
||||
let addr: Vec<u8> = Deserialize::deserialize(deserializer)?;
|
||||
Multiaddr::from_bytes(addr).map_err(|err| DeserializerError::custom(err))
|
||||
deserializer.deserialize_bytes(Visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,7 +124,7 @@ impl Multiaddr {
|
||||
|
||||
/// Return a copy to disallow changing the bytes directly
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
self.bytes.to_owned()
|
||||
self.bytes.clone()
|
||||
}
|
||||
|
||||
/// Produces a `Multiaddr` from its bytes representation.
|
||||
@ -103,11 +132,10 @@ impl Multiaddr {
|
||||
{
|
||||
let mut ptr = &bytes[..];
|
||||
while !ptr.is_empty() {
|
||||
let (_, new_ptr) = AddrComponent::from_bytes(ptr)?;
|
||||
let (_, new_ptr) = Protocol::from_bytes(ptr)?;
|
||||
ptr = new_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Multiaddr { bytes })
|
||||
}
|
||||
|
||||
@ -116,25 +144,6 @@ impl Multiaddr {
|
||||
&self.bytes
|
||||
}
|
||||
|
||||
/// Return a list of protocols
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A single protocol
|
||||
///
|
||||
/// ```
|
||||
/// use multiaddr::{Multiaddr, Protocol};
|
||||
///
|
||||
/// let address: Multiaddr = "/ip4/127.0.0.1".parse().unwrap();
|
||||
/// assert_eq!(address.protocol(), vec![Protocol::IP4]);
|
||||
/// ```
|
||||
///
|
||||
#[inline]
|
||||
#[deprecated(note = "Use `self.iter().map(|addr| addr.protocol_id())` instead")]
|
||||
pub fn protocol(&self) -> Vec<Protocol> {
|
||||
self.iter().map(|addr| addr.protocol_id()).collect()
|
||||
}
|
||||
|
||||
/// Wrap a given Multiaddr and return the combination.
|
||||
///
|
||||
/// # Examples
|
||||
@ -150,10 +159,8 @@ impl Multiaddr {
|
||||
pub fn encapsulate<T: ToMultiaddr>(&self, input: T) -> Result<Multiaddr> {
|
||||
let new = input.to_multiaddr()?;
|
||||
let mut bytes = self.bytes.clone();
|
||||
|
||||
bytes.extend(new.to_bytes());
|
||||
|
||||
Ok(Multiaddr { bytes: bytes })
|
||||
Ok(Multiaddr { bytes })
|
||||
}
|
||||
|
||||
/// Adds an already-parsed address component to the end of this multiaddr.
|
||||
@ -161,18 +168,18 @@ impl Multiaddr {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use multiaddr::{Multiaddr, AddrComponent};
|
||||
/// use multiaddr::{Multiaddr, Protocol};
|
||||
///
|
||||
/// let mut address: Multiaddr = "/ip4/127.0.0.1".parse().unwrap();
|
||||
/// address.append(AddrComponent::TCP(10000));
|
||||
/// address.append(Protocol::Tcp(10000));
|
||||
/// assert_eq!(address, "/ip4/127.0.0.1/tcp/10000".parse().unwrap());
|
||||
/// ```
|
||||
///
|
||||
#[inline]
|
||||
pub fn append(&mut self, component: AddrComponent) {
|
||||
component.write_bytes(&mut self.bytes).expect(
|
||||
"writing to a Vec never fails",
|
||||
)
|
||||
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.
|
||||
@ -218,7 +225,7 @@ impl Multiaddr {
|
||||
continue;
|
||||
}
|
||||
|
||||
if &self.bytes[i..next] == input.as_slice() {
|
||||
if self.bytes[i..next] == input[..] {
|
||||
matches = true;
|
||||
input_pos = i;
|
||||
break;
|
||||
@ -232,22 +239,21 @@ impl Multiaddr {
|
||||
let mut bytes = self.bytes.clone();
|
||||
bytes.truncate(input_pos);
|
||||
|
||||
Ok(Multiaddr { bytes: bytes })
|
||||
Ok(Multiaddr { bytes })
|
||||
}
|
||||
|
||||
/// Returns the components of this multiaddress.
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::Ipv4Addr;
|
||||
/// use multiaddr::AddrComponent;
|
||||
/// use multiaddr::Multiaddr;
|
||||
/// use 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], AddrComponent::IP4(Ipv4Addr::new(127, 0, 0, 1)));
|
||||
/// assert_eq!(components[1], AddrComponent::UDT);
|
||||
/// assert_eq!(components[2], AddrComponent::SCTP(5678));
|
||||
/// 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]
|
||||
@ -255,38 +261,35 @@ impl Multiaddr {
|
||||
Iter(&self.bytes)
|
||||
}
|
||||
|
||||
/// Pops the last `AddrComponent` of this multiaddr, or `None` if the multiaddr is empty.
|
||||
/// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty.
|
||||
/// ```
|
||||
/// use multiaddr::AddrComponent;
|
||||
/// use multiaddr::Multiaddr;
|
||||
/// use multiaddr::{Multiaddr, Protocol};
|
||||
///
|
||||
/// let mut address: Multiaddr = "/ip4/127.0.0.1/udt/sctp/5678".parse().unwrap();
|
||||
///
|
||||
/// assert_eq!(address.pop().unwrap(), AddrComponent::SCTP(5678));
|
||||
/// assert_eq!(address.pop().unwrap(), AddrComponent::UDT);
|
||||
/// assert_eq!(address.pop().unwrap(), Protocol::Sctp(5678));
|
||||
/// assert_eq!(address.pop().unwrap(), Protocol::Udt);
|
||||
/// ```
|
||||
///
|
||||
pub fn pop<'a>(&mut self) -> Option<AddrComponent<'a>> {
|
||||
pub fn pop<'a>(&mut self) -> Option<Protocol<'a>> {
|
||||
// Note: could be more optimized
|
||||
let mut list = self.iter().map(AddrComponent::acquire).collect::<Vec<_>>();
|
||||
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<AddrComponent<'a>> for Multiaddr {
|
||||
fn from(addr: AddrComponent) -> Multiaddr {
|
||||
let mut out = Vec::new();
|
||||
addr.write_bytes(&mut out).expect(
|
||||
"writing to a Vec never fails",
|
||||
);
|
||||
Multiaddr { bytes: out }
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Multiaddr {
|
||||
type Item = AddrComponent<'a>;
|
||||
type Item = Protocol<'a>;
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
#[inline]
|
||||
@ -295,18 +298,16 @@ impl<'a> IntoIterator for &'a Multiaddr {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromIterator<AddrComponent<'a>> for Multiaddr {
|
||||
impl<'a> FromIterator<Protocol<'a>> for Multiaddr {
|
||||
fn from_iter<T>(iter: T) -> Self
|
||||
where
|
||||
T: IntoIterator<Item = AddrComponent<'a>>,
|
||||
T: IntoIterator<Item = Protocol<'a>>,
|
||||
{
|
||||
let mut bytes = Vec::new();
|
||||
let mut writer = Vec::new();
|
||||
for cmp in iter {
|
||||
cmp.write_bytes(&mut bytes).expect(
|
||||
"writing to a Vec never fails",
|
||||
);
|
||||
cmp.write_bytes(&mut writer).expect("writing to a Vec never fails");
|
||||
}
|
||||
Multiaddr { bytes: bytes }
|
||||
Multiaddr { bytes: writer }
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,32 +316,20 @@ impl FromStr for Multiaddr {
|
||||
|
||||
#[inline]
|
||||
fn from_str(input: &str) -> Result<Self> {
|
||||
let mut bytes = Vec::new();
|
||||
let mut writer = Vec::new();
|
||||
let mut parts = input.split('/').peekable();
|
||||
|
||||
let mut parts = input.split('/');
|
||||
// A multiaddr must start with `/`
|
||||
if !parts.next().ok_or(Error::InvalidMultiaddr)?.is_empty() {
|
||||
return Err(Error::InvalidMultiaddr);
|
||||
if Some("") != parts.next() {
|
||||
// A multiaddr must start with `/`
|
||||
return Err(Error::InvalidMultiaddr)
|
||||
}
|
||||
|
||||
while let Some(part) = parts.next() {
|
||||
let protocol: Protocol = part.parse()?;
|
||||
let addr_component = match protocol.size() {
|
||||
ProtocolArgSize::Fixed { bytes: 0 } => {
|
||||
protocol.parse_data("")? // TODO: bad design
|
||||
}
|
||||
_ => {
|
||||
let data = parts.next().ok_or(Error::MissingAddress)?;
|
||||
protocol.parse_data(data)?
|
||||
}
|
||||
};
|
||||
|
||||
addr_component.write_bytes(&mut bytes).expect(
|
||||
"writing to a Vec never fails",
|
||||
);
|
||||
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: bytes })
|
||||
Ok(Multiaddr { bytes: writer })
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,17 +337,18 @@ impl FromStr for Multiaddr {
|
||||
pub struct Iter<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = AddrComponent<'a>;
|
||||
type Item = Protocol<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.0.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let (component, next_data) =
|
||||
AddrComponent::from_bytes(self.0).expect("multiaddr is known to be valid");
|
||||
let (p, next_data) =
|
||||
Protocol::from_bytes(self.0).expect("multiaddr is known to be valid");
|
||||
|
||||
self.0 = next_data;
|
||||
Some(component)
|
||||
Some(p)
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,14 +385,18 @@ impl ToMultiaddr for SocketAddr {
|
||||
|
||||
impl ToMultiaddr for SocketAddrV4 {
|
||||
fn to_multiaddr(&self) -> Result<Multiaddr> {
|
||||
format!("/ip4/{}/tcp/{}", self.ip(), self.port()).parse()
|
||||
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 how should we handle `flowinfo` and `scope_id`?
|
||||
format!("/ip6/{}/tcp/{}", self.ip(), self.port()).parse()
|
||||
// TODO: Should we handle `flowinfo` and `scope_id`?
|
||||
let mut m = self.ip().to_multiaddr()?;
|
||||
m.append(Protocol::Tcp(self.port()));
|
||||
Ok(m)
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,13 +411,13 @@ impl ToMultiaddr for IpAddr {
|
||||
|
||||
impl ToMultiaddr for Ipv4Addr {
|
||||
fn to_multiaddr(&self) -> Result<Multiaddr> {
|
||||
format!("/ip4/{}", &self).parse()
|
||||
Ok(Protocol::Ip4(*self).into())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToMultiaddr for Ipv6Addr {
|
||||
fn to_multiaddr(&self) -> Result<Multiaddr> {
|
||||
format!("/ip6/{}", &self).parse()
|
||||
Ok(Protocol::Ip6(*self).into())
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,3 +438,4 @@ impl ToMultiaddr for Multiaddr {
|
||||
Ok(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,390 +1,179 @@
|
||||
use bs58;
|
||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
use multihash::Multihash;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
convert::From,
|
||||
fmt,
|
||||
io::{Cursor, Write, Result as IoResult},
|
||||
io::{self, Cursor, Write},
|
||||
net::{Ipv4Addr, Ipv6Addr},
|
||||
str::{self, FromStr}
|
||||
};
|
||||
use multihash::Multihash;
|
||||
use unsigned_varint::{encode, decode};
|
||||
use {Result, Error};
|
||||
|
||||
///! # Protocol
|
||||
///!
|
||||
///! A type to describe the possible protocol used in a
|
||||
///! Multiaddr.
|
||||
const DCCP: u32 = 33;
|
||||
const DNS4: u32 = 54;
|
||||
const DNS6: u32 = 55;
|
||||
const HTTP: u32 = 480;
|
||||
const HTTPS: u32 = 443;
|
||||
const IP4: u32 = 4;
|
||||
const IP6: u32 = 41;
|
||||
const P2P_WEBRTC_DIRECT: u32 = 276;
|
||||
const P2P_WEBRTC_STAR: u32 = 275;
|
||||
const P2P_WEBSOCKET_STAR: u32 = 479;
|
||||
const MEMORY: u32 = 777;
|
||||
const ONION: u32 = 444;
|
||||
const P2P: u32 = 421;
|
||||
const P2P_CIRCUIT: u32 = 290;
|
||||
const QUIC: u32 = 460;
|
||||
const SCTP: u32 = 132;
|
||||
const TCP: u32 = 6;
|
||||
const UDP: u32 = 17;
|
||||
const UDT: u32 = 301;
|
||||
const UNIX: u32 = 400;
|
||||
const UTP: u32 = 302;
|
||||
const WS: u32 = 477;
|
||||
const WSS: u32 = 478;
|
||||
|
||||
/// Protocol is the list of all possible protocols.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
#[repr(u32)]
|
||||
pub enum Protocol {
|
||||
IP4 = 4,
|
||||
TCP = 6,
|
||||
UDP = 17,
|
||||
DCCP = 33,
|
||||
IP6 = 41,
|
||||
DNS4 = 54,
|
||||
DNS6 = 55,
|
||||
SCTP = 132,
|
||||
UDT = 301,
|
||||
UTP = 302,
|
||||
UNIX = 400,
|
||||
P2P = 421,
|
||||
HTTP = 480,
|
||||
HTTPS = 443,
|
||||
ONION = 444,
|
||||
QUIC = 460,
|
||||
WS = 477,
|
||||
WSS = 478,
|
||||
Libp2pWebsocketStar = 479,
|
||||
Libp2pWebrtcStar = 275,
|
||||
Libp2pWebrtcDirect = 276,
|
||||
P2pCircuit = 290,
|
||||
Memory = 777, // TODO: not standard: https://github.com/multiformats/multiaddr/pull/71
|
||||
/// `Protocol` describes all possible multiaddress protocols.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub enum Protocol<'a> {
|
||||
Dccp(u16),
|
||||
Dns4(Cow<'a, str>),
|
||||
Dns6(Cow<'a, str>),
|
||||
Http,
|
||||
Https,
|
||||
Ip4(Ipv4Addr),
|
||||
Ip6(Ipv6Addr),
|
||||
P2pWebRtcDirect,
|
||||
P2pWebRtcStar,
|
||||
P2pWebSocketStar,
|
||||
Memory,
|
||||
Onion(Cow<'a, [u8]>),
|
||||
P2p(Multihash),
|
||||
P2pCircuit,
|
||||
Quic,
|
||||
Sctp(u16),
|
||||
Tcp(u16),
|
||||
Udp(u16),
|
||||
Udt,
|
||||
Unix(Cow<'a, str>),
|
||||
Utp,
|
||||
Ws,
|
||||
Wss
|
||||
}
|
||||
|
||||
impl From<Protocol> for u32 {
|
||||
fn from(proto: Protocol) -> u32 {
|
||||
proto as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Protocol> for u64 {
|
||||
fn from(proto: Protocol) -> u64 {
|
||||
proto as u32 as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Protocol {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Protocol::IP4 => f.write_str("ip4"),
|
||||
Protocol::TCP => f.write_str("tcp"),
|
||||
Protocol::UDP => f.write_str("udp"),
|
||||
Protocol::DCCP => f.write_str("dccp"),
|
||||
Protocol::IP6 => f.write_str("ip6"),
|
||||
Protocol::DNS4 => f.write_str("dns4"),
|
||||
Protocol::DNS6 => f.write_str("dns6"),
|
||||
Protocol::SCTP => f.write_str("sctp"),
|
||||
Protocol::UDT => f.write_str("udt"),
|
||||
Protocol::UTP => f.write_str("utp"),
|
||||
Protocol::UNIX => f.write_str("unix"),
|
||||
Protocol::P2P => f.write_str("p2p"),
|
||||
Protocol::HTTP => f.write_str("http"),
|
||||
Protocol::HTTPS => f.write_str("https"),
|
||||
Protocol::ONION => f.write_str("onion"),
|
||||
Protocol::QUIC => f.write_str("quic"),
|
||||
Protocol::WS => f.write_str("ws"),
|
||||
Protocol::WSS => f.write_str("wss"),
|
||||
Protocol::Libp2pWebsocketStar => f.write_str("p2p-websocket-star"),
|
||||
Protocol::Libp2pWebrtcStar => f.write_str("p2p-webrtc-star"),
|
||||
Protocol::Libp2pWebrtcDirect => f.write_str("p2p-webrtc-direct"),
|
||||
Protocol::P2pCircuit => f.write_str("p2p-circuit"),
|
||||
Protocol::Memory => f.write_str("memory"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Protocol {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(raw: &str) -> Result<Self> {
|
||||
match raw {
|
||||
"ip4" => Ok(Protocol::IP4),
|
||||
"tcp" => Ok(Protocol::TCP),
|
||||
"udp" => Ok(Protocol::UDP),
|
||||
"dccp" => Ok(Protocol::DCCP),
|
||||
"ip6" => Ok(Protocol::IP6),
|
||||
"dns4" => Ok(Protocol::DNS4),
|
||||
"dns6" => Ok(Protocol::DNS6),
|
||||
"sctp" => Ok(Protocol::SCTP),
|
||||
"udt" => Ok(Protocol::UDT),
|
||||
"utp" => Ok(Protocol::UTP),
|
||||
"unix" => Ok(Protocol::UNIX),
|
||||
"p2p" => Ok(Protocol::P2P),
|
||||
"http" => Ok(Protocol::HTTP),
|
||||
"https" => Ok(Protocol::HTTPS),
|
||||
"onion" => Ok(Protocol::ONION),
|
||||
"quic" => Ok(Protocol::QUIC),
|
||||
"ws" => Ok(Protocol::WS),
|
||||
"wss" => Ok(Protocol::WSS),
|
||||
"p2p-websocket-star" => Ok(Protocol::Libp2pWebsocketStar),
|
||||
"p2p-webrtc-star" => Ok(Protocol::Libp2pWebrtcStar),
|
||||
"p2p-webrtc-direct" => Ok(Protocol::Libp2pWebrtcDirect),
|
||||
impl<'a> Protocol<'a> {
|
||||
/// Parse a protocol value from the given iterator of string slices.
|
||||
///
|
||||
/// The parsing only consumes the minimum amount of string slices necessary to
|
||||
/// produce a well-formed protocol. The same iterator can thus be used to parse
|
||||
/// a sequence of protocols in succession. It is up to client code to check
|
||||
/// that iteration has finished whenever appropriate.
|
||||
pub fn from_str_parts<I>(mut iter: I) -> Result<Self>
|
||||
where
|
||||
I: Iterator<Item=&'a str>
|
||||
{
|
||||
match iter.next().ok_or(Error::InvalidProtocolString)? {
|
||||
"ip4" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Ip4(Ipv4Addr::from_str(s)?))
|
||||
}
|
||||
"tcp" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Tcp(s.parse()?))
|
||||
}
|
||||
"udp" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Udp(s.parse()?))
|
||||
}
|
||||
"dccp" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Dccp(s.parse()?))
|
||||
}
|
||||
"ip6" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Ip6(Ipv6Addr::from_str(s)?))
|
||||
}
|
||||
"dns4" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Dns4(Cow::Borrowed(s)))
|
||||
}
|
||||
"dns6" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Dns6(Cow::Borrowed(s)))
|
||||
}
|
||||
"sctp" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Sctp(s.parse()?))
|
||||
}
|
||||
"udt" => Ok(Protocol::Udt),
|
||||
"utp" => Ok(Protocol::Utp),
|
||||
"unix" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
Ok(Protocol::Unix(Cow::Borrowed(s)))
|
||||
}
|
||||
"p2p" => {
|
||||
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
|
||||
let decoded = bs58::decode(s).into_vec()?;
|
||||
Ok(Protocol::P2p(Multihash::from_bytes(decoded)?))
|
||||
}
|
||||
"http" => Ok(Protocol::Http),
|
||||
"https" => Ok(Protocol::Https),
|
||||
"onion" => unimplemented!(), // FIXME
|
||||
"quic" => Ok(Protocol::Quic),
|
||||
"ws" => Ok(Protocol::Ws),
|
||||
"wss" => Ok(Protocol::Wss),
|
||||
"p2p-websocket-star" => Ok(Protocol::P2pWebSocketStar),
|
||||
"p2p-webrtc-star" => Ok(Protocol::P2pWebRtcStar),
|
||||
"p2p-webrtc-direct" => Ok(Protocol::P2pWebRtcDirect),
|
||||
"p2p-circuit" => Ok(Protocol::P2pCircuit),
|
||||
"memory" => Ok(Protocol::Memory),
|
||||
_ => Err(Error::UnknownProtocolString),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Protocol {
|
||||
/// Convert a `u64` based code to a `Protocol`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use multiaddr::Protocol;
|
||||
///
|
||||
/// assert_eq!(Protocol::from(6).unwrap(), Protocol::TCP);
|
||||
/// assert!(Protocol::from(455).is_err());
|
||||
/// ```
|
||||
pub fn from(raw: u64) -> Result<Protocol> {
|
||||
match raw {
|
||||
4 => Ok(Protocol::IP4),
|
||||
6 => Ok(Protocol::TCP),
|
||||
17 => Ok(Protocol::UDP),
|
||||
33 => Ok(Protocol::DCCP),
|
||||
41 => Ok(Protocol::IP6),
|
||||
54 => Ok(Protocol::DNS4),
|
||||
55 => Ok(Protocol::DNS6),
|
||||
132 => Ok(Protocol::SCTP),
|
||||
301 => Ok(Protocol::UDT),
|
||||
302 => Ok(Protocol::UTP),
|
||||
400 => Ok(Protocol::UNIX),
|
||||
421 => Ok(Protocol::P2P),
|
||||
480 => Ok(Protocol::HTTP),
|
||||
443 => Ok(Protocol::HTTPS),
|
||||
444 => Ok(Protocol::ONION),
|
||||
460 => Ok(Protocol::QUIC),
|
||||
477 => Ok(Protocol::WS),
|
||||
478 => Ok(Protocol::WSS),
|
||||
479 => Ok(Protocol::Libp2pWebsocketStar),
|
||||
275 => Ok(Protocol::Libp2pWebrtcStar),
|
||||
276 => Ok(Protocol::Libp2pWebrtcDirect),
|
||||
290 => Ok(Protocol::P2pCircuit),
|
||||
777 => Ok(Protocol::Memory),
|
||||
_ => Err(Error::UnknownProtocol),
|
||||
_ => Err(Error::UnknownProtocolString)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the size from a `Protocol`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use multiaddr::Protocol;
|
||||
/// use multiaddr::ProtocolArgSize;
|
||||
///
|
||||
/// assert_eq!(Protocol::TCP.size(), ProtocolArgSize::Fixed { bytes: 2 });
|
||||
/// ```
|
||||
///
|
||||
pub fn size(&self) -> ProtocolArgSize {
|
||||
match *self {
|
||||
Protocol::IP4 => ProtocolArgSize::Fixed { bytes: 4 },
|
||||
Protocol::TCP => ProtocolArgSize::Fixed { bytes: 2 },
|
||||
Protocol::UDP => ProtocolArgSize::Fixed { bytes: 2 },
|
||||
Protocol::DCCP => ProtocolArgSize::Fixed { bytes: 2 },
|
||||
Protocol::IP6 => ProtocolArgSize::Fixed { bytes: 16 },
|
||||
Protocol::DNS4 => ProtocolArgSize::Variable,
|
||||
Protocol::DNS6 => ProtocolArgSize::Variable,
|
||||
Protocol::SCTP => ProtocolArgSize::Fixed { bytes: 2 },
|
||||
Protocol::UDT => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::UTP => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::UNIX => ProtocolArgSize::Variable,
|
||||
Protocol::P2P => ProtocolArgSize::Variable,
|
||||
Protocol::HTTP => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::HTTPS => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::ONION => ProtocolArgSize::Fixed { bytes: 10 },
|
||||
Protocol::QUIC => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::WS => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::WSS => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::Libp2pWebsocketStar => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::Libp2pWebrtcStar => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::Libp2pWebrtcDirect => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::P2pCircuit => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
Protocol::Memory => ProtocolArgSize::Fixed { bytes: 0 },
|
||||
/// Parse a single `Protocol` value from its byte slice representation,
|
||||
/// returning the protocol as well as the remaining byte slice.
|
||||
pub fn from_bytes(input: &'a [u8]) -> Result<(Self, &'a [u8])> {
|
||||
fn split_at(n: usize, input: &[u8]) -> Result<(&[u8], &[u8])> {
|
||||
if input.len() < n {
|
||||
return Err(Error::DataLessThanLen)
|
||||
}
|
||||
Ok(input.split_at(n))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ProtocolArgSize {
|
||||
/// The size of the argument is of fixed length. The length can be 0, in which case there is no
|
||||
/// argument.
|
||||
Fixed { bytes: usize },
|
||||
/// The size of the argument is of variable length.
|
||||
Variable,
|
||||
}
|
||||
|
||||
impl Protocol {
|
||||
/// Convert an array slice to the string representation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::Ipv4Addr;
|
||||
/// use multiaddr::AddrComponent;
|
||||
/// use multiaddr::Protocol;
|
||||
///
|
||||
/// let proto = Protocol::IP4;
|
||||
/// assert_eq!(proto.parse_data("127.0.0.1").unwrap(),
|
||||
/// AddrComponent::IP4(Ipv4Addr::new(127, 0, 0, 1)));
|
||||
/// ```
|
||||
///
|
||||
pub fn parse_data<'a>(&self, a: &'a str) -> Result<AddrComponent<'a>> {
|
||||
match *self {
|
||||
Protocol::IP4 => {
|
||||
let addr = Ipv4Addr::from_str(a)?;
|
||||
Ok(AddrComponent::IP4(addr))
|
||||
}
|
||||
Protocol::IP6 => {
|
||||
let addr = Ipv6Addr::from_str(a)?;
|
||||
Ok(AddrComponent::IP6(addr))
|
||||
}
|
||||
Protocol::DNS4 => Ok(AddrComponent::DNS4(Cow::Borrowed(a))),
|
||||
Protocol::DNS6 => Ok(AddrComponent::DNS6(Cow::Borrowed(a))),
|
||||
Protocol::TCP => {
|
||||
let parsed: u16 = a.parse()?;
|
||||
Ok(AddrComponent::TCP(parsed))
|
||||
}
|
||||
Protocol::UDP => {
|
||||
let parsed: u16 = a.parse()?;
|
||||
Ok(AddrComponent::UDP(parsed))
|
||||
}
|
||||
Protocol::DCCP => {
|
||||
let parsed: u16 = a.parse()?;
|
||||
Ok(AddrComponent::DCCP(parsed))
|
||||
}
|
||||
Protocol::SCTP => {
|
||||
let parsed: u16 = a.parse()?;
|
||||
Ok(AddrComponent::SCTP(parsed))
|
||||
}
|
||||
Protocol::P2P => {
|
||||
let decoded = bs58::decode(a).into_vec()?;
|
||||
Ok(AddrComponent::P2P(Multihash::from_bytes(decoded)?))
|
||||
}
|
||||
Protocol::ONION => unimplemented!(), // TODO:
|
||||
Protocol::QUIC => Ok(AddrComponent::QUIC),
|
||||
Protocol::UTP => Ok(AddrComponent::UTP),
|
||||
Protocol::UNIX => Ok(AddrComponent::UNIX(Cow::Borrowed(a))),
|
||||
Protocol::UDT => Ok(AddrComponent::UDT),
|
||||
Protocol::HTTP => Ok(AddrComponent::HTTP),
|
||||
Protocol::HTTPS => Ok(AddrComponent::HTTPS),
|
||||
Protocol::WS => Ok(AddrComponent::WS),
|
||||
Protocol::WSS => Ok(AddrComponent::WSS),
|
||||
Protocol::Libp2pWebsocketStar => Ok(AddrComponent::Libp2pWebsocketStar),
|
||||
Protocol::Libp2pWebrtcStar => Ok(AddrComponent::Libp2pWebrtcStar),
|
||||
Protocol::Libp2pWebrtcDirect => Ok(AddrComponent::Libp2pWebrtcDirect),
|
||||
Protocol::P2pCircuit => Ok(AddrComponent::P2pCircuit),
|
||||
Protocol::Memory => Ok(AddrComponent::Memory),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub enum AddrComponent<'a> {
|
||||
IP4(Ipv4Addr),
|
||||
TCP(u16),
|
||||
UDP(u16),
|
||||
DCCP(u16),
|
||||
IP6(Ipv6Addr),
|
||||
DNS4(Cow<'a, str>),
|
||||
DNS6(Cow<'a, str>),
|
||||
SCTP(u16),
|
||||
UDT,
|
||||
UTP,
|
||||
UNIX(Cow<'a, str>),
|
||||
P2P(Multihash),
|
||||
HTTP,
|
||||
HTTPS,
|
||||
ONION(Cow<'a, [u8]>),
|
||||
QUIC,
|
||||
WS,
|
||||
WSS,
|
||||
Libp2pWebsocketStar,
|
||||
Libp2pWebrtcStar,
|
||||
Libp2pWebrtcDirect,
|
||||
P2pCircuit,
|
||||
Memory,
|
||||
}
|
||||
|
||||
impl<'a> AddrComponent<'a> {
|
||||
/// Turn this `AddrComponent` into one that owns its data, thus being valid for any lifetime.
|
||||
pub fn acquire<'b>(self) -> AddrComponent<'b> {
|
||||
use AddrComponent::*;
|
||||
match self {
|
||||
DNS4(cow) => DNS4(Cow::Owned(cow.into_owned())),
|
||||
DNS6(cow) => DNS6(Cow::Owned(cow.into_owned())),
|
||||
UNIX(cow) => UNIX(Cow::Owned(cow.into_owned())),
|
||||
ONION(cow) => ONION(Cow::Owned(cow.into_owned())),
|
||||
IP4(a) => IP4(a),
|
||||
TCP(a) => TCP(a),
|
||||
UDP(a) => UDP(a),
|
||||
DCCP(a) => DCCP(a),
|
||||
IP6(a) => IP6(a),
|
||||
SCTP(a) => SCTP(a),
|
||||
UDT => UDT,
|
||||
UTP => UTP,
|
||||
P2P(a) => P2P(a),
|
||||
HTTP => HTTP,
|
||||
HTTPS => HTTPS,
|
||||
QUIC => QUIC,
|
||||
WS => WS,
|
||||
WSS => WSS,
|
||||
Libp2pWebsocketStar => Libp2pWebsocketStar,
|
||||
Libp2pWebrtcStar => Libp2pWebrtcStar,
|
||||
Libp2pWebrtcDirect => Libp2pWebrtcDirect,
|
||||
P2pCircuit => P2pCircuit,
|
||||
Memory => Memory
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `Protocol` corresponding to this `AddrComponent`.
|
||||
#[inline]
|
||||
pub fn protocol_id(&self) -> Protocol {
|
||||
match *self {
|
||||
AddrComponent::IP4(_) => Protocol::IP4,
|
||||
AddrComponent::TCP(_) => Protocol::TCP,
|
||||
AddrComponent::UDP(_) => Protocol::UDP,
|
||||
AddrComponent::DCCP(_) => Protocol::DCCP,
|
||||
AddrComponent::IP6(_) => Protocol::IP6,
|
||||
AddrComponent::DNS4(_) => Protocol::DNS4,
|
||||
AddrComponent::DNS6(_) => Protocol::DNS6,
|
||||
AddrComponent::SCTP(_) => Protocol::SCTP,
|
||||
AddrComponent::UDT => Protocol::UDT,
|
||||
AddrComponent::UTP => Protocol::UTP,
|
||||
AddrComponent::UNIX(_) => Protocol::UNIX,
|
||||
AddrComponent::P2P(_) => Protocol::P2P,
|
||||
AddrComponent::HTTP => Protocol::HTTP,
|
||||
AddrComponent::HTTPS => Protocol::HTTPS,
|
||||
AddrComponent::ONION(_) => Protocol::ONION,
|
||||
AddrComponent::QUIC => Protocol::QUIC,
|
||||
AddrComponent::WS => Protocol::WS,
|
||||
AddrComponent::WSS => Protocol::WSS,
|
||||
AddrComponent::Libp2pWebsocketStar => Protocol::Libp2pWebsocketStar,
|
||||
AddrComponent::Libp2pWebrtcStar => Protocol::Libp2pWebrtcStar,
|
||||
AddrComponent::Libp2pWebrtcDirect => Protocol::Libp2pWebrtcDirect,
|
||||
AddrComponent::P2pCircuit => Protocol::P2pCircuit,
|
||||
AddrComponent::Memory => Protocol::Memory,
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds an `AddrComponent` from an array that starts with a bytes representation. On
|
||||
/// success, also returns the rest of the slice.
|
||||
pub fn from_bytes(input: &[u8]) -> Result<(AddrComponent, &[u8])> {
|
||||
let (proto_num, input) = decode::u64(input)?;
|
||||
let protocol_id = Protocol::from(proto_num)?;
|
||||
let (data_size, input) = match protocol_id.size() {
|
||||
ProtocolArgSize::Fixed { bytes } => (bytes, input),
|
||||
ProtocolArgSize::Variable => decode::usize(input)?
|
||||
};
|
||||
let (data, rest) = input.split_at(data_size);
|
||||
|
||||
let addr_component = match protocol_id {
|
||||
Protocol::IP4 => {
|
||||
AddrComponent::IP4(Ipv4Addr::new(data[0], data[1], data[2], data[3]))
|
||||
},
|
||||
Protocol::IP6 => {
|
||||
let (id, input) = decode::u32(input)?;
|
||||
match id {
|
||||
DCCP => {
|
||||
let (data, rest) = split_at(2, input)?;
|
||||
let mut rdr = Cursor::new(data);
|
||||
let mut seg = [0; 8];
|
||||
let num = rdr.read_u16::<BigEndian>()?;
|
||||
Ok((Protocol::Dccp(num), rest))
|
||||
}
|
||||
DNS4 => {
|
||||
let (n, input) = decode::usize(input)?;
|
||||
let (data, rest) = split_at(n, input)?;
|
||||
Ok((Protocol::Dns4(Cow::Borrowed(str::from_utf8(data)?)), rest))
|
||||
}
|
||||
DNS6 => {
|
||||
let (n, input) = decode::usize(input)?;
|
||||
let (data, rest) = split_at(n, input)?;
|
||||
Ok((Protocol::Dns6(Cow::Borrowed(str::from_utf8(data)?)), rest))
|
||||
}
|
||||
HTTP => Ok((Protocol::Http, input)),
|
||||
HTTPS => Ok((Protocol::Https, input)),
|
||||
IP4 => {
|
||||
let (data, rest) = split_at(4, input)?;
|
||||
Ok((Protocol::Ip4(Ipv4Addr::new(data[0], data[1], data[2], data[3])), rest))
|
||||
}
|
||||
IP6 => {
|
||||
let (data, rest) = split_at(16, input)?;
|
||||
let mut rdr = Cursor::new(data);
|
||||
let mut seg = [0_u16; 8];
|
||||
|
||||
for i in 0..8 {
|
||||
seg[i] = rdr.read_u16::<BigEndian>()?;
|
||||
for x in seg.iter_mut() {
|
||||
*x = rdr.read_u16::<BigEndian>()?;
|
||||
}
|
||||
|
||||
let addr = Ipv6Addr::new(seg[0],
|
||||
@ -395,146 +184,197 @@ impl<'a> AddrComponent<'a> {
|
||||
seg[5],
|
||||
seg[6],
|
||||
seg[7]);
|
||||
AddrComponent::IP6(addr)
|
||||
}
|
||||
Protocol::DNS4 => {
|
||||
AddrComponent::DNS4(Cow::Borrowed(str::from_utf8(data)?))
|
||||
}
|
||||
Protocol::DNS6 => {
|
||||
AddrComponent::DNS6(Cow::Borrowed(str::from_utf8(data)?))
|
||||
}
|
||||
Protocol::TCP => {
|
||||
let mut rdr = Cursor::new(data);
|
||||
let num = rdr.read_u16::<BigEndian>()?;
|
||||
AddrComponent::TCP(num)
|
||||
}
|
||||
Protocol::UDP => {
|
||||
let mut rdr = Cursor::new(data);
|
||||
let num = rdr.read_u16::<BigEndian>()?;
|
||||
AddrComponent::UDP(num)
|
||||
}
|
||||
Protocol::DCCP => {
|
||||
let mut rdr = Cursor::new(data);
|
||||
let num = rdr.read_u16::<BigEndian>()?;
|
||||
AddrComponent::DCCP(num)
|
||||
}
|
||||
Protocol::SCTP => {
|
||||
let mut rdr = Cursor::new(data);
|
||||
let num = rdr.read_u16::<BigEndian>()?;
|
||||
AddrComponent::SCTP(num)
|
||||
}
|
||||
Protocol::UNIX => {
|
||||
AddrComponent::UNIX(Cow::Borrowed(str::from_utf8(data)?))
|
||||
}
|
||||
Protocol::P2P => {
|
||||
AddrComponent::P2P(Multihash::from_bytes(data.to_owned())?)
|
||||
}
|
||||
Protocol::ONION => unimplemented!(), // TODO:
|
||||
Protocol::QUIC => AddrComponent::QUIC,
|
||||
Protocol::UTP => AddrComponent::UTP,
|
||||
Protocol::UDT => AddrComponent::UDT,
|
||||
Protocol::HTTP => AddrComponent::HTTP,
|
||||
Protocol::HTTPS => AddrComponent::HTTPS,
|
||||
Protocol::WS => AddrComponent::WS,
|
||||
Protocol::WSS => AddrComponent::WSS,
|
||||
Protocol::Libp2pWebsocketStar => AddrComponent::Libp2pWebsocketStar,
|
||||
Protocol::Libp2pWebrtcStar => AddrComponent::Libp2pWebrtcStar,
|
||||
Protocol::Libp2pWebrtcDirect => AddrComponent::Libp2pWebrtcDirect,
|
||||
Protocol::P2pCircuit => AddrComponent::P2pCircuit,
|
||||
Protocol::Memory => AddrComponent::Memory,
|
||||
};
|
||||
|
||||
Ok((addr_component, rest))
|
||||
Ok((Protocol::Ip6(addr), rest))
|
||||
}
|
||||
P2P_WEBRTC_DIRECT => Ok((Protocol::P2pWebRtcDirect, input)),
|
||||
P2P_WEBRTC_STAR => Ok((Protocol::P2pWebRtcStar, input)),
|
||||
P2P_WEBSOCKET_STAR => Ok((Protocol::P2pWebSocketStar, input)),
|
||||
MEMORY => Ok((Protocol::Memory, input)),
|
||||
ONION => unimplemented!(), // FIXME
|
||||
P2P => {
|
||||
let (n, input) = decode::usize(input)?;
|
||||
let (data, rest) = split_at(n, input)?;
|
||||
Ok((Protocol::P2p(Multihash::from_bytes(data.to_owned())?), rest))
|
||||
}
|
||||
P2P_CIRCUIT => Ok((Protocol::P2pCircuit, input)),
|
||||
QUIC => Ok((Protocol::Quic, input)),
|
||||
SCTP => {
|
||||
let (data, rest) = split_at(2, input)?;
|
||||
let mut rdr = Cursor::new(data);
|
||||
let num = rdr.read_u16::<BigEndian>()?;
|
||||
Ok((Protocol::Sctp(num), rest))
|
||||
}
|
||||
TCP => {
|
||||
let (data, rest) = split_at(2, input)?;
|
||||
let mut rdr = Cursor::new(data);
|
||||
let num = rdr.read_u16::<BigEndian>()?;
|
||||
Ok((Protocol::Tcp(num), rest))
|
||||
}
|
||||
UDP => {
|
||||
let (data, rest) = split_at(2, input)?;
|
||||
let mut rdr = Cursor::new(data);
|
||||
let num = rdr.read_u16::<BigEndian>()?;
|
||||
Ok((Protocol::Udp(num), rest))
|
||||
}
|
||||
UDT => Ok((Protocol::Udt, input)),
|
||||
UNIX => {
|
||||
let (n, input) = decode::usize(input)?;
|
||||
let (data, rest) = split_at(n, input)?;
|
||||
Ok((Protocol::Unix(Cow::Borrowed(str::from_utf8(data)?)), rest))
|
||||
}
|
||||
UTP => Ok((Protocol::Utp, input)),
|
||||
WS => Ok((Protocol::Ws, input)),
|
||||
WSS => Ok((Protocol::Wss, input)),
|
||||
_ => Err(Error::UnknownProtocolId(id))
|
||||
}
|
||||
}
|
||||
|
||||
/// Turns this address component into bytes by writing it to a `Write`.
|
||||
pub fn write_bytes<W: Write>(self, out: &mut W) -> IoResult<()> {
|
||||
out.write_all(encode::u64(self.protocol_id().into(), &mut encode::u64_buffer()))?;
|
||||
|
||||
/// Encode this protocol by writing its binary representation into
|
||||
/// the given `Write` impl.
|
||||
pub fn write_bytes<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||
let mut buf = encode::u32_buffer();
|
||||
match self {
|
||||
AddrComponent::IP4(addr) => {
|
||||
out.write_all(&addr.octets())?;
|
||||
Protocol::Ip4(addr) => {
|
||||
w.write_all(encode::u32(IP4, &mut buf))?;
|
||||
w.write_all(&addr.octets())?
|
||||
}
|
||||
AddrComponent::IP6(addr) => {
|
||||
Protocol::Ip6(addr) => {
|
||||
w.write_all(encode::u32(IP6, &mut buf))?;
|
||||
for &segment in &addr.segments() {
|
||||
out.write_u16::<BigEndian>(segment)?;
|
||||
w.write_u16::<BigEndian>(segment)?
|
||||
}
|
||||
}
|
||||
AddrComponent::TCP(port) | AddrComponent::UDP(port) | AddrComponent::DCCP(port) |
|
||||
AddrComponent::SCTP(port) => {
|
||||
out.write_u16::<BigEndian>(port)?;
|
||||
Protocol::Tcp(port) => {
|
||||
w.write_all(encode::u32(TCP, &mut buf))?;
|
||||
w.write_u16::<BigEndian>(*port)?
|
||||
}
|
||||
AddrComponent::DNS4(s) | AddrComponent::DNS6(s) | AddrComponent::UNIX(s) => {
|
||||
Protocol::Udp(port) => {
|
||||
w.write_all(encode::u32(UDP, &mut buf))?;
|
||||
w.write_u16::<BigEndian>(*port)?
|
||||
}
|
||||
Protocol::Dccp(port) => {
|
||||
w.write_all(encode::u32(DCCP, &mut buf))?;
|
||||
w.write_u16::<BigEndian>(*port)?
|
||||
}
|
||||
Protocol::Sctp(port) => {
|
||||
w.write_all(encode::u32(SCTP, &mut buf))?;
|
||||
w.write_u16::<BigEndian>(*port)?
|
||||
}
|
||||
Protocol::Dns4(s) => {
|
||||
w.write_all(encode::u32(DNS4, &mut buf))?;
|
||||
let bytes = s.as_bytes();
|
||||
out.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||
out.write_all(&bytes)?;
|
||||
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||
w.write_all(&bytes)?
|
||||
}
|
||||
AddrComponent::P2P(multihash) => {
|
||||
let bytes = multihash.into_bytes();
|
||||
out.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||
out.write_all(&bytes)?;
|
||||
Protocol::Dns6(s) => {
|
||||
w.write_all(encode::u32(DNS6, &mut buf))?;
|
||||
let bytes = s.as_bytes();
|
||||
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||
w.write_all(&bytes)?
|
||||
}
|
||||
AddrComponent::ONION(_) => {
|
||||
unimplemented!() // TODO:
|
||||
},
|
||||
AddrComponent::QUIC |
|
||||
AddrComponent::UTP |
|
||||
AddrComponent::UDT |
|
||||
AddrComponent::HTTP |
|
||||
AddrComponent::HTTPS |
|
||||
AddrComponent::WS |
|
||||
AddrComponent::WSS |
|
||||
AddrComponent::Libp2pWebsocketStar |
|
||||
AddrComponent::Libp2pWebrtcStar |
|
||||
AddrComponent::Libp2pWebrtcDirect |
|
||||
AddrComponent::P2pCircuit |
|
||||
AddrComponent::Memory => {}
|
||||
};
|
||||
|
||||
Protocol::Unix(s) => {
|
||||
w.write_all(encode::u32(UNIX, &mut buf))?;
|
||||
let bytes = s.as_bytes();
|
||||
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||
w.write_all(&bytes)?
|
||||
}
|
||||
Protocol::P2p(multihash) => {
|
||||
w.write_all(encode::u32(P2P, &mut buf))?;
|
||||
let bytes = multihash.as_bytes();
|
||||
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
|
||||
w.write_all(&bytes)?
|
||||
}
|
||||
Protocol::Onion(_) => unimplemented!(), // FIXME
|
||||
Protocol::Quic => w.write_all(encode::u32(QUIC, &mut buf))?,
|
||||
Protocol::Utp => w.write_all(encode::u32(UTP, &mut buf))?,
|
||||
Protocol::Udt => w.write_all(encode::u32(UDT, &mut buf))?,
|
||||
Protocol::Http => w.write_all(encode::u32(HTTP, &mut buf))?,
|
||||
Protocol::Https => w.write_all(encode::u32(HTTPS, &mut buf))?,
|
||||
Protocol::Ws => w.write_all(encode::u32(WS, &mut buf))?,
|
||||
Protocol::Wss => w.write_all(encode::u32(WSS, &mut buf))?,
|
||||
Protocol::P2pWebSocketStar => w.write_all(encode::u32(P2P_WEBSOCKET_STAR, &mut buf))?,
|
||||
Protocol::P2pWebRtcStar => w.write_all(encode::u32(P2P_WEBRTC_STAR, &mut buf))?,
|
||||
Protocol::P2pWebRtcDirect => w.write_all(encode::u32(P2P_WEBRTC_DIRECT, &mut buf))?,
|
||||
Protocol::P2pCircuit => w.write_all(encode::u32(P2P_CIRCUIT, &mut buf))?,
|
||||
Protocol::Memory => w.write_all(encode::u32(MEMORY, &mut buf))?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for AddrComponent<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// Turn this `Protocol` into one that owns its data, thus being valid for any lifetime.
|
||||
pub fn acquire<'b>(self) -> Protocol<'b> {
|
||||
use Protocol::*;
|
||||
match self {
|
||||
AddrComponent::IP4(addr) => write!(f, "/ip4/{}", addr),
|
||||
AddrComponent::TCP(port) => write!(f, "/tcp/{}", port),
|
||||
AddrComponent::UDP(port) => write!(f, "/udp/{}", port),
|
||||
AddrComponent::DCCP(port) => write!(f, "/dccp/{}", port),
|
||||
AddrComponent::IP6(addr) => write!(f, "/ip6/{}", addr),
|
||||
AddrComponent::DNS4(s) => write!(f, "/dns4/{}", s),
|
||||
AddrComponent::DNS6(s) => write!(f, "/dns6/{}", s),
|
||||
AddrComponent::SCTP(port) => write!(f, "/sctp/{}", port),
|
||||
AddrComponent::UDT => f.write_str("/udt"),
|
||||
AddrComponent::UTP => f.write_str("/utp"),
|
||||
AddrComponent::UNIX(s) => write!(f, "/unix/{}", s),
|
||||
AddrComponent::P2P(c) => write!(f, "/p2p/{}", bs58::encode(c.as_bytes()).into_string()),
|
||||
AddrComponent::HTTP => f.write_str("/http"),
|
||||
AddrComponent::HTTPS => f.write_str("/https"),
|
||||
AddrComponent::ONION(_) => unimplemented!(),//write!("/onion"), // TODO:
|
||||
AddrComponent::QUIC => f.write_str("/quic"),
|
||||
AddrComponent::WS => f.write_str("/ws"),
|
||||
AddrComponent::WSS => f.write_str("/wss"),
|
||||
AddrComponent::Libp2pWebsocketStar => f.write_str("/p2p-websocket-star"),
|
||||
AddrComponent::Libp2pWebrtcStar => f.write_str("/p2p-webrtc-star"),
|
||||
AddrComponent::Libp2pWebrtcDirect => f.write_str("/p2p-webrtc-direct"),
|
||||
AddrComponent::P2pCircuit => f.write_str("/p2p-circuit"),
|
||||
AddrComponent::Memory => f.write_str("/memory"),
|
||||
Dccp(a) => Dccp(a),
|
||||
Dns4(cow) => Dns4(Cow::Owned(cow.into_owned())),
|
||||
Dns6(cow) => Dns6(Cow::Owned(cow.into_owned())),
|
||||
Http => Http,
|
||||
Https => Https,
|
||||
Ip4(a) => Ip4(a),
|
||||
Ip6(a) => Ip6(a),
|
||||
P2pWebRtcDirect => P2pWebRtcDirect,
|
||||
P2pWebRtcStar => P2pWebRtcStar,
|
||||
P2pWebSocketStar => P2pWebSocketStar,
|
||||
Memory => Memory,
|
||||
Onion(cow) => Onion(Cow::Owned(cow.into_owned())),
|
||||
P2p(a) => P2p(a),
|
||||
P2pCircuit => P2pCircuit,
|
||||
Quic => Quic,
|
||||
Sctp(a) => Sctp(a),
|
||||
Tcp(a) => Tcp(a),
|
||||
Udp(a) => Udp(a),
|
||||
Udt => Udt,
|
||||
Unix(cow) => Unix(Cow::Owned(cow.into_owned())),
|
||||
Utp => Utp,
|
||||
Ws => Ws,
|
||||
Wss => Wss
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Ipv4Addr> for AddrComponent<'a> {
|
||||
#[inline]
|
||||
fn from(addr: Ipv4Addr) -> Self {
|
||||
AddrComponent::IP4(addr)
|
||||
impl<'a> fmt::Display for Protocol<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Protocol::*;
|
||||
match self {
|
||||
Dccp(port) => write!(f, "/dccp/{}", port),
|
||||
Dns4(s) => write!(f, "/dns4/{}", s),
|
||||
Dns6(s) => write!(f, "/dns6/{}", s),
|
||||
Http => f.write_str("/http"),
|
||||
Https => f.write_str("/https"),
|
||||
Ip4(addr) => write!(f, "/ip4/{}", addr),
|
||||
Ip6(addr) => write!(f, "/ip6/{}", addr),
|
||||
P2pWebRtcDirect => f.write_str("/p2p-webrtc-direct"),
|
||||
P2pWebRtcStar => f.write_str("/p2p-webrtc-star"),
|
||||
P2pWebSocketStar => f.write_str("/p2p-websocket-star"),
|
||||
Memory => f.write_str("/memory"),
|
||||
Onion(_) => unimplemented!(), // FIXME!
|
||||
P2p(c) => write!(f, "/p2p/{}", bs58::encode(c.as_bytes()).into_string()),
|
||||
P2pCircuit => f.write_str("/p2p-circuit"),
|
||||
Quic => f.write_str("/quic"),
|
||||
Sctp(port) => write!(f, "/sctp/{}", port),
|
||||
Tcp(port) => write!(f, "/tcp/{}", port),
|
||||
Udp(port) => write!(f, "/udp/{}", port),
|
||||
Udt => f.write_str("/udt"),
|
||||
Unix(s) => write!(f, "/unix/{}", s),
|
||||
Utp => f.write_str("/utp"),
|
||||
Ws => f.write_str("/ws"),
|
||||
Wss => f.write_str("/wss"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Ipv6Addr> for AddrComponent<'a> {
|
||||
impl<'a> From<Ipv4Addr> for Protocol<'a> {
|
||||
#[inline]
|
||||
fn from(addr: Ipv6Addr) -> Self {
|
||||
AddrComponent::IP6(addr)
|
||||
fn from(addr: Ipv4Addr) -> Self {
|
||||
Protocol::Ip4(addr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Ipv6Addr> for Protocol<'a> {
|
||||
#[inline]
|
||||
fn from(addr: Ipv6Addr) -> Self {
|
||||
Protocol::Ip6(addr)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,29 +1,118 @@
|
||||
extern crate multiaddr;
|
||||
extern crate data_encoding;
|
||||
extern crate serde_json;
|
||||
extern crate bs58;
|
||||
extern crate bincode;
|
||||
extern crate data_encoding;
|
||||
extern crate multiaddr;
|
||||
extern crate multihash;
|
||||
extern crate quickcheck;
|
||||
extern crate rand;
|
||||
extern crate serde_json;
|
||||
|
||||
use data_encoding::hex;
|
||||
use data_encoding::HEXUPPER;
|
||||
use multiaddr::*;
|
||||
use std::net::{SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr};
|
||||
use multihash::Multihash;
|
||||
use quickcheck::{Arbitrary, Gen, QuickCheck};
|
||||
use rand::Rng;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
iter::FromIterator,
|
||||
net::{SocketAddrV4, SocketAddrV6, Ipv4Addr, Ipv6Addr},
|
||||
str::FromStr
|
||||
};
|
||||
|
||||
// Property tests
|
||||
|
||||
#[test]
|
||||
fn protocol_to_code() {
|
||||
assert_eq!(Protocol::IP4 as usize, 4);
|
||||
fn to_from_bytes_identity() {
|
||||
fn prop(a: Ma) -> bool {
|
||||
let b = a.0.to_bytes();
|
||||
Some(a) == Multiaddr::from_bytes(b).ok().map(Ma)
|
||||
}
|
||||
QuickCheck::new().quickcheck(prop as fn(Ma) -> bool)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn protocol_to_name() {
|
||||
assert_eq!(Protocol::TCP.to_string(), "tcp");
|
||||
fn to_from_str_identity() {
|
||||
fn prop(a: Ma) -> bool {
|
||||
let b = a.0.to_string();
|
||||
Some(a) == Multiaddr::from_str(&b).ok().map(Ma)
|
||||
}
|
||||
QuickCheck::new().quickcheck(prop as fn(Ma) -> bool)
|
||||
}
|
||||
|
||||
|
||||
// Arbitrary impls
|
||||
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
|
||||
struct Ma(Multiaddr);
|
||||
|
||||
impl Arbitrary for Ma {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||
let iter = (0 .. g.next_u32() % 128).map(|_| Proto::arbitrary(g).0);
|
||||
Ma(Multiaddr::from_iter(iter))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
struct Proto(Protocol<'static>);
|
||||
|
||||
impl Arbitrary for Proto {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||
use Protocol::*;
|
||||
match g.gen_range(0, 22) { // TODO: Add Protocol::Quic
|
||||
0 => Proto(Dccp(g.gen())),
|
||||
1 => Proto(Dns4(Cow::Owned(SubString::arbitrary(g).0))),
|
||||
2 => Proto(Dns6(Cow::Owned(SubString::arbitrary(g).0))),
|
||||
3 => Proto(Http),
|
||||
4 => Proto(Https),
|
||||
5 => Proto(Ip4(Ipv4Addr::arbitrary(g))),
|
||||
6 => Proto(Ip6(Ipv6Addr::arbitrary(g))),
|
||||
7 => Proto(P2pWebRtcDirect),
|
||||
8 => Proto(P2pWebRtcStar),
|
||||
9 => Proto(P2pWebSocketStar),
|
||||
10 => Proto(Memory),
|
||||
// TODO: impl Arbitrary for Multihash:
|
||||
11 => Proto(P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))),
|
||||
12 => Proto(P2pCircuit),
|
||||
13 => Proto(Quic),
|
||||
14 => Proto(Sctp(g.gen())),
|
||||
15 => Proto(Tcp(g.gen())),
|
||||
16 => Proto(Udp(g.gen())),
|
||||
17 => Proto(Udt),
|
||||
18 => Proto(Unix(Cow::Owned(SubString::arbitrary(g).0))),
|
||||
19 => Proto(Utp),
|
||||
20 => Proto(Ws),
|
||||
21 => Proto(Wss),
|
||||
_ => panic!("outside range")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
struct SubString(String); // ASCII string without '/'
|
||||
|
||||
impl Arbitrary for SubString {
|
||||
fn arbitrary<G: Gen>(g: &mut G) -> Self {
|
||||
let mut s = String::arbitrary(g);
|
||||
s.retain(|c| c.is_ascii() && c != '/');
|
||||
SubString(s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// other unit tests
|
||||
|
||||
|
||||
fn ma_valid(source: &str, target: &str, protocols: Vec<Protocol>) {
|
||||
let parsed = source.parse::<Multiaddr>().unwrap();
|
||||
assert_eq!(hex::encode(parsed.to_bytes().as_slice()), target);
|
||||
assert_eq!(parsed.iter().map(|addr| addr.protocol_id()).collect::<Vec<_>>(), protocols);
|
||||
assert_eq!(HEXUPPER.encode(&parsed.to_bytes()[..]), target);
|
||||
assert_eq!(parsed.iter().collect::<Vec<_>>(), protocols);
|
||||
assert_eq!(source.parse::<Multiaddr>().unwrap().to_string(), source);
|
||||
assert_eq!(Multiaddr::from_bytes(hex::decode(target.as_bytes()).unwrap()).unwrap(), parsed);
|
||||
assert_eq!(Multiaddr::from_bytes(HEXUPPER.decode(target.as_bytes()).unwrap()).unwrap(), parsed);
|
||||
}
|
||||
|
||||
fn multihash(s: &str) -> Multihash {
|
||||
Multihash::from_bytes(bs58::decode(s).into_vec().unwrap()).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -42,68 +131,61 @@ fn multiaddr_eq() {
|
||||
fn construct_success() {
|
||||
use Protocol::*;
|
||||
|
||||
ma_valid("/ip4/1.2.3.4", "0401020304", vec![IP4]);
|
||||
ma_valid("/ip4/0.0.0.0", "0400000000", vec![IP4]);
|
||||
ma_valid("/ip6/::1", "2900000000000000000000000000000001", vec![IP6]);
|
||||
let local: Ipv4Addr = "127.0.0.1".parse().unwrap();
|
||||
let addr6: Ipv6Addr = "2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095".parse().unwrap();
|
||||
|
||||
ma_valid("/ip4/1.2.3.4", "0401020304", vec![Ip4("1.2.3.4".parse().unwrap())]);
|
||||
ma_valid("/ip4/0.0.0.0", "0400000000", vec![Ip4("0.0.0.0".parse().unwrap())]);
|
||||
ma_valid("/ip6/::1", "2900000000000000000000000000000001", vec![Ip6("::1".parse().unwrap())]);
|
||||
ma_valid("/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21",
|
||||
"29260100094F819700803ECA6566E80C21",
|
||||
vec![IP6]);
|
||||
ma_valid("/udp/0", "110000", vec![UDP]);
|
||||
ma_valid("/tcp/0", "060000", vec![TCP]);
|
||||
ma_valid("/sctp/0", "84010000", vec![SCTP]);
|
||||
ma_valid("/udp/1234", "1104D2", vec![UDP]);
|
||||
ma_valid("/tcp/1234", "0604D2", vec![TCP]);
|
||||
ma_valid("/sctp/1234", "840104D2", vec![SCTP]);
|
||||
ma_valid("/udp/65535", "11FFFF", vec![UDP]);
|
||||
ma_valid("/tcp/65535", "06FFFF", vec![TCP]);
|
||||
vec![Ip6("2601:9:4f81:9700:803e:ca65:66e8:c21".parse().unwrap())]);
|
||||
ma_valid("/udp/0", "110000", vec![Udp(0)]);
|
||||
ma_valid("/tcp/0", "060000", vec![Tcp(0)]);
|
||||
ma_valid("/sctp/0", "84010000", vec![Sctp(0)]);
|
||||
ma_valid("/udp/1234", "1104D2", vec![Udp(1234)]);
|
||||
ma_valid("/tcp/1234", "0604D2", vec![Tcp(1234)]);
|
||||
ma_valid("/sctp/1234", "840104D2", vec![Sctp(1234)]);
|
||||
ma_valid("/udp/65535", "11FFFF", vec![Udp(65535)]);
|
||||
ma_valid("/tcp/65535", "06FFFF", vec![Tcp(65535)]);
|
||||
ma_valid("/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![P2P]);
|
||||
ma_valid("/udp/1234/sctp/1234", "1104D2840104D2", vec![UDP, SCTP]);
|
||||
ma_valid("/udp/1234/udt", "1104D2AD02", vec![UDP, UDT]);
|
||||
ma_valid("/udp/1234/utp", "1104D2AE02", vec![UDP, UTP]);
|
||||
ma_valid("/tcp/1234/http", "0604D2E003", vec![TCP, HTTP]);
|
||||
ma_valid("/tcp/1234/https", "0604D2BB03", vec![TCP, HTTPS]);
|
||||
vec![P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]);
|
||||
ma_valid("/udp/1234/sctp/1234", "1104D2840104D2", vec![Udp(1234), Sctp(1234)]);
|
||||
ma_valid("/udp/1234/udt", "1104D2AD02", vec![Udp(1234), Udt]);
|
||||
ma_valid("/udp/1234/utp", "1104D2AE02", vec![Udp(1234), Utp]);
|
||||
ma_valid("/tcp/1234/http", "0604D2E003", vec![Tcp(1234), Http]);
|
||||
ma_valid("/tcp/1234/https", "0604D2BB03", vec![Tcp(1234), Https]);
|
||||
ma_valid("/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
|
||||
"A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
|
||||
vec![P2P, TCP]);
|
||||
ma_valid("/ip4/127.0.0.1/udp/1234",
|
||||
"047F0000011104D2",
|
||||
vec![IP4, UDP]);
|
||||
ma_valid("/ip4/127.0.0.1/udp/0", "047F000001110000", vec![IP4, UDP]);
|
||||
ma_valid("/ip4/127.0.0.1/tcp/1234",
|
||||
"047F0000010604D2",
|
||||
vec![IP4, TCP]);
|
||||
vec![P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")), Tcp(1234)]);
|
||||
ma_valid("/ip4/127.0.0.1/udp/1234", "047F0000011104D2", vec![Ip4(local.clone()), Udp(1234)]);
|
||||
ma_valid("/ip4/127.0.0.1/udp/0", "047F000001110000", vec![Ip4(local.clone()), Udp(0)]);
|
||||
ma_valid("/ip4/127.0.0.1/tcp/1234", "047F0000010604D2", vec![Ip4(local.clone()), Tcp(1234)]);
|
||||
ma_valid("/ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![IP4, P2P]);
|
||||
vec![Ip4(local.clone()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]);
|
||||
ma_valid("/ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
|
||||
"047F000001A503221220D52EBB89D85B02A284948203A\
|
||||
62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
|
||||
vec![IP4, P2P, TCP]);
|
||||
"047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2",
|
||||
vec![Ip4(local.clone()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")), Tcp(1234)]);
|
||||
// /unix/a/b/c/d/e,
|
||||
// /unix/stdio,
|
||||
// /ip4/1.2.3.4/tcp/80/unix/a/b/c/d/e/f,
|
||||
// /ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234/unix/stdio
|
||||
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\
|
||||
7095/tcp/8000/ws/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"29200108A07AC542013AC986FFFE317095061F40DD03A5\
|
||||
03221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![IP6, TCP, WS, P2P]);
|
||||
ma_valid("/p2p-webrtc-star/ip4/127.0.0.\
|
||||
1/tcp/9090/ws/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"9302047F000001062382DD03A503221220D52EBB89D85B\
|
||||
02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![Libp2pWebrtcStar, IP4, TCP, WS, P2P]);
|
||||
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:\
|
||||
7095/tcp/8000/wss/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"29200108A07AC542013AC986FFFE317095061F40DE03A503221220D52EBB8\
|
||||
9D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![IP6, TCP, WSS, P2P]);
|
||||
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/8000/ws/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"29200108A07AC542013AC986FFFE317095061F40DD03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![Ip6(addr6.clone()), Tcp(8000), Ws, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))
|
||||
]);
|
||||
ma_valid("/p2p-webrtc-star/ip4/127.0.0.1/tcp/9090/ws/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"9302047F000001062382DD03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![P2pWebRtcStar, Ip4(local.clone()), Tcp(9090), Ws, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))
|
||||
]);
|
||||
ma_valid("/ip6/2001:8a0:7ac5:4201:3ac9:86ff:fe31:7095/tcp/8000/wss/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"29200108A07AC542013AC986FFFE317095061F40DE03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![Ip6(addr6.clone()), Tcp(8000), Wss, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]);
|
||||
ma_valid("/ip4/127.0.0.1/tcp/9090/p2p-circuit/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
||||
"047F000001062382A202A503221220D52EBB89D85B\
|
||||
02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![IP4, TCP, P2pCircuit, P2P]);
|
||||
"047F000001062382A202A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B",
|
||||
vec![Ip4(local.clone()), Tcp(9090), P2pCircuit, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -46,7 +46,7 @@ use futures::sync::mpsc;
|
||||
use futures::{future, Future, Poll, Sink, Stream};
|
||||
use libp2p_core::{ConnectionUpgrade, Endpoint, PeerId};
|
||||
use log::Level;
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use parking_lot::{Mutex, RwLock, RwLockUpgradableReadGuard};
|
||||
use protobuf::Message as ProtobufMessage;
|
||||
use smallvec::SmallVec;
|
||||
@ -602,7 +602,7 @@ fn handle_packet_received(
|
||||
}
|
||||
};
|
||||
|
||||
let from: Multiaddr = AddrComponent::P2P(peer_id.into()).into();
|
||||
let from: Multiaddr = Protocol::P2p(peer_id.into()).into();
|
||||
|
||||
let topics = publish
|
||||
.take_topicIDs()
|
||||
|
@ -21,7 +21,7 @@
|
||||
use futures::{future, stream, Future, Stream};
|
||||
use identify_transport::{IdentifyTransport, IdentifyTransportOutcome};
|
||||
use libp2p_core::{PeerId, MuxedTransport, Transport};
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
|
||||
@ -98,7 +98,7 @@ where
|
||||
.map(move |info| {
|
||||
let peer_id = info.info.public_key.clone().into_peer_id();
|
||||
debug!("Identified {} as {:?}", original_addr, peer_id);
|
||||
AddrComponent::P2P(peer_id.into()).into()
|
||||
Protocol::P2p(peer_id.into()).into()
|
||||
})) as Box<Future<Item = _, Error = _> + Send>;
|
||||
(out, real_addr)
|
||||
});
|
||||
@ -199,7 +199,7 @@ where
|
||||
.map(move |info| {
|
||||
let peer_id = info.info.public_key.clone().into_peer_id();
|
||||
debug!("Identified {} as {:?}", original_addr, peer_id);
|
||||
AddrComponent::P2P(peer_id.into()).into()
|
||||
Protocol::P2p(peer_id.into()).into()
|
||||
})) as Box<Future<Item = _, Error = _> + Send>;
|
||||
(out, real_addr)
|
||||
});
|
||||
@ -254,7 +254,7 @@ where
|
||||
.map(move |info| {
|
||||
let peer_id = info.info.public_key.clone().into_peer_id();
|
||||
debug!("Identified {} as {:?}", original_addr, peer_id);
|
||||
AddrComponent::P2P(peer_id.into()).into()
|
||||
Protocol::P2p(peer_id.into()).into()
|
||||
})) as Box<Future<Item = _, Error = _> + Send>;
|
||||
(out, real_addr)
|
||||
});
|
||||
@ -288,7 +288,7 @@ fn multiaddr_to_peerid(addr: Multiaddr) -> Result<PeerId, Multiaddr> {
|
||||
return Err(addr)
|
||||
}
|
||||
match addr.iter().last() {
|
||||
Some(AddrComponent::P2P(ref peer_id)) => {
|
||||
Some(Protocol::P2p(ref peer_id)) => {
|
||||
match PeerId::from_multihash(peer_id.clone()) {
|
||||
Ok(peer_id) => Ok(peer_id),
|
||||
Err(_) => Err(addr),
|
||||
@ -307,7 +307,7 @@ mod tests {
|
||||
use PeerIdTransport;
|
||||
use futures::{Future, Stream};
|
||||
use libp2p_core::{Transport, PeerId, PublicKey};
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use std::io::Error as IoError;
|
||||
use std::iter;
|
||||
|
||||
@ -361,7 +361,7 @@ mod tests {
|
||||
});
|
||||
|
||||
let future = transport
|
||||
.dial(iter::once(AddrComponent::P2P(peer_id.into())).collect())
|
||||
.dial(iter::once(Protocol::P2p(peer_id.into())).collect())
|
||||
.unwrap_or_else(|_| panic!())
|
||||
.then::<_, Result<(), ()>>(|_| Ok(()));
|
||||
|
||||
|
@ -24,7 +24,7 @@ use fnv::FnvHashSet;
|
||||
use futures::{future, Future, stream, Stream};
|
||||
use kbucket::KBucketsPeerId;
|
||||
use libp2p_core::PeerId;
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use protocol;
|
||||
use rand;
|
||||
use smallvec::SmallVec;
|
||||
@ -237,7 +237,7 @@ where
|
||||
// For each node in `to_contact`, start an RPC query and a corresponding entry in the two
|
||||
// `state.current_attempts_*` fields.
|
||||
for peer in to_contact {
|
||||
let multiaddr: Multiaddr = AddrComponent::P2P(peer.clone().into_bytes()).into();
|
||||
let multiaddr: Multiaddr = Protocol::P2p(peer.clone().into_bytes()).into();
|
||||
|
||||
let searched_key2 = searched_key.clone();
|
||||
let current_attempt = find_node_rpc(multiaddr.clone(), searched_key2); // TODO: suboptimal
|
||||
|
10
src/lib.rs
10
src/lib.rs
@ -254,23 +254,23 @@ impl Transport for CommonTransport {
|
||||
/// # #[macro_use]
|
||||
/// # extern crate libp2p;
|
||||
/// # 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 `AddrComponent` 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.
|
||||
///
|
||||
/// 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_rules! multiaddr {
|
||||
($($comp:ident $(($param:expr))*),+) => {
|
||||
{
|
||||
use std::iter;
|
||||
let elem = iter::empty::<$crate::multiaddr::AddrComponent>();
|
||||
let elem = iter::empty::<$crate::multiaddr::Protocol>();
|
||||
$(
|
||||
let elem = {
|
||||
let cmp = $crate::multiaddr::AddrComponent::$comp $(( $param.into() ))*;
|
||||
let cmp = $crate::multiaddr::Protocol::$comp $(( $param.into() ))*;
|
||||
elem.chain(iter::once(cmp))
|
||||
};
|
||||
)+
|
||||
|
@ -43,7 +43,7 @@ extern crate tokio_io;
|
||||
|
||||
use futures::future::{self, Future};
|
||||
use log::Level;
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use std::fmt;
|
||||
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
|
||||
use std::net::IpAddr;
|
||||
@ -119,8 +119,8 @@ where
|
||||
|
||||
fn dial(self, addr: Multiaddr) -> Result<Self::Dial, (Self, Multiaddr)> {
|
||||
let contains_dns = addr.iter().any(|cmp| match cmp {
|
||||
AddrComponent::DNS4(_) => true,
|
||||
AddrComponent::DNS6(_) => true,
|
||||
Protocol::Dns4(_) => true,
|
||||
Protocol::Dns6(_) => true,
|
||||
_ => false,
|
||||
});
|
||||
|
||||
@ -143,10 +143,10 @@ where
|
||||
trace!("Dialing address with DNS: {}", addr);
|
||||
let resolve_iters = addr.iter()
|
||||
.map(move |cmp| match cmp {
|
||||
AddrComponent::DNS4(ref name) => {
|
||||
Protocol::Dns4(ref name) => {
|
||||
future::Either::A(resolve_dns(name, &resolver, ResolveTy::Dns4))
|
||||
}
|
||||
AddrComponent::DNS6(ref name) => {
|
||||
Protocol::Dns6(ref name) => {
|
||||
future::Either::A(resolve_dns(name, &resolver, ResolveTy::Dns6))
|
||||
}
|
||||
cmp => future::Either::B(future::ok(cmp.acquire())),
|
||||
@ -192,7 +192,7 @@ fn resolve_dns<'a>(
|
||||
name: &str,
|
||||
resolver: &CpuPoolResolver,
|
||||
ty: ResolveTy,
|
||||
) -> impl Future<Item = AddrComponent<'a>, Error = IoError> {
|
||||
) -> impl Future<Item = Protocol<'a>, Error = IoError> {
|
||||
let debug_name = if log_enabled!(Level::Trace) {
|
||||
Some(name.to_owned())
|
||||
} else {
|
||||
@ -211,8 +211,8 @@ fn resolve_dns<'a>(
|
||||
addrs
|
||||
.into_iter()
|
||||
.filter_map(move |addr| match (addr, ty) {
|
||||
(IpAddr::V4(addr), ResolveTy::Dns4) => Some(AddrComponent::IP4(addr)),
|
||||
(IpAddr::V6(addr), ResolveTy::Dns6) => Some(AddrComponent::IP6(addr)),
|
||||
(IpAddr::V4(addr), ResolveTy::Dns4) => Some(Protocol::Ip4(addr)),
|
||||
(IpAddr::V6(addr), ResolveTy::Dns6) => Some(Protocol::Ip6(addr)),
|
||||
_ => None,
|
||||
})
|
||||
.next()
|
||||
@ -227,7 +227,7 @@ mod tests {
|
||||
extern crate libp2p_tcp_transport;
|
||||
use self::libp2p_tcp_transport::TcpConfig;
|
||||
use futures::future;
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use std::io::Error as IoError;
|
||||
use swarm::Transport;
|
||||
use DnsConfig;
|
||||
@ -255,12 +255,12 @@ mod tests {
|
||||
let addr = addr.iter().collect::<Vec<_>>();
|
||||
assert_eq!(addr.len(), 2);
|
||||
match addr[1] {
|
||||
AddrComponent::TCP(_) => (),
|
||||
Protocol::Tcp(_) => (),
|
||||
_ => panic!(),
|
||||
};
|
||||
match addr[0] {
|
||||
AddrComponent::DNS4(_) => (),
|
||||
AddrComponent::DNS6(_) => (),
|
||||
Protocol::Dns4(_) => (),
|
||||
Protocol::Dns6(_) => (),
|
||||
_ => panic!(),
|
||||
};
|
||||
Ok(future::empty())
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
use futures::{future::{self, Either}, prelude::*};
|
||||
use message::{CircuitRelay, CircuitRelay_Peer, CircuitRelay_Status, CircuitRelay_Type};
|
||||
use multiaddr::{AddrComponent, Multiaddr, Protocol};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use peerstore::PeerId;
|
||||
use protobuf::{self, Message};
|
||||
use std::{io, error::Error, iter::FromIterator};
|
||||
@ -103,11 +103,10 @@ impl RelayAddr {
|
||||
pub(crate) fn parse(addr: &Multiaddr) -> RelayAddr {
|
||||
let mut iter = addr.iter().peekable();
|
||||
|
||||
let relay = if let Some(&AddrComponent::P2pCircuit) = iter.peek() {
|
||||
let relay = if let Some(&Protocol::P2pCircuit) = iter.peek() {
|
||||
None // Address begins with "p2p-circuit", i.e. no relay is specified.
|
||||
} else {
|
||||
let prefix = iter.by_ref()
|
||||
.take_while(|ac| ac.protocol_id() != Protocol::P2pCircuit);
|
||||
let prefix = iter.by_ref().take_while(|p| *p != Protocol::P2pCircuit);
|
||||
match Peer::from(Multiaddr::from_iter(prefix)) {
|
||||
None => return RelayAddr::Malformed,
|
||||
peer => peer,
|
||||
@ -115,13 +114,12 @@ impl RelayAddr {
|
||||
};
|
||||
|
||||
// After the (optional) relay, "p2p-circuit" is expected.
|
||||
if Some(Protocol::P2pCircuit) != iter.next().map(|ac| ac.protocol_id()) {
|
||||
if Some(Protocol::P2pCircuit) != iter.next() {
|
||||
return RelayAddr::Malformed;
|
||||
}
|
||||
|
||||
let dest = {
|
||||
let suffix = iter.by_ref()
|
||||
.take_while(|ac| ac.protocol_id() != Protocol::P2pCircuit);
|
||||
let suffix = iter.by_ref().take_while(|p| *p != Protocol::P2pCircuit);
|
||||
match Peer::from(Multiaddr::from_iter(suffix)) {
|
||||
None => return RelayAddr::Malformed,
|
||||
Some(p) => p,
|
||||
@ -145,7 +143,7 @@ pub(crate) struct Peer {
|
||||
impl Peer {
|
||||
pub(crate) fn from(mut addr: Multiaddr) -> Option<Peer> {
|
||||
match addr.pop() {
|
||||
Some(AddrComponent::P2P(id)) => {
|
||||
Some(Protocol::P2p(id)) => {
|
||||
PeerId::from_multihash(id).ok().map(|pid| {
|
||||
if addr.iter().count() == 0 {
|
||||
Peer {
|
||||
|
@ -51,7 +51,7 @@ extern crate tokio_tcp;
|
||||
extern crate tokio_current_thread;
|
||||
|
||||
use futures::{future, future::FutureResult, prelude::*, Async, Poll};
|
||||
use multiaddr::{AddrComponent, Multiaddr, ToMultiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr, ToMultiaddr};
|
||||
use std::fmt;
|
||||
use std::io::{Error as IoError, Read, Write};
|
||||
use std::iter;
|
||||
@ -212,15 +212,15 @@ impl Transport for TcpConfig {
|
||||
|
||||
// Check that `server` is a valid TCP/IP address.
|
||||
match (&server_proto1, &server_proto2) {
|
||||
(&AddrComponent::IP4(_), &AddrComponent::TCP(_))
|
||||
| (&AddrComponent::IP6(_), &AddrComponent::TCP(_)) => {}
|
||||
(&Protocol::Ip4(_), &Protocol::Tcp(_))
|
||||
| (&Protocol::Ip6(_), &Protocol::Tcp(_)) => {}
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
// Check that `observed` is a valid TCP/IP address.
|
||||
match (&observed_proto1, &observed_proto2) {
|
||||
(&AddrComponent::IP4(_), &AddrComponent::TCP(_))
|
||||
| (&AddrComponent::IP6(_), &AddrComponent::TCP(_)) => {}
|
||||
(&Protocol::Ip4(_), &Protocol::Tcp(_))
|
||||
| (&Protocol::Ip6(_), &Protocol::Tcp(_)) => {}
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
@ -242,8 +242,8 @@ fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Result<SocketAddr, ()> {
|
||||
}
|
||||
|
||||
match (proto1, proto2) {
|
||||
(AddrComponent::IP4(ip), AddrComponent::TCP(port)) => Ok(SocketAddr::new(ip.into(), port)),
|
||||
(AddrComponent::IP6(ip), AddrComponent::TCP(port)) => Ok(SocketAddr::new(ip.into(), port)),
|
||||
(Protocol::Ip4(ip), Protocol::Tcp(port)) => Ok(SocketAddr::new(ip.into(), port)),
|
||||
(Protocol::Ip6(ip), Protocol::Tcp(port)) => Ok(SocketAddr::new(ip.into(), port)),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ extern crate tokio_io;
|
||||
|
||||
use futures::future::{self, Future, FutureResult};
|
||||
use futures::stream::Stream;
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use std::io::Error as IoError;
|
||||
use std::path::PathBuf;
|
||||
use libp2p_core::Transport;
|
||||
@ -148,7 +148,7 @@ fn multiaddr_to_path(addr: &Multiaddr) -> Result<PathBuf, ()> {
|
||||
}
|
||||
|
||||
match path {
|
||||
Some(AddrComponent::UNIX(ref path)) => Ok(path.as_ref().into()),
|
||||
Some(Protocol::Unix(ref path)) => Ok(path.as_ref().into()),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
@ -158,7 +158,7 @@ mod tests {
|
||||
use super::{multiaddr_to_path, UdsConfig};
|
||||
use futures::stream::Stream;
|
||||
use futures::Future;
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use std::{self, borrow::Cow, path::Path};
|
||||
use libp2p_core::Transport;
|
||||
use tempfile;
|
||||
@ -173,11 +173,11 @@ mod tests {
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
multiaddr_to_path(&Multiaddr::from(AddrComponent::UNIX("/tmp/foo".into()))),
|
||||
multiaddr_to_path(&Multiaddr::from(Protocol::Unix("/tmp/foo".into()))),
|
||||
Ok(Path::new("/tmp/foo").to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
multiaddr_to_path(&Multiaddr::from(AddrComponent::UNIX("/home/bar/baz".into()))),
|
||||
multiaddr_to_path(&Multiaddr::from(Protocol::Unix("/home/bar/baz".into()))),
|
||||
Ok(Path::new("/home/bar/baz").to_owned())
|
||||
);
|
||||
}
|
||||
@ -188,7 +188,7 @@ mod tests {
|
||||
|
||||
let temp_dir = tempfile::tempdir().unwrap();
|
||||
let socket = temp_dir.path().join("socket");
|
||||
let addr = Multiaddr::from(AddrComponent::UNIX(Cow::Owned(socket.to_string_lossy().into_owned())));
|
||||
let addr = Multiaddr::from(Protocol::Unix(Cow::Owned(socket.to_string_lossy().into_owned())));
|
||||
let addr2 = addr.clone();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
|
@ -21,7 +21,7 @@
|
||||
use futures::stream::Then as StreamThen;
|
||||
use futures::sync::{mpsc, oneshot};
|
||||
use futures::{future, future::FutureResult, Async, Future, Poll, Stream};
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use rw_stream_sink::RwStreamSink;
|
||||
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
|
||||
use std::io::{Read, Write};
|
||||
@ -227,19 +227,19 @@ impl Transport for BrowserWsConfig {
|
||||
|
||||
// Check that `server` is a valid TCP/IP address.
|
||||
match (&server_proto0, &server_proto1, &server_proto2) {
|
||||
(&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WS)
|
||||
| (&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WS)
|
||||
| (&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WSS)
|
||||
| (&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WSS) => {}
|
||||
(&Protocol::Ip4(_), &Protocol::Tcp(_), &Protocol::Ws)
|
||||
| (&Protocol::Ip6(_), &Protocol::Tcp(_), &Protocol::Ws)
|
||||
| (&Protocol::Ip4(_), &Protocol::Tcp(_), &Protocol::Wss)
|
||||
| (&Protocol::Ip6(_), &Protocol::Tcp(_), &Protocol::Wss) => {}
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
// Check that `observed` is a valid TCP/IP address.
|
||||
match (&obs_proto0, &obs_proto1, &obs_proto2) {
|
||||
(&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WS)
|
||||
| (&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WS)
|
||||
| (&AddrComponent::IP4(_), &AddrComponent::TCP(_), &AddrComponent::WSS)
|
||||
| (&AddrComponent::IP6(_), &AddrComponent::TCP(_), &AddrComponent::WSS) => {}
|
||||
(&Protocol::Ip4(_), &Protocol::Tcp(_), &Protocol::Ws)
|
||||
| (&Protocol::Ip6(_), &Protocol::Tcp(_), &Protocol::Ws)
|
||||
| (&Protocol::Ip4(_), &Protocol::Tcp(_), &Protocol::Wss)
|
||||
| (&Protocol::Ip6(_), &Protocol::Tcp(_), &Protocol::Wss) => {}
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
@ -333,40 +333,40 @@ fn multiaddr_to_target(addr: &Multiaddr) -> Result<String, ()> {
|
||||
}
|
||||
|
||||
match (&protocols[0], &protocols[1], &protocols[2]) {
|
||||
(&AddrComponent::IP4(ref ip), &AddrComponent::TCP(port), &AddrComponent::WS) => {
|
||||
(&Protocol::Ip4(ref ip), &Protocol::Tcp(port), &Protocol::Ws) => {
|
||||
if ip.is_unspecified() || port == 0 {
|
||||
return Err(());
|
||||
}
|
||||
Ok(format!("ws://{}:{}/", ip, port))
|
||||
}
|
||||
(&AddrComponent::IP6(ref ip), &AddrComponent::TCP(port), &AddrComponent::WS) => {
|
||||
(&Protocol::Ip6(ref ip), &Protocol::Tcp(port), &Protocol::Ws) => {
|
||||
if ip.is_unspecified() || port == 0 {
|
||||
return Err(());
|
||||
}
|
||||
Ok(format!("ws://[{}]:{}/", ip, port))
|
||||
}
|
||||
(&AddrComponent::IP4(ref ip), &AddrComponent::TCP(port), &AddrComponent::WSS) => {
|
||||
(&Protocol::Ip4(ref ip), &Protocol::Tcp(port), &Protocol::Wss) => {
|
||||
if ip.is_unspecified() || port == 0 {
|
||||
return Err(());
|
||||
}
|
||||
Ok(format!("wss://{}:{}/", ip, port))
|
||||
}
|
||||
(&AddrComponent::IP6(ref ip), &AddrComponent::TCP(port), &AddrComponent::WSS) => {
|
||||
(&Protocol::Ip6(ref ip), &Protocol::Tcp(port), &Protocol::Wss) => {
|
||||
if ip.is_unspecified() || port == 0 {
|
||||
return Err(());
|
||||
}
|
||||
Ok(format!("wss://[{}]:{}/", ip, port))
|
||||
}
|
||||
(&AddrComponent::DNS4(ref ns), &AddrComponent::TCP(port), &AddrComponent::WS) => {
|
||||
(&Protocol::Dns4(ref ns), &Protocol::Tcp(port), &Protocol::Ws) => {
|
||||
Ok(format!("ws://{}:{}/", ns, port))
|
||||
}
|
||||
(&AddrComponent::DNS6(ref ns), &AddrComponent::TCP(port), &AddrComponent::WS) => {
|
||||
(&Protocol::Dns6(ref ns), &Protocol::Tcp(port), &Protocol::Ws) => {
|
||||
Ok(format!("ws://{}:{}/", ns, port))
|
||||
}
|
||||
(&AddrComponent::DNS4(ref ns), &AddrComponent::TCP(port), &AddrComponent::WSS) => {
|
||||
(&Protocol::Dns4(ref ns), &Protocol::Tcp(port), &Protocol::Wss) => {
|
||||
Ok(format!("wss://{}:{}/", ns, port))
|
||||
}
|
||||
(&AddrComponent::DNS6(ref ns), &AddrComponent::TCP(port), &AddrComponent::WSS) => {
|
||||
(&Protocol::Dns6(ref ns), &Protocol::Tcp(port), &Protocol::Wss) => {
|
||||
Ok(format!("wss://{}:{}/", ns, port))
|
||||
}
|
||||
_ => Err(()),
|
||||
|
@ -19,7 +19,7 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use futures::{stream, Future, IntoFuture, Sink, Stream};
|
||||
use multiaddr::{AddrComponent, Multiaddr};
|
||||
use multiaddr::{Protocol, Multiaddr};
|
||||
use rw_stream_sink::RwStreamSink;
|
||||
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
|
||||
use swarm::Transport;
|
||||
@ -80,14 +80,14 @@ where
|
||||
) -> Result<(Self::Listener, Multiaddr), (Self, Multiaddr)> {
|
||||
let mut inner_addr = original_addr.clone();
|
||||
match inner_addr.pop() {
|
||||
Some(AddrComponent::WS) => {}
|
||||
Some(Protocol::Ws) => {}
|
||||
_ => return Err((self, original_addr)),
|
||||
};
|
||||
|
||||
let (inner_listen, new_addr) = match self.transport.listen_on(inner_addr) {
|
||||
Ok((listen, mut new_addr)) => {
|
||||
// Need to suffix `/ws` to the listening address.
|
||||
new_addr.append(AddrComponent::WS);
|
||||
new_addr.append(Protocol::Ws);
|
||||
(listen, new_addr)
|
||||
}
|
||||
Err((transport, _)) => {
|
||||
@ -107,7 +107,7 @@ where
|
||||
let upgraded = stream.and_then(|(stream, client_addr)| {
|
||||
// Need to suffix `/ws` to each client address.
|
||||
let client_addr = client_addr.map(|mut addr| {
|
||||
addr.append(AddrComponent::WS);
|
||||
addr.append(Protocol::Ws);
|
||||
addr
|
||||
});
|
||||
debug!("Incoming connection");
|
||||
@ -161,8 +161,8 @@ where
|
||||
fn dial(self, original_addr: Multiaddr) -> Result<Self::Dial, (Self, Multiaddr)> {
|
||||
let mut inner_addr = original_addr.clone();
|
||||
let is_wss = match inner_addr.pop() {
|
||||
Some(AddrComponent::WS) => false,
|
||||
Some(AddrComponent::WSS) => true,
|
||||
Some(Protocol::Ws) => false,
|
||||
Some(Protocol::Wss) => true,
|
||||
_ => {
|
||||
trace!(
|
||||
"Ignoring dial attempt for {} because it is not a websocket multiaddr",
|
||||
@ -197,9 +197,9 @@ where
|
||||
.and_then(move |(connec, client_addr)| {
|
||||
let client_addr = Box::new(client_addr.map(move |mut addr| {
|
||||
if is_wss {
|
||||
addr.append(AddrComponent::WSS);
|
||||
addr.append(Protocol::Wss);
|
||||
} else {
|
||||
addr.append(AddrComponent::WS);
|
||||
addr.append(Protocol::Ws);
|
||||
};
|
||||
addr
|
||||
})) as Box<Future<Item = _, Error = _> + Send>;
|
||||
@ -238,14 +238,14 @@ where
|
||||
fn nat_traversal(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
|
||||
let mut server = server.clone();
|
||||
let last_proto = match server.pop() {
|
||||
Some(v @ AddrComponent::WS) | Some(v @ AddrComponent::WSS) => v,
|
||||
Some(v @ Protocol::Ws) | Some(v @ Protocol::Wss) => v,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let mut observed = observed.clone();
|
||||
match observed.pop() {
|
||||
Some(AddrComponent::WS) => false,
|
||||
Some(AddrComponent::WSS) => true,
|
||||
Some(Protocol::Ws) => false,
|
||||
Some(Protocol::Wss) => true,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
@ -266,16 +266,16 @@ fn client_addr_to_ws(client_addr: &Multiaddr, is_wss: bool) -> String {
|
||||
"127.0.0.1".to_owned()
|
||||
} else {
|
||||
match (&protocols[0], &protocols[1]) {
|
||||
(&AddrComponent::IP4(ref ip), &AddrComponent::TCP(port)) => {
|
||||
(&Protocol::Ip4(ref ip), &Protocol::Tcp(port)) => {
|
||||
format!("{}:{}", ip, port)
|
||||
}
|
||||
(&AddrComponent::IP6(ref ip), &AddrComponent::TCP(port)) => {
|
||||
(&Protocol::Ip6(ref ip), &Protocol::Tcp(port)) => {
|
||||
format!("[{}]:{}", ip, port)
|
||||
}
|
||||
(&AddrComponent::DNS4(ref ns), &AddrComponent::TCP(port)) => {
|
||||
(&Protocol::Dns4(ref ns), &Protocol::Tcp(port)) => {
|
||||
format!("{}:{}", ns, port)
|
||||
}
|
||||
(&AddrComponent::DNS6(ref ns), &AddrComponent::TCP(port)) => {
|
||||
(&Protocol::Dns6(ref ns), &Protocol::Tcp(port)) => {
|
||||
format!("{}:{}", ns, port)
|
||||
}
|
||||
_ => "127.0.0.1".to_owned(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user