feat: add TeamSpeak address resolver
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user