Skip to content

Commit 827b601

Browse files
committed
Implement missing protocols
1 parent 40eb356 commit 827b601

File tree

1 file changed

+142
-6
lines changed

1 file changed

+142
-6
lines changed

src/protocol.rs

Lines changed: 142 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ const DNS4: u32 = 54;
2323
const DNS6: u32 = 55;
2424
const DNSADDR: u32 = 56;
2525
const HTTP: u32 = 480;
26-
const HTTPS: u32 = 443;
26+
const HTTPS: u32 = 443; // Deprecated - alias for /tls/http
2727
const IP4: u32 = 4;
2828
const IP6: u32 = 41;
29-
const P2P_WEBRTC_DIRECT: u32 = 276;
30-
const P2P_WEBRTC_STAR: u32 = 275;
29+
const P2P_WEBRTC_DIRECT: u32 = 276; // Deprecated
30+
const P2P_WEBRTC_STAR: u32 = 275; // Deprecated
3131
const WEBRTC_DIRECT: u32 = 280;
3232
const CERTHASH: u32 = 466;
33-
const P2P_WEBSOCKET_STAR: u32 = 479;
33+
const P2P_WEBSOCKET_STAR: u32 = 479; // Deprecated
3434
const MEMORY: u32 = 777;
3535
const ONION: u32 = 444;
3636
const ONION3: u32 = 445;
@@ -49,8 +49,16 @@ const UTP: u32 = 302;
4949
const WEBTRANSPORT: u32 = 465;
5050
const WS: u32 = 477;
5151
const WS_WITH_PATH: u32 = 4770; // Note: not standard
52-
const WSS: u32 = 478;
52+
const WSS: u32 = 478; // Deprecated - alias for /tls/ws
5353
const WSS_WITH_PATH: u32 = 4780; // Note: not standard
54+
const IP6ZONE: u32 = 42;
55+
const IPCIDR: u32 = 43;
56+
// const IPFS: u32 = 421; // Deprecated
57+
const GARLIC64: u32 = 446;
58+
const GARLIC32: u32 = 447;
59+
const SNI: u32 = 449;
60+
const P2P_STARDUST: u32 = 277; // Deprecated
61+
const WEBRTC: u32 = 281;
5462

