2025-12-15 16:13:00 +01:00
|
|
|
use std::{ops::Deref, path::PathBuf, sync::Arc};
|
2025-01-28 20:55:28 +00:00
|
|
|
|
|
|
|
|
use async_trait::async_trait;
|
|
|
|
|
use conduwuit::{
|
2025-02-23 01:17:45 -05:00
|
|
|
Result, Server,
|
|
|
|
|
config::{Config, check},
|
|
|
|
|
error, implement,
|
2025-01-28 20:55:28 +00:00
|
|
|
};
|
|
|
|
|
|
2026-02-12 10:16:03 -05:00
|
|
|
use crate::registration_tokens::{ValidToken, ValidTokenSource};
|
|
|
|
|
|
2025-01-28 20:55:28 +00:00
|
|
|
pub struct Service {
|
|
|
|
|
server: Arc<Server>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SIGNAL: &str = "SIGUSR1";
|
|
|
|
|
|
2026-02-12 10:16:03 -05:00
|
|
|
impl Service {
|
|
|
|
|
/// Get the registration token set in the config file, if it exists.
|
|
|
|
|
#[must_use]
|
|
|
|
|
pub fn get_config_file_token(&self) -> Option<ValidToken> {
|
|
|
|
|
self.registration_token.clone().map(|token| ValidToken {
|
|
|
|
|
token,
|
|
|
|
|
source: ValidTokenSource::ConfigFile,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-28 20:55:28 +00:00
|
|
|
#[async_trait]
|
|
|
|
|
impl crate::Service for Service {
|
|
|
|
|
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
|
|
|
|
Ok(Arc::new(Self { server: args.server.clone() }))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn worker(self: Arc<Self>) -> Result {
|
|
|
|
|
while self.server.running() {
|
|
|
|
|
if self.server.signal.subscribe().recv().await == Ok(SIGNAL) {
|
|
|
|
|
if let Err(e) = self.handle_reload() {
|
|
|
|
|
error!("Failed to reload config: {e}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-28 21:30:12 +00:00
|
|
|
impl Deref for Service {
|
|
|
|
|
type Target = Arc<Config>;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn deref(&self) -> &Self::Target { &self.server.config }
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-28 20:55:28 +00:00
|
|
|
#[implement(Service)]
|
|
|
|
|
fn handle_reload(&self) -> Result {
|
|
|
|
|
if self.server.config.config_reload_signal {
|
2025-02-05 01:45:21 -05:00
|
|
|
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
2025-09-24 08:51:39 -04:00
|
|
|
sd_notify::notify(false, &[
|
|
|
|
|
sd_notify::NotifyState::Reloading,
|
|
|
|
|
sd_notify::NotifyState::monotonic_usec_now().expect("Failed to read monotonic time"),
|
|
|
|
|
])
|
|
|
|
|
.expect("failed to notify systemd of reloading state");
|
2025-02-05 01:45:21 -05:00
|
|
|
|
2025-12-15 16:13:00 +01:00
|
|
|
let config_paths = self.server.config.config_paths.clone().unwrap_or_default();
|
|
|
|
|
self.reload(&config_paths)?;
|
2025-02-05 01:45:21 -05:00
|
|
|
|
|
|
|
|
#[cfg(all(feature = "systemd", target_os = "linux"))]
|
2025-09-24 08:51:39 -04:00
|
|
|
sd_notify::notify(false, &[sd_notify::NotifyState::Ready])
|
2025-02-05 01:45:21 -05:00
|
|
|
.expect("failed to notify systemd of ready state");
|
2025-01-28 20:55:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[implement(Service)]
|
2025-12-15 16:13:00 +01:00
|
|
|
pub fn reload(&self, paths: &[PathBuf]) -> Result<Arc<Config>> {
|
2025-01-28 20:55:28 +00:00
|
|
|
let old = self.server.config.clone();
|
|
|
|
|
let new = Config::load(paths).and_then(|raw| Config::new(&raw))?;
|
|
|
|
|
|
|
|
|
|
check::reload(&old, &new)?;
|
|
|
|
|
self.server.config.update(new)
|
|
|
|
|
}
|