mod cli;
mod config;
mod tunnel;
use anyhow::Result;
fn main() -> Result<()> {
tracing_subscriber::fmt().init();
cli::Cli::run()
}
fn cmd_login(server: &str, key: &str) -> Result<()> {
config::write(server, key)?;
println!("[+] saved to ~/.goutrc (server: {server})");
Ok(())
}
fn cmd_list() -> Result<()> {
let cfg = config::read()?;
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async {
let gout = gout_api::client::GoutClient::new(&cfg.server.addr, &cfg.server.api_key);
let tunnels = gout.list_tunnels().await?;
if tunnels.is_empty() {
println!("[*] no active tunnels");
} else {
println!("{:<20} {:>5} {:>4} {:>7}", "TUNNEL_ID", "PORT", "TYPE", "STATUS");
for t in &tunnels {
let status = if t.connected { "active" } else { "waiting" };
println!("{:<20} {:>5} {:>4} {:>7}", t.token.to_string(), t.public_port, t.tunnel_type, status);
}
}
Ok(())
})
}
fn cmd_tunnel(tunnel_type: &str, local_port: u16) -> Result<()> {
let cfg = config::read()?;
let tt = gout_api::TunnelType::parse(tunnel_type);
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async {
tunnel::TunnelSession::create(cfg, tt, local_port).await?;
Ok(())
})
}