From 6950fff7639b116b0575397f6d2ec634c5522007 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 1 May 2022 13:18:38 +0200 Subject: [PATCH 1/2] cargo fmt --- src/errors.rs | 6 +- src/from_url.rs | 57 ++++++---- src/lib.rs | 110 ++++++++++++-------- src/onion_addr.rs | 10 +- src/protocol.rs | 112 +++++++++++--------- tests/lib.rs | 260 ++++++++++++++++++++++++++++++++-------------- 6 files changed, 358 insertions(+), 197 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index c272a28..a867a84 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,4 +1,4 @@ -use std::{net, fmt, error, io, num, str, string}; +use std::{error, fmt, io, net, num, str, string}; use unsigned_varint::decode; pub type Result = ::std::result::Result; @@ -25,7 +25,9 @@ impl fmt::Display for Error { Error::InvalidUvar(e) => write!(f, "failed to decode unsigned varint: {}", e), Error::ParsingError(e) => write!(f, "failed to parse: {}", e), Error::UnknownProtocolId(id) => write!(f, "unknown protocol id: {}", id), - Error::UnknownProtocolString(string) => write!(f, "unknown protocol string: {}", string), + Error::UnknownProtocolString(string) => { + write!(f, "unknown protocol string: {}", string) + } } } } diff --git a/src/from_url.rs b/src/from_url.rs index 9d5914a..37eb667 100644 --- a/src/from_url.rs +++ b/src/from_url.rs @@ -57,18 +57,21 @@ fn from_url_inner(url: &str, lossy: bool) -> std::result::Result from_url_inner_http_ws(url, lossy), "unix" => from_url_inner_path(url, lossy), - _ => Err(FromUrlErr::UnsupportedScheme) + _ => Err(FromUrlErr::UnsupportedScheme), } } /// Called when `url.scheme()` is an Internet-like URL. -fn from_url_inner_http_ws(url: url::Url, lossy: bool) -> std::result::Result { +fn from_url_inner_http_ws( + url: url::Url, + lossy: bool, +) -> std::result::Result { let (protocol, lost_path, default_port) = match url.scheme() { "ws" => (Protocol::Ws(url.path().to_owned().into()), false, 80), "wss" => (Protocol::Wss(url.path().to_owned().into()), false, 443), "http" => (Protocol::Http, true, 80), "https" => (Protocol::Https, true, 443), - _ => unreachable!("We only call this function for one of the given schemes; qed") + _ => unreachable!("We only call this function for one of the given schemes; qed"), }; let port = Protocol::Tcp(url.port().unwrap_or(default_port)); @@ -82,12 +85,13 @@ fn from_url_inner_http_ws(url: url::Url, lossy: bool) -> std::result::Result std::result::Result std::result::Result { let protocol = match url.scheme() { "unix" => Protocol::Unix(url.path().to_owned().into()), - _ => unreachable!("We only call this function for one of the given schemes; qed") + _ => unreachable!("We only call this function for one of the given schemes; qed"), }; - if !lossy && ( - !url.username().is_empty() || - url.password().is_some() || - url.query().is_some() || - url.fragment().is_some() - ) { + if !lossy + && (!url.username().is_empty() + || url.password().is_some() + || url.query().is_some() + || url.fragment().is_some()) + { return Err(FromUrlErr::InformationLoss); } @@ -137,8 +141,7 @@ impl fmt::Display for FromUrlErr { } } -impl error::Error for FromUrlErr { -} +impl error::Error for FromUrlErr {} #[cfg(test)] mod tests { @@ -146,7 +149,7 @@ mod tests { #[test] fn parse_garbage_doesnt_panic() { - for _ in 0 .. 50 { + for _ in 0..50 { let url = (0..16).map(|_| rand::random::()).collect::>(); let url = String::from_utf8_lossy(&url); assert!(from_url(&url).is_err()); @@ -223,7 +226,7 @@ mod tests { fn wrong_scheme() { match from_url("foo://127.0.0.1") { Err(FromUrlErr::UnsupportedScheme) => {} - _ => panic!() + _ => panic!(), } } @@ -271,13 +274,23 @@ mod tests { #[test] fn ws_path() { let addr = from_url("ws://1.2.3.4:1000/foo/bar").unwrap(); - assert_eq!(addr, "/ip4/1.2.3.4/tcp/1000/x-parity-ws/%2ffoo%2fbar".parse().unwrap()); + assert_eq!( + addr, + "/ip4/1.2.3.4/tcp/1000/x-parity-ws/%2ffoo%2fbar" + .parse() + .unwrap() + ); let addr = from_url("ws://1.2.3.4:1000/").unwrap(); assert_eq!(addr, "/ip4/1.2.3.4/tcp/1000/ws".parse().unwrap()); let addr = from_url("wss://1.2.3.4:1000/foo/bar").unwrap(); - assert_eq!(addr, "/ip4/1.2.3.4/tcp/1000/x-parity-wss/%2ffoo%2fbar".parse().unwrap()); + assert_eq!( + addr, + "/ip4/1.2.3.4/tcp/1000/x-parity-wss/%2ffoo%2fbar" + .parse() + .unwrap() + ); let addr = from_url("wss://1.2.3.4:1000").unwrap(); assert_eq!(addr, "/ip4/1.2.3.4/tcp/1000/wss".parse().unwrap()); diff --git a/src/lib.rs b/src/lib.rs index c9c4b41..f0e2196 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,37 +1,32 @@ -///! Implementation of [multiaddr](https://github.com/jbenet/multiaddr) in Rust. - +///! Implementation of [multiaddr](https://github.com/multiformats/multiaddr) in Rust. pub use multihash; -mod protocol; -mod onion_addr; mod errors; +mod onion_addr; +mod protocol; #[cfg(feature = "url")] mod from_url; +pub use self::errors::{Error, Result}; +pub use self::onion_addr::Onion3Addr; +pub use self::protocol::Protocol; use serde::{ - Deserialize, - Deserializer, - Serialize, - Serializer, - de::{self, Error as DeserializerError} + de::{self, Error as DeserializerError}, + Deserialize, Deserializer, Serialize, Serializer, }; use std::{ convert::TryFrom, - fmt, - io, + fmt, io, iter::FromIterator, net::{IpAddr, Ipv4Addr, Ipv6Addr}, result::Result as StdResult, str::FromStr, - sync::Arc + sync::Arc, }; -pub use self::errors::{Result, Error}; -pub use self::protocol::Protocol; -pub use self::onion_addr::Onion3Addr; #[cfg(feature = "url")] -pub use self::from_url::{FromUrlErr, from_url, from_url_lossy}; +pub use self::from_url::{from_url, from_url_lossy, FromUrlErr}; static_assertions::const_assert! { // This check is most certainly overkill right now, but done here @@ -42,17 +37,23 @@ static_assertions::const_assert! { /// Representation of a Multiaddr. #[allow(clippy::rc_buffer)] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)] -pub struct Multiaddr { bytes: Arc> } +pub struct Multiaddr { + bytes: Arc>, +} impl Multiaddr { /// Create a new, empty multiaddress. pub fn empty() -> Self { - Self { bytes: Arc::new(Vec::new()) } + Self { + bytes: Arc::new(Vec::new()), + } } /// Create a new, empty multiaddress with the given capacity. pub fn with_capacity(n: usize) -> Self { - Self { bytes: Arc::new(Vec::with_capacity(n)) } + Self { + bytes: Arc::new(Vec::with_capacity(n)), + } } /// Return the length in bytes of this multiaddress. @@ -85,7 +86,8 @@ impl Multiaddr { pub fn push(&mut self, p: Protocol<'_>) { let mut w = io::Cursor::<&mut Vec>::new(Arc::make_mut(&mut self.bytes)); w.set_position(w.get_ref().len() as u64); - p.write_bytes(&mut w).expect("Writing to a `io::Cursor<&mut Vec>` never fails.") + p.write_bytes(&mut w) + .expect("Writing to a `io::Cursor<&mut Vec>` never fails.") } /// Pops the last `Protocol` of this multiaddr, or `None` if the multiaddr is empty. @@ -101,12 +103,12 @@ impl Multiaddr { pub fn pop<'a>(&mut self) -> Option> { let mut slice = &self.bytes[..]; // the remaining multiaddr slice if slice.is_empty() { - return None + 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() + break p.acquire(); } slice = s }; @@ -119,7 +121,8 @@ impl Multiaddr { pub fn with(mut self, p: Protocol<'_>) -> Self { let mut w = io::Cursor::<&mut Vec>::new(Arc::make_mut(&mut self.bytes)); w.set_position(w.get_ref().len() as u64); - p.write_bytes(&mut w).expect("Writing to a `io::Cursor<&mut Vec>` never fails."); + p.write_bytes(&mut w) + .expect("Writing to a `io::Cursor<&mut Vec>` never fails."); self } @@ -153,7 +156,7 @@ impl Multiaddr { /// updated `Protocol` at position `at` will be returned. pub fn replace<'a, F>(&self, at: usize, by: F) -> Option where - F: FnOnce(&Protocol<'_>) -> Option> + F: FnOnce(&Protocol<'_>) -> Option>, { let mut address = Multiaddr::with_capacity(self.len()); let mut fun = Some(by); @@ -165,14 +168,18 @@ impl Multiaddr { if let Some(q) = f(&p) { address = address.with(q); replaced = true; - continue + continue; } - return None + return None; } address = address.with(p) } - if replaced { Some(address) } else { None } + if replaced { + Some(address) + } else { + None + } } /// Checks whether the given `Multiaddr` is a suffix of this `Multiaddr`. @@ -180,9 +187,9 @@ impl Multiaddr { let n = self.bytes.len(); let m = other.bytes.len(); if n < m { - return false + return false; } - self.bytes[(n - m) ..] == other.bytes[..] + self.bytes[(n - m)..] == other.bytes[..] } } @@ -234,9 +241,12 @@ impl<'a> FromIterator> for Multiaddr { { let mut writer = Vec::new(); for cmp in iter { - cmp.write_bytes(&mut writer).expect("Writing to a `Vec` never fails."); + cmp.write_bytes(&mut writer) + .expect("Writing to a `Vec` never fails."); + } + Multiaddr { + bytes: Arc::new(writer), } - Multiaddr { bytes: Arc::new(writer) } } } @@ -249,15 +259,18 @@ impl FromStr for Multiaddr { if Some("") != parts.next() { // A multiaddr must start with `/` - return Err(Error::InvalidMultiaddr) + 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."); + p.write_bytes(&mut writer) + .expect("Writing to a `Vec` never fails."); } - Ok(Multiaddr { bytes: Arc::new(writer) }) + Ok(Multiaddr { + bytes: Arc::new(writer), + }) } } @@ -283,7 +296,8 @@ impl<'a> Iterator for Iter<'a> { impl<'a> From> 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."); + p.write_bytes(&mut w) + .expect("Writing to a `Vec` never fails."); Multiaddr { bytes: Arc::new(w) } } } @@ -292,7 +306,7 @@ impl From for Multiaddr { fn from(v: IpAddr) -> Multiaddr { match v { IpAddr::V4(a) => a.into(), - IpAddr::V6(a) => a.into() + IpAddr::V6(a) => a.into(), } } } @@ -357,7 +371,9 @@ impl<'de> Deserialize<'de> for Multiaddr { where D: Deserializer<'de>, { - struct Visitor { is_human_readable: bool } + struct Visitor { + is_human_readable: bool, + } impl<'de> de::Visitor<'de> for Visitor { type Value = Multiaddr; @@ -365,9 +381,15 @@ impl<'de> Deserialize<'de> for Multiaddr { fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("multiaddress") } - fn visit_seq>(self, mut seq: A) -> StdResult { - let mut buf: Vec = Vec::with_capacity(std::cmp::min(seq.size_hint().unwrap_or(0), 4096)); - while let Some(e) = seq.next_element()? { buf.push(e); } + fn visit_seq>( + self, + mut seq: A, + ) -> StdResult { + let mut buf: Vec = + Vec::with_capacity(std::cmp::min(seq.size_hint().unwrap_or(0), 4096)); + while let Some(e) = seq.next_element()? { + buf.push(e); + } if self.is_human_readable { let s = String::from_utf8(buf).map_err(DeserializerError::custom)?; s.parse().map_err(DeserializerError::custom) @@ -396,9 +418,13 @@ impl<'de> Deserialize<'de> for Multiaddr { } if deserializer.is_human_readable() { - deserializer.deserialize_str(Visitor { is_human_readable: true }) + deserializer.deserialize_str(Visitor { + is_human_readable: true, + }) } else { - deserializer.deserialize_bytes(Visitor { is_human_readable: false }) + deserializer.deserialize_bytes(Visitor { + is_human_readable: false, + }) } } } diff --git a/src/onion_addr.rs b/src/onion_addr.rs index 2926128..08cedb7 100644 --- a/src/onion_addr.rs +++ b/src/onion_addr.rs @@ -27,7 +27,7 @@ impl PartialEq for Onion3Addr<'_> { } } -impl Eq for Onion3Addr<'_> { } +impl Eq for Onion3Addr<'_> {} impl From<([u8; 35], u16)> for Onion3Addr<'_> { fn from(parts: ([u8; 35], u16)) -> Self { @@ -43,9 +43,9 @@ impl<'a> From<(&'a [u8; 35], u16)> for Onion3Addr<'a> { impl fmt::Debug for Onion3Addr<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - f.debug_tuple("Onion3Addr") - .field(&format!("{:02x?}", &self.0[..])) - .field(&self.1) - .finish() + f.debug_tuple("Onion3Addr") + .field(&format!("{:02x?}", &self.0[..])) + .field(&self.1) + .finish() } } diff --git a/src/protocol.rs b/src/protocol.rs index e67d5e6..bed0abe 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -1,6 +1,7 @@ +use crate::onion_addr::Onion3Addr; +use crate::{Error, Result}; use arrayref::array_ref; use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt}; -use crate::{Result, Error}; use data_encoding::BASE32; use multihash::Multihash; use std::{ @@ -9,10 +10,9 @@ use std::{ fmt, io::{Cursor, Write}, net::{IpAddr, Ipv4Addr, Ipv6Addr}, - str::{self, FromStr} + str::{self, FromStr}, }; -use unsigned_varint::{encode, decode}; -use crate::onion_addr::Onion3Addr; +use unsigned_varint::{decode, encode}; // All the values are obtained by converting hexadecimal protocol codes to u32. // Protocols as well as their corresponding codes are defined in @@ -43,9 +43,9 @@ const UDT: u32 = 301; const UNIX: u32 = 400; const UTP: u32 = 302; const WS: u32 = 477; -const WS_WITH_PATH: u32 = 4770; // Note: not standard +const WS_WITH_PATH: u32 = 4770; // Note: not standard const WSS: u32 = 478; -const WSS_WITH_PATH: u32 = 4780; // Note: not standard +const WSS_WITH_PATH: u32 = 4780; // Note: not standard const PATH_SEGMENT_ENCODE_SET: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS .add(b'%') @@ -107,7 +107,7 @@ impl<'a> Protocol<'a> { /// that iteration has finished whenever appropriate. pub fn from_str_parts(mut iter: I) -> Result where - I: Iterator + I: Iterator, { match iter.next().ok_or(Error::InvalidProtocolString)? { "ip4" => { @@ -164,16 +164,16 @@ impl<'a> Protocol<'a> { } "http" => Ok(Protocol::Http), "https" => Ok(Protocol::Https), - "onion" => - iter.next() - .ok_or(Error::InvalidProtocolString) - .and_then(|s| read_onion(&s.to_uppercase())) - .map(|(a, p)| Protocol::Onion(Cow::Owned(a), p)), - "onion3" => - iter.next() - .ok_or(Error::InvalidProtocolString) - .and_then(|s| read_onion3(&s.to_uppercase())) - .map(|(a, p)| Protocol::Onion3((a, p).into())), + "onion" => iter + .next() + .ok_or(Error::InvalidProtocolString) + .and_then(|s| read_onion(&s.to_uppercase())) + .map(|(a, p)| Protocol::Onion(Cow::Owned(a), p)), + "onion3" => iter + .next() + .ok_or(Error::InvalidProtocolString) + .and_then(|s| read_onion3(&s.to_uppercase())) + .map(|(a, p)| Protocol::Onion3((a, p).into())), "quic" => Ok(Protocol::Quic), "ws" => Ok(Protocol::Ws(Cow::Borrowed("/"))), "wss" => Ok(Protocol::Wss(Cow::Borrowed("/"))), @@ -195,7 +195,7 @@ impl<'a> Protocol<'a> { let s = iter.next().ok_or(Error::InvalidProtocolString)?; Ok(Protocol::Memory(s.parse()?)) } - unknown => Err(Error::UnknownProtocolString(unknown.to_string())) + unknown => Err(Error::UnknownProtocolString(unknown.to_string())), } } @@ -204,7 +204,7 @@ impl<'a> Protocol<'a> { 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) + return Err(Error::DataLessThanLen); } Ok(input.split_at(n)) } @@ -234,13 +234,19 @@ impl<'a> Protocol<'a> { DNSADDR => { let (n, input) = decode::usize(input)?; let (data, rest) = split_at(n, input)?; - Ok((Protocol::Dnsaddr(Cow::Borrowed(str::from_utf8(data)?)), rest)) + Ok(( + Protocol::Dnsaddr(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)) + Ok(( + Protocol::Ip4(Ipv4Addr::new(data[0], data[1], data[2], data[3])), + rest, + )) } IP6 => { let (data, rest) = split_at(16, input)?; @@ -251,14 +257,9 @@ impl<'a> Protocol<'a> { *x = rdr.read_u16::()?; } - let addr = Ipv6Addr::new(seg[0], - seg[1], - seg[2], - seg[3], - seg[4], - seg[5], - seg[6], - seg[7]); + let addr = Ipv6Addr::new( + seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7], + ); Ok((Protocol::Ip6(addr), rest)) } @@ -273,13 +274,19 @@ impl<'a> Protocol<'a> { } ONION => { let (data, rest) = split_at(12, input)?; - let port = BigEndian::read_u16(&data[10 ..]); - Ok((Protocol::Onion(Cow::Borrowed(array_ref!(data, 0, 10)), port), rest)) + let port = BigEndian::read_u16(&data[10..]); + Ok(( + Protocol::Onion(Cow::Borrowed(array_ref!(data, 0, 10)), port), + rest, + )) } ONION3 => { let (data, rest) = split_at(37, input)?; - let port = BigEndian::read_u16(&data[35 ..]); - Ok((Protocol::Onion3((array_ref!(data, 0, 35), port).into()), rest)) + let port = BigEndian::read_u16(&data[35..]); + Ok(( + Protocol::Onion3((array_ref!(data, 0, 35), port).into()), + rest, + )) } P2P => { let (n, input) = decode::usize(input)?; @@ -326,7 +333,7 @@ impl<'a> Protocol<'a> { let (data, rest) = split_at(n, input)?; Ok((Protocol::Wss(Cow::Borrowed(str::from_utf8(data)?)), rest)) } - _ => Err(Error::UnknownProtocolId(id)) + _ => Err(Error::UnknownProtocolId(id)), } } @@ -419,14 +426,14 @@ impl<'a> Protocol<'a> { let bytes = s.as_bytes(); w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?; w.write_all(&bytes)? - }, + } Protocol::Wss(ref s) if s == "/" => w.write_all(encode::u32(WSS, &mut buf))?, Protocol::Wss(s) => { w.write_all(encode::u32(WSS_WITH_PATH, &mut buf))?; let bytes = s.as_bytes(); w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?; w.write_all(&bytes)? - }, + } 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))?, @@ -495,7 +502,7 @@ impl<'a> fmt::Display for Protocol<'a> { let s = BASE32.encode(addr.as_ref()); write!(f, "/onion/{}:{}", s.to_lowercase(), port) } - Onion3(addr ) => { + Onion3(addr) => { let s = BASE32.encode(addr.hash()); write!(f, "/onion3/{}:{}", s.to_lowercase(), addr.port()) } @@ -511,14 +518,16 @@ impl<'a> fmt::Display for Protocol<'a> { Utp => f.write_str("/utp"), Ws(ref s) if s == "/" => f.write_str("/ws"), Ws(s) => { - let encoded = percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET); + let encoded = + percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET); write!(f, "/x-parity-ws/{}", encoded) - }, + } Wss(ref s) if s == "/" => f.write_str("/wss"), Wss(s) => { - let encoded = percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET); + let encoded = + percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET); write!(f, "/x-parity-wss/{}", encoded) - }, + } } } } @@ -555,11 +564,12 @@ macro_rules! read_onion_impl { // address part (without ".onion") let b32 = parts.next().ok_or(Error::InvalidMultiaddr)?; if b32.len() != $encoded_len { - return Err(Error::InvalidMultiaddr) + return Err(Error::InvalidMultiaddr); } // port number - let port = parts.next() + let port = parts + .next() .ok_or(Error::InvalidMultiaddr) .and_then(|p| str::parse(p).map_err(From::from))?; @@ -570,19 +580,25 @@ macro_rules! read_onion_impl { // nothing else expected if parts.next().is_some() { - return Err(Error::InvalidMultiaddr) + return Err(Error::InvalidMultiaddr); } - if $len != BASE32.decode_len(b32.len()).map_err(|_| Error::InvalidMultiaddr)? { - return Err(Error::InvalidMultiaddr) + if $len + != BASE32 + .decode_len(b32.len()) + .map_err(|_| Error::InvalidMultiaddr)? + { + return Err(Error::InvalidMultiaddr); } let mut buf = [0u8; $len]; - BASE32.decode_mut(b32.as_bytes(), &mut buf).map_err(|_| Error::InvalidMultiaddr)?; + BASE32 + .decode_mut(b32.as_bytes(), &mut buf) + .map_err(|_| Error::InvalidMultiaddr)?; Ok((buf, port)) } - } + }; } // Parse a version 2 onion address and return its binary representation. diff --git a/tests/lib.rs b/tests/lib.rs index 39ed765..78ee058 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,13 +1,13 @@ use data_encoding::HEXUPPER; -use multihash::Multihash; use multiaddr::*; +use multihash::Multihash; use quickcheck::{Arbitrary, Gen, QuickCheck}; use std::{ borrow::Cow, convert::{TryFrom, TryInto}, - iter::{FromIterator, self}, + iter::{self, FromIterator}, net::{Ipv4Addr, Ipv6Addr}, - str::FromStr + str::FromStr, }; // Property tests @@ -37,7 +37,9 @@ fn byteswriter() { for p in b.0.iter() { x = x.with(p) } - x.iter().zip(a.0.iter().chain(b.0.iter())).all(|(x, y)| x == y) + x.iter() + .zip(a.0.iter().chain(b.0.iter())) + .all(|(x, y)| x == y) } QuickCheck::new().quickcheck(prop as fn(Ma, Ma) -> bool) } @@ -58,7 +60,7 @@ fn push_pop_identity() { fn ends_with() { fn prop(Ma(m): Ma) { let n = m.iter().count(); - for i in 0 .. n { + for i in 0..n { let suffix = m.iter().skip(i).collect::(); assert!(m.ends_with(&suffix)); } @@ -66,16 +68,14 @@ fn ends_with() { QuickCheck::new().quickcheck(prop as fn(_)) } - // Arbitrary impls - #[derive(PartialEq, Eq, Clone, Hash, Debug)] struct Ma(Multiaddr); impl Arbitrary for Ma { fn arbitrary(g: &mut G) -> Self { - let iter = (0 .. g.next_u32() % 128).map(|_| Proto::arbitrary(g).0); + let iter = (0..g.next_u32() % 128).map(|_| Proto::arbitrary(g).0); Ma(Multiaddr::from_iter(iter)) } } @@ -86,21 +86,24 @@ struct Proto(Protocol<'static>); impl Arbitrary for Proto { fn arbitrary(g: &mut G) -> Self { use Protocol::*; - match u8::arbitrary(g) % 26 { // TODO: Add Protocol::Quic - 0 => Proto(Dccp(Arbitrary::arbitrary(g))), - 1 => Proto(Dns(Cow::Owned(SubString::arbitrary(g).0))), - 2 => Proto(Dns4(Cow::Owned(SubString::arbitrary(g).0))), - 3 => Proto(Dns6(Cow::Owned(SubString::arbitrary(g).0))), - 4 => Proto(Http), - 5 => Proto(Https), - 6 => Proto(Ip4(Ipv4Addr::arbitrary(g))), - 7 => Proto(Ip6(Ipv6Addr::arbitrary(g))), - 8 => Proto(P2pWebRtcDirect), - 9 => Proto(P2pWebRtcStar), + match u8::arbitrary(g) % 26 { + // TODO: Add Protocol::Quic + 0 => Proto(Dccp(Arbitrary::arbitrary(g))), + 1 => Proto(Dns(Cow::Owned(SubString::arbitrary(g).0))), + 2 => Proto(Dns4(Cow::Owned(SubString::arbitrary(g).0))), + 3 => Proto(Dns6(Cow::Owned(SubString::arbitrary(g).0))), + 4 => Proto(Http), + 5 => Proto(Https), + 6 => Proto(Ip4(Ipv4Addr::arbitrary(g))), + 7 => Proto(Ip6(Ipv6Addr::arbitrary(g))), + 8 => Proto(P2pWebRtcDirect), + 9 => Proto(P2pWebRtcStar), 10 => Proto(P2pWebSocketStar), 11 => Proto(Memory(Arbitrary::arbitrary(g))), // TODO: impl Arbitrary for Multihash: - 12 => Proto(P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))), + 12 => Proto(P2p(multihash( + "QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", + ))), 13 => Proto(P2pCircuit), 14 => Proto(Quic), 15 => Proto(Sctp(Arbitrary::arbitrary(g))), @@ -112,24 +115,23 @@ impl Arbitrary for Proto { 21 => Proto(Ws("/".into())), 22 => Proto(Wss("/".into())), 23 => { - let a = iter::repeat_with(|| u8::arbitrary(g)) .take(10) .collect::>() .try_into() .unwrap(); Proto(Onion(Cow::Owned(a), std::cmp::max(1, u16::arbitrary(g)))) - }, + } 24 => { - let a: [u8;35] = iter::repeat_with(|| u8::arbitrary(g)) + let a: [u8; 35] = iter::repeat_with(|| u8::arbitrary(g)) .take(35) .collect::>() .try_into() .unwrap(); Proto(Onion3((a, std::cmp::max(1, u16::arbitrary(g))).into())) - }, + } 25 => Proto(Tls), - _ => panic!("outside range") + _ => panic!("outside range"), } } } @@ -145,16 +147,17 @@ impl Arbitrary for SubString { } } - // other unit tests - fn ma_valid(source: &str, target: &str, protocols: Vec>) { let parsed = source.parse::().unwrap(); assert_eq!(HEXUPPER.encode(&parsed.to_vec()[..]), target); assert_eq!(parsed.iter().collect::>(), protocols); assert_eq!(source.parse::().unwrap().to_string(), source); - assert_eq!(Multiaddr::try_from(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 { @@ -180,12 +183,26 @@ fn construct_success() { 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("2601:9:4f81:9700:803e:ca65:66e8:c21".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("2601:9:4f81:9700:803e:ca65:66e8:c21".parse().unwrap())], + ); ma_valid("/udp/0", "91020000", vec![Udp(0)]); ma_valid("/tcp/0", "060000", vec![Tcp(0)]); ma_valid("/sctp/0", "84010000", vec![Sctp(0)]); @@ -194,24 +211,58 @@ fn construct_success() { ma_valid("/sctp/1234", "840104D2", vec![Sctp(1234)]); ma_valid("/udp/65535", "9102FFFF", vec![Udp(65535)]); ma_valid("/tcp/65535", "06FFFF", vec![Tcp(65535)]); - ma_valid("/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", - "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", - vec![P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]); - ma_valid("/udp/1234/sctp/1234", "910204D2840104D2", vec![Udp(1234), Sctp(1234)]); + ma_valid( + "/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", + "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", + vec![P2p(multihash( + "QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", + ))], + ); + ma_valid( + "/udp/1234/sctp/1234", + "910204D2840104D2", + vec![Udp(1234), Sctp(1234)], + ); ma_valid("/udp/1234/udt", "910204D2AD02", vec![Udp(1234), Udt]); ma_valid("/udp/1234/utp", "910204D2AE02", vec![Udp(1234), Utp]); ma_valid("/tcp/1234/http", "0604D2E003", vec![Tcp(1234), Http]); - ma_valid("/tcp/1234/tls/http", "0604D2C003E003", vec![Tcp(1234), Tls, Http]); + ma_valid( + "/tcp/1234/tls/http", + "0604D2C003E003", + vec![Tcp(1234), Tls, Http], + ); ma_valid("/tcp/1234/https", "0604D2BB03", vec![Tcp(1234), Https]); - ma_valid("/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", - "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2", - vec![P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")), Tcp(1234)]); - ma_valid("/ip4/127.0.0.1/udp/1234", "047F000001910204D2", vec![Ip4(local.clone()), Udp(1234)]); - ma_valid("/ip4/127.0.0.1/udp/0", "047F00000191020000", 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(local.clone()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]); + ma_valid( + "/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", + "A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2", + vec![ + P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")), + Tcp(1234), + ], + ); + ma_valid( + "/ip4/127.0.0.1/udp/1234", + "047F000001910204D2", + vec![Ip4(local.clone()), Udp(1234)], + ); + ma_valid( + "/ip4/127.0.0.1/udp/0", + "047F00000191020000", + 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(local.clone()), + P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")), + ], + ); ma_valid("/ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", "047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2", vec![Ip4(local.clone()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")), Tcp(1234)]); @@ -237,26 +288,50 @@ fn construct_success() { ma_valid( "/onion/aaimaq4ygg2iegci:80", "BC030010C0439831B48218480050", - vec![Onion(Cow::Owned([0, 16, 192, 67, 152, 49, 180, 130, 24, 72]), 80)], + vec![Onion( + Cow::Owned([0, 16, 192, 67, 152, 49, 180, 130, 24, 72]), + 80, + )], ); ma_valid( "/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:1234", "BD03ADADEC040BE047F9658668B11A504F3155001F231A37F54C4476C07FB4CC139ED7E30304D2", - vec![Onion3(([173, 173, 236, 4, 11, 224, 71, 249, 101, 134, 104, 177, 26, 80, 79, 49, 85, 0, 31, 35, 26, 55, 245, 76, 68, 118, 192, 127, 180, 204, 19, 158, 215, 227, 3], 1234).into())], + vec![Onion3( + ( + [ + 173, 173, 236, 4, 11, 224, 71, 249, 101, 134, 104, 177, 26, 80, 79, 49, 85, 0, + 31, 35, 26, 55, 245, 76, 68, 118, 192, 127, 180, 204, 19, 158, 215, 227, 3, + ], + 1234, + ) + .into(), + )], ); ma_valid( "/dnsaddr/sjc-1.bootstrap.libp2p.io", "3819736A632D312E626F6F7473747261702E6C69627032702E696F", - vec![Dnsaddr(Cow::Borrowed("sjc-1.bootstrap.libp2p.io"))] + vec![Dnsaddr(Cow::Borrowed("sjc-1.bootstrap.libp2p.io"))], ); ma_valid( "/dnsaddr/sjc-1.bootstrap.libp2p.io/tcp/1234/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN", "3819736A632D312E626F6F7473747261702E6C69627032702E696F0604D2A50322122006B3608AA000274049EB28AD8E793A26FF6FAB281A7D3BD77CD18EB745DFAABB", vec![Dnsaddr(Cow::Borrowed("sjc-1.bootstrap.libp2p.io")), Tcp(1234), P2p(multihash("QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN"))] ); - ma_valid("/ip4/127.0.0.1/tcp/127/ws", "047F00000106007FDD03", vec![Ip4(local.clone()),Tcp(127),Ws("/".into())] ); - ma_valid("/ip4/127.0.0.1/tcp/127/tls", "047F00000106007FC003", vec![Ip4(local.clone()),Tcp(127),Tls] ); - ma_valid("/ip4/127.0.0.1/tcp/127/tls/ws", "047F00000106007FC003DD03", vec![Ip4(local.clone()),Tcp(127),Tls,Ws("/".into())] ); + ma_valid( + "/ip4/127.0.0.1/tcp/127/ws", + "047F00000106007FDD03", + vec![Ip4(local.clone()), Tcp(127), Ws("/".into())], + ); + ma_valid( + "/ip4/127.0.0.1/tcp/127/tls", + "047F00000106007FC003", + vec![Ip4(local.clone()), Tcp(127), Tls], + ); + ma_valid( + "/ip4/127.0.0.1/tcp/127/tls/ws", + "047F00000106007FC003DD03", + vec![Ip4(local.clone()), Tcp(127), Tls, Ws("/".into())], + ); } #[test] @@ -292,28 +367,53 @@ fn construct_fail() { "/ip4/127.0.0.1/tcp", "/ip4/127.0.0.1/p2p", "/ip4/127.0.0.1/p2p/tcp", - "/p2p-circuit/50" + "/p2p-circuit/50", ]; for address in &addresses { - assert!(address.parse::().is_err(), "{}", address.to_string()); + assert!( + address.parse::().is_err(), + "{}", + address.to_string() + ); } } #[test] fn to_multiaddr() { - assert_eq!(Multiaddr::from(Ipv4Addr::new(127, 0, 0, 1)), "/ip4/127.0.0.1".parse().unwrap()); - assert_eq!(Multiaddr::from(Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21)), - "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse().unwrap()); - assert_eq!(Multiaddr::try_from("/ip4/127.0.0.1/tcp/1234".to_string()).unwrap(), - "/ip4/127.0.0.1/tcp/1234".parse::().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::().unwrap()); - assert_eq!(Multiaddr::from(Ipv4Addr::new(127, 0, 0, 1)).with(Protocol::Tcp(1234)), - "/ip4/127.0.0.1/tcp/1234".parse::().unwrap()); - assert_eq!(Multiaddr::from(Ipv6Addr::new(0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21)) - .with(Protocol::Tcp(1234)), - "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/tcp/1234".parse::().unwrap()); + assert_eq!( + Multiaddr::from(Ipv4Addr::new(127, 0, 0, 1)), + "/ip4/127.0.0.1".parse().unwrap() + ); + assert_eq!( + Multiaddr::from(Ipv6Addr::new( + 0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21 + )), + "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21".parse().unwrap() + ); + assert_eq!( + Multiaddr::try_from("/ip4/127.0.0.1/tcp/1234".to_string()).unwrap(), + "/ip4/127.0.0.1/tcp/1234".parse::().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::() + .unwrap() + ); + assert_eq!( + Multiaddr::from(Ipv4Addr::new(127, 0, 0, 1)).with(Protocol::Tcp(1234)), + "/ip4/127.0.0.1/tcp/1234".parse::().unwrap() + ); + assert_eq!( + Multiaddr::from(Ipv6Addr::new( + 0x2601, 0x9, 0x4f81, 0x9700, 0x803e, 0xca65, 0x66e8, 0xc21 + )) + .with(Protocol::Tcp(1234)), + "/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21/tcp/1234" + .parse::() + .unwrap() + ); } #[test] @@ -322,23 +422,24 @@ fn from_bytes_fail() { assert!(Multiaddr::try_from(bytes).is_err()); } - #[test] fn ser_and_deser_json() { - let addr : Multiaddr = "/ip4/0.0.0.0/tcp/0/tls".parse::().unwrap(); + let addr: Multiaddr = "/ip4/0.0.0.0/tcp/0/tls".parse::().unwrap(); let serialized = serde_json::to_string(&addr).unwrap(); assert_eq!(serialized, "\"/ip4/0.0.0.0/tcp/0/tls\""); let deserialized: Multiaddr = serde_json::from_str(&serialized).unwrap(); assert_eq!(addr, deserialized); } - #[test] fn ser_and_deser_bincode() { - let addr : Multiaddr = "/ip4/0.0.0.0/tcp/0/tls".parse::().unwrap(); + let addr: Multiaddr = "/ip4/0.0.0.0/tcp/0/tls".parse::().unwrap(); let serialized = bincode::serialize(&addr).unwrap(); // compact addressing - assert_eq!(serialized, vec![10, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0, 192, 3]); + assert_eq!( + serialized, + vec![10, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0, 192, 3] + ); let deserialized: Multiaddr = bincode::deserialize(&serialized).unwrap(); assert_eq!(addr, deserialized); } @@ -359,7 +460,7 @@ fn append() { fn replace_ip_addr(a: &Multiaddr, p: Protocol<'_>) -> Option { a.replace(0, move |x| match x { Protocol::Ip4(_) | Protocol::Ip6(_) => Some(p), - _ => None + _ => None, }) } @@ -381,7 +482,10 @@ fn replace_ip6_with_ip4() { fn replace_ip4_with_ip6() { let server = multiaddr!(Ip4(Ipv4Addr::LOCALHOST), Tcp(10000u16)); let result = replace_ip_addr(&server, "2001:db8::1".parse::().unwrap().into()); - assert_eq!(result.unwrap(), "/ip6/2001:db8::1/tcp/10000".parse::().unwrap()) + assert_eq!( + result.unwrap(), + "/ip6/2001:db8::1/tcp/10000".parse::().unwrap() + ) } #[test] @@ -391,8 +495,8 @@ fn unknown_protocol_string() { Err(e) => match e { crate::Error::UnknownProtocolString(protocol) => { assert_eq!(protocol, "unknown") - }, - _ => assert!(false, "The UnknownProtocolString error should be caused") - } + } + _ => assert!(false, "The UnknownProtocolString error should be caused"), + }, } } From b30bfed5cdb76e09aeb5819c05d6600c31e4afe6 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 1 May 2022 13:19:21 +0200 Subject: [PATCH 2/2] feat: add noise security protocol --- src/protocol.rs | 7 +++++++ tests/lib.rs | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/protocol.rs b/src/protocol.rs index bed0abe..7c72a5b 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -38,6 +38,7 @@ const QUIC: u32 = 460; const SCTP: u32 = 132; const TCP: u32 = 6; const TLS: u32 = 448; +const NOISE: u32 = 454; const UDP: u32 = 273; const UDT: u32 = 301; const UNIX: u32 = 400; @@ -90,6 +91,7 @@ pub enum Protocol<'a> { Sctp(u16), Tcp(u16), Tls, + Noise, Udp(u16), Udt, Unix(Cow<'a, str>), @@ -119,6 +121,7 @@ impl<'a> Protocol<'a> { Ok(Protocol::Tcp(s.parse()?)) } "tls" => Ok(Protocol::Tls), + "noise" => Ok(Protocol::Noise), "udp" => { let s = iter.next().ok_or(Error::InvalidProtocolString)?; Ok(Protocol::Udp(s.parse()?)) @@ -308,6 +311,7 @@ impl<'a> Protocol<'a> { Ok((Protocol::Tcp(num), rest)) } TLS => Ok((Protocol::Tls, input)), + NOISE => Ok((Protocol::Noise, input)), UDP => { let (data, rest) = split_at(2, input)?; let mut rdr = Cursor::new(data); @@ -357,6 +361,7 @@ impl<'a> Protocol<'a> { w.write_u16::(*port)? } Protocol::Tls => w.write_all(encode::u32(TLS, &mut buf))?, + Protocol::Noise => w.write_all(encode::u32(NOISE, &mut buf))?, Protocol::Udp(port) => { w.write_all(encode::u32(UDP, &mut buf))?; w.write_u16::(*port)? @@ -471,6 +476,7 @@ impl<'a> Protocol<'a> { Sctp(a) => Sctp(a), Tcp(a) => Tcp(a), Tls => Tls, + Noise => Noise, Udp(a) => Udp(a), Udt => Udt, Unix(cow) => Unix(Cow::Owned(cow.into_owned())), @@ -512,6 +518,7 @@ impl<'a> fmt::Display for Protocol<'a> { Sctp(port) => write!(f, "/sctp/{}", port), Tcp(port) => write!(f, "/tcp/{}", port), Tls => write!(f, "/tls"), + Noise => write!(f, "/noise"), Udp(port) => write!(f, "/udp/{}", port), Udt => f.write_str("/udt"), Unix(s) => write!(f, "/unix/{}", s), diff --git a/tests/lib.rs b/tests/lib.rs index 78ee058..4a13660 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -332,6 +332,12 @@ fn construct_success() { "047F00000106007FC003DD03", vec![Ip4(local.clone()), Tcp(127), Tls, Ws("/".into())], ); + + ma_valid( + "/ip4/127.0.0.1/tcp/127/noise", + "047F00000106007FC603", + vec![Ip4(local.clone()), Tcp(127), Noise], + ); } #[test]