convert Resolver into a Service.
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
2fd6f6b0ff
commit
f465d77ad3
11 changed files with 381 additions and 409 deletions
|
@ -2,7 +2,7 @@ use std::{sync::Arc, time::Duration};
|
|||
|
||||
use reqwest::redirect;
|
||||
|
||||
use crate::{globals::resolver, Config, Result};
|
||||
use crate::{resolver, Config, Result};
|
||||
|
||||
pub struct Client {
|
||||
pub default: reqwest::Client,
|
||||
|
@ -15,7 +15,7 @@ pub struct Client {
|
|||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(config: &Config, resolver: &Arc<resolver::Resolver>) -> Self {
|
||||
pub fn new(config: &Config, resolver: &Arc<resolver::Service>) -> Self {
|
||||
Self {
|
||||
default: Self::base(config)
|
||||
.unwrap()
|
||||
|
|
|
@ -2,7 +2,6 @@ mod client;
|
|||
mod data;
|
||||
mod emerg_access;
|
||||
pub(super) mod migrations;
|
||||
pub(crate) mod resolver;
|
||||
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
|
@ -25,7 +24,7 @@ use ruma::{
|
|||
use tokio::sync::Mutex;
|
||||
use url::Url;
|
||||
|
||||
use crate::services;
|
||||
use crate::{resolver, service, services};
|
||||
|
||||
pub struct Service {
|
||||
pub db: Data,
|
||||
|
@ -34,7 +33,6 @@ pub struct Service {
|
|||
pub cidr_range_denylist: Vec<IPAddress>,
|
||||
keypair: Arc<ruma::signatures::Ed25519KeyPair>,
|
||||
jwt_decoding_key: Option<jsonwebtoken::DecodingKey>,
|
||||
pub resolver: Arc<resolver::Resolver>,
|
||||
pub client: client::Client,
|
||||
pub stable_room_versions: Vec<RoomVersionId>,
|
||||
pub unstable_room_versions: Vec<RoomVersionId>,
|
||||
|
@ -68,8 +66,6 @@ impl crate::Service for Service {
|
|||
.as_ref()
|
||||
.map(|secret| jsonwebtoken::DecodingKey::from_secret(secret.as_bytes()));
|
||||
|
||||
let resolver = Arc::new(resolver::Resolver::new(config));
|
||||
|
||||
// Supported and stable room versions
|
||||
let stable_room_versions = vec![
|
||||
RoomVersionId::V6,
|
||||
|
@ -89,12 +85,14 @@ impl crate::Service for Service {
|
|||
cidr_range_denylist.push(cidr);
|
||||
}
|
||||
|
||||
let resolver = service::get::<resolver::Service>(args.service, "resolver")
|
||||
.expect("resolver must be built prior to globals");
|
||||
|
||||
let mut s = Self {
|
||||
db,
|
||||
config: config.clone(),
|
||||
cidr_range_denylist,
|
||||
keypair: Arc::new(keypair),
|
||||
resolver: resolver.clone(),
|
||||
client: client::Client::new(config, &resolver),
|
||||
jwt_decoding_key,
|
||||
stable_room_versions,
|
||||
|
@ -126,8 +124,6 @@ impl crate::Service for Service {
|
|||
}
|
||||
|
||||
fn memory_usage(&self, out: &mut dyn Write) -> Result<()> {
|
||||
self.resolver.memory_usage(out)?;
|
||||
|
||||
let bad_event_ratelimiter = self
|
||||
.bad_event_ratelimiter
|
||||
.read()
|
||||
|
@ -146,8 +142,6 @@ impl crate::Service for Service {
|
|||
}
|
||||
|
||||
fn clear_cache(&self) {
|
||||
self.resolver.clear_cache();
|
||||
|
||||
self.bad_event_ratelimiter
|
||||
.write()
|
||||
.expect("locked for writing")
|
||||
|
@ -159,7 +153,7 @@ impl crate::Service for Service {
|
|||
.clear();
|
||||
}
|
||||
|
||||
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
|
||||
fn name(&self) -> &str { service::make_name(std::module_path!()) }
|
||||
}
|
||||
|
||||
impl Service {
|
||||
|
|
|
@ -1,156 +0,0 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::Write,
|
||||
future, iter,
|
||||
net::{IpAddr, SocketAddr},
|
||||
sync::{Arc, RwLock},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use conduit::{error, Config, Result};
|
||||
use hickory_resolver::TokioAsyncResolver;
|
||||
use reqwest::dns::{Addrs, Name, Resolve, Resolving};
|
||||
use ruma::OwnedServerName;
|
||||
|
||||
use crate::sending::{CachedDest, CachedOverride};
|
||||
|
||||
type WellKnownMap = HashMap<OwnedServerName, CachedDest>;
|
||||
type TlsNameMap = HashMap<String, CachedOverride>;
|
||||
|
||||
pub struct Resolver {
|
||||
pub destinations: Arc<RwLock<WellKnownMap>>, // actual_destination, host
|
||||
pub overrides: Arc<RwLock<TlsNameMap>>,
|
||||
pub(crate) resolver: Arc<TokioAsyncResolver>,
|
||||
pub(crate) hooked: Arc<Hooked>,
|
||||
}
|
||||
|
||||
pub(crate) struct Hooked {
|
||||
overrides: Arc<RwLock<TlsNameMap>>,
|
||||
resolver: Arc<TokioAsyncResolver>,
|
||||
}
|
||||
|
||||
impl Resolver {
|
||||
#[allow(clippy::as_conversions, clippy::cast_sign_loss, clippy::cast_possible_truncation)]
|
||||
pub(super) fn new(config: &Config) -> Self {
|
||||
let (sys_conf, mut opts) = hickory_resolver::system_conf::read_system_conf()
|
||||
.inspect_err(|e| error!("Failed to set up hickory dns resolver with system config: {e}"))
|
||||
.expect("DNS system config must be valid");
|
||||
|
||||
let mut conf = hickory_resolver::config::ResolverConfig::new();
|
||||
|
||||
if let Some(domain) = sys_conf.domain() {
|
||||
conf.set_domain(domain.clone());
|
||||
}
|
||||
|
||||
for sys_conf in sys_conf.search() {
|
||||
conf.add_search(sys_conf.clone());
|
||||
}
|
||||
|
||||
for sys_conf in sys_conf.name_servers() {
|
||||
let mut ns = sys_conf.clone();
|
||||
|
||||
if config.query_over_tcp_only {
|
||||
ns.protocol = hickory_resolver::config::Protocol::Tcp;
|
||||
}
|
||||
|
||||
ns.trust_negative_responses = !config.query_all_nameservers;
|
||||
|
||||
conf.add_name_server(ns);
|
||||
}
|
||||
|
||||
opts.cache_size = config.dns_cache_entries as usize;
|
||||
opts.negative_min_ttl = Some(Duration::from_secs(config.dns_min_ttl_nxdomain));
|
||||
opts.negative_max_ttl = Some(Duration::from_secs(60 * 60 * 24 * 30));
|
||||
opts.positive_min_ttl = Some(Duration::from_secs(config.dns_min_ttl));
|
||||
opts.positive_max_ttl = Some(Duration::from_secs(60 * 60 * 24 * 7));
|
||||
opts.timeout = Duration::from_secs(config.dns_timeout);
|
||||
opts.attempts = config.dns_attempts as usize;
|
||||
opts.try_tcp_on_error = config.dns_tcp_fallback;
|
||||
opts.num_concurrent_reqs = 1;
|
||||
opts.shuffle_dns_servers = true;
|
||||
opts.rotate = true;
|
||||
opts.ip_strategy = match config.ip_lookup_strategy {
|
||||
1 => hickory_resolver::config::LookupIpStrategy::Ipv4Only,
|
||||
2 => hickory_resolver::config::LookupIpStrategy::Ipv6Only,
|
||||
3 => hickory_resolver::config::LookupIpStrategy::Ipv4AndIpv6,
|
||||
4 => hickory_resolver::config::LookupIpStrategy::Ipv6thenIpv4,
|
||||
_ => hickory_resolver::config::LookupIpStrategy::Ipv4thenIpv6,
|
||||
};
|
||||
opts.authentic_data = false;
|
||||
|
||||
let resolver = Arc::new(TokioAsyncResolver::tokio(conf, opts));
|
||||
let overrides = Arc::new(RwLock::new(TlsNameMap::new()));
|
||||
Self {
|
||||
destinations: Arc::new(RwLock::new(WellKnownMap::new())),
|
||||
overrides: overrides.clone(),
|
||||
resolver: resolver.clone(),
|
||||
hooked: Arc::new(Hooked {
|
||||
overrides,
|
||||
resolver,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn memory_usage(&self, out: &mut dyn Write) -> Result<()> {
|
||||
let resolver_overrides_cache = self.overrides.read().expect("locked for reading").len();
|
||||
writeln!(out, "resolver_overrides_cache: {resolver_overrides_cache}")?;
|
||||
|
||||
let resolver_destinations_cache = self.destinations.read().expect("locked for reading").len();
|
||||
writeln!(out, "resolver_destinations_cache: {resolver_destinations_cache}")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn clear_cache(&self) {
|
||||
self.overrides.write().expect("write locked").clear();
|
||||
self.destinations.write().expect("write locked").clear();
|
||||
self.resolver.clear_cache();
|
||||
}
|
||||
}
|
||||
|
||||
impl Resolve for Resolver {
|
||||
fn resolve(&self, name: Name) -> Resolving { resolve_to_reqwest(self.resolver.clone(), name) }
|
||||
}
|
||||
|
||||
impl Resolve for Hooked {
|
||||
fn resolve(&self, name: Name) -> Resolving {
|
||||
let cached = self
|
||||
.overrides
|
||||
.read()
|
||||
.expect("locked for reading")
|
||||
.get(name.as_str())
|
||||
.filter(|cached| cached.valid())
|
||||
.cloned();
|
||||
|
||||
if let Some(cached) = cached {
|
||||
cached_to_reqwest(&cached.ips, cached.port)
|
||||
} else {
|
||||
resolve_to_reqwest(self.resolver.clone(), name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cached_to_reqwest(override_name: &[IpAddr], port: u16) -> Resolving {
|
||||
override_name
|
||||
.first()
|
||||
.map(|first_name| -> Resolving {
|
||||
let saddr = SocketAddr::new(*first_name, port);
|
||||
let result: Box<dyn Iterator<Item = SocketAddr> + Send> = Box::new(iter::once(saddr));
|
||||
Box::pin(future::ready(Ok(result)))
|
||||
})
|
||||
.expect("must provide at least one override name")
|
||||
}
|
||||
|
||||
fn resolve_to_reqwest(resolver: Arc<TokioAsyncResolver>, name: Name) -> Resolving {
|
||||
Box::pin(async move {
|
||||
let results = resolver
|
||||
.lookup_ip(name.as_str())
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|ip| SocketAddr::new(ip, 0));
|
||||
|
||||
let results: Addrs = Box::new(results);
|
||||
|
||||
Ok(results)
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue