use log::info; use std::sync::Arc; use crate::{daemon::Daemon, dbus::interface}; use dbus_crossroads::Crossroads; use dbus_tokio::connection; use dbus::{ message::MatchRule, nonblock::SyncConnection, channel::{Sender, MatchingReceiver}, Path, }; 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 = interface::register_net_buzzert_kordophone_server(&mut cr); cr.insert(interface::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(interface::OBJECT_PATH).unwrap()); self.connection.send(message) } }