libp2prs_multiaddr/
protocol.rs

1use crate::onion_addr::Onion3Addr;
2use crate::{Error, Result};
3use arrayref::array_ref;
4use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt};
5use data_encoding::BASE32;
6use multihash::Multihash;
7pub use multihash::{Code, Sha2_256};
8use std::{
9    borrow::Cow,
10    convert::From,
11    fmt,
12    io::{Cursor, Write},
13    net::{IpAddr, Ipv4Addr, Ipv6Addr},
14    str::{self, FromStr},
15};
16use unsigned_varint::{decode, encode};
17
18pub const DCCP: u32 = 33;
19pub const DNS: u32 = 53;
20pub const DNS4: u32 = 54;
21pub const DNS6: u32 = 55;
22pub const DNSADDR: u32 = 56;
23pub const HTTP: u32 = 480;
24pub const HTTPS: u32 = 443;
25pub const IP4: u32 = 4;
26pub const IP6: u32 = 41;
27pub const P2P_WEBRTC_DIRECT: u32 = 276;
28pub const P2P_WEBRTC_STAR: u32 = 275;
29pub const P2P_WEBSOCKET_STAR: u32 = 479;
30pub const MEMORY: u32 = 777;
31pub const ONION: u32 = 444;
32pub const ONION3: u32 = 445;
33pub const P2P: u32 = 421;
34pub const P2P_CIRCUIT: u32 = 290;
35pub const QUIC: u32 = 460;
36pub const SCTP: u32 = 132;
37pub const TCP: u32 = 6;
38pub const UDP: u32 = 273;
39pub const UDT: u32 = 301;
40pub const UNIX: u32 = 400;
41pub const UTP: u32 = 302;
42pub const WS: u32 = 477;
43pub const WS_WITH_PATH: u32 = 4770; // Note: not standard
44pub const WSS: u32 = 478;
45pub const WSS_WITH_PATH: u32 = 4780; // Note: not standard
46
47const PATH_SEGMENT_ENCODE_SET: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
48    .add(b'%')
49    .add(b'/')
50    .add(b'`')
51    .add(b'?')
52    .add(b'{')
53    .add(b'}')
54    .add(b' ')
55    .add(b'"')
56    .add(b'#')
57    .add(b'<')
58    .add(b'>');
59
60/// `Protocol` describes all possible multiaddress protocols.
61///
62/// For `Unix`, `Ws` and `Wss` we use `&str` instead of `Path` to allow
63/// cross-platform usage of `Protocol` since encoding `Paths` to bytes is
64/// platform-specific. This means that the actual validation of paths needs to
65/// happen separately.
66#[derive(PartialEq, Eq, Clone, Debug)]
67pub enum Protocol<'a> {
68    Dccp(u16),
69    Dns(Cow<'a, str>),
70    Dns4(Cow<'a, str>),
71    Dns6(Cow<'a, str>),
72    Dnsaddr(Cow<'a, str>),
73    Http,
74    Https,
75    Ip4(Ipv4Addr),
76    Ip6(Ipv6Addr),
77    P2pWebRtcDirect,
78    P2pWebRtcStar,
79    P2pWebSocketStar,
80    /// Contains the "port" to contact. Similar to TCP or UDP, 0 means "assign me a port".
81    Memory(u64),
82    Onion(Cow<'a, [u8; 10]>, u16),
83    Onion3(Onion3Addr<'a>),
84    P2p(Multihash),
85    P2pCircuit,
86    Quic,
87    Sctp(u16),
88    Tcp(u16),
89    Udp(u16),
90    Udt,
91    Unix(Cow<'a, str>),
92    Utp,
93    Ws(Cow<'a, str>),
94    Wss(Cow<'a, str>),
95}
96
97impl<'a> Protocol<'a> {
98    /// Parse a protocol value from the given iterator of string slices.
99    ///
100    /// The parsing only consumes the minimum amount of string slices necessary to
101    /// produce a well-formed protocol. The same iterator can thus be used to parse
102    /// a sequence of protocols in succession. It is up to client code to check
103    /// that iteration has finished whenever appropriate.
104    pub fn from_str_parts<I>(mut iter: I) -> Result<Self>
105    where
106        I: Iterator<Item = &'a str>,
107    {
108        match iter.next().ok_or(Error::InvalidProtocolString)? {
109            "ip4" => {
110                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
111                Ok(Protocol::Ip4(Ipv4Addr::from_str(s)?))
112            }
113            "tcp" => {
114                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
115                Ok(Protocol::Tcp(s.parse()?))
116            }
117            "udp" => {
118                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
119                Ok(Protocol::Udp(s.parse()?))
120            }
121            "dccp" => {
122                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
123                Ok(Protocol::Dccp(s.parse()?))
124            }
125            "ip6" => {
126                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
127                Ok(Protocol::Ip6(Ipv6Addr::from_str(s)?))
128            }
129            "dns" => {
130                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
131                Ok(Protocol::Dns(Cow::Borrowed(s)))
132            }
133            "dns4" => {
134                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
135                Ok(Protocol::Dns4(Cow::Borrowed(s)))
136            }
137            "dns6" => {
138                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
139                Ok(Protocol::Dns6(Cow::Borrowed(s)))
140            }
141            "dnsaddr" => {
142                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
143                Ok(Protocol::Dnsaddr(Cow::Borrowed(s)))
144            }
145            "sctp" => {
146                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
147                Ok(Protocol::Sctp(s.parse()?))
148            }
149            "udt" => Ok(Protocol::Udt),
150            "utp" => Ok(Protocol::Utp),
151            "unix" => {
152                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
153                Ok(Protocol::Unix(Cow::Borrowed(s)))
154            }
155            "p2p" => {
156                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
157                let decoded = bs58::decode(s).into_vec()?;
158                Ok(Protocol::P2p(Multihash::from_bytes(&decoded)?))
159            }
160            "http" => Ok(Protocol::Http),
161            "https" => Ok(Protocol::Https),
162            "onion" => iter
163                .next()
164                .ok_or(Error::InvalidProtocolString)
165                .and_then(|s| read_onion(&s.to_uppercase()))
166                .map(|(a, p)| Protocol::Onion(Cow::Owned(a), p)),
167            "onion3" => iter
168                .next()
169                .ok_or(Error::InvalidProtocolString)
170                .and_then(|s| read_onion3(&s.to_uppercase()))
171                .map(|(a, p)| Protocol::Onion3((a, p).into())),
172            "quic" => Ok(Protocol::Quic),
173            "ws" => Ok(Protocol::Ws(Cow::Borrowed("/"))),
174            "wss" => Ok(Protocol::Wss(Cow::Borrowed("/"))),
175            "x-parity-ws" => {
176                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
177                let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
178                Ok(Protocol::Ws(decoded))
179            }
180            "x-parity-wss" => {
181                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
182                let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
183                Ok(Protocol::Wss(decoded))
184            }
185            "p2p-websocket-star" => Ok(Protocol::P2pWebSocketStar),
186            "p2p-webrtc-star" => Ok(Protocol::P2pWebRtcStar),
187            "p2p-webrtc-direct" => Ok(Protocol::P2pWebRtcDirect),
188            "p2p-circuit" => Ok(Protocol::P2pCircuit),
189            "memory" => {
190                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
191                Ok(Protocol::Memory(s.parse()?))
192            }
193            unknown => Err(Error::UnknownProtocolString(unknown.to_string())),
194        }
195    }
196
197    pub fn get_enum(id: u32) -> Result<Self> {
198        match id {
199            IP4 => Ok(Protocol::Ip4(Ipv4Addr::new(127, 0, 0, 1))),
200            IP6 => Ok(Protocol::Ip6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff))),
201            MEMORY => Ok(Protocol::Memory(0)),
202            ONION => Ok(Protocol::Onion(Cow::Owned([0_u8; 10]), 0)),
203            ONION3 => Ok(Protocol::Onion3(Onion3Addr::from(([0_u8; 35], 0)))),
204            TCP => Ok(Protocol::Tcp(0)),
205            UDP => Ok(Protocol::Udp(0)),
206            SCTP => Ok(Protocol::Sctp(0)),
207            UDT => Ok(Protocol::Udt),
208            UTP => Ok(Protocol::Utp),
209            UNIX => Ok(Protocol::Unix(Cow::Borrowed(""))),
210            QUIC => Ok(Protocol::Quic),
211            DCCP => Ok(Protocol::Dccp(0)),
212            DNS => Ok(Protocol::Dns(Cow::Borrowed(""))),
213            DNS4 => Ok(Protocol::Dns4(Cow::Borrowed(""))),
214            DNS6 => Ok(Protocol::Dns6(Cow::Borrowed(""))),
215            DNSADDR => Ok(Protocol::Dnsaddr(Cow::Borrowed(""))),
216            WS => Ok(Protocol::Ws(Cow::Borrowed("/"))),
217            WSS => Ok(Protocol::Wss(Cow::Borrowed("/"))),
218            HTTP => Ok(Protocol::Http),
219            HTTPS => Ok(Protocol::Https),
220            //P2P => Ok(Protocol::P2p(multihash::wrap(Code::Sha2_256, &Sha2_256::digest(b"0").digest()))),
221            P2P_CIRCUIT => Ok(Protocol::P2pCircuit),
222            P2P_WEBRTC_DIRECT => Ok(Protocol::P2pWebRtcDirect),
223            P2P_WEBRTC_STAR => Ok(Protocol::P2pWebRtcStar),
224            P2P_WEBSOCKET_STAR => Ok(Protocol::P2pWebSocketStar),
225            _ => Err(Error::UnknownProtocolId(id)),
226        }
227    }
228
229    pub fn get_key(&self) -> Result<u32> {
230        match self {
231            Protocol::Ip4(_) => Ok(IP4),
232            Protocol::Ip6(_) => Ok(IP6),
233            Protocol::Memory(_) => Ok(MEMORY),
234            Protocol::Onion(_, _) => Ok(ONION),
235            Protocol::Onion3(_) => Ok(ONION3),
236            Protocol::Tcp(_) => Ok(TCP),
237            Protocol::Udp(_) => Ok(UDP),
238            Protocol::Sctp(_) => Ok(SCTP),
239            Protocol::Udt => Ok(UDT),
240            Protocol::Utp => Ok(UTP),
241            Protocol::Unix(_) => Ok(UNIX),
242            Protocol::Quic => Ok(QUIC),
243            Protocol::Dccp(_) => Ok(DCCP),
244            Protocol::Dns(_) => Ok(DNS),
245            Protocol::Dns4(_) => Ok(DNS4),
246            Protocol::Dns6(_) => Ok(DNS6),
247            Protocol::Dnsaddr(_) => Ok(DNSADDR),
248            Protocol::Ws(_) => Ok(WS),
249            Protocol::Wss(_) => Ok(WSS),
250            Protocol::Http => Ok(HTTP),
251            Protocol::Https => Ok(HTTPS),
252            Protocol::P2pCircuit => Ok(P2P_CIRCUIT),
253            Protocol::P2pWebRtcDirect => Ok(P2P_WEBRTC_DIRECT),
254            Protocol::P2pWebRtcStar => Ok(P2P_WEBRTC_STAR),
255            Protocol::P2pWebSocketStar => Ok(P2P_WEBSOCKET_STAR),
256            _ => Err(Error::InvalidProtocolString),
257        }
258    }
259    /// Parse a single `Protocol` value from its byte slice representation,
260    /// returning the protocol as well as the remaining byte slice.
261    pub fn from_bytes(input: &'a [u8]) -> Result<(Self, &'a [u8])> {
262        fn split_at(n: usize, input: &[u8]) -> Result<(&[u8], &[u8])> {
263            if input.len() < n {
264                return Err(Error::DataLessThanLen);
265            }
266            Ok(input.split_at(n))
267        }
268        let (id, input) = decode::u32(input)?;
269        match id {
270            DCCP => {
271                let (data, rest) = split_at(2, input)?;
272                let mut rdr = Cursor::new(data);
273                let num = rdr.read_u16::<BigEndian>()?;
274                Ok((Protocol::Dccp(num), rest))
275            }
276            DNS => {
277                let (n, input) = decode::usize(input)?;
278                let (data, rest) = split_at(n, input)?;
279                Ok((Protocol::Dns(Cow::Borrowed(str::from_utf8(data)?)), rest))
280            }
281            DNS4 => {
282                let (n, input) = decode::usize(input)?;
283                let (data, rest) = split_at(n, input)?;
284                Ok((Protocol::Dns4(Cow::Borrowed(str::from_utf8(data)?)), rest))
285            }
286            DNS6 => {
287                let (n, input) = decode::usize(input)?;
288                let (data, rest) = split_at(n, input)?;
289                Ok((Protocol::Dns6(Cow::Borrowed(str::from_utf8(data)?)), rest))
290            }
291            DNSADDR => {
292                let (n, input) = decode::usize(input)?;
293                let (data, rest) = split_at(n, input)?;
294                Ok((Protocol::Dnsaddr(Cow::Borrowed(str::from_utf8(data)?)), rest))
295            }
296            HTTP => Ok((Protocol::Http, input)),
297            HTTPS => Ok((Protocol::Https, input)),
298            IP4 => {
299                let (data, rest) = split_at(4, input)?;
300                Ok((Protocol::Ip4(Ipv4Addr::new(data[0], data[1], data[2], data[3])), rest))
301            }
302            IP6 => {
303                let (data, rest) = split_at(16, input)?;
304                let mut rdr = Cursor::new(data);
305                let mut seg = [0_u16; 8];
306
307                for x in seg.iter_mut() {
308                    *x = rdr.read_u16::<BigEndian>()?;
309                }
310
311                let addr = Ipv6Addr::new(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7]);
312
313                Ok((Protocol::Ip6(addr), rest))
314            }
315            P2P_WEBRTC_DIRECT => Ok((Protocol::P2pWebRtcDirect, input)),
316            P2P_WEBRTC_STAR => Ok((Protocol::P2pWebRtcStar, input)),
317            P2P_WEBSOCKET_STAR => Ok((Protocol::P2pWebSocketStar, input)),
318            MEMORY => {
319                let (data, rest) = split_at(8, input)?;
320                let mut rdr = Cursor::new(data);
321                let num = rdr.read_u64::<BigEndian>()?;
322                Ok((Protocol::Memory(num), rest))
323            }
324            ONION => {
325                let (data, rest) = split_at(12, input)?;
326                let port = BigEndian::read_u16(&data[10..]);
327                Ok((Protocol::Onion(Cow::Borrowed(array_ref!(data, 0, 10)), port), rest))
328            }
329            ONION3 => {
330                let (data, rest) = split_at(37, input)?;
331                let port = BigEndian::read_u16(&data[35..]);
332                Ok((Protocol::Onion3((array_ref!(data, 0, 35), port).into()), rest))
333            }
334            P2P => {
335                let (n, input) = decode::usize(input)?;
336                let (data, rest) = split_at(n, input)?;
337                Ok((Protocol::P2p(Multihash::from_bytes(data)?), rest))
338            }
339            P2P_CIRCUIT => Ok((Protocol::P2pCircuit, input)),
340            QUIC => Ok((Protocol::Quic, input)),
341            SCTP => {
342                let (data, rest) = split_at(2, input)?;
343                let mut rdr = Cursor::new(data);
344                let num = rdr.read_u16::<BigEndian>()?;
345                Ok((Protocol::Sctp(num), rest))
346            }
347            TCP => {
348                let (data, rest) = split_at(2, input)?;
349                let mut rdr = Cursor::new(data);
350                let num = rdr.read_u16::<BigEndian>()?;
351                Ok((Protocol::Tcp(num), rest))
352            }
353            UDP => {
354                let (data, rest) = split_at(2, input)?;
355                let mut rdr = Cursor::new(data);
356                let num = rdr.read_u16::<BigEndian>()?;
357                Ok((Protocol::Udp(num), rest))
358            }
359            UDT => Ok((Protocol::Udt, input)),
360            UNIX => {
361                let (n, input) = decode::usize(input)?;
362                let (data, rest) = split_at(n, input)?;
363                Ok((Protocol::Unix(Cow::Borrowed(str::from_utf8(data)?)), rest))
364            }
365            UTP => Ok((Protocol::Utp, input)),
366            WS => Ok((Protocol::Ws(Cow::Borrowed("/")), input)),
367            WS_WITH_PATH => {
368                let (n, input) = decode::usize(input)?;
369                let (data, rest) = split_at(n, input)?;
370                Ok((Protocol::Ws(Cow::Borrowed(str::from_utf8(data)?)), rest))
371            }
372            WSS => Ok((Protocol::Wss(Cow::Borrowed("/")), input)),
373            WSS_WITH_PATH => {
374                let (n, input) = decode::usize(input)?;
375                let (data, rest) = split_at(n, input)?;
376                Ok((Protocol::Wss(Cow::Borrowed(str::from_utf8(data)?)), rest))
377            }
378            _ => Err(Error::UnknownProtocolId(id)),
379        }
380    }
381
382    /// Encode this protocol by writing its binary representation into
383    /// the given `Write` impl.
384    pub fn write_bytes<W: Write>(&self, w: &mut W) -> Result<()> {
385        let mut buf = encode::u32_buffer();
386        match self {
387            Protocol::Ip4(addr) => {
388                w.write_all(encode::u32(IP4, &mut buf))?;
389                w.write_all(&addr.octets())?
390            }
391            Protocol::Ip6(addr) => {
392                w.write_all(encode::u32(IP6, &mut buf))?;
393                for &segment in &addr.segments() {
394                    w.write_u16::<BigEndian>(segment)?
395                }
396            }
397            Protocol::Tcp(port) => {
398                w.write_all(encode::u32(TCP, &mut buf))?;
399                w.write_u16::<BigEndian>(*port)?
400            }
401            Protocol::Udp(port) => {
402                w.write_all(encode::u32(UDP, &mut buf))?;
403                w.write_u16::<BigEndian>(*port)?
404            }
405            Protocol::Dccp(port) => {
406                w.write_all(encode::u32(DCCP, &mut buf))?;
407                w.write_u16::<BigEndian>(*port)?
408            }
409            Protocol::Sctp(port) => {
410                w.write_all(encode::u32(SCTP, &mut buf))?;
411                w.write_u16::<BigEndian>(*port)?
412            }
413            Protocol::Dns(s) => {
414                w.write_all(encode::u32(DNS, &mut buf))?;
415                let bytes = s.as_bytes();
416                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
417                w.write_all(&bytes)?
418            }
419            Protocol::Dns4(s) => {
420                w.write_all(encode::u32(DNS4, &mut buf))?;
421                let bytes = s.as_bytes();
422                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
423                w.write_all(&bytes)?
424            }
425            Protocol::Dns6(s) => {
426                w.write_all(encode::u32(DNS6, &mut buf))?;
427                let bytes = s.as_bytes();
428                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
429                w.write_all(&bytes)?
430            }
431            Protocol::Dnsaddr(s) => {
432                w.write_all(encode::u32(DNSADDR, &mut buf))?;
433                let bytes = s.as_bytes();
434                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
435                w.write_all(&bytes)?
436            }
437            Protocol::Unix(s) => {
438                w.write_all(encode::u32(UNIX, &mut buf))?;
439                let bytes = s.as_bytes();
440                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
441                w.write_all(&bytes)?
442            }
443            Protocol::P2p(multihash) => {
444                w.write_all(encode::u32(P2P, &mut buf))?;
445                let bytes = multihash.to_bytes();
446                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
447                w.write_all(&bytes)?
448            }
449            Protocol::Onion(addr, port) => {
450                w.write_all(encode::u32(ONION, &mut buf))?;
451                w.write_all(addr.as_ref())?;
452                w.write_u16::<BigEndian>(*port)?
453            }
454            Protocol::Onion3(addr) => {
455                w.write_all(encode::u32(ONION3, &mut buf))?;
456                w.write_all(addr.hash().as_ref())?;
457                w.write_u16::<BigEndian>(addr.port())?
458            }
459            Protocol::Quic => w.write_all(encode::u32(QUIC, &mut buf))?,
460            Protocol::Utp => w.write_all(encode::u32(UTP, &mut buf))?,
461            Protocol::Udt => w.write_all(encode::u32(UDT, &mut buf))?,
462            Protocol::Http => w.write_all(encode::u32(HTTP, &mut buf))?,
463            Protocol::Https => w.write_all(encode::u32(HTTPS, &mut buf))?,
464            Protocol::Ws(ref s) if s == "/" => w.write_all(encode::u32(WS, &mut buf))?,
465            Protocol::Ws(s) => {
466                w.write_all(encode::u32(WS_WITH_PATH, &mut buf))?;
467                let bytes = s.as_bytes();
468                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
469                w.write_all(&bytes)?
470            }
471            Protocol::Wss(ref s) if s == "/" => w.write_all(encode::u32(WSS, &mut buf))?,
472            Protocol::Wss(s) => {
473                w.write_all(encode::u32(WSS_WITH_PATH, &mut buf))?;
474                let bytes = s.as_bytes();
475                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
476                w.write_all(&bytes)?
477            }
478            Protocol::P2pWebSocketStar => w.write_all(encode::u32(P2P_WEBSOCKET_STAR, &mut buf))?,
479            Protocol::P2pWebRtcStar => w.write_all(encode::u32(P2P_WEBRTC_STAR, &mut buf))?,
480            Protocol::P2pWebRtcDirect => w.write_all(encode::u32(P2P_WEBRTC_DIRECT, &mut buf))?,
481            Protocol::P2pCircuit => w.write_all(encode::u32(P2P_CIRCUIT, &mut buf))?,
482            Protocol::Memory(port) => {
483                w.write_all(encode::u32(MEMORY, &mut buf))?;
484                w.write_u64::<BigEndian>(*port)?
485            }
486        }
487        Ok(())
488    }
489
490    /// Turn this `Protocol` into one that owns its data, thus being valid for any lifetime.
491    pub fn acquire<'b>(self) -> Protocol<'b> {
492        use self::Protocol::*;
493        match self {
494            Dccp(a) => Dccp(a),
495            Dns(cow) => Dns(Cow::Owned(cow.into_owned())),
496            Dns4(cow) => Dns4(Cow::Owned(cow.into_owned())),
497            Dns6(cow) => Dns6(Cow::Owned(cow.into_owned())),
498            Dnsaddr(cow) => Dnsaddr(Cow::Owned(cow.into_owned())),
499            Http => Http,
500            Https => Https,
501            Ip4(a) => Ip4(a),
502            Ip6(a) => Ip6(a),
503            P2pWebRtcDirect => P2pWebRtcDirect,
504            P2pWebRtcStar => P2pWebRtcStar,
505            P2pWebSocketStar => P2pWebSocketStar,
506            Memory(a) => Memory(a),
507            Onion(addr, port) => Onion(Cow::Owned(addr.into_owned()), port),
508            Onion3(addr) => Onion3(addr.acquire()),
509            P2p(a) => P2p(a),
510            P2pCircuit => P2pCircuit,
511            Quic => Quic,
512            Sctp(a) => Sctp(a),
513            Tcp(a) => Tcp(a),
514            Udp(a) => Udp(a),
515            Udt => Udt,
516            Unix(cow) => Unix(Cow::Owned(cow.into_owned())),
517            Utp => Utp,
518            Ws(cow) => Ws(Cow::Owned(cow.into_owned())),
519            Wss(cow) => Wss(Cow::Owned(cow.into_owned())),
520        }
521    }
522}
523
524impl<'a> fmt::Display for Protocol<'a> {
525    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526        use self::Protocol::*;
527        match self {
528            Dccp(port) => write!(f, "/dccp/{}", port),
529            Dns(s) => write!(f, "/dns/{}", s),
530            Dns4(s) => write!(f, "/dns4/{}", s),
531            Dns6(s) => write!(f, "/dns6/{}", s),
532            Dnsaddr(s) => write!(f, "/dnsaddr/{}", s),
533            Http => f.write_str("/http"),
534            Https => f.write_str("/https"),
535            Ip4(addr) => write!(f, "/ip4/{}", addr),
536            Ip6(addr) => write!(f, "/ip6/{}", addr),
537            P2pWebRtcDirect => f.write_str("/p2p-webrtc-direct"),
538            P2pWebRtcStar => f.write_str("/p2p-webrtc-star"),
539            P2pWebSocketStar => f.write_str("/p2p-websocket-star"),
540            Memory(port) => write!(f, "/memory/{}", port),
541            Onion(addr, port) => {
542                let s = BASE32.encode(addr.as_ref());
543                write!(f, "/onion/{}:{}", s.to_lowercase(), port)
544            }
545            Onion3(addr) => {
546                let s = BASE32.encode(addr.hash());
547                write!(f, "/onion3/{}:{}", s.to_lowercase(), addr.port())
548            }
549            P2p(c) => write!(f, "/p2p/{}", bs58::encode(c.to_bytes()).into_string()),
550            P2pCircuit => f.write_str("/p2p-circuit"),
551            Quic => f.write_str("/quic"),
552            Sctp(port) => write!(f, "/sctp/{}", port),
553            Tcp(port) => write!(f, "/tcp/{}", port),
554            Udp(port) => write!(f, "/udp/{}", port),
555            Udt => f.write_str("/udt"),
556            Unix(s) => write!(f, "/unix/{}", s),
557            Utp => f.write_str("/utp"),
558            Ws(ref s) if s == "/" => f.write_str("/ws"),
559            Ws(s) => {
560                let encoded = percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
561                write!(f, "/x-parity-ws/{}", encoded)
562            }
563            Wss(ref s) if s == "/" => f.write_str("/wss"),
564            Wss(s) => {
565                let encoded = percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
566                write!(f, "/x-parity-wss/{}", encoded)
567            }
568        }
569    }
570}
571
572impl<'a> From<IpAddr> for Protocol<'a> {
573    #[inline]
574    fn from(addr: IpAddr) -> Self {
575        match addr {
576            IpAddr::V4(addr) => Protocol::Ip4(addr),
577            IpAddr::V6(addr) => Protocol::Ip6(addr),
578        }
579    }
580}
581
582impl<'a> From<Ipv4Addr> for Protocol<'a> {
583    #[inline]
584    fn from(addr: Ipv4Addr) -> Self {
585        Protocol::Ip4(addr)
586    }
587}
588
589impl<'a> From<Ipv6Addr> for Protocol<'a> {
590    #[inline]
591    fn from(addr: Ipv6Addr) -> Self {
592        Protocol::Ip6(addr)
593    }
594}
595
596macro_rules! read_onion_impl {
597    ($name:ident, $len:expr, $encoded_len:expr) => {
598        fn $name(s: &str) -> Result<([u8; $len], u16)> {
599            let mut parts = s.split(':');
600
601            // address part (without ".onion")
602            let b32 = parts.next().ok_or(Error::InvalidMultiaddr)?;
603            if b32.len() != $encoded_len {
604                return Err(Error::InvalidMultiaddr);
605            }
606
607            // port number
608            let port = parts
609                .next()
610                .ok_or(Error::InvalidMultiaddr)
611                .and_then(|p| str::parse(p).map_err(From::from))?;
612
613            // port == 0 is not valid for onion
614            if port == 0 {
615                return Err(Error::InvalidMultiaddr);
616            }
617
618            // nothing else expected
619            if parts.next().is_some() {
620                return Err(Error::InvalidMultiaddr);
621            }
622
623            if $len != BASE32.decode_len(b32.len()).map_err(|_| Error::InvalidMultiaddr)? {
624                return Err(Error::InvalidMultiaddr);
625            }
626
627            let mut buf = [0u8; $len];
628            BASE32
629                .decode_mut(b32.as_bytes(), &mut buf)
630                .map_err(|_| Error::InvalidMultiaddr)?;
631
632            Ok((buf, port))
633        }
634    };
635}
636
637// Parse a version 2 onion address and return its binary representation.
638//
639// Format: <base-32 address> ":" <port number>
640read_onion_impl!(read_onion, 10, 16);
641// Parse a version 3 onion address and return its binary representation.
642//
643// Format: <base-32 address> ":" <port number>
644read_onion_impl!(read_onion3, 35, 56);