1 | use std::future::Future; |
2 | use std::mem; |
3 | use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
4 | use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; |
5 | use std::pin::Pin; |
6 | |
7 | use crate::io; |
8 | use crate::task::{spawn_blocking, Context, JoinHandle, Poll}; |
9 | use crate::utils::Context as ErrorContext; |
10 | |
11 | cfg_not_docs! { |
12 | macro_rules! ret { |
13 | (impl Future<Output = $out:ty>, $fut:ty) => ($fut); |
14 | } |
15 | } |
16 | |
17 | cfg_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 | /// ``` |
45 | pub 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)] |
65 | pub 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. |
72 | impl<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`. |
77 | impl<T> ErrorContext for ToSocketAddrsFuture<T> { |
78 | fn context(self, message: impl Fn() -> String) -> Self { |
79 | match self { |
80 | ToSocketAddrsFuture::Ready(res: Result) => ToSocketAddrsFuture::Ready(res.context(message)), |
81 | x: ToSocketAddrsFuture => x, |
82 | } |
83 | } |
84 | } |
85 | |
86 | impl<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: &mut ToSocketAddrsFuture = self.get_mut(); |
91 | let state: ToSocketAddrsFuture = mem::replace(dest:this, src:ToSocketAddrsFuture::Done); |
92 | |
93 | match state { |
94 | ToSocketAddrsFuture::Resolving(mut task: JoinHandle>) => { |
95 | let poll: 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: Result) => Poll::Ready(res), |
102 | ToSocketAddrsFuture::Done => panic!("polled a completed future" ), |
103 | } |
104 | } |
105 | } |
106 | |
107 | impl 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 | |
120 | impl 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 | |
135 | impl 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 | |
150 | impl 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: IpAddr, port: u16) = *self; |
160 | match ip { |
161 | IpAddr::V4(a: Ipv4Addr) => (a, port).to_socket_addrs(), |
162 | IpAddr::V6(a: Ipv6Addr) => (a, port).to_socket_addrs(), |
163 | } |
164 | } |
165 | } |
166 | |
167 | impl 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: Ipv4Addr, port: u16) = *self; |
177 | SocketAddrV4::new(ip, port).to_socket_addrs() |
178 | } |
179 | } |
180 | |
181 | impl 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: Ipv6Addr, port: u16) = *self; |
191 | SocketAddrV6::new(ip, port, flowinfo:0, scope_id:0).to_socket_addrs() |
192 | } |
193 | } |
194 | |
195 | impl 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 | |
226 | impl 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: SocketAddr) = self.parse() { |
236 | return ToSocketAddrsFuture::Ready(Ok(vec![addr].into_iter())); |
237 | } |
238 | |
239 | let addr: String = self.to_string(); |
240 | let task: JoinHandle, …>> = 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 | |
248 | impl<'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 | |
261 | impl<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 | |
274 | impl 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 | } |
286 | |