106 lines
4.4 KiB
Markdown
106 lines
4.4 KiB
Markdown
# 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:
|
|
|
|
1. Normalize raw client input, including `ts3server://host?port=...`.
|
|
2. For dotless names such as `6666` or `wwb`, query the myTeamSpeak server-name endpoint first. If it returns a hostname, restart normal resolution with that hostname. If it returns `ip:port`, use that final address.
|
|
3. Start plain A/AAAA DNS as the final fallback address.
|
|
4. If the user supplied an explicit port and DNS resolved, return that direct target immediately.
|
|
5. Prefer `_ts3._udp.<host>` SRV. Its target host and port override the default port, then the target is resolved to a final IP.
|
|
6. Try `_tsdns._tcp.<candidate>` SRV on candidate parent/full hosts and query the returned TSDNS server over TCP.
|
|
7. Try direct TSDNS TCP on candidate parent/full hosts at port `41144`.
|
|
8. 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.
|
|
|
|
```mermaid
|
|
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
|
|
|
|
```rust
|
|
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
|
|
|
|
```bash
|
|
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 `6666` are 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`-style `host:port` to `tsclientlib`.
|
|
- 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
|
|
|
|
```bash
|
|
cargo fmt --all -- --check
|
|
cargo test
|
|
cargo clippy --all-targets --all-features -- -D warnings
|
|
```
|