From dfc24ed12cdee69987bdd321ea55c6b940f2d0f0 Mon Sep 17 00:00:00 2001 From: yyoyoian-pixel <279225925+yyoyoian-pixel@users.noreply.github.com> Date: Sat, 25 Apr 2026 20:46:30 +0200 Subject: [PATCH] feat(android): add udpgw_server parameter to JNI run() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an optional `udpgw_server` JString parameter to the Android JNI `run()` function. When non-empty (e.g. "198.18.0.1:7300"), tun2proxy will forward UDP packets via the udpgw protocol through a TCP connection to the specified address. This enables Android VPN apps using tun2proxy to leverage the existing udpgw support for UDP forwarding (DNS, QUIC, VoIP) without needing to call `tun2proxy_run_with_cli_args` or fork the crate. The parameter is gated behind `#[cfg(feature = "udpgw")]` — when the feature is disabled, the extra JString argument is accepted but ignored, keeping the JNI signature stable. --- src/android.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/android.rs b/src/android.rs index 837485c..03f6e20 100644 --- a/src/android.rs +++ b/src/android.rs @@ -21,6 +21,9 @@ use jni::{ /// - tun_mtu: the tun mtu /// - dns_strategy: the dns strategy, see ArgDns enum /// - verbosity: the verbosity level, see ArgVerbosity enum +/// - udpgw_server: optional udpgw server address (e.g. "198.18.0.1:7300"), +/// empty string to disable. When set, UDP packets are forwarded via the +/// udpgw protocol through a TCP connection to this address. #[unsafe(no_mangle)] pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run( mut env: EnvUnowned<'_>, @@ -31,6 +34,7 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run( tun_mtu: jchar, verbosity: jint, dns_strategy: jint, + udpgw_server: JString<'_>, ) -> jint { let dns = dns_strategy.try_into().unwrap(); let verbosity = verbosity.try_into().unwrap(); @@ -52,6 +56,18 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run( .close_fd_on_drop(close_fd_on_drop) .dns(dns) .verbosity(verbosity); + + #[cfg(feature = "udpgw")] + { + let udpgw_str = get_java_string(env, &udpgw_server).unwrap_or_default(); + if !udpgw_str.is_empty() { + if let Ok(addr) = udpgw_str.parse::() { + args.udpgw_server(addr); + log::info!("udpgw_server={}", addr); + } + } + } + let v = crate::general_api::general_run_for_api(args, tun_mtu, false); Ok::(v) })