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// The field of `Self::Resolving` is `Unpin`, and the field of `Self::Ready` is never pinned.
72impl<I> Unpin for ToSocketAddrsFuture<I> {}
73
74/// Wrap `std::io::Error` with additional message
75///
76/// Keeps the original error kind and stores the original I/O error as `source`.
77impl<T> ErrorContext for ToSocketAddrsFuture<T> {
78    fn context(self, message: impl Fn() -> String) -> Self {
79        match self {
80            ToSocketAddrsFuture::Ready(res) => ToSocketAddrsFuture::Ready(res.context(message)),
81            x => x,
82        }
83    }
84}
85
86impl<I: Iterator<Item = SocketAddr>> Future for ToSocketAddrsFuture<I> {
87    type Output = io::Result<I>;
88
89    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
90        let this = self.get_mut();
91        let state = mem::replace(this, ToSocketAddrsFuture::Done);
92
93        match state {
94            ToSocketAddrsFuture::Resolving(mut task) => {
95                let poll = Pin::new(&mut task).poll(cx);
96                if poll.is_pending() {
97                    *this = ToSocketAddrsFuture::Resolving(task);
98                }
99                poll
100            }
101            ToSocketAddrsFuture::Ready(res) => Poll::Ready(res),
102            ToSocketAddrsFuture::Done => panic!("polled a completed future"),
103        }
104    }
105}
106
107impl ToSocketAddrs for SocketAddr {
108    type Iter = std::option::IntoIter<SocketAddr>;
109
110    fn to_socket_addrs(
111        &self,
112    ) -> ret!(
113        impl Future<Output = Self::Iter>,
114        ToSocketAddrsFuture<Self::Iter>
115    ) {
116        ToSocketAddrsFuture::Ready(Ok(Some(*self).into_iter()))
117    }
118}
119
120impl ToSocketAddrs for SocketAddrV4 {
121    type Iter = std::option::IntoIter<SocketAddr>;
122
123    fn to_socket_addrs(
124        &self,
125    ) -> ret!(
126        impl Future<Output = Self::Iter>,
127        ToSocketAddrsFuture<Self::Iter>
128    ) {
129        SocketAddr::V4(*self)
130            .to_socket_addrs()
131            .context(|| format!("could not resolve address `{}`", self))
132    }
133}
134
135impl ToSocketAddrs for SocketAddrV6 {
136    type Iter = std::option::IntoIter<SocketAddr>;
137
138    fn to_socket_addrs(
139        &self,
140    ) -> ret!(
141        impl Future<Output = Self::Iter>,
142        ToSocketAddrsFuture<Self::Iter>
143    ) {
144        SocketAddr::V6(*self)
145            .to_socket_addrs()
146            .context(|| format!("could not resolve address `{}`", self))
147    }
148}
149
150impl ToSocketAddrs for (IpAddr, u16) {
151    type Iter = std::option::IntoIter<SocketAddr>;
152
153    fn to_socket_addrs(
154        &self,
155    ) -> ret!(
156        impl Future<Output = Self::Iter>,
157        ToSocketAddrsFuture<Self::Iter>
158    ) {
159        let (ip, port) = *self;
160        match ip {
161            IpAddr::V4(a) => (a, port).to_socket_addrs(),
162            IpAddr::V6(a) => (a, port).to_socket_addrs(),
163        }
164    }
165}
166
167impl ToSocketAddrs for (Ipv4Addr, u16) {
168    type Iter = std::option::IntoIter<SocketAddr>;
169
170    fn to_socket_addrs(
171        &self,
172    ) -> ret!(
173        impl Future<Output = Self::Iter>,
174        ToSocketAddrsFuture<Self::Iter>
175    ) {
176        let (ip, port) = *self;
177        SocketAddrV4::new(ip, port).to_socket_addrs()
178    }
179}
180
181impl ToSocketAddrs for (Ipv6Addr, u16) {
182    type Iter = std::option::IntoIter<SocketAddr>;
183
184    fn to_socket_addrs(
185        &self,
186    ) -> ret!(
187        impl Future<Output = Self::Iter>,
188        ToSocketAddrsFuture<Self::Iter>
189    ) {
190        let (ip, port) = *self;
191        SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs()
192    }
193}
194
195impl ToSocketAddrs for (&str, u16) {
196    type Iter = std::vec::IntoIter<SocketAddr>;
197
198    fn to_socket_addrs(
199        &self,
200    ) -> ret!(
201        impl Future<Output = Self::Iter>,
202        ToSocketAddrsFuture<Self::Iter>
203    ) {
204        let (host, port) = *self;
205
206        if let Ok(addr) = host.parse::<Ipv4Addr>() {
207            let addr = SocketAddrV4::new(addr, port);
208            return ToSocketAddrsFuture::Ready(Ok(vec![SocketAddr::V4(addr)].into_iter()));
209        }
210
211        if let Ok(addr) = host.parse::<Ipv6Addr>() {
212            let addr = SocketAddrV6::new(addr, port, 0, 0);
213            return ToSocketAddrsFuture::Ready(Ok(vec![SocketAddr::V6(addr)].into_iter()));
214        }
215
216        let host = host.to_string();
217        let task = spawn_blocking(move || {
218            let addr = (host.as_str(), port);
219            std::net::ToSocketAddrs::to_socket_addrs(&addr)
220                .context(|| format!("could not resolve address `{:?}`", addr))
221        });
222        ToSocketAddrsFuture::Resolving(task)
223    }
224}
225
226impl ToSocketAddrs for str {
227    type Iter = std::vec::IntoIter<SocketAddr>;
228
229    fn to_socket_addrs(
230        &self,
231    ) -> ret!(
232        impl Future<Output = Self::Iter>,
233        ToSocketAddrsFuture<Self::Iter>
234    ) {
235        if let Ok(addr) = self.parse() {
236            return ToSocketAddrsFuture::Ready(Ok(vec![addr].into_iter()));
237        }
238
239        let addr = self.to_string();
240        let task = spawn_blocking(move || {
241            std::net::ToSocketAddrs::to_socket_addrs(addr.as_str())
242                .context(|| format!("could not resolve address `{:?}`", addr))
243        });
244        ToSocketAddrsFuture::Resolving(task)
245    }
246}
247
248impl<'a> ToSocketAddrs for &'a [SocketAddr] {
249    type Iter = std::iter::Cloned<std::slice::Iter<'a, SocketAddr>>;
250
251    fn to_socket_addrs(
252        &self,
253    ) -> ret!(
254        impl Future<Output = Self::Iter>,
255        ToSocketAddrsFuture<Self::Iter>
256    ) {
257        ToSocketAddrsFuture::Ready(Ok(self.iter().cloned()))
258    }
259}
260
261impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {
262    type Iter = T::Iter;
263
264    fn to_socket_addrs(
265        &self,
266    ) -> ret!(
267        impl Future<Output = Self::Iter>,
268        ToSocketAddrsFuture<Self::Iter>
269    ) {
270        (**self).to_socket_addrs()
271    }
272}
273
274impl ToSocketAddrs for String {
275    type Iter = std::vec::IntoIter<SocketAddr>;
276
277    fn to_socket_addrs(
278        &self,
279    ) -> ret!(
280        impl Future<Output = Self::Iter>,
281        ToSocketAddrsFuture<Self::Iter>
282    ) {
283        (&**self).to_socket_addrs()
284    }
285}