use clap::{Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(name = "gout", version, about = "轻量内网穿透工具")]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Subcommand, Debug)]
pub enum Command {
Login {
name: Option<String>,
server: String,
key: String,
},
Tcp {
port: u16,
#[arg(long, short = 'd')]
detach: bool,
#[arg(long, short = 's')]
server: Option<String>,
},
Udp {
port: u16,
#[arg(long, short = 'd')]
detach: bool,
#[arg(long, short = 's')]
server: Option<String>,
},
Http {
port: u16,
#[arg(long, short = 'd')]
detach: bool,
#[arg(long, short = 's')]
server: Option<String>,
},
List,
Log {
port: u16,
#[arg(long, short = 'f')]
follow: bool,
},
Kill {
port: u16,
},
Default {
name: String,
},
Show,
}
impl Cli {
pub fn run() -> anyhow::Result<()> {
let cli = Cli::parse();
if let Some(pidfile) = std::env::var("GOUT_DAEMON_PIDFILE").ok() {
let result = match cli.command {
Command::Tcp { port, .. } => crate::cmd_tunnel("tcp", port, None),
Command::Udp { port, .. } => crate::cmd_tunnel("udp", port, None),
Command::Http { port, .. } => crate::cmd_tunnel("http", port, None),
_ => anyhow::bail!("daemon mode unsupported for this command"),
};
std::fs::remove_file(&pidfile).ok();
return result;
}
match cli.command {
Command::Login { name, server, key } => {
let n = name.unwrap_or_else(|| {
server.split(':').next().unwrap_or(&server).to_string()
});
crate::cmd_login(&n, &server, &key)
}
Command::Tcp { port, detach: true, server } => crate::cmd_start_daemon("tcp", port, server.as_deref()),
Command::Tcp { port, detach: false, server } => crate::cmd_tunnel("tcp", port, server.as_deref()),
Command::Udp { port, detach: true, server } => crate::cmd_start_daemon("udp", port, server.as_deref()),
Command::Udp { port, detach: false, server } => crate::cmd_tunnel("udp", port, server.as_deref()),
Command::Http { port, detach: true, server } => crate::cmd_start_daemon("http", port, server.as_deref()),
Command::Http { port, detach: false, server } => crate::cmd_tunnel("http", port, server.as_deref()),
Command::Log { port, follow } => crate::cmd_log(port, follow),
Command::Kill { port } => crate::cmd_kill(port),
Command::List => crate::cmd_list(),
Command::Default { name } => crate::cmd_set_default(&name),
Command::Show => crate::cmd_show(),
}
}
}