diff options
Diffstat (limited to 'src/daemon_dbus.rs')
-rw-r--r-- | src/daemon_dbus.rs | 90 |
1 files changed, 68 insertions, 22 deletions
diff --git a/src/daemon_dbus.rs b/src/daemon_dbus.rs index 7065eec..5ed4d94 100644 --- a/src/daemon_dbus.rs +++ b/src/daemon_dbus.rs @@ -1,30 +1,69 @@ use base64::prelude::*; -use dbus::{channel::MatchingReceiver, message::MatchRule}; -use dbus_crossroads::{Context, Crossroads, MethodErr}; -use defguard_wireguard_rs::{ - host::Peer, key::Key, net::IpAddrMask, InterfaceConfiguration, WGApi, WireguardInterfaceApi, +use dbus::{ + channel::{MatchingReceiver, Token}, + message::MatchRule, + nonblock::SyncConnection, }; +use dbus_crossroads::{Context, Crossroads, MethodErr}; +use defguard_wireguard_rs::{key::Key, net::IpAddrMask, WireguardInterfaceApi}; use log::{debug, error, info, warn}; use rand::Rng; use std::{ - collections::{BTreeSet, HashMap}, - marker::PhantomData, - ops::DerefMut, - str::FromStr, + collections::HashMap, marker::PhantomData, ops::DerefMut, path::PathBuf, str::FromStr, sync::Arc, }; -use tokio::{ - net::TcpListener, - sync::{broadcast, RwLock}, - task, -}; +use tokio::{net::TcpListener, sync::RwLock, task}; + +use crate::{daemon::*, daemon_config::*, daemon_network::*}; + +pub async fn start_dbus( + state: Arc<RwLock<State>>, + config_path: PathBuf, +) -> Result<(Arc<SyncConnection>, Token), DaemonError> { + let mut cr = Crossroads::new(); + let if_token = cr.register("de.a.maesch", move |b| { + b.signal::<(String, String), _>("Proposal", ("network", "peer_data")); + b.method_with_cr_async( + "AddNetwork", + ("name", "key", "ip", "listen_port", "maesch_port"), + ("success",), + move |ctx, _, args: (String, String, String, u16, u16)| { + debug!("Received AddNetwork"); + handle_add_network(ctx, state.clone(), config_path.clone(), args) + }, + ); + }); + 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(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| { + cr.handle_message(msg, conn).unwrap(); + true + }), + ); + c.request_name("de.a.maesch", false, true, false).await?; -use crate::{daemon::*, daemon_network::*}; + Ok((c, receive_token)) +} // TODO also take peers pub async fn handle_add_network( mut ctx: Context, state: Arc<RwLock<State>>, + config_path: PathBuf, (name, may_key, may_ip, may_lp, may_mp): (String, String, String, u16, u16), ) -> PhantomData<(bool,)> { // NOTE: this is kinda stupid: we convert to a string later anyways, as thats what @@ -55,11 +94,7 @@ pub async fn handle_add_network( let lp = if may_lp == 0 { 25565 } else { may_lp }; let mp = if may_mp == 0 { 51820 } else { may_mp }; - let mut state_rw_guard = state.write().await; - let state_rw = state_rw_guard.deref_mut(); - - let wg_api = match add_network( - &mut state_rw.hostfile, + let (wg_api, hostnames) = match add_network( name.clone(), key.to_string(), ip_string, @@ -68,14 +103,13 @@ pub async fn handle_add_network( ) .await { - Ok(wg_api) => wg_api, + Ok(v) => v, Err(e) => { warn!("AddNetwork couldn't add network: {e}"); return ctx.reply(Err(MethodErr::failed(&e))); } }; - // TODO ins wg_api let listener = match TcpListener::bind((ip, mp)).await { Ok(l) => l, Err(e) => { @@ -90,9 +124,21 @@ pub async fn handle_add_network( name.clone(), ))); + let mut state_rw_guard = state.write().await; + let state_rw = state_rw_guard.deref_mut(); state_rw.nw_handles.insert(name.clone(), (wg_api, h)); - // TODO save new config + // NOTE this _is_ thread-safe, as we hold an exclusive write handle to the state. + match write_config(&state_rw.conf, &config_path) { + Ok(_) => info!("Synced config"), + Err(e) => error!("Couldn't sync config: {e}"), + } + // similarly, this is still racy w.r.t. other processes running on the system, but at least + // no other thread from this program should be able to concurrently call this + match sync_hostnames(&hostnames) { + Ok(_) => (), + Err(e) => error!("Failed to sync hostnames to disk: {e}"), + }; ctx.reply(Ok((true,))) } |