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; pub const WSS: u32 = 478;
45pub const WSS_WITH_PATH: u32 = 4780; const 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#[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 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 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_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 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 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 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 let b32 = parts.next().ok_or(Error::InvalidMultiaddr)?;
603 if b32.len() != $encoded_len {
604 return Err(Error::InvalidMultiaddr);
605 }
606
607 let port = parts
609 .next()
610 .ok_or(Error::InvalidMultiaddr)
611 .and_then(|p| str::parse(p).map_err(From::from))?;
612
613 if port == 0 {
615 return Err(Error::InvalidMultiaddr);
616 }
617
618 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
637read_onion_impl!(read_onion, 10, 16);
641read_onion_impl!(read_onion3, 35, 56);