libp2p_webrtc_utils/
transport.rs1use std::net::{IpAddr, SocketAddr};
2
3use libp2p_core::{multiaddr::Protocol, Multiaddr};
4
5use crate::fingerprint::Fingerprint;
6
7pub fn parse_webrtc_dial_addr(addr: &Multiaddr) -> Option<(SocketAddr, Fingerprint)> {
9 let mut iter = addr.iter();
10
11 let ip = match iter.next()? {
12 Protocol::Ip4(ip) => IpAddr::from(ip),
13 Protocol::Ip6(ip) => IpAddr::from(ip),
14 _ => return None,
15 };
16
17 let port = iter.next()?;
18 let webrtc = iter.next()?;
19 let certhash = iter.next()?;
20
21 let (port, fingerprint) = match (port, webrtc, certhash) {
22 (Protocol::Udp(port), Protocol::WebRTCDirect, Protocol::Certhash(cert_hash)) => {
23 let fingerprint = Fingerprint::try_from_multihash(cert_hash)?;
24
25 (port, fingerprint)
26 }
27 _ => return None,
28 };
29
30 match iter.next() {
31 Some(Protocol::P2p(_)) => {}
32 None => {}
34 Some(_) => return None,
36 }
37
38 Some((SocketAddr::new(ip, port), fingerprint))
39}
40
41#[cfg(test)]
42mod tests {
43 use std::net::{Ipv4Addr, Ipv6Addr};
44
45 use super::*;
46
47 #[test]
48 fn parse_valid_address_with_certhash_and_p2p() {
49 let addr = "/ip4/127.0.0.1/udp/39901/webrtc-direct/certhash/uEiDikp5KVUgkLta1EjUN-IKbHk-dUBg8VzKgf5nXxLK46w/p2p/12D3KooWNpDk9w6WrEEcdsEH1y47W71S36yFjw4sd3j7omzgCSMS"
50 .parse()
51 .unwrap();
52
53 let maybe_parsed = parse_webrtc_dial_addr(&addr);
54
55 assert_eq!(
56 maybe_parsed,
57 Some((
58 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 39901),
59 Fingerprint::raw(hex_literal::hex!(
60 "e2929e4a5548242ed6b512350df8829b1e4f9d50183c5732a07f99d7c4b2b8eb"
61 ))
62 ))
63 );
64 }
65
66 #[test]
67 fn peer_id_is_not_required() {
68 let addr = "/ip4/127.0.0.1/udp/39901/webrtc-direct/certhash/uEiDikp5KVUgkLta1EjUN-IKbHk-dUBg8VzKgf5nXxLK46w"
69 .parse()
70 .unwrap();
71
72 let maybe_parsed = parse_webrtc_dial_addr(&addr);
73
74 assert_eq!(
75 maybe_parsed,
76 Some((
77 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 39901),
78 Fingerprint::raw(hex_literal::hex!(
79 "e2929e4a5548242ed6b512350df8829b1e4f9d50183c5732a07f99d7c4b2b8eb"
80 ))
81 ))
82 );
83 }
84
85 #[test]
86 fn parse_ipv6() {
87 let addr =
88 "/ip6/::1/udp/12345/webrtc-direct/certhash/uEiDikp5KVUgkLta1EjUN-IKbHk-dUBg8VzKgf5nXxLK46w/p2p/12D3KooWNpDk9w6WrEEcdsEH1y47W71S36yFjw4sd3j7omzgCSMS"
89 .parse()
90 .unwrap();
91
92 let maybe_parsed = parse_webrtc_dial_addr(&addr);
93
94 assert_eq!(
95 maybe_parsed,
96 Some((
97 SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), 12345),
98 Fingerprint::raw(hex_literal::hex!(
99 "e2929e4a5548242ed6b512350df8829b1e4f9d50183c5732a07f99d7c4b2b8eb"
100 ))
101 ))
102 );
103 }
104}