async_std/net/
addr.rs

1use std::future::Future;
2use std::mem;
3use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
4use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
5use std::pin::Pin;
6
7use crate::io;
8use crate::task::{spawn_blocking, Context, JoinHandle, Poll};
9use crate::utils::Context as ErrorContext;
10
11cfg_not_docs! {
12    macro_rules! ret {
13        (impl Future<Output = $out:ty>, $fut:ty) => ($fut);
14    }
15}
16
17cfg_docs! {
18    #[doc(hidden)]
19    pub struct ImplFuture<T>(std::marker::PhantomData<T>);
20
21    macro_rules! ret {
22        (impl Future<Output = $out:ty>, $fut:ty) => (ImplFuture<$out>);
23    }
24}
25
26/// Converts or resolves addresses to [`SocketAddr`] values.
27///
28/// This trait is an async version of [`std::net::ToSocketAddrs`].
29///
30/// [`std::net::ToSocketAddrs`]: https://doc.rust-lang.org/std/net/trait.ToSocketAddrs.html
31/// [`SocketAddr`]: enum.SocketAddr.html
32///
33/// # Examples
34///
35/// ```
36/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
37/// #
38/// use async_std::net::ToSocketAddrs;
39///
40/// let addr = "localhost:8080".to_socket_addrs().await?.next().unwrap();
41/// println!("resolved: {:?}", addr);
42/// #
43/// # Ok(()) }) }
44/// ```
45pub trait ToSocketAddrs {
46    /// Returned iterator over socket addresses which this type may correspond to.
47    type Iter: Iterator<Item = SocketAddr>;
48
49    /// Converts this object to an iterator of resolved `SocketAddr`s.
50    ///
51    /// The returned iterator may not actually yield any values depending on the outcome of any
52    /// resolution performed.
53    ///
54    /// Note that this function may block a backend thread while resolution is performed.
55    fn to_socket_addrs(
56        &self,
57    ) -> ret!(
58        impl Future<Output = Self::Iter>,
59        ToSocketAddrsFuture<Self::Iter>
60    );
61}
62
63#[doc(hidden)]
64#[allow(missing_debug_implementations)]
65pub enum ToSocketAddrsFuture<I> {
66    Resolving(JoinHandle<io::Result<I>>),
67    Ready(io::Result<I>),
68    Done,
69}
70
71/// Wrap `std::io::Error` with additional message
72///
73/// Keeps the original error kind and stores the original I/O error as `source`.
74impl<T> ErrorContext for ToSocketAddrsFuture<T> {
75    fn context(self, message: impl Fn() -> String) -> Self {
76        match self {
77            ToSocketAddrsFuture::Ready(res) => ToSocketAddrsFuture::Ready(res.context(message)),
78            x => x,
79        }
80    }
81}
82
83impl<I: Iterator<Item = SocketAddr>> Future for ToSocketAddrsFuture<I> {
84    type Output = io::Result<I>;
85
86    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
87        let this = unsafe { self.get_unchecked_mut() };
88        let state = mem::replace(this, ToSocketAddrsFuture::Done);
89
90        match state {
91            ToSocketAddrsFuture::Resolving(mut task) => {
92                let poll = Pin::new(&mut task).poll(cx)?;
93                if poll.is_pending() {
94                    *this = ToSocketAddrsFuture::Resolving(task);
95                }
96                poll
97            }
98            ToSocketAddrsFuture::Ready(res) => Poll::Ready(res),
99            ToSocketAddrsFuture::Done => panic!("polled a completed future"),
100        }
101    }
102}
103
104impl ToSocketAddrs for SocketAddr {
105    type Iter = std::option::IntoIter<SocketAddr>;
106
107    fn to_socket_addrs(
108        &self,
109    ) -> ret!(
110        impl Future<Output = Self::Iter>,
111        ToSocketAddrsFuture<Self::Iter>
112    ) {
113        ToSocketAddrsFuture::Ready(Ok(Some(*self).into_iter()))
114    }
115}
116
117impl ToSocketAddrs for SocketAddrV4 {
118    type Iter = std::option::IntoIter<SocketAddr>;
119
120    fn to_socket_addrs(
121        &self,
122    ) -> ret!(
123        impl Future<Output = Self::Iter>,
124        ToSocketAddrsFuture<Self::Iter>
125    ) {
126        SocketAddr::V4(*self)
127            .to_socket_addrs()
128            .context(|| format!("could not resolve address `{}`", self))
129    }
130}
131
132impl ToSocketAddrs for SocketAddrV6 {
133    type Iter = std::option::IntoIter<SocketAddr>;
134
135    fn to_socket_addrs(
136        &self,
137    ) -> ret!(
138        impl Future<Output = Self::Iter>,
139        ToSocketAddrsFuture<Self::Iter>
140    ) {
141        SocketAddr::V6(*self)
142            .to_socket_addrs()
143            .context(|| format!("could not resolve address `{}`", self))
144    }
145}
146
147impl ToSocketAddrs for (IpAddr, u16) {
148    type Iter = std::option::IntoIter<SocketAddr>;
149
150    fn to_socket_addrs(
151        &self,
152    ) -> ret!(
153        impl Future<Output = Self::Iter>,
154        ToSocketAddrsFuture<Self::Iter>
155    ) {
156        let (ip, port) = *self;
157        match ip {
158            IpAddr::V4(a) => (a, port).to_socket_addrs(),
159            IpAddr::V6(a) => (a, port).to_socket_addrs(),
160        }
161    }
162}
163
164impl ToSocketAddrs for (Ipv4Addr, u16) {
165    type Iter = std::option::IntoIter<SocketAddr>;
166
167    fn to_socket_addrs(
168        &self,
169    ) -> ret!(
170        impl Future<Output = Self::Iter>,
171        ToSocketAddrsFuture<Self::Iter>
172    ) {
173        let (ip, port) = *self;
174        SocketAddrV4::new(ip, port).to_socket_addrs()
175    }
176}
177
178impl ToSocketAddrs for (Ipv6Addr, u16) {
179    type Iter = std::option::IntoIter<SocketAddr>;
180
181    fn to_socket_addrs(
182        &self,
183    ) -> ret!(
184        impl Future<Output = Self::Iter>,
185        ToSocketAddrsFuture<Self::Iter>
186    ) {
187        let (ip, port) = *self;
188        SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs()
189    }
190}
191
192impl ToSocketAddrs for (&str, u16) {
193    type Iter = std::vec::IntoIter<SocketAddr>;
194
195    fn to_socket_addrs(
196        &self,
197    ) -> ret!(
198        impl Future<Output = Self::Iter>,
199        ToSocketAddrsFuture<Self::Iter>
200    ) {
201        let (host, port) = *self;
202
203        if let Ok(addr) = host.parse::<Ipv4Addr>() {
204            let addr = SocketAddrV4::new(addr, port);
205            return ToSocketAddrsFuture::Ready(Ok(vec![SocketAddr::V4(addr)].into_iter()));
206        }
207
208        if let Ok(addr) = host.parse::<Ipv6Addr>() {
209            let addr = SocketAddrV6::new(addr, port, 0, 0);
210            return ToSocketAddrsFuture::Ready(Ok(vec![SocketAddr::V6(addr)].into_iter()));
211        }
212
213        let host = host.to_string();
214        let task = spawn_blocking(move || {
215            let addr = (host.as_str(), port);
216            std::net::ToSocketAddrs::to_socket_addrs(&addr)
217                .context(|| format!("could not resolve address `{:?}`", addr))
218        });
219        ToSocketAddrsFuture::Resolving(task)
220    }
221}
222
223impl ToSocketAddrs for str {
224    type Iter = std::vec::IntoIter<SocketAddr>;
225
226    fn to_socket_addrs(
227        &self,
228    ) -> ret!(
229        impl Future<Output = Self::Iter>,
230        ToSocketAddrsFuture<Self::Iter>
231    ) {
232        if let Ok(addr) = self.parse() {
233            return ToSocketAddrsFuture::Ready(Ok(vec![addr].into_iter()));
234        }
235
236        let addr = self.to_string();
237        let task = spawn_blocking(move || {
238            std::net::ToSocketAddrs::to_socket_addrs(addr.as_str())
239                .context(|| format!("could not resolve address `{:?}`", addr))
240        });
241        ToSocketAddrsFuture::Resolving(task)
242    }
243}
244
245impl<'a> ToSocketAddrs for &'a [SocketAddr] {
246    type Iter = std::iter::Cloned<std::slice::Iter<'a, SocketAddr>>;
247
248    fn to_socket_addrs(
249        &self,
250    ) -> ret!(
251        impl Future<Output = Self::Iter>,
252        ToSocketAddrsFuture<Self::Iter>
253    ) {
254        ToSocketAddrsFuture::Ready(Ok(self.iter().cloned()))
255    }
256}
257
258impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {
259    type Iter = T::Iter;
260
261    fn to_socket_addrs(
262        &self,
263    ) -> ret!(
264        impl Future<Output = Self::Iter>,
265        ToSocketAddrsFuture<Self::Iter>
266    ) {
267        (**self).to_socket_addrs()
268    }
269}
270
271impl ToSocketAddrs for String {
272    type Iter = std::vec::IntoIter<SocketAddr>;
273
274    fn to_socket_addrs(
275        &self,
276    ) -> ret!(
277        impl Future<Output = Self::Iter>,
278        ToSocketAddrsFuture<Self::Iter>
279    ) {
280        (&**self).to_socket_addrs()
281    }
282}