diff --git a/Cargo.lock b/Cargo.lock index 4b21695..fc42871 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3961,7 +3961,8 @@ dependencies = [ [[package]] name = "tun2proxy" version = "0.7.21" -source = "git+https://github.com/yyoyoian-pixel/tun2proxy?branch=feat%2Fudpgw-jni-param#dfc24ed12cdee69987bdd321ea55c6b940f2d0f0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336ad07beb04a9e219972fcdc54a71d2586cdfd35ac03551a629e4ca328db3c" dependencies = [ "android_logger", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 2ef3b1f..003d362 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -100,12 +100,6 @@ tun2proxy = { version = "0.7", default-features = false, features = ["udpgw"] } # Used in mitm tests to sanity-check the cert extensions we emit. x509-parser = "0.16" -# Temporary patch: adds udpgw_server parameter to the Android JNI run() -# function. Upstream PR: https://github.com/tun2proxy/tun2proxy/pull/247 -# Remove this section once tun2proxy >= 0.8 ships with the change. -[patch.crates-io] -tun2proxy = { git = "https://github.com/yyoyoian-pixel/tun2proxy", branch = "feat/udpgw-jni-param" } - [profile.release] panic = "abort" codegen-units = 1 diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 6f64f46..4362ad1 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -136,6 +136,10 @@ dependencies { implementation("androidx.compose.material3:material3") implementation("androidx.compose.material:material-icons-extended") + // QR code generation + scanning (self-contained, no ML Kit needed). + implementation("com.google.zxing:core:3.5.3") + implementation("com.journeyapps:zxing-android-embedded:4.3.0") + debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index dd2e94e..4d74ca5 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -53,8 +53,33 @@ + + + + + + + + + + + + + + + %1$d lines + + Paste config from clipboard + Export config + Show QR code + Scan QR code + Copy to clipboard + Config imported + Config copied to clipboard + Invalid config in clipboard + Export config + This includes your auth_key. Only share with people you trust. + Import config? + This will replace your current settings. + Camera permission needed to scan QR codes + google_ip updated to %1$s google_ip already current (%1$s) diff --git a/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..1e63d10 --- /dev/null +++ b/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/android_jni.rs b/src/android_jni.rs index 6f467be..6bb5a97 100644 --- a/src/android_jni.rs +++ b/src/android_jni.rs @@ -482,3 +482,53 @@ pub extern "system" fn Java_com_therealaleph_mhrv_Native_statsJson<'a>( })); env.new_string(out).map(|s| s.into_raw()).unwrap_or(std::ptr::null_mut()) } + +// --------------------------------------------------------------------------- +// tun2proxy CLI API wrapper (dlsym — no fork or patch needed) +// --------------------------------------------------------------------------- + +/// `Native.runTun2proxy(cliArgs, tunMtu)` -> int +/// +/// Calls `tun2proxy_run_with_cli_args` from libtun2proxy.so via dlsym. +/// This is the C API the tun2proxy maintainer recommends for callers that +/// need full CLI flexibility (e.g. --udpgw-server). BLOCKS until shutdown. +#[no_mangle] +pub extern "system" fn Java_com_therealaleph_mhrv_Native_runTun2proxy<'a>( + mut env: JNIEnv<'a>, + _class: JClass, + cli_args: JString, + tun_mtu: jni::sys::jint, +) -> jni::sys::jint { + safe(-1, AssertUnwindSafe(|| { + let args_str = jstring_to_string(&mut env, &cli_args); + tracing::info!("runTun2proxy: cli={}", args_str); + + unsafe { + use std::ffi::{CStr, CString}; + + let lib = CString::new("libtun2proxy.so").unwrap(); + let handle = libc::dlopen(lib.as_ptr(), libc::RTLD_NOW); + if handle.is_null() { + let err = CStr::from_ptr(libc::dlerror()); + tracing::error!("dlopen libtun2proxy.so failed: {:?}", err); + return -10; + } + + let sym = CString::new("tun2proxy_run_with_cli_args").unwrap(); + let func = libc::dlsym(handle, sym.as_ptr()); + if func.is_null() { + let err = CStr::from_ptr(libc::dlerror()); + tracing::error!("dlsym tun2proxy_run_with_cli_args: {:?}", err); + libc::dlclose(handle); + return -11; + } + + type RunFn = unsafe extern "C" fn(*const std::ffi::c_char, u16, bool) -> i32; + let run: RunFn = std::mem::transmute(func); + let c_args = CString::new(args_str).unwrap(); + let rc = run(c_args.as_ptr(), tun_mtu as u16, false); + libc::dlclose(handle); + rc + } + })) +}