Skip to main content

tuwunel_service/config/
mod.rs

1use std::{iter, ops::Deref, path::Path, sync::Arc};
2
3use async_trait::async_trait;
4use tuwunel_core::{
5	Result, Server,
6	config::{Config, check},
7	error, implement,
8};
9
10pub struct Service {
11	server: Arc<Server>,
12}
13
14const SIGNAL: &str = "SIGUSR1";
15
16#[async_trait]
17impl crate::Service for Service {
18	fn build(args: &crate::Args<'_>) -> Result<Arc<Self>> {
19		Ok(Arc::new(Self { server: args.server.clone() }))
20	}
21
22	async fn worker(self: Arc<Self>) -> Result {
23		let mut signaled = self.server.signal.subscribe();
24		while self.server.is_running() {
25			tokio::select! {
26				() = self.server.until_shutdown() => break,
27				signal = signaled.recv() => if signal !=  Ok(SIGNAL) { continue; },
28			}
29
30			if let Err(e) = self.handle_reload() {
31				error!("Failed to reload config: {e}");
32			}
33		}
34
35		Ok(())
36	}
37
38	fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
39}
40
41impl Deref for Service {
42	type Target = Arc<Config>;
43
44	#[inline]
45	fn deref(&self) -> &Self::Target { &self.server.config }
46}
47
48#[implement(Service)]
49fn handle_reload(&self) -> Result {
50	if self.server.config.config_reload_signal {
51		#[cfg(all(feature = "systemd", target_os = "linux"))]
52		sd_notify::notify(false, &[
53			sd_notify::NotifyState::Reloading,
54			sd_notify::NotifyState::monotonic_usec_now().expect("failed to get monotonic time"),
55		])
56		.expect("failed to notify systemd of reloading state");
57
58		self.reload(iter::empty())?;
59
60		#[cfg(all(feature = "systemd", target_os = "linux"))]
61		sd_notify::notify(false, &[sd_notify::NotifyState::Ready])
62			.expect("failed to notify systemd of ready state");
63	}
64
65	Ok(())
66}
67
68#[implement(Service)]
69pub fn reload<'a, I>(&self, paths: I) -> Result<Arc<Config>>
70where
71	I: Iterator<Item = &'a Path>,
72{
73	let old = self.server.config.clone();
74	let new = Config::load(paths).and_then(|raw| Config::new(&raw))?;
75
76	check::reload(&old, &new)?;
77	self.server.config.update(new)
78}