1use std::{collections::HashMap, marker::PhantomData, sync::Arc};
4use tracing::{Instrument, debug, instrument, trace, trace_span};
5
6use zbus_names::InterfaceName;
7use zvariant::{ObjectPath, Value};
8
9use crate::{
10 Connection, Error, Result,
11 async_lock::RwLock,
12 connection::WeakConnection,
13 fdo,
14 fdo::ObjectManager,
15 message::{Header, Message},
16};
17
18mod interface;
19pub(crate) use interface::ArcInterface;
20#[allow(deprecated)]
21pub use interface::DispatchResult;
22pub use interface::{DispatchResult2, Interface, InterfaceDeref, InterfaceDerefMut, InterfaceRef};
23
24mod signal_emitter;
25pub use signal_emitter::SignalEmitter;
26#[deprecated(since = "5.0.0", note = "Please use `SignalEmitter` instead.")]
27pub type SignalContext<'s> = SignalEmitter<'s>;
28
29mod dispatch_notifier;
30pub use dispatch_notifier::ResponseDispatchNotifier;
31
32mod node;
33pub(crate) use node::Node;
34
35#[derive(Debug, Clone)]
93pub struct ObjectServer {
94 conn: WeakConnection,
95 root: Arc<RwLock<Node>>,
96}
97
98impl ObjectServer {
99 pub(crate) fn new(conn: &Connection) -> Self {
101 Self {
102 conn: conn.into(),
103 root: Arc::new(RwLock::new(Node::new(
104 "/".try_into().expect("zvariant bug"),
105 ))),
106 }
107 }
108
109 pub(crate) fn root(&self) -> &RwLock<Node> {
110 &self.root
111 }
112
113 pub async fn at<'p, P, I>(&self, path: P, iface: I) -> Result<bool>
122 where
123 I: Interface,
124 P: TryInto<ObjectPath<'p>>,
125 P::Error: Into<Error>,
126 {
127 self.add_arc_interface(path, I::name(), ArcInterface::new(iface))
128 .await
129 }
130
131 pub(crate) async fn add_arc_interface<'p, P>(
132 &self,
133 path: P,
134 name: InterfaceName<'static>,
135 arc_iface: ArcInterface,
136 ) -> Result<bool>
137 where
138 P: TryInto<ObjectPath<'p>>,
139 P::Error: Into<Error>,
140 {
141 let path = path.try_into().map_err(Into::into)?;
142 let mut root = self.root().write().await;
143 let (node, manager_path) = root.get_child_mut(&path, true);
144 let node = node.unwrap();
145 let added = node.add_arc_interface(name.clone(), arc_iface);
146 if added {
147 if name == ObjectManager::name() {
148 let emitter = SignalEmitter::new(&self.connection(), path)?;
150 let objects = node.get_managed_objects(self, &self.connection()).await?;
151 for (path, owned_interfaces) in objects {
152 let interfaces = owned_interfaces
153 .iter()
154 .map(|(i, props)| {
155 let props = props
156 .iter()
157 .map(|(k, v)| Ok((k.as_str(), Value::try_from(v)?)))
158 .collect::<Result<_>>();
159 Ok((i.into(), props?))
160 })
161 .collect::<Result<_>>()?;
162 ObjectManager::interfaces_added(&emitter, path.into(), interfaces).await?;
163 }
164 } else if let Some(manager_path) = manager_path {
165 let emitter = SignalEmitter::new(&self.connection(), manager_path.clone())?;
166 let mut interfaces = HashMap::new();
167 let owned_props = node
168 .get_properties(self, &self.connection(), name.clone())
169 .await?;
170 let props = owned_props
171 .iter()
172 .map(|(k, v)| Ok((k.as_str(), Value::try_from(v)?)))
173 .collect::<Result<_>>()?;
174 interfaces.insert(name, props);
175
176 ObjectManager::interfaces_added(&emitter, path, interfaces).await?;
177 }
178 }
179
180 Ok(added)
181 }
182
183 pub async fn remove<'p, I, P>(&self, path: P) -> Result<bool>
188 where
189 I: Interface,
190 P: TryInto<ObjectPath<'p>>,
191 P::Error: Into<Error>,
192 {
193 self.remove_named(path, I::name()).await
194 }
195
196 pub async fn remove_named<'p, P>(
201 &self,
202 path: P,
203 interface_name: InterfaceName<'static>,
204 ) -> Result<bool>
205 where
206 P: TryInto<ObjectPath<'p>>,
207 P::Error: Into<Error>,
208 {
209 let path = path.try_into().map_err(Into::into)?;
210 let mut root = self.root.write().await;
211 let (node, manager_path) = root.get_child_mut(&path, false);
212 let node = node.ok_or(Error::InterfaceNotFound)?;
213 if !node.remove_interface(&interface_name) {
214 return Err(Error::InterfaceNotFound);
215 }
216 if let Some(manager_path) = manager_path {
217 let ctxt = SignalEmitter::new(&self.connection(), manager_path.clone())?;
218 ObjectManager::interfaces_removed(&ctxt, path.clone(), (&[interface_name]).into())
219 .await?;
220 }
221 if node.is_empty() {
222 let mut path_parts = path.rsplit('/').filter(|i| !i.is_empty());
223 let last_part = path_parts.next().unwrap();
224 let ppath = ObjectPath::from_string_unchecked(
225 path_parts.fold(String::new(), |a, p| format!("/{p}{a}")),
226 );
227 root.get_child_mut(&ppath, false)
228 .0
229 .unwrap()
230 .remove_node(last_part);
231 return Ok(true);
232 }
233 Ok(false)
234 }
235
236 pub async fn interface<'p, P, I>(&self, path: P) -> Result<InterfaceRef<I>>
279 where
280 I: Interface,
281 P: TryInto<ObjectPath<'p>>,
282 P::Error: Into<Error>,
283 {
284 let path = path.try_into().map_err(Into::into)?;
285 let root = self.root().read().await;
286 let node = root.get_child(&path).ok_or(Error::InterfaceNotFound)?;
287
288 let lock = node
289 .interface_lock(I::name())
290 .ok_or(Error::InterfaceNotFound)?
291 .instance
292 .clone();
293
294 lock.read()
296 .await
297 .downcast_ref::<I>()
298 .ok_or(Error::InterfaceNotFound)?;
299
300 let conn = self.connection();
301 let emitter = SignalEmitter::new(&conn, path).unwrap().into_owned();
303
304 Ok(InterfaceRef {
305 emitter,
306 lock,
307 phantom: PhantomData,
308 })
309 }
310
311 async fn dispatch_call_to_iface(
312 &self,
313 iface: Arc<RwLock<dyn Interface>>,
314 connection: &Connection,
315 msg: &Message,
316 hdr: &Header<'_>,
317 ) -> fdo::Result<()> {
318 let member = hdr
319 .member()
320 .ok_or_else(|| fdo::Error::Failed("Missing member".into()))?;
321 let iface_name = hdr
322 .interface()
323 .ok_or_else(|| fdo::Error::Failed("Missing interface".into()))?;
324
325 trace!("acquiring read lock on interface `{}`", iface_name);
326 let read_lock = iface.read().await;
327 trace!("acquired read lock on interface `{}`", iface_name);
328 match read_lock.call(self, connection, msg, member.as_ref()) {
329 DispatchResult2::NotFound => {
330 return Err(fdo::Error::UnknownMethod(format!(
331 "Unknown method '{member}'"
332 )));
333 }
334 DispatchResult2::Async(f) => {
335 return f.await;
336 }
337 DispatchResult2::RequiresMut => {}
338 }
339 drop(read_lock);
340 trace!("acquiring write lock on interface `{}`", iface_name);
341 let mut write_lock = iface.write().await;
342 trace!("acquired write lock on interface `{}`", iface_name);
343 match write_lock.call_mut(self, connection, msg, member.as_ref()) {
344 DispatchResult2::NotFound => {}
345 DispatchResult2::RequiresMut => {}
346 DispatchResult2::Async(f) => {
347 return f.await;
348 }
349 }
350 drop(write_lock);
351 Err(fdo::Error::UnknownMethod(format!(
352 "Unknown method '{member}'"
353 )))
354 }
355
356 async fn dispatch_method_call_try(
357 &self,
358 connection: &Connection,
359 msg: &Message,
360 hdr: &Header<'_>,
361 ) -> fdo::Result<()> {
362 let path = hdr
363 .path()
364 .ok_or_else(|| fdo::Error::Failed("Missing object path".into()))?;
365 let iface_name = hdr
366 .interface()
367 .ok_or_else(|| fdo::Error::Failed("Missing interface".into()))?;
373 let _ = hdr
378 .member()
379 .ok_or_else(|| fdo::Error::Failed("Missing member".into()))?;
380
381 let (iface, with_spawn) = {
384 let root = self.root.read().await;
385
386 let path = if *iface_name == fdo::Peer::name() {
390 ObjectPath::from_static_str_unchecked("/")
391 } else {
392 path.clone()
393 };
394
395 let node = root
396 .get_child(&path)
397 .ok_or_else(|| fdo::Error::UnknownObject(format!("Unknown object '{path}'")))?;
398
399 let iface = node.interface_lock(iface_name.as_ref()).ok_or_else(|| {
400 fdo::Error::UnknownInterface(format!("Unknown interface '{iface_name}'"))
401 })?;
402 (iface.instance, iface.spawn_tasks_for_methods)
403 };
404
405 if with_spawn {
406 let executor = connection.executor().clone();
407 let task_name = format!("`{msg}` method dispatcher");
408 let connection = connection.clone();
409 let msg = msg.clone();
410 executor
411 .spawn(
412 async move {
413 let server = connection.object_server();
414 let hdr = msg.header();
415 if let Err(e) = server
416 .dispatch_call_to_iface(iface, &connection, &msg, &hdr)
417 .await
418 {
419 debug!("Returning error: {}", e);
421 if let Err(e) = connection.reply_dbus_error(&hdr, e).await {
422 debug!(
423 "Error dispatching message. Message: {:?}, error: {:?}",
424 msg, e
425 );
426 }
427 }
428 }
429 .instrument(trace_span!("{}", task_name)),
430 &task_name,
431 )
432 .detach();
433 Ok(())
434 } else {
435 self.dispatch_call_to_iface(iface, connection, msg, hdr)
436 .await
437 }
438 }
439
440 #[instrument(skip(self))]
453 pub(crate) async fn dispatch_call(&self, msg: &Message, hdr: &Header<'_>) -> Result<()> {
454 let conn = self.connection();
455
456 if let Err(e) = self.dispatch_method_call_try(&conn, msg, hdr).await {
457 debug!("Returning error: {}", e);
458 conn.reply_dbus_error(hdr, e).await?;
459 }
460 trace!("Handled: {}", msg);
461
462 Ok(())
463 }
464
465 pub(crate) fn connection(&self) -> Connection {
466 self.conn
467 .upgrade()
468 .expect("ObjectServer can't exist w/o an associated Connection")
469 }
470}
471
472#[cfg(feature = "blocking-api")]
473impl From<crate::blocking::ObjectServer> for ObjectServer {
474 fn from(server: crate::blocking::ObjectServer) -> Self {
475 server.into_inner()
476 }
477}