axstd/net/
socket_addr.rs

1extern crate alloc;
2
3use crate::io;
4use alloc::string::String;
5use core::{iter, option, slice};
6
7pub use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
8
9/// A trait for objects which can be converted or resolved to one or more
10/// [`SocketAddr`] values.
11///
12/// This trait is used for generic address resolution when constructing network
13/// objects. By default it is implemented for the following types:
14///
15///  * [`SocketAddr`]: [`to_socket_addrs`] is the identity function.
16///
17///  * [`SocketAddrV4`], <code>([IpAddr], [u16])</code>,
18///    <code>([Ipv4Addr], [u16])</code>:
19///    [`to_socket_addrs`] constructs a [`SocketAddr`] trivially.
20///
21///  * <code>(&[str], [u16])</code>: <code>&[str]</code> should be either a string representation
22///    of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host
23///    name. [`u16`] is the port number.
24///
25///  * <code>&[str]</code>: the string should be either a string representation of a
26///    [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like
27///    `<host_name>:<port>` pair where `<port>` is a [`u16`] value.
28///
29/// [`FromStr`]: core::str::FromStr
30/// [`to_socket_addrs`]: ToSocketAddrs::to_socket_addrs
31pub trait ToSocketAddrs {
32    /// Returned iterator over socket addresses which this type may correspond to.
33    type Iter: Iterator<Item = SocketAddr>;
34
35    /// Converts this object to an iterator of resolved [`SocketAddr`]s.
36    fn to_socket_addrs(&self) -> io::Result<Self::Iter>;
37}
38
39impl ToSocketAddrs for SocketAddr {
40    type Iter = option::IntoIter<SocketAddr>;
41    fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
42        Ok(Some(*self).into_iter())
43    }
44}
45
46impl ToSocketAddrs for SocketAddrV4 {
47    type Iter = option::IntoIter<SocketAddr>;
48    fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
49        SocketAddr::V4(*self).to_socket_addrs()
50    }
51}
52
53impl ToSocketAddrs for (IpAddr, u16) {
54    type Iter = option::IntoIter<SocketAddr>;
55    fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
56        let (ip, port) = *self;
57        SocketAddr::new(ip, port).to_socket_addrs()
58    }
59}
60
61impl ToSocketAddrs for (Ipv4Addr, u16) {
62    type Iter = option::IntoIter<SocketAddr>;
63    fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
64        let (ip, port) = *self;
65        SocketAddrV4::new(ip, port).to_socket_addrs()
66    }
67}
68
69impl<'a> ToSocketAddrs for &'a [SocketAddr] {
70    type Iter = iter::Cloned<slice::Iter<'a, SocketAddr>>;
71
72    fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
73        Ok(self.iter().cloned())
74    }
75}
76
77impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {
78    type Iter = T::Iter;
79    fn to_socket_addrs(&self) -> io::Result<T::Iter> {
80        (**self).to_socket_addrs()
81    }
82}
83
84#[cfg(not(feature = "dns"))]
85#[doc(cfg(feature = "net"))]
86mod no_dns {
87    use super::*;
88
89    impl ToSocketAddrs for (&str, u16) {
90        type Iter = option::IntoIter<SocketAddr>;
91        fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
92            let (host, port) = *self;
93            Ok(host
94                .parse::<Ipv4Addr>()
95                .ok()
96                .map(|addr| {
97                    let addr = SocketAddrV4::new(addr, port);
98                    SocketAddr::V4(addr)
99                })
100                .into_iter())
101        }
102    }
103
104    impl ToSocketAddrs for str {
105        type Iter = option::IntoIter<SocketAddr>;
106        fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
107            // parse as a regular SocketAddr first
108            Ok(self.parse().ok().into_iter())
109        }
110    }
111
112    impl ToSocketAddrs for (String, u16) {
113        type Iter = option::IntoIter<SocketAddr>;
114        fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
115            (&*self.0, self.1).to_socket_addrs()
116        }
117    }
118
119    impl ToSocketAddrs for String {
120        type Iter = option::IntoIter<SocketAddr>;
121        fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
122            (**self).to_socket_addrs()
123        }
124    }
125}
126
127#[cfg(feature = "dns")]
128#[doc(cfg(feature = "net"))]
129mod dns {
130    use super::*;
131    use alloc::{vec, vec::Vec};
132
133    impl ToSocketAddrs for (&str, u16) {
134        type Iter = vec::IntoIter<SocketAddr>;
135        fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
136            let (host, port) = *self;
137
138            // try to parse the host as a regular IP address first
139            if let Ok(addr) = host.parse::<Ipv4Addr>() {
140                let addr = SocketAddrV4::new(addr, port);
141                return Ok(vec![SocketAddr::V4(addr)].into_iter());
142            }
143
144            Ok(arceos_api::net::ax_dns_query(host)?
145                .into_iter()
146                .map(|ip| SocketAddr::new(ip, port))
147                .collect::<Vec<_>>()
148                .into_iter())
149        }
150    }
151
152    impl ToSocketAddrs for str {
153        type Iter = vec::IntoIter<SocketAddr>;
154
155        fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
156            // try to parse as a regular SocketAddr first
157            if let Ok(addr) = self.parse() {
158                return Ok(vec![addr].into_iter());
159            }
160
161            // split the string by ':' and convert the second part to u16
162            let (host, port_str) = self
163                .rsplit_once(':')
164                .ok_or_else(|| axerrno::ax_err_type!(InvalidInput, "invalid socket address"))?;
165            let port: u16 = port_str
166                .parse()
167                .map_err(|_| axerrno::ax_err_type!(InvalidInput, "invalid port value"))?;
168
169            Ok(arceos_api::net::ax_dns_query(host)?
170                .into_iter()
171                .map(|ip| SocketAddr::new(ip, port))
172                .collect::<Vec<_>>()
173                .into_iter())
174        }
175    }
176
177    impl ToSocketAddrs for (String, u16) {
178        type Iter = vec::IntoIter<SocketAddr>;
179        fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
180            (&*self.0, self.1).to_socket_addrs()
181        }
182    }
183
184    impl ToSocketAddrs for String {
185        type Iter = vec::IntoIter<SocketAddr>;
186        fn to_socket_addrs(&self) -> io::Result<vec::IntoIter<SocketAddr>> {
187            (**self).to_socket_addrs()
188        }
189    }
190}