1 use crate::{Message, MessageType, Error, to_c_str, c_str_to_slice};
2 use std::ptr;
3 
4 use std::collections::HashMap;
5 
6 /// [Unstable and Experimental]
7 pub trait MessageDispatcherConfig: Sized {
8     /// The type of method reply stored inside the dispatcher
9     type Reply;
10 
11     /// Called when a method call has received a reply.
on_reply(reply: Self::Reply, msg: Message, dispatcher: &mut MessageDispatcher<Self>)12     fn on_reply(reply: Self::Reply, msg: Message, dispatcher: &mut MessageDispatcher<Self>);
13 
14     /// Called when a signal is received.
15     ///
16     /// Defaults to doing nothing.
17     #[allow(unused_variables)]
on_signal(msg: Message, dispatcher: &mut MessageDispatcher<Self>)18     fn on_signal(msg: Message, dispatcher: &mut MessageDispatcher<Self>) {}
19 
20     /// Called when a method call is received.
21     ///
22     /// Defaults to calling default_dispatch.
on_method_call(msg: Message, dispatcher: &mut MessageDispatcher<Self>)23     fn on_method_call(msg: Message, dispatcher: &mut MessageDispatcher<Self>) {
24         if let Some(reply) = MessageDispatcher::<Self>::default_dispatch(&msg) {
25             Self::on_send(reply, dispatcher);
26         }
27     }
28 
29     /// Called in the other direction, i e, when a message should be sent over the connection.
on_send(msg: Message, dispatcher: &mut MessageDispatcher<Self>)30     fn on_send(msg: Message, dispatcher: &mut MessageDispatcher<Self>);
31 }
32 
33 /// Dummy implementation
34 impl MessageDispatcherConfig for () {
35     type Reply = ();
on_reply(_: Self::Reply, _: Message, _: &mut MessageDispatcher<Self>)36     fn on_reply(_: Self::Reply, _: Message, _: &mut MessageDispatcher<Self>) { unreachable!() }
on_send(_: Message, _: &mut MessageDispatcher<Self>)37     fn on_send(_: Message, _: &mut MessageDispatcher<Self>) { unreachable!() }
38 }
39 
40 /// [Unstable and Experimental] Meant for usage with RxTx.
41 pub struct MessageDispatcher<C: MessageDispatcherConfig> {
42     waiting_replies: HashMap<u32, C::Reply>,
43     inner: C,
44 }
45 
46 impl<C: MessageDispatcherConfig> MessageDispatcher<C> {
47 
48     /// Creates a new message dispatcher.
new(inner: C) -> Self49     pub fn new(inner: C) -> Self { MessageDispatcher {
50         waiting_replies: HashMap::new(),
51         inner: inner,
52     } }
53 
54     /// "Inner" accessor
inner(&self) -> &C55     pub fn inner(&self) -> &C { &self.inner }
56 
57     /// "Inner" mutable accessor
inner_mut(&mut self) -> &mut C58     pub fn inner_mut(&mut self) -> &mut C { &mut self.inner }
59 
60     /// Adds a waiting reply to a method call. func will be called when a method reply is dispatched.
add_reply(&mut self, serial: u32, func: C::Reply)61     pub fn add_reply(&mut self, serial: u32, func: C::Reply) {
62         if let Some(_) = self.waiting_replies.insert(serial, func) {
63             // panic because we're overwriting something else, or just ignore?
64         }
65     }
66 
67     /// Cancels a waiting reply.
cancel_reply(&mut self, serial: u32) -> Option<C::Reply>68     pub fn cancel_reply(&mut self, serial: u32) -> Option<C::Reply> {
69         self.waiting_replies.remove(&serial)
70     }
71 
72 
73     /// Dispatch an incoming message.
dispatch(&mut self, msg: Message)74     pub fn dispatch(&mut self, msg: Message) {
75         if let Some(serial) = msg.get_reply_serial() {
76             if let Some(sender) = self.waiting_replies.remove(&serial) {
77                 C::on_reply(sender, msg, self);
78                 return;
79             }
80         }
81         match msg.msg_type() {
82             MessageType::Signal => C::on_signal(msg, self),
83             MessageType::MethodCall => C::on_method_call(msg, self),
84             MessageType::Error | MessageType::MethodReturn => {},
85             MessageType::Invalid => unreachable!(),
86         }
87     }
88 
89     /// Handles what we need to be a good D-Bus citizen.
90     ///
91     /// Call this if you have not handled the message yourself:
92     /// * It handles calls to org.freedesktop.DBus.Peer.
93     /// * For other method calls, it sends an error reply back that the method was unknown.
default_dispatch(m: &Message) -> Option<Message>94     pub fn default_dispatch(m: &Message) -> Option<Message> {
95         Self::peer(&m)
96             .or_else(|| Self::unknown_method(&m))
97     }
98 
99     /// Replies if this is a call to org.freedesktop.DBus.Peer, otherwise returns None.
peer(m: &Message) -> Option<Message>100     pub fn peer(m: &Message) -> Option<Message> {
101         if let Some(intf) = m.interface() {
102             if &*intf != "org.freedesktop.DBus.Peer" { return None; }
103             if let Some(method) = m.member() {
104                 if &*method == "Ping" { return Some(m.method_return()) }
105                 if &*method == "GetMachineId" {
106                     let mut r = m.method_return();
107                     let mut e = Error::empty();
108                     unsafe {
109                         let id = ffi::dbus_try_get_local_machine_id(e.get_mut());
110                         if id != ptr::null_mut() {
111                             r = r.append1(c_str_to_slice(&(id as *const _)).unwrap());
112                             ffi::dbus_free(id as *mut _);
113                             return Some(r)
114                         }
115                     }
116                 }
117             }
118             Some(m.error(&"org.freedesktop.DBus.Error.UnknownMethod".into(), &to_c_str("Method does not exist")))
119         } else { None }
120     }
121 
122     /// For method calls, it replies that the method was unknown, otherwise returns None.
unknown_method(m: &Message) -> Option<Message>123     pub fn unknown_method(m: &Message) -> Option<Message> {
124         if m.msg_type() != MessageType::MethodCall { return None; }
125         // if m.get_no_reply() { return None; } // The reference implementation does not do this?
126         Some(m.error(&"org.freedesktop.DBus.Error.UnknownMethod".into(), &to_c_str("Path, Interface, or Method does not exist")))
127     }
128 }
129 
130