1 | use event_listener::{Event, EventListener}; |
2 | use serde::Serialize; |
3 | use std::{ |
4 | collections::{hash_map::Entry, HashMap}, |
5 | convert::TryInto, |
6 | fmt::Write, |
7 | marker::PhantomData, |
8 | ops::{Deref, DerefMut}, |
9 | sync::Arc, |
10 | }; |
11 | use tracing::{debug, instrument, trace}; |
12 | |
13 | use static_assertions::assert_impl_all; |
14 | use zbus_names::InterfaceName; |
15 | use zvariant::{ObjectPath, OwnedObjectPath, OwnedValue, Signature, Type, Value}; |
16 | |
17 | use crate::{ |
18 | async_lock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, |
19 | fdo, |
20 | fdo::{Introspectable, ManagedObjects, ObjectManager, Peer, Properties}, |
21 | Connection, DispatchResult, Error, Interface, Message, Result, SignalContext, WeakConnection, |
22 | }; |
23 | |
24 | /// Opaque structure that derefs to an `Interface` type. |
25 | pub struct InterfaceDeref<'d, I> { |
26 | iface: RwLockReadGuard<'d, dyn Interface>, |
27 | phantom: PhantomData<I>, |
28 | } |
29 | |
30 | impl<I> Deref for InterfaceDeref<'_, I> |
31 | where |
32 | I: Interface, |
33 | { |
34 | type Target = I; |
35 | |
36 | fn deref(&self) -> &I { |
37 | self.iface.downcast_ref::<I>().unwrap() |
38 | } |
39 | } |
40 | |
41 | /// Opaque structure that mutably derefs to an `Interface` type. |
42 | pub struct InterfaceDerefMut<'d, I> { |
43 | iface: RwLockWriteGuard<'d, dyn Interface>, |
44 | phantom: PhantomData<I>, |
45 | } |
46 | |
47 | impl<I> Deref for InterfaceDerefMut<'_, I> |
48 | where |
49 | I: Interface, |
50 | { |
51 | type Target = I; |
52 | |
53 | fn deref(&self) -> &I { |
54 | self.iface.downcast_ref::<I>().unwrap() |
55 | } |
56 | } |
57 | |
58 | impl<I> DerefMut for InterfaceDerefMut<'_, I> |
59 | where |
60 | I: Interface, |
61 | { |
62 | fn deref_mut(&mut self) -> &mut Self::Target { |
63 | self.iface.downcast_mut::<I>().unwrap() |
64 | } |
65 | } |
66 | |
67 | /// Wrapper over an interface, along with its corresponding `SignalContext` |
68 | /// instance. A reference to the underlying interface may be obtained via |
69 | /// [`InterfaceRef::get`] and [`InterfaceRef::get_mut`]. |
70 | pub struct InterfaceRef<I> { |
71 | ctxt: SignalContext<'static>, |
72 | lock: Arc<RwLock<dyn Interface>>, |
73 | phantom: PhantomData<I>, |
74 | } |
75 | |
76 | impl<I> InterfaceRef<I> |
77 | where |
78 | I: 'static, |
79 | { |
80 | /// Get a reference to the underlying interface. |
81 | /// |
82 | /// **WARNING:** If methods (e.g property setters) in `ObjectServer` require `&mut self` |
83 | /// `ObjectServer` will not be able to access the interface in question until all references |
84 | /// of this method are dropped, it is highly recommended that the scope of the interface |
85 | /// returned is restricted. |
86 | pub async fn get(&self) -> InterfaceDeref<'_, I> { |
87 | let iface = self.lock.read().await; |
88 | |
89 | iface |
90 | .downcast_ref::<I>() |
91 | .expect("Unexpected interface type" ); |
92 | |
93 | InterfaceDeref { |
94 | iface, |
95 | phantom: PhantomData, |
96 | } |
97 | } |
98 | |
99 | /// Get a reference to the underlying interface. |
100 | /// |
101 | /// **WARNINGS:** Since the `ObjectServer` will not be able to access the interface in question |
102 | /// until the return value of this method is dropped, it is highly recommended that the scope |
103 | /// of the interface returned is restricted. |
104 | /// |
105 | /// # Errors |
106 | /// |
107 | /// If the interface at this instance's path is not valid, `Error::InterfaceNotFound` error is |
108 | /// returned. |
109 | /// |
110 | /// # Examples |
111 | /// |
112 | /// ```no_run |
113 | /// # use std::error::Error; |
114 | /// # use async_io::block_on; |
115 | /// # use zbus::{Connection, dbus_interface}; |
116 | /// |
117 | /// struct MyIface(u32); |
118 | /// |
119 | /// #[dbus_interface(name = "org.myiface.MyIface" )] |
120 | /// impl MyIface { |
121 | /// #[dbus_interface(property)] |
122 | /// async fn count(&self) -> u32 { |
123 | /// self.0 |
124 | /// } |
125 | /// } |
126 | /// |
127 | /// # block_on(async { |
128 | /// // Setup connection and object_server etc here and then in another part of the code: |
129 | /// # let connection = Connection::session().await?; |
130 | /// # |
131 | /// # let path = "/org/zbus/path" ; |
132 | /// # connection.object_server().at(path, MyIface(22)).await?; |
133 | /// let object_server = connection.object_server(); |
134 | /// let iface_ref = object_server.interface::<_, MyIface>(path).await?; |
135 | /// let mut iface = iface_ref.get_mut().await; |
136 | /// iface.0 = 42; |
137 | /// iface.count_changed(iface_ref.signal_context()).await?; |
138 | /// # Ok::<_, Box<dyn Error + Send + Sync>>(()) |
139 | /// # })?; |
140 | /// # |
141 | /// # Ok::<_, Box<dyn Error + Send + Sync>>(()) |
142 | /// ``` |
143 | pub async fn get_mut(&self) -> InterfaceDerefMut<'_, I> { |
144 | let mut iface = self.lock.write().await; |
145 | |
146 | iface |
147 | .downcast_ref::<I>() |
148 | .expect("Unexpected interface type" ); |
149 | iface |
150 | .downcast_mut::<I>() |
151 | .expect("Unexpected interface type" ); |
152 | |
153 | InterfaceDerefMut { |
154 | iface, |
155 | phantom: PhantomData, |
156 | } |
157 | } |
158 | |
159 | pub fn signal_context(&self) -> &SignalContext<'static> { |
160 | &self.ctxt |
161 | } |
162 | } |
163 | |
164 | impl<I> Clone for InterfaceRef<I> { |
165 | fn clone(&self) -> Self { |
166 | Self { |
167 | ctxt: self.ctxt.clone(), |
168 | lock: self.lock.clone(), |
169 | phantom: PhantomData, |
170 | } |
171 | } |
172 | } |
173 | |
174 | #[derive (Default, derivative::Derivative)] |
175 | #[derivative(Debug)] |
176 | pub(crate) struct Node { |
177 | path: OwnedObjectPath, |
178 | children: HashMap<String, Node>, |
179 | #[derivative(Debug = "ignore" )] |
180 | interfaces: HashMap<InterfaceName<'static>, Arc<RwLock<dyn Interface>>>, |
181 | } |
182 | |
183 | impl Node { |
184 | pub(crate) fn new(path: OwnedObjectPath) -> Self { |
185 | let mut node = Self { |
186 | path, |
187 | ..Default::default() |
188 | }; |
189 | node.at(Peer::name(), || Arc::new(RwLock::new(Peer))); |
190 | node.at(Introspectable::name(), || { |
191 | Arc::new(RwLock::new(Introspectable)) |
192 | }); |
193 | node.at(Properties::name(), || Arc::new(RwLock::new(Properties))); |
194 | |
195 | node |
196 | } |
197 | |
198 | // Get the child Node at path. |
199 | pub(crate) fn get_child(&self, path: &ObjectPath<'_>) -> Option<&Node> { |
200 | let mut node = self; |
201 | |
202 | for i in path.split('/' ).skip(1) { |
203 | if i.is_empty() { |
204 | continue; |
205 | } |
206 | match node.children.get(i) { |
207 | Some(n) => node = n, |
208 | None => return None, |
209 | } |
210 | } |
211 | |
212 | Some(node) |
213 | } |
214 | |
215 | // Get the child Node at path. Optionally create one if it doesn't exist. |
216 | // It also returns the path of parent node that implements ObjectManager (if any). If multiple |
217 | // parents implement it (they shouldn't), then the closest one is returned. |
218 | fn get_child_mut( |
219 | &mut self, |
220 | path: &ObjectPath<'_>, |
221 | create: bool, |
222 | ) -> (Option<&mut Node>, Option<ObjectPath<'_>>) { |
223 | let mut node = self; |
224 | let mut node_path = String::new(); |
225 | let mut obj_manager_path = None; |
226 | |
227 | for i in path.split('/' ).skip(1) { |
228 | if i.is_empty() { |
229 | continue; |
230 | } |
231 | |
232 | if node.interfaces.contains_key(&ObjectManager::name()) { |
233 | obj_manager_path = Some((*node.path).clone()); |
234 | } |
235 | |
236 | write!(&mut node_path, "/ {i}" ).unwrap(); |
237 | match node.children.entry(i.into()) { |
238 | Entry::Vacant(e) => { |
239 | if create { |
240 | let path = node_path.as_str().try_into().expect("Invalid Object Path" ); |
241 | node = e.insert(Node::new(path)); |
242 | } else { |
243 | return (None, obj_manager_path); |
244 | } |
245 | } |
246 | Entry::Occupied(e) => node = e.into_mut(), |
247 | } |
248 | } |
249 | |
250 | (Some(node), obj_manager_path) |
251 | } |
252 | |
253 | pub(crate) fn interface_lock( |
254 | &self, |
255 | interface_name: InterfaceName<'_>, |
256 | ) -> Option<Arc<RwLock<dyn Interface>>> { |
257 | self.interfaces.get(&interface_name).cloned() |
258 | } |
259 | |
260 | fn remove_interface(&mut self, interface_name: InterfaceName<'static>) -> bool { |
261 | self.interfaces.remove(&interface_name).is_some() |
262 | } |
263 | |
264 | fn is_empty(&self) -> bool { |
265 | !self.interfaces.keys().any(|k| { |
266 | *k != Peer::name() |
267 | && *k != Introspectable::name() |
268 | && *k != Properties::name() |
269 | && *k != ObjectManager::name() |
270 | }) |
271 | } |
272 | |
273 | fn remove_node(&mut self, node: &str) -> bool { |
274 | self.children.remove(node).is_some() |
275 | } |
276 | |
277 | // Takes a closure so caller can avoid having to create an Arc & RwLock in case interface was |
278 | // already added. |
279 | fn at<F>(&mut self, name: InterfaceName<'static>, iface_creator: F) -> bool |
280 | where |
281 | F: FnOnce() -> Arc<RwLock<dyn Interface>>, |
282 | { |
283 | match self.interfaces.entry(name) { |
284 | Entry::Vacant(e) => e.insert(iface_creator()), |
285 | Entry::Occupied(_) => return false, |
286 | }; |
287 | |
288 | true |
289 | } |
290 | |
291 | #[async_recursion::async_recursion ] |
292 | async fn introspect_to_writer<W: Write + Send>(&self, writer: &mut W, level: usize) { |
293 | if level == 0 { |
294 | writeln!( |
295 | writer, |
296 | r#" |
297 | <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" |
298 | "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> |
299 | <node>"# |
300 | ) |
301 | .unwrap(); |
302 | } |
303 | |
304 | for iface in self.interfaces.values() { |
305 | iface.read().await.introspect_to_writer(writer, level + 2); |
306 | } |
307 | |
308 | for (path, node) in &self.children { |
309 | let level = level + 2; |
310 | writeln!( |
311 | writer, |
312 | "{:indent$}<node name= \"{} \">" , |
313 | "" , |
314 | path, |
315 | indent = level |
316 | ) |
317 | .unwrap(); |
318 | node.introspect_to_writer(writer, level).await; |
319 | writeln!(writer, "{:indent$}</node>" , "" , indent = level).unwrap(); |
320 | } |
321 | |
322 | if level == 0 { |
323 | writeln!(writer, "</node>" ).unwrap(); |
324 | } |
325 | } |
326 | |
327 | pub(crate) async fn introspect(&self) -> String { |
328 | let mut xml = String::with_capacity(1024); |
329 | |
330 | self.introspect_to_writer(&mut xml, 0).await; |
331 | |
332 | xml |
333 | } |
334 | |
335 | #[async_recursion::async_recursion ] |
336 | pub(crate) async fn get_managed_objects(&self) -> ManagedObjects { |
337 | // Recursively get all properties of all interfaces of descendants. |
338 | let mut managed_objects = ManagedObjects::new(); |
339 | for node in self.children.values() { |
340 | let mut interfaces = HashMap::new(); |
341 | for iface_name in node.interfaces.keys().filter(|n| { |
342 | // Filter standard interfaces. |
343 | *n != &Peer::name() |
344 | && *n != &Introspectable::name() |
345 | && *n != &Properties::name() |
346 | && *n != &ObjectManager::name() |
347 | }) { |
348 | let props = node.get_properties(iface_name.clone()).await; |
349 | interfaces.insert(iface_name.clone().into(), props); |
350 | } |
351 | managed_objects.insert(node.path.clone(), interfaces); |
352 | managed_objects.extend(node.get_managed_objects().await); |
353 | } |
354 | |
355 | managed_objects |
356 | } |
357 | |
358 | async fn get_properties( |
359 | &self, |
360 | interface_name: InterfaceName<'_>, |
361 | ) -> HashMap<String, OwnedValue> { |
362 | self.interface_lock(interface_name) |
363 | .expect("Interface was added but not found" ) |
364 | .read() |
365 | .await |
366 | .get_all() |
367 | .await |
368 | } |
369 | } |
370 | |
371 | /// An object server, holding server-side D-Bus objects & interfaces. |
372 | /// |
373 | /// Object servers hold interfaces on various object paths, and expose them over D-Bus. |
374 | /// |
375 | /// All object paths will have the standard interfaces implemented on your behalf, such as |
376 | /// `org.freedesktop.DBus.Introspectable` or `org.freedesktop.DBus.Properties`. |
377 | /// |
378 | /// # Example |
379 | /// |
380 | /// This example exposes the `org.myiface.Example.Quit` method on the `/org/zbus/path` |
381 | /// path. |
382 | /// |
383 | /// ```no_run |
384 | /// # use std::error::Error; |
385 | /// use zbus::{Connection, dbus_interface}; |
386 | /// use event_listener::Event; |
387 | /// # use async_io::block_on; |
388 | /// |
389 | /// struct Example { |
390 | /// // Interfaces are owned by the ObjectServer. They can have |
391 | /// // `&mut self` methods. |
392 | /// quit_event: Event, |
393 | /// } |
394 | /// |
395 | /// impl Example { |
396 | /// fn new(quit_event: Event) -> Self { |
397 | /// Self { quit_event } |
398 | /// } |
399 | /// } |
400 | /// |
401 | /// #[dbus_interface(name = "org.myiface.Example" )] |
402 | /// impl Example { |
403 | /// // This will be the "Quit" D-Bus method. |
404 | /// async fn quit(&mut self) { |
405 | /// self.quit_event.notify(1); |
406 | /// } |
407 | /// |
408 | /// // See `dbus_interface` documentation to learn |
409 | /// // how to expose properties & signals as well. |
410 | /// } |
411 | /// |
412 | /// # block_on(async { |
413 | /// let connection = Connection::session().await?; |
414 | /// |
415 | /// let quit_event = Event::new(); |
416 | /// let quit_listener = quit_event.listen(); |
417 | /// let interface = Example::new(quit_event); |
418 | /// connection |
419 | /// .object_server() |
420 | /// .at("/org/zbus/path" , interface) |
421 | /// .await?; |
422 | /// |
423 | /// quit_listener.await; |
424 | /// # Ok::<_, Box<dyn Error + Send + Sync>>(()) |
425 | /// # })?; |
426 | /// # Ok::<_, Box<dyn Error + Send + Sync>>(()) |
427 | /// ``` |
428 | #[derive (Debug)] |
429 | pub struct ObjectServer { |
430 | conn: WeakConnection, |
431 | root: RwLock<Node>, |
432 | } |
433 | |
434 | assert_impl_all!(ObjectServer: Send, Sync, Unpin); |
435 | |
436 | impl ObjectServer { |
437 | /// Creates a new D-Bus `ObjectServer`. |
438 | pub(crate) fn new(conn: &Connection) -> Self { |
439 | Self { |
440 | conn: conn.into(), |
441 | root: RwLock::new(Node::new("/" .try_into().expect("zvariant bug" ))), |
442 | } |
443 | } |
444 | |
445 | pub(crate) fn root(&self) -> &RwLock<Node> { |
446 | &self.root |
447 | } |
448 | |
449 | /// Register a D-Bus [`Interface`] at a given path. (see the example above) |
450 | /// |
451 | /// Typically you'd want your interfaces to be registered immediately after the associated |
452 | /// connection is established and therefore use [`zbus::ConnectionBuilder::serve_at`] instead. |
453 | /// However, there are situations where you'd need to register interfaces dynamically and that's |
454 | /// where this method becomes useful. |
455 | /// |
456 | /// If the interface already exists at this path, returns false. |
457 | pub async fn at<'p, P, I>(&self, path: P, iface: I) -> Result<bool> |
458 | where |
459 | I: Interface, |
460 | P: TryInto<ObjectPath<'p>>, |
461 | P::Error: Into<Error>, |
462 | { |
463 | self.at_ready(path, I::name(), move || Arc::new(RwLock::new(iface))) |
464 | .await |
465 | } |
466 | |
467 | /// Same as `at` but expects an interface already in `Arc<RwLock<dyn Interface>>` form. |
468 | // FIXME: Better name? |
469 | pub(crate) async fn at_ready<'node, 'p, P, F>( |
470 | &'node self, |
471 | path: P, |
472 | name: InterfaceName<'static>, |
473 | iface_creator: F, |
474 | ) -> Result<bool> |
475 | where |
476 | // Needs to be hardcoded as 'static instead of 'p like most other |
477 | // functions, due to https://github.com/rust-lang/rust/issues/63033 |
478 | // (It doesn't matter a whole lot since this is an internal-only API |
479 | // anyway.) |
480 | P: TryInto<ObjectPath<'p>>, |
481 | P::Error: Into<Error>, |
482 | F: FnOnce() -> Arc<RwLock<dyn Interface + 'static>>, |
483 | { |
484 | let path = path.try_into().map_err(Into::into)?; |
485 | let mut root = self.root().write().await; |
486 | let (node, manager_path) = root.get_child_mut(&path, true); |
487 | let node = node.unwrap(); |
488 | let added = node.at(name.clone(), iface_creator); |
489 | if added { |
490 | if name == ObjectManager::name() { |
491 | // Just added an object manager. Need to signal all managed objects under it. |
492 | let ctxt = SignalContext::new(&self.connection(), path)?; |
493 | let objects = node.get_managed_objects().await; |
494 | for (path, owned_interfaces) in objects { |
495 | let interfaces = owned_interfaces |
496 | .iter() |
497 | .map(|(i, props)| { |
498 | let props = props |
499 | .iter() |
500 | .map(|(k, v)| (k.as_str(), Value::from(v))) |
501 | .collect(); |
502 | (i.into(), props) |
503 | }) |
504 | .collect(); |
505 | ObjectManager::interfaces_added(&ctxt, &path, &interfaces).await?; |
506 | } |
507 | } else if let Some(manager_path) = manager_path { |
508 | let ctxt = SignalContext::new(&self.connection(), manager_path.clone())?; |
509 | let mut interfaces = HashMap::new(); |
510 | let owned_props = node.get_properties(name.clone()).await; |
511 | let props = owned_props |
512 | .iter() |
513 | .map(|(k, v)| (k.as_str(), Value::from(v))) |
514 | .collect(); |
515 | interfaces.insert(name, props); |
516 | |
517 | ObjectManager::interfaces_added(&ctxt, &path, &interfaces).await?; |
518 | } |
519 | } |
520 | |
521 | Ok(added) |
522 | } |
523 | |
524 | /// Unregister a D-Bus [`Interface`] at a given path. |
525 | /// |
526 | /// If there are no more interfaces left at that path, destroys the object as well. |
527 | /// Returns whether the object was destroyed. |
528 | pub async fn remove<'p, I, P>(&self, path: P) -> Result<bool> |
529 | where |
530 | I: Interface, |
531 | P: TryInto<ObjectPath<'p>>, |
532 | P::Error: Into<Error>, |
533 | { |
534 | let path = path.try_into().map_err(Into::into)?; |
535 | let mut root = self.root.write().await; |
536 | let (node, manager_path) = root.get_child_mut(&path, false); |
537 | let node = node.ok_or(Error::InterfaceNotFound)?; |
538 | if !node.remove_interface(I::name()) { |
539 | return Err(Error::InterfaceNotFound); |
540 | } |
541 | if let Some(manager_path) = manager_path { |
542 | let ctxt = SignalContext::new(&self.connection(), manager_path.clone())?; |
543 | ObjectManager::interfaces_removed(&ctxt, &path, &[I::name()]).await?; |
544 | } |
545 | if node.is_empty() { |
546 | let mut path_parts = path.rsplit('/' ).filter(|i| !i.is_empty()); |
547 | let last_part = path_parts.next().unwrap(); |
548 | let ppath = ObjectPath::from_string_unchecked( |
549 | path_parts.fold(String::new(), |a, p| format!("/ {p}{a}" )), |
550 | ); |
551 | root.get_child_mut(&ppath, false) |
552 | .0 |
553 | .unwrap() |
554 | .remove_node(last_part); |
555 | return Ok(true); |
556 | } |
557 | Ok(false) |
558 | } |
559 | |
560 | /// Get the interface at the given path. |
561 | /// |
562 | /// # Errors |
563 | /// |
564 | /// If the interface is not registered at the given path, `Error::InterfaceNotFound` error is |
565 | /// returned. |
566 | /// |
567 | /// # Examples |
568 | /// |
569 | /// The typical use of this is property changes outside of a dispatched handler: |
570 | /// |
571 | /// ```no_run |
572 | /// # use std::error::Error; |
573 | /// # use zbus::{Connection, dbus_interface}; |
574 | /// # use async_io::block_on; |
575 | /// # |
576 | /// struct MyIface(u32); |
577 | /// |
578 | /// #[dbus_interface(name = "org.myiface.MyIface" )] |
579 | /// impl MyIface { |
580 | /// #[dbus_interface(property)] |
581 | /// async fn count(&self) -> u32 { |
582 | /// self.0 |
583 | /// } |
584 | /// } |
585 | /// |
586 | /// # block_on(async { |
587 | /// # let connection = Connection::session().await?; |
588 | /// # |
589 | /// # let path = "/org/zbus/path" ; |
590 | /// # connection.object_server().at(path, MyIface(0)).await?; |
591 | /// let iface_ref = connection |
592 | /// .object_server() |
593 | /// .interface::<_, MyIface>(path).await?; |
594 | /// let mut iface = iface_ref.get_mut().await; |
595 | /// iface.0 = 42; |
596 | /// iface.count_changed(iface_ref.signal_context()).await?; |
597 | /// # Ok::<_, Box<dyn Error + Send + Sync>>(()) |
598 | /// # })?; |
599 | /// # |
600 | /// # Ok::<_, Box<dyn Error + Send + Sync>>(()) |
601 | /// ``` |
602 | pub async fn interface<'p, P, I>(&self, path: P) -> Result<InterfaceRef<I>> |
603 | where |
604 | I: Interface, |
605 | P: TryInto<ObjectPath<'p>>, |
606 | P::Error: Into<Error>, |
607 | { |
608 | let path = path.try_into().map_err(Into::into)?; |
609 | let root = self.root().read().await; |
610 | let node = root.get_child(&path).ok_or(Error::InterfaceNotFound)?; |
611 | |
612 | let lock = node |
613 | .interface_lock(I::name()) |
614 | .ok_or(Error::InterfaceNotFound)? |
615 | .clone(); |
616 | |
617 | // Ensure what we return can later be dowcasted safely. |
618 | lock.read() |
619 | .await |
620 | .downcast_ref::<I>() |
621 | .ok_or(Error::InterfaceNotFound)?; |
622 | |
623 | let conn = self.connection(); |
624 | // SAFETY: We know that there is a valid path on the node as we already converted w/o error. |
625 | let ctxt = SignalContext::new(&conn, path).unwrap().into_owned(); |
626 | |
627 | Ok(InterfaceRef { |
628 | ctxt, |
629 | lock, |
630 | phantom: PhantomData, |
631 | }) |
632 | } |
633 | |
634 | #[instrument (skip(self, connection))] |
635 | async fn dispatch_method_call_try( |
636 | &self, |
637 | connection: &Connection, |
638 | msg: &Message, |
639 | ) -> fdo::Result<Result<()>> { |
640 | let path = msg |
641 | .path() |
642 | .ok_or_else(|| fdo::Error::Failed("Missing object path" .into()))?; |
643 | let iface_name = msg |
644 | .interface() |
645 | // TODO: In the absence of an INTERFACE field, if two or more interfaces on the same |
646 | // object have a method with the same name, it is undefined which of those |
647 | // methods will be invoked. Implementations may choose to either return an |
648 | // error, or deliver the message as though it had an arbitrary one of those |
649 | // interfaces. |
650 | .ok_or_else(|| fdo::Error::Failed("Missing interface" .into()))?; |
651 | let member = msg |
652 | .member() |
653 | .ok_or_else(|| fdo::Error::Failed("Missing member" .into()))?; |
654 | |
655 | // Ensure the root lock isn't held while dispatching the message. That |
656 | // way, the object server can be mutated during that time. |
657 | let iface = { |
658 | let root = self.root.read().await; |
659 | let node = root |
660 | .get_child(&path) |
661 | .ok_or_else(|| fdo::Error::UnknownObject(format!("Unknown object '{path}'" )))?; |
662 | |
663 | node.interface_lock(iface_name.as_ref()).ok_or_else(|| { |
664 | fdo::Error::UnknownInterface(format!("Unknown interface '{iface_name}'" )) |
665 | })? |
666 | }; |
667 | |
668 | trace!("acquiring read lock on interface `{}`" , iface_name); |
669 | let read_lock = iface.read().await; |
670 | trace!("acquired read lock on interface `{}`" , iface_name); |
671 | match read_lock.call(self, connection, msg, member.as_ref()) { |
672 | DispatchResult::NotFound => { |
673 | return Err(fdo::Error::UnknownMethod(format!( |
674 | "Unknown method '{member}'" |
675 | ))); |
676 | } |
677 | DispatchResult::Async(f) => { |
678 | return Ok(f.await); |
679 | } |
680 | DispatchResult::RequiresMut => {} |
681 | } |
682 | drop(read_lock); |
683 | trace!("acquiring write lock on interface `{}`" , iface_name); |
684 | let mut write_lock = iface.write().await; |
685 | trace!("acquired write lock on interface `{}`" , iface_name); |
686 | match write_lock.call_mut(self, connection, msg, member.as_ref()) { |
687 | DispatchResult::NotFound => {} |
688 | DispatchResult::RequiresMut => {} |
689 | DispatchResult::Async(f) => { |
690 | return Ok(f.await); |
691 | } |
692 | } |
693 | drop(write_lock); |
694 | Err(fdo::Error::UnknownMethod(format!( |
695 | "Unknown method '{member}'" |
696 | ))) |
697 | } |
698 | |
699 | #[instrument (skip(self, connection))] |
700 | async fn dispatch_method_call(&self, connection: &Connection, msg: &Message) -> Result<()> { |
701 | match self.dispatch_method_call_try(connection, msg).await { |
702 | Err(e) => { |
703 | let hdr = msg.header()?; |
704 | debug!("Returning error: {}" , e); |
705 | connection.reply_dbus_error(&hdr, e).await?; |
706 | Ok(()) |
707 | } |
708 | Ok(r) => r, |
709 | } |
710 | } |
711 | |
712 | /// Dispatch an incoming message to a registered interface. |
713 | /// |
714 | /// The object server will handle the message by: |
715 | /// |
716 | /// - looking up the called object path & interface, |
717 | /// |
718 | /// - calling the associated method if one exists, |
719 | /// |
720 | /// - returning a message (responding to the caller with either a return or error message) to |
721 | /// the caller through the associated server connection. |
722 | /// |
723 | /// Returns an error if the message is malformed, true if it's handled, false otherwise. |
724 | #[instrument (skip(self))] |
725 | pub(crate) async fn dispatch_message(&self, msg: &Message) -> Result<bool> { |
726 | let conn = self.connection(); |
727 | self.dispatch_method_call(&conn, msg).await?; |
728 | trace!("Handled: {}" , msg); |
729 | |
730 | Ok(true) |
731 | } |
732 | |
733 | pub(crate) fn connection(&self) -> Connection { |
734 | self.conn |
735 | .upgrade() |
736 | .expect("ObjectServer can't exist w/o an associated Connection" ) |
737 | } |
738 | } |
739 | |
740 | impl From<crate::blocking::ObjectServer> for ObjectServer { |
741 | fn from(server: crate::blocking::ObjectServer) -> Self { |
742 | server.into_inner() |
743 | } |
744 | } |
745 | |
746 | /// A response wrapper that notifies after response has been sent. |
747 | /// |
748 | /// Sometimes in [`dbus_interface`] method implemenations we need to do some other work after the |
749 | /// response has been sent off. This wrapper type allows us to do that. Instead of returning your |
750 | /// intended response type directly, wrap it in this type and return it from your method. The |
751 | /// returned `EventListener` from `new` method will be notified when the response has been sent. |
752 | /// |
753 | /// A typical use case is sending off signals after the response has been sent. The easiest way to |
754 | /// do that is to spawn a task from the method that sends the signal but only after being notified |
755 | /// of the response dispatch. |
756 | /// |
757 | /// # Caveats |
758 | /// |
759 | /// The notification indicates that the response has been sent off, not that destination peer has |
760 | /// received it. That can only be guaranteed for a peer-to-peer connection. |
761 | /// |
762 | /// [`dbus_interface`]: crate::dbus_interface |
763 | #[derive (Debug)] |
764 | pub struct ResponseDispatchNotifier<R> { |
765 | response: R, |
766 | event: Option<Event>, |
767 | } |
768 | |
769 | impl<R> ResponseDispatchNotifier<R> { |
770 | /// Create a new `NotifyResponse`. |
771 | pub fn new(response: R) -> (Self, EventListener) { |
772 | let event: Event = Event::new(); |
773 | let listener: EventListener = event.listen(); |
774 | ( |
775 | Self { |
776 | response, |
777 | event: Some(event), |
778 | }, |
779 | listener, |
780 | ) |
781 | } |
782 | } |
783 | |
784 | impl<R> Serialize for ResponseDispatchNotifier<R> |
785 | where |
786 | R: Serialize, |
787 | { |
788 | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> |
789 | where |
790 | S: serde::Serializer, |
791 | { |
792 | self.response.serialize(serializer) |
793 | } |
794 | } |
795 | |
796 | impl<R> Type for ResponseDispatchNotifier<R> |
797 | where |
798 | R: Type, |
799 | { |
800 | fn signature() -> Signature<'static> { |
801 | R::signature() |
802 | } |
803 | } |
804 | |
805 | impl<T> Drop for ResponseDispatchNotifier<T> { |
806 | fn drop(&mut self) { |
807 | if let Some(event: Event) = self.event.take() { |
808 | event.notify(usize::MAX); |
809 | } |
810 | } |
811 | } |
812 | |