refactor desktop_run_async

This commit is contained in:
ssrlive 2025-01-02 23:18:40 +08:00
parent 2a8e31225c
commit 7136e2a20c
6 changed files with 127 additions and 98 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "tun2proxy" name = "tun2proxy"
version = "0.6.7" version = "0.7.0"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
repository = "https://github.com/tun2proxy/tun2proxy" repository = "https://github.com/tun2proxy/tun2proxy"

View file

@ -3,6 +3,7 @@ cpp_compat = true
[export] [export]
include = [ include = [
"tun2proxy_run_with_cli",
"tun2proxy_with_fd_run", "tun2proxy_with_fd_run",
"tun2proxy_with_name_run", "tun2proxy_with_name_run",
"tun2proxy_with_name_stop", "tun2proxy_with_name_stop",

View file

@ -1,3 +1,4 @@
use tun::DEFAULT_MTU as MTU;
use tun2proxy::{Args, BoxError}; use tun2proxy::{Args, BoxError};
fn main() -> Result<(), BoxError> { fn main() -> Result<(), BoxError> {
@ -49,7 +50,7 @@ async fn main_async(args: Args) -> Result<(), BoxError> {
} }
unsafe { tun2proxy::tun2proxy_set_traffic_status_callback(1, Some(traffic_cb), std::ptr::null_mut()) }; unsafe { tun2proxy::tun2proxy_set_traffic_status_callback(1, Some(traffic_cb), std::ptr::null_mut()) };
if let Err(err) = tun2proxy::desktop_run_async(args, shutdown_token).await { if let Err(err) = tun2proxy::desktop_run_async(args, MTU, false, shutdown_token).await {
log::error!("main loop error: {}", err); log::error!("main loop error: {}", err);
} }
} }

View file

@ -5,7 +5,6 @@ use crate::{
ArgVerbosity, Args, ArgVerbosity, Args,
}; };
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use tproxy_config::{TproxyArgs, TUN_GATEWAY, TUN_IPV4, TUN_NETMASK};
use tun::{AbstractDevice, DEFAULT_MTU as MTU}; use tun::{AbstractDevice, DEFAULT_MTU as MTU};
static TUN_QUIT: std::sync::Mutex<Option<tokio_util::sync::CancellationToken>> = std::sync::Mutex::new(None); static TUN_QUIT: std::sync::Mutex<Option<tokio_util::sync::CancellationToken>> = std::sync::Mutex::new(None);
@ -29,6 +28,42 @@ pub unsafe extern "C" fn tun2proxy_with_name_run(
_root_privilege: bool, _root_privilege: bool,
verbosity: ArgVerbosity, verbosity: ArgVerbosity,
) -> c_int { ) -> c_int {
let proxy_url = std::ffi::CStr::from_ptr(proxy_url).to_str().unwrap();
let proxy = ArgProxy::try_from(proxy_url).unwrap();
let tun = std::ffi::CStr::from_ptr(tun).to_str().unwrap().to_string();
let mut args = Args::default();
if let Ok(bypass) = std::ffi::CStr::from_ptr(bypass).to_str() {
args.bypass(bypass.parse().unwrap());
}
args.proxy(proxy).tun(tun).dns(dns_strategy).verbosity(verbosity);
#[cfg(target_os = "linux")]
args.setup(_root_privilege);
desktop_run(args)
}
/// # Safety
/// Run the tun2proxy component with command line arguments
/// Parameters:
/// - cli_args: The command line arguments,
/// e.g. `tun2proxy-bin --setup --proxy socks5://127.0.0.1:1080 --bypass 98.76.54.0/24 --dns over-tcp --verbosity trace`
#[no_mangle]
pub unsafe extern "C" fn tun2proxy_run_with_cli_args(cli_args: *const c_char) -> c_int {
let Ok(cli_args) = std::ffi::CStr::from_ptr(cli_args).to_str() else {
return -5;
};
let args = <Args as ::clap::Parser>::parse_from(cli_args.split_whitespace());
desktop_run(args)
}
pub fn desktop_run(args: Args) -> c_int {
log::set_max_level(args.verbosity.into());
if let Err(err) = log::set_boxed_logger(Box::<crate::dump_logger::DumpLogger>::default()) {
log::warn!("set logger error: {}", err);
}
let shutdown_token = tokio_util::sync::CancellationToken::new(); let shutdown_token = tokio_util::sync::CancellationToken::new();
{ {
if let Ok(mut lock) = TUN_QUIT.lock() { if let Ok(mut lock) = TUN_QUIT.lock() {
@ -41,51 +76,38 @@ pub unsafe extern "C" fn tun2proxy_with_name_run(
} }
} }
log::set_max_level(verbosity.into()); let Ok(rt) = tokio::runtime::Builder::new_multi_thread().enable_all().build() else {
if let Err(err) = log::set_boxed_logger(Box::<crate::dump_logger::DumpLogger>::default()) { return -3;
log::warn!("set logger error: {}", err); };
} let res = rt.block_on(async move {
if let Err(err) = desktop_run_async(args, MTU, false, shutdown_token).await {
let proxy_url = std::ffi::CStr::from_ptr(proxy_url).to_str().unwrap();
let proxy = ArgProxy::try_from(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 main_loop = async move {
if let Err(err) = desktop_run_async(args, shutdown_token).await {
log::error!("main loop error: {}", err); log::error!("main loop error: {}", err);
return Err(err); return Err(err);
} }
Ok(()) Ok(())
}; });
match res {
let exit_code = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
Err(_e) => -3,
Ok(rt) => match rt.block_on(main_loop) {
Ok(_) => 0, Ok(_) => 0,
Err(_e) => -4, Err(_) => -4,
}, }
};
exit_code
} }
/// Run the tun2proxy component with some arguments. /// Run the tun2proxy component with some arguments.
pub async fn desktop_run_async(args: Args, shutdown_token: tokio_util::sync::CancellationToken) -> std::io::Result<()> { pub async fn desktop_run_async(
let bypass_ips = args.bypass.clone(); args: Args,
tun_mtu: u16,
_packet_information: bool,
shutdown_token: tokio_util::sync::CancellationToken,
) -> std::io::Result<()> {
let mut tun_config = tun::Configuration::default(); let mut tun_config = tun::Configuration::default();
tun_config.address(TUN_IPV4).netmask(TUN_NETMASK).mtu(MTU).up();
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
{
use tproxy_config::{TUN_GATEWAY, TUN_IPV4, TUN_NETMASK};
tun_config.address(TUN_IPV4).netmask(TUN_NETMASK).mtu(tun_mtu).up();
tun_config.destination(TUN_GATEWAY); tun_config.destination(TUN_GATEWAY);
}
#[cfg(unix)] #[cfg(unix)]
if let Some(fd) = args.tun_fd { if let Some(fd) = args.tun_fd {
tun_config.raw_fd(fd); tun_config.raw_fd(fd);
@ -112,11 +134,17 @@ pub async fn desktop_run_async(args: Args, shutdown_token: tokio_util::sync::Can
cfg.device_guid(12324323423423434234_u128); cfg.device_guid(12324323423423434234_u128);
}); });
#[cfg(any(target_os = "ios", target_os = "macos"))]
tun_config.platform_config(|cfg| {
cfg.packet_information(_packet_information);
});
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
#[allow(unused_variables)] #[allow(unused_variables)]
let mut tproxy_args = TproxyArgs::new() let mut tproxy_args = tproxy_config::TproxyArgs::new()
.tun_dns(args.dns_addr) .tun_dns(args.dns_addr)
.proxy_addr(args.proxy.addr) .proxy_addr(args.proxy.addr)
.bypass_ips(&bypass_ips) .bypass_ips(&args.bypass)
.ipv6_default_route(args.ipv6_enabled); .ipv6_default_route(args.ipv6_enabled);
#[allow(unused_mut, unused_assignments, unused_variables)] #[allow(unused_mut, unused_assignments, unused_variables)]
@ -124,12 +152,14 @@ pub async fn desktop_run_async(args: Args, shutdown_token: tokio_util::sync::Can
let device = tun::create_as_async(&tun_config)?; let device = tun::create_as_async(&tun_config)?;
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
if let Ok(tun_name) = device.tun_name() { if let Ok(tun_name) = device.tun_name() {
tproxy_args = tproxy_args.tun_name(&tun_name); tproxy_args = tproxy_args.tun_name(&tun_name);
} }
// TproxyState implements the Drop trait to restore network configuration, // TproxyState implements the Drop trait to restore network configuration,
// so we need to assign it to a variable, even if it is not used. // so we need to assign it to a variable, even if it is not used.
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
let mut _restore: Option<tproxy_config::TproxyState> = None; let mut _restore: Option<tproxy_config::TproxyState> = None;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -166,10 +196,8 @@ pub async fn desktop_run_async(args: Args, shutdown_token: tokio_util::sync::Can
} }
} }
let join_handle = tokio::spawn(crate::run(device, MTU, args, shutdown_token)); let join_handle = tokio::spawn(crate::run(device, tun_mtu, args, shutdown_token));
join_handle.await.map_err(std::io::Error::from)??; Ok(join_handle.await.map_err(std::io::Error::from)??)
Ok::<(), std::io::Error>(())
} }
/// # Safety /// # Safety

