Skip to content

Commit

Permalink
Merge branch 'master' into add-doc-auto-cfg
Browse files Browse the repository at this point in the history
  • Loading branch information
umgefahren authored Sep 4, 2024
2 parents 9ec95ad + acb4df7 commit 30838ff
Show file tree
Hide file tree
Showing 2 changed files with 220 additions and 7 deletions.
148 changes: 142 additions & 6 deletions src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ const DNS4: u32 = 54;
const DNS6: u32 = 55;
const DNSADDR: u32 = 56;
const HTTP: u32 = 480;
const HTTPS: u32 = 443;
const HTTPS: u32 = 443; // Deprecated - alias for /tls/http
const IP4: u32 = 4;
const IP6: u32 = 41;
const P2P_WEBRTC_DIRECT: u32 = 276;
const P2P_WEBRTC_STAR: u32 = 275;
const P2P_WEBRTC_DIRECT: u32 = 276; // Deprecated
const P2P_WEBRTC_STAR: u32 = 275; // Deprecated
const WEBRTC_DIRECT: u32 = 280;
const CERTHASH: u32 = 466;
const P2P_WEBSOCKET_STAR: u32 = 479;
const P2P_WEBSOCKET_STAR: u32 = 479; // Deprecated
const MEMORY: u32 = 777;
const ONION: u32 = 444;
const ONION3: u32 = 445;
Expand All @@ -49,8 +49,16 @@ const UTP: u32 = 302;
const WEBTRANSPORT: u32 = 465;
const WS: u32 = 477;
const WS_WITH_PATH: u32 = 4770; // Note: not standard
const WSS: u32 = 478;
const WSS: u32 = 478; // Deprecated - alias for /tls/ws
const WSS_WITH_PATH: u32 = 4780; // Note: not standard
const IP6ZONE: u32 = 42;
const IPCIDR: u32 = 43;
// const IPFS: u32 = 421; // Deprecated
const GARLIC64: u32 = 446;
const GARLIC32: u32 = 447;
const SNI: u32 = 449;
const P2P_STARDUST: u32 = 277; // Deprecated
const WEBRTC: u32 = 281;

