diff --git a/Cargo.lock b/Cargo.lock index b5107df..a36d850 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -41,6 +41,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anstream" version = "0.6.15" @@ -113,6 +122,17 @@ dependencies = [ "syn", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.2.0" @@ -190,6 +210,21 @@ dependencies = [ "windows-targets 0.52.4", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "clap" version = "4.5.20" @@ -209,7 +244,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.1", ] [[package]] @@ -282,7 +317,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.11.1", "syn", ] @@ -297,6 +332,59 @@ dependencies = [ "syn", ] +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "futures-channel", + "futures-util", + "libc", + "libdbus-sys", + "winapi", +] + +[[package]] +name = "dbus-codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76dc35ce83e4e9fa089b4fabe66c757b27bd504dc2179c97a01b36d3e874fb0" +dependencies = [ + "clap 2.34.0", + "dbus", + "xml-rs", +] + +[[package]] +name = "dbus-crossroads" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a4c83437187544ba5142427746835061b330446ca8902eabd70e4afb8f76de0" +dependencies = [ + "dbus", +] + +[[package]] +name = "dbus-tokio" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "007688d459bc677131c063a3a77fb899526e17b7980f390b69644bdbc41fad13" +dependencies = [ + "dbus", + "libc", + "tokio", +] + +[[package]] +name = "dbus-tree" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f456e698ae8e54575e19ddb1f9b7bce2298568524f215496b248eb9498b4f508" +dependencies = [ + "dbus", +] + [[package]] name = "deranged" version = "0.3.11" @@ -390,9 +478,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", @@ -531,6 +619,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.9" @@ -708,12 +805,27 @@ dependencies = [ "uuid", ] +[[package]] +name = "kordophoned" +version = "0.1.0" +dependencies = [ + "dbus", + "dbus-codegen", + "dbus-crossroads", + "dbus-tokio", + "dbus-tree", + "env_logger", + "kordophone", + "log", + "tokio", +] + [[package]] name = "kpcli" version = "0.1.0" dependencies = [ "anyhow", - "clap", + "clap 4.5.20", "dotenv", "kordophone", "kordophone-db", @@ -735,6 +847,15 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "pkg-config", +] + [[package]] name = "libsqlite3-sys" version = "0.30.1" @@ -763,9 +884,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" @@ -809,7 +930,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", "wasi", "windows-sys", @@ -1204,6 +1325,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.11.1" @@ -1242,6 +1369,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "time" version = "0.3.37" @@ -1443,6 +1579,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "want" version = "0.3.1" @@ -1513,6 +1655,22 @@ version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -1522,6 +1680,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.52.0" @@ -1662,3 +1826,9 @@ checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] + +[[package]] +name = "xml-rs" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" diff --git a/Cargo.toml b/Cargo.toml index 85fc82d..e9fa9ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [workspace] members = [ "kordophone", - "kordophone-db", + "kordophone-db", + "kordophoned", "kpcli" ] resolver = "2" diff --git a/kordophoned/Cargo.toml b/kordophoned/Cargo.toml new file mode 100644 index 0000000..208b953 --- /dev/null +++ b/kordophoned/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "kordophoned" +version = "0.1.0" +edition = "2021" + +[dependencies] +dbus = "0.9.7" +dbus-crossroads = "0.5.2" +dbus-tokio = "0.7.6" +dbus-tree = "0.9.2" +env_logger = "0.11.6" +kordophone = { path = "../kordophone" } +log = "0.4.25" +tokio = { version = "1", features = ["full"] } + +[build-dependencies] +dbus-codegen = "0.10.0" +dbus-crossroads = "0.5.1" diff --git a/kordophoned/build.rs b/kordophoned/build.rs new file mode 100644 index 0000000..e9d606b --- /dev/null +++ b/kordophoned/build.rs @@ -0,0 +1,24 @@ +const KORDOPHONE_XML: &str = "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-server.rs"); + + let opts = dbus_codegen::GenOpts { + connectiontype: dbus_codegen::ConnectionType::Nonblock, + methodtype: None, // Set to None for crossroads + crossroads: true, + ..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 server dbus interface"); + + std::fs::write(out_path, output) + .expect("Error writing server dbus code"); + + println!("cargo:rerun-if-changed={}", KORDOPHONE_XML); +} diff --git a/kordophoned/include/net.buzzert.kordophonecd.Server.xml b/kordophoned/include/net.buzzert.kordophonecd.Server.xml new file mode 100644 index 0000000..4e2b4b9 --- /dev/null +++ b/kordophoned/include/net.buzzert.kordophonecd.Server.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/kordophoned/src/daemon/mod.rs b/kordophoned/src/daemon/mod.rs new file mode 100644 index 0000000..5f75ab0 --- /dev/null +++ b/kordophoned/src/daemon/mod.rs @@ -0,0 +1,11 @@ +use std::sync::Arc; + +pub struct Daemon { + pub version: String, +} + +impl Daemon { + pub fn new() -> Self { + Self { version: "0.1.0".to_string() } + } +} \ No newline at end of file diff --git a/kordophoned/src/dbus/endpoint.rs b/kordophoned/src/dbus/endpoint.rs new file mode 100644 index 0000000..66f6350 --- /dev/null +++ b/kordophoned/src/dbus/endpoint.rs @@ -0,0 +1,93 @@ +use crate::{dbus::interface::OBJECT_PATH, daemon::Daemon}; + +use crossroads::Crossroads; +use dbus::{ + channel::{MatchingReceiver, Sender}, + message::MatchRule, + nonblock::SyncConnection, + Path, +}; + +use dbus_crossroads as crossroads; +use dbus_tokio::connection; +use dbus_tree::{DataType, MethodErr}; +use log::info; +use std::{future::Future, sync::Arc, thread}; + +mod dbus_interface { + #![allow(unused)] + include!(concat!(env!("OUT_DIR"), "/kordophone-server.rs")); +} + +use dbus_interface::NetBuzzertKordophoneServer; + +pub struct Endpoint { + connection: Arc, + daemon: Arc, +} + +impl Endpoint { + pub fn new(daemon: Arc) -> Self { + let (resource, connection) = connection::new_session_sync().unwrap(); + + // The resource is a task that should be spawned onto a tokio compatible + // reactor ASAP. If the resource ever finishes, you lost connection to D-Bus. + // + // To shut down the connection, both call _handle.abort() and drop the connection. + let _handle = tokio::spawn(async { + let err = resource.await; + panic!("Lost connection to D-Bus: {}", err); + }); + + Self { connection, daemon } + } + + pub async fn start(&self) { + use crate::dbus::interface; + + self.connection + .request_name(interface::NAME, false, true, false) + .await + .expect("Unable to acquire dbus name"); + + let mut cr = Crossroads::new(); + + // Enable async support for the crossroads instance. + // (Currently irrelevant since dbus generates sync code) + cr.set_async_support(Some(( + self.connection.clone(), + Box::new(|x| { + tokio::spawn(x); + }), + ))); + + // Register the daemon as a D-Bus object. + let token = dbus_interface::register_net_buzzert_kordophone_server(&mut cr); + cr.insert(OBJECT_PATH, &[token], self.daemon.clone()); + + // Start receiving messages. + self.connection.start_receive( + MatchRule::new_method_call(), + Box::new(move |msg, conn| + cr.handle_message(msg, conn).is_ok() + ), + ); + + info!(target: "dbus", "DBus server started"); + } + + pub fn send_signal(&self, signal: S) -> Result + where + S: dbus::message::SignalArgs + dbus::arg::AppendAll, + { + let message = signal.to_emit_message(&Path::new(OBJECT_PATH).unwrap()); + self.connection.send(message) + } + +} + +impl NetBuzzertKordophoneServer for Arc { + fn get_version(&mut self) -> Result { + Ok(self.version.clone()) + } +} diff --git a/kordophoned/src/dbus/mod.rs b/kordophoned/src/dbus/mod.rs new file mode 100644 index 0000000..e178de5 --- /dev/null +++ b/kordophoned/src/dbus/mod.rs @@ -0,0 +1,6 @@ +pub mod endpoint; + +pub mod interface { + pub static NAME: &str = "net.buzzert.kordophonecd"; + pub static OBJECT_PATH: &str = "/net/buzzert/kordophone/Server"; +} diff --git a/kordophoned/src/main.rs b/kordophoned/src/main.rs new file mode 100644 index 0000000..6761a1f --- /dev/null +++ b/kordophoned/src/main.rs @@ -0,0 +1,24 @@ +mod dbus; +mod daemon; + +use std::future; +use std::sync::Arc; +use log::LevelFilter; +fn initialize_logging() { + env_logger::Builder::from_default_env() + .filter_level(LevelFilter::Info) + .format_timestamp_secs() + .init(); +} + +#[tokio::main] +async fn main() { + initialize_logging(); + + let daemon = Arc::new(daemon::Daemon::new()); + let endpoint = Arc::new(dbus::endpoint::Endpoint::new(daemon)); + endpoint.start().await; + + future::pending::<()>().await; + unreachable!() +}