tun2proxy/src/desktop_api.rs

158 lines
4.5 KiB
Rust
Raw Normal View History

2024-02-13 10:46:13 +08:00
#![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());
}
2024-02-24 20:40:39 +08:00
let main_loop = async move {
if let Err(err) = desktop_run_async(args, shutdown_token).await {
log::error!("main loop error: {}", err);
return Err(err);
}
Ok(())
};
2024-02-13 10:46:13 +08:00
let exit_code = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
Err(_e) => -3,
2024-02-24 20:40:39 +08:00
Ok(rt) => match rt.block_on(main_loop) {
2024-02-13 10:46:13 +08:00
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;
let device = tun2::create_as_async(&config)?;
2024-02-13 10:46:13 +08:00
#[cfg(target_os = "linux")]
{
setup = args.setup;
if setup {
log::trace!("Entering route setup");
2024-02-13 10:46:13 +08:00
tproxy_config::tproxy_setup(&tproxy_args)?;
}
}
#[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
}