chore: restore product scaffold to rollback baseline
This commit is contained in:
@@ -18,6 +18,8 @@ const NICK_RESOLVE_URL: &str = "https://named.myteamspeak.com/lookup";
|
||||
const TSDNS_PORT: u16 = 41144;
|
||||
const TSDNS_TERMINATOR: &[u8] = b"\n\r\r\r\n";
|
||||
const TSDNS_TIMEOUT: Duration = Duration::from_secs(3);
|
||||
const TS3_SRV_FALLBACK_DISCOVERY_BUDGET: Duration = Duration::from_millis(900);
|
||||
const TSDNS_FALLBACK_DISCOVERY_BUDGET: Duration = Duration::from_millis(900);
|
||||
pub const DEFAULT_TEAMSPEAK_PORT: u16 = 9987;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@@ -262,7 +264,7 @@ impl ChanoraResolver {
|
||||
));
|
||||
}
|
||||
|
||||
let direct = if is_bare_numeric_name(&host) {
|
||||
let mut direct = if is_bare_numeric_name(&host) {
|
||||
errors.push("dns: skipped bare numeric server name".to_string());
|
||||
None
|
||||
} else {
|
||||
@@ -275,53 +277,80 @@ impl ChanoraResolver {
|
||||
}
|
||||
};
|
||||
|
||||
match self.resolve_ts3(&host, "").await {
|
||||
Ok(resolution) => {
|
||||
let selected = match &resolution {
|
||||
Resolution::Srv { selected, .. } => selected.clone(),
|
||||
_ => unreachable!("ts3 resolution must be an srv result"),
|
||||
};
|
||||
return self
|
||||
.client_srv_resolution(
|
||||
input,
|
||||
ClientResolutionMethod::Ts3Srv,
|
||||
&selected,
|
||||
resolution,
|
||||
)
|
||||
.await;
|
||||
if should_return_direct_dns_before_discovery(port) {
|
||||
if let Some(resolution) = direct.take() {
|
||||
return Ok(direct_client_resolution(
|
||||
input,
|
||||
from_server_name,
|
||||
fallback_port,
|
||||
resolution,
|
||||
));
|
||||
}
|
||||
Err(err) => errors.push(format!("ts3 srv: {err}")),
|
||||
}
|
||||
|
||||
match self
|
||||
.resolve_tsdns_srv_candidates(input, &host, fallback_port)
|
||||
.await
|
||||
{
|
||||
Ok(resolution) => return Ok(resolution),
|
||||
Err(err) => errors.push(format!("tsdns srv: {err}")),
|
||||
let ts3 = self.resolve_ts3(&host, "");
|
||||
match ts3_srv_discovery_budget(direct.is_some()) {
|
||||
Some(budget) => match timeout(budget, ts3).await {
|
||||
Ok(Ok(resolution)) => {
|
||||
let selected = match &resolution {
|
||||
Resolution::Srv { selected, .. } => selected.clone(),
|
||||
_ => unreachable!("ts3 resolution must be an srv result"),
|
||||
};
|
||||
return self
|
||||
.client_srv_resolution(
|
||||
input,
|
||||
ClientResolutionMethod::Ts3Srv,
|
||||
&selected,
|
||||
resolution,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Ok(Err(err)) => errors.push(format!("ts3 srv: {err}")),
|
||||
Err(_) => errors.push(format!(
|
||||
"ts3 srv: discovery timed out after {}ms",
|
||||
budget.as_millis()
|
||||
)),
|
||||
},
|
||||
None => match ts3.await {
|
||||
Ok(resolution) => {
|
||||
let selected = match &resolution {
|
||||
Resolution::Srv { selected, .. } => selected.clone(),
|
||||
_ => unreachable!("ts3 resolution must be an srv result"),
|
||||
};
|
||||
return self
|
||||
.client_srv_resolution(
|
||||
input,
|
||||
ClientResolutionMethod::Ts3Srv,
|
||||
&selected,
|
||||
resolution,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
Err(err) => errors.push(format!("ts3 srv: {err}")),
|
||||
},
|
||||
}
|
||||
|
||||
match self
|
||||
.resolve_tsdns_tcp_candidates(input, &host, fallback_port)
|
||||
.await
|
||||
{
|
||||
Ok(resolution) => return Ok(resolution),
|
||||
Err(err) => errors.push(format!("tsdns tcp: {err}")),
|
||||
let tsdns = self.resolve_tsdns_candidates(input, &host, fallback_port);
|
||||
match tsdns_discovery_budget(direct.is_some()) {
|
||||
Some(budget) => match timeout(budget, tsdns).await {
|
||||
Ok(Ok(resolution)) => return Ok(resolution),
|
||||
Ok(Err(err)) => errors.push(format!("tsdns: {err}")),
|
||||
Err(_) => errors.push(format!(
|
||||
"tsdns: discovery timed out after {}ms",
|
||||
budget.as_millis()
|
||||
)),
|
||||
},
|
||||
None => match tsdns.await {
|
||||
Ok(resolution) => return Ok(resolution),
|
||||
Err(err) => errors.push(format!("tsdns: {err}")),
|
||||
},
|
||||
}
|
||||
|
||||
if let Some(resolution) = direct {
|
||||
let selected = match &resolution {
|
||||
Resolution::Dns { selected, .. } => *selected,
|
||||
_ => unreachable!("direct fallback must be a dns resolution"),
|
||||
};
|
||||
return Ok(client_resolution_with_address(
|
||||
return Ok(direct_client_resolution(
|
||||
input,
|
||||
if from_server_name {
|
||||
ClientResolutionMethod::Nick
|
||||
} else {
|
||||
ClientResolutionMethod::Dns
|
||||
},
|
||||
format_host_port(&selected.to_string(), fallback_port),
|
||||
from_server_name,
|
||||
fallback_port,
|
||||
resolution,
|
||||
));
|
||||
}
|
||||
@@ -332,6 +361,32 @@ impl ChanoraResolver {
|
||||
)
|
||||
}
|
||||
|
||||
async fn resolve_tsdns_candidates(
|
||||
&self,
|
||||
input: &str,
|
||||
query_host: &str,
|
||||
fallback_port: u16,
|
||||
) -> Result<ClientResolution> {
|
||||
let mut errors = Vec::new();
|
||||
match self
|
||||
.resolve_tsdns_srv_candidates(input, query_host, fallback_port)
|
||||
.await
|
||||
{
|
||||
Ok(resolution) => return Ok(resolution),
|
||||
Err(err) => errors.push(format!("tsdns srv: {err}")),
|
||||
}
|
||||
|
||||
match self
|
||||
.resolve_tsdns_tcp_candidates(input, query_host, fallback_port)
|
||||
.await
|
||||
{
|
||||
Ok(resolution) => return Ok(resolution),
|
||||
Err(err) => errors.push(format!("tsdns tcp: {err}")),
|
||||
}
|
||||
|
||||
bail!("{}", errors.join("; "))
|
||||
}
|
||||
|
||||
async fn client_srv_resolution(
|
||||
&self,
|
||||
input: &str,
|
||||
@@ -716,17 +771,6 @@ impl ChanoraResolver {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
fn srv_resolver_builder() -> Result<hickory_resolver::ResolverBuilder<TokioRuntimeProvider>> {
|
||||
use hickory_resolver::config::{ResolverConfig, CLOUDFLARE};
|
||||
|
||||
Ok(TokioResolver::builder_with_config(
|
||||
ResolverConfig::udp_and_tcp(&CLOUDFLARE),
|
||||
TokioRuntimeProvider::default(),
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn srv_resolver_builder() -> Result<hickory_resolver::ResolverBuilder<TokioRuntimeProvider>> {
|
||||
TokioResolver::builder_tokio().context("failed to initialize DNS resolver")
|
||||
}
|
||||
@@ -801,6 +845,40 @@ fn format_host_port(host: &str, port: u16) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn should_return_direct_dns_before_discovery(port: Option<u16>) -> bool {
|
||||
port.is_some()
|
||||
}
|
||||
|
||||
fn tsdns_discovery_budget(has_dns_fallback: bool) -> Option<Duration> {
|
||||
has_dns_fallback.then_some(TSDNS_FALLBACK_DISCOVERY_BUDGET)
|
||||
}
|
||||
|
||||
fn ts3_srv_discovery_budget(has_dns_fallback: bool) -> Option<Duration> {
|
||||
has_dns_fallback.then_some(TS3_SRV_FALLBACK_DISCOVERY_BUDGET)
|
||||
}
|
||||
|
||||
fn direct_client_resolution(
|
||||
input: &str,
|
||||
from_server_name: bool,
|
||||
fallback_port: u16,
|
||||
resolution: Resolution,
|
||||
) -> ClientResolution {
|
||||
let selected = match &resolution {
|
||||
Resolution::Dns { selected, .. } => *selected,
|
||||
_ => unreachable!("direct fallback must be a dns resolution"),
|
||||
};
|
||||
client_resolution_with_address(
|
||||
input,
|
||||
if from_server_name {
|
||||
ClientResolutionMethod::Nick
|
||||
} else {
|
||||
ClientResolutionMethod::Dns
|
||||
},
|
||||
format_host_port(&selected.to_string(), fallback_port),
|
||||
resolution,
|
||||
)
|
||||
}
|
||||
|
||||
fn client_resolution_with_address(
|
||||
input: &str,
|
||||
method: ClientResolutionMethod,
|
||||
@@ -1313,4 +1391,44 @@ mod tests {
|
||||
vec!["teamspeak.app"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_ports_use_direct_dns_fast_path() {
|
||||
assert!(should_return_direct_dns_before_discovery(Some(9987)));
|
||||
assert!(!should_return_direct_dns_before_discovery(None));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn explicit_port_client_request_uses_dns_result() {
|
||||
let resolver = ChanoraResolver {
|
||||
resolver: None,
|
||||
http: Client::new(),
|
||||
};
|
||||
|
||||
let resolved = resolver
|
||||
.resolve_client_request("localhost:10075")
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(resolved.method, ClientResolutionMethod::Dns);
|
||||
assert!(resolved.address.ends_with(":10075"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tsdns_discovery_is_bounded_when_dns_fallback_exists() {
|
||||
assert_eq!(
|
||||
tsdns_discovery_budget(true),
|
||||
Some(TSDNS_FALLBACK_DISCOVERY_BUDGET)
|
||||
);
|
||||
assert_eq!(tsdns_discovery_budget(false), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ts3_srv_discovery_is_bounded_when_dns_fallback_exists() {
|
||||
assert_eq!(
|
||||
ts3_srv_discovery_budget(true),
|
||||
Some(TS3_SRV_FALLBACK_DISCOVERY_BUDGET)
|
||||
);
|
||||
assert_eq!(ts3_srv_discovery_budget(false), None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user