diff --git a/src/http.rs b/src/http.rs index 76ff707..dc0d2c3 100644 --- a/src/http.rs +++ b/src/http.rs @@ -101,7 +101,70 @@ pub async fn run_server(cfg: &Config) { match &cfg.listen { #[cfg(feature = "systemd_socket_activation")] - listen::Socket::Systemd => handle_systemd_activation(), + listen::Socket::Systemd => { + use std::{future::Future, pin::Pin}; + + let incoming = match socket_from_systemd_activation() { + Ok(Some(socket)) => socket, + Ok(None) => { + error!("No systemd socket activation provided"); + process::exit(-2); + } + Err(err) => { + error!("Error determining socket activation: {err}"); + process::exit(-3); + } + }; + + let mut tasks: Vec>>>> = vec![]; + + // Add the http server to the task list + tasks.push(Box::pin(async move { + _ = server.listen_uds(incoming).unwrap().run().await; + Ok(()) + })); + + // Add the Ctrl+C handler to the task list + tasks.push(Box::pin(async move { + _ = signal::ctrl_c().await; + Ok(()) + })); + + // If a idle timeout is set, create a new timeout task and add it to the task list + if let Some(idle_time) = cfg.systemd_activation_idle { + if idle_time > 0 { + let timeout = tokio::time::Duration::from_secs(idle_time as u64); + let request_received_check = request_received.clone(); + + let idle_timeout = tokio::task::spawn(async move { + loop { + tokio::time::sleep(timeout).await; + + // If the request_received has not been set to true in the timeout period => exit + if request_received_check + .compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) + .is_err() + { + break; + } + } + }); + + tasks.push(Box::pin(async move { + _ = idle_timeout.await; + Err("Idle timeout") + })); + } + } + + select! { + result = futures::future::select_all(tasks) => + match result { + (Err(err), ..) => error!("Closing server: {err}"), + _ => (), + } + } + } listen::Socket::File(path) => { if cfg!(windows) { @@ -134,7 +197,6 @@ pub async fn run_server(cfg: &Config) { } } - /// Generate a cookie with the given authorization fn generate_cookie( name: &str,