feat: add TeamSpeak address resolver
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
/target/
|
||||
|
||||
# Local editor and OS files.
|
||||
.DS_Store
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Local environment overrides.
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "chanora_resolver"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1"
|
||||
hickory-resolver = { version = "0.26", features = ["tokio", "system-config"] }
|
||||
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"] }
|
||||
tokio = { version = "1", features = ["io-util", "macros", "net", "rt-multi-thread", "signal", "time"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }
|
||||
@@ -0,0 +1,104 @@
|
||||
# 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. Prefer `_ts3._udp.<host>` SRV. Its target host and port override the user input port, then the target is resolved to a final IP.
|
||||
5. Try `_tsdns._tcp.<candidate>` SRV on candidate parent/full hosts and query the returned TSDNS server over TCP.
|
||||
6. Try direct TSDNS TCP on candidate parent/full hosts at port `41144`.
|
||||
7. Fall back to the A/AAAA result with the user-supplied port, or default TeamSpeak port `9987`.
|
||||
|
||||
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
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
use std::{env, process::Command};
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=.git/HEAD");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
let version = env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "development".to_string());
|
||||
let commit = git_output(&["rev-parse", "--short", "HEAD"]).unwrap_or_else(|| "unknown".into());
|
||||
let date =
|
||||
git_output(&["show", "-s", "--format=%cI", "HEAD"]).unwrap_or_else(|| "unknown".into());
|
||||
|
||||
println!("cargo:rustc-env=CHANORA_RESOLVER_BUILD_VERSION={version}");
|
||||
println!("cargo:rustc-env=CHANORA_RESOLVER_BUILD_COMMIT={commit}");
|
||||
println!("cargo:rustc-env=CHANORA_RESOLVER_BUILD_DATE={date}");
|
||||
}
|
||||
|
||||
fn git_output(args: &[&str]) -> Option<String> {
|
||||
let output = Command::new("git").args(args).output().ok()?;
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let value = String::from_utf8(output.stdout).ok()?;
|
||||
Some(value.trim().to_owned())
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
1. -----------
|
||||
|
||||
2026/5/22 21:29:16 ClientUI Info Connect to server: teamspeak.app
|
||||
|
||||
2026/5/22 21:29:16 ClientUI Info Trying to resolve teamspeak.app
|
||||
|
||||
2026/5/22 21:29:16 TSDNS Info A/AAAA DNS resolve successful, "teamspeak.app" =(h: 13.33.183.64 p:0)
|
||||
|
||||
2026/5/22 21:29:16 TSDNS Info A/AAAA DNS resolve for possible TSDNS successful, "teamspeak.app" =(h: 13.33.183.4 p:0)
|
||||
|
||||
2026/5/22 21:29:16 TSDNS Info SRV DNS resolve unsuccessful, "_tsdns._tcp.teamspeak.app" Domain name not found
|
||||
|
||||
2026/5/22 21:29:16 TSDNS Info SRV DNS resolve successful, "_ts3._udp.teamspeak.app" =(h: global.teamspeak.app p:9987)
|
||||
|
||||
2026/5/22 21:29:16 TSDNS Info A/AAAA DNS resolve successful, "global.teamspeak.app" =(h: 103.224.172.62 p:0)
|
||||
|
||||
2026/5/22 21:29:16 ClientUI Info Lookup finished: ip=103.224.172.62 port=9987 query=teamspeak.app error=0
|
||||
|
||||
2026/5/22 21:29:16 ClientUI Info Resolve successful: 103.224.172.62:9987
|
||||
|
||||
2026/5/22 21:29:16 ClientUI Info Initiating connection: 103.224.172.62:9987
|
||||
|
||||
2026/5/22 21:29:16 ClientUI Info Connect status: Connecting
|
||||
|
||||
2026/5/22 21:29:17 PktHandler Info server sent ciphers:1
|
||||
|
||||
2026/5/22 21:29:17 PktHandler Info Selected cipher:0
|
||||
|
||||
2026/5/22 21:29:17 PktHandler Devel Puzzle solve time: 3
|
||||
|
||||
2026/5/22 21:29:18 ClientUI Info Connect status: Connected
|
||||
|
||||
2026/5/22 21:29:18 ClientUI Info Connect status: Establishing connection
|
||||
|
||||
2026/5/22 21:29:18 TSDNS Info TSDNS queried unsuccessfully 13.33.183.4:41144
|
||||
|
||||
2026/5/22 21:29:18 TSDNS Info No TSDNS found
|
||||
|
||||
2026/5/22 21:29:18 ClientUI Info Connect status: Connection established
|
||||
|
||||
|
||||
|
||||
2. ----------
|
||||
|
||||
2026/5/22 21:30:12 ClientUI Info Connect to server: kr.teamspeak.app
|
||||
|
||||
2026/5/22 21:30:12 ClientUI Info Connect status: Disconnected
|
||||
|
||||
2026/5/22 21:30:12 ClientUI Info Disconnected or forced to leave, want autoreconnect = 0
|
||||
|
||||
2026/5/22 21:30:12 ClientUI Info Connecting to next server...
|
||||
|
||||
2026/5/22 21:30:12 ClientUI Info Connect to server: kr.teamspeak.app
|
||||
|
||||
2026/5/22 21:30:12 ClientUI Info Trying to resolve kr.teamspeak.app
|
||||
|
||||
2026/5/22 21:30:12 TSDNS Info A/AAAA DNS resolve for possible TSDNS successful, "teamspeak.app" =(h: 13.33.183.64 p:0)
|
||||
|
||||
2026/5/22 21:30:12 TSDNS Info SRV DNS resolve unsuccessful, "_tsdns._tcp.teamspeak.app" Domain name not found
|
||||
|
||||
2026/5/22 21:30:12 TSDNS Info A/AAAA DNS resolve for possible TSDNS successful, "kr.teamspeak.app" =(h: 140.238.11.238 p:0)
|
||||
|
||||
2026/5/22 21:30:12 TSDNS Info A/AAAA DNS resolve successful, "kr.teamspeak.app" =(h: 140.238.11.238 p:0)
|
||||
|
||||
2026/5/22 21:30:12 TSDNS Info SRV DNS resolve unsuccessful, "_ts3._udp.kr.teamspeak.app" Domain name not found
|
||||
|
||||
2026/5/22 21:30:14 TSDNS Info TSDNS queried unsuccessfully 13.33.183.64:41144
|
||||
|
||||
2026/5/22 21:30:14 TSDNS Info No TSDNS found
|
||||
|
||||
2026/5/22 21:30:14 TSDNS Info TSDNS queried unsuccessfully 140.238.11.238:41144
|
||||
|
||||
2026/5/22 21:30:14 TSDNS Info No TSDNS found
|
||||
|
||||
2026/5/22 21:30:14 ClientUI Info Lookup finished: ip=140.238.11.238 port=9987 query=kr.teamspeak.app error=0
|
||||
|
||||
2026/5/22 21:30:14 ClientUI Info Resolve successful: 140.238.11.238:9987
|
||||
|
||||
2026/5/22 21:30:14 ClientUI Info Initiating connection: 140.238.11.238:9987
|
||||
|
||||
2026/5/22 21:30:14 ClientUI Info Connect status: Connecting
|
||||
|
||||
2026/5/22 21:30:14 PktHandler Info server sent ciphers:1
|
||||
|
||||
2026/5/22 21:30:14 PktHandler Info Selected cipher:0
|
||||
|
||||
2026/5/22 21:30:14 PktHandler Devel Puzzle solve time: 3
|
||||
|
||||
2026/5/22 21:30:15 ClientUI Info Connect status: Connected
|
||||
|
||||
2026/5/22 21:30:15 ClientUI Info Connect status: Establishing connection
|
||||
|
||||
2026/5/22 21:30:15 ClientUI Info Connect status: Connection established
|
||||
|
||||
|
||||
|
||||
3. ---------
|
||||
|
||||
2026/5/22 21:40:35 ClientUI Info Connect to server: 6666
|
||||
|
||||
2026/5/22 21:40:35 ClientUI Info Trying to resolve 6666
|
||||
|
||||
2026/5/22 21:40:35 TSDNS Info Trying to resolve server name: 6666
|
||||
|
||||
2026/5/22 21:40:35 Addon Info Addon up to date.
|
||||
|
||||
2026/5/22 21:40:35 TSDNS Info Server name successfully resolved
|
||||
|
||||
2026/5/22 21:40:35 TSDNS Info Lookup: teamspeak.app, parse result: DNS teamspeak.app 9987
|
||||
|
||||
2026/5/22 21:40:35 TSDNS Info Server name resolved to host: teamspeak.app 9987
|
||||
|
||||
2026/5/22 21:40:35 Addon Info Addon up to date.
|
||||
|
||||
2026/5/22 21:40:35 TSDNS Info A/AAAA DNS resolve successful, "teamspeak.app" =(h: 13.33.183.4 p:0)
|
||||
|
||||
2026/5/22 21:40:35 TSDNS Info A/AAAA DNS resolve for possible TSDNS successful, "teamspeak.app" =(h: 13.33.183.4 p:0)
|
||||
|
||||
2026/5/22 21:40:35 TSDNS Info SRV DNS resolve successful, "_ts3._udp.teamspeak.app" =(h: global.teamspeak.app p:9987)
|
||||
|
||||
2026/5/22 21:40:36 TSDNS Info A/AAAA DNS resolve successful, "global.teamspeak.app" =(h: 103.224.172.62 p:0)
|
||||
|
||||
2026/5/22 21:40:36 ClientUI Info Lookup finished: ip=103.224.172.62 port=9987 query=teamspeak.app error=0
|
||||
|
||||
2026/5/22 21:40:36 ClientUI Info Resolve successful: 103.224.172.62:9987
|
||||
|
||||
2026/5/22 21:40:36 ClientUI Info Initiating connection: 103.224.172.62:9987
|
||||
|
||||
2026/5/22 21:40:36 Windows Audio Session Devel DeviceDeleteList::wait_for_deletes - enter - DeviceDeleteList
|
||||
|
||||
2026/5/22 21:40:36 Windows Audio Session Devel DeviceDeleteList::wait_for_deletes - leave - DeviceDeleteList
|
||||
|
||||
2026/5/22 21:40:36 TSDNS Info SRV DNS resolve unsuccessful, "_tsdns._tcp.teamspeak.app" Domain name not found
|
||||
|
||||
2026/5/22 21:40:36 Windows Audio Session Devel DeviceDeleteList::wait_for_deletes - enter - DeviceDeleteList
|
||||
|
||||
2026/5/22 21:40:36 Windows Audio Session Devel DeviceDeleteList::wait_for_deletes - leave - DeviceDeleteList
|
||||
|
||||
2026/5/22 21:40:36 Direct Sound Warning RenderDeviceContext::int_processData outerLoop proc (3) time: 41 msecs - {E4AE96A7-FDC2-4AF6-8C44-22ADDD8A821B}
|
||||
|
||||
2026/5/22 21:40:36 ClientUI Info Connect status: Connecting
|
||||
|
||||
2026/5/22 21:40:36 Addon Info Addon up to date.
|
||||
|
||||
2026/5/22 21:40:36 PktHandler Info server sent ciphers:1
|
||||
|
||||
2026/5/22 21:40:36 PktHandler Info Selected cipher:0
|
||||
|
||||
2026/5/22 21:40:36 PktHandler Devel Puzzle solve time: 2
|
||||
|
||||
2026/5/22 21:40:36 Addon Info Addon up to date.
|
||||
|
||||
2026/5/22 21:40:37 Info connected to push system.
|
||||
|
||||
2026/5/22 21:40:37 Addon Info Addon up to date.
|
||||
|
||||
2026/5/22 21:40:37 ClientUI Info Connect status: Connected
|
||||
|
||||
2026/5/22 21:40:37 ClientUI Info Connect status: Establishing connection
|
||||
|
||||
2026/5/22 21:40:37 Addon Info Addon up to date.
|
||||
|
||||
2026/5/22 21:40:37 TSDNS Info TSDNS queried unsuccessfully 13.33.183.4:41144
|
||||
|
||||
2026/5/22 21:40:37 TSDNS Info No TSDNS found
|
||||
|
||||
2026/5/22 21:40:37 ClientUI Info Connect status: Connection established
|
||||
|
||||
|
||||
|
||||
4. --------
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Connect to server: voice.teamspeak.com
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Connect status: Disconnected
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Disconnected or forced to leave, want autoreconnect = 0
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Connecting to next server...
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Connect to server: voice.teamspeak.com
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Trying to resolve voice.teamspeak.com
|
||||
|
||||
2026/5/22 21:41:46 TSDNS Info A/AAAA DNS resolve successful, "voice.teamspeak.com" =(h: 148.113.198.70 p:0)
|
||||
|
||||
2026/5/22 21:41:46 TSDNS Info A/AAAA DNS resolve for possible TSDNS successful, "teamspeak.com" =(h: 104.18.4.167 p:0)
|
||||
|
||||
2026/5/22 21:41:46 TSDNS Info A/AAAA DNS resolve for possible TSDNS successful, "voice.teamspeak.com" =(h: 148.113.198.70 p:0)
|
||||
|
||||
2026/5/22 21:41:46 TSDNS Info SRV DNS resolve unsuccessful, "_tsdns._tcp.teamspeak.com" Domain name not found
|
||||
|
||||
2026/5/22 21:41:46 TSDNS Info SRV DNS resolve successful, "_ts3._udp.voice.teamspeak.com" =(h: voice.teamspeak.com p:9987)
|
||||
|
||||
2026/5/22 21:41:46 TSDNS Info A/AAAA DNS resolve successful, "voice.teamspeak.com" =(h: 148.113.198.70 p:0)
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Lookup finished: ip=148.113.198.70 port=9987 query=voice.teamspeak.com error=0
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Resolve successful: 148.113.198.70:9987
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Initiating connection: 148.113.198.70:9987
|
||||
|
||||
2026/5/22 21:41:46 ClientUI Info Connect status: Connecting
|
||||
|
||||
2026/5/22 21:41:46 PktHandler Info server sent ciphers:1
|
||||
|
||||
2026/5/22 21:41:46 PktHandler Info server sent ciphers:1
|
||||
|
||||
2026/5/22 21:41:46 PktHandler Info server sent ciphers:1
|
||||
|
||||
2026/5/22 21:41:47 PktHandler Info server sent ciphers:1
|
||||
|
||||
2026/5/22 21:41:47 PktHandler Info Selected cipher:0
|
||||
|
||||
2026/5/22 21:41:47 PktHandler Devel Puzzle solve time: 2
|
||||
|
||||
2026/5/22 21:41:48 TSDNS Info TSDNS queried unsuccessfully 104.18.4.167:41144
|
||||
|
||||
2026/5/22 21:41:48 TSDNS Info No TSDNS found
|
||||
|
||||
2026/5/22 21:41:48 TSDNS Info TSDNS queried unsuccessfully 148.113.198.70:41144
|
||||
|
||||
2026/5/22 21:41:48 TSDNS Info No TSDNS found
|
||||
|
||||
2026/5/22 21:41:48 ClientUI Info Connect status: Connected
|
||||
|
||||
2026/5/22 21:41:48 ClientUI Info Connect status: Establishing connection
|
||||
|
||||
2026/5/22 21:41:49 ClientUI Info Connect status: Connection established
|
||||
@@ -0,0 +1,102 @@
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use chanora_resolver::{run, setup_log, Args};
|
||||
|
||||
const DEFAULT_SERVICE: &str = "ts3";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
setup_log();
|
||||
|
||||
if let Err(err) = execute(std::env::args().skip(1)).await {
|
||||
tracing::error!(err = %err, "lookup failed");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async fn execute<I, S>(args: I) -> Result<()>
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: Into<String>,
|
||||
{
|
||||
let parsed = parse_args(args)?;
|
||||
run(parsed).await
|
||||
}
|
||||
|
||||
fn parse_args<I, S>(args: I) -> Result<Args>
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: Into<String>,
|
||||
{
|
||||
let mut host = String::new();
|
||||
let mut service = DEFAULT_SERVICE.to_string();
|
||||
let mut protocol = String::new();
|
||||
|
||||
let mut iter = args.into_iter().map(Into::into).peekable();
|
||||
while let Some(arg) = iter.next() {
|
||||
match arg.as_str() {
|
||||
"-h" | "--help" => {
|
||||
print_help();
|
||||
std::process::exit(0);
|
||||
}
|
||||
"-host" | "--host" => {
|
||||
host = next_value(&mut iter, "host")?;
|
||||
}
|
||||
"-service" | "--service" => {
|
||||
service = next_value(&mut iter, "service")?;
|
||||
}
|
||||
"-protocol" | "--protocol" => {
|
||||
protocol = next_value(&mut iter, "protocol")?;
|
||||
}
|
||||
value if value.starts_with('-') => {
|
||||
bail!("unknown flag: {value}");
|
||||
}
|
||||
value => {
|
||||
bail!("unexpected positional argument: {value}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Args {
|
||||
host,
|
||||
service,
|
||||
protocol,
|
||||
})
|
||||
}
|
||||
|
||||
fn next_value<I>(iter: &mut std::iter::Peekable<I>, flag: &str) -> Result<String>
|
||||
where
|
||||
I: Iterator<Item = String>,
|
||||
{
|
||||
iter.next()
|
||||
.ok_or_else(|| anyhow!("missing value for {flag} flag"))
|
||||
}
|
||||
|
||||
fn print_help() {
|
||||
println!("chanora-resolver -host <host> -service <dns|ts3|tsdns|nick> -protocol <udp|tcp>");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_args_supports_flag_pairs() {
|
||||
let args = parse_args([
|
||||
"-host",
|
||||
"Example.com",
|
||||
"-service",
|
||||
"dns",
|
||||
"-protocol",
|
||||
"udp",
|
||||
])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
args,
|
||||
Args {
|
||||
host: "Example.com".into(),
|
||||
service: "dns".into(),
|
||||
protocol: "udp".into(),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
use chanora_resolver::{setup_log, ChanoraResolver};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
setup_log();
|
||||
|
||||
let input = std::env::args()
|
||||
.nth(1)
|
||||
.unwrap_or_else(|| "voice.teamspeak.com".into());
|
||||
|
||||
let client = match ChanoraResolver::new() {
|
||||
Ok(client) => client,
|
||||
Err(err) => {
|
||||
tracing::error!(err = %err, "failed to initialize client");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
match client.resolve_client_request(&input).await {
|
||||
Ok(resolution) => {
|
||||
let connect_addr = resolution.address;
|
||||
tracing::info!(
|
||||
input = %resolution.input,
|
||||
method = ?resolution.method,
|
||||
addr = %connect_addr,
|
||||
"client connection target"
|
||||
);
|
||||
|
||||
// Direct tsclientlib handoff:
|
||||
// let mut connection = tsclientlib::Connection::build(connect_addr).connect()?;
|
||||
//
|
||||
// Chanora handoff:
|
||||
// let cfg = chanora_core::ConnectConfig {
|
||||
// address: connect_addr,
|
||||
// nickname,
|
||||
// password,
|
||||
// identity,
|
||||
// ready_timeout,
|
||||
// };
|
||||
// let snapshot = session.connect(cfg).await?;
|
||||
}
|
||||
Err(err) => {
|
||||
tracing::error!(err = %err, "example lookup failed");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user