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
67
68
69
70
71
72
73
74
use std::sync::Arc;

use axum_server::tls_rustls::RustlsConfig;
use log::info;
use tokio::sync::oneshot;
use tokio::task::JoinHandle;
use torrust_tracker_configuration::HttpTracker;

use crate::servers::http::v1::launcher;
use crate::servers::http::Version;
use crate::tracker;

#[derive(Debug)]
pub struct ServerJobStarted();

pub async fn start_job(config: &HttpTracker, tracker: Arc<tracker::Tracker>, version: Version) -> JoinHandle<()> {
    match version {
        Version::V1 => start_v1(config, tracker.clone()).await,
    }
}

/// # Panics
///
/// It would panic if the `config::HttpTracker` struct would contain inappropriate values.
async fn start_v1(config: &HttpTracker, tracker: Arc<tracker::Tracker>) -> JoinHandle<()> {
    let bind_addr = config
        .bind_address
        .parse::<std::net::SocketAddr>()
        .expect("Tracker API bind_address invalid.");
    let ssl_enabled = config.ssl_enabled;
    let ssl_cert_path = config.ssl_cert_path.clone();
    let ssl_key_path = config.ssl_key_path.clone();

    let (tx, rx) = oneshot::channel::<ServerJobStarted>();

    // Run the API server
    let join_handle = tokio::spawn(async move {
        if !ssl_enabled {
            info!("Starting Torrust HTTP tracker server on: http://{}", bind_addr);

            let handle = launcher::start(bind_addr, tracker);

            tx.send(ServerJobStarted())
                .expect("the HTTP tracker server should not be dropped");

            if let Ok(()) = handle.await {
                info!("Torrust HTTP tracker server on http://{} stopped", bind_addr);
            }
        } else if ssl_enabled && ssl_cert_path.is_some() && ssl_key_path.is_some() {
            info!("Starting Torrust HTTP tracker server on: https://{}", bind_addr);

            let ssl_config = RustlsConfig::from_pem_file(ssl_cert_path.unwrap(), ssl_key_path.unwrap())
                .await
                .unwrap();

            let handle = launcher::start_tls(bind_addr, ssl_config, tracker);

            tx.send(ServerJobStarted())
                .expect("the HTTP tracker server should not be dropped");

            if let Ok(()) = handle.await {
                info!("Torrust HTTP tracker server on https://{} stopped", bind_addr);
            }
        }
    });

    // Wait until the HTTP tracker server job is running
    match rx.await {
        Ok(_msg) => info!("Torrust HTTP tracker server started"),
        Err(e) => panic!("the HTTP tracker server was dropped: {e}"),
    }

    join_handle
}