From 3f4784031806b670600342f36aba9ac9e34927d8 Mon Sep 17 00:00:00 2001 From: EliasSchriefer Date: Sun, 20 Sep 2020 14:16:29 +0200 Subject: [PATCH] Add basic dbus proxy logic --- sfsmcctl/src/main.rs | 103 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/sfsmcctl/src/main.rs b/sfsmcctl/src/main.rs index e17e671..d80d1a8 100644 --- a/sfsmcctl/src/main.rs +++ b/sfsmcctl/src/main.rs @@ -1,4 +1,103 @@ use log::{ debug, info, warn, error }; +use dbus::{ + nonblock::Proxy, + Error +}; +use std::sync::Arc; + +const DBUS_NAME: &'static str = "org.ddnss.sfs.mc"; + +fn iface_name(iface: &str) -> String { + DBUS_NAME.to_owned() + "." + iface +} + +// #[non_exhaustive] +pub enum NativeObject<'proxy> { + Daemon(Proxy<'proxy, Arc>), + Minecraft(Proxy<'proxy, Arc>), +} + +impl core::fmt::Debug for NativeObject<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "NativeObject::").and( + match self { + Self::Daemon(_) => f.debug_tuple("Daemon"), + Self::Minecraft(_) => f.debug_tuple("Minecraft") + }.field(&"_").finish() + ) + } +} + +impl<'proxy> NativeObject<'proxy> { + pub fn new(c: Arc, path: &'proxy str) -> Self { + match path { + "/" => Self::Daemon(Proxy::<'proxy>::new(DBUS_NAME, path, std::time::Duration::from_secs(5), c)), + "/minecraft" => Self::Minecraft(Proxy::<'proxy>::new(DBUS_NAME, path, std::time::Duration::from_secs(5), c)), + _ => panic!("Unknown object path {:?}", path) + } + } + + fn no_path(method: MD, variant: VD) -> ! { + panic!("No method {} on variant {:?}", method, variant) + } + + pub async fn start(&self) -> Result<(), Error> { + let proxy = match self { + Self::Daemon(p) | Self::Minecraft(p) => p, + _ => Self::no_path("start", self) + }; + + proxy.method_call(iface_name("Service"), "Start", ()).await + } + + pub async fn stop(&self) -> Result<(), Error> { + let proxy = match self { + Self::Daemon(p) | Self::Minecraft(p) => p, + _ => Self::no_path("stop", self) + }; + + let res = proxy.method_call(iface_name("Service"), "Stop", ()).await; + res.or_else(|err| + if + proxy.path.to_string() == "/".to_owned() && + err.name() == Some("org.freedesktop.DBus.Error.NoReply") && + err.message() == Some("Message recipient disconnected from message bus without replying") + { + Ok(()) + } else { + Err(err) + } + ) + } + + pub async fn is_running(&self) -> bool { + let proxy = match self { + Self::Daemon(p) | Self::Minecraft(p) => p, + _ => Self::no_path("is_running", self) + }; + + let res = proxy.method_call(iface_name("Service"), "IsRunning", ()).await; + res.map(|data: (bool,)| data.0).or_else(|err| + if + proxy.path.to_string() == "/".to_string() && + err.name() == Some("org.freedesktop.DBus.Error.ServiceUnknown") + { + Ok(false) + } else { + Err(err) + } + ).unwrap() + } + + pub async fn restart(&self) -> Result<(), Error> { + let proxy = match self { + Self::Daemon(p) | Self::Minecraft(p) => p, + _ => Self::no_path("restart", self) + }; + + proxy.method_call(iface_name("Service"), "Restart", ()).await + } +} #[tokio::main] async fn main() -> Result<(), Box> { @@ -21,8 +120,12 @@ async fn main() -> Result<(), Box> { panic!("Lost connection to D-Bus: {}", err); }); + // Get a proxy connection to the daemon + let daemon = NativeObject::new(c, "/"); + // TODO: // Perform operations + info!("The daemon is{} running", if !daemon.is_running().await {"n't"} else {""}); Ok(()) } \ No newline at end of file