View file

@ -8,26 +8,16 @@ static TUN_QUIT: std::sync::Mutex<Option<tokio_util::sync::CancellationToken>> =
/// Dummy function to make the build pass. /// Dummy function to make the build pass.
#[doc(hidden)] #[doc(hidden)]
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
pub async fn desktop_run_async(_: Args, _: tokio_util::sync::CancellationToken) -> std::io::Result<()> { pub async fn desktop_run_async(_: Args, _: u16, _: bool, _: tokio_util::sync::CancellationToken) -> std::io::Result<()> {
Ok(()) Ok(())
} }
pub fn mobile_run(args: Args, tun_mtu: u16, _packet_information: bool) -> c_int { pub async fn mobile_run_async(
let shutdown_token = tokio_util::sync::CancellationToken::new(); args: Args,
{ tun_mtu: u16,
if let Ok(mut lock) = TUN_QUIT.lock() { _packet_information: bool,
if lock.is_some() { shutdown_token: tokio_util::sync::CancellationToken,
log::error!("tun2proxy already started"); ) -> std::io::Result<()> {
return -1;
}
*lock = Some(shutdown_token.clone());
} else {
log::error!("failed to lock tun2proxy quit token");
return -2;
}
}
let block = async move {
let mut config = tun::Configuration::default(); let mut config = tun::Configuration::default();
#[cfg(unix)] #[cfg(unix)]
@ -52,24 +42,33 @@ pub fn mobile_run(args: Args, tun_mtu: u16, _packet_information: bool) -> c_int
let device = tun::create_as_async(&config).map_err(std::io::Error::from)?; let device = tun::create_as_async(&config).map_err(std::io::Error::from)?;
let join_handle = tokio::spawn(crate::run(device, tun_mtu, args, shutdown_token)); let join_handle = tokio::spawn(crate::run(device, tun_mtu, args, shutdown_token));
join_handle.await.map_err(std::io::Error::from)? Ok(join_handle.await.map_err(std::io::Error::from)??)
};
let exit_code = match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
Err(e) => {
log::error!("failed to create tokio runtime with error: {:?}", e);
-1
} }
Ok(rt) => match rt.block_on(block) {
pub fn mobile_run(args: Args, tun_mtu: u16, _packet_information: bool) -> c_int {
let shutdown_token = tokio_util::sync::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!("failed to lock tun2proxy quit token");
return -2;
}
let Ok(rt) = tokio::runtime::Builder::new_multi_thread().enable_all().build() else {
log::error!("failed to create tokio runtime with");
return -1;
};
match rt.block_on(mobile_run_async(args, tun_mtu, _packet_information, shutdown_token)) {
Ok(_) => 0, Ok(_) => 0,
Err(e) => { Err(e) => {
log::error!("failed to run tun2proxy with error: {:?}", e); log::error!("failed to run tun2proxy with error: {:?}", e);
-2 -2
} }
}, }
};
exit_code
} }
pub fn mobile_stop() -> c_int { pub fn mobile_stop() -> c_int {

View file

@ -78,7 +78,7 @@ fn run_service(_arguments: Vec<std::ffi::OsString>) -> Result<(), crate::BoxErro
} }
unsafe { crate::tun2proxy_set_traffic_status_callback(1, Some(traffic_cb), std::ptr::null_mut()) }; unsafe { crate::tun2proxy_set_traffic_status_callback(1, Some(traffic_cb), std::ptr::null_mut()) };
if let Err(err) = crate::desktop_run_async(args, shutdown_token).await { if let Err(err) = crate::desktop_run_async(args, tun::DEFAULT_MTU, false, shutdown_token).await {
log::error!("main loop error: {}", err); log::error!("main loop error: {}", err);
} }
Ok::<(), crate::Error>(()) Ok::<(), crate::Error>(())