hopr_transport_p2p/
utils.rs1use std::net::{Ipv4Addr, ToSocketAddrs};
2
3use libp2p::Multiaddr;
4use multiaddr::Protocol;
5
6use crate::errors::{P2PError, Result};
7
8pub fn replace_transport_with_unspecified(ma: &Multiaddr) -> Result<Multiaddr> {
10 let mut out = Multiaddr::empty();
11
12 for proto in ma.iter() {
13 match proto {
14 Protocol::Ip4(_) => out.push(std::net::IpAddr::V4(Ipv4Addr::UNSPECIFIED).into()),
15 Protocol::Ip6(_) => out.push(std::net::IpAddr::V6(std::net::Ipv6Addr::UNSPECIFIED).into()),
16 _ => out.push(proto),
17 }
18 }
19
20 Ok(out)
21}
22
23pub fn resolve_dns_if_any(ma: &Multiaddr) -> Result<Multiaddr> {
25 let mut out = Multiaddr::empty();
26
27 for proto in ma.iter() {
28 match proto {
29 Protocol::Dns4(domain) => {
30 let ip = format!("{domain}:443") .to_socket_addrs()
32 .map_err(|e| P2PError::Multiaddress(e.to_string()))?
33 .filter(|sa| sa.is_ipv4())
34 .collect::<Vec<_>>()
35 .first()
36 .ok_or(P2PError::Multiaddress(format!(
37 "Failed to resolve {domain} to an IPv4 address. Does the DNS entry has an A record?"
38 )))?
39 .ip();
40
41 out.push(ip.into())
42 }
43 Protocol::Dns6(domain) => {
44 let ip = format!("{domain}:443") .to_socket_addrs()
46 .map_err(|e| P2PError::Multiaddress(e.to_string()))?
47 .filter(|sa| sa.is_ipv6())
48 .collect::<Vec<_>>()
49 .first()
50 .ok_or(P2PError::Multiaddress(format!(
51 "Failed to resolve {domain} to an IPv6 address. Does the DNS entry has an AAAA record?"
52 )))?
53 .ip();
54
55 out.push(ip.into())
56 }
57 _ => out.push(proto),
58 }
59 }
60
61 Ok(out)
62}
63
64#[cfg(test)]
65mod tests {
66 use std::str::FromStr;
67
68 use super::*;
69
70 #[test]
71 fn multiaddrs_modification_specific_ipv4_transport_should_be_replacable_with_unspecified() -> anyhow::Result<()> {
72 assert_eq!(
73 replace_transport_with_unspecified(&Multiaddr::from_str("/ip4/33.42.112.22/udp/9090/quic")?),
74 Ok(Multiaddr::from_str("/ip4/0.0.0.0/udp/9090/quic")?)
75 );
76
77 Ok(())
78 }
79
80 #[test]
81 fn multiaddrs_modification_specific_ipv6_transport_should_be_replacable_with_unspecified() -> anyhow::Result<()> {
82 assert_eq!(
83 replace_transport_with_unspecified(&Multiaddr::from_str(
84 "/ip6/82b0:a523:d8c0:1cba:365f:85f6:af3b:e369/udp/9090/quic"
85 )?),
86 Ok(Multiaddr::from_str("/ip6/0:0:0:0:0:0:0:0/udp/9090/quic")?)
87 );
88
89 Ok(())
90 }
91}