diff --git a/Cargo.lock b/Cargo.lock index 158e017e..c5169714 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,6 +41,54 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + [[package]] name = "async-trait" version = "0.1.74" @@ -52,17 +100,6 @@ dependencies = [ "syn 2.0.41", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -165,27 +202,36 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.25" +version = "4.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" dependencies = [ - "atty", - "bitflags 1.3.2", + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +dependencies = [ + "anstream", + "anstyle", "clap_lex", - "indexmap 1.9.3", "strsim", - "termcolor", - "textwrap", ] [[package]] name = "clap_lex" -version = "0.2.4" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "core-foundation-sys" @@ -442,12 +488,6 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.3" @@ -460,15 +500,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.3" @@ -586,16 +617,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.1.0" @@ -603,7 +624,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown", ] [[package]] @@ -630,7 +651,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi", "rustix", "windows-sys 0.48.0", ] @@ -850,7 +871,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi", "libc", ] @@ -869,12 +890,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1424,12 +1439,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - [[package]] name = "thiserror" version = "1.0.51" @@ -1549,7 +1558,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", @@ -1631,6 +1640,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index b296c5ad..0098b9ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ fern = "0.6" chrono = "0.4" # command -clap = "3.1" +clap = "4" toml = "0.8" serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/src/cmd/flag.rs b/src/cmd/flag.rs index 77f8e8fd..e7003c72 100644 --- a/src/cmd/flag.rs +++ b/src/cmd/flag.rs @@ -1,6 +1,6 @@ -use clap::{Command, Arg}; +#![allow(clippy::let_and_return)] +use clap::{Command, Arg, ArgAction}; -#[allow(clippy::let_and_return)] pub fn add_all(app: Command) -> Command { let app = add_flags(app); let app = add_options(app); @@ -14,36 +14,43 @@ pub fn add_flags(app: Command) -> Command { .short('h') .long("help") .help("show help") + .action(ArgAction::SetTrue) .display_order(0), Arg::new("version") .short('v') .long("version") .help("show version") + .action(ArgAction::SetTrue) .display_order(1), Arg::new("daemon") .short('d') .long("daemon") .help("run as a unix daemon") + .action(ArgAction::SetTrue) .display_order(2), Arg::new("use_udp") .short('u') .long("udp") .help("force enable udp forward") + .action(ArgAction::SetTrue) .display_order(3), Arg::new("no_tcp") .short('t') .long("ntcp") .help("force disable tcp forward") + .action(ArgAction::SetTrue) .display_order(4), Arg::new("fast_open") .short('f') .long("tfo") .help("force enable tcp fast open -- deprecated") + .action(ArgAction::SetTrue) .display_order(5), Arg::new("zero_copy") .short('z') .long("splice") .help("force enable tcp zero copy -- deprecated") + .action(ArgAction::SetTrue) .display_order(6), ]) } @@ -55,49 +62,42 @@ pub fn add_options(app: Command) -> Command { .long("config") .help("use config file") .value_name("path") - .takes_value(true) .display_order(0), Arg::new("local") .short('l') .long("listen") .help("listen address") .value_name("address") - .takes_value(true) .display_order(1), Arg::new("remote") .short('r') .long("remote") .help("remote address") .value_name("address") - .takes_value(true) .display_order(2), Arg::new("through") .short('x') .long("through") .help("send through ip or address") .value_name("address") - .takes_value(true) .display_order(3), Arg::new("interface") .short('i') .long("interface") .help("bind to interface") .value_name("device") - .takes_value(true) .display_order(4), Arg::new("listen_transport") .short('a') .long("listen-transport") .help("listen transport") .value_name("options") - .takes_value(true) .display_order(5), Arg::new("remote_transport") .short('b') .long("remote-transport") .help("remote transport") .value_name("options") - .takes_value(true) .display_order(6), ]) } @@ -110,21 +110,18 @@ pub fn add_global_options(app: Command) -> Command { .long("nofile") .help("set nofile limit") .value_name("limit") - .takes_value(true) .display_order(0), Arg::new("pipe_page") .short('p') .long("pipe-page") .help("set pipe capacity") .value_name("number") - .takes_value(true) .display_order(1), Arg::new("pre_conn_hook") .short('j') .long("pre-conn-hook") .help("set pre-connect hook") .value_name("path") - .takes_value(true) .display_order(2), ]); @@ -134,13 +131,11 @@ pub fn add_global_options(app: Command) -> Command { .long("log-level") .help("override log level") .value_name("level") - .takes_value(true) .display_order(0), Arg::new("log_output") .long("log-output") .help("override log output") .value_name("path") - .takes_value(true) .display_order(1), ]); @@ -150,37 +145,31 @@ pub fn add_global_options(app: Command) -> Command { .long("dns-mode") .help("override dns mode") .value_name("mode") - .takes_value(true) .display_order(0), Arg::new("dns_min_ttl") .long("dns-min-ttl") .help("override dns min ttl") .value_name("second") - .takes_value(true) .display_order(1), Arg::new("dns_max_ttl") .long("dns-max-ttl") .help("override dns max ttl") .value_name("second") - .takes_value(true) .display_order(2), Arg::new("dns_cache_size") .long("dns-cache-size") .help("override dns cache size") .value_name("number") - .takes_value(true) .display_order(3), Arg::new("dns_protocol") .long("dns-protocol") .help("override dns protocol") .value_name("protocol") - .takes_value(true) .display_order(4), Arg::new("dns_servers") .long("dns-servers") .help("override dns servers") .value_name("servers") - .takes_value(true) .display_order(5), ]); @@ -194,7 +183,6 @@ pub fn add_global_options(app: Command) -> Command { .long("send-proxy-version") .help("send proxy protocol version") .value_name("version") - .takes_value(true) .display_order(1), Arg::new("accept_proxy") .long("accept-proxy") @@ -204,7 +192,6 @@ pub fn add_global_options(app: Command) -> Command { .long("accept-proxy-timeout") .help("accept proxy protocol timeout") .value_name("second") - .takes_value(true) .display_order(3), ]); @@ -214,25 +201,21 @@ pub fn add_global_options(app: Command) -> Command { .long("tcp-timeout") .help("override tcp timeout(5s)") .value_name("second") - .takes_value(true) .display_order(0), Arg::new("udp_timeout") .long("udp-timeout") .help("override udp timeout(30s)") .value_name("second") - .takes_value(true) .display_order(1), Arg::new("tcp_keepalive") .long("tcp-keepalive") .help("override default tcp keepalive interval(15s)") .value_name("second") - .takes_value(true) .display_order(2), Arg::new("tcp_keepalive_probe") .long("tcp-keepalive-probe") .help("override default tcp keepalive count(3)") .value_name("count") - .takes_value(true) .display_order(3), ]); diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 56635568..8d89a83e 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -21,10 +21,16 @@ pub enum CmdInput { } pub fn scan() -> CmdInput { + static mut _VER: String = String::new(); // damn! let version = format!("{} {}", VERSION, FEATURES); + let version = unsafe { + _VER = version; + _VER.as_str() + }; + let app = Command::new("Realm") .about("A high efficiency relay tool") - .version(version.as_str()); + .version(version); let app = app .disable_help_flag(true) @@ -40,12 +46,12 @@ pub fn scan() -> CmdInput { let mut app2 = app.clone(); let matches = app.get_matches(); - if matches.is_present("help") { + if matches.get_flag("help") { app2.print_help().unwrap(); return CmdInput::None; } - if matches.is_present("version") { + if matches.get_flag("version") { print!("{}", app2.render_version()); return CmdInput::None; } @@ -65,7 +71,7 @@ pub fn scan() -> CmdInput { fn handle_matches(matches: ArgMatches) -> CmdInput { #[cfg(unix)] - if matches.is_present("daemon") { + if matches.get_flag("daemon") { realm_syscall::daemonize("realm is running in the background"); } @@ -76,7 +82,7 @@ fn handle_matches(matches: ArgMatches) -> CmdInput { use realm_syscall::bump_nofile_limit; // set - if let Some(nofile) = matches.value_of("nofile") { + if let Some(nofile) = matches.get_one::("nofile") { if let Ok(nofile) = nofile.parse::() { let _ = set_nofile_limit(nofile); } else { @@ -96,10 +102,12 @@ fn handle_matches(matches: ArgMatches) -> CmdInput { { use realm_io::set_pipe_size; - if let Some(page) = matches.value_of("pipe_page") { + if let Some(page) = matches.get_one::("pipe_page") { if let Ok(page) = page.parse::() { set_pipe_size(page * 0x1000); println!("pipe capacity: {}", page * 0x1000); + } else { + eprintln!("invalid page value: {}", page); } } } @@ -107,7 +115,7 @@ fn handle_matches(matches: ArgMatches) -> CmdInput { #[cfg(feature = "hook")] { use realm_core::hook::pre_conn::load_dylib as load_pre_conn; - if let Some(path) = matches.value_of("pre_conn_hook") { + if let Some(path) = matches.get_one::("pre_conn_hook") { load_pre_conn(path); println!("hook: {}", path); } @@ -115,11 +123,11 @@ fn handle_matches(matches: ArgMatches) -> CmdInput { let opts = parse_global_opts(&matches); - if let Some(config) = matches.value_of("config") { - return CmdInput::Config(String::from(config), opts); + if let Some(config) = matches.get_one("config").cloned() { + return CmdInput::Config(config, opts); } - if matches.value_of("local").is_some() && matches.value_of("remote").is_some() { + if matches.contains_id("local") && matches.contains_id("remote") { let ep = EndpointConf::from_cmd_args(&matches); return CmdInput::Endpoint(ep, opts); } diff --git a/src/cmd/sub.rs b/src/cmd/sub.rs index e26c986f..98aa7b80 100644 --- a/src/cmd/sub.rs +++ b/src/cmd/sub.rs @@ -27,19 +27,19 @@ pub fn add_convert(app: Command) -> Command { } pub fn handle_convert(matches: &ArgMatches) { - let old = matches.value_of("config").unwrap(); + let old = matches.get_one::("config").unwrap(); let old = fs::read(old).unwrap(); let data: LegacyConf = serde_json::from_slice(&old).unwrap(); let data: FullConf = data.into(); - let data = match matches.value_of("type").unwrap() { + let data = match matches.get_one::("type").unwrap().as_str() { "toml" => toml::to_string(&data).unwrap(), "json" => serde_json::to_string(&data).unwrap(), _ => unreachable!(), }; - if let Some(out) = matches.value_of("output") { + if let Some(out) = matches.get_one::("output") { fs::write(out, &data).unwrap(); } else { println!("{}", &data) diff --git a/src/conf/dns.rs b/src/conf/dns.rs index bea3e9a9..02ded607 100644 --- a/src/conf/dns.rs +++ b/src/conf/dns.rs @@ -298,18 +298,25 @@ impl Config for DnsConf { } fn from_cmd_args(matches: &clap::ArgMatches) -> Self { - let mode = matches.value_of("dns_mode").map(|x| String::from(x).into()); - - let min_ttl = matches.value_of("dns_min_ttl").map(|x| x.parse::().unwrap()); - - let max_ttl = matches.value_of("dns_max_ttl").map(|x| x.parse::().unwrap()); - - let cache_size = matches.value_of("dns_cache_size").map(|x| x.parse::().unwrap()); - - let protocol = matches.value_of("dns_protocol").map(|x| String::from(x).into()); + let mode = matches.get_one::("dns_mode").cloned().map(DnsMode::from); + + let min_ttl = matches + .get_one::("dns_min_ttl") + .and_then(|x| x.parse::().ok()); + let max_ttl = matches + .get_one::("dns_max_ttl") + .and_then(|x| x.parse::().ok()); + let cache_size = matches + .get_one::("dns_cache_size") + .and_then(|x| x.parse::().ok()); + + let protocol = matches + .get_one::("dns_protocol") + .cloned() + .map(DnsProtocol::from); let nameservers = matches - .value_of("dns_servers") + .get_one::("dns_servers") .map(|x| x.split(',').map(String::from).collect()); Self { diff --git a/src/conf/endpoint.rs b/src/conf/endpoint.rs index 201c2b31..7dcac1a9 100644 --- a/src/conf/endpoint.rs +++ b/src/conf/endpoint.rs @@ -199,12 +199,12 @@ impl Config for EndpointConf { } fn from_cmd_args(matches: &clap::ArgMatches) -> Self { - let listen = matches.value_of("local").unwrap().to_string(); - let remote = matches.value_of("remote").unwrap().to_string(); - let through = matches.value_of("through").map(String::from); - let interface = matches.value_of("interface").map(String::from); - let listen_transport = matches.value_of("listen_transport").map(String::from); - let remote_transport = matches.value_of("remote_transport").map(String::from); + let listen = matches.get_one("local").cloned().unwrap(); + let remote = matches.get_one("remote").cloned().unwrap(); + let through = matches.get_one("through").cloned(); + let interface = matches.get_one("interface").cloned(); + let listen_transport = matches.get_one("listen_transport").cloned(); + let remote_transport = matches.get_one("remote_transport").cloned(); EndpointConf { listen, diff --git a/src/conf/log.rs b/src/conf/log.rs index 3191acfb..3fa55531 100644 --- a/src/conf/log.rs +++ b/src/conf/log.rs @@ -119,9 +119,9 @@ impl Config for LogConf { } fn from_cmd_args(matches: &clap::ArgMatches) -> Self { - let level = matches.value_of("log_level").map(|x| String::from(x).into()); + let level = matches.get_one::("log_level").cloned().map(LogLevel::from); - let output = matches.value_of("log_output").map(String::from); + let output = matches.get_one("log_output").cloned(); Self { level, output } } diff --git a/src/conf/net.rs b/src/conf/net.rs index 44d8b496..20ace59f 100644 --- a/src/conf/net.rs +++ b/src/conf/net.rs @@ -157,14 +157,14 @@ impl Config for NetConf { fn from_cmd_args(matches: &clap::ArgMatches) -> Self { macro_rules! unpack { ($key: expr) => { - if matches.is_present($key) { + if matches.get_flag($key) { Some(true) } else { None } }; ($key: expr, $t: ident) => { - matches.value_of($key).map(|x| x.parse::<$t>().unwrap()) + matches.get_one::($key).and_then(|x| x.parse::<$t>().ok()) }; } @@ -176,10 +176,10 @@ impl Config for NetConf { let tcp_timeout = unpack!("tcp_timeout", usize); let udp_timeout = unpack!("udp_timeout", usize); - let send_proxy = unpack!("send_proxy"); + let send_proxy = unpack!("send_proxy", bool); let send_proxy_version = unpack!("send_proxy_version", usize); - let accept_proxy = unpack!("accept_proxy"); + let accept_proxy = unpack!("accept_proxy", bool); let accept_proxy_timeout = unpack!("accept_proxy_timeout", usize); Self {