summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/daemon.rs96
1 files changed, 62 insertions, 34 deletions
diff --git a/src/daemon.rs b/src/daemon.rs
index 34e4474..b5d1fc4 100644
--- a/src/daemon.rs
+++ b/src/daemon.rs
@@ -2,26 +2,31 @@ use atomic_write_file::AtomicWriteFile;
use base64::prelude::*;
use core::net::SocketAddr;
use dbus::{channel::MatchingReceiver, message::MatchRule};
-use dbus_crossroads::{Crossroads, MethodErr, Context};
+use dbus_crossroads::{Context, Crossroads, MethodErr};
use defguard_wireguard_rs::{
host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration, WGApi, WireguardInterfaceApi,
};
-use futures::future;
-use log::{debug, info, warn};
+use log::{debug, error, info, warn};
use rand::Rng;
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeSet, HashMap},
fs::File,
io::{ErrorKind, Read, Write},
- ops::DerefMut,
- net::ToSocketAddrs,
marker::PhantomData,
+ net::ToSocketAddrs,
+ ops::DerefMut,
sync::Arc,
time::SystemTime,
};
use thiserror::Error;
-use tokio::{net::TcpListener, runtime::Builder, sync::RwLock, task};
+use tokio::{
+ net::TcpListener,
+ runtime::Builder,
+ signal::unix::{signal, SignalKind},
+ sync::{broadcast, RwLock},
+ task,
+};
use xdg::BaseDirectories;
use std::str::FromStr;
@@ -150,15 +155,16 @@ pub fn daemon() -> Result<(), DaemonError> {
}));
let rt = Builder::new_current_thread().enable_all().build()?;
- rt.block_on(init_networks(state))?;
+ rt.block_on(run_networks(state))?;
Ok(())
}
-async fn init_networks(state: Arc<RwLock<State>>) -> Result<(), DaemonError> {
+async fn run_networks(state: Arc<RwLock<State>>) -> Result<(), DaemonError> {
let mut state_rw_guard = state.write().await;
let state_rw = state_rw_guard.deref_mut();
+ // load existing configurations
for (name, nw) in &state_rw.conf.networks {
let wg_api = add_network(
&mut state_rw.hostfile,
@@ -167,10 +173,11 @@ async fn init_networks(state: Arc<RwLock<State>>) -> Result<(), DaemonError> {
nw.address.clone(),
nw.listen_port,
&nw.peers,
- ).await?;
+ )
+ .await?;
let addr = IpAddrMask::from_str(&nw.address)?.ip;
- let h = task::spawn(make_fatal(run_network(
+ let h = task::spawn(print_error(run_network(
state.clone(),
TcpListener::bind((addr, nw.mäsch_port)).await?,
name.clone(),
@@ -183,9 +190,9 @@ async fn init_networks(state: Arc<RwLock<State>>) -> Result<(), DaemonError> {
info!("loaded all existing configurations");
drop(state_rw_guard);
+ // set up dbus interface
let mut cr = Crossroads::new();
let state_ref = state.clone();
-
let if_token = cr.register("de.a.maesch", move |b| {
b.signal::<(String, String), _>("Proposal", ("network", "peer_data"));
b.method_with_cr_async(
@@ -198,16 +205,20 @@ async fn init_networks(state: Arc<RwLock<State>>) -> Result<(), DaemonError> {
},
);
});
-
cr.insert("/de/a/maesch", &[if_token], ());
+ // drive dbus interface
let (res, c) = dbus_tokio::connection::new_system_sync()?;
- cr.set_async_support(Some((c.clone(), Box::new(|x| { tokio::spawn(x); }))));
- let _ = tokio::spawn(make_fatal(async {
+ cr.set_async_support(Some((
+ c.clone(),
+ Box::new(|x| {
+ tokio::spawn(x);
+ }),
+ )));
+ let _ = tokio::spawn(print_error(async {
res.await;
Result::<!, &'static str>::Err("lost connection to dbus!")
}));
-
let receive_token = c.start_receive(
MatchRule::new_method_call(),
Box::new(move |msg, conn| {
@@ -215,14 +226,31 @@ async fn init_networks(state: Arc<RwLock<State>>) -> Result<(), DaemonError> {
true
}),
);
-
c.request_name("de.a.maesch", false, true, false).await?;
- future::pending::<!>().await
+ // wait for SIGTERM/SIGINT
+ let mut sigterm_fut = signal(SignalKind::terminate())?;
+ let mut sigint_fut = signal(SignalKind::interrupt())?;
+ let mut sighup_fut = signal(SignalKind::hangup())?;
+
+ tokio::select! {
+ _ = sigterm_fut.recv() => info!("Received SIGTERM"),
+ _ = sigint_fut.recv() => info!("Received SIGINT"),
+ _ = sighup_fut.recv() => info!("Received SIGHUP"),
+ };
+
+ // clean exit
+ c.stop_receive(receive_token);
+ let mut state_rw_guard = state.write().await;
+ for (_, (wg_api, h)) in state_rw_guard.nw_handles.drain() {
+ let _ = wg_api.remove_interface();
+ h.abort(); // could also join the handles... don't think that would do too much, though
+ }
- //c.stop_receive(receive_token);
+ Ok(())
}
+// TODO also take peers
async fn handle_add_network(
mut ctx: Context,
state: Arc<RwLock<State>>,
@@ -236,8 +264,8 @@ async fn handle_add_network(
Ok(v) if v.len() == 32 => v.try_into().unwrap(),
_ => {
warn!("AddNetwork with bad key");
- return ctx.reply(Err(MethodErr::invalid_arg("bad key")))
- },
+ return ctx.reply(Err(MethodErr::invalid_arg("bad key")));
+ }
},
});
@@ -248,8 +276,8 @@ async fn handle_add_network(
Ok(ip_mask) => (ip_mask.ip, may_ip),
Err(_) => {
warn!("AddNetwork with bad ip");
- return ctx.reply(Err(MethodErr::invalid_arg("invalid ip")))
- },
+ return ctx.reply(Err(MethodErr::invalid_arg("invalid ip")));
+ }
},
};
@@ -266,12 +294,14 @@ async fn handle_add_network(
ip_string,
lp,
&HashMap::new(),
- ).await {
+ )
+ .await
+ {
Ok(wg_api) => wg_api,
Err(e) => {
warn!("AddNetwork couldn't add network: {e}");
- return ctx.reply(Err(MethodErr::failed(&e)))
- },
+ return ctx.reply(Err(MethodErr::failed(&e)));
+ }
};
// TODO ins wg_api
@@ -280,10 +310,10 @@ async fn handle_add_network(
Err(e) => {
let _ = wg_api.remove_interface();
warn!("AddNetwork couldn't start listener: {e}");
- return ctx.reply(Err(MethodErr::failed(&e)))
- },
+ return ctx.reply(Err(MethodErr::failed(&e)));
+ }
};
- let h = task::spawn(make_fatal(run_network(
+ let h = task::spawn(print_error(run_network(
state.clone(),
listener,
name.clone(),
@@ -291,6 +321,8 @@ async fn handle_add_network(
state_rw.nw_handles.insert(name.clone(), (wg_api, h));
+ // TODO save new config
+
ctx.reply(Ok((true,)))
}
@@ -371,15 +403,11 @@ async fn add_network(
Ok(wg)
}
-async fn make_fatal<E: std::fmt::Display, O, F: std::future::Future<Output = Result<O, E>>>(
+async fn print_error<E: std::fmt::Display, O, F: std::future::Future<Output = Result<O, E>>>(
f: F,
) -> () {
match f.await {
- Err(e) => {
- eprintln!("oh no: {e}");
- // TODO das soll lieber die tokio runtime beenden...
- std::process::exit(1);
- }
+ Err(e) => error!("oh no: {e}"),
_ => (),
};
}