use crate::{ArgVerbosity, main_entry};
use std::ffi::{c_char, c_int};
static TUN_QUIT: std::sync::Mutex<Option<tokio_util::sync::CancellationToken>> = std::sync::Mutex::new(None);
#[unsafe(no_mangle)]
pub unsafe extern "C" fn dns2socks_start(
listen_addr: *const c_char,
dns_remote_server: *const c_char,
socks5_settings: *const c_char,
force_tcp: bool,
cache_records: bool,
verbosity: ArgVerbosity,
timeout: i32,
) -> 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());
if let Err(err) = log::set_boxed_logger(Box::<crate::dump_logger::DumpLogger>::default()) {
log::warn!("set logger error: {}", err);
}
let mut config = crate::Config::default();
config
.verbosity(verbosity)
.timeout(timeout as u64)
.force_tcp(force_tcp)
.cache_records(cache_records);
if !listen_addr.is_null() {
let Ok(listen_addr) = unsafe { std::ffi::CStr::from_ptr(listen_addr) }.to_str() else {
return -3;
};
let Ok(addr) = listen_addr.parse() else {
return -4;
};
config.listen_addr(addr);
}
if !dns_remote_server.is_null() {
let Ok(dns_remote_server) = unsafe { std::ffi::CStr::from_ptr(dns_remote_server) }.to_str() else {
return -5;
};
let Ok(addr) = dns_remote_server.parse() else {
return -6;
};
config.dns_remote_server(addr);
}
if !socks5_settings.is_null() {
let Ok(socks5_settings) = unsafe { std::ffi::CStr::from_ptr(socks5_settings) }.to_str() else {
return -7;
};
let Ok(proxy_settings) = crate::config::ArgProxy::try_from(socks5_settings) else {
return -8;
};
config.socks5_settings(proxy_settings);
}
let main_loop = async move {
if let Err(err) = main_entry(config, shutdown_token).await {
log::error!("main loop error: {}", err);
return Err(err);
}
Ok(())
};
match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
Err(_e) => -9,
Ok(rt) => match rt.block_on(main_loop) {
Ok(_) => 0,
Err(_e) => -10,
},
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn dns2socks_stop() -> c_int {
if let Ok(mut lock) = TUN_QUIT.lock()
&& let Some(shutdown_token) = lock.take()
{
shutdown_token.cancel();
return 0;
}
-1
}