don't cache server name lookups indefinitely (#436)

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-07-04 11:46:30 +00:00
parent eaf1cf38a5
commit dc18f89c0b
3 changed files with 30 additions and 2 deletions

View file

@ -122,6 +122,7 @@ impl Resolve for Hooked {
.read() .read()
.expect("locked for reading") .expect("locked for reading")
.get(name.as_str()) .get(name.as_str())
.filter(|cached| cached.valid())
.cloned(); .cloned();
if let Some(cached) = cached { if let Some(cached) = cached {

View file

@ -2,6 +2,7 @@ use std::{
fmt, fmt,
fmt::Debug, fmt::Debug,
net::{IpAddr, SocketAddr}, net::{IpAddr, SocketAddr},
time::SystemTime,
}; };
use hickory_resolver::{error::ResolveError, lookup::SrvLookup}; use hickory_resolver::{error::ResolveError, lookup::SrvLookup};
@ -9,7 +10,7 @@ use ipaddress::IPAddress;
use ruma::{OwnedServerName, ServerName}; use ruma::{OwnedServerName, ServerName};
use tracing::{debug, error, trace}; use tracing::{debug, error, trace};
use crate::{debug_error, debug_info, debug_warn, services, Error, Result}; use crate::{debug_error, debug_info, debug_warn, services, utils::rand, Error, Result};
/// Wraps either an literal IP address plus port, or a hostname plus complement /// Wraps either an literal IP address plus port, or a hostname plus complement
/// (colon-plus-port if it was specified). /// (colon-plus-port if it was specified).
@ -47,12 +48,14 @@ pub(crate) struct ActualDest {
pub struct CachedDest { pub struct CachedDest {
pub dest: FedDest, pub dest: FedDest,
pub host: String, pub host: String,
pub expire: SystemTime,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct CachedOverride { pub struct CachedOverride {
pub ips: Vec<IpAddr>, pub ips: Vec<IpAddr>,
pub port: u16, pub port: u16,
pub expire: SystemTime,
} }
#[tracing::instrument(skip_all, name = "resolve")] #[tracing::instrument(skip_all, name = "resolve")]
@ -125,6 +128,7 @@ pub async fn resolve_actual_dest(dest: &ServerName, cache: bool) -> Result<Cache
Ok(CachedDest { Ok(CachedDest {
dest: actual_dest, dest: actual_dest,
host: host.into_uri_string(), host: host.into_uri_string(),
expire: CachedDest::default_expire(),
}) })
} }
@ -286,6 +290,7 @@ async fn query_and_cache_override(overname: &'_ str, hostname: &'_ str, port: u1
CachedOverride { CachedOverride {
ips: override_ip.iter().collect(), ips: override_ip.iter().collect(),
port, port,
expire: CachedOverride::default_expire(),
}, },
); );
@ -416,6 +421,7 @@ impl crate::globals::resolver::Resolver {
.read() .read()
.expect("locked for reading") .expect("locked for reading")
.get(name) .get(name)
.filter(|cached| cached.valid())
.cloned() .cloned()
} }
@ -431,10 +437,30 @@ impl crate::globals::resolver::Resolver {
self.overrides self.overrides
.read() .read()
.expect("locked for reading") .expect("locked for reading")
.contains_key(name) .get(name)
.filter(|cached| cached.valid())
.is_some()
} }
} }
impl CachedDest {
#[inline]
#[must_use]
pub fn valid(&self) -> bool { self.expire > SystemTime::now() }
#[must_use]
pub(crate) fn default_expire() -> SystemTime { rand::timepoint_secs(60 * 60 * 18..60 * 60 * 36) }
}
impl CachedOverride {
#[inline]
#[must_use]
pub fn valid(&self) -> bool { self.expire > SystemTime::now() }
#[must_use]
pub(crate) fn default_expire() -> SystemTime { rand::timepoint_secs(60 * 60 * 6..60 * 60 * 12) }
}
impl FedDest { impl FedDest {
fn into_https_string(self) -> String { fn into_https_string(self) -> String {
match self { match self {

View file

@ -111,6 +111,7 @@ where
CachedDest { CachedDest {
dest: actual.dest.clone(), dest: actual.dest.clone(),
host: actual.host.clone(), host: actual.host.clone(),
expire: CachedDest::default_expire(),
}, },
); );
} }