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
61
62
63
64
65
66
#![warn(clippy::all)]

use std::time::Duration;

use tokio::runtime::Runtime;

pub mod proxy;

mod app;
mod process;
pub mod process_manager;
use crate::process_manager::ProcessManager;
pub mod config;
use crate::config::Config;
pub mod client;
#[cfg(target_os = "macos")]
mod dns;
mod host_resolver;
pub mod ipc_command;
mod ipc_listener;
mod ipc_response;
mod output;
mod procfile;
mod signals;
mod tmux;

fn server_running() -> bool {
    if let Ok(response) = ipc_command::ping_server() {
        response == "pong"
    } else {
        false
    }
}

pub fn run_server(config: Config) {
    if server_running() {
        return eprint!("Error: server is already running");
    }

    let mut runtime = Runtime::new().unwrap();

    #[cfg(target_os = "macos")]
    runtime.enter(|| {
        dns::start_dns_server(config.general.dns_port, &config.general.domain, &runtime)
            .expect("Failed to start DNS server");
    });

    runtime.block_on(async {
        ProcessManager::initialize(&config);

        tokio::spawn(ProcessManager::monitor_idle_timeout());

        let shutdown_rx = signals::ctrlc_listener();

        ipc_listener::start_ipc_sock();

        proxy::start_server(config, shutdown_rx).await;
    });

    runtime.shutdown_timeout(Duration::from_millis(500));
}

// File for shared helpers between integration and unit tests
#[cfg(test)]
#[path = "../tests/helpers/test_utils.rs"]
mod test_utils;