From 6a7d376aa98c4e7853efc499e50ec81275f3692e Mon Sep 17 00:00:00 2001 From: James Magahern Date: Wed, 12 Feb 2025 00:10:33 -0800 Subject: [PATCH] kpcli: add daemon messaging support --- Cargo.lock | 3 +++ kpcli/Cargo.toml | 5 +++++ kpcli/build.rs | 23 +++++++++++++++++++ kpcli/src/daemon/mod.rs | 50 +++++++++++++++++++++++++++++++++++++++++ kpcli/src/main.rs | 8 +++++++ 5 files changed, 89 insertions(+) create mode 100644 kpcli/build.rs create mode 100644 kpcli/src/daemon/mod.rs diff --git a/Cargo.lock b/Cargo.lock index a36d850..7a70174 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -826,6 +826,9 @@ version = "0.1.0" dependencies = [ "anyhow", "clap 4.5.20", + "dbus", + "dbus-codegen", + "dbus-tree", "dotenv", "kordophone", "kordophone-db", diff --git a/kpcli/Cargo.toml b/kpcli/Cargo.toml index 760462e..d55b6d7 100644 --- a/kpcli/Cargo.toml +++ b/kpcli/Cargo.toml @@ -8,6 +8,8 @@ edition = "2021" [dependencies] anyhow = "1.0.93" clap = { version = "4.5.20", features = ["derive"] } +dbus = "0.9.7" +dbus-tree = "0.9.2" dotenv = "0.15.0" kordophone = { path = "../kordophone" } kordophone-db = { path = "../kordophone-db" } @@ -15,3 +17,6 @@ log = "0.4.22" pretty = { version = "0.12.3", features = ["termcolor"] } time = "0.3.37" tokio = "1.41.1" + +[build-dependencies] +dbus-codegen = "0.10.0" diff --git a/kpcli/build.rs b/kpcli/build.rs new file mode 100644 index 0000000..7d9bf4e --- /dev/null +++ b/kpcli/build.rs @@ -0,0 +1,23 @@ +const KORDOPHONE_XML: &str = "../kordophoned/include/net.buzzert.kordophonecd.Server.xml"; + +fn main() { + let out_dir = std::env::var("OUT_DIR").unwrap(); + let out_path = std::path::Path::new(&out_dir).join("kordophone-client.rs"); + + let opts = dbus_codegen::GenOpts { + connectiontype: dbus_codegen::ConnectionType::Blocking, + methodtype: None, + ..Default::default() + }; + + let xml = std::fs::read_to_string(KORDOPHONE_XML) + .expect("Error reading server dbus interface"); + + let output = dbus_codegen::generate(&xml, &opts) + .expect("Error generating client dbus interface"); + + std::fs::write(out_path, output) + .expect("Error writing client dbus code"); + + println!("cargo:rerun-if-changed={}", KORDOPHONE_XML); +} diff --git a/kpcli/src/daemon/mod.rs b/kpcli/src/daemon/mod.rs new file mode 100644 index 0000000..9e52757 --- /dev/null +++ b/kpcli/src/daemon/mod.rs @@ -0,0 +1,50 @@ +use anyhow::Result; +use clap::Subcommand; +use dbus::blocking::{Connection, Proxy}; + +const DBUS_NAME: &str = "net.buzzert.kordophonecd"; +const DBUS_PATH: &str = "/net/buzzert/kordophone/Server"; + +mod dbus_interface { + #![allow(unused)] + include!(concat!(env!("OUT_DIR"), "/kordophone-client.rs")); +} + +use dbus_interface::NetBuzzertKordophoneServer as KordophoneServer; + +#[derive(Subcommand)] +pub enum Commands { + /// Prints the server Kordophone version. + Version, +} + +impl Commands { + pub async fn run(cmd: Commands) -> Result<()> { + let mut client = DaemonCli::new()?; + match cmd { + Commands::Version => client.print_version().await, + } + } +} + +struct DaemonCli { + conn: Connection, +} + +impl DaemonCli { + pub fn new() -> Result { + Ok(Self { + conn: Connection::new_session()? + }) + } + + fn proxy(&self) -> Proxy<&Connection> { + self.conn.with_proxy(DBUS_NAME, DBUS_PATH, std::time::Duration::from_millis(5000)) + } + + pub async fn print_version(&mut self) -> Result<()> { + let version = KordophoneServer::get_version(&self.proxy())?; + println!("Server version: {}", version); + Ok(()) + } +} \ No newline at end of file diff --git a/kpcli/src/main.rs b/kpcli/src/main.rs index 628a112..7445699 100644 --- a/kpcli/src/main.rs +++ b/kpcli/src/main.rs @@ -1,6 +1,7 @@ mod client; mod db; mod printers; +mod daemon; use anyhow::Result; use clap::{Parser, Subcommand}; @@ -25,6 +26,12 @@ enum Commands { Db { #[command(subcommand)] command: db::Commands, + }, + + /// Commands for interacting with the daemon + Daemon { + #[command(subcommand)] + command: daemon::Commands, } } @@ -32,6 +39,7 @@ async fn run_command(command: Commands) -> Result<()> { match command { Commands::Client { command } => client::Commands::run(command).await, Commands::Db { command } => db::Commands::run(command).await, + Commands::Daemon { command } => daemon::Commands::run(command).await, } }