5563
/// Type-alias for how multi-addresses use `Multihash`.
5664
///
@@ -114,6 +122,13 @@ pub enum Protocol<'a> {
114122
WebTransport,
115123
Ws(Cow<'a, str>),
116124
Wss(Cow<'a, str>),
125+
Ip6zone(Cow<'a, str>),
126+
Ipcidr(u8),
127+
Garlic64(Cow<'a, [u8]>),
128+
Garlic32(Cow<'a, [u8]>),
129+
Sni(Cow<'a, str>),
130+
P2pStardust,
131+
WebRTC,
117132
}
118133

119134
impl<'a> Protocol<'a> {
@@ -176,7 +191,7 @@ impl<'a> Protocol<'a> {
176191
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
177192
Ok(Protocol::Unix(Cow::Borrowed(s)))
178193
}
179-
"p2p" => {
194+
"p2p" | "ipfs" => {
180195
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
181196
let decoded = multibase::Base::Base58Btc.decode(s)?;
182197
let peer_id =
@@ -224,6 +239,44 @@ impl<'a> Protocol<'a> {
224239
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
225240
Ok(Protocol::Memory(s.parse()?))
226241
}
242+
"ip6zone" => {
243+
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
244+
Ok(Protocol::Ip6zone(Cow::Borrowed(s)))
245+
}
246+
"ipcidr" => {
247+
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
248+
Ok(Protocol::Ipcidr(s.parse()?))
249+
}
250+
"garlic64" => {
251+
let s = iter
252+
.next()
253+
.ok_or(Error::InvalidProtocolString)?
254+
.replace('-', "+")
255+
.replace('~', "/");
256+
257+
if s.len() < 516 || s.len() > 616 {
258+
return Err(Error::InvalidProtocolString);
259+
}
260+
261+
let decoded = multibase::Base::Base64.decode(s)?;
262+
Ok(Protocol::Garlic64(Cow::from(decoded)))
263+
}
264+
"garlic32" => {
265+
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
266+
267+
if s.len() < 55 && s.len() != 52 {
268+
return Err(Error::InvalidProtocolString);
269+
}
270+
271+
let decoded = multibase::Base::Base32Lower.decode(s)?;
272+
Ok(Protocol::Garlic32(Cow::from(decoded)))
273+
}
274+
"sni" => {
275+
let s = iter.next().ok_or(Error::InvalidProtocolString)?;
276+
Ok(Protocol::Sni(Cow::Borrowed(s)))
277+
}
278+
"p2p-stardust" => Ok(Protocol::P2pStardust),
279+
"webrtc" => Ok(Protocol::WebRTC),
227280
unknown => Err(Error::UnknownProtocolString(unknown.to_string())),
228281
}
229282
}
@@ -376,6 +429,35 @@ impl<'a> Protocol<'a> {
376429
let (data, rest) = split_at(n, input)?;
377430
Ok((Protocol::Wss(Cow::Borrowed(str::from_utf8(data)?)), rest))
378431
}
432+
IP6ZONE => {
433+
let (n, input) = decode::usize(input)?;
434+
let (data, rest) = split_at(n, input)?;
435+
Ok((
436+
Protocol::Ip6zone(Cow::Borrowed(str::from_utf8(data)?)),
437+
rest,
438+
))
439+
}
440+
IPCIDR => {
441+
let (data, rest) = split_at(1, input)?;
442+
Ok((Protocol::Ipcidr(data[0]), rest))
443+
}
444+
GARLIC64 => {
445+
let (n, input) = decode::usize(input)?;
446+
let (data, rest) = split_at(n, input)?;
447+
Ok((Protocol::Garlic64(Cow::Borrowed(data)), rest))
448+
}
449+
GARLIC32 => {
450+
let (n, input) = decode::usize(input)?;
451+
let (data, rest) = split_at(n, input)?;
452+
Ok((Protocol::Garlic32(Cow::Borrowed(data)), rest))
453+
}
454+
SNI => {
455+
let (n, input) = decode::usize(input)?;
456+
let (data, rest) = split_at(n, input)?;
457+
Ok((Protocol::Sni(Cow::Borrowed(str::from_utf8(data)?)), rest))
458+
}
459+
P2P_STARDUST => Ok((Protocol::P2pStardust, input)),
460+
WEBRTC => Ok((Protocol::WebRTC, input)),
379461
_ => Err(Error::UnknownProtocolId(id)),
380462
}
381463
}
@@ -495,6 +577,34 @@ impl<'a> Protocol<'a> {
495577
w.write_all(encode::u32(MEMORY, &mut buf))?;
496578
w.write_u64::<BigEndian>(*port)?
497579
}
580+
Protocol::Ip6zone(zone_id) => {
581+
w.write_all(encode::u32(IP6ZONE, &mut buf))?;
582+
let bytes = zone_id.as_bytes();
583+
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
584+
w.write_all(bytes)?
585+
}
586+
Protocol::Ipcidr(mask) => {
587+
w.write_all(encode::u32(IPCIDR, &mut buf))?;
588+
w.write_u8(*mask)?
589+
}
590+
Protocol::Garlic64(addr) => {
591+
w.write_all(encode::u32(GARLIC64, &mut buf))?;
592+
w.write_all(encode::usize(addr.len(), &mut encode::usize_buffer()))?;
593+
w.write_all(addr)?
594+
}
595+
Protocol::Garlic32(addr) => {
596+
w.write_all(encode::u32(GARLIC32, &mut buf))?;
597+
w.write_all(encode::usize(addr.len(), &mut encode::usize_buffer()))?;
598+
w.write_all(addr)?
599+
}
600+
Protocol::Sni(s) => {
601+
w.write_all(encode::u32(SNI, &mut buf))?;
602+
let bytes = s.as_bytes();
603+
w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
604+
w.write_all(bytes)?
605+
}
606+
Protocol::P2pStardust => w.write_all(encode::u32(P2P_STARDUST, &mut buf))?,
607+
Protocol::WebRTC => w.write_all(encode::u32(WEBRTC, &mut buf))?,
498608
}
499609
Ok(())
500610
}
@@ -535,6 +645,13 @@ impl<'a> Protocol<'a> {
535645
WebTransport => WebTransport,
536646
Ws(cow) => Ws(Cow::Owned(cow.into_owned())),
537647
Wss(cow) => Wss(Cow::Owned(cow.into_owned())),
648+
Ip6zone(cow) => Ip6zone(Cow::Owned(cow.into_owned())),
649+
Ipcidr(mask) => Ipcidr(mask),
650+
Garlic64(addr) => Garlic64(Cow::Owned(addr.into_owned())),
651+
Garlic32(addr) => Garlic32(Cow::Owned(addr.into_owned())),
652+
Sni(cow) => Sni(Cow::Owned(cow.into_owned())),
653+
P2pStardust => P2pStardust,
654+
WebRTC => WebRTC,
538655
}
539656
}
540657

@@ -575,6 +692,13 @@ impl<'a> Protocol<'a> {
575692
Ws(_) => "x-parity-ws",
576693
Wss(ref s) if s == "/" => "wss",
577694
Wss(_) => "x-parity-wss",
695+
Ip6zone(_) => "ip6zone",
696+
Ipcidr(_) => "ipcidr",
697+
Garlic64(_) => "garlic64",
698+
Garlic32(_) => "garlic32",
699+
Sni(_) => "sni",
700+
P2pStardust => "p2p-stardust",
701+
WebRTC => "webrtc",
578702
}
579703
}
580704
}
@@ -620,6 +744,18 @@ impl<'a> fmt::Display for Protocol<'a> {
620744
percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
621745
write!(f, "/{encoded}")
622746
}
747+
Ip6zone(zone) => write!(f, "/{zone}"),
748+
Ipcidr(mask) => write!(f, "/{mask}"),
749+
Garlic64(addr) => write!(
750+
f,
751+
"/{}",
752+
multibase::Base::Base64
753+
.encode(addr)
754+
.replace('+', "-")
755+
.replace('/', "~")
756+
),
757+
Garlic32(addr) => write!(f, "/{}", multibase::Base::Base32Lower.encode(addr)),
758+
Sni(s) => write!(f, "/{s}"),
623759
_ => Ok(()),
624760
}
625761
}

0 commit comments

Comments
 (0)