From b2c3659f7fa6277871d054c012be847cad900c38 Mon Sep 17 00:00:00 2001 From: ssrlive <30760636+ssrlive@users.noreply.github.com> Date: Mon, 27 Apr 2026 12:16:44 +0800 Subject: [PATCH] Update Android JNI wrapper to parse CLI args with clap try_parse_from; remove legacy C export wrappers from general_api/cbindgen --- cbindgen.toml | 2 -- src/android.rs | 62 +++++++++++++++++++------------------- src/general_api.rs | 75 +--------------------------------------------- 3 files changed, 32 insertions(+), 107 deletions(-) diff --git a/cbindgen.toml b/cbindgen.toml index 50ea65f..5ec4ba2 100644 --- a/cbindgen.toml +++ b/cbindgen.toml @@ -4,8 +4,6 @@ cpp_compat = true [export] include = [ "tun2proxy_run_with_cli", - "tun2proxy_with_fd_run", - "tun2proxy_with_name_run", "tun2proxy_stop", "tun2proxy_set_log_callback", "tun2proxy_set_traffic_status_callback", diff --git a/src/android.rs b/src/android.rs index 837485c..ade2091 100644 --- a/src/android.rs +++ b/src/android.rs @@ -2,56 +2,56 @@ use crate::{ Args, - args::ArgProxy, error::{Error, Result}, }; use jni::{ Env, EnvUnowned, objects::{JClass, JString}, - sys::{jboolean, jchar, jint}, + sys::{jchar, jint}, }; /// # Safety /// /// Running tun2proxy with some arguments /// Parameters: -/// - proxy_url: the proxy url, e.g. "socks5://127.0.0.1:1080" -/// - tun_fd: the tun file descriptor, it will be owned by tun2proxy -/// - close_fd_on_drop: whether close the tun_fd on drop -/// - tun_mtu: the tun mtu -/// - dns_strategy: the dns strategy, see ArgDns enum -/// - verbosity: the verbosity level, see ArgVerbosity enum +/// - cli_args: The command line arguments, +/// e.g. `tun2proxy-bin --tun-fd 43 --close-fd-on-drop false --proxy socks5://127.0.0.1:1080 --dns over-tcp --verbosity trace` +/// - tun_mtu: The MTU of the TUN device, e.g. 1500 #[unsafe(no_mangle)] pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run( mut env: EnvUnowned<'_>, _clazz: JClass<'_>, - proxy_url: JString<'_>, - tun_fd: jint, - close_fd_on_drop: jboolean, + cli_args: JString<'_>, tun_mtu: jchar, - verbosity: jint, - dns_strategy: jint, ) -> jint { - let dns = dns_strategy.try_into().unwrap(); - let verbosity = verbosity.try_into().unwrap(); - let filter_str = &format!("off,tun2proxy={verbosity}"); - let filter = android_logger::FilterBuilder::new().parse(filter_str).build(); - android_logger::init_once( - android_logger::Config::default() - .with_tag("tun2proxy") - .with_max_level(log::LevelFilter::Trace) - .with_filter(filter), - ); env.with_env(|env: &mut Env| -> Result { - let proxy_url = get_java_string(env, &proxy_url).unwrap(); - let proxy = ArgProxy::try_from(proxy_url.as_str()).unwrap(); + let cli_args = get_java_string(env, &cli_args)?; + let tokens = shlex::split(&cli_args).ok_or_else(|| Error::from("Failed to split CLI args"))?; + let tokens_clone = tokens.clone(); + let args = ::try_parse_from(tokens).map_err(|err| Error::from(format!("Parse CLI args: {err}")))?; + + let filter_str = format!("off,tun2proxy={}", args.verbosity); + let filter = android_logger::FilterBuilder::new().parse(&filter_str).build(); + android_logger::init_once( + android_logger::Config::default() + .with_tag("tun2proxy") + .with_max_level(log::LevelFilter::Trace) + .with_filter(filter), + ); + + if !tokens_clone + .iter() + .any(|token| token == "--dns" || token.starts_with("--dns=") || token == "-d" || token.starts_with("-d")) + { + log::error!("--dns is required for Android"); + return Err(Error::from("--dns is required for Android")); + } + + if args.tun_fd.is_none() { + log::error!("tun_fd is required for Android"); + return Err(Error::from("tun_fd is required for Android")); + } - let mut args = Args::default(); - args.proxy(proxy) - .tun_fd(Some(tun_fd)) - .close_fd_on_drop(close_fd_on_drop) - .dns(dns) - .verbosity(verbosity); let v = crate::general_api::general_run_for_api(args, tun_mtu, false); Ok::(v) }) diff --git a/src/general_api.rs b/src/general_api.rs index e5587ef..6377302 100644 --- a/src/general_api.rs +++ b/src/general_api.rs @@ -1,79 +1,6 @@ -use crate::{ - ArgVerbosity, Args, - args::{ArgDns, ArgProxy}, -}; +use crate::Args; use std::os::raw::{c_char, c_int, c_ushort}; -/// # Safety -/// -/// Run the tun2proxy component with some arguments. -/// Parameters: -/// - proxy_url: the proxy url, e.g. "socks5://127.0.0.1:1080" -/// - tun: the tun device name, e.g. "utun5" -/// - bypass: the bypass IP/CIDR, e.g. "123.45.67.0/24" -/// - dns_strategy: the dns strategy, see ArgDns enum -/// - root_privilege: whether to run with root privilege -/// - verbosity: the verbosity level, see ArgVerbosity enum -#[unsafe(no_mangle)] -pub unsafe extern "C" fn tun2proxy_with_name_run( - proxy_url: *const c_char, - tun: *const c_char, - bypass: *const c_char, - dns_strategy: ArgDns, - _root_privilege: bool, - verbosity: ArgVerbosity, -) -> c_int { - let proxy_url = unsafe { std::ffi::CStr::from_ptr(proxy_url) }.to_str().unwrap(); - let proxy = ArgProxy::try_from(proxy_url).unwrap(); - let tun = unsafe { std::ffi::CStr::from_ptr(tun) }.to_str().unwrap().to_string(); - - let mut args = Args::default(); - if let Ok(bypass) = unsafe { std::ffi::CStr::from_ptr(bypass) }.to_str() { - args.bypass(bypass.parse().unwrap()); - } - args.proxy(proxy).tun(tun).dns(dns_strategy).verbosity(verbosity); - - #[cfg(target_os = "linux")] - args.setup(_root_privilege); - - general_run_for_api(args, tun::DEFAULT_MTU, false) -} - -/// # Safety -/// -/// Run the tun2proxy component with some arguments. -/// Parameters: -/// - proxy_url: the proxy url, e.g. "socks5://127.0.0.1:1080" -/// - tun_fd: the tun file descriptor, it will be owned by tun2proxy -/// - close_fd_on_drop: whether close the tun_fd on drop -/// - packet_information: indicates whether exists packet information in packet from TUN device -/// - tun_mtu: the tun mtu -/// - dns_strategy: the dns strategy, see ArgDns enum -/// - verbosity: the verbosity level, see ArgVerbosity enum -#[cfg(unix)] -#[unsafe(no_mangle)] -pub unsafe extern "C" fn tun2proxy_with_fd_run( - proxy_url: *const c_char, - tun_fd: c_int, - close_fd_on_drop: bool, - packet_information: bool, - tun_mtu: c_ushort, - dns_strategy: ArgDns, - verbosity: ArgVerbosity, -) -> c_int { - let proxy_url = unsafe { std::ffi::CStr::from_ptr(proxy_url) }.to_str().unwrap(); - let proxy = ArgProxy::try_from(proxy_url).unwrap(); - - let mut args = Args::default(); - args.proxy(proxy) - .tun_fd(Some(tun_fd)) - .close_fd_on_drop(close_fd_on_drop) - .dns(dns_strategy) - .verbosity(verbosity); - - general_run_for_api(args, tun_mtu, packet_information) -} - /// # Safety /// Run the tun2proxy component with command line arguments /// Parameters: