diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /vendor/reqwest/src/dns | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/reqwest/src/dns')
-rw-r--r-- | vendor/reqwest/src/dns/gai.rs | 32 | ||||
-rw-r--r-- | vendor/reqwest/src/dns/mod.rs | 9 | ||||
-rw-r--r-- | vendor/reqwest/src/dns/resolve.rs | 84 | ||||
-rw-r--r-- | vendor/reqwest/src/dns/trust_dns.rs | 108 |
4 files changed, 233 insertions, 0 deletions
diff --git a/vendor/reqwest/src/dns/gai.rs b/vendor/reqwest/src/dns/gai.rs new file mode 100644 index 000000000..f32f3b0e0 --- /dev/null +++ b/vendor/reqwest/src/dns/gai.rs @@ -0,0 +1,32 @@ +use futures_util::future::FutureExt; +use hyper::client::connect::dns::{GaiResolver as HyperGaiResolver, Name}; +use hyper::service::Service; + +use crate::dns::{Addrs, Resolve, Resolving}; +use crate::error::BoxError; + +#[derive(Debug)] +pub struct GaiResolver(HyperGaiResolver); + +impl GaiResolver { + pub fn new() -> Self { + Self(HyperGaiResolver::new()) + } +} + +impl Default for GaiResolver { + fn default() -> Self { + GaiResolver::new() + } +} + +impl Resolve for GaiResolver { + fn resolve(&self, name: Name) -> Resolving { + let this = &mut self.0.clone(); + Box::pin(Service::<Name>::call(this, name).map(|result| { + result + .map(|addrs| -> Addrs { Box::new(addrs) }) + .map_err(|err| -> BoxError { Box::new(err) }) + })) + } +} diff --git a/vendor/reqwest/src/dns/mod.rs b/vendor/reqwest/src/dns/mod.rs new file mode 100644 index 000000000..40cdabf9e --- /dev/null +++ b/vendor/reqwest/src/dns/mod.rs @@ -0,0 +1,9 @@ +//! DNS resolution + +pub use resolve::{Addrs, Resolve, Resolving}; +pub(crate) use resolve::{DnsResolverWithOverrides, DynResolver}; + +pub(crate) mod gai; +pub(crate) mod resolve; +#[cfg(feature = "trust-dns")] +pub(crate) mod trust_dns; diff --git a/vendor/reqwest/src/dns/resolve.rs b/vendor/reqwest/src/dns/resolve.rs new file mode 100644 index 000000000..3686765a0 --- /dev/null +++ b/vendor/reqwest/src/dns/resolve.rs @@ -0,0 +1,84 @@ +use hyper::client::connect::dns::Name; +use hyper::service::Service; + +use std::collections::HashMap; +use std::future::Future; +use std::net::SocketAddr; +use std::pin::Pin; +use std::sync::Arc; +use std::task::{Context, Poll}; + +use crate::error::BoxError; + +/// Alias for an `Iterator` trait object over `SocketAddr`. +pub type Addrs = Box<dyn Iterator<Item = SocketAddr> + Send>; + +/// Alias for the `Future` type returned by a DNS resolver. +pub type Resolving = Pin<Box<dyn Future<Output = Result<Addrs, BoxError>> + Send>>; + +/// Trait for customizing DNS resolution in reqwest. +pub trait Resolve: Send + Sync { + /// Performs DNS resolution on a `Name`. + /// The return type is a future containing an iterator of `SocketAddr`. + /// + /// It differs from `tower_service::Service<Name>` in several ways: + /// * It is assumed that `resolve` will always be ready to poll. + /// * It does not need a mutable reference to `self`. + /// * Since trait objects cannot make use of associated types, it requires + /// wrapping the returned `Future` and its contained `Iterator` with `Box`. + fn resolve(&self, name: Name) -> Resolving; +} + +#[derive(Clone)] +pub(crate) struct DynResolver { + resolver: Arc<dyn Resolve>, +} + +impl DynResolver { + pub(crate) fn new(resolver: Arc<dyn Resolve>) -> Self { + Self { resolver } + } +} + +impl Service<Name> for DynResolver { + type Response = Addrs; + type Error = BoxError; + type Future = Resolving; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, name: Name) -> Self::Future { + self.resolver.resolve(name) + } +} + +pub(crate) struct DnsResolverWithOverrides { + dns_resolver: Arc<dyn Resolve>, + overrides: Arc<HashMap<String, Vec<SocketAddr>>>, +} + +impl DnsResolverWithOverrides { + pub(crate) fn new( + dns_resolver: Arc<dyn Resolve>, + overrides: HashMap<String, Vec<SocketAddr>>, + ) -> Self { + DnsResolverWithOverrides { + dns_resolver, + overrides: Arc::new(overrides), + } + } +} + +impl Resolve for DnsResolverWithOverrides { + fn resolve(&self, name: Name) -> Resolving { + match self.overrides.get(name.as_str()) { + Some(dest) => { + let addrs: Addrs = Box::new(dest.clone().into_iter()); + Box::pin(futures_util::future::ready(Ok(addrs))) + } + None => self.dns_resolver.resolve(name), + } + } +} diff --git a/vendor/reqwest/src/dns/trust_dns.rs b/vendor/reqwest/src/dns/trust_dns.rs new file mode 100644 index 000000000..129000c8b --- /dev/null +++ b/vendor/reqwest/src/dns/trust_dns.rs @@ -0,0 +1,108 @@ +//! DNS resolution via the [trust_dns_resolver](https://github.com/bluejekyll/trust-dns) crate + +use hyper::client::connect::dns::Name; +use once_cell::sync::Lazy; +use tokio::sync::Mutex; +pub use trust_dns_resolver::config::{ResolverConfig, ResolverOpts}; +use trust_dns_resolver::{ + lookup_ip::LookupIpIntoIter, system_conf, AsyncResolver, TokioConnection, + TokioConnectionProvider, TokioHandle, +}; + +use std::io; +use std::net::SocketAddr; +use std::sync::Arc; + +use super::{Addrs, Resolve, Resolving}; + +use crate::error::BoxError; + +type SharedResolver = Arc<AsyncResolver<TokioConnection, TokioConnectionProvider>>; + +static SYSTEM_CONF: Lazy<io::Result<(ResolverConfig, ResolverOpts)>> = + Lazy::new(|| system_conf::read_system_conf().map_err(io::Error::from)); + +/// Wrapper around an `AsyncResolver`, which implements the `Resolve` trait. +#[derive(Debug, Clone)] +pub(crate) struct TrustDnsResolver { + state: Arc<Mutex<State>>, +} + +struct SocketAddrs { + iter: LookupIpIntoIter, +} + +#[derive(Debug)] +enum State { + Init, + Ready(SharedResolver), +} + +impl TrustDnsResolver { + /// Create a new resolver with the default configuration, + /// which reads from `/etc/resolve.conf`. + pub fn new() -> io::Result<Self> { + SYSTEM_CONF.as_ref().map_err(|e| { + io::Error::new(e.kind(), format!("error reading DNS system conf: {}", e)) + })?; + + // At this stage, we might not have been called in the context of a + // Tokio Runtime, so we must delay the actual construction of the + // resolver. + Ok(TrustDnsResolver { + state: Arc::new(Mutex::new(State::Init)), + }) + } +} + +impl Resolve for TrustDnsResolver { + fn resolve(&self, name: Name) -> Resolving { + let resolver = self.clone(); + Box::pin(async move { + let mut lock = resolver.state.lock().await; + + let resolver = match &*lock { + State::Init => { + let resolver = new_resolver().await?; + *lock = State::Ready(resolver.clone()); + resolver + } + State::Ready(resolver) => resolver.clone(), + }; + + // Don't keep lock once the resolver is constructed, otherwise + // only one lookup could be done at a time. + drop(lock); + + let lookup = resolver.lookup_ip(name.as_str()).await?; + let addrs: Addrs = Box::new(SocketAddrs { + iter: lookup.into_iter(), + }); + Ok(addrs) + }) + } +} + +impl Iterator for SocketAddrs { + type Item = SocketAddr; + + fn next(&mut self) -> Option<Self::Item> { + self.iter.next().map(|ip_addr| SocketAddr::new(ip_addr, 0)) + } +} + +async fn new_resolver() -> Result<SharedResolver, BoxError> { + let (config, opts) = SYSTEM_CONF + .as_ref() + .expect("can't construct TrustDnsResolver if SYSTEM_CONF is error") + .clone(); + new_resolver_with_config(config, opts) +} + +fn new_resolver_with_config( + config: ResolverConfig, + opts: ResolverOpts, +) -> Result<SharedResolver, BoxError> { + let resolver = AsyncResolver::new(config, opts, TokioHandle)?; + Ok(Arc::new(resolver)) +} |