From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/dbus/src/dispatcher.rs | 129 ++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 third_party/rust/dbus/src/dispatcher.rs (limited to 'third_party/rust/dbus/src/dispatcher.rs') diff --git a/third_party/rust/dbus/src/dispatcher.rs b/third_party/rust/dbus/src/dispatcher.rs new file mode 100644 index 0000000000..eda78ed586 --- /dev/null +++ b/third_party/rust/dbus/src/dispatcher.rs @@ -0,0 +1,129 @@ +use crate::{Message, MessageType, Error, to_c_str, c_str_to_slice}; +use std::ptr; + +use std::collections::HashMap; + +/// [Unstable and Experimental] +pub trait MessageDispatcherConfig: Sized { + /// The type of method reply stored inside the dispatcher + type Reply; + + /// Called when a method call has received a reply. + fn on_reply(reply: Self::Reply, msg: Message, dispatcher: &mut MessageDispatcher); + + /// Called when a signal is received. + /// + /// Defaults to doing nothing. + #[allow(unused_variables)] + fn on_signal(msg: Message, dispatcher: &mut MessageDispatcher) {} + + /// Called when a method call is received. + /// + /// Defaults to calling default_dispatch. + fn on_method_call(msg: Message, dispatcher: &mut MessageDispatcher) { + if let Some(reply) = MessageDispatcher::::default_dispatch(&msg) { + Self::on_send(reply, dispatcher); + } + } + + /// Called in the other direction, i e, when a message should be sent over the connection. + fn on_send(msg: Message, dispatcher: &mut MessageDispatcher); +} + +/// Dummy implementation +impl MessageDispatcherConfig for () { + type Reply = (); + fn on_reply(_: Self::Reply, _: Message, _: &mut MessageDispatcher) { unreachable!() } + fn on_send(_: Message, _: &mut MessageDispatcher) { unreachable!() } +} + +/// [Unstable and Experimental] Meant for usage with RxTx. +pub struct MessageDispatcher { + waiting_replies: HashMap, + inner: C, +} + +impl MessageDispatcher { + + /// Creates a new message dispatcher. + pub fn new(inner: C) -> Self { MessageDispatcher { + waiting_replies: HashMap::new(), + inner: inner, + } } + + /// "Inner" accessor + pub fn inner(&self) -> &C { &self.inner } + + /// "Inner" mutable accessor + pub fn inner_mut(&mut self) -> &mut C { &mut self.inner } + + /// Adds a waiting reply to a method call. func will be called when a method reply is dispatched. + pub fn add_reply(&mut self, serial: u32, func: C::Reply) { + if let Some(_) = self.waiting_replies.insert(serial, func) { + // panic because we're overwriting something else, or just ignore? + } + } + + /// Cancels a waiting reply. + pub fn cancel_reply(&mut self, serial: u32) -> Option { + self.waiting_replies.remove(&serial) + } + + + /// Dispatch an incoming message. + pub fn dispatch(&mut self, msg: Message) { + if let Some(serial) = msg.get_reply_serial() { + if let Some(sender) = self.waiting_replies.remove(&serial) { + C::on_reply(sender, msg, self); + return; + } + } + match msg.msg_type() { + MessageType::Signal => C::on_signal(msg, self), + MessageType::MethodCall => C::on_method_call(msg, self), + MessageType::Error | MessageType::MethodReturn => {}, + MessageType::Invalid => unreachable!(), + } + } + + /// Handles what we need to be a good D-Bus citizen. + /// + /// Call this if you have not handled the message yourself: + /// * It handles calls to org.freedesktop.DBus.Peer. + /// * For other method calls, it sends an error reply back that the method was unknown. + pub fn default_dispatch(m: &Message) -> Option { + Self::peer(&m) + .or_else(|| Self::unknown_method(&m)) + } + + /// Replies if this is a call to org.freedesktop.DBus.Peer, otherwise returns None. + pub fn peer(m: &Message) -> Option { + if let Some(intf) = m.interface() { + if &*intf != "org.freedesktop.DBus.Peer" { return None; } + if let Some(method) = m.member() { + if &*method == "Ping" { return Some(m.method_return()) } + if &*method == "GetMachineId" { + let mut r = m.method_return(); + let mut e = Error::empty(); + unsafe { + let id = ffi::dbus_try_get_local_machine_id(e.get_mut()); + if id != ptr::null_mut() { + r = r.append1(c_str_to_slice(&(id as *const _)).unwrap()); + ffi::dbus_free(id as *mut _); + return Some(r) + } + } + } + } + Some(m.error(&"org.freedesktop.DBus.Error.UnknownMethod".into(), &to_c_str("Method does not exist"))) + } else { None } + } + + /// For method calls, it replies that the method was unknown, otherwise returns None. + pub fn unknown_method(m: &Message) -> Option { + if m.msg_type() != MessageType::MethodCall { return None; } + // if m.get_no_reply() { return None; } // The reference implementation does not do this? + Some(m.error(&"org.freedesktop.DBus.Error.UnknownMethod".into(), &to_c_str("Path, Interface, or Method does not exist"))) + } +} + -- cgit v1.2.3