1use crate::{Error, Result};
2use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
3use std::{
4 borrow::Cow,
5 convert::From,
6 fmt,
7 io::{Cursor, Write},
8 net::{IpAddr, Ipv4Addr, Ipv6Addr},
9 str::{self, FromStr},
10};
11use unsigned_varint::{decode, encode};
12
13const DCCP: u32 = 33;
17const DNS: u32 = 53;
18const DNS4: u32 = 54;
19const DNS6: u32 = 55;
20const DNSADDR: u32 = 56;
21const HTTP: u32 = 480;
22const HTTPS: u32 = 443;
23const IP4: u32 = 4;
24const IP6: u32 = 41;
25const P2P_WEBRTC_DIRECT: u32 = 276;
26const P2P_WEBRTC_STAR: u32 = 275;
27const WEBRTC_DIRECT: u32 = 280;
28const P2P_WEBSOCKET_STAR: u32 = 479;
29const MEMORY: u32 = 777;
30const P2P: u32 = 421;
31const P2P_CIRCUIT: u32 = 290;
32const QUIC: u32 = 460;
33const QUIC_V1: u32 = 461;
34const SCTP: u32 = 132;
35const TCP: u32 = 6;
36const TLS: u32 = 448;
37const NOISE: u32 = 454;
38const UDP: u32 = 273;
39const UDT: u32 = 301;
40const UNIX: u32 = 400;
41const UTP: u32 = 302;
42const WEBTRANSPORT: u32 = 465;
43const WS: u32 = 477;
44const WS_WITH_PATH: u32 = 4770; const WSS: u32 = 478;
46const WSS_WITH_PATH: u32 = 4780; const PATH_SEGMENT_ENCODE_SET: &percent_encoding::AsciiSet = &percent_encoding::CONTROLS
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 .add(b'>');
60
61#[derive(PartialEq, Eq, Clone, Debug)]
68#[non_exhaustive]
69pub enum Protocol<'a> {
70 Dccp(u16),
71 Dns(Cow<'a, str>),
72 Dns4(Cow<'a, str>),
73 Dns6(Cow<'a, str>),
74 Dnsaddr(Cow<'a, str>),
75 Http,
76 Https,
77 Ip4(Ipv4Addr),
78 Ip6(Ipv6Addr),
79 P2pWebRtcDirect,
80 P2pWebRtcStar,
81 WebRTCDirect,
82 P2pWebSocketStar,
83 Memory(u64),
85 P2p(u32),
86 P2pCircuit,
87 Quic,
88 QuicV1,
89 Sctp(u16),
90 Tcp(u16),
91 Tls,
92 Noise,
93 Udp(u16),
94 Udt,
95 Unix(Cow<'a, str>),
96 Utp,
97 WebTransport,
98 Ws(Cow<'a, str>),
99 Wss(Cow<'a, str>),
100}
101
102impl<'a> Protocol<'a> {
103 pub fn from_str_parts<I>(mut iter: I) -> Result<Self>
110 where
111 I: Iterator<Item = &'a str>,
112 {
113 match iter.next().ok_or(Error::InvalidProtocolString)? {
114 "ip4" => {
115 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
116 Ok(Protocol::Ip4(Ipv4Addr::from_str(s)?))
117 }
118 "tcp" => {
119 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
120 Ok(Protocol::Tcp(s.parse()?))
121 }
122 "tls" => Ok(Protocol::Tls),
123 "noise" => Ok(Protocol::Noise),
124 "udp" => {
125 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
126 Ok(Protocol::Udp(s.parse()?))
127 }
128 "dccp" => {
129 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
130 Ok(Protocol::Dccp(s.parse()?))
131 }
132 "ip6" => {
133 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
134 Ok(Protocol::Ip6(Ipv6Addr::from_str(s)?))
135 }
136 "dns" => {
137 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
138 Ok(Protocol::Dns(Cow::Borrowed(s)))
139 }
140 "dns4" => {
141 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
142 Ok(Protocol::Dns4(Cow::Borrowed(s)))
143 }
144 "dns6" => {
145 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
146 Ok(Protocol::Dns6(Cow::Borrowed(s)))
147 }
148 "dnsaddr" => {
149 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
150 Ok(Protocol::Dnsaddr(Cow::Borrowed(s)))
151 }
152 "sctp" => {
153 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
154 Ok(Protocol::Sctp(s.parse()?))
155 }
156 "udt" => Ok(Protocol::Udt),
157 "utp" => Ok(Protocol::Utp),
158 "unix" => {
159 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
160 Ok(Protocol::Unix(Cow::Borrowed(s)))
161 }
162 "p2p" => {
163 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
164 Ok(Protocol::P2p(s.parse()?))
165 }
166 "http" => Ok(Protocol::Http),
167 "https" => Ok(Protocol::Https),
168 "quic" => Ok(Protocol::Quic),
169 "quic-v1" => Ok(Protocol::QuicV1),
170 "webtransport" => Ok(Protocol::WebTransport),
171 "ws" => Ok(Protocol::Ws(Cow::Borrowed("/"))),
172 "wss" => Ok(Protocol::Wss(Cow::Borrowed("/"))),
173 "x-parity-ws" => {
174 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
175 let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
176 Ok(Protocol::Ws(decoded))
177 }
178 "x-parity-wss" => {
179 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
180 let decoded = percent_encoding::percent_decode(s.as_bytes()).decode_utf8()?;
181 Ok(Protocol::Wss(decoded))
182 }
183 "p2p-websocket-star" => Ok(Protocol::P2pWebSocketStar),
184 "p2p-webrtc-star" => Ok(Protocol::P2pWebRtcStar),
185 "webrtc-direct" => Ok(Protocol::WebRTCDirect),
186 "p2p-webrtc-direct" => Ok(Protocol::P2pWebRtcDirect),
187 "p2p-circuit" => Ok(Protocol::P2pCircuit),
188 "memory" => {
189 let s = iter.next().ok_or(Error::InvalidProtocolString)?;
190 Ok(Protocol::Memory(s.parse()?))
191 }
192 unknown => Err(Error::UnknownProtocolString(unknown.to_string())),
193 }
194 }
195
196 pub fn from_bytes(input: &'a [u8]) -> Result<(Self, &'a [u8])> {
199 fn split_at(n: usize, input: &[u8]) -> Result<(&[u8], &[u8])> {
200 if input.len() < n {
201 return Err(Error::DataLessThanLen);
202 }
203 Ok(input.split_at(n))
204 }
205 let (id, input) = decode::u32(input)?;
206 match id {
207 DCCP => {
208 let (data, rest) = split_at(2, input)?;
209 let mut rdr = Cursor::new(data);
210 let num = rdr.read_u16::<BigEndian>()?;
211 Ok((Protocol::Dccp(num), rest))
212 }
213 DNS => {
214 let (n, input) = decode::usize(input)?;
215 let (data, rest) = split_at(n, input)?;
216 Ok((Protocol::Dns(Cow::Borrowed(str::from_utf8(data)?)), rest))
217 }
218 DNS4 => {
219 let (n, input) = decode::usize(input)?;
220 let (data, rest) = split_at(n, input)?;
221 Ok((Protocol::Dns4(Cow::Borrowed(str::from_utf8(data)?)), rest))
222 }
223 DNS6 => {
224 let (n, input) = decode::usize(input)?;
225 let (data, rest) = split_at(n, input)?;
226 Ok((Protocol::Dns6(Cow::Borrowed(str::from_utf8(data)?)), rest))
227 }
228 DNSADDR => {
229 let (n, input) = decode::usize(input)?;
230 let (data, rest) = split_at(n, input)?;
231 Ok((Protocol::Dnsaddr(Cow::Borrowed(str::from_utf8(data)?)), rest))
232 }
233 HTTP => Ok((Protocol::Http, input)),
234 HTTPS => Ok((Protocol::Https, input)),
235 IP4 => {
236 let (data, rest) = split_at(4, input)?;
237 Ok((Protocol::Ip4(Ipv4Addr::new(data[0], data[1], data[2], data[3])), rest))
238 }
239 IP6 => {
240 let (data, rest) = split_at(16, input)?;
241 let mut rdr = Cursor::new(data);
242 let mut seg = [0_u16; 8];
243
244 for x in seg.iter_mut() {
245 *x = rdr.read_u16::<BigEndian>()?;
246 }
247
248 let addr = Ipv6Addr::new(seg[0], seg[1], seg[2], seg[3], seg[4], seg[5], seg[6], seg[7]);
249
250 Ok((Protocol::Ip6(addr), rest))
251 }
252 P2P_WEBRTC_DIRECT => Ok((Protocol::P2pWebRtcDirect, input)),
253 P2P_WEBRTC_STAR => Ok((Protocol::P2pWebRtcStar, input)),
254 WEBRTC_DIRECT => Ok((Protocol::WebRTCDirect, input)),
255 P2P_WEBSOCKET_STAR => Ok((Protocol::P2pWebSocketStar, input)),
256 MEMORY => {
257 let (data, rest) = split_at(8, input)?;
258 let mut rdr = Cursor::new(data);
259 let num = rdr.read_u64::<BigEndian>()?;
260 Ok((Protocol::Memory(num), rest))
261 }
262 P2P => {
263 let (data, rest) = split_at(4, input)?;
264 let mut rdr = Cursor::new(data);
265 let num = rdr.read_u32::<BigEndian>()?;
266 Ok((Protocol::P2p(num), rest))
267 }
268 P2P_CIRCUIT => Ok((Protocol::P2pCircuit, input)),
269 QUIC => Ok((Protocol::Quic, input)),
270 QUIC_V1 => Ok((Protocol::QuicV1, input)),
271 SCTP => {
272 let (data, rest) = split_at(2, input)?;
273 let mut rdr = Cursor::new(data);
274 let num = rdr.read_u16::<BigEndian>()?;
275 Ok((Protocol::Sctp(num), rest))
276 }
277 TCP => {
278 let (data, rest) = split_at(2, input)?;
279 let mut rdr = Cursor::new(data);
280 let num = rdr.read_u16::<BigEndian>()?;
281 Ok((Protocol::Tcp(num), rest))
282 }
283 TLS => Ok((Protocol::Tls, input)),
284 NOISE => Ok((Protocol::Noise, input)),
285 UDP => {
286 let (data, rest) = split_at(2, input)?;
287 let mut rdr = Cursor::new(data);
288 let num = rdr.read_u16::<BigEndian>()?;
289 Ok((Protocol::Udp(num), rest))
290 }
291 UDT => Ok((Protocol::Udt, input)),
292 UNIX => {
293 let (n, input) = decode::usize(input)?;
294 let (data, rest) = split_at(n, input)?;
295 Ok((Protocol::Unix(Cow::Borrowed(str::from_utf8(data)?)), rest))
296 }
297 UTP => Ok((Protocol::Utp, input)),
298 WEBTRANSPORT => Ok((Protocol::WebTransport, input)),
299 WS => Ok((Protocol::Ws(Cow::Borrowed("/")), input)),
300 WS_WITH_PATH => {
301 let (n, input) = decode::usize(input)?;
302 let (data, rest) = split_at(n, input)?;
303 Ok((Protocol::Ws(Cow::Borrowed(str::from_utf8(data)?)), rest))
304 }
305 WSS => Ok((Protocol::Wss(Cow::Borrowed("/")), input)),
306 WSS_WITH_PATH => {
307 let (n, input) = decode::usize(input)?;
308 let (data, rest) = split_at(n, input)?;
309 Ok((Protocol::Wss(Cow::Borrowed(str::from_utf8(data)?)), rest))
310 }
311 _ => Err(Error::UnknownProtocolId(id)),
312 }
313 }
314
315 pub fn write_bytes<W: Write>(&self, w: &mut W) -> Result<()> {
318 let mut buf = encode::u32_buffer();
319 match self {
320 Protocol::Ip4(addr) => {
321 w.write_all(encode::u32(IP4, &mut buf))?;
322 w.write_all(&addr.octets())?
323 }
324 Protocol::Ip6(addr) => {
325 w.write_all(encode::u32(IP6, &mut buf))?;
326 for &segment in &addr.segments() {
327 w.write_u16::<BigEndian>(segment)?
328 }
329 }
330 Protocol::Tcp(port) => {
331 w.write_all(encode::u32(TCP, &mut buf))?;
332 w.write_u16::<BigEndian>(*port)?
333 }
334 Protocol::Tls => w.write_all(encode::u32(TLS, &mut buf))?,
335 Protocol::Noise => w.write_all(encode::u32(NOISE, &mut buf))?,
336 Protocol::Udp(port) => {
337 w.write_all(encode::u32(UDP, &mut buf))?;
338 w.write_u16::<BigEndian>(*port)?
339 }
340 Protocol::Dccp(port) => {
341 w.write_all(encode::u32(DCCP, &mut buf))?;
342 w.write_u16::<BigEndian>(*port)?
343 }
344 Protocol::Sctp(port) => {
345 w.write_all(encode::u32(SCTP, &mut buf))?;
346 w.write_u16::<BigEndian>(*port)?
347 }
348 Protocol::Dns(s) => {
349 w.write_all(encode::u32(DNS, &mut buf))?;
350 let bytes = s.as_bytes();
351 w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
352 w.write_all(bytes)?
353 }
354 Protocol::Dns4(s) => {
355 w.write_all(encode::u32(DNS4, &mut buf))?;
356 let bytes = s.as_bytes();
357 w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
358 w.write_all(bytes)?
359 }
360 Protocol::Dns6(s) => {
361 w.write_all(encode::u32(DNS6, &mut buf))?;
362 let bytes = s.as_bytes();
363 w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
364 w.write_all(bytes)?
365 }
366 Protocol::Dnsaddr(s) => {
367 w.write_all(encode::u32(DNSADDR, &mut buf))?;
368 let bytes = s.as_bytes();
369 w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
370 w.write_all(bytes)?
371 }
372 Protocol::Unix(s) => {
373 w.write_all(encode::u32(UNIX, &mut buf))?;
374 let bytes = s.as_bytes();
375 w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
376 w.write_all(bytes)?
377 }
378 Protocol::P2p(node_id) => {
379 w.write_all(encode::u32(P2P, &mut buf))?;
380 w.write_u32::<BigEndian>(*node_id)?
381 }
382 Protocol::Quic => w.write_all(encode::u32(QUIC, &mut buf))?,
383 Protocol::QuicV1 => w.write_all(encode::u32(QUIC_V1, &mut buf))?,
384 Protocol::Utp => w.write_all(encode::u32(UTP, &mut buf))?,
385 Protocol::Udt => w.write_all(encode::u32(UDT, &mut buf))?,
386 Protocol::Http => w.write_all(encode::u32(HTTP, &mut buf))?,
387 Protocol::Https => w.write_all(encode::u32(HTTPS, &mut buf))?,
388 Protocol::WebTransport => w.write_all(encode::u32(WEBTRANSPORT, &mut buf))?,
389 Protocol::Ws(ref s) if s == "/" => w.write_all(encode::u32(WS, &mut buf))?,
390 Protocol::Ws(s) => {
391 w.write_all(encode::u32(WS_WITH_PATH, &mut buf))?;
392 let bytes = s.as_bytes();
393 w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
394 w.write_all(bytes)?
395 }
396 Protocol::Wss(ref s) if s == "/" => w.write_all(encode::u32(WSS, &mut buf))?,
397 Protocol::Wss(s) => {
398 w.write_all(encode::u32(WSS_WITH_PATH, &mut buf))?;
399 let bytes = s.as_bytes();
400 w.write_all(encode::usize(bytes.len(), &mut encode::usize_buffer()))?;
401 w.write_all(bytes)?
402 }
403 Protocol::P2pWebSocketStar => w.write_all(encode::u32(P2P_WEBSOCKET_STAR, &mut buf))?,
404 Protocol::P2pWebRtcStar => w.write_all(encode::u32(P2P_WEBRTC_STAR, &mut buf))?,
405 Protocol::WebRTCDirect => w.write_all(encode::u32(WEBRTC_DIRECT, &mut buf))?,
406 Protocol::P2pWebRtcDirect => w.write_all(encode::u32(P2P_WEBRTC_DIRECT, &mut buf))?,
407 Protocol::P2pCircuit => w.write_all(encode::u32(P2P_CIRCUIT, &mut buf))?,
408 Protocol::Memory(port) => {
409 w.write_all(encode::u32(MEMORY, &mut buf))?;
410 w.write_u64::<BigEndian>(*port)?
411 }
412 }
413 Ok(())
414 }
415
416 pub fn acquire<'b>(self) -> Protocol<'b> {
418 use self::Protocol::*;
419 match self {
420 Dccp(a) => Dccp(a),
421 Dns(cow) => Dns(Cow::Owned(cow.into_owned())),
422 Dns4(cow) => Dns4(Cow::Owned(cow.into_owned())),
423 Dns6(cow) => Dns6(Cow::Owned(cow.into_owned())),
424 Dnsaddr(cow) => Dnsaddr(Cow::Owned(cow.into_owned())),
425 Http => Http,
426 Https => Https,
427 Ip4(a) => Ip4(a),
428 Ip6(a) => Ip6(a),
429 P2pWebRtcDirect => P2pWebRtcDirect,
430 P2pWebRtcStar => P2pWebRtcStar,
431 WebRTCDirect => WebRTCDirect,
432 P2pWebSocketStar => P2pWebSocketStar,
433 Memory(a) => Memory(a),
434 P2p(a) => P2p(a),
435 P2pCircuit => P2pCircuit,
436 Quic => Quic,
437 QuicV1 => QuicV1,
438 Sctp(a) => Sctp(a),
439 Tcp(a) => Tcp(a),
440 Tls => Tls,
441 Noise => Noise,
442 Udp(a) => Udp(a),
443 Udt => Udt,
444 Unix(cow) => Unix(Cow::Owned(cow.into_owned())),
445 Utp => Utp,
446 WebTransport => WebTransport,
447 Ws(cow) => Ws(Cow::Owned(cow.into_owned())),
448 Wss(cow) => Wss(Cow::Owned(cow.into_owned())),
449 }
450 }
451
452 pub fn tag(&self) -> &'static str {
453 use self::Protocol::*;
454 match self {
455 Dccp(_) => "dccp",
456 Dns(_) => "dns",
457 Dns4(_) => "dns4",
458 Dns6(_) => "dns6",
459 Dnsaddr(_) => "dnsaddr",
460 Http => "http",
461 Https => "https",
462 Ip4(_) => "ip4",
463 Ip6(_) => "ip6",
464 P2pWebRtcDirect => "p2p-webrtc-direct",
465 P2pWebRtcStar => "p2p-webrtc-star",
466 WebRTCDirect => "webrtc-direct",
467 P2pWebSocketStar => "p2p-websocket-star",
468 Memory(_) => "memory",
469 P2p(_) => "p2p",
470 P2pCircuit => "p2p-circuit",
471 Quic => "quic",
472 QuicV1 => "quic-v1",
473 Sctp(_) => "sctp",
474 Tcp(_) => "tcp",
475 Tls => "tls",
476 Noise => "noise",
477 Udp(_) => "udp",
478 Udt => "udt",
479 Unix(_) => "unix",
480 Utp => "utp",
481 WebTransport => "webtransport",
482 Ws(ref s) if s == "/" => "ws",
483 Ws(_) => "x-parity-ws",
484 Wss(ref s) if s == "/" => "wss",
485 Wss(_) => "x-parity-wss",
486 }
487 }
488}
489
490impl<'a> fmt::Display for Protocol<'a> {
491 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
492 use self::Protocol::*;
493 write!(f, "/{}", self.tag())?;
494 match self {
495 Dccp(port) => write!(f, "/{port}"),
496 Dns(s) => write!(f, "/{s}"),
497 Dns4(s) => write!(f, "/{s}"),
498 Dns6(s) => write!(f, "/{s}"),
499 Dnsaddr(s) => write!(f, "/{s}"),
500 Ip4(addr) => write!(f, "/{addr}"),
501 Ip6(addr) => write!(f, "/{addr}"),
502 Memory(port) => write!(f, "/{port}"),
503 P2p(node_id) => write!(f, "/{node_id}"),
504 Sctp(port) => write!(f, "/{port}"),
505 Tcp(port) => write!(f, "/{port}"),
506 Udp(port) => write!(f, "/{port}"),
507 Unix(s) => write!(f, "/{s}"),
508 Ws(s) if s != "/" => {
509 let encoded = percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
510 write!(f, "/{encoded}")
511 }
512 Wss(s) if s != "/" => {
513 let encoded = percent_encoding::percent_encode(s.as_bytes(), PATH_SEGMENT_ENCODE_SET);
514 write!(f, "/{encoded}")
515 }
516 _ => Ok(()),
517 }
518 }
519}
520
521impl<'a> From<IpAddr> for Protocol<'a> {
522 #[inline]
523 fn from(addr: IpAddr) -> Self {
524 match addr {
525 IpAddr::V4(addr) => Protocol::Ip4(addr),
526 IpAddr::V6(addr) => Protocol::Ip6(addr),
527 }
528 }
529}
530
531impl<'a> From<Ipv4Addr> for Protocol<'a> {
532 #[inline]
533 fn from(addr: Ipv4Addr) -> Self {
534 Protocol::Ip4(addr)
535 }
536}
537
538impl<'a> From<Ipv6Addr> for Protocol<'a> {
539 #[inline]
540 fn from(addr: Ipv6Addr) -> Self {
541 Protocol::Ip6(addr)
542 }
543}
544
545#[allow(unused_macros)]
546macro_rules! read_onion_impl {
547 ($name:ident, $len:expr, $encoded_len:expr) => {
548 fn $name(s: &str) -> Result<([u8; $len], u16)> {
549 let mut parts = s.split(':');
550
551 let b32 = parts.next().ok_or(Error::InvalidMultiaddr)?;
553 if b32.len() != $encoded_len {
554 return Err(Error::InvalidMultiaddr);
555 }
556
557 let port = parts.next().ok_or(Error::InvalidMultiaddr).and_then(|p| str::parse(p).map_err(From::from))?;
559
560 if port == 0 {
562 return Err(Error::InvalidMultiaddr);
563 }
564
565 if parts.next().is_some() {
567 return Err(Error::InvalidMultiaddr);
568 }
569
570 if $len != BASE32.decode_len(b32.len()).map_err(|_| Error::InvalidMultiaddr)? {
571 return Err(Error::InvalidMultiaddr);
572 }
573
574 let mut buf = [0u8; $len];
575 BASE32.decode_mut(b32.as_bytes(), &mut buf).map_err(|_| Error::InvalidMultiaddr)?;
576
577 Ok((buf, port))
578 }
579 };
580}