1 use super::utils::{ArcMap, Iter, IterE, Annotations, Introspect};
2 use super::{Factory, MethodType, MethodInfo, MethodResult, MethodErr, DataType, Property, Method, Signal, methodtype};
3 use std::sync::{Arc, Mutex};
4 use dbus::{Message, MessageType, Error, arg, message, channel};
5 use dbus::strings::{Member, Path, Signature, Interface as IfaceName};
6 use dbus::ffidisp::{ConnectionItem, MsgHandler, Connection, MsgHandlerType, MsgHandlerResult};
7 use std::fmt;
8 use super::leaves::prop_append_dict;
9 use dbus::channel::Channel;
10 use std::time::Duration;
11 
introspect_map<I: fmt::Display, T: Introspect> (h: &ArcMap<I, T>, indent: &str) -> String12 fn introspect_map<I: fmt::Display, T: Introspect>
13     (h: &ArcMap<I, T>, indent: &str) -> String {
14 
15     h.iter().fold("".into(), |a, (k, v)| {
16         let (name, params, contents) = (v.xml_name(), v.xml_params(), v.xml_contents());
17         format!("{}{}<{} name=\"{}\"{}{}>\n",
18             a, indent, name, &*k, params, if !contents.is_empty() {
19                 format!(">\n{}{}</{}", contents, indent, name)
20             }
21             else { "/".to_string() }
22         )
23     })
24 }
25 
26 #[derive(Debug)]
27 /// Represents a D-Bus interface.
28 pub struct Interface<M: MethodType<D>, D: DataType> {
29     name: Arc<IfaceName<'static>>,
30     methods: ArcMap<Member<'static>, Method<M, D>>,
31     signals: ArcMap<Member<'static>, Signal<D>>,
32     properties: ArcMap<String, Property<M, D>>,
33     anns: Annotations,
34     data: D::Interface,
35 }
36 
37 impl<M: MethodType<D>, D: DataType> Interface<M, D> {
38     /// Builder function that adds a method to the interface.
add_m<I: Into<Arc<Method<M, D>>>>(mut self, m: I) -> Self39     pub fn add_m<I: Into<Arc<Method<M, D>>>>(mut self, m: I) -> Self {
40         let m = m.into();
41         self.methods.insert(m.get_name().clone(), m);
42         self
43     }
44 
45     /// Builder function that adds a signal to the interface.
add_s<I: Into<Arc<Signal<D>>>>(mut self, s: I) -> Self46     pub fn add_s<I: Into<Arc<Signal<D>>>>(mut self, s: I) -> Self {
47         let m = s.into();
48         self.signals.insert(m.get_name().clone(), m);
49         self
50     }
51 
52     /// Builder function that adds a property to the interface.
add_p<I: Into<Arc<Property<M, D>>>>(mut self, p: I) -> Self53     pub fn add_p<I: Into<Arc<Property<M, D>>>>(mut self, p: I) -> Self {
54         let m = p.into();
55         self.properties.insert(m.get_name().to_owned(), m);
56         self
57     }
58 
59     /// Builder function that adds an annotation to this interface.
annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self60     pub fn annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self {
61         self.anns.insert(name, value); self
62     }
63 
64     /// Builder function that adds an annotation that this entity is deprecated.
deprecated(self) -> Self65     pub fn deprecated(self) -> Self { self.annotate("org.freedesktop.DBus.Deprecated", "true") }
66 
67     /// Get interface name
get_name(&self) -> &IfaceName<'static>68     pub fn get_name(&self) -> &IfaceName<'static> { &self.name }
69 
70     /// Get associated data
get_data(&self) -> &D::Interface71     pub fn get_data(&self) -> &D::Interface { &self.data }
72 
73     /// Iterates over methods implemented by this interface.
iter_m<'a>(&'a self) -> Iter<'a, Method<M, D>>74     pub fn iter_m<'a>(&'a self) -> Iter<'a, Method<M, D>> { IterE::Member(self.methods.values()).into() }
75 
76     /// Iterates over signals implemented by this interface.
iter_s<'a>(&'a self) -> Iter<'a, Signal<D>>77     pub fn iter_s<'a>(&'a self) -> Iter<'a, Signal<D>> { IterE::Member(self.signals.values()).into() }
78 
79     /// Iterates over properties implemented by this interface.
iter_p<'a>(&'a self) -> Iter<'a, Property<M, D>>80     pub fn iter_p<'a>(&'a self) -> Iter<'a, Property<M, D>> { IterE::String(self.properties.values()).into() }
81 }
82 
83 impl<M: MethodType<D>, D: DataType> Introspect for Interface<M, D> {
xml_name(&self) -> &'static str84     fn xml_name(&self) -> &'static str { "interface" }
xml_params(&self) -> String85     fn xml_params(&self) -> String { String::new() }
xml_contents(&self) -> String86     fn xml_contents(&self) -> String {
87         format!("{}{}{}{}",
88             introspect_map(&self.methods, "    "),
89             introspect_map(&self.properties, "    "),
90             introspect_map(&self.signals, "    "),
91             self.anns.introspect("    "))
92     }
93 }
94 
95 
new_interface<M: MethodType<D>, D: DataType>(t: IfaceName<'static>, d: D::Interface) -> Interface<M, D>96 pub fn new_interface<M: MethodType<D>, D: DataType>(t: IfaceName<'static>, d: D::Interface) -> Interface<M, D> {
97     Interface { name: Arc::new(t), methods: ArcMap::new(), signals: ArcMap::new(),
98         properties: ArcMap::new(), anns: Annotations::new(), data: d
99     }
100 }
101 
102 
103 #[derive(Debug)]
104 /// Cache of built-in interfaces, in order to save memory when many object paths implement the same interface(s).
105 pub struct IfaceCache<M: MethodType<D>, D: DataType>(Mutex<ArcMap<IfaceName<'static>, Interface<M, D>>>);
106 
107 impl<M: MethodType<D>, D: DataType> IfaceCache<M, D>
108 where D::Interface: Default {
get<S: Into<IfaceName<'static>> + Clone, F>(&self, s: S, f: F) -> Arc<Interface<M, D>> where F: FnOnce(Interface<M, D>) -> Interface<M, D>109     pub fn get<S: Into<IfaceName<'static>> + Clone, F>(&self, s: S, f: F) -> Arc<Interface<M, D>>
110         where F: FnOnce(Interface<M, D>) -> Interface<M, D> {
111         let s2 = s.clone().into();
112         let mut m = self.0.lock().unwrap();
113         m.entry(s2).or_insert_with(|| {
114             let i = new_interface(s.into(), Default::default());
115             Arc::new(f(i))
116         }).clone()
117     }
118 }
119 
120 impl<M: MethodType<D>, D: DataType> IfaceCache<M, D> {
get_factory<S: Into<IfaceName<'static>> + Clone, F>(&self, s: S, f: F) -> Arc<Interface<M, D>> where F: FnOnce() -> Interface<M, D>121     pub fn get_factory<S: Into<IfaceName<'static>> + Clone, F>(&self, s: S, f: F) -> Arc<Interface<M, D>>
122         where F: FnOnce() -> Interface<M, D> {
123         let s2 = s.clone().into();
124         let mut m = self.0.lock().unwrap();
125         m.entry(s2).or_insert_with(|| {
126             Arc::new(f())
127         }).clone()
128     }
129 
130 
new() -> Arc<Self>131     pub fn new() -> Arc<Self> { Arc::new(IfaceCache(Mutex::new(ArcMap::new()))) }
132 }
133 
134 #[derive(Debug)]
135 /// A D-Bus Object Path.
136 pub struct ObjectPath<M: MethodType<D>, D: DataType> {
137     name: Arc<Path<'static>>,
138     default_iface: Option<IfaceName<'static>>,
139     ifaces: ArcMap<Arc<IfaceName<'static>>, Interface<M, D>>,
140     ifacecache: Arc<IfaceCache<M, D>>,
141     data: D::ObjectPath,
142 }
143 
144 impl<M: MethodType<D>, D: DataType> ObjectPath<M, D> {
145 
146     /// Get property name
get_name(&self) -> &Path<'static>147     pub fn get_name(&self) -> &Path<'static> { &self.name }
148 
149     /// Get associated data
get_data(&self) -> &D::ObjectPath150     pub fn get_data(&self) -> &D::ObjectPath { &self.data }
151 
152     /// Iterates over interfaces implemented by this object path.
iter<'a>(&'a self) -> Iter<'a, Interface<M, D>>153     pub fn iter<'a>(&'a self) -> Iter<'a, Interface<M, D>> { IterE::Iface(self.ifaces.values()).into() }
154 
introspect(&self, tree: &Tree<M, D>) -> String155     pub(super) fn introspect(&self, tree: &Tree<M, D>) -> String {
156         let ifacestr = introspect_map(&self.ifaces, "  ");
157         let olen = if &**self.name == "/" { 1 } else { self.name.len()+1 };
158         let childstr = tree.children(self, true).iter().fold("".to_string(), |na, n|
159             format!("{}  <node name=\"{}\"/>\n", na, &n.name[olen..])
160         );
161 
162         let nodestr = format!(r##"<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
163 <node name="{}">
164 {}{}</node>"##, self.name, ifacestr, childstr);
165         nodestr
166     }
167 
get_iface<'a>(&'a self, iface_name: &'a str) -> Result<&Arc<Interface<M, D>>, MethodErr>168     fn get_iface<'a>(&'a self, iface_name: &'a str) -> Result<&Arc<Interface<M, D>>, MethodErr> {
169         let j = IfaceName::from_slice(iface_name).map_err(|e| MethodErr::invalid_arg(&e))?;
170         self.ifaces.get(&j).ok_or_else(|| MethodErr::no_interface(&j))
171     }
172 
prop_get(&self, m: &MethodInfo<M, D>) -> MethodResult173     fn prop_get(&self, m: &MethodInfo<M, D>) -> MethodResult {
174         let (iname, prop_name): (&str, &str) = m.msg.read2()?;
175         let iface = self.get_iface(iname)?;
176         let prop: &Property<M, D> = iface.properties.get(&String::from(prop_name))
177             .ok_or_else(|| MethodErr::no_property(&prop_name))?;
178         prop.can_get()?;
179         let mut mret = m.msg.method_return();
180         {
181             let mut iter = arg::IterAppend::new(&mut mret);
182             let pinfo = m.to_prop_info(iface, prop);
183             prop.get_as_variant(&mut iter, &pinfo)?;
184         }
185         Ok(vec!(mret))
186     }
187 
prop_get_all(&self, m: &MethodInfo<M, D>) -> MethodResult188     fn prop_get_all(&self, m: &MethodInfo<M, D>) -> MethodResult {
189         let iface = self.get_iface(m.msg.read1()?)?;
190         let mut mret = m.msg.method_return();
191         prop_append_dict(&mut arg::IterAppend::new(&mut mret),
192             iface.properties.values().map(|v| &**v), m)?;
193         Ok(vec!(mret))
194     }
195 
196 
prop_set(&self, m: &MethodInfo<M, D>) -> MethodResult197     fn prop_set(&self, m: &MethodInfo<M, D>) -> MethodResult {
198         let (iname, prop_name): (&str, &str) = m.msg.read2()?;
199         let iface = self.get_iface(iname)?;
200         let prop: &Property<M, D> = iface.properties.get(&String::from(prop_name))
201             .ok_or_else(|| MethodErr::no_property(&prop_name))?;
202 
203         let mut iter = arg::Iter::new(m.msg);
204         iter.next(); iter.next();
205         let mut iter2 = iter;
206         prop.can_set(Some(iter))?;
207 
208         let pinfo = m.to_prop_info(iface, prop);
209         let mut r: Vec<Message> = prop.set_as_variant(&mut iter2, &pinfo)?.into_iter().collect();
210         r.push(m.msg.method_return());
211         Ok(r)
212 
213     }
214 
get_managed_objects(&self, m: &MethodInfo<M, D>) -> MethodResult215     fn get_managed_objects(&self, m: &MethodInfo<M, D>) -> MethodResult {
216         use dbus::arg::{Dict, Variant};
217         let paths = m.tree.children(&self, false);
218         let mut result = Ok(());
219         let mut r = m.msg.method_return();
220         {
221             let mut i = arg::IterAppend::new(&mut r);
222             i.append_dict(&Signature::make::<Path>(), &Signature::make::<Dict<&str,Dict<&str,Variant<()>,()>,()>>(), |ii| {
223                 for p in paths {
224                     ii.append_dict_entry(|pi| {
225                         pi.append(&*p.name);
226                         pi.append_dict(&Signature::make::<&str>(), &Signature::make::<Dict<&str,Variant<()>,()>>(), |pii| {
227                             for ifaces in p.ifaces.values() {
228                                 let m2 = MethodInfo { msg: m.msg, path: p, iface: ifaces, tree: m.tree, method: m.method };
229                                 pii.append_dict_entry(|ppii| {
230                                     ppii.append(&**ifaces.name);
231                                     result = prop_append_dict(ppii, ifaces.properties.values().map(|v| &**v), &m2);
232                                 });
233                                 if result.is_err() { break; }
234                             }
235                         });
236                     });
237                     if result.is_err() { break; }
238                 }
239             });
240         }
241         result?;
242         Ok(vec!(r))
243     }
244 
handle(&self, m: &Message, t: &Tree<M, D>) -> MethodResult245     fn handle(&self, m: &Message, t: &Tree<M, D>) -> MethodResult {
246         let iname = m.interface().or_else(|| { self.default_iface.clone() });
247         let i = iname.and_then(|i| self.ifaces.get(&i)).ok_or_else(|| MethodErr::no_interface(&""))?;
248         let me = m.member().and_then(|me| i.methods.get(&me)).ok_or_else(|| MethodErr::no_method(&""))?;
249         let minfo = MethodInfo { msg: m, tree: t, path: self, iface: i, method: me };
250         me.call(&minfo)
251     }
252 
253 }
254 
255 impl<M: MethodType<D>, D: DataType> ObjectPath<M, D>
256 where <D as DataType>::Interface: Default,
257       <D as DataType>::Method: Default,
258       <D as DataType>::Signal: Default
259 {
260     /// Adds introspection support for this object path.
introspectable(self) -> Self261     pub fn introspectable(self) -> Self {
262         let z = self.ifacecache.get_factory("org.freedesktop.DBus.Introspectable", || {
263             let f = Factory::from(self.ifacecache.clone());
264             methodtype::org_freedesktop_dbus_introspectable_server(&f, Default::default())
265         });
266         self.add(z)
267     }
268 
269     /// Builder function that adds a interface to the object path.
add<I: Into<Arc<Interface<M, D>>>>(mut self, s: I) -> Self270     pub fn add<I: Into<Arc<Interface<M, D>>>>(mut self, s: I) -> Self {
271         let m = s.into();
272         if !m.properties.is_empty() { self.add_property_handler(); }
273         self.ifaces.insert(m.name.clone(), m);
274         self
275     }
276 
277     /// Builder function that sets what interface should be dispatched on an incoming
278     /// method call without interface.
default_interface(mut self, i: IfaceName<'static>) -> Self279     pub fn default_interface(mut self, i: IfaceName<'static>) -> Self {
280         self.default_iface = Some(i);
281         self
282     }
283 
284     /// Adds ObjectManager support for this object path.
285     ///
286     /// It is not possible to add/remove interfaces while the object path belongs to a tree,
287     /// hence no InterfacesAdded / InterfacesRemoved signals are sent.
object_manager(mut self) -> Self288     pub fn object_manager(mut self) -> Self {
289         use dbus::arg::{Variant, Dict};
290         let ifname = IfaceName::from("org.freedesktop.DBus.ObjectManager");
291         if self.ifaces.contains_key(&ifname) { return self };
292         let z = self.ifacecache.get(ifname, |i| {
293             i.add_m(super::leaves::new_method("GetManagedObjects".into(), Default::default(),
294                 M::make_method(|m| m.path.get_managed_objects(m)))
295                 .outarg::<Dict<Path,Dict<&str,Dict<&str,Variant<()>,()>,()>,()>,_>("objpath_interfaces_and_properties"))
296         });
297         self.ifaces.insert(z.name.clone(), z);
298         self
299     }
300 
add_property_handler(&mut self)301     fn add_property_handler(&mut self) {
302         use dbus::arg::{Variant, Dict};
303         let ifname = IfaceName::from("org.freedesktop.DBus.Properties");
304         if self.ifaces.contains_key(&ifname) { return };
305         let z = self.ifacecache.get(ifname, |i| {
306             i.add_m(super::leaves::new_method("Get".into(), Default::default(),
307                 M::make_method(|m| m.path.prop_get(m)))
308                 .inarg::<&str,_>("interface_name")
309                 .inarg::<&str,_>("property_name")
310                 .outarg::<Variant<()>,_>("value"))
311             .add_m(super::leaves::new_method("GetAll".into(), Default::default(),
312                 M::make_method(|m| m.path.prop_get_all(m)))
313                 .inarg::<&str,_>("interface_name")
314                 .outarg::<Dict<&str, Variant<()>, ()>,_>("props"))
315             .add_m(super::leaves::new_method("Set".into(), Default::default(),
316                 M::make_method(|m| m.path.prop_set(m)))
317                 .inarg::<&str,_>("interface_name")
318                 .inarg::<&str,_>("property_name")
319                 .inarg::<Variant<bool>,_>("value"))
320             .add_s(super::leaves::new_signal("PropertiesChanged".into(), Default::default())
321                 .sarg::<&str, _>("interface_name")
322                 .sarg::<Dict<&str, Variant<()>, ()>, _>("changed_properties")
323                 .sarg::<Vec<&str>, _>("invalidated_properties"))
324         });
325         self.ifaces.insert(z.name.clone(), z);
326     }
327 }
328 
new_objectpath<M: MethodType<D>, D: DataType>(n: Path<'static>, d: D::ObjectPath, cache: Arc<IfaceCache<M, D>>) -> ObjectPath<M, D>329 pub fn new_objectpath<M: MethodType<D>, D: DataType>(n: Path<'static>, d: D::ObjectPath, cache: Arc<IfaceCache<M, D>>)
330     -> ObjectPath<M, D> {
331     ObjectPath { name: Arc::new(n), data: d, ifaces: ArcMap::new(), ifacecache: cache, default_iface: None }
332 }
333 
334 
335 /// A collection of object paths.
336 #[derive(Debug, Default)]
337 pub struct Tree<M: MethodType<D>, D: DataType> {
338     paths: ArcMap<Arc<Path<'static>>, ObjectPath<M, D>>,
339     data: D::Tree,
340 }
341 
342 impl<M: MethodType<D>, D: DataType> Tree<M, D> {
343     /// Builder function that adds an object path to this tree.
add<I: Into<Arc<ObjectPath<M, D>>>>(mut self, s: I) -> Self344     pub fn add<I: Into<Arc<ObjectPath<M, D>>>>(mut self, s: I) -> Self {
345         self.insert(s);
346         self
347     }
348 
349     /// Get a reference to an object path from the tree.
get(&self, p: &Path<'static>) -> Option<&Arc<ObjectPath<M, D>>>350     pub fn get(&self, p: &Path<'static>) -> Option<&Arc<ObjectPath<M, D>>> {
351         self.paths.get(p)
352     }
353 
354     /// Iterates over object paths in this tree.
iter<'a>(&'a self) -> Iter<'a, ObjectPath<M, D>>355     pub fn iter<'a>(&'a self) -> Iter<'a, ObjectPath<M, D>> { IterE::Path(self.paths.values()).into() }
356 
357     /// Non-builder function that adds an object path to this tree.
insert<I: Into<Arc<ObjectPath<M, D>>>>(&mut self, s: I)358     pub fn insert<I: Into<Arc<ObjectPath<M, D>>>>(&mut self, s: I) {
359         let m = s.into();
360         self.paths.insert(m.name.clone(), m);
361     }
362 
363 
364     /// Remove a object path from the Tree. Returns the object path removed, or None if not found.
remove(&mut self, p: &Path<'static>) -> Option<Arc<ObjectPath<M, D>>>365     pub fn remove(&mut self, p: &Path<'static>) -> Option<Arc<ObjectPath<M, D>>> {
366         // There is no real reason p needs to have a static lifetime; but
367         // the borrow checker doesn't agree. :-(
368         self.paths.remove(p)
369     }
370 
371     /// Registers or unregisters all object paths in the tree to a ffidisp::Connection.
set_registered(&self, c: &Connection, b: bool) -> Result<(), Error>372     pub fn set_registered(&self, c: &Connection, b: bool) -> Result<(), Error> {
373         let mut regd_paths = Vec::new();
374         for p in self.paths.keys() {
375             if b {
376                 match c.register_object_path(p) {
377                     Ok(()) => regd_paths.push(p.clone()),
378                     Err(e) => {
379                         while let Some(rp) = regd_paths.pop() {
380                             c.unregister_object_path(&rp);
381                         }
382                         return Err(e)
383                     }
384                 }
385             } else {
386                 c.unregister_object_path(p);
387             }
388         }
389         Ok(())
390     }
391 
392     /// This method takes an `ConnectionItem` iterator (you get it from `Connection::iter()`)
393     /// and handles all matching items. Non-matching items (e g signals) are passed through.
run<'a, I: Iterator<Item=ConnectionItem>>(&'a self, c: &'a Connection, i: I) -> TreeServer<'a, I, M, D>394     pub fn run<'a, I: Iterator<Item=ConnectionItem>>(&'a self, c: &'a Connection, i: I) -> TreeServer<'a, I, M, D> {
395         TreeServer { iter: i, tree: &self, conn: c }
396     }
397 
398     /// Handles a message.
399     ///
400     /// Will return None in case the object path was not
401     /// found in this tree, or otherwise a list of messages to be sent back.
handle(&self, m: &Message) -> Option<Vec<Message>>402     pub fn handle(&self, m: &Message) -> Option<Vec<Message>> {
403         if m.msg_type() != MessageType::MethodCall { None }
404         else { m.path().and_then(|p| self.paths.get(&p).map(|s| s.handle(m, &self)
405             .unwrap_or_else(|e| vec!(e.to_message(m))))) }
406     }
407 
408     /// Tries to handle an incoming message from the provided channel if there is one. If there isn't one,
409     /// it will wait up to timeout
process_channel(&self, channel: &Channel, timeout: Duration) -> Result<bool, Error>410     pub fn process_channel(&self, channel: &Channel, timeout: Duration) -> Result<bool, Error> {
411         if let Some(msg) = channel.blocking_pop_message(timeout)? {
412             if let Some(replies) = self.handle(&msg) {
413                 for r in replies {
414                     let _ = channel.send(r);
415                 }
416             } else if let Some(reply) = dbus::channel::default_reply(&msg) {
417                 let _ = channel.send(reply);
418             }
419 
420             Ok(true)
421         } else {
422             Ok(false)
423         }
424     }
425 
426 
children(&self, o: &ObjectPath<M, D>, direct_only: bool) -> Vec<&ObjectPath<M, D>>427     fn children(&self, o: &ObjectPath<M, D>, direct_only: bool) -> Vec<&ObjectPath<M, D>> {
428         let parent: &str = &o.name;
429         let plen = if parent == "/" { 1 } else { parent.len()+1 };
430         let mut r: Vec<&ObjectPath<M, D>> = self.paths.values().filter_map(|v| {
431             let k: &str = &v.name;
432             if !k.starts_with(parent) || k.len() <= plen || &k[plen-1..plen] != "/" {None} else {
433                 Some(&**v)
434             }
435         }).collect();
436         if direct_only {
437             r.sort_by_key(|v| &**v.name);
438             // println!("DEBUG before: {:?}", r.iter().map(|v| &**v.name).collect::<Vec<_>>());
439             let mut prev: Option<&ObjectPath<M, D>> = None;
440             r.retain(|v| {
441                 let a = prev.map(|prev|
442                      !(v.name.starts_with(&**prev.name) && v.name.as_bytes().get(prev.name.len()) == Some(&b'/'))
443                  ).unwrap_or(true);
444                 if a { prev = Some(v); }
445                 a
446             });
447         }
448         r
449     }
450 
451     /// Get associated data
get_data(&self) -> &D::Tree452     pub fn get_data(&self) -> &D::Tree { &self.data }
453 }
454 
455 impl<M: MethodType<D> + 'static, D: DataType + 'static> Tree<M, D> {
456     /// Connects a SyncConnection with a Tree so that incoming method calls are handled.
457     ///
458     /// The tree needs to be of type MTSync.
start_receive_sync<C>(self, connection: &C) where C: channel::MatchingReceiver<F=Box<dyn FnMut(Message, &C) -> bool + Send + Sync>> + channel::Sender, D::Tree: Send + Sync, D::ObjectPath: Send + Sync, D::Interface: Send + Sync, D::Property: Send + Sync, D::Method: Send + Sync, D::Signal: Send + Sync, M::Method: Send + Sync, M::GetProp: Send + Sync, M::SetProp: Send + Sync,459     pub fn start_receive_sync<C>(self, connection: &C)
460     where
461         C: channel::MatchingReceiver<F=Box<dyn FnMut(Message, &C) -> bool + Send + Sync>> + channel::Sender,
462         D::Tree: Send + Sync, D::ObjectPath: Send + Sync, D::Interface: Send + Sync,
463         D::Property: Send + Sync, D::Method: Send + Sync, D::Signal: Send + Sync,
464         M::Method: Send + Sync, M::GetProp: Send + Sync, M::SetProp: Send + Sync,
465     {
466         connection.start_receive(message::MatchRule::new_method_call(), Box::new(move |msg, c| {
467             if let Some(replies) = self.handle(&msg) {
468                 for r in replies { let _ = c.send(r); }
469             }
470             true
471         }));
472     }
473 
474     /// Connects a Connection with a Tree so that incoming method calls are handled.
475     ///
476     /// The tree needs to be of type MTSync.
start_receive_send<C>(self, connection: &C) where C: channel::MatchingReceiver<F=Box<dyn FnMut(Message, &C) -> bool + Send>> + channel::Sender, D::Tree: Send + Sync, D::ObjectPath: Send + Sync, D::Interface: Send + Sync, D::Property: Send + Sync, D::Method: Send + Sync, D::Signal: Send + Sync, M::Method: Send + Sync, M::GetProp: Send + Sync, M::SetProp: Send + Sync,477     pub fn start_receive_send<C>(self, connection: &C)
478     where
479         C: channel::MatchingReceiver<F=Box<dyn FnMut(Message, &C) -> bool + Send>> + channel::Sender,
480         D::Tree: Send + Sync, D::ObjectPath: Send + Sync, D::Interface: Send + Sync,
481         D::Property: Send + Sync, D::Method: Send + Sync, D::Signal: Send + Sync,
482         M::Method: Send + Sync, M::GetProp: Send + Sync, M::SetProp: Send + Sync,
483     {
484         connection.start_receive(message::MatchRule::new_method_call(), Box::new(move |msg, c| {
485             if let Some(replies) = self.handle(&msg) {
486                 for r in replies { let _ = c.send(r); }
487             }
488             true
489         }));
490     }
491 
492 
493     /// Connects a LocalConnection with a Tree so that incoming method calls are handled.
start_receive<C>(self, connection: &C) where C: channel::MatchingReceiver<F=Box<dyn FnMut(Message, &C) -> bool>> + channel::Sender494     pub fn start_receive<C>(self, connection: &C)
495     where
496         C: channel::MatchingReceiver<F=Box<dyn FnMut(Message, &C) -> bool>> + channel::Sender
497     {
498         connection.start_receive(message::MatchRule::new_method_call(), Box::new(move |msg, c| {
499             if let Some(replies) = self.handle(&msg) {
500                 for r in replies { let _ = c.send(r); }
501             }
502             true
503         }));
504     }
505 
506 }
507 
new_tree<M: MethodType<D>, D: DataType>(d: D::Tree) -> Tree<M, D>508 pub fn new_tree<M: MethodType<D>, D: DataType>(d: D::Tree) -> Tree<M, D> {
509     Tree { paths: ArcMap::new(), data: d }
510 }
511 
512 impl<M: MethodType<D>, D: DataType> MsgHandler for Tree<M, D> {
handle_msg(&mut self, msg: &Message) -> Option<MsgHandlerResult>513     fn handle_msg(&mut self, msg: &Message) -> Option<MsgHandlerResult> {
514         self.handle(msg).map(|v| MsgHandlerResult { handled: true, done: false, reply: v })
515     }
handler_type(&self) -> MsgHandlerType516     fn handler_type(&self) -> MsgHandlerType { MsgHandlerType::MsgType(MessageType::MethodCall) }
517 }
518 /*
519 impl<M: MethodType<D>, D: DataType> MsgHandler for Arc<Tree<M, D>> {
520     fn handle_msg(&mut self, msg: &Message) -> Option<MsgHandlerResult> {
521         self.handle(msg).map(|v| MsgHandlerResult { handled: true, done: false, reply: v })
522     }
523     fn handler_type(&self) -> MsgHandlerType { MsgHandlerType::MsgType(MessageType::MethodCall) }
524 }
525 */
526 /// An iterator adapter that handles incoming method calls.
527 ///
528 /// Method calls that match an object path in the tree are handled and consumed by this
529 /// iterator. Other messages are passed through.
530 pub struct TreeServer<'a, I, M: MethodType<D> + 'a, D: DataType + 'a> {
531     iter: I,
532     conn: &'a Connection,
533     tree: &'a Tree<M, D>,
534 }
535 
536 impl<'a, I: Iterator<Item=ConnectionItem>, M: 'a + MethodType<D>, D: DataType + 'a> Iterator for TreeServer<'a, I, M, D> {
537     type Item = ConnectionItem;
538 
next(&mut self) -> Option<ConnectionItem>539     fn next(&mut self) -> Option<ConnectionItem> {
540         loop {
541             let n = self.iter.next();
542             if let Some(ConnectionItem::MethodCall(ref msg)) = n {
543                 if let Some(v) = self.tree.handle(&msg) {
544                     // Probably the wisest is to ignore any send errors here -
545                     // maybe the remote has disconnected during our processing.
546                     for m in v { let _ = self.conn.send(m); };
547                     continue;
548                 }
549             }
550             return n;
551         }
552     }
553 }
554 
555 
556 #[test]
test_iter()557 fn test_iter() {
558     let f = super::Factory::new_fn::<()>();
559     let t = f.tree(())
560     .add(f.object_path("/echo", ()).introspectable()
561         .add(f.interface("com.example.echo", ())
562             .add_m(f.method("Echo", (), |_| unimplemented!()).in_arg(("request", "s")).out_arg(("reply", "s")))
563             .add_p(f.property::<i32,_>("EchoCount", ()))
564             .add_s(f.signal("Echoed", ()).arg(("data", "s")).deprecated()
565         )
566     )).add(f.object_path("/echo/subpath", ()));
567 
568     let paths: Vec<_> = t.iter().collect();
569     assert_eq!(paths.len(), 2);
570 }
571 
572 #[test]
test_set_default_interface()573 fn test_set_default_interface() {
574     let iface_name: IfaceName<'_> = "com.example.echo".into();
575     let f = super::Factory::new_fn::<()>();
576     let t = f.object_path("/echo", ()).default_interface(iface_name.clone());
577     assert_eq!(t.default_iface, Some(iface_name));
578 }
579 
580 
581 #[test]
test_introspection()582 fn test_introspection() {
583     let f = super::Factory::new_fn::<()>();
584     let t = f.object_path("/echo", ()).introspectable()
585         .add(f.interface("com.example.echo", ())
586             .add_m(f.method("Echo", (), |_| unimplemented!()).in_arg(("request", "s")).out_arg(("reply", "s")))
587             .add_p(f.property::<i32,_>("EchoCount", ()))
588             .add_s(f.signal("Echoed", ()).arg(("data", "s")).deprecated())
589     );
590 
591     let actual_result = t.introspect(&f.tree(()).add(f.object_path("/echo/subpath2", ())).add(f.object_path("/echo/subpath", ())));
592     println!("\n=== Introspection XML start ===\n{}\n=== Introspection XML end ===", actual_result);
593 
594     let expected_result = r##"<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
595 <node name="/echo">
596   <interface name="com.example.echo">
597     <method name="Echo">
598       <arg name="request" type="s" direction="in"/>
599       <arg name="reply" type="s" direction="out"/>
600     </method>
601     <property name="EchoCount" type="i" access="read"/>
602     <signal name="Echoed">
603       <arg name="data" type="s"/>
604       <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
605     </signal>
606   </interface>
607   <interface name="org.freedesktop.DBus.Introspectable">
608     <method name="Introspect">
609       <arg name="xml_data" type="s" direction="out"/>
610     </method>
611   </interface>
612   <interface name="org.freedesktop.DBus.Properties">
613     <method name="Get">
614       <arg name="interface_name" type="s" direction="in"/>
615       <arg name="property_name" type="s" direction="in"/>
616       <arg name="value" type="v" direction="out"/>
617     </method>
618     <method name="GetAll">
619       <arg name="interface_name" type="s" direction="in"/>
620       <arg name="props" type="a{sv}" direction="out"/>
621     </method>
622     <method name="Set">
623       <arg name="interface_name" type="s" direction="in"/>
624       <arg name="property_name" type="s" direction="in"/>
625       <arg name="value" type="v" direction="in"/>
626     </method>
627     <signal name="PropertiesChanged">
628       <arg name="interface_name" type="s"/>
629       <arg name="changed_properties" type="a{sv}"/>
630       <arg name="invalidated_properties" type="as"/>
631     </signal>
632   </interface>
633   <node name="subpath"/>
634   <node name="subpath2"/>
635 </node>"##;
636 
637     assert_eq!(expected_result, actual_result);
638 }
639 
640 #[test]
test_introspection_dynamic()641 fn test_introspection_dynamic() {
642     let f = super::Factory::new_fn::<()>();
643     let tree = f
644         .tree(())
645         .add(f.object_path("/", ()).introspectable())
646         .add(f.object_path("/foo/bar", ()).introspectable())
647         .add(f.object_path("/foo/bar/item1", ()).introspectable());
648 
649     // For / only node /foo/bar is listed.
650     let o = f.object_path("/", ()).introspectable();
651     let actual_result = o.introspect(&tree);
652     println!("\n=== Introspection XML start ===\n{}\n=== Introspection XML end ===", actual_result);
653 
654     let expected_result = r##"<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
655 <node name="/">
656   <interface name="org.freedesktop.DBus.Introspectable">
657     <method name="Introspect">
658       <arg name="xml_data" type="s" direction="out"/>
659     </method>
660   </interface>
661   <node name="foo/bar"/>
662 </node>"##;
663 
664     assert_eq!(expected_result, actual_result);
665 
666     // For /foo/bar node /foo/bar/item1 is listed.
667     let o = f.object_path("/foo/bar", ()).introspectable();
668     let actual_result = o.introspect(&tree);
669     println!("\n=== Introspection XML start ===\n{}\n=== Introspection XML end ===", actual_result);
670 
671     let expected_result = r##"<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
672 <node name="/foo/bar">
673   <interface name="org.freedesktop.DBus.Introspectable">
674     <method name="Introspect">
675       <arg name="xml_data" type="s" direction="out"/>
676     </method>
677   </interface>
678   <node name="item1"/>
679 </node>"##;
680 
681     assert_eq!(expected_result, actual_result);
682 
683     // Dynamically add an object /foo/bar/item2.
684     let tree = tree.add(f.object_path("/foo/bar/item2", ()).introspectable());
685 
686     // Now, for / still only node /foo/bar is listed.
687     let o = f.object_path("/", ()).introspectable();
688     let actual_result = o.introspect(&tree);
689     println!("\n=== Introspection XML start ===\n{}\n=== Introspection XML end ===", actual_result);
690 
691     let expected_result = r##"<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
692 <node name="/">
693   <interface name="org.freedesktop.DBus.Introspectable">
694     <method name="Introspect">
695       <arg name="xml_data" type="s" direction="out"/>
696     </method>
697   </interface>
698   <node name="foo/bar"/>
699 </node>"##;
700 
701     assert_eq!(expected_result, actual_result);
702 
703     // And for /foo/bar node /foo/bar/item2 is now listed too.
704     let o = f.object_path("/foo/bar", ()).introspectable();
705     let actual_result = o.introspect(&tree);
706     println!("\n=== Introspection XML start ===\n{}\n=== Introspection XML end ===", actual_result);
707 
708     let expected_result = r##"<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
709 <node name="/foo/bar">
710   <interface name="org.freedesktop.DBus.Introspectable">
711     <method name="Introspect">
712       <arg name="xml_data" type="s" direction="out"/>
713     </method>
714   </interface>
715   <node name="item1"/>
716   <node name="item2"/>
717 </node>"##;
718 
719     assert_eq!(expected_result, actual_result);
720 }
721