mirror of
https://github.com/tun2proxy/tun2proxy.git
synced 2025-04-19 21:39:09 +00:00
Ffi2 (#90)
This commit is contained in:
parent
a26621bbcd
commit
a1083273ee
9 changed files with 187 additions and 230 deletions
|
@ -32,7 +32,7 @@ tokio = { version = "1.36", features = ["full"] }
|
|||
tokio-util = "0.7"
|
||||
tproxy-config = { version = "0.1", features = ["log"] }
|
||||
trust-dns-proto = "0.23"
|
||||
tun2 = { version = "1.0", features = ["async"] }
|
||||
tun2 = { version = "1.1", features = ["async"] }
|
||||
udp-stream = { version = "0.0", default-features = false }
|
||||
unicase = "2.7"
|
||||
url = "2.5"
|
||||
|
|
|
@ -39,7 +39,7 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run(
|
|||
|
||||
let mut args = Args::default();
|
||||
args.proxy(proxy).tun_fd(Some(tun_fd)).dns(dns).verbosity(verbosity);
|
||||
crate::api::tun2proxy_internal_run(args, tun_mtu)
|
||||
crate::mobile_api::mobile_run(args, tun_mtu)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
|
@ -47,7 +47,7 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run(
|
|||
/// Shutdown tun2proxy
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_stop(_env: JNIEnv, _: JClass) -> jint {
|
||||
crate::api::tun2proxy_internal_stop()
|
||||
crate::mobile_api::mobile_stop()
|
||||
}
|
||||
|
||||
unsafe fn get_java_string<'a>(env: &'a mut JNIEnv, string: &'a JString) -> Result<&'a str, Error> {
|
||||
|
|
|
@ -1,72 +1,16 @@
|
|||
use tokio_util::sync::CancellationToken;
|
||||
use tproxy_config::{TproxyArgs, TUN_GATEWAY, TUN_IPV4, TUN_NETMASK};
|
||||
use tun2::DEFAULT_MTU as MTU;
|
||||
use tun2proxy::{self, Args};
|
||||
use tun2proxy::{desktop_run_async, Args, BoxError};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
async fn main() -> Result<(), BoxError> {
|
||||
dotenvy::dotenv().ok();
|
||||
let args = Args::parse_args();
|
||||
|
||||
let bypass_ips = args.bypass.clone();
|
||||
|
||||
// let default = format!("{}={:?}", module_path!(), args.verbosity);
|
||||
let default = format!("{:?}", args.verbosity);
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(default)).init();
|
||||
|
||||
let mut config = tun2::Configuration::default();
|
||||
config.address(TUN_IPV4).netmask(TUN_NETMASK).mtu(MTU).up();
|
||||
config.destination(TUN_GATEWAY);
|
||||
if let Some(tun_fd) = args.tun_fd {
|
||||
config.raw_fd(tun_fd);
|
||||
} else {
|
||||
config.name(&args.tun);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
config.platform_config(|config| {
|
||||
#[allow(deprecated)]
|
||||
config.packet_information(true);
|
||||
config.ensure_root_privileges(args.setup);
|
||||
});
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
config.platform_config(|config| {
|
||||
config.device_guid(Some(12324323423423434234_u128));
|
||||
});
|
||||
|
||||
#[allow(unused_variables)]
|
||||
let mut tproxy_args = TproxyArgs::new()
|
||||
.tun_dns(args.dns_addr)
|
||||
.proxy_addr(args.proxy.addr)
|
||||
.bypass_ips(&bypass_ips);
|
||||
#[allow(unused_assignments)]
|
||||
if args.tun_fd.is_none() {
|
||||
tproxy_args = tproxy_args.tun_name(&args.tun);
|
||||
}
|
||||
|
||||
#[allow(unused_mut, unused_assignments, unused_variables)]
|
||||
let mut setup = true;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
setup = args.setup;
|
||||
if setup {
|
||||
tproxy_config::tproxy_setup(&tproxy_args)?;
|
||||
}
|
||||
}
|
||||
|
||||
let device = tun2::create_as_async(&config)?;
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
if setup {
|
||||
tproxy_config::tproxy_setup(&tproxy_args)?;
|
||||
}
|
||||
|
||||
log::info!("Proxy {} server: {}", args.proxy.proxy_type, args.proxy.addr);
|
||||
|
||||
let shutdown_token = CancellationToken::new();
|
||||
let join_handle = tokio::spawn(tun2proxy::run(device, MTU, args, shutdown_token.clone()));
|
||||
let shutdown_token = tokio_util::sync::CancellationToken::new();
|
||||
let join_handle = tokio::spawn(desktop_run_async(args, shutdown_token.clone()));
|
||||
|
||||
ctrlc2::set_async_handler(async move {
|
||||
log::info!("Ctrl-C received, exiting...");
|
||||
|
@ -78,10 +22,5 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
log::trace!("main_entry error {}", err);
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
|
||||
if setup {
|
||||
tproxy_config::tproxy_remove(&tproxy_args)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
148
src/desktop_api.rs
Normal file
148
src/desktop_api.rs
Normal file
|
@ -0,0 +1,148 @@
|
|||
#![cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
|
||||
|
||||
use crate::{
|
||||
args::{ArgDns, ArgProxy},
|
||||
ArgVerbosity, Args,
|
||||
};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use tproxy_config::{TproxyArgs, TUN_GATEWAY, TUN_IPV4, TUN_NETMASK};
|
||||
use tun2::DEFAULT_MTU as MTU;
|
||||
|
||||
static TUN_QUIT: std::sync::Mutex<Option<tokio_util::sync::CancellationToken>> = std::sync::Mutex::new(None);
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Run the tun2proxy component with some arguments.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tun2proxy_run_with_name(
|
||||
proxy_url: *const c_char,
|
||||
tun: *const c_char,
|
||||
bypass: *const c_char,
|
||||
dns_strategy: ArgDns,
|
||||
_root_privilege: bool,
|
||||
verbosity: ArgVerbosity,
|
||||
) -> c_int {
|
||||
let shutdown_token = tokio_util::sync::CancellationToken::new();
|
||||
{
|
||||
if let Ok(mut lock) = TUN_QUIT.lock() {
|
||||
if lock.is_some() {
|
||||
return -1;
|
||||
}
|
||||
*lock = Some(shutdown_token.clone());
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
log::set_max_level(verbosity.into());
|
||||
log::set_boxed_logger(Box::<crate::dump_logger::DumpLogger>::default()).unwrap();
|
||||
|
||||
let proxy_url = std::ffi::CStr::from_ptr(proxy_url).to_str().unwrap();
|
||||
let proxy = ArgProxy::from_url(proxy_url).unwrap();
|
||||
let tun = std::ffi::CStr::from_ptr(tun).to_str().unwrap().to_string();
|
||||
|
||||
let mut args = Args::default();
|
||||
args.proxy(proxy).tun(tun).dns(dns_strategy).verbosity(verbosity);
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
args.setup(_root_privilege);
|
||||
|
||||
if let Ok(bypass) = std::ffi::CStr::from_ptr(bypass).to_str() {
|
||||
args.bypass(bypass.parse().unwrap());
|
||||
}
|
||||
|
||||
let exit_code = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
|
||||
Err(_e) => -3,
|
||||
Ok(rt) => match rt.block_on(desktop_run_async(args, shutdown_token)) {
|
||||
Ok(_) => 0,
|
||||
Err(_e) => -4,
|
||||
},
|
||||
};
|
||||
|
||||
// release shutdown token before exit.
|
||||
if let Ok(mut lock) = TUN_QUIT.lock() {
|
||||
let _ = lock.take();
|
||||
}
|
||||
|
||||
exit_code
|
||||
}
|
||||
|
||||
/// Run the tun2proxy component with some arguments.
|
||||
pub async fn desktop_run_async(args: Args, shutdown_token: tokio_util::sync::CancellationToken) -> std::io::Result<()> {
|
||||
let bypass_ips = args.bypass.clone();
|
||||
|
||||
let mut config = tun2::Configuration::default();
|
||||
config.address(TUN_IPV4).netmask(TUN_NETMASK).mtu(MTU).up();
|
||||
config.destination(TUN_GATEWAY);
|
||||
if let Some(tun_fd) = args.tun_fd {
|
||||
config.raw_fd(tun_fd);
|
||||
} else {
|
||||
config.name(&args.tun);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
config.platform_config(|config| {
|
||||
#[allow(deprecated)]
|
||||
config.packet_information(true);
|
||||
config.ensure_root_privileges(args.setup);
|
||||
});
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
config.platform_config(|config| {
|
||||
config.device_guid(Some(12324323423423434234_u128));
|
||||
});
|
||||
|
||||
#[allow(unused_variables)]
|
||||
let mut tproxy_args = TproxyArgs::new()
|
||||
.tun_dns(args.dns_addr)
|
||||
.proxy_addr(args.proxy.addr)
|
||||
.bypass_ips(&bypass_ips);
|
||||
#[allow(unused_assignments)]
|
||||
if args.tun_fd.is_none() {
|
||||
tproxy_args = tproxy_args.tun_name(&args.tun);
|
||||
}
|
||||
|
||||
#[allow(unused_mut, unused_assignments, unused_variables)]
|
||||
let mut setup = true;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
setup = args.setup;
|
||||
if setup {
|
||||
tproxy_config::tproxy_setup(&tproxy_args)?;
|
||||
}
|
||||
}
|
||||
|
||||
let device = tun2::create_as_async(&config)?;
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
if setup {
|
||||
tproxy_config::tproxy_setup(&tproxy_args)?;
|
||||
}
|
||||
|
||||
log::info!("Proxy {} server: {}", args.proxy.proxy_type, args.proxy.addr);
|
||||
|
||||
let join_handle = tokio::spawn(crate::run(device, MTU, args, shutdown_token));
|
||||
join_handle.await.map_err(std::io::Error::from)??;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
|
||||
if setup {
|
||||
tproxy_config::tproxy_remove(&tproxy_args)?;
|
||||
}
|
||||
|
||||
Ok::<(), std::io::Error>(())
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Shutdown the tun2proxy component.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tun2proxy_stop() -> c_int {
|
||||
if let Ok(lock) = TUN_QUIT.lock() {
|
||||
if let Some(shutdown_token) = lock.as_ref() {
|
||||
shutdown_token.cancel();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
|
@ -6,18 +6,19 @@ use std::{
|
|||
|
||||
pub(crate) static DUMP_CALLBACK: Mutex<Option<DumpCallback>> = Mutex::new(None);
|
||||
|
||||
pub type RawCallback = unsafe extern "C" fn(ArgVerbosity, *const c_char, *mut c_void);
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// set dump log info callback.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tun2proxy_set_log_callback(callback: Option<RawCallback>, ctx: *mut c_void) {
|
||||
pub unsafe extern "C" fn tun2proxy_set_log_callback(
|
||||
callback: Option<unsafe extern "C" fn(ArgVerbosity, *const c_char, *mut c_void)>,
|
||||
ctx: *mut c_void,
|
||||
) {
|
||||
*DUMP_CALLBACK.lock().unwrap() = Some(DumpCallback(callback, ctx));
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DumpCallback(Option<RawCallback>, *mut c_void);
|
||||
pub struct DumpCallback(Option<unsafe extern "C" fn(ArgVerbosity, *const c_char, *mut c_void)>, *mut c_void);
|
||||
|
||||
impl DumpCallback {
|
||||
unsafe fn call(self, dump_level: ArgVerbosity, info: *const c_char) {
|
||||
|
|
140
src/ffi.rs
140
src/ffi.rs
|
@ -1,140 +0,0 @@
|
|||
#![cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
|
||||
|
||||
use crate::{
|
||||
args::{ArgDns, ArgProxy},
|
||||
ArgVerbosity, Args,
|
||||
};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tproxy_config::{TproxyArgs, TUN_GATEWAY, TUN_IPV4, TUN_NETMASK};
|
||||
use tun2::DEFAULT_MTU as MTU;
|
||||
|
||||
static TUN_QUIT: std::sync::Mutex<Option<CancellationToken>> = std::sync::Mutex::new(None);
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Run the tun2proxy component with some arguments.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tun2proxy_run_with_name(
|
||||
proxy_url: *const c_char,
|
||||
tun: *const c_char,
|
||||
bypass: *const c_char,
|
||||
dns_strategy: ArgDns,
|
||||
_root_privilege: bool,
|
||||
verbosity: ArgVerbosity,
|
||||
) -> c_int {
|
||||
let shutdown_token = CancellationToken::new();
|
||||
{
|
||||
if let Ok(mut lock) = TUN_QUIT.lock() {
|
||||
if lock.is_some() {
|
||||
log::error!("tun2proxy already started");
|
||||
return -1;
|
||||
}
|
||||
*lock = Some(shutdown_token.clone());
|
||||
} else {
|
||||
log::error!("tun2proxy unknown error");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
log::set_max_level(verbosity.into());
|
||||
log::set_boxed_logger(Box::<crate::dump_logger::DumpLogger>::default()).unwrap();
|
||||
|
||||
let proxy_url = std::ffi::CStr::from_ptr(proxy_url).to_str().unwrap();
|
||||
let proxy = ArgProxy::from_url(proxy_url).unwrap();
|
||||
let tun = std::ffi::CStr::from_ptr(tun).to_str().unwrap().to_string();
|
||||
|
||||
let mut args = Args::default();
|
||||
args.proxy(proxy).tun(tun).dns(dns_strategy).verbosity(verbosity);
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
args.setup(_root_privilege);
|
||||
|
||||
if let Ok(bypass) = std::ffi::CStr::from_ptr(bypass).to_str() {
|
||||
args.bypass(bypass.parse().unwrap());
|
||||
}
|
||||
|
||||
let block = async move {
|
||||
let bypass_ips = args.bypass.clone();
|
||||
|
||||
let mut config = tun2::Configuration::default();
|
||||
config.address(TUN_IPV4).netmask(TUN_NETMASK).mtu(MTU).up();
|
||||
config.destination(TUN_GATEWAY);
|
||||
if let Some(tun_fd) = args.tun_fd {
|
||||
config.raw_fd(tun_fd);
|
||||
} else {
|
||||
config.name(&args.tun);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
config.platform_config(|config| {
|
||||
#[allow(deprecated)]
|
||||
config.packet_information(true);
|
||||
config.ensure_root_privileges(args.setup);
|
||||
});
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
config.platform_config(|config| {
|
||||
config.device_guid(Some(12324323423423434234_u128));
|
||||
});
|
||||
|
||||
#[allow(unused_variables)]
|
||||
let mut tproxy_args = TproxyArgs::new()
|
||||
.tun_dns(args.dns_addr)
|
||||
.proxy_addr(args.proxy.addr)
|
||||
.bypass_ips(&bypass_ips);
|
||||
#[allow(unused_assignments)]
|
||||
if args.tun_fd.is_none() {
|
||||
tproxy_args = tproxy_args.tun_name(&args.tun);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
tproxy_config::tproxy_setup(&tproxy_args)?;
|
||||
|
||||
let device = tun2::create_as_async(&config)?;
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
tproxy_config::tproxy_setup(&tproxy_args)?;
|
||||
|
||||
log::info!("Proxy {} server: {}", args.proxy.proxy_type, args.proxy.addr);
|
||||
|
||||
let join_handle = tokio::spawn(crate::run(device, MTU, args, shutdown_token));
|
||||
join_handle.await.map_err(std::io::Error::from)??;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
|
||||
if _root_privilege {
|
||||
tproxy_config::tproxy_remove(&tproxy_args)?;
|
||||
}
|
||||
|
||||
Ok::<(), crate::BoxError>(())
|
||||
};
|
||||
|
||||
let exit_code = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
|
||||
Err(_e) => -1,
|
||||
Ok(rt) => match rt.block_on(block) {
|
||||
Ok(_) => 0,
|
||||
Err(_e) => -2,
|
||||
},
|
||||
};
|
||||
|
||||
// release shutdown token before exit.
|
||||
if let Ok(mut lock) = TUN_QUIT.lock() {
|
||||
let _ = lock.take();
|
||||
}
|
||||
|
||||
exit_code
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Shutdown the tun2proxy component.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tun2proxy_stop() -> c_int {
|
||||
if let Ok(lock) = TUN_QUIT.lock() {
|
||||
if let Some(shutdown_token) = lock.as_ref() {
|
||||
shutdown_token.cancel();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
|
@ -26,7 +26,7 @@ pub unsafe extern "C" fn tun2proxy_run_with_fd(
|
|||
let mut args = Args::default();
|
||||
args.proxy(proxy).tun_fd(Some(tun_fd)).dns(dns_strategy).verbosity(verbosity);
|
||||
|
||||
crate::api::tun2proxy_internal_run(args, tun_mtu)
|
||||
crate::mobile_api::mobile_run(args, tun_mtu)
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
|
@ -34,5 +34,5 @@ pub unsafe extern "C" fn tun2proxy_run_with_fd(
|
|||
/// Shutdown the tun2proxy component.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn tun2proxy_stop() -> c_int {
|
||||
crate::api::tun2proxy_internal_stop()
|
||||
crate::mobile_api::mobile_stop()
|
||||
}
|
||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -23,16 +23,22 @@ pub use {
|
|||
error::{BoxError, Error, Result},
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos", target_os = "linux"))]
|
||||
pub use desktop_api::desktop_run_async;
|
||||
|
||||
#[cfg(any(target_os = "ios", target_os = "android"))]
|
||||
pub use mobile_api::{desktop_run_async, mobile_run, mobile_stop};
|
||||
|
||||
mod android;
|
||||
mod api;
|
||||
mod args;
|
||||
mod desktop_api;
|
||||
mod directions;
|
||||
mod dns;
|
||||
mod dump_logger;
|
||||
mod error;
|
||||
mod ffi;
|
||||
mod http;
|
||||
mod ios;
|
||||
mod mobile_api;
|
||||
mod proxy_handler;
|
||||
mod session_info;
|
||||
mod socks;
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
#![cfg(any(target_os = "ios", target_os = "android"))]
|
||||
|
||||
use crate::Args;
|
||||
use std::{os::raw::c_int, sync::Mutex};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
static TUN_QUIT: Mutex<Option<CancellationToken>> = Mutex::new(None);
|
||||
static TUN_QUIT: std::sync::Mutex<Option<tokio_util::sync::CancellationToken>> = std::sync::Mutex::new(None);
|
||||
|
||||
pub(crate) fn tun2proxy_internal_run(args: Args, tun_mtu: u16) -> c_int {
|
||||
let shutdown_token = CancellationToken::new();
|
||||
/// Dummy function to make the build pass.
|
||||
#[doc(hidden)]
|
||||
pub async fn desktop_run_async(_: Args, _: tokio_util::sync::CancellationToken) -> std::io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mobile_run(args: Args, tun_mtu: u16) -> c_int {
|
||||
let shutdown_token = tokio_util::sync::CancellationToken::new();
|
||||
{
|
||||
let mut lock = TUN_QUIT.lock().unwrap();
|
||||
if lock.is_some() {
|
||||
|
@ -58,14 +63,12 @@ pub(crate) fn tun2proxy_internal_run(args: Args, tun_mtu: u16) -> c_int {
|
|||
exit_code
|
||||
}
|
||||
|
||||
pub(crate) fn tun2proxy_internal_stop() -> c_int {
|
||||
let lock = TUN_QUIT.lock().unwrap();
|
||||
|
||||
pub fn mobile_stop() -> c_int {
|
||||
if let Ok(lock) = TUN_QUIT.lock() {
|
||||
if let Some(shutdown_token) = lock.as_ref() {
|
||||
shutdown_token.cancel();
|
||||
0
|
||||
} else {
|
||||
log::error!("tun2proxy not started");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue