4.4 KiB
4.4 KiB
chanora_resolver
The library accepts the same kind of raw server input a client UI receives and returns a final host:port address suitable for tsclientlib::Connection::build or Chanora's ConnectConfig.address.
Resolution Flow
Use ChanoraResolver::resolve_client_request or resolve_client_address for app code. The resolver owns the decision tree:
- Normalize raw client input, including
ts3server://host?port=.... - For dotless names such as
6666orwwb, query the myTeamSpeak server-name endpoint first. If it returns a hostname, restart normal resolution with that hostname. If it returnsip:port, use that final address. - Start plain A/AAAA DNS as the final fallback address.
- If the user supplied an explicit port and DNS resolved, return that direct target immediately.
- Prefer
_ts3._udp.<host>SRV. Its target host and port override the default port, then the target is resolved to a final IP. - Try
_tsdns._tcp.<candidate>SRV on candidate parent/full hosts and query the returned TSDNS server over TCP. - Try direct TSDNS TCP on candidate parent/full hosts at port
41144. - Fall back to the A/AAAA result with the default TeamSpeak port
9987. When DNS fallback is already available, TSDNS discovery is capped so missing or filtered TSDNS cannot add multi-second join delays.
The older explicit API (Args { host, service, protocol }) is still available for diagnostic example use.
DNS Setup Guide
This chart is for choosing DNS records when operating a TeamSpeak 3 server. It is not the client lookup order; the library still implements the client-side resolver behavior above.
flowchart TD
A["Which DNS type fits your TeamSpeak 3 server?"]
A --> X["Don't do this!"]
X --> X1["Do not use simple TSDNS<br/>without SRV TSDNS"]
A --> B{"How many servers do you have?"}
B -->|One virtual server| C{"Does your server use<br/>the default port 9987?"}
C -->|Yes| D{"Do all services under this domain<br/>run on the same server<br/>as the TS3 server?"}
D -->|Yes| E1["Use A/AAAA or CNAME"]
D -->|No| E2["Use SRV TS3"]
C -->|No| F{"Are you okay with<br/>entering the port manually?"}
F -->|No| E3["Use SRV TS3"]
F -->|Yes| G{"Do all services under this domain<br/>run on the same server<br/>as the TS3 server?"}
G -->|Yes| E4["Use A/AAAA or CNAME"]
G -->|No| E5["Use SRV TSDNS"]
B -->|More than one virtual server| H{"Are you okay with port numbers?"}
H -->|No| I1["Use subdomains with SRV TS3<br/>for each subdomain"]
H -->|Yes| I{"On how many servers<br/>do you run TS3 servers?"}
I -->|Only one| J{"Do all services under this domain<br/>run on the same server<br/>as the TS3 server?"}
J -->|Yes| K1["Use A/AAAA or CNAME"]
J -->|No| K2["Use SRV TSDNS"]
I -->|More than one| K3["Use subdomains with A/AAAA<br/>or CNAME for each server"]
Library Example
use chanora_resolver::ChanoraResolver;
let client = ChanoraResolver::new()?;
let address = client.resolve_client_address("voice.teamspeak.com").await?;
// tsclientlib:
// let mut connection = tsclientlib::Connection::build(address).connect()?;
// Chanora:
// let cfg = chanora_core::ConnectConfig {
// address,
// nickname,
// password,
// identity,
// ready_timeout,
// };
// let snapshot = session.connect(cfg).await?;
Run
cargo run --example library -- voice.teamspeak.com
cargo run --example library -- 6666
cargo run --example library -- wwb
cargo run --example library -- kr.teamspeak.app
cargo run --example library -- 'ts3server://voice.teamspeak.com?port=9987'
cargo run --example cli -- -host voice.teamspeak.com -service ts3
example_log contains live sample outputs for TS3 SRV, DNS fallback, server-name lookup, and unsuccessful TSDNS attempts that must remain non-fatal.
Fail-Safes
- Bare numeric names such as
6666are treated as server names first, avoiding OS DNS coercion into numeric IPv4 addresses. - SRV targets and TSDNS responses are resolved to final IP addresses before handoff, so Chanora can pass a concrete
SocketAddr-stylehost:porttotsclientlib. - TSDNS TCP lookups use short timeouts and are non-fatal; DNS fallback remains available when TSDNS is absent or unreachable.
- Android uses an explicit SRV resolver configuration instead of relying on system resolver initialization in a raw binary context.
Test
cargo fmt --all -- --check
cargo test
cargo clippy --all-targets --all-features -- -D warnings