diff options
Diffstat (limited to 'gd/rust/linux/dbus_projection/src/lib.rs')
-rw-r--r-- | gd/rust/linux/dbus_projection/src/lib.rs | 102 |
1 files changed, 0 insertions, 102 deletions
diff --git a/gd/rust/linux/dbus_projection/src/lib.rs b/gd/rust/linux/dbus_projection/src/lib.rs deleted file mode 100644 index 7d948a730..000000000 --- a/gd/rust/linux/dbus_projection/src/lib.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! This crate provides tools to automatically project generic API to D-Bus RPC. -//! -//! For D-Bus projection to work automatically, the API needs to follow certain restrictions. - -use dbus::channel::MatchingReceiver; -use dbus::message::MatchRule; -use dbus::nonblock::SyncConnection; -use dbus::strings::BusName; - -use std::collections::HashMap; -use std::sync::{Arc, Mutex}; - -/// A D-Bus "NameOwnerChanged" handler that continuously monitors client disconnects. -pub struct DisconnectWatcher { - callbacks: Arc<Mutex<HashMap<BusName<'static>, Vec<Box<dyn Fn() + Send>>>>>, -} - -impl DisconnectWatcher { - /// Creates a new DisconnectWatcher with empty callbacks. - pub fn new() -> DisconnectWatcher { - DisconnectWatcher { callbacks: Arc::new(Mutex::new(HashMap::new())) } - } -} - -impl DisconnectWatcher { - /// Adds a client address to be monitored for disconnect events. - pub fn add(&mut self, address: BusName<'static>, callback: Box<dyn Fn() + Send>) { - if !self.callbacks.lock().unwrap().contains_key(&address) { - self.callbacks.lock().unwrap().insert(address.clone(), vec![]); - } - - (*self.callbacks.lock().unwrap().get_mut(&address).unwrap()).push(callback); - } - - /// Sets up the D-Bus handler that monitors client disconnects. - pub async fn setup_watch(&mut self, conn: Arc<SyncConnection>) { - let mr = MatchRule::new_signal("org.freedesktop.DBus", "NameOwnerChanged"); - - conn.add_match_no_cb(&mr.match_str()).await.unwrap(); - let callbacks_map = self.callbacks.clone(); - conn.start_receive( - mr, - Box::new(move |msg, _conn| { - // The args are "address", "old address", "new address". - // https://dbus.freedesktop.org/doc/dbus-specification.html#bus-messages-name-owner-changed - let (addr, old, new) = msg.get3::<String, String, String>(); - - if addr.is_none() || old.is_none() || new.is_none() { - return true; - } - - if old.unwrap().eq("") || !new.unwrap().eq("") { - return true; - } - - // If old address exists but new address is empty, that means that client is - // disconnected. So call the registered callbacks to be notified of this client - // disconnect. - let addr = BusName::new(addr.unwrap()).unwrap().into_static(); - if !callbacks_map.lock().unwrap().contains_key(&addr) { - return true; - } - - for callback in &callbacks_map.lock().unwrap()[&addr] { - callback(); - } - - callbacks_map.lock().unwrap().remove(&addr); - - true - }), - ); - } -} - -#[macro_export] -macro_rules! impl_dbus_arg_enum { - ($enum_type:ty) => { - impl DBusArg for $enum_type { - type DBusType = i32; - fn from_dbus( - data: i32, - _conn: Arc<SyncConnection>, - _remote: BusName<'static>, - _disconnect_watcher: Arc<Mutex<dbus_projection::DisconnectWatcher>>, - ) -> Result<$enum_type, Box<dyn Error>> { - match <$enum_type>::from_i32(data) { - Some(x) => Ok(x), - None => Err(Box::new(DBusArgError::new(String::from(format!( - "error converting {} to {}", - data, - stringify!($enum_type) - ))))), - } - } - - fn to_dbus(data: $enum_type) -> Result<i32, Box<dyn Error>> { - return Ok(data.to_i32().unwrap()); - } - } - }; -} |