2023-04-14 18:44:41 +08:00
|
|
|
#![cfg(target_os = "android")]
|
|
|
|
|
2023-07-23 02:03:15 +08:00
|
|
|
use crate::{error::Error, tun2proxy::TunToProxy, tun_to_proxy, NetworkInterface, Options, Proxy};
|
2023-04-14 18:44:41 +08:00
|
|
|
use jni::{
|
|
|
|
objects::{JClass, JString},
|
|
|
|
sys::{jboolean, jint},
|
|
|
|
JNIEnv,
|
|
|
|
};
|
|
|
|
|
2023-04-27 22:41:54 +02:00
|
|
|
static mut TUN_TO_PROXY: Option<TunToProxy> = None;
|
|
|
|
|
2023-04-14 18:44:41 +08:00
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// Running tun2proxy
|
|
|
|
#[no_mangle]
|
|
|
|
pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run(
|
|
|
|
mut env: JNIEnv,
|
|
|
|
_clazz: JClass,
|
|
|
|
proxy_url: JString,
|
|
|
|
tun_fd: jint,
|
|
|
|
tun_mtu: jint,
|
|
|
|
verbose: jboolean,
|
|
|
|
) -> jint {
|
|
|
|
let log_level = if verbose != 0 { "trace" } else { "info" };
|
|
|
|
let filter_str = &format!("off,tun2proxy={log_level}");
|
2023-08-08 23:45:16 +08:00
|
|
|
let filter = android_logger::FilterBuilder::new().parse(filter_str).build();
|
2023-04-14 18:44:41 +08:00
|
|
|
android_logger::init_once(
|
|
|
|
android_logger::Config::default()
|
|
|
|
.with_tag("tun2proxy")
|
|
|
|
.with_max_level(log::LevelFilter::Trace)
|
|
|
|
.with_filter(filter),
|
|
|
|
);
|
|
|
|
|
|
|
|
let mut block = || -> Result<(), Error> {
|
|
|
|
let proxy_url = get_java_string(&mut env, &proxy_url)?;
|
|
|
|
let proxy = Proxy::from_url(proxy_url)?;
|
|
|
|
|
|
|
|
let addr = proxy.addr;
|
|
|
|
let proxy_type = proxy.proxy_type;
|
|
|
|
log::info!("Proxy {proxy_type} server: {addr}");
|
|
|
|
|
|
|
|
let options = Options::new().with_virtual_dns().with_mtu(tun_mtu as usize);
|
|
|
|
|
|
|
|
let interface = NetworkInterface::Fd(tun_fd);
|
2023-04-27 22:41:54 +02:00
|
|
|
let tun2proxy = tun_to_proxy(&interface, &proxy, options)?;
|
|
|
|
TUN_TO_PROXY = Some(tun2proxy);
|
|
|
|
if let Some(tun2proxy) = &mut TUN_TO_PROXY {
|
|
|
|
tun2proxy.run()?;
|
|
|
|
}
|
2023-04-14 18:44:41 +08:00
|
|
|
Ok::<(), Error>(())
|
|
|
|
};
|
|
|
|
if let Err(error) = block() {
|
|
|
|
log::error!("failed to run tun2proxy with error: {:?}", error);
|
|
|
|
}
|
|
|
|
0
|
|
|
|
}
|
|
|
|
|
|
|
|
/// # Safety
|
|
|
|
///
|
|
|
|
/// Shutdown tun2proxy
|
|
|
|
#[no_mangle]
|
2023-08-08 23:45:16 +08:00
|
|
|
pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_stop(_env: JNIEnv, _: JClass) -> jint {
|
2023-04-27 22:41:54 +02:00
|
|
|
match &mut TUN_TO_PROXY {
|
|
|
|
None => {
|
|
|
|
log::error!("tun2proxy not started");
|
|
|
|
1
|
|
|
|
}
|
|
|
|
Some(tun2proxy) => {
|
|
|
|
if let Err(e) = tun2proxy.shutdown() {
|
|
|
|
log::error!("failed to shutdown tun2proxy with error: {:?}", e);
|
|
|
|
1
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
}
|
|
|
|
}
|
2023-04-14 18:44:41 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn get_java_string<'a>(env: &'a mut JNIEnv, string: &'a JString) -> Result<&'a str, Error> {
|
|
|
|
let str_ptr = env.get_string(string)?.as_ptr();
|
|
|
|
let s: &str = std::ffi::CStr::from_ptr(str_ptr).to_str()?;
|
|
|
|
Ok(s)
|
|
|
|
}
|