1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use crate::Config;
use std::{os::raw::c_int, sync::Arc};

static mut TUN_QUIT: Option<Arc<tokio::sync::mpsc::Sender<()>>> = None;

pub(crate) fn api_internal_run(config: Config) -> c_int {
    if unsafe { TUN_QUIT.is_some() } {
        log::error!("socks-hub already started");
        return -1;
    }

    let block = async move {
        log::info!("config: {}", serde_json::to_string_pretty(&config)?);

        let (tx, quit) = tokio::sync::mpsc::channel::<()>(1);

        unsafe { TUN_QUIT = Some(Arc::new(tx)) };

        crate::main_entry(&config, quit).await?;
        Ok::<_, crate::BoxError>(())
    };

    match tokio::runtime::Builder::new_multi_thread().enable_all().build() {
        Err(_err) => {
            log::error!("failed to create tokio runtime with error: {:?}", _err);
            -1
        }
        Ok(rt) => match rt.block_on(block) {
            Ok(_) => 0,
            Err(_err) => {
                log::error!("failed to run socks-hub with error: {:?}", _err);
                -2
            }
        },
    }
}

pub(crate) fn api_internal_stop() -> c_int {
    let res = match unsafe { &TUN_QUIT } {
        None => {
            log::error!("socks-hub 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.send(()).await }) {
                Ok(_) => 0,
                Err(_err) => {
                    log::error!("failed to stop socks-hub with error: {:?}", _err);
                    -3
                }
            },
        },
    };
    unsafe { TUN_QUIT = None };
    res
}