mysten_network/
multiaddr.rs1use eyre::{eyre, Result};
5use multiaddr::{Multiaddr, Protocol};
6use std::{
7 borrow::Cow,
8 net::{IpAddr, SocketAddr},
9};
10
11pub fn to_socket_addr(addr: &Multiaddr) -> Result<SocketAddr> {
15 let mut iter = addr.iter();
16 let ip = match iter
17 .next()
18 .ok_or_else(|| eyre!("failed to convert to SocketAddr: Multiaddr does not contain IP"))?
19 {
20 Protocol::Ip4(ip4_addr) => IpAddr::V4(ip4_addr),
21 Protocol::Ip6(ip6_addr) => IpAddr::V6(ip6_addr),
22 unsupported => return Err(eyre!("unsupported protocol {unsupported}")),
23 };
24 let tcp_port = parse_tcp(&mut iter)?;
25 Ok(SocketAddr::new(ip, tcp_port))
26}
27
28pub(crate) fn parse_tcp<'a, T: Iterator<Item = Protocol<'a>>>(protocols: &mut T) -> Result<u16> {
29 if let Protocol::Tcp(port) = protocols
30 .next()
31 .ok_or_else(|| eyre!("unexpected end of multiaddr"))?
32 {
33 Ok(port)
34 } else {
35 Err(eyre!("expected tcp protocol"))
36 }
37}
38
39pub(crate) fn parse_http_https<'a, T: Iterator<Item = Protocol<'a>>>(
40 protocols: &mut T,
41) -> Result<&'static str> {
42 match protocols
43 .next()
44 .ok_or_else(|| eyre!("unexpected end of multiaddr"))?
45 {
46 Protocol::Http => Ok("http"),
47 Protocol::Https => Ok("https"),
48 _ => Err(eyre!("expected http/https protocol")),
49 }
50}
51
52pub(crate) fn parse_end<'a, T: Iterator<Item = Protocol<'a>>>(protocols: &mut T) -> Result<()> {
53 if protocols.next().is_none() {
54 Ok(())
55 } else {
56 Err(eyre!("expected end of multiaddr"))
57 }
58}
59
60pub(crate) fn parse_dns(address: &Multiaddr) -> Result<(Cow<'_, str>, u16, &'static str)> {
62 let mut iter = address.iter();
63
64 let dns_name = match iter
65 .next()
66 .ok_or_else(|| eyre!("unexpected end of multiaddr"))?
67 {
68 Protocol::Dns(dns_name) => dns_name,
69 other => return Err(eyre!("expected dns found {other}")),
70 };
71 let tcp_port = parse_tcp(&mut iter)?;
72 let http_or_https = parse_http_https(&mut iter)?;
73 parse_end(&mut iter)?;
74 Ok((dns_name, tcp_port, http_or_https))
75}
76
77pub(crate) fn parse_ip4(address: &Multiaddr) -> Result<(SocketAddr, &'static str)> {
79 let mut iter = address.iter();
80
81 let ip_addr = match iter
82 .next()
83 .ok_or_else(|| eyre!("unexpected end of multiaddr"))?
84 {
85 Protocol::Ip4(ip4_addr) => IpAddr::V4(ip4_addr),
86 other => return Err(eyre!("expected ip4 found {other}")),
87 };
88 let tcp_port = parse_tcp(&mut iter)?;
89 let http_or_https = parse_http_https(&mut iter)?;
90 parse_end(&mut iter)?;
91 let socket_addr = SocketAddr::new(ip_addr, tcp_port);
92
93 Ok((socket_addr, http_or_https))
94}
95
96pub(crate) fn parse_ip6(address: &Multiaddr) -> Result<(SocketAddr, &'static str)> {
98 let mut iter = address.iter();
99
100 let ip_addr = match iter
101 .next()
102 .ok_or_else(|| eyre!("unexpected end of multiaddr"))?
103 {
104 Protocol::Ip6(ip6_addr) => IpAddr::V6(ip6_addr),
105 other => return Err(eyre!("expected ip6 found {other}")),
106 };
107 let tcp_port = parse_tcp(&mut iter)?;
108 let http_or_https = parse_http_https(&mut iter)?;
109 parse_end(&mut iter)?;
110 let socket_addr = SocketAddr::new(ip_addr, tcp_port);
111
112 Ok((socket_addr, http_or_https))
113}
114
115#[cfg(unix)]
117pub(crate) fn parse_unix(address: &Multiaddr) -> Result<(Cow<'_, str>, &'static str)> {
118 let mut iter = address.iter();
119
120 let path = match iter
121 .next()
122 .ok_or_else(|| eyre!("unexpected end of multiaddr"))?
123 {
124 Protocol::Unix(path) => path,
125 other => return Err(eyre!("expected unix found {other}")),
126 };
127 let http_or_https = parse_http_https(&mut iter)?;
128 parse_end(&mut iter)?;
129
130 Ok((path, http_or_https))
131}
132
133#[cfg(test)]
134mod test {
135 use super::to_socket_addr;
136 use multiaddr::multiaddr;
137
138 #[test]
139 fn test_to_socket_addr_basic() {
140 let multi_addr_ipv4 = multiaddr!(Ip4([127, 0, 0, 1]), Tcp(10500u16));
141 let socket_addr_ipv4 =
142 to_socket_addr(&multi_addr_ipv4).expect("Couldn't convert to socket addr");
143 assert_eq!(socket_addr_ipv4.to_string(), "127.0.0.1:10500");
144
145 let multi_addr_ipv6 = multiaddr!(Ip6([172, 0, 0, 1, 1, 1, 1, 1]), Tcp(10500u16));
146 let socket_addr_ipv6 =
147 to_socket_addr(&multi_addr_ipv6).expect("Couldn't convert to socket addr");
148 assert_eq!(socket_addr_ipv6.to_string(), "[ac::1:1:1:1:1]:10500");
149 }
150
151 #[test]
152 fn test_to_socket_addr_unsupported_protocol() {
153 let multi_addr_dns = multiaddr!(Dnsaddr("mysten.sui"), Tcp(10500u16));
154 let _ = to_socket_addr(&multi_addr_dns).expect_err("DNS is unsupported");
155 }
156}