Introduce cancellation token and reduce amount of code (#88)

Test passed on Android. Thanks a lot.
This commit is contained in:
Andrej Mihajlov 2024-02-10 17:36:54 +01:00 committed by GitHub
parent 2434c62524
commit 2a9775ce2e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 59 additions and 126 deletions

View file

@ -1,16 +1,23 @@
#![cfg(any(target_os = "ios", target_os = "android"))]
use crate::{Args, Builder, Quit};
use std::{os::raw::c_int, sync::Arc};
use crate::Args;
use std::{os::raw::c_int, sync::Mutex};
use tokio_util::sync::CancellationToken;
static mut TUN_QUIT: Option<Arc<Quit>> = None;
static TUN_QUIT: Mutex<Option<CancellationToken>> = Mutex::new(None);
pub(crate) fn tun2proxy_internal_run(args: Args, tun_mtu: usize) -> c_int {
if unsafe { TUN_QUIT.is_some() } {
pub(crate) fn tun2proxy_internal_run(args: Args, tun_mtu: u16) -> c_int {
let mut lock = TUN_QUIT.lock().unwrap();
if lock.is_some() {
log::error!("tun2proxy already started");
return -1;
}
let shutdown_token = CancellationToken::new();
*lock = Some(shutdown_token.clone());
// explicit drop to avoid holding mutex lock while running proxy.
drop(lock);
let block = async move {
log::info!("Proxy {} server: {}", args.proxy.proxy_type, args.proxy.addr);
@ -18,53 +25,40 @@ pub(crate) fn tun2proxy_internal_run(args: Args, tun_mtu: usize) -> c_int {
config.raw_fd(args.tun_fd.ok_or(crate::Error::from("tun_fd"))?);
let device = tun2::create_as_async(&config).map_err(std::io::Error::from)?;
let join_handle = tokio::spawn(crate::run(device, tun_mtu, args, shutdown_token));
#[cfg(target_os = "android")]
let tun2proxy = Builder::new(device, args).mtu(tun_mtu).build();
#[cfg(target_os = "ios")]
let tun2proxy = Builder::new(device, args).mtu(tun_mtu).build();
let (join_handle, quit) = tun2proxy.start();
unsafe { TUN_QUIT = Some(Arc::new(quit)) };
join_handle.await
join_handle.await.map_err(std::io::Error::from)?
};
match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
Err(_err) => {
log::error!("failed to create tokio runtime with error: {:?}", _err);
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) {
Ok(_) => 0,
Err(_err) => {
log::error!("failed to run tun2proxy with error: {:?}", _err);
Err(e) => {
log::error!("failed to run tun2proxy with error: {:?}", e);
-2
}
},
}
};
// release shutdown token before exit.
let mut lock = TUN_QUIT.lock().unwrap();
let _ = lock.take();
exit_code
}
pub(crate) fn tun2proxy_internal_stop() -> c_int {
let res = match unsafe { &TUN_QUIT } {
None => {
log::error!("tun2proxy not started");
-1
}
Some(tun_quit) => match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
Err(_err) => {
log::error!("failed to create tokio runtime with error: {:?}", _err);
-2
}
Ok(rt) => match rt.block_on(async move { tun_quit.trigger().await }) {
Ok(_) => 0,
Err(_err) => {
log::error!("failed to stop tun2proxy with error: {:?}", _err);
-3
}
},
},
};
unsafe { TUN_QUIT = None };
res
let lock = TUN_QUIT.lock().unwrap();
if let Some(shutdown_token) = lock.as_ref() {
shutdown_token.cancel();
0
} else {
log::error!("tun2proxy not started");
-1
}
}