Reduce high volume of strings from FedDest and ActualDest in resolver.
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
@@ -163,7 +163,7 @@ async fn into_http_response(
|
|||||||
request_url = ?url,
|
request_url = ?url,
|
||||||
response_url = ?response.url(),
|
response_url = ?response.url(),
|
||||||
"Received response from {}",
|
"Received response from {}",
|
||||||
actual.string(),
|
actual.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut http_response_builder = http::Response::builder()
|
let mut http_response_builder = http::Response::builder()
|
||||||
@@ -249,7 +249,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut request = request
|
let mut request = request
|
||||||
.try_into_http_request::<Vec<u8>>(actual.string().as_str(), SATIR, &supported)
|
.try_into_http_request::<Vec<u8>>(actual.to_string().as_str(), SATIR, &supported)
|
||||||
.map_err(|e| err!(BadServerResponse("Invalid destination: {e:?}")))?;
|
.map_err(|e| err!(BadServerResponse("Invalid destination: {e:?}")))?;
|
||||||
|
|
||||||
if matches!(T::METADATA.authentication, AuthScheme::ServerSignatures) {
|
if matches!(T::METADATA.authentication, AuthScheme::ServerSignatures) {
|
||||||
|
|||||||
@@ -10,19 +10,20 @@ use ruma::ServerName;
|
|||||||
use tuwunel_core::{Err, Result, debug, debug_info, err, error, trace};
|
use tuwunel_core::{Err, Result, debug, debug_info, err, error, trace};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
DestString, FedDest,
|
||||||
cache::{CachedDest, CachedOverride, MAX_IPS},
|
cache::{CachedDest, CachedOverride, MAX_IPS},
|
||||||
fed::{FedDest, PortString, add_port_to_hostname, get_ip_with_port},
|
fed::{PortString, add_port_to_hostname, get_ip_with_port},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct ActualDest {
|
pub(crate) struct ActualDest {
|
||||||
pub(crate) dest: FedDest,
|
pub(crate) dest: FedDest,
|
||||||
pub(crate) host: String,
|
pub(crate) host: DestString,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActualDest {
|
impl ActualDest {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn string(&self) -> String { self.dest.https_string() }
|
pub(crate) fn to_string(&self) -> DestString { self.dest.https_string() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Service {
|
impl super::Service {
|
||||||
@@ -65,7 +66,7 @@ impl super::Service {
|
|||||||
cache: bool,
|
cache: bool,
|
||||||
) -> Result<CachedDest> {
|
) -> Result<CachedDest> {
|
||||||
self.validate_dest(dest)?;
|
self.validate_dest(dest)?;
|
||||||
let mut host = dest.as_str().to_owned();
|
let mut host: DestString = dest.as_str().into();
|
||||||
let actual_dest = match get_ip_with_port(dest.as_str()) {
|
let actual_dest = match get_ip_with_port(dest.as_str()) {
|
||||||
| Some(host_port) => Self::actual_dest_1(host_port)?,
|
| Some(host_port) => Self::actual_dest_1(host_port)?,
|
||||||
| None =>
|
| None =>
|
||||||
@@ -77,7 +78,7 @@ impl super::Service {
|
|||||||
self.services.server.check_running()?;
|
self.services.server.check_running()?;
|
||||||
match self.request_well_known(dest.as_str()).await? {
|
match self.request_well_known(dest.as_str()).await? {
|
||||||
| Some(delegated) =>
|
| Some(delegated) =>
|
||||||
self.actual_dest_3(&mut host, cache, delegated)
|
self.actual_dest_3(&mut host, cache, &delegated)
|
||||||
.await?,
|
.await?,
|
||||||
| _ => match self.query_srv_record(dest.as_str()).await? {
|
| _ => match self.query_srv_record(dest.as_str()).await? {
|
||||||
| Some(overrider) =>
|
| Some(overrider) =>
|
||||||
@@ -94,16 +95,16 @@ impl super::Service {
|
|||||||
let host = if let Ok(addr) = host.parse::<SocketAddr>() {
|
let host = if let Ok(addr) = host.parse::<SocketAddr>() {
|
||||||
FedDest::Literal(addr)
|
FedDest::Literal(addr)
|
||||||
} else if let Ok(addr) = host.parse::<IpAddr>() {
|
} else if let Ok(addr) = host.parse::<IpAddr>() {
|
||||||
FedDest::Named(addr.to_string(), FedDest::default_port())
|
FedDest::Named(addr.to_string().into(), FedDest::default_port())
|
||||||
} else if let Some(pos) = host.find(':') {
|
} else if let Some(pos) = host.find(':') {
|
||||||
let (host, port) = host.split_at(pos);
|
let (host, port) = host.split_at(pos);
|
||||||
FedDest::Named(
|
FedDest::Named(
|
||||||
host.to_owned(),
|
host.into(),
|
||||||
port.try_into()
|
port.try_into()
|
||||||
.unwrap_or_else(|_| FedDest::default_port()),
|
.unwrap_or_else(|_| FedDest::default_port()),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
FedDest::Named(host, FedDest::default_port())
|
FedDest::Named(host.as_str().into(), FedDest::default_port())
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("Actual destination: {actual_dest:?} hostname: {host:?}");
|
debug!("Actual destination: {actual_dest:?} hostname: {host:?}");
|
||||||
@@ -126,7 +127,7 @@ impl super::Service {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(FedDest::Named(
|
Ok(FedDest::Named(
|
||||||
host.to_owned(),
|
host.into(),
|
||||||
port.try_into()
|
port.try_into()
|
||||||
.unwrap_or_else(|_| FedDest::default_port()),
|
.unwrap_or_else(|_| FedDest::default_port()),
|
||||||
))
|
))
|
||||||
@@ -134,20 +135,20 @@ impl super::Service {
|
|||||||
|
|
||||||
async fn actual_dest_3(
|
async fn actual_dest_3(
|
||||||
&self,
|
&self,
|
||||||
host: &mut String,
|
host: &mut DestString,
|
||||||
cache: bool,
|
cache: bool,
|
||||||
delegated: String,
|
delegated: &str,
|
||||||
) -> Result<FedDest> {
|
) -> Result<FedDest> {
|
||||||
debug!("3: A .well-known file is available");
|
debug!("3: A .well-known file is available");
|
||||||
*host = add_port_to_hostname(&delegated).uri_string();
|
*host = add_port_to_hostname(delegated).uri_string();
|
||||||
match get_ip_with_port(&delegated) {
|
match get_ip_with_port(delegated) {
|
||||||
| Some(host_and_port) => Self::actual_dest_3_1(host_and_port),
|
| Some(host_and_port) => Self::actual_dest_3_1(host_and_port),
|
||||||
| None =>
|
| None =>
|
||||||
if let Some(pos) = delegated.find(':') {
|
if let Some(pos) = delegated.find(':') {
|
||||||
self.actual_dest_3_2(cache, delegated, pos).await
|
self.actual_dest_3_2(cache, delegated, pos).await
|
||||||
} else {
|
} else {
|
||||||
trace!("Delegated hostname has no port in this branch");
|
trace!("Delegated hostname has no port in this branch");
|
||||||
match self.query_srv_record(&delegated).await? {
|
match self.query_srv_record(delegated).await? {
|
||||||
| Some(overrider) =>
|
| Some(overrider) =>
|
||||||
self.actual_dest_3_3(cache, delegated, overrider)
|
self.actual_dest_3_3(cache, delegated, overrider)
|
||||||
.await,
|
.await,
|
||||||
@@ -162,19 +163,14 @@ impl super::Service {
|
|||||||
Ok(host_and_port)
|
Ok(host_and_port)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn actual_dest_3_2(
|
async fn actual_dest_3_2(&self, cache: bool, delegated: &str, pos: usize) -> Result<FedDest> {
|
||||||
&self,
|
|
||||||
cache: bool,
|
|
||||||
delegated: String,
|
|
||||||
pos: usize,
|
|
||||||
) -> Result<FedDest> {
|
|
||||||
debug!("3.2: Hostname with port in .well-known file");
|
debug!("3.2: Hostname with port in .well-known file");
|
||||||
let (host, port) = delegated.split_at(pos);
|
let (host, port) = delegated.split_at(pos);
|
||||||
self.conditional_query_and_cache(host, port.parse::<u16>().unwrap_or(8448), cache)
|
self.conditional_query_and_cache(host, port.parse::<u16>().unwrap_or(8448), cache)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(FedDest::Named(
|
Ok(FedDest::Named(
|
||||||
host.to_owned(),
|
host.into(),
|
||||||
port.try_into()
|
port.try_into()
|
||||||
.unwrap_or_else(|_| FedDest::default_port()),
|
.unwrap_or_else(|_| FedDest::default_port()),
|
||||||
))
|
))
|
||||||
@@ -183,13 +179,13 @@ impl super::Service {
|
|||||||
async fn actual_dest_3_3(
|
async fn actual_dest_3_3(
|
||||||
&self,
|
&self,
|
||||||
cache: bool,
|
cache: bool,
|
||||||
delegated: String,
|
delegated: &str,
|
||||||
overrider: FedDest,
|
overrider: FedDest,
|
||||||
) -> Result<FedDest> {
|
) -> Result<FedDest> {
|
||||||
debug!("3.3: SRV lookup successful");
|
debug!("3.3: SRV lookup successful");
|
||||||
let force_port = overrider.port();
|
let force_port = overrider.port();
|
||||||
self.conditional_query_and_cache_override(
|
self.conditional_query_and_cache_override(
|
||||||
&delegated,
|
delegated,
|
||||||
&overrider.hostname(),
|
&overrider.hostname(),
|
||||||
force_port.unwrap_or(8448),
|
force_port.unwrap_or(8448),
|
||||||
cache,
|
cache,
|
||||||
@@ -198,7 +194,7 @@ impl super::Service {
|
|||||||
|
|
||||||
if let Some(port) = force_port {
|
if let Some(port) = force_port {
|
||||||
return Ok(FedDest::Named(
|
return Ok(FedDest::Named(
|
||||||
delegated,
|
delegated.into(),
|
||||||
format!(":{port}")
|
format!(":{port}")
|
||||||
.as_str()
|
.as_str()
|
||||||
.try_into()
|
.try_into()
|
||||||
@@ -206,14 +202,15 @@ impl super::Service {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(add_port_to_hostname(&delegated))
|
Ok(add_port_to_hostname(delegated))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn actual_dest_3_4(&self, cache: bool, delegated: String) -> Result<FedDest> {
|
async fn actual_dest_3_4(&self, cache: bool, delegated: &str) -> Result<FedDest> {
|
||||||
debug!("3.4: No SRV records, just use the hostname from .well-known");
|
debug!("3.4: No SRV records, just use the hostname from .well-known");
|
||||||
self.conditional_query_and_cache(&delegated, 8448, cache)
|
self.conditional_query_and_cache(delegated, 8448, cache)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(add_port_to_hostname(&delegated))
|
|
||||||
|
Ok(add_port_to_hostname(delegated))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn actual_dest_4(
|
async fn actual_dest_4(
|
||||||
@@ -234,9 +231,8 @@ impl super::Service {
|
|||||||
|
|
||||||
if let Some(port) = force_port {
|
if let Some(port) = force_port {
|
||||||
let port = format!(":{port}");
|
let port = format!(":{port}");
|
||||||
|
|
||||||
return Ok(FedDest::Named(
|
return Ok(FedDest::Named(
|
||||||
host.to_owned(),
|
host.into(),
|
||||||
PortString::from(port.as_str()).unwrap_or_else(|_| FedDest::default_port()),
|
PortString::from(port.as_str()).unwrap_or_else(|_| FedDest::default_port()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -334,7 +330,7 @@ impl super::Service {
|
|||||||
.target()
|
.target()
|
||||||
.to_string()
|
.to_string()
|
||||||
.trim_end_matches('.')
|
.trim_end_matches('.')
|
||||||
.to_owned(),
|
.into(),
|
||||||
format!(":{}", result.port())
|
format!(":{}", result.port())
|
||||||
.as_str()
|
.as_str()
|
||||||
.try_into()
|
.try_into()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use tuwunel_core::{
|
|||||||
};
|
};
|
||||||
use tuwunel_database::{Cbor, Deserialized, Map};
|
use tuwunel_database::{Cbor, Deserialized, Map};
|
||||||
|
|
||||||
use super::fed::FedDest;
|
use super::{DestString, FedDest};
|
||||||
|
|
||||||
pub struct Cache {
|
pub struct Cache {
|
||||||
destinations: Arc<Map>,
|
destinations: Arc<Map>,
|
||||||
@@ -21,7 +21,7 @@ pub struct Cache {
|
|||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct CachedDest {
|
pub struct CachedDest {
|
||||||
pub dest: FedDest,
|
pub dest: FedDest,
|
||||||
pub host: String,
|
pub host: DestString,
|
||||||
pub expire: SystemTime,
|
pub expire: SystemTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ pub struct CachedOverride {
|
|||||||
pub ips: IpAddrs,
|
pub ips: IpAddrs,
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub expire: SystemTime,
|
pub expire: SystemTime,
|
||||||
pub overriding: Option<String>,
|
pub overriding: Option<DestString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type IpAddrs = ArrayVec<IpAddr, MAX_IPS>;
|
pub type IpAddrs = ArrayVec<IpAddr, MAX_IPS>;
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
|
||||||
fmt,
|
fmt,
|
||||||
net::{IpAddr, SocketAddr},
|
net::{IpAddr, SocketAddr},
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tuwunel_core::{arrayvec::ArrayString, utils::math::Expected};
|
use tuwunel_core::{arrayvec::ArrayString, smallstr::SmallString, utils::math::Expected};
|
||||||
|
|
||||||
|
use super::DestString;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
|
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)]
|
||||||
pub enum FedDest {
|
pub enum FedDest {
|
||||||
Literal(SocketAddr),
|
Literal(SocketAddr),
|
||||||
Named(String, PortString),
|
Named(HostString, PortString),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// numeric or service-name
|
/// FedDest::Named host domain
|
||||||
pub type PortString = ArrayString<16>;
|
pub(super) type HostString = SmallString<[u8; 32]>;
|
||||||
|
|
||||||
|
/// FedDest::Named numeric or service-name
|
||||||
|
pub(super) type PortString = ArrayString<16>;
|
||||||
|
|
||||||
const DEFAULT_PORT: &str = ":8448";
|
const DEFAULT_PORT: &str = ":8448";
|
||||||
|
|
||||||
@@ -35,31 +39,31 @@ pub(crate) fn add_port_to_hostname(dest: &str) -> FedDest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
FedDest::Named(
|
FedDest::Named(
|
||||||
host.to_owned(),
|
host.into(),
|
||||||
PortString::from(port).unwrap_or_else(|_| FedDest::default_port()),
|
PortString::from(port).unwrap_or_else(|_| FedDest::default_port()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FedDest {
|
impl FedDest {
|
||||||
pub(crate) fn https_string(&self) -> String {
|
pub(crate) fn https_string(&self) -> DestString {
|
||||||
match self {
|
match self {
|
||||||
| Self::Literal(addr) => format!("https://{addr}"),
|
| Self::Literal(addr) => format!("https://{addr}").into(),
|
||||||
| Self::Named(host, port) => format!("https://{host}{port}"),
|
| Self::Named(host, port) => format!("https://{host}{port}").into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn uri_string(&self) -> String {
|
pub(crate) fn uri_string(&self) -> DestString {
|
||||||
match self {
|
match self {
|
||||||
| Self::Literal(addr) => addr.to_string(),
|
| Self::Literal(addr) => addr.to_string().into(),
|
||||||
| Self::Named(host, port) => format!("{host}{port}"),
|
| Self::Named(host, port) => [host.as_str(), port.as_str()].concat().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn hostname(&self) -> Cow<'_, str> {
|
pub(crate) fn hostname(&self) -> HostString {
|
||||||
match &self {
|
match &self {
|
||||||
| Self::Literal(addr) => addr.ip().to_string().into(),
|
| Self::Literal(addr) => addr.ip().to_string().into(),
|
||||||
| Self::Named(host, _) => host.into(),
|
| Self::Named(host, _) => host.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ mod well_known;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use tuwunel_core::{Result, arrayvec::ArrayString, utils::MutexMap};
|
use tuwunel_core::{Result, arrayvec::ArrayString, smallstr::SmallString, utils::MutexMap};
|
||||||
|
|
||||||
use self::{cache::Cache, dns::Resolver};
|
use self::{cache::Cache, dns::Resolver, fed::FedDest};
|
||||||
|
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
pub cache: Arc<Cache>,
|
pub cache: Arc<Cache>,
|
||||||
@@ -20,6 +20,7 @@ pub struct Service {
|
|||||||
services: Arc<crate::services::OnceServices>,
|
services: Arc<crate::services::OnceServices>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) type DestString = SmallString<[u8; 40]>;
|
||||||
type Resolving = MutexMap<NameBuf, ()>;
|
type Resolving = MutexMap<NameBuf, ()>;
|
||||||
type NameBuf = ArrayString<256>;
|
type NameBuf = ArrayString<256>;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ fn ips_keep_custom_ports() {
|
|||||||
fn hostnames_get_default_ports() {
|
fn hostnames_get_default_ports() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
add_port_to_hostname("example.com"),
|
add_port_to_hostname("example.com"),
|
||||||
FedDest::Named(String::from("example.com"), ":8448".try_into().unwrap())
|
FedDest::Named("example.com".into(), ":8448".try_into().unwrap())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +36,6 @@ fn hostnames_get_default_ports() {
|
|||||||
fn hostnames_keep_custom_ports() {
|
fn hostnames_keep_custom_ports() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
add_port_to_hostname("example.com:1337"),
|
add_port_to_hostname("example.com:1337"),
|
||||||
FedDest::Named(String::from("example.com"), ":1337".try_into().unwrap())
|
FedDest::Named("example.com".into(), ":1337".try_into().unwrap())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
use tuwunel_core::{Result, debug, debug_error, debug_info, debug_warn, implement, trace};
|
use tuwunel_core::{Result, debug, debug_error, debug_info, debug_warn, implement, trace};
|
||||||
|
|
||||||
|
use super::DestString;
|
||||||
|
|
||||||
#[implement(super::Service)]
|
#[implement(super::Service)]
|
||||||
#[tracing::instrument(name = "well-known", level = "debug", skip(self, dest))]
|
#[tracing::instrument(name = "well-known", level = "debug", skip(self, dest))]
|
||||||
pub(super) async fn request_well_known(&self, dest: &str) -> Result<Option<String>> {
|
pub(super) async fn request_well_known(&self, dest: &str) -> Result<Option<DestString>> {
|
||||||
trace!("Requesting well known for {dest}");
|
trace!("Requesting well known for {dest}");
|
||||||
let response = self
|
let response = self
|
||||||
.services
|
.services
|
||||||
@@ -45,5 +47,5 @@ pub(super) async fn request_well_known(&self, dest: &str) -> Result<Option<Strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug_info!("{dest:?} found at {m_server:?}");
|
debug_info!("{dest:?} found at {m_server:?}");
|
||||||
Ok(Some(m_server.to_owned()))
|
Ok(Some(m_server.into()))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user