diff options
Diffstat (limited to 'third_party/rust/tokio/src/net/addr.rs')
-rw-r--r-- | third_party/rust/tokio/src/net/addr.rs | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/third_party/rust/tokio/src/net/addr.rs b/third_party/rust/tokio/src/net/addr.rs new file mode 100644 index 0000000000..13f743c962 --- /dev/null +++ b/third_party/rust/tokio/src/net/addr.rs @@ -0,0 +1,318 @@ +use std::future; +use std::io; +use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; + +/// Converts or resolves without blocking to one or more `SocketAddr` values. +/// +/// # DNS +/// +/// Implementations of `ToSocketAddrs` for string types require a DNS lookup. +/// +/// # Calling +/// +/// Currently, this trait is only used as an argument to Tokio functions that +/// need to reference a target socket address. To perform a `SocketAddr` +/// conversion directly, use [`lookup_host()`](super::lookup_host()). +/// +/// This trait is sealed and is intended to be opaque. The details of the trait +/// will change. Stabilization is pending enhancements to the Rust language. +pub trait ToSocketAddrs: sealed::ToSocketAddrsPriv {} + +type ReadyFuture<T> = future::Ready<io::Result<T>>; + +cfg_net! { + pub(crate) fn to_socket_addrs<T>(arg: T) -> T::Future + where + T: ToSocketAddrs, + { + arg.to_socket_addrs(sealed::Internal) + } +} + +// ===== impl &impl ToSocketAddrs ===== + +impl<T: ToSocketAddrs + ?Sized> ToSocketAddrs for &T {} + +impl<T> sealed::ToSocketAddrsPriv for &T +where + T: sealed::ToSocketAddrsPriv + ?Sized, +{ + type Iter = T::Iter; + type Future = T::Future; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + (**self).to_socket_addrs(sealed::Internal) + } +} + +// ===== impl SocketAddr ===== + +impl ToSocketAddrs for SocketAddr {} + +impl sealed::ToSocketAddrsPriv for SocketAddr { + type Iter = std::option::IntoIter<SocketAddr>; + type Future = ReadyFuture<Self::Iter>; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + let iter = Some(*self).into_iter(); + future::ready(Ok(iter)) + } +} + +// ===== impl SocketAddrV4 ===== + +impl ToSocketAddrs for SocketAddrV4 {} + +impl sealed::ToSocketAddrsPriv for SocketAddrV4 { + type Iter = std::option::IntoIter<SocketAddr>; + type Future = ReadyFuture<Self::Iter>; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + SocketAddr::V4(*self).to_socket_addrs(sealed::Internal) + } +} + +// ===== impl SocketAddrV6 ===== + +impl ToSocketAddrs for SocketAddrV6 {} + +impl sealed::ToSocketAddrsPriv for SocketAddrV6 { + type Iter = std::option::IntoIter<SocketAddr>; + type Future = ReadyFuture<Self::Iter>; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + SocketAddr::V6(*self).to_socket_addrs(sealed::Internal) + } +} + +// ===== impl (IpAddr, u16) ===== + +impl ToSocketAddrs for (IpAddr, u16) {} + +impl sealed::ToSocketAddrsPriv for (IpAddr, u16) { + type Iter = std::option::IntoIter<SocketAddr>; + type Future = ReadyFuture<Self::Iter>; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + let iter = Some(SocketAddr::from(*self)).into_iter(); + future::ready(Ok(iter)) + } +} + +// ===== impl (Ipv4Addr, u16) ===== + +impl ToSocketAddrs for (Ipv4Addr, u16) {} + +impl sealed::ToSocketAddrsPriv for (Ipv4Addr, u16) { + type Iter = std::option::IntoIter<SocketAddr>; + type Future = ReadyFuture<Self::Iter>; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + let (ip, port) = *self; + SocketAddrV4::new(ip, port).to_socket_addrs(sealed::Internal) + } +} + +// ===== impl (Ipv6Addr, u16) ===== + +impl ToSocketAddrs for (Ipv6Addr, u16) {} + +impl sealed::ToSocketAddrsPriv for (Ipv6Addr, u16) { + type Iter = std::option::IntoIter<SocketAddr>; + type Future = ReadyFuture<Self::Iter>; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + let (ip, port) = *self; + SocketAddrV6::new(ip, port, 0, 0).to_socket_addrs(sealed::Internal) + } +} + +// ===== impl &[SocketAddr] ===== + +impl ToSocketAddrs for &[SocketAddr] {} + +impl sealed::ToSocketAddrsPriv for &[SocketAddr] { + type Iter = std::vec::IntoIter<SocketAddr>; + type Future = ReadyFuture<Self::Iter>; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + let iter = self.to_vec().into_iter(); + future::ready(Ok(iter)) + } +} + +cfg_net! { + // ===== impl str ===== + + impl ToSocketAddrs for str {} + + impl sealed::ToSocketAddrsPriv for str { + type Iter = sealed::OneOrMore; + type Future = sealed::MaybeReady; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + use crate::blocking::spawn_blocking; + use sealed::MaybeReady; + + // First check if the input parses as a socket address + let res: Result<SocketAddr, _> = self.parse(); + + if let Ok(addr) = res { + return MaybeReady(sealed::State::Ready(Some(addr))); + } + + // Run DNS lookup on the blocking pool + let s = self.to_owned(); + + MaybeReady(sealed::State::Blocking(spawn_blocking(move || { + std::net::ToSocketAddrs::to_socket_addrs(&s) + }))) + } + } + + // ===== impl (&str, u16) ===== + + impl ToSocketAddrs for (&str, u16) {} + + impl sealed::ToSocketAddrsPriv for (&str, u16) { + type Iter = sealed::OneOrMore; + type Future = sealed::MaybeReady; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + use crate::blocking::spawn_blocking; + use sealed::MaybeReady; + + let (host, port) = *self; + + // try to parse the host as a regular IP address first + if let Ok(addr) = host.parse::<Ipv4Addr>() { + let addr = SocketAddrV4::new(addr, port); + let addr = SocketAddr::V4(addr); + + return MaybeReady(sealed::State::Ready(Some(addr))); + } + + if let Ok(addr) = host.parse::<Ipv6Addr>() { + let addr = SocketAddrV6::new(addr, port, 0, 0); + let addr = SocketAddr::V6(addr); + + return MaybeReady(sealed::State::Ready(Some(addr))); + } + + let host = host.to_owned(); + + MaybeReady(sealed::State::Blocking(spawn_blocking(move || { + std::net::ToSocketAddrs::to_socket_addrs(&(&host[..], port)) + }))) + } + } + + // ===== impl (String, u16) ===== + + impl ToSocketAddrs for (String, u16) {} + + impl sealed::ToSocketAddrsPriv for (String, u16) { + type Iter = sealed::OneOrMore; + type Future = sealed::MaybeReady; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + (self.0.as_str(), self.1).to_socket_addrs(sealed::Internal) + } + } + + // ===== impl String ===== + + impl ToSocketAddrs for String {} + + impl sealed::ToSocketAddrsPriv for String { + type Iter = <str as sealed::ToSocketAddrsPriv>::Iter; + type Future = <str as sealed::ToSocketAddrsPriv>::Future; + + fn to_socket_addrs(&self, _: sealed::Internal) -> Self::Future { + (&self[..]).to_socket_addrs(sealed::Internal) + } + } +} + +pub(crate) mod sealed { + //! The contents of this trait are intended to remain private and __not__ + //! part of the `ToSocketAddrs` public API. The details will change over + //! time. + + use std::future::Future; + use std::io; + use std::net::SocketAddr; + + #[doc(hidden)] + pub trait ToSocketAddrsPriv { + type Iter: Iterator<Item = SocketAddr> + Send + 'static; + type Future: Future<Output = io::Result<Self::Iter>> + Send + 'static; + + fn to_socket_addrs(&self, internal: Internal) -> Self::Future; + } + + #[allow(missing_debug_implementations)] + pub struct Internal; + + cfg_net! { + use crate::blocking::JoinHandle; + + use std::option; + use std::pin::Pin; + use std::task::{Context, Poll}; + use std::vec; + + #[doc(hidden)] + #[derive(Debug)] + pub struct MaybeReady(pub(super) State); + + #[derive(Debug)] + pub(super) enum State { + Ready(Option<SocketAddr>), + Blocking(JoinHandle<io::Result<vec::IntoIter<SocketAddr>>>), + } + + #[doc(hidden)] + #[derive(Debug)] + pub enum OneOrMore { + One(option::IntoIter<SocketAddr>), + More(vec::IntoIter<SocketAddr>), + } + + impl Future for MaybeReady { + type Output = io::Result<OneOrMore>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { + match self.0 { + State::Ready(ref mut i) => { + let iter = OneOrMore::One(i.take().into_iter()); + Poll::Ready(Ok(iter)) + } + State::Blocking(ref mut rx) => { + let res = ready!(Pin::new(rx).poll(cx))?.map(OneOrMore::More); + + Poll::Ready(res) + } + } + } + } + + impl Iterator for OneOrMore { + type Item = SocketAddr; + + fn next(&mut self) -> Option<Self::Item> { + match self { + OneOrMore::One(i) => i.next(), + OneOrMore::More(i) => i.next(), + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + match self { + OneOrMore::One(i) => i.size_hint(), + OneOrMore::More(i) => i.size_hint(), + } + } + } + } +} |