From 6950fff7639b116b0575397f6d2ec634c5522007 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 1 May 2022 13:18:38 +0200 Subject: [PATCH 1/6] 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/6] 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] From 195d766365a10ce3cb59f88b4c37c0acdb55eb94 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 1 May 2022 13:22:19 +0200 Subject: [PATCH 3/6] chore: happy clippy --- src/protocol.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/protocol.rs b/src/protocol.rs index 7c72a5b..b736c3e 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -378,31 +378,31 @@ impl<'a> Protocol<'a> { w.write_all(encode::u32(DNS, &mut buf))?; let bytes = s.as_bytes(); w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?; - w.write_all(&bytes)? + w.write_all(bytes)? } Protocol::Dns4(s) => { w.write_all(encode::u32(DNS4, &mut buf))?; let bytes = s.as_bytes(); w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?; - w.write_all(&bytes)? + w.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)? + w.write_all(bytes)? } Protocol::Dnsaddr(s) => { w.write_all(encode::u32(DNSADDR, &mut buf))?; let bytes = s.as_bytes(); w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?; - w.write_all(&bytes)? + w.write_all(bytes)? } 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)? + w.write_all(bytes)? } Protocol::P2p(multihash) => { w.write_all(encode::u32(P2P, &mut buf))?; @@ -430,14 +430,14 @@ impl<'a> Protocol<'a> { w.write_all(encode::u32(WS_WITH_PATH, &mut buf))?; let bytes = s.as_bytes(); w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?; - w.write_all(&bytes)? + 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)? + 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))?, From fe3cc5ea929981034898c593ffd6428c2d53dc85 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 1 May 2022 13:25:27 +0200 Subject: [PATCH 4/6] ci: switch from travis to github actions --- .github/codecov.yml | 3 ++ .github/workflows/build.yml | 77 +++++++++++++++++++++++++++++++++++++ .travis.yml | 31 --------------- 3 files changed, 80 insertions(+), 31 deletions(-) create mode 100644 .github/codecov.yml create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml diff --git a/.github/codecov.yml b/.github/codecov.yml new file mode 100644 index 0000000..fa348a8 --- /dev/null +++ b/.github/codecov.yml @@ -0,0 +1,3 @@ +coverage: + status: + patch: off diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..8739d7c --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,77 @@ +name: build + +on: [push, pull_request] + +jobs: + build: + name: Build + strategy: + fail-fast: false + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] + toolchain: [stable] + runs-on: ${{ matrix.platform }} + + steps: + - name: Checkout Sources + uses: actions/checkout@v3 + + - name: Cache Dependencies & Build Outputs + uses: actions/cache@v3 + with: + path: ~/.cargo + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Install Rust Toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.toolchain }} + override: true + components: rustfmt, clippy + + - name: Check Code Format + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + - name: Code Lint + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --all-targets --all-features --workspace -- -D warnings + + - name: Code Lint Without Default Features + uses: actions-rs/cargo@v1 + with: + command: clippy + args: --no-default-features --workspace -- -D warnings + + - name: Test + uses: actions-rs/cargo@v1 + with: + command: test + args: --all-features --workspace + + coverage: + name: Code Coverage + runs-on: ubuntu-latest + steps: + - name: Checkout Sources + uses: actions/checkout@v3 + + - name: Install Rust Toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - name: Generate Code Coverage + uses: actions-rs/tarpaulin@v0.1 + with: + args: --all-features + + - name: Upload Code Coverage + uses: codecov/codecov-action@v3 diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a40d6ee..0000000 --- a/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -sudo: false -language: rust -addons: - apt: - packages: - - libcurl4-openssl-dev - - libelf-dev - - libdw-dev - - binutils-dev -rust: -# - nightly # enable when passing -- beta -- stable - -before_script: -- | - pip install 'travis-cargo<0.2' --user && - export PATH=$HOME/.local/bin:$PATH -script: -- | - travis-cargo build && - travis-cargo test && - travis-cargo bench && - travis-cargo --only stable doc -after_success: -- travis-cargo --only stable doc-upload -- travis-cargo coveralls --no-sudo --verify -env: - global: - - TRAVIS_CARGO_NIGHTLY_FEATURE=nightly - - secure: f/VDWCDpQazAB1TX4QlwGDumT7ft4uip5isALquR3TUT/WyKScnXe9JCAMp5/kJaVzSUeQgbqbBXsNmkzMpqBGj5Cu8GqUDIPf2TbqfFJ/wNzzQXrvwB2n3fA5affbSLBvLBw1R9Jonv14tPduYgnfkGDi89UbxMhXDRhpmwrFlKxHLcbz36+pYG5Qg3ftAGDrNDWprh5W0J1RgwyXGj56fUKLcHDzZoyvNEEzkSM3WV4OdWixCDESrS3SZLaYCjLNHLbCsbaa6AWUlGZMJXj5mrNDDxeCFU6Z9euUWG9ypJkiRA6eMo1zqXZrHYvPJM2ivqWqEYUXtKGHpugH2Sa34C/PvXOiuYkC2yXLO6TmSaAYWo5x6z1I2WrgMKSbhpqsrV0ZRKywCBuMooyQw85tQJRFPqSxbaJYPjsVhZ4yZEDnbsCvr8puhKtWAYOhz/0d15Pyom+yJ3roT4eSt4VyPVifEFAKC4/tLxbXkzB44PvOg0Ur+HxUUoAxi0dgrb1MTOwgkDxUl3iIdQtn6bAjM2D84ciCtYvlcTQAp7Rohgoda3FU99Hoxujj7YJ3eRLfBpLOclXTqUFBU0JFRDlec1xcD4MnwsLz9oWdw/hIhyh4PGfm6wuvfBKkJdQ4JhzIS7UcDCUdrsTx7LqMtA5M1CkN53mw+HNXfUncOOyLw= From 8bcd8ef1926ad7194e6bf086f9db0a144361148a Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 1 May 2022 13:31:52 +0200 Subject: [PATCH 5/6] chore: happy clippy in tests --- tests/lib.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/lib.rs b/tests/lib.rs index 4a13660..ebffdfc 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -243,47 +243,47 @@ fn construct_success() { ma_valid( "/ip4/127.0.0.1/udp/1234", "047F000001910204D2", - vec![Ip4(local.clone()), Udp(1234)], + vec![Ip4(local), Udp(1234)], ); ma_valid( "/ip4/127.0.0.1/udp/0", "047F00000191020000", - vec![Ip4(local.clone()), Udp(0)], + vec![Ip4(local), Udp(0)], ); ma_valid( "/ip4/127.0.0.1/tcp/1234", "047F0000010604D2", - vec![Ip4(local.clone()), Tcp(1234)], + vec![Ip4(local), Tcp(1234)], ); ma_valid( "/ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", "047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", vec![ - Ip4(local.clone()), + Ip4(local), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")), ], ); ma_valid("/ip4/127.0.0.1/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", "047F000001A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B0604D2", - vec![Ip4(local.clone()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")), Tcp(1234)]); + vec![Ip4(local), 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", "29200108A07AC542013AC986FFFE317095061F40DD03A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", - vec![Ip6(addr6.clone()), Tcp(8000), Ws("/".into()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")) + vec![Ip6(addr6), Tcp(8000), Ws("/".into()), 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("/".into()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC")) + vec![P2pWebRtcStar, Ip4(local), Tcp(9090), Ws("/".into()), 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("/".into()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]); + vec![Ip6(addr6), Tcp(8000), Wss("/".into()), P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]); ma_valid("/ip4/127.0.0.1/tcp/9090/p2p-circuit/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", "047F000001062382A202A503221220D52EBB89D85B02A284948203A62FF28389C57C9F42BEEC4EC20DB76A68911C0B", - vec![Ip4(local.clone()), Tcp(9090), P2pCircuit, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]); + vec![Ip4(local), Tcp(9090), P2pCircuit, P2p(multihash("QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"))]); ma_valid( "/onion/aaimaq4ygg2iegci:80", @@ -320,23 +320,23 @@ fn construct_success() { ma_valid( "/ip4/127.0.0.1/tcp/127/ws", "047F00000106007FDD03", - vec![Ip4(local.clone()), Tcp(127), Ws("/".into())], + vec![Ip4(local), Tcp(127), Ws("/".into())], ); ma_valid( "/ip4/127.0.0.1/tcp/127/tls", "047F00000106007FC003", - vec![Ip4(local.clone()), Tcp(127), Tls], + vec![Ip4(local), Tcp(127), Tls], ); ma_valid( "/ip4/127.0.0.1/tcp/127/tls/ws", "047F00000106007FC003DD03", - vec![Ip4(local.clone()), Tcp(127), Tls, Ws("/".into())], + vec![Ip4(local), Tcp(127), Tls, Ws("/".into())], ); ma_valid( "/ip4/127.0.0.1/tcp/127/noise", "047F00000106007FC603", - vec![Ip4(local.clone()), Tcp(127), Noise], + vec![Ip4(local), Tcp(127), Noise], ); } @@ -497,12 +497,12 @@ fn replace_ip4_with_ip6() { #[test] fn unknown_protocol_string() { match "/unknown/1.2.3.4".parse::() { - Ok(_) => assert!(false, "The UnknownProtocolString error should be caused"), + Ok(_) => panic!("The UnknownProtocolString error should be caused"), Err(e) => match e { crate::Error::UnknownProtocolString(protocol) => { assert_eq!(protocol, "unknown") } - _ => assert!(false, "The UnknownProtocolString error should be caused"), + _ => panic!("The UnknownProtocolString error should be caused"), }, } } From a9abfadaaa9f78a105e64ee76452ba574adcd9be Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sun, 1 May 2022 13:46:24 +0200 Subject: [PATCH 6/6] refactor: switch from bs58 to multibase for base58 Most projects will already use multibase in their dependency tree, so this should reduce duplication there. If multibase is not good enough for folks, we should make sure to improve it, so we can include it without worry. --- Cargo.toml | 2 +- src/errors.rs | 4 ++-- src/protocol.rs | 8 ++++++-- tests/lib.rs | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4ce2c75..160796b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,9 +14,9 @@ default = ["url"] [dependencies] arrayref = "0.3" -bs58 = "0.4.0" byteorder = "1.3.1" data-encoding = "2.1" +multibase = "0.9.1" multihash = { version = "0.16", default-features = false, features = ["std", "multihash-impl", "identity"] } percent-encoding = "2.1.0" serde = "1.0.70" diff --git a/src/errors.rs b/src/errors.rs index a867a84..4a2447d 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -55,8 +55,8 @@ impl From for Error { } } -impl From for Error { - fn from(err: bs58::decode::Error) -> Error { +impl From for Error { + fn from(err: multibase::Error) -> Error { Error::ParsingError(err.into()) } } diff --git a/src/protocol.rs b/src/protocol.rs index b736c3e..67d3cf6 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -162,7 +162,7 @@ impl<'a> Protocol<'a> { } "p2p" => { let s = iter.next().ok_or(Error::InvalidProtocolString)?; - let decoded = bs58::decode(s).into_vec()?; + let decoded = multibase::Base::Base58Btc.decode(s)?; Ok(Protocol::P2p(Multihash::from_bytes(&decoded)?)) } "http" => Ok(Protocol::Http), @@ -512,7 +512,11 @@ impl<'a> fmt::Display for Protocol<'a> { let s = BASE32.encode(addr.hash()); write!(f, "/onion3/{}:{}", s.to_lowercase(), addr.port()) } - P2p(c) => write!(f, "/p2p/{}", bs58::encode(c.to_bytes()).into_string()), + P2p(c) => write!( + f, + "/p2p/{}", + multibase::Base::Base58Btc.encode(c.to_bytes()) + ), P2pCircuit => f.write_str("/p2p-circuit"), Quic => f.write_str("/quic"), Sctp(port) => write!(f, "/sctp/{}", port), diff --git a/tests/lib.rs b/tests/lib.rs index ebffdfc..2631b65 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -161,7 +161,7 @@ fn ma_valid(source: &str, target: &str, protocols: Vec>) { } fn multihash(s: &str) -> Multihash { - Multihash::from_bytes(&bs58::decode(s).into_vec().unwrap()).unwrap() + Multihash::from_bytes(&multibase::Base::Base58Btc.decode(s).unwrap()).unwrap() } #[test]