diff --git a/Cargo.lock b/Cargo.lock index 07ea059..71e764d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,6 +190,12 @@ version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -1089,11 +1095,12 @@ dependencies = [ [[package]] name = "omnip" -version = "0.4.21" +version = "0.4.22" dependencies = [ "android_logger", "anyhow", "async-trait", + "base64 0.22.1", "byte-pool", "chrono", "clap", @@ -1161,7 +1168,7 @@ version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" dependencies = [ - "base64", + "base64 0.21.5", "serde", ] @@ -1520,7 +1527,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64", + "base64 0.21.5", ] [[package]] @@ -1661,7 +1668,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ - "base64", + "base64 0.21.5", "chrono", "hex", "indexmap 1.9.3", diff --git a/Cargo.toml b/Cargo.toml index 2249c83..d7fca0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "omnip" -version = "0.4.21" +version = "0.4.22" edition = "2021" [lib] @@ -34,6 +34,7 @@ http = "0.2" http-body = "0.4" mime_guess = "2.0" monolithica = { git = "https://github.com/neevek/monolithica" } +base64 = "0.22" [dev-dependencies] jni = "0.19" diff --git a/src/bin/omnip.rs b/src/bin/omnip.rs index 250a320..c89f089 100644 --- a/src/bin/omnip.rs +++ b/src/bin/omnip.rs @@ -1,12 +1,21 @@ -use anyhow::Result; +use anyhow::{bail, Context, Result}; +use base64::prelude::*; use clap::builder::TypedValueParser as _; use clap::{builder::PossibleValuesParser, Parser}; +use log::error; use omnip::*; +use rs_utilities::log_and_bail; +use std::env; +use url::Url; extern crate pretty_env_logger; fn main() -> Result<()> { - let args = OmnipArgs::parse(); + let args = parse_args()?; + if print_args_as_base64(&args) { + return Ok(()); + } + let log_filter = format!( "omnip={},rstun={},rs_utilities={}", args.loglevel, args.loglevel, args.loglevel @@ -38,6 +47,54 @@ fn main() -> Result<()> { server.run() } +fn parse_args() -> Result { + let args = OmnipArgs::parse(); + if args.addr.starts_with("opp://") { + match Url::parse(args.addr.as_str()) { + Ok(url) => { + let base64_args = url.host().context("invalid opp args")?.to_string(); + let space_sep_args = String::from_utf8( + BASE64_STANDARD + .decode(base64_args) + .context("invalid base64")?, + )?; + let parts: Vec = space_sep_args + .split_whitespace() + .map(String::from) + .collect(); + let mut vec_args = vec![String::from("")]; // empty string as the first arg (the programm name) + vec_args.extend(parts); + + return Ok(OmnipArgs::parse_from(vec_args)); + } + _ => { + log_and_bail!("invalid addr: {}", args.addr); + } + }; + } + Ok(args) +} + +fn print_args_as_base64(args: &OmnipArgs) -> bool { + if args.print_base64 { + let space_sep_args = env::args_os() + .skip(1) + .filter(|arg| arg != "-P" && arg != "--print-base64") + .map(|arg| { + arg.into_string() + .unwrap_or_else(|os_str| os_str.to_string_lossy().into_owned()) + }) + .collect::>() + .join(" "); + + let base64_args = BASE64_STANDARD.encode(space_sep_args.as_bytes()); + println!("opp://{base64_args}"); + true + } else { + false + } +} + #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] struct OmnipArgs { @@ -46,8 +103,8 @@ struct OmnipArgs { #[arg(short = 'a', long, required = true)] addr: String, - /// upstream which the proxy server will relay traffic to based on proxy rules, [://]ip:port - /// for example: http://127.0.0.1:8000, http+quic://127.0.0.1:8000 + /// upstream which the proxy server will relay traffic to based on proxy rules, + /// [://]ip:port for example: http://127.0.0.1:8000, http+quic://127.0.0.1:8000 #[arg(short = 'u', long, default_value = "")] upstream: String, @@ -63,7 +120,8 @@ struct OmnipArgs { #[arg(long, default_value = "")] dot_server: String, - /// comma saprated domain servers (E.g. 1.1.1.1,8.8.8.8), which will be used if no dot_server is specified, or system default if empty + /// comma saprated domain servers (E.g. 1.1.1.1,8.8.8.8), which will be used + /// if no dot_server is specified, or system default if empty #[arg(long, default_value = "")] name_servers: String, @@ -99,11 +157,11 @@ struct OmnipArgs { #[arg(short = 'R', long, default_value = "5000")] retry_interval_ms: u64, - /// set TCP_NODELAY + /// Set TCP_NODELAY #[arg(long, action)] tcp_nodelay: bool, - /// reload proxy rules if updated + /// Reload proxy rules if updated #[arg(short = 'w', long, action)] watch_proxy_rules_change: bool, @@ -118,4 +176,9 @@ struct OmnipArgs { _ => "info", }.to_string()))] loglevel: String, + + /// Print the args as base64 string to be used in opp:// address, will be ignored if passing in + /// as an opp:// address, which can combine all args as a single base64 string + #[arg(short = 'P', long, action)] + print_base64: bool, } diff --git a/src/server.rs b/src/server.rs index 46858be..9cc4a1c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -157,7 +157,7 @@ impl Server { async fn run_internal(self: &mut Arc) -> Result<()> { info!( - "tcp_nodelay:{}, threads:%{}", + "tcp_nodelay:{}, threads:{}", self.config.tcp_nodelay, self.config.threads ); self.set_and_post_server_state(ServerState::Preparing);