Add basic dbus proxy logic

This commit is contained in:
Elias Schriefer 2020-09-20 14:16:29 +02:00
parent f99ee75f98
commit 3f47840318

View File

@ -1,4 +1,103 @@
use log::{ debug, info, warn, error }; 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<dbus::nonblock::SyncConnection>>),
Minecraft(Proxy<'proxy, Arc<dbus::nonblock::SyncConnection>>),
}
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<dbus::nonblock::SyncConnection>, 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<MD: core::fmt::Display, VD: core::fmt::Debug>(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] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
@ -21,8 +120,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
panic!("Lost connection to D-Bus: {}", err); panic!("Lost connection to D-Bus: {}", err);
}); });
// Get a proxy connection to the daemon
let daemon = NativeObject::new(c, "/");
// TODO: // TODO:
// Perform operations // Perform operations
info!("The daemon is{} running", if !daemon.is_running().await {"n't"} else {""});
Ok(()) Ok(())
} }