broker_tokio/net/
addr.rs

1use crate::future;
2
3use std::io;
4use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
5
6/// Convert or resolve without blocking to one or more `SocketAddr` values.
7///
8/// # DNS
9///
10/// Implementations of `ToSocketAddrs` for string types require a DNS lookup.
11/// These implementations are only provided when Tokio is used with the
12/// **`dns`** feature flag.
13///
14/// # Calling
15///
16/// Currently, this trait is only used as an argument to Tokio functions that
17/// need to reference a target socket address. To perform a `SocketAddr`
18/// conversion directly, use [`lookup_host()`](super::lookup_host()).
19///
20/// This trait is sealed and is intended to be opaque. The details of the trait
21/// will change. Stabilization is pending enhancements to the Rust langague.
22pub trait ToSocketAddrs: sealed::ToSocketAddrsPriv {}
23
24type ReadyFuture<T> = future::Ready<io::Result<T>>;
25
26// ===== impl &impl ToSocketAddrs =====
27
28impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {}
29
30impl<T> sealed::ToSocketAddrsPriv for &T
31where
32    T: sealed::ToSocketAddrsPriv + ?Sized,
33{
34    type Iter = T::Iter;
35    type Future = T::Future;
36
37    fn to_socket_addrs(&self) -> Self::Future {
38        (**self).to_socket_addrs()
39    }
40}
41
42// ===== impl SocketAddr =====
43
44impl ToSocketAddrs for SocketAddr {}
45
46impl sealed::ToSocketAddrsPriv for SocketAddr {
47    type Iter = std::option::IntoIter<SocketAddr>;
48    type Future = ReadyFuture<Self::Iter>;
49
50    fn to_socket_addrs(&self) -> Self::Future {
51        let iter = Some(*self).into_iter();
52        future::ok(iter)
53    }
54}
55
56// ===== impl SocketAddrV4 =====
57
58impl ToSocketAddrs for SocketAddrV4 {}
59
60impl sealed::ToSocketAddrsPriv for SocketAddrV4 {
61    type Iter = std::option::IntoIter<SocketAddr>;
62    type Future = ReadyFuture<Self::Iter>;
63
64    fn to_socket_addrs(&self) -> Self::Future {
65        SocketAddr::V4(*self).to_socket_addrs()
66    }
67}
68
69// ===== impl SocketAddrV6 =====
70
71impl ToSocketAddrs for SocketAddrV6 {}
72
73impl sealed::ToSocketAddrsPriv for SocketAddrV6 {
74    type Iter = std::option::IntoIter<SocketAddr>;
75    type Future = ReadyFuture<Self::Iter>;
76
77    fn to_socket_addrs(&self) -> Self::Future {
78        SocketAddr::V6(*self).to_socket_addrs()
79    }
80}
81
82// ===== impl (IpAddr, u16) =====
83
84impl ToSocketAddrs for (IpAddr, u16) {}
85
86impl sealed::ToSocketAddrsPriv for (IpAddr, u16) {
87    type Iter = std::option::IntoIter<SocketAddr>;
88    type Future = ReadyFuture<Self::Iter>;
89
90    fn to_socket_addrs(&self) -> Self::Future {
91        let iter = Some(SocketAddr::from(*self)).into_iter();
92        future::ok(iter)
93    }
94}
95
96// ===== impl (Ipv4Addr, u16) =====
97
98impl ToSocketAddrs for (Ipv4Addr, u16) {}
99
100impl sealed::ToSocketAddrsPriv for (Ipv4Addr, u16) {
101    type Iter = std::option::IntoIter<SocketAddr>;
102    type Future = ReadyFuture<Self::Iter>;
103
104    fn to_socket_addrs(&self) -> Self::Future {
105        let (ip, port) = *self;
106        SocketAddrV4::new(ip, port).to_socket_addrs()
107    }
108}
109
110// ===== impl (Ipv6Addr, u16) =====
111
112impl ToSocketAddrs for (Ipv6Addr, u16) {}
113
114impl sealed::ToSocketAddrsPriv for (Ipv6Addr, u16) {
115    type Iter = std::option::IntoIter<SocketAddr>;
116    type Future = ReadyFuture<Self::Iter>;
117
118    fn to_socket_addrs(&self) -> Self::Future {
119        let (ip, port) = *self;
120        SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs()
121    }
122}
123
124cfg_dns! {
125    // ===== impl str =====
126
127    impl ToSocketAddrs for str {}
128
129    impl sealed::ToSocketAddrsPriv for str {
130        type Iter = sealed::OneOrMore;
131        type Future = sealed::MaybeReady;
132
133        fn to_socket_addrs(&self) -> Self::Future {
134            use crate::runtime::spawn_blocking;
135            use sealed::MaybeReady;
136
137            // First check if the input parses as a socket address
138            let res: Result<SocketAddr, _> = self.parse();
139
140            if let Ok(addr) = res {
141                return MaybeReady::Ready(Some(addr));
142            }
143
144            // Run DNS lookup on the blocking pool
145            let s = self.to_owned();
146
147            MaybeReady::Blocking(spawn_blocking(move || {
148                std::net::ToSocketAddrs::to_socket_addrs(&s)
149            }))
150        }
151    }
152
153    // ===== impl (&str, u16) =====
154
155    impl ToSocketAddrs for (&str, u16) {}
156
157    impl sealed::ToSocketAddrsPriv for (&str, u16) {
158        type Iter = sealed::OneOrMore;
159        type Future = sealed::MaybeReady;
160
161        fn to_socket_addrs(&self) -> Self::Future {
162            use crate::runtime::spawn_blocking;
163            use sealed::MaybeReady;
164
165            let (host, port) = *self;
166
167            // try to parse the host as a regular IP address first
168            if let Ok(addr) = host.parse::<Ipv4Addr>() {
169                let addr = SocketAddrV4::new(addr, port);
170                let addr = SocketAddr::V4(addr);
171
172                return MaybeReady::Ready(Some(addr));
173            }
174
175            if let Ok(addr) = host.parse::<Ipv6Addr>() {
176                let addr = SocketAddrV6::new(addr, port, 0, 0);
177                let addr = SocketAddr::V6(addr);
178
179                return MaybeReady::Ready(Some(addr));
180            }
181
182            let host = host.to_owned();
183
184            MaybeReady::Blocking(spawn_blocking(move || {
185                std::net::ToSocketAddrs::to_socket_addrs(&(&host[..], port))
186            }))
187        }
188    }
189
190    // ===== impl String =====
191
192    impl ToSocketAddrs for String {}
193
194    impl sealed::ToSocketAddrsPriv for String {
195        type Iter = <str as sealed::ToSocketAddrsPriv>::Iter;
196        type Future = <str as sealed::ToSocketAddrsPriv>::Future;
197
198        fn to_socket_addrs(&self) -> Self::Future {
199            (&self[..]).to_socket_addrs()
200        }
201    }
202}
203
204pub(crate) mod sealed {
205    //! The contents of this trait are intended to remain private and __not__
206    //! part of the `ToSocketAddrs` public API. The details will change over
207    //! time.
208
209    use std::future::Future;
210    use std::io;
211    use std::net::SocketAddr;
212
213    cfg_dns! {
214        use crate::task::JoinHandle;
215
216        use std::option;
217        use std::pin::Pin;
218        use std::task::{Context, Poll};
219        use std::vec;
220    }
221
222    #[doc(hidden)]
223    pub trait ToSocketAddrsPriv {
224        type Iter: Iterator<Item = SocketAddr> + Send + 'static;
225        type Future: Future<Output = io::Result<Self::Iter>> + Send + 'static;
226
227        fn to_socket_addrs(&self) -> Self::Future;
228    }
229
230    cfg_dns! {
231        #[doc(hidden)]
232        #[derive(Debug)]
233        pub enum MaybeReady {
234            Ready(Option<SocketAddr>),
235            Blocking(JoinHandle<io::Result<vec::IntoIter<SocketAddr>>>),
236        }
237
238        #[doc(hidden)]
239        #[derive(Debug)]
240        pub enum OneOrMore {
241            One(option::IntoIter<SocketAddr>),
242            More(vec::IntoIter<SocketAddr>),
243        }
244
245        impl Future for MaybeReady {
246            type Output = io::Result<OneOrMore>;
247
248            fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
249                match *self {
250                    MaybeReady::Ready(ref mut i) => {
251                        let iter = OneOrMore::One(i.take().into_iter());
252                        Poll::Ready(Ok(iter))
253                    }
254                    MaybeReady::Blocking(ref mut rx) => {
255                        let res = ready!(Pin::new(rx).poll(cx))?.map(OneOrMore::More);
256
257                        Poll::Ready(res)
258                    }
259                }
260            }
261        }
262
263        impl Iterator for OneOrMore {
264            type Item = SocketAddr;
265
266            fn next(&mut self) -> Option<Self::Item> {
267                match self {
268                    OneOrMore::One(i) => i.next(),
269                    OneOrMore::More(i) => i.next(),
270                }
271            }
272
273            fn size_hint(&self) -> (usize, Option<usize>) {
274                match self {
275                    OneOrMore::One(i) => i.size_hint(),
276                    OneOrMore::More(i) => i.size_hint(),
277                }
278            }
279        }
280    }
281}