feat(tools): add protocol probe and audio test binaries (TODO-044,047)

Protocol probe: connects to server, reports capabilities, channels,
clients. Audio test: DSP pipeline benchmark with configurable params.
This commit is contained in:
Edison Jwa
2026-06-11 21:58:26 +09:00
parent 11a2541042
commit 6c00fae1cf
7 changed files with 4256 additions and 0 deletions
+3735
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
[package]
name = "protocol-probe"
version = "0.1.0"
edition = "2021"
publish = false
[[bin]]
name = "protocol-probe"
path = "src/main.rs"
[dependencies]
chanora_protocol = { path = "../../crates/chanora_protocol" }
chanora_resolver = { path = "../../crates/chanora_resolver" }
tokio = { version = "1", features = ["full"] }
clap = { version = "4", features = ["derive"] }
anyhow = "1"
tracing = "0.1"
tracing-subscriber = "0.3"
serde_json = "1"
+105
View File
@@ -0,0 +1,105 @@
use anyhow::Result;
use clap::Parser;
use chanora_protocol::{ConnectConfig, ProtocolClient};
use chanora_resolver::ChanoraResolver;
#[derive(Parser)]
#[command(name = "protocol-probe", about = "Probe a TeamSpeak server for capabilities and compatibility")]
struct Args {
/// Server address (hostname:port or ts3server:// URL)
server: String,
/// Nickname to use
#[arg(short, long, default_value = "Probe")]
nickname: String,
/// Server password (optional)
#[arg(short, long)]
password: Option<String>,
/// Verbose output
#[arg(short, long)]
verbose: bool,
}
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
let args = Args::parse();
println!("Protocol Probe Tool");
println!("===================");
println!("Server: {}", args.server);
println!();
// Step 1: Resolve address
println!("1. Resolving address...");
let resolver = ChanoraResolver::new()?;
match resolver.resolve_client_address(&args.server).await {
Ok(address) => {
println!(" Resolved: {}", address);
}
Err(e) => {
println!(" Resolution failed: {}", e);
return Ok(());
}
}
// Step 2: Connect
println!("2. Connecting...");
let cfg = ConnectConfig {
address: args.server.clone(),
nickname: args.nickname.clone(),
password: args.password.clone(),
..ConnectConfig::default()
};
let client = match ProtocolClient::connect(cfg).await {
Ok(c) => {
println!(" Connected successfully");
c
}
Err(e) => {
println!(" Connection failed: {}", e);
return Ok(());
}
};
// Step 3: Collect server info
println!("3. Server Info:");
match client.snapshot().await {
Ok(snap) => {
println!(" Name: {}", snap.server_name);
println!(" Platform: {}", snap.platform);
println!(" Version: {}", snap.version);
println!(" Channels: {}", snap.channels.len());
println!(" Clients: {}", snap.clients.len());
println!(" Welcome: {}", snap.welcome_message);
}
Err(e) => {
println!(" Snapshot failed: {}", e);
}
}
// Step 4: Client info
println!("4. Client Info:");
match client.client_profile(0).await {
Ok(profile) => {
println!(" ID: {:?}", profile.database_id);
println!(" Name: {}", profile.name);
println!(" UID: {}", profile.unique_id);
println!(" Server groups: {:?}", profile.server_groups);
println!(" Channel: {:?}", profile.channel);
}
Err(e) => {
println!(" Profile failed: {}", e);
}
}
// Step 5: Disconnect
println!("5. Disconnecting...");
client.disconnect().await;
println!(" Done");
Ok(())
}