1use crate::Config;
2use std::{net::SocketAddr, os::raw::c_int, sync::LazyLock, sync::Mutex};
3
4static TUN_QUIT: LazyLock<Mutex<Option<tokio_util::sync::CancellationToken>>> = LazyLock::new(|| Mutex::new(None));
5
6pub(crate) fn api_internal_run<F>(config: Config, callback: Option<F>) -> c_int
7where
8 F: FnOnce(SocketAddr) + Send + Sync + 'static,
9{
10 if TUN_QUIT.lock().unwrap().is_some() {
11 log::error!("socks-hub already started");
12 return -1;
13 }
14
15 let block = async move {
16 log::info!("config: {}", serde_json::to_string_pretty(&config)?);
17
18 let cancel_token = tokio_util::sync::CancellationToken::new();
19
20 TUN_QUIT.lock().unwrap().replace(cancel_token.clone());
21
22 crate::main_entry(&config, cancel_token, callback).await?;
23 Ok::<_, crate::BoxError>(())
24 };
25
26 match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
27 Err(_err) => {
28 log::error!("failed to create tokio runtime with error: {_err:?}");
29 -1
30 }
31 Ok(rt) => match rt.block_on(block) {
32 Ok(_) => 0,
33 Err(_err) => {
34 log::error!("failed to run socks-hub with error: {_err:?}");
35 -2
36 }
37 },
38 }
39}
40
41pub(crate) fn api_internal_stop() -> c_int {
42 match TUN_QUIT.lock().unwrap().take() {
43 None => {
44 log::error!("socks-hub not started");
45 -1
46 }
47 Some(tun_quit) => {
48 tun_quit.cancel();
49 0
50 }
51 }
52}