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
18const 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; const WSS: u32 = 478;
54const WSS_WITH_PATH: u32 = 4780; const SCION: u32 =2;
56
57type 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#[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 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 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 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 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 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
711impl<'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 let b32 = parts.next().ok_or(Error::InvalidMultiaddr)?;
769 if b32.len() != $encoded_len {
770 return Err(Error::InvalidMultiaddr);
771 }
772
773 let port = parts
775 .next()
776 .ok_or(Error::InvalidMultiaddr)
777 .and_then(|p| str::parse(p).map_err(From::from))?;
778
779 if port == 0 {
781 return Err(Error::InvalidMultiaddr);
782 }
783
784 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
807read_onion_impl!(read_onion, 10, 16);
811read_onion_impl!(read_onion3, 35, 56);