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 libp2p_identity::PeerId;
7use std::{
8    borrow::Cow,
9    convert::From,
10    fmt,
11    io::{Cursor, Write},
12    net::{IpAddr, Ipv4Addr, Ipv6Addr},
13    str::{self, FromStr},
14};
15use unsigned_varint::{decode, encode};
16use scionnet::{ScionAddr};
17
18// All the values are obtained by converting hexadecimal protocol codes to u32.
19// Protocols as well as their corresponding codes are defined in
20// https://github.com/multiformats/multiaddr/blob/master/protocols.csv .
21const DCCP: u32 = 33;
22const DNS: u32 = 53;
23const DNS4: u32 = 54;
24const DNS6: u32 = 55;
25const DNSADDR: u32 = 56;
26const HTTP: u32 = 480;
27const HTTPS: u32 = 443;
28const IP4: u32 = 4;
29const IP6: u32 = 41;
30const P2P_WEBRTC_DIRECT: u32 = 276;
31const P2P_WEBRTC_STAR: u32 = 275;
32const WEBRTC_DIRECT: u32 = 280;
33const CERTHASH: u32 = 466;
34const P2P_WEBSOCKET_STAR: u32 = 479;
35const MEMORY: u32 = 777;
36const ONION: u32 = 444;
37const ONION3: u32 = 445;
38const P2P: u32 = 421;
39const P2P_CIRCUIT: u32 = 290;
40const QUIC: u32 = 460;
41const QUIC_V1: u32 = 461;
42const SCTP: u32 = 132;
43const TCP: u32 = 6;
44const TLS: u32 = 448;
45const NOISE: u32 = 454;
46const UDP: u32 = 273;
47const UDT: u32 = 301;
48const UNIX: u32 = 400;
49const UTP: u32 = 302;
50const WEBTRANSPORT: u32 = 465;
51const WS: u32 = 477;
52const WS_WITH_PATH: u32 = 4770; // Note: not standard
53const WSS: u32 = 478;
54const WSS_WITH_PATH: u32 = 4780; // Note: not standard
55const SCION: u32 =2;
56
57/// Type-alias for how multi-addresses use `Multihash`.
58///
59/// The `64` defines the allocation size for the digest within the `Multihash`.
60/// This allows us to use hashes such as SHA512.
61/// In case protocols like `/certhash` ever support hashes larger than that, we will need to update this size here (which will be a breaking change!).
62type Multihash = multihash::Multihash<64>;
63
64const PATH_SEGMENT_ENCODE_SET: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
65    .add(b'%')
66    .add(b'/')
67    .add(b'`')
68    .add(b'?')
69    .add(b'{')
70    .add(b'}')
71    .add(b' ')
72    .add(b'"')
73    .add(b'#')
74    .add(b'<')
75    .add(b'>');
76
77/// `Protocol` describes all possible multiaddress protocols.
78///
79/// For `Unix`, `Ws` and `Wss` we use `&str` instead of `Path` to allow
80/// cross-platform usage of `Protocol` since encoding `Paths` to bytes is
81/// platform-specific. This means that the actual validation of paths needs to
82/// happen separately.
83#[derive(PartialEq, Eq, Clone, Debug)]
84#[non_exhaustive]
85pub enum Protocol<'a> {
86    Dccp(u16),
87    Dns(Cow<'a, str>),
88    Dns4(Cow<'a, str>),
89    Dns6(Cow<'a, str>),
90    Dnsaddr(Cow<'a, str>),
91    Http,
92    Https,
93    Scion(ScionAddr),
94    Ip4(Ipv4Addr),
95    Ip6(Ipv6Addr),
96    P2pWebRtcDirect,
97    P2pWebRtcStar,
98    WebRTCDirect,
99    Certhash(Multihash),
100    P2pWebSocketStar,
101    /// Contains the "port" to contact. Similar to TCP or UDP, 0 means "assign me a port".
102    Memory(u64),
103    Onion(Cow<'a, [u8; 10]>, u16),
104    Onion3(Onion3Addr<'a>),
105    P2p(PeerId),
106    P2pCircuit,
107    Quic,
108    QuicV1,
109    Sctp(u16),
110    Tcp(u16),
111    Tls,
112    Noise,
113    Udp(u16),
114    Udt,
115    Unix(Cow<'a, str>),
116    Utp,
117    WebTransport,
118    Ws(Cow<'a, str>),
119    Wss(Cow<'a, str>),
120}
121
122impl<'a> Protocol<'a> {
123    /// Parse a protocol value from the given iterator of string slices.
124    ///
125    /// The parsing only consumes the minimum amount of string slices necessary to
126    /// produce a well-formed protocol. The same iterator can thus be used to parse
127    /// a sequence of protocols in succession. It is up to client code to check
128    /// that iteration has finished whenever appropriate.
129    pub fn from_str_parts<I>(mut iter: I) -> Result<Self>
130    where
131        I: Iterator<Item = &'a str>,
132    {
133        match iter.next().ok_or(Error::InvalidProtocolString)? {
134            "scion" => { 
135                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
136                let addr = ScionAddr::from_str(s).map_err(|e|{ Error::ParsingError(Box::new(e))})?;
137                Ok(Protocol::Scion(addr))
138            }
139            "ip4" => {
140                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
141                Ok(Protocol::Ip4(Ipv4Addr::from_str(s)?))
142            }
143            "tcp" => {
144                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
145                Ok(Protocol::Tcp(s.parse()?))
146            }
147            "tls" => Ok(Protocol::Tls),
148            "noise" => Ok(Protocol::Noise),
149            "udp" => {
150                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
151                Ok(Protocol::Udp(s.parse()?))
152            }
153            "dccp" => {
154                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
155                Ok(Protocol::Dccp(s.parse()?))
156            }
157            "ip6" => {
158                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
159                Ok(Protocol::Ip6(Ipv6Addr::from_str(s)?))
160            }
161            "dns" => {
162                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
163                Ok(Protocol::Dns(Cow::Borrowed(s)))
164            }
165            "dns4" => {
166                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
167                Ok(Protocol::Dns4(Cow::Borrowed(s)))
168            }
169            "dns6" => {
170                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
171                Ok(Protocol::Dns6(Cow::Borrowed(s)))
172            }
173            "dnsaddr" => {
174                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
175                Ok(Protocol::Dnsaddr(Cow::Borrowed(s)))
176            }
177            "sctp" => {
178                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
179                Ok(Protocol::Sctp(s.parse()?))
180            }
181            "udt" => Ok(Protocol::Udt),
182            "utp" => Ok(Protocol::Utp),
183            "unix" => {
184                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
185                Ok(Protocol::Unix(Cow::Borrowed(s)))
186            }
187            "p2p" => {
188                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
189                let decoded = multibase::Base::Base58Btc.decode(s)?;
190                let peer_id =
191                    PeerId::from_bytes(&decoded).map_err(|e| Error::ParsingError(Box::new(e)))?;
192                Ok(Protocol::P2p(peer_id))
193            }
194            "http" => Ok(Protocol::Http),
195            "https" => Ok(Protocol::Https),
196            "onion" => iter
197                .next()
198                .ok_or(Error::InvalidProtocolString)
199                .and_then(|s| read_onion(&s.to_uppercase()))
200                .map(|(a, p)| Protocol::Onion(Cow::Owned(a), p)),
201            "onion3" => iter
202                .next()
203                .ok_or(Error::InvalidProtocolString)
204                .and_then(|s| read_onion3(&s.to_uppercase()))
205                .map(|(a, p)| Protocol::Onion3((a, p).into())),
206            "quic" => Ok(Protocol::Quic),
207            "quic-v1" => Ok(Protocol::QuicV1),
208            "webtransport" => Ok(Protocol::WebTransport),
209            "ws" => Ok(Protocol::Ws(Cow::Borrowed("/"))),
210            "wss" => Ok(Protocol::Wss(Cow::Borrowed("/"))),
211            "x-parity-ws" => {
212                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
213                let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
214                Ok(Protocol::Ws(decoded))
215            }
216            "x-parity-wss" => {
217                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
218                let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
219                Ok(Protocol::Wss(decoded))
220            }
221            "p2p-websocket-star" => Ok(Protocol::P2pWebSocketStar),
222            "p2p-webrtc-star" => Ok(Protocol::P2pWebRtcStar),
223            "webrtc-direct" => Ok(Protocol::WebRTCDirect),
224            "certhash" => {
225                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
226                let (_base, decoded) = multibase::decode(s)?;
227                Ok(Protocol::Certhash(Multihash::from_bytes(&decoded)?))
228            }
229            "p2p-webrtc-direct" => Ok(Protocol::P2pWebRtcDirect),
230            "p2p-circuit" => Ok(Protocol::P2pCircuit),
231            "memory" => {
232                let s = iter.next().ok_or(Error::InvalidProtocolString)?;
233                Ok(Protocol::Memory(s.parse()?))
234            }
235            unknown => Err(Error::UnknownProtocolString(unknown.to_string())),
236        }
237    }
238
239    /// Parse a single `Protocol` value from its byte slice representation,
240    /// returning the protocol as well as the remaining byte slice.
241    pub fn from_bytes(input: &'a [u8]) -> Result<(Self, &'a [u8])> {
242        fn split_at(n: usize, input: &[u8]) -> Result<(&[u8], &[u8])> {
243            if input.len() < n {
244                return Err(Error::DataLessThanLen);
245            }
246            Ok(input.split_at(n))
247        }
248        let (id, input) = decode::u32(input)?;
249        match id {
250            DCCP => {
251                let (data, rest) = split_at(2, input)?;
252                let mut rdr = Cursor::new(data);
253                let num = rdr.read_u16::<BigEndian>()?;
254                Ok((Protocol::Dccp(num), rest))
255            }
256            DNS => {
257                let (n, input) = decode::usize(input)?;
258                let (data, rest) = split_at(n, input)?;
259                Ok((Protocol::Dns(Cow::Borrowed(str::from_utf8(data)?)), rest))
260            }
261            DNS4 => {
262                let (n, input) = decode::usize(input)?;
263                let (data, rest) = split_at(n, input)?;
264                Ok((Protocol::Dns4(Cow::Borrowed(str::from_utf8(data)?)), rest))
265            }
266            DNS6 => {
267                let (n, input) = decode::usize(input)?;
268                let (data, rest) = split_at(n, input)?;
269                Ok((Protocol::Dns6(Cow::Borrowed(str::from_utf8(data)?)), rest))
270            }
271            DNSADDR => {
272                let (n, input) = decode::usize(input)?;
273                let (data, rest) = split_at(n, input)?;
274                Ok((
275                    Protocol::Dnsaddr(Cow::Borrowed(str::from_utf8(data)?)),
276                    rest,
277                ))
278            }
279            HTTP => Ok((Protocol::Http, input)),
280            HTTPS => Ok((Protocol::Https, input)),
281            IP4 => {
282                let (data, rest) = split_at(4, input)?;
283                Ok((
284                    Protocol::Ip4(Ipv4Addr::new(data[0], data[1], data[2], data[3])),
285                    rest,
286                ))
287            }
288            IP6 => {
289                let (data, rest) = split_at(16, input)?;
290                let mut rdr = Cursor::new(data);
291                let mut seg = [0_u16; 8];
292
293                for x in seg.iter_mut() {
294                    *x = rdr.read_u16::<BigEndian>()?;
295                }
296
297                let addr = Ipv6Addr::new(
298                    seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7],
299                );
300
301                Ok((Protocol::Ip6(addr), rest))
302            }
303            SCION => {
304                let mut rdr = Cursor::new(input);
305                let ia: u64 = rdr.read_u64::<BigEndian>()?;
306
307                let mut len: usize =9;
308                let mut host:IpAddr = Ipv4Addr::new(0,0,0,0).into();
309
310                match rdr.read_u8()?
311                {
312                    4 => {
313                        len += 4;
314                        let b0 = rdr.read_u8()?;
315                        let b1= rdr.read_u8()?;
316                        let b2=rdr.read_u8()?;
317                        let b3=rdr.read_u8()?;
318                        host = Ipv4Addr::new(b0, b1, b2, b3).into();
319                    },
320                    6 => {
321                        len +=16;
322                        let mut seg = [0_u16; 8];
323
324                        for x in seg.iter_mut() {
325                            *x = rdr.read_u16::<BigEndian>()?;
326                        }
327        
328                        host = Ipv6Addr::new(
329                            seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7],
330                        ).into();
331                    },
332                    _ =>{unreachable!();}
333                }
334
335                let ( _, rest) = split_at(len, input)?;
336                Ok( (Protocol::Scion( ScionAddr{ia: ia, host: host.into()}) ,rest) )
337            },
338            P2P_WEBRTC_DIRECT => Ok((Protocol::P2pWebRtcDirect, input)),
339            P2P_WEBRTC_STAR => Ok((Protocol::P2pWebRtcStar, input)),
340            WEBRTC_DIRECT => Ok((Protocol::WebRTCDirect, input)),
341            CERTHASH => {
342                let (n, input) = decode::usize(input)?;
343                let (data, rest) = split_at(n, input)?;
344                Ok((Protocol::Certhash(Multihash::from_bytes(data)?), rest))
345            }
346            P2P_WEBSOCKET_STAR => Ok((Protocol::P2pWebSocketStar, input)),
347            MEMORY => {
348                let (data, rest) = split_at(8, input)?;
349                let mut rdr = Cursor::new(data);
350                let num = rdr.read_u64::<BigEndian>()?;
351                Ok((Protocol::Memory(num), rest))
352            }
353            ONION => {
354                let (data, rest) = split_at(12, input)?;
355                let port = BigEndian::read_u16(&data[10..]);
356                Ok((
357                    Protocol::Onion(Cow::Borrowed(array_ref!(data, 0, 10)), port),
358                    rest,
359                ))
360            }
361            ONION3 => {
362                let (data, rest) = split_at(37, input)?;
363                let port = BigEndian::read_u16(&data[35..]);
364                Ok((
365                    Protocol::Onion3((array_ref!(data, 0, 35), port).into()),
366                    rest,
367                ))
368            }
369            P2P => {
370                let (n, input) = decode::usize(input)?;
371                let (data, rest) = split_at(n, input)?;
372                Ok((
373                    Protocol::P2p(
374                        PeerId::from_bytes(data).map_err(|e| Error::ParsingError(Box::new(e)))?,
375                    ),
376                    rest,
377                ))
378            }
379            P2P_CIRCUIT => Ok((Protocol::P2pCircuit, input)),
380            QUIC => Ok((Protocol::Quic, input)),
381            QUIC_V1 => Ok((Protocol::QuicV1, input)),
382            SCTP => {
383                let (data, rest) = split_at(2, input)?;
384                let mut rdr = Cursor::new(data);
385                let num = rdr.read_u16::<BigEndian>()?;
386                Ok((Protocol::Sctp(num), rest))
387            }
388            TCP => {
389                let (data, rest) = split_at(2, input)?;
390                let mut rdr = Cursor::new(data);
391                let num = rdr.read_u16::<BigEndian>()?;
392                Ok((Protocol::Tcp(num), rest))
393            }
394            TLS => Ok((Protocol::Tls, input)),
395            NOISE => Ok((Protocol::Noise, input)),
396            UDP => {
397                let (data, rest) = split_at(2, input)?;
398                let mut rdr = Cursor::new(data);
399                let num = rdr.read_u16::<BigEndian>()?;
400                Ok((Protocol::Udp(num), rest))
401            }
402            UDT => Ok((Protocol::Udt, input)),
403            UNIX => {
404                let (n, input) = decode::usize(input)?;
405                let (data, rest) = split_at(n, input)?;
406                Ok((Protocol::Unix(Cow::Borrowed(str::from_utf8(data)?)), rest))
407            }
408            UTP => Ok((Protocol::Utp, input)),
409            WEBTRANSPORT => Ok((Protocol::WebTransport, input)),
410            WS => Ok((Protocol::Ws(Cow::Borrowed("/")), input)),
411            WS_WITH_PATH => {
412                let (n, input) = decode::usize(input)?;
413                let (data, rest) = split_at(n, input)?;
414                Ok((Protocol::Ws(Cow::Borrowed(str::from_utf8(data)?)), rest))
415            }
416            WSS => Ok((Protocol::Wss(Cow::Borrowed("/")), input)),
417            WSS_WITH_PATH => {
418                let (n, input) = decode::usize(input)?;
419                let (data, rest) = split_at(n, input)?;
420                Ok((Protocol::Wss(Cow::Borrowed(str::from_utf8(data)?)), rest))
421            }
422            _ => Err(Error::UnknownProtocolId(id)),
423        }
424    }
425
426    /// Encode this protocol by writing its binary representation into
427    /// the given `Write` impl.
428    pub fn write_bytes<W: Write>(&self, w: &mut W) -> Result<()> {
429        let mut buf = encode::u32_buffer();
430        match self {
431            Protocol::Scion(addr) => {
432                w.write_all( encode::u32(SCION, &mut buf))?;
433                w.write_u64::<BigEndian>(addr.get_ia())?;
434                
435                match (*addr.get_host()).into() {
436                    IpAddr::V4(ip) => {
437                        w.write_u8(4)?;
438                        w.write_all(&ip.octets())?
439                    },
440                    IpAddr::V6(ip)=>{
441                        w.write_u8(6)?;
442                        for &segment in &ip.segments() {
443                            w.write_u16::<BigEndian>(segment)?
444                        }
445                    }
446                }
447            }
448            Protocol::Ip4(addr) => {
449                w.write_all(encode::u32(IP4, &mut buf))?;
450                w.write_all(&addr.octets())?
451            }
452            Protocol::Ip6(addr) => {
453                w.write_all(encode::u32(IP6, &mut buf))?;
454                for &segment in &addr.segments() {
455                    w.write_u16::<BigEndian>(segment)?
456                }
457            }
458            Protocol::Tcp(port) => {
459                w.write_all(encode::u32(TCP, &mut buf))?;
460                w.write_u16::<BigEndian>(*port)?
461            }
462            Protocol::Tls => w.write_all(encode::u32(TLS, &mut buf))?,
463            Protocol::Noise => w.write_all(encode::u32(NOISE, &mut buf))?,
464            Protocol::Udp(port) => {
465                w.write_all(encode::u32(UDP, &mut buf))?;
466                w.write_u16::<BigEndian>(*port)?
467            }
468            Protocol::Dccp(port) => {
469                w.write_all(encode::u32(DCCP, &mut buf))?;
470                w.write_u16::<BigEndian>(*port)?
471            }
472            Protocol::Sctp(port) => {
473                w.write_all(encode::u32(SCTP, &mut buf))?;
474                w.write_u16::<BigEndian>(*port)?
475            }
476            Protocol::Dns(s) => {
477                w.write_all(encode::u32(DNS, &mut buf))?;
478                let bytes = s.as_bytes();
479                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
480                w.write_all(bytes)?
481            }
482            Protocol::Dns4(s) => {
483                w.write_all(encode::u32(DNS4, &mut buf))?;
484                let bytes = s.as_bytes();
485                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
486                w.write_all(bytes)?
487            }
488            Protocol::Dns6(s) => {
489                w.write_all(encode::u32(DNS6, &mut buf))?;
490                let bytes = s.as_bytes();
491                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
492                w.write_all(bytes)?
493            }
494            Protocol::Dnsaddr(s) => {
495                w.write_all(encode::u32(DNSADDR, &mut buf))?;
496                let bytes = s.as_bytes();
497                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
498                w.write_all(bytes)?
499            }
500            Protocol::Unix(s) => {
501                w.write_all(encode::u32(UNIX, &mut buf))?;
502                let bytes = s.as_bytes();
503                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
504                w.write_all(bytes)?
505            }
506            Protocol::P2p(peer_id) => {
507                w.write_all(encode::u32(P2P, &mut buf))?;
508                let bytes = peer_id.to_bytes();
509                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
510                w.write_all(&bytes)?
511            }
512            Protocol::Onion(addr, port) => {
513                w.write_all(encode::u32(ONION, &mut buf))?;
514                w.write_all(addr.as_ref())?;
515                w.write_u16::<BigEndian>(*port)?
516            }
517            Protocol::Onion3(addr) => {
518                w.write_all(encode::u32(ONION3, &mut buf))?;
519                w.write_all(addr.hash().as_ref())?;
520                w.write_u16::<BigEndian>(addr.port())?
521            }
522            Protocol::Quic => w.write_all(encode::u32(QUIC, &mut buf))?,
523            Protocol::QuicV1 => w.write_all(encode::u32(QUIC_V1, &mut buf))?,
524            Protocol::Utp => w.write_all(encode::u32(UTP, &mut buf))?,
525            Protocol::Udt => w.write_all(encode::u32(UDT, &mut buf))?,
526            Protocol::Http => w.write_all(encode::u32(HTTP, &mut buf))?,
527            Protocol::Https => w.write_all(encode::u32(HTTPS, &mut buf))?,
528            Protocol::WebTransport => w.write_all(encode::u32(WEBTRANSPORT, &mut buf))?,
529            Protocol::Ws(ref s) if s == "/" => w.write_all(encode::u32(WS, &mut buf))?,
530            Protocol::Ws(s) => {
531                w.write_all(encode::u32(WS_WITH_PATH, &mut buf))?;
532                let bytes = s.as_bytes();
533                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
534                w.write_all(bytes)?
535            }
536            Protocol::Wss(ref s) if s == "/" => w.write_all(encode::u32(WSS, &mut buf))?,
537            Protocol::Wss(s) => {
538                w.write_all(encode::u32(WSS_WITH_PATH, &mut buf))?;
539                let bytes = s.as_bytes();
540                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
541                w.write_all(bytes)?
542            }
543            Protocol::P2pWebSocketStar => w.write_all(encode::u32(P2P_WEBSOCKET_STAR, &mut buf))?,
544            Protocol::P2pWebRtcStar => w.write_all(encode::u32(P2P_WEBRTC_STAR, &mut buf))?,
545            Protocol::WebRTCDirect => w.write_all(encode::u32(WEBRTC_DIRECT, &mut buf))?,
546            Protocol::Certhash(hash) => {
547                w.write_all(encode::u32(CERTHASH, &mut buf))?;
548                let bytes = hash.to_bytes();
549                w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
550                w.write_all(&bytes)?
551            }
552            Protocol::P2pWebRtcDirect => w.write_all(encode::u32(P2P_WEBRTC_DIRECT, &mut buf))?,
553            Protocol::P2pCircuit => w.write_all(encode::u32(P2P_CIRCUIT, &mut buf))?,
554            Protocol::Memory(port) => {
555                w.write_all(encode::u32(MEMORY, &mut buf))?;
556                w.write_u64::<BigEndian>(*port)?
557            }
558        }
559        Ok(())
560    }
561
562    /// Turn this `Protocol` into one that owns its data, thus being valid for any lifetime.
563    pub fn acquire<'b>(self) -> Protocol<'b> {
564        use self::Protocol::*;
565        match self {
566            Dccp(a) => Dccp(a),
567            Dns(cow) => Dns(Cow::Owned(cow.into_owned())),
568            Dns4(cow) => Dns4(Cow::Owned(cow.into_owned())),
569            Dns6(cow) => Dns6(Cow::Owned(cow.into_owned())),
570            Dnsaddr(cow) => Dnsaddr(Cow::Owned(cow.into_owned())),
571            Http => Http,
572            Https => Https,
573            Scion(s)=> Scion(s),
574            Ip4(a) => Ip4(a),
575            Ip6(a) => Ip6(a),
576            P2pWebRtcDirect => P2pWebRtcDirect,
577            P2pWebRtcStar => P2pWebRtcStar,
578            WebRTCDirect => WebRTCDirect,
579            Certhash(hash) => Certhash(hash),
580            P2pWebSocketStar => P2pWebSocketStar,
581            Memory(a) => Memory(a),
582            Onion(addr, port) => Onion(Cow::Owned(addr.into_owned()), port),
583            Onion3(addr) => Onion3(addr.acquire()),
584            P2p(a) => P2p(a),
585            P2pCircuit => P2pCircuit,
586            Quic => Quic,
587            QuicV1 => QuicV1,
588            Sctp(a) => Sctp(a),
589            Tcp(a) => Tcp(a),
590            Tls => Tls,
591            Noise => Noise,
592            Udp(a) => Udp(a),
593            Udt => Udt,
594            Unix(cow) => Unix(Cow::Owned(cow.into_owned())),
595            Utp => Utp,
596            WebTransport => WebTransport,
597            Ws(cow) => Ws(Cow::Owned(cow.into_owned())),
598            Wss(cow) => Wss(Cow::Owned(cow.into_owned())),
599        }
600    }
601
602    pub fn tag(&self) -> &'static str {
603        use self::Protocol::*;
604        match self {
605            Dccp(_) => "dccp",
606            Dns(_) => "dns",
607            Dns4(_) => "dns4",
608            Dns6(_) => "dns6",
609            Dnsaddr(_) => "dnsaddr",
610            Http => "http",
611            Https => "https",
612            Ip4(_) => "ip4",
613            Ip6(_) => "ip6",
614            Scion(_)=>"scion",
615            P2pWebRtcDirect => "p2p-webrtc-direct",
616            P2pWebRtcStar => "p2p-webrtc-star",
617            WebRTCDirect => "webrtc-direct",
618            Certhash(_) => "certhash",
619            P2pWebSocketStar => "p2p-websocket-star",
620            Memory(_) => "memory",
621            Onion(_, _) => "onion",
622            Onion3(_) => "onion3",
623            P2p(_) => "p2p",
624            P2pCircuit => "p2p-circuit",
625            Quic => "quic",
626            QuicV1 => "quic-v1",
627            Sctp(_) => "sctp",
628            Tcp(_) => "tcp",
629            Tls => "tls",
630            Noise => "noise",
631            Udp(_) => "udp",
632            Udt => "udt",
633            Unix(_) => "unix",
634            Utp => "utp",
635            WebTransport => "webtransport",
636            Ws(ref s) if s == "/" => "ws",
637            Ws(_) => "x-parity-ws",
638            Wss(ref s) if s == "/" => "wss",
639            Wss(_) => "x-parity-wss",
640        }
641    }
642}
643
644impl<'a> fmt::Display for Protocol<'a> {
645    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
646        use self::Protocol::*;
647        write!(f, "/{}", self.tag())?;
648        match self {
649            Dccp(port) => write!(f, "/{port}"),
650            Dns(s) => write!(f, "/{s}"),
651            Dns4(s) => write!(f, "/{s}"),
652            Dns6(s) => write!(f, "/{s}"),
653            Dnsaddr(s) => write!(f, "/{s}"),
654            Ip4(addr) => write!(f, "/{addr}"),
655            Ip6(addr) => write!(f, "/{addr}"),
656            Scion(addr)=>write!(f,"/{addr}"),
657            Certhash(hash) => write!(
658                f,
659                "/{}",
660                multibase::encode(multibase::Base::Base64Url, hash.to_bytes())
661            ),
662            Memory(port) => write!(f, "/{port}"),
663            Onion(addr, port) => {
664                let s = BASE32.encode(addr.as_ref());
665                write!(f, "/{}:{}", s.to_lowercase(), port)
666            }
667            Onion3(addr) => {
668                let s = BASE32.encode(addr.hash());
669                write!(f, "/{}:{}", s.to_lowercase(), addr.port())
670            }
671            P2p(c) => write!(f, "/{}", multibase::Base::Base58Btc.encode(c.to_bytes())),
672            Sctp(port) => write!(f, "/{port}"),
673            Tcp(port) => write!(f, "/{port}"),
674            Udp(port) => write!(f, "/{port}"),
675            Unix(s) => write!(f, "/{s}"),
676            Ws(s) if s != "/" => {
677                let encoded =
678                    percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
679                write!(f, "/{encoded}")
680            }
681            Wss(s) if s != "/" => {
682                let encoded =
683                    percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
684                write!(f, "/{encoded}")
685            }
686            _ => Ok(()),
687        }
688    }
689}
690
691impl<'a> From<IpAddr> for Protocol<'a> {
692    #[inline]
693    fn from(addr: IpAddr) -> Self {
694        match addr {
695            IpAddr::V4(addr) => Protocol::Ip4(addr),
696            IpAddr::V6(addr) => Protocol::Ip6(addr),
697        }
698    }
699}
700
701impl<'a> From<scionnet::IpAddr> for Protocol<'a> {
702    #[inline]
703    fn from(addr: scionnet::IpAddr) -> Self {
704        match addr {
705            scionnet::IpAddr::V4(addr) => Protocol::Ip4(addr.into()),
706            scionnet::IpAddr::V6(addr) => Protocol::Ip6(addr.into()),
707        }
708    }
709}
710
711/*
712impl<'a> FromStr for Protocol<'a> {
713    type Err = Error;
714    fn from_str(s: &str) -> std::prelude::v1::Result<Self, Self::Err> {
715        let addr: scionnet::SocketAddr = <scionnet::SocketAddr as FromStr>::from_str(s)
716        .map_err(|e|Error::ParsingError(Box::new(e)))?;
717        match addr {
718            scionnet::SocketAddr::V4(a) =>{ Ok((*a.ip()).into()) },
719            scionnet::SocketAddr::V6(a) =>{Ok((*a.ip()).into()) },
720            scionnet::SocketAddr::SCION(s) =>{Ok((s.addr).into()) }
721        }
722    }
723}
724*/
725
726impl<'a> From<ScionAddr> for Protocol<'a> {
727    #[inline]
728    fn from(addr: ScionAddr) -> Self {
729        Protocol::Scion(addr)
730    }
731}
732
733
734impl<'a> From<Ipv4Addr> for Protocol<'a> {
735    #[inline]
736    fn from(addr: Ipv4Addr) -> Self {
737        Protocol::Ip4(addr)
738    }
739}
740
741impl<'a> From<Ipv6Addr> for Protocol<'a> {
742    #[inline]
743    fn from(addr: Ipv6Addr) -> Self {
744        Protocol::Ip6(addr)
745    }
746}
747
748impl<'a> From<scionnet::Ipv4Addr> for Protocol<'a> {
749    #[inline]
750    fn from(addr: scionnet::Ipv4Addr) -> Self {
751        Protocol::Ip4(addr.into())
752    }
753}
754
755impl<'a> From<scionnet::Ipv6Addr> for Protocol<'a> {
756    #[inline]
757    fn from(addr: scionnet::Ipv6Addr) -> Self {
758        Protocol::Ip6(addr.into())
759    }
760}
761
762macro_rules! read_onion_impl {
763    ($name:ident, $len:expr, $encoded_len:expr) => {
764        fn $name(s: &str) -> Result<([u8; $len], u16)> {
765            let mut parts = s.split(':');
766
767            // address part (without ".onion")
768            let b32 = parts.next().ok_or(Error::InvalidMultiaddr)?;
769            if b32.len() != $encoded_len {
770                return Err(Error::InvalidMultiaddr);
771            }
772
773            // port number
774            let port = parts
775                .next()
776                .ok_or(Error::InvalidMultiaddr)
777                .and_then(|p| str::parse(p).map_err(From::from))?;
778
779            // port == 0 is not valid for onion
780            if port == 0 {
781                return Err(Error::InvalidMultiaddr);
782            }
783
784            // nothing else expected
785            if parts.next().is_some() {
786                return Err(Error::InvalidMultiaddr);
787            }
788
789            if $len
790                != BASE32
791                    .decode_len(b32.len())
792                    .map_err(|_| Error::InvalidMultiaddr)?
793            {
794                return Err(Error::InvalidMultiaddr);
795            }
796
797            let mut buf = [0u8; $len];
798            BASE32
799                .decode_mut(b32.as_bytes(), &mut buf)
800                .map_err(|_| Error::InvalidMultiaddr)?;
801
802            Ok((buf, port))
803        }
804    };
805}
806
807// Parse a version 2 onion address and return its binary representation.
808//
809// Format: <base-32 address> ":" <port number>
810read_onion_impl!(read_onion, 10, 16);
811// Parse a version 3 onion address and return its binary representation.
812//
813// Format: <base-32 address> ":" <port number>
814read_onion_impl!(read_onion3, 35, 56);