/// Type-alias for how multi-addresses use `Multihash`.
///
Expand Down Expand Up @@ -114,6 +122,13 @@ pub enum Protocol<'a> {
WebTransport,
Ws(Cow<'a, str>),
Wss(Cow<'a, str>),
Ip6zone(Cow<'a, str>),
Ipcidr(u8),
Garlic64(Cow<'a, [u8]>),
Garlic32(Cow<'a, [u8]>),
Sni(Cow<'a, str>),
P2pStardust,
WebRTC,
}

impl<'a> Protocol<'a> {
Expand Down Expand Up @@ -176,7 +191,7 @@ impl<'a> Protocol<'a> {
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
Ok(Protocol::Unix(Cow::Borrowed(s)))
}
"p2p" => {
"p2p" | "ipfs" => {
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
let decoded = multibase::Base::Base58Btc.decode(s)?;
let peer_id =
Expand Down Expand Up @@ -224,6 +239,44 @@ impl<'a> Protocol<'a> {
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
Ok(Protocol::Memory(s.parse()?))
}
"ip6zone" => {
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
Ok(Protocol::Ip6zone(Cow::Borrowed(s)))
}
"ipcidr" => {
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
Ok(Protocol::Ipcidr(s.parse()?))
}
"garlic64" => {
let s = iter
.next()
.ok_or(Error::InvalidProtocolString)?
.replace('-', "+")
.replace('~', "/");

if s.len() < 516 || s.len() > 616 {
return Err(Error::InvalidProtocolString);
}

let decoded = multibase::Base::Base64.decode(s)?;
Ok(Protocol::Garlic64(Cow::from(decoded)))
}
"garlic32" => {
let s = iter.next().ok_or(Error::InvalidProtocolString)?;

if s.len() < 55 && s.len() != 52 {
return Err(Error::InvalidProtocolString);
}

let decoded = multibase::Base::Base32Lower.decode(s)?;
Ok(Protocol::Garlic32(Cow::from(decoded)))
}
"sni" => {
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
Ok(Protocol::Sni(Cow::Borrowed(s)))
}
"p2p-stardust" => Ok(Protocol::P2pStardust),
"webrtc" => Ok(Protocol::WebRTC),
unknown => Err(Error::UnknownProtocolString(unknown.to_string())),
}
}
Expand Down Expand Up @@ -376,6 +429,35 @@ impl<'a> Protocol<'a> {
let (data, rest) = split_at(n, input)?;
Ok((Protocol::Wss(Cow::Borrowed(str::from_utf8(data)?)), rest))
}
IP6ZONE => {
let (n, input) = decode::usize(input)?;
let (data, rest) = split_at(n, input)?;
Ok((
Protocol::Ip6zone(Cow::Borrowed(str::from_utf8(data)?)),
rest,
))
}
IPCIDR => {
let (data, rest) = split_at(1, input)?;
Ok((Protocol::Ipcidr(data[0]), rest))
}
GARLIC64 => {
let (n, input) = decode::usize(input)?;
let (data, rest) = split_at(n, input)?;
Ok((Protocol::Garlic64(Cow::Borrowed(data)), rest))
}
GARLIC32 => {
let (n, input) = decode::usize(input)?;
let (data, rest) = split_at(n, input)?;
Ok((Protocol::Garlic32(Cow::Borrowed(data)), rest))
}
SNI => {
let (n, input) = decode::usize(input)?;
let (data, rest) = split_at(n, input)?;
Ok((Protocol::Sni(Cow::Borrowed(str::from_utf8(data)?)), rest))
}
P2P_STARDUST => Ok((Protocol::P2pStardust, input)),
WEBRTC => Ok((Protocol::WebRTC, input)),
_ => Err(Error::UnknownProtocolId(id)),
}
}
Expand Down Expand Up @@ -495,6 +577,34 @@ impl<'a> Protocol<'a> {
w.write_all(encode::u32(MEMORY, &mut buf))?;
w.write_u64::<BigEndian>(*port)?
}
Protocol::Ip6zone(zone_id) => {
w.write_all(encode::u32(IP6ZONE, &mut buf))?;
let bytes = zone_id.as_bytes();
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
w.write_all(bytes)?
}
Protocol::Ipcidr(mask) => {
w.write_all(encode::u32(IPCIDR, &mut buf))?;
w.write_u8(*mask)?
}
Protocol::Garlic64(addr) => {
w.write_all(encode::u32(GARLIC64, &mut buf))?;
w.write_all(encode::usize(addr.len(), &mut encode::usize_buffer()))?;
w.write_all(addr)?
}
Protocol::Garlic32(addr) => {
w.write_all(encode::u32(GARLIC32, &mut buf))?;
w.write_all(encode::usize(addr.len(), &mut encode::usize_buffer()))?;
w.write_all(addr)?
}
Protocol::Sni(s) => {
w.write_all(encode::u32(SNI, &mut buf))?;
let bytes = s.as_bytes();
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
w.write_all(bytes)?
}
Protocol::P2pStardust => w.write_all(encode::u32(P2P_STARDUST, &mut buf))?,
Protocol::WebRTC => w.write_all(encode::u32(WEBRTC, &mut buf))?,
}
Ok(())
}
Expand Down Expand Up @@ -535,6 +645,13 @@ impl<'a> Protocol<'a> {
WebTransport => WebTransport,
Ws(cow) => Ws(Cow::Owned(cow.into_owned())),
Wss(cow) => Wss(Cow::Owned(cow.into_owned())),
Ip6zone(cow) => Ip6zone(Cow::Owned(cow.into_owned())),
Ipcidr(mask) => Ipcidr(mask),
Garlic64(addr) => Garlic64(Cow::Owned(addr.into_owned())),
Garlic32(addr) => Garlic32(Cow::Owned(addr.into_owned())),
Sni(cow) => Sni(Cow::Owned(cow.into_owned())),
P2pStardust => P2pStardust,
WebRTC => WebRTC,
}
}

Expand Down Expand Up @@ -575,6 +692,13 @@ impl<'a> Protocol<'a> {
Ws(_) => "x-parity-ws",
Wss(ref s) if s == "/" => "wss",
Wss(_) => "x-parity-wss",
Ip6zone(_) => "ip6zone",
Ipcidr(_) => "ipcidr",
Garlic64(_) => "garlic64",
Garlic32(_) => "garlic32",
Sni(_) => "sni",
P2pStardust => "p2p-stardust",
WebRTC => "webrtc",
}
}
}
Expand Down Expand Up @@ -620,6 +744,18 @@ impl<'a> fmt::Display for Protocol<'a> {
percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
write!(f, "/{encoded}")
}
Ip6zone(zone) => write!(f, "/{zone}"),
Ipcidr(mask) => write!(f, "/{mask}"),
Garlic64(addr) => write!(
f,
"/{}",
multibase::Base::Base64
.encode(addr)
.replace('+', "-")
.replace('/', "~")
),
Garlic32(addr) => write!(f, "/{}", multibase::Base::Base32Lower.encode(addr)),
Sni(s) => write!(f, "/{s}"),
_ => Ok(()),
}
}
Expand Down
79 changes: 78 additions & 1 deletion tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl Arbitrary for Ma {
struct Proto(Protocol<'static>);

impl Proto {
const IMPL_VARIANT_COUNT: u8 = 32;
const IMPL_VARIANT_COUNT: u8 = 39;
}

impl Arbitrary for Proto {
Expand Down Expand Up @@ -138,6 +138,29 @@ impl Arbitrary for Proto {
29 => Proto(WebTransport),
30 => Proto(Ws("/".into())),
31 => Proto(Wss("/".into())),
32 => Proto(Ip6zone(Cow::Owned(SubString::arbitrary(g).0))),
33 => Proto(Ipcidr(Arbitrary::arbitrary(g))),
34 => {
let len = usize::arbitrary(g) % (462 - 387) + 387;
let a = iter::repeat_with(|| u8::arbitrary(g))
.take(len)
.collect::<Vec<_>>();
Proto(Garlic64(Cow::Owned(a)))
}
35 => {
let len = if bool::arbitrary(g) {
32
} else {
usize::arbitrary(g) % 128 + 35
};
let a = iter::repeat_with(|| u8::arbitrary(g))
.take(len)
.collect::<Vec<_>>();
Proto(Garlic32(Cow::Owned(a)))
}
36 => Proto(Sni(Cow::Owned(SubString::arbitrary(g).0))),
37 => Proto(P2pStardust),
38 => Proto(WebRTC),
_ => panic!("outside range"),
}
}
Expand Down Expand Up @@ -232,6 +255,14 @@ fn construct_success() {
"29260100094F819700803ECA6566E80C21",
vec![Ip6("2601:9:4f81:9700:803e:ca65:66e8:c21".parse().unwrap())],
);
ma_valid(
"/ip6/fe80::9700:803e:ca65:66e8:c21/ip6zone/wlan0",
"29FE80000000009700803ECA6566E80C212A05776C616E30",
vec![
Ip6("fe80::9700:803e:ca65:66e8:c21".parse().unwrap()),
Ip6zone(Cow::Borrowed("wlan0")),
],
);
ma_valid("/udp/0", "91020000", vec![Udp(0)]);
ma_valid("/tcp/0", "060000", vec![Tcp(0)]);
ma_valid("/sctp/0", "84010000", vec![Sctp(0)]);
Expand Down Expand Up @@ -336,6 +367,44 @@ fn construct_success() {
.into(),
)],
);
ma_valid(
"/garlic64/jT~IyXaoauTni6N4517EG8mrFUKpy0IlgZh-EY9csMAk82Odatmzr~YTZy8Hv7u~wvkg75EFNOyqb~nAPg-khyp2TS~ObUz8WlqYAM2VlEzJ7wJB91P-cUlKF\
18zSzVoJFmsrcQHZCirSbWoOknS6iNmsGRh5KVZsBEfp1Dg3gwTipTRIx7Vl5Vy~1OSKQVjYiGZS9q8RL0MF~7xFiKxZDLbPxk0AK9TzGGqm~wMTI2HS0Gm4Ycy8LYPVmLvG\
onIBYndg2bJC7WLuF6tVjVquiokSVDKFwq70BCUU5AU-EvdOD5KEOAM7mPfw-gJUG4tm1TtvcobrObqoRnmhXPTBTN5H7qDD12AvlwFGnfAlBXjuP4xOUAISL5SRLiulrsMS\
iT4GcugSI80mF6sdB0zWRgL1yyvoVWeTBn1TqjO27alr95DGTluuSqrNAxgpQzCKEWAyzrQkBfo2avGAmmz2NaHaAvYbOg0QSJz1PLjv2jdPW~ofiQmrGWM1cd~1cCqAAAA",
"BE0383038D3FC8C976A86AE4E78BA378E75EC41BC9AB1542A9CB422581987E118F5CB0C024F3639D6AD9B3AFF613672F07BFBBBFC2F920EF910534ECAA6FF9C03E\
0FA4872A764D2FCE6D4CFC5A5A9800CD95944CC9EF0241F753FE71494A175F334B35682459ACADC4076428AB49B5A83A49D2EA2366B06461E4A559B0111FA750E0D\
E0C138A94D1231ED5979572FF53922905636221994BDABC44BD0C17FEF11622B16432DB3F193400AF53CC61AA9BFC0C4C8D874B41A6E18732F0B60F5662EF1A89C8\
0589DD8366C90BB58BB85EAD56356ABA2A244950CA170ABBD01094539014F84BDD383E4A10E00CEE63DFC3E809506E2D9B54EDBDCA1BACE6EAA119E68573D305337\
91FBA830F5D80BE5C051A77C09415E3B8FE3139400848BE5244B8AE96BB0C4A24F819CBA0488F34985EAC741D3359180BD72CAFA1559E4C19F54EA8CEDBB6A5AFDE\
4319396EB92AAB340C60A50CC2284580CB3AD09017E8D9ABC60269B3D8D687680BD86CE834412273D4F2E3BF68DD3D6FE87E2426AC658CD5C77FD5C0AA000000",
vec![Garlic64(
(
&[
141, 63, 200, 201, 118, 168, 106, 228, 231, 139, 163, 120, 231, 94, 196, 27, 201, 171, 21, 66,
169, 203, 66, 37, 129, 152, 126, 17, 143, 92, 176, 192, 36, 243, 99, 157, 106, 217, 179, 175,
246, 19, 103, 47, 7, 191, 187, 191, 194, 249, 32, 239, 145, 5, 52, 236, 170, 111, 249, 192,
62, 15, 164, 135, 42, 118, 77, 47, 206, 109, 76, 252, 90, 90, 152, 0, 205, 149, 148, 76,
201, 239, 2, 65, 247, 83, 254, 113, 73, 74, 23, 95, 51, 75, 53, 104, 36, 89, 172, 173,
196, 7, 100, 40, 171, 73, 181, 168, 58, 73, 210, 234, 35, 102, 176, 100, 97, 228, 165, 89,
176, 17, 31, 167, 80, 224, 222, 12, 19, 138, 148, 209, 35, 30, 213, 151, 149, 114, 255, 83,
146, 41, 5, 99, 98, 33, 153, 75, 218, 188, 68, 189, 12, 23, 254, 241, 22, 34, 177, 100,
50, 219, 63, 25, 52, 0, 175, 83, 204, 97, 170, 155, 252, 12, 76, 141, 135, 75, 65, 166,
225, 135, 50, 240, 182, 15, 86, 98, 239, 26, 137, 200, 5, 137, 221, 131, 102, 201, 11, 181,
139, 184, 94, 173, 86, 53, 106, 186, 42, 36, 73, 80, 202, 23, 10, 187, 208, 16, 148, 83,
144, 20, 248, 75, 221, 56, 62, 74, 16, 224, 12, 238, 99, 223, 195, 232, 9, 80, 110, 45,
155, 84, 237, 189, 202, 27, 172, 230, 234, 161, 25, 230, 133, 115, 211, 5, 51, 121, 31, 186,
131, 15, 93, 128, 190, 92, 5, 26, 119, 192, 148, 21, 227, 184, 254, 49, 57, 64, 8, 72,
190, 82, 68, 184, 174, 150, 187, 12, 74, 36, 248, 25, 203, 160, 72, 143, 52, 152, 94, 172,
116, 29, 51, 89, 24, 11, 215, 44, 175, 161, 85, 158, 76, 25, 245, 78, 168, 206, 219, 182,
165, 175, 222, 67, 25, 57, 110, 185, 42, 171, 52, 12, 96, 165, 12, 194, 40, 69, 128, 203,
58, 208, 144, 23, 232, 217, 171, 198, 2, 105, 179, 216, 214, 135, 104, 11, 216, 108, 232, 52,
65, 34, 115, 212, 242, 227, 191, 104, 221, 61, 111, 232, 126, 36, 38, 172, 101, 140, 213, 199,
127, 213, 192, 170, 0, 0, 0,
]
).into()
)],
);
ma_valid(
"/dnsaddr/sjc-1.bootstrap.libp2p.io",
"3819736A632D312E626F6F7473747261702E6C69627032702E696F",
Expand Down Expand Up @@ -414,6 +483,7 @@ fn construct_fail() {
"/ip4/::1",
"/ip4/fdpsofodsajfdoisa",
"/ip6",
"/ip6/fe80::9700:803e:ca65:66e8:c21/ip6zone",
"/udp",
"/tcp",
"/sctp",
Expand All @@ -431,6 +501,12 @@ fn construct_fail() {
"/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd:-1",
"/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyyd",
"/onion3/vww6ybal4bd7szmgncyruucpgfkqahzddi37ktceo3ah7ngmcopnpyy@:666",
"/garlic64/jT~",
"/garlic32/566niximlxdzpanmn4qouucvua3k7neniwss47li5r6ugoertzu",
"/garlic32/566niximlxdzpanmn4qouucvua3k7neniwss47li5r6ugoertzu77",
"/garlic32/566niximlxdzpanmn4qouucvua3k7neniwss47li5r6ugoertzu:80",
"/garlic32/566niximlxdzpanmn4qouucvua3k7neniwss47li5r6ugoertzuq:-1",
"/garlic32/566niximlxdzpanmn4qouucvua3k7neniwss47li5r6ugoertzu@",
"/udp/1234/sctp",
"/udp/1234/udt/1234",
"/udp/1234/utp/1234",
Expand Down Expand Up @@ -582,6 +658,7 @@ fn protocol_stack() {
"/ip4/0.0.0.0",
"/ip6/::1",
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21",
"/ip6/fe80::9700:803e:ca65:66e8:c21/ip6zone/wlan0",
"/udp/0",
"/tcp/0",
"/sctp/0",
Expand Down

0 comments on commit 30838ff

Please sign in to comment.