Skip to main content

tokio_dbus_runtime/
connection.rs

1use std::collections::VecDeque;
2use std::fmt;
3use std::future::Future;
4use std::pin::{Pin, pin};
5use std::task::{Context, Poll};
6use std::time::Duration;
7
8use tokio::time::{Instant, Sleep};
9
10use tokio_dbus::org_freedesktop_dbus::{self, NameFlag, NameReply};
11use tokio_dbus::{
12    Alignment, Body, BodyBuf, Buffers, MessageBuf, MessageKind, ObjectPath, RawArray, Serial,
13    Signature,
14};
15
16use crate::error::ErrorKind;
17use crate::{Decode, Encode, Error, Result};
18
19/// The body of a message being built.
20///
21/// The signature of the arguments is declared up front, since generated code
22/// knows it at build time, after which each argument is written in order.
23///
24/// # Examples
25///
26/// ```
27/// use tokio_dbus::Signature;
28/// use tokio_dbus_runtime::Arguments;
29///
30/// let mut arguments = Arguments::new(Signature::new("su")?)?;
31/// arguments.store("Hello World!");
32/// arguments.store(&42u32);
33/// # Ok::<_, tokio_dbus_runtime::Error>(())
34/// ```
35#[derive(Default)]
36pub struct Arguments {
37    buf: BodyBuf,
38}
39
40impl Arguments {
41    /// Construct an argument list matching the given signature.
42    pub fn new(signature: &Signature) -> Result<Self> {
43        let mut buf = BodyBuf::new();
44        buf.extend_signature(signature)?;
45        Ok(Self { buf })
46    }
47
48    /// Construct an argument list matching a signature which is known at
49    /// compile time.
50    ///
51    /// This is the infallible form of [`new()`], for the common case where the
52    /// signature comes out of [`Signature::new_const`] and has therefore
53    /// already been validated at compile time.
54    ///
55    /// [`new()`]: Self::new
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use tokio_dbus::Signature;
61    /// use tokio_dbus_runtime::Arguments;
62    ///
63    /// const SIGNATURE: &Signature = Signature::new_const(b"su");
64    ///
65    /// let mut arguments = Arguments::new_const(SIGNATURE);
66    /// arguments.store("Hello World!");
67    /// arguments.store(&42u32);
68    /// ```
69    pub fn new_const(signature: &'static Signature) -> Self {
70        let mut buf = BodyBuf::new();
71
72        // NB: Extending an empty buffer with an already validated signature
73        // cannot fail, since the only failure is the combined signature growing
74        // too long.
75        buf.extend_signature(signature)
76            .expect("A validated signature cannot fail to extend an empty body");
77
78        Self { buf }
79    }
80
81    /// Construct an empty argument list.
82    pub fn empty() -> Self {
83        Self::default()
84    }
85
86    /// Write the next argument.
87    pub fn store<T>(&mut self, value: T) -> &mut Self
88    where
89        T: Encode,
90    {
91        value.encode(&mut self.buf.raw());
92        self
93    }
94
95    /// Write the next argument as a variant containing a value of the given
96    /// type.
97    ///
98    /// The signature is the one of the value inside the variant, not the `v` of
99    /// the variant itself.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use tokio_dbus::Signature;
105    /// use tokio_dbus_runtime::Arguments;
106    ///
107    /// let mut arguments = Arguments::new(Signature::VARIANT)?;
108    /// arguments.store_variant(Signature::UINT32, 42u32);
109    /// # Ok::<_, tokio_dbus_runtime::Error>(())
110    /// ```
111    pub fn store_variant<T>(&mut self, signature: &Signature, value: T) -> &mut Self
112    where
113        T: Encode,
114    {
115        let mut raw = self.buf.raw();
116        raw.store_signature(signature);
117        value.encode(&mut raw);
118        self
119    }
120
121    /// Write the next argument as an `a{sv}`, which is how a set of properties
122    /// of differing types is carried.
123    ///
124    /// # Examples
125    ///
126    /// ```
127    /// use tokio_dbus::Signature;
128    /// use tokio_dbus_runtime::Arguments;
129    ///
130    /// let mut arguments = Arguments::new(Signature::new("a{sv}")?)?;
131    ///
132    /// let mut dict = arguments.store_variant_dict();
133    /// dict.entry("Version", Signature::UINT32, 3u32);
134    /// dict.entry("Status", Signature::STRING, "normal");
135    /// dict.finish();
136    /// # Ok::<_, tokio_dbus_runtime::Error>(())
137    /// ```
138    pub fn store_variant_dict(&mut self) -> VariantDict<'_> {
139        VariantDict {
140            // NB: Dict entries are aligned just like structs.
141            array: self.buf.raw().into_array(Alignment::U64),
142        }
143    }
144
145    fn body(&self) -> Body<'_> {
146        self.buf.as_body()
147    }
148
149    #[cfg(test)]
150    pub(crate) fn body_for_test(&self) -> Body<'_> {
151        self.body()
152    }
153}
154
155/// A writer for an `a{sv}`, where every value is a variant of its own type.
156///
157/// See [`Arguments::store_variant_dict`].
158pub struct VariantDict<'a> {
159    array: RawArray<'a>,
160}
161
162impl VariantDict<'_> {
163    /// Write an entry, whose value is a variant containing a value of the given
164    /// type.
165    pub fn entry<T>(&mut self, name: &str, signature: &Signature, value: T) -> &mut Self
166    where
167        T: Encode,
168    {
169        let mut entry = self.array.as_raw();
170        entry.align(Alignment::U64);
171        name.encode(&mut entry);
172        entry.store_signature(signature);
173        value.encode(&mut entry);
174        self
175    }
176
177    /// Finish writing the dictionary.
178    ///
179    /// This also happens implicitly when the writer is dropped.
180    pub fn finish(self) {}
181}
182
183/// Read a variant which is expected to contain a value of type `T`.
184///
185/// # Examples
186///
187/// ```
188/// use tokio_dbus::{BodyBuf, Signature};
189/// use tokio_dbus_runtime::decode_variant;
190///
191/// let mut buf = BodyBuf::new();
192/// buf.store_variant(Signature::UINT32)?.store(42u32);
193///
194/// let mut body = buf.as_body();
195/// assert_eq!(decode_variant::<u32>(&mut body, Signature::UINT32)?, 42);
196/// # Ok::<_, tokio_dbus_runtime::Error>(())
197/// ```
198pub fn decode_variant<T>(body: &mut Body<'_>, expected: &Signature) -> Result<T>
199where
200    T: Decode,
201{
202    let signature = body.read::<Signature>()?;
203
204    if signature != expected {
205        return Err(Error::new(ErrorKind::UnexpectedSignature(Box::new((
206            expected.to_owned(),
207            signature.to_owned(),
208        )))));
209    }
210
211    T::decode(body)
212}
213
214impl fmt::Debug for Arguments {
215    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216        f.debug_struct("Arguments")
217            .field("signature", &self.buf.signature())
218            .finish()
219    }
220}
221
222/// A connection to a bus which speaks in owned Rust values.
223///
224/// This is the driver used by generated clients and servers. It wraps a
225/// [`tokio_dbus::Connection`] and takes care of matching replies to calls,
226/// buffering the messages which arrive while a call is outstanding so that they
227/// can be dispatched later.
228///
229/// Incoming messages are copied out of the receive buffer so that the connection
230/// stays usable while one is being handled. Use the low level API directly if
231/// that copy matters.
232pub struct Connection {
233    connection: tokio_dbus::Connection,
234    buffers: Buffers,
235    /// Messages which arrived while waiting for the reply to a call.
236    queue: VecDeque<MessageBuf>,
237    unique_name: String,
238    /// How long to wait for the reply to a call before giving up.
239    timeout: Option<Duration>,
240    /// The timer driving call timeouts, created on the first timed call and
241    /// reused for every one after that. See [`wait_for()`][Self::wait_for].
242    sleep: Option<Pin<Box<Sleep>>>,
243}
244
245impl Connection {
246    /// The default for how long a call waits for its reply, matching the 25
247    /// seconds every other D-Bus implementation defaults to.
248    pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(25);
249
250    /// Connect to the session bus and say `Hello`.
251    pub async fn session_bus() -> Result<Self> {
252        Self::start(tokio_dbus::Connection::session_bus()?).await
253    }
254
255    /// Connect to the system bus and say `Hello`.
256    pub async fn system_bus() -> Result<Self> {
257        Self::start(tokio_dbus::Connection::system_bus()?).await
258    }
259
260    async fn start(connection: tokio_dbus::Connection) -> Result<Self> {
261        let mut this = Self {
262            connection,
263            buffers: Buffers::new(),
264            queue: VecDeque::new(),
265            unique_name: String::new(),
266            timeout: Some(Self::DEFAULT_TIMEOUT),
267            sleep: None,
268        };
269
270        this.connection.connect(&mut this.buffers).await?;
271
272        let serial = this.buffers.hello()?;
273        let reply = this.wait_for(serial).await?;
274
275        let Ok(name) = reply.body().read::<str>() else {
276            return Err(Error::new(ErrorKind::MissingUniqueName));
277        };
278
279        this.unique_name = name.to_owned();
280        Ok(this)
281    }
282
283    /// The unique name the bus assigned to this connection, such as `:1.42`.
284    pub fn unique_name(&self) -> &str {
285        &self.unique_name
286    }
287
288    /// Set how long a call waits for its reply before failing, or `None` to
289    /// wait forever.
290    ///
291    /// The default is [`DEFAULT_TIMEOUT`], since the bus does not time method
292    /// calls out on its own, a peer which is alive but not reading its socket
293    /// would otherwise hang the caller forever. The timeout applies to
294    /// everything which waits for a reply, including [`call()`] and the name
295    /// and match management methods.
296    ///
297    /// A call which times out fails with an error for which
298    /// [`Error::is_timeout()`] is true and whose [`Error::name()`] is
299    /// `org.freedesktop.DBus.Error.NoReply`. The connection itself remains
300    /// usable, a reply which arrives after the deadline is discarded.
301    ///
302    /// The timeout is driven by the Tokio timer, which must be enabled on the
303    /// runtime. `#[tokio::main]` enables it by default.
304    ///
305    /// [`DEFAULT_TIMEOUT`]: Self::DEFAULT_TIMEOUT
306    /// [`call()`]: Self::call
307    pub fn set_default_timeout(&mut self, timeout: Option<Duration>) {
308        self.timeout = timeout;
309    }
310
311    /// How long a call waits for its reply before failing, if limited.
312    ///
313    /// See [`set_default_timeout()`][Self::set_default_timeout].
314    pub fn default_timeout(&self) -> Option<Duration> {
315        self.timeout
316    }
317
318    /// Call a method and wait for its reply.
319    ///
320    /// An error reply is turned into an [`Error`] carrying the name the remote
321    /// end used.
322    ///
323    /// The call fails with a timeout error when no reply arrives within the
324    /// configured deadline, see
325    /// [`set_default_timeout()`][Self::set_default_timeout].
326    ///
327    /// # Cancellation
328    ///
329    /// This method is cancel safe. If the future is dropped before it
330    /// completes, the call itself may still reach the peer, but the connection
331    /// remains usable and a reply which arrives later is discarded rather than
332    /// surfaced or confused with the reply to another call.
333    pub async fn call(
334        &mut self,
335        destination: &str,
336        path: &ObjectPath,
337        interface: &str,
338        member: &str,
339        arguments: &Arguments,
340    ) -> Result<Reply> {
341        let m = self
342            .buffers
343            .send
344            .method_call(path, member)
345            .with_destination(destination)
346            .with_interface(interface)
347            .with_body(arguments.body());
348
349        let serial = m.serial();
350        self.buffers.send.write_message(m)?;
351        let message = self.wait_for(serial).await?;
352        Ok(Reply { message })
353    }
354
355    /// Emit a signal.
356    ///
357    /// Signals are buffered and written out the next time the connection makes
358    /// progress. Call [`flush()`] to force them out.
359    ///
360    /// [`flush()`]: Self::flush
361    pub fn emit(
362        &mut self,
363        path: &ObjectPath,
364        interface: &str,
365        member: &str,
366        arguments: &Arguments,
367    ) -> Result<()> {
368        let m = self
369            .buffers
370            .send
371            .signal(path, member)
372            .with_interface(interface)
373            .with_body(arguments.body());
374
375        self.buffers.send.write_message(m)?;
376        Ok(())
377    }
378
379    /// Reply to a method call.
380    pub fn reply(&mut self, call: &Call, arguments: &Arguments) -> Result<()> {
381        let m = call
382            .message
383            .borrow()
384            .method_return(self.buffers.send.next_serial())
385            .with_body(arguments.body());
386
387        self.buffers.send.write_message(m)?;
388        Ok(())
389    }
390
391    /// Reply to a method call with an error.
392    pub fn reply_error(&mut self, call: &Call, error: &Error) -> Result<()> {
393        let name = error
394            .name()
395            .unwrap_or(org_freedesktop_dbus::FAILED_ERROR)
396            .to_owned();
397
398        let mut arguments = Arguments::new_const(Signature::STRING);
399        arguments.store(error.to_string().as_str());
400
401        let m = call
402            .message
403            .borrow()
404            .error(&name, self.buffers.send.next_serial())
405            .with_body(arguments.body());
406
407        self.buffers.send.write_message(m)?;
408        Ok(())
409    }
410
411    /// Request ownership of a well known name.
412    pub async fn request_name(&mut self, name: &str, flags: NameFlag) -> Result<NameReply> {
413        let serial = self.buffers.request_name(name, flags)?;
414        let reply = self.wait_for(serial).await?;
415        Ok(reply.body().load::<NameReply>()?)
416    }
417
418    /// Request ownership of a well known name, erroring unless it was acquired.
419    pub async fn acquire_name(&mut self, name: &str, flags: NameFlag) -> Result<()> {
420        match self.request_name(name, flags).await? {
421            NameReply::PRIMARY_OWNER | NameReply::ALREADY_OWNER => Ok(()),
422            _ => Err(Error::new(ErrorKind::NameTaken(name.into()))),
423        }
424    }
425
426    /// Release a well known name previously acquired.
427    pub async fn release_name(&mut self, name: &str) -> Result<()> {
428        let serial = self.buffers.release_name(name)?;
429        self.wait_for(serial).await?;
430        Ok(())
431    }
432
433    /// Add a match rule, so that the bus routes matching signals here.
434    pub async fn add_match(&mut self, rule: &str) -> Result<()> {
435        let serial = self.buffers.add_match(rule)?;
436        self.wait_for(serial).await?;
437        Ok(())
438    }
439
440    /// Remove a match rule.
441    pub async fn remove_match(&mut self, rule: &str) -> Result<()> {
442        let serial = self.buffers.remove_match(rule)?;
443        self.wait_for(serial).await?;
444        Ok(())
445    }
446
447    /// Ask the bus to route [`NameOwnerChanged`] signals for `name` here.
448    ///
449    /// Watching a name is how a client survives its peer restarting: the
450    /// signal announces both the name going away and it being claimed again.
451    /// Decode the incoming signal with [`NameOwnerChanged::decode`], and pair
452    /// this with [`name_owner()`] to learn the initial state, since the signal
453    /// only reports changes.
454    ///
455    /// [`NameOwnerChanged`]: crate::NameOwnerChanged
456    /// [`NameOwnerChanged::decode`]: crate::NameOwnerChanged::decode
457    /// [`name_owner()`]: Self::name_owner
458    pub async fn watch_name(&mut self, name: &str) -> Result<()> {
459        self.add_match(&crate::NameOwnerChanged::rule(name)).await
460    }
461
462    /// Remove the interest registered by [`watch_name()`][Self::watch_name].
463    pub async fn unwatch_name(&mut self, name: &str) -> Result<()> {
464        self.remove_match(&crate::NameOwnerChanged::rule(name))
465            .await
466    }
467
468    /// The unique name currently owning `name`, or `None` when the name has no
469    /// owner.
470    pub async fn name_owner(&mut self, name: &str) -> Result<Option<String>> {
471        let mut arguments = Arguments::new_const(Signature::STRING);
472        arguments.store(name);
473
474        let result = self
475            .call(
476                org_freedesktop_dbus::DESTINATION,
477                org_freedesktop_dbus::PATH,
478                org_freedesktop_dbus::INTERFACE,
479                "GetNameOwner",
480                &arguments,
481            )
482            .await;
483
484        match result {
485            Ok(reply) => Ok(Some(reply.read::<String>()?)),
486            Err(error) if error.name() == Some(org_freedesktop_dbus::NAME_HAS_NO_OWNER_ERROR) => {
487                Ok(None)
488            }
489            Err(error) => Err(error),
490        }
491    }
492
493    /// Reply to a method call which no dispatcher recognised.
494    ///
495    /// The generated `dispatch` functions return `false` for a call which is
496    /// not theirs, so that several interfaces can be served from one
497    /// connection. Once every dispatcher has declined, this produces the
498    /// standard `org.freedesktop.DBus.Error.UnknownMethod` reply leaving the
499    /// call unanswered would leave the caller waiting for its timeout instead.
500    pub fn reply_unknown_method(&mut self, call: &Call) -> Result<()> {
501        self.reply_error(
502            call,
503            &Error::remote(
504                org_freedesktop_dbus::UNKNOWN_METHOD_ERROR,
505                format_args!(
506                    "No such method: {}.{}",
507                    call.interface().unwrap_or_default(),
508                    call.member()
509                ),
510            ),
511        )
512    }
513
514    /// Write out everything which has been buffered for sending.
515    ///
516    /// This is only needed before dropping the connection, since [`next()`] and
517    /// [`call()`] both drive writes as a side effect.
518    ///
519    /// [`next()`]: Self::next
520    /// [`call()`]: Self::call
521    pub async fn flush(&mut self) -> Result<()> {
522        self.connection.flush(&mut self.buffers).await?;
523
524        if self.buffers.recv.has_message() {
525            let message = self.buffers.recv.last_message()?.to_owned();
526            self.queue.push_back(message);
527            self.buffers.recv.clear();
528        }
529
530        Ok(())
531    }
532
533    /// Wait for the next method call or signal directed at this connection.
534    pub async fn next(&mut self) -> Result<Incoming> {
535        loop {
536            if let Some(message) = self.queue.pop_front() {
537                if let Some(incoming) = Incoming::new(message) {
538                    return Ok(incoming);
539                }
540
541                continue;
542            }
543
544            self.connection.wait(&mut self.buffers).await?;
545            let message = self.buffers.recv.last_message()?.to_owned();
546
547            if let Some(incoming) = Incoming::new(message) {
548                return Ok(incoming);
549            }
550        }
551    }
552
553    /// Wait for the reply with the given serial, applying the configured
554    /// timeout.
555    async fn wait_for(&mut self, serial: Serial) -> Result<MessageBuf> {
556        let Self {
557            connection,
558            buffers,
559            queue,
560            timeout,
561            sleep,
562            ..
563        } = self;
564
565        let future = pin!(drive_until_reply(connection, buffers, queue, serial));
566
567        let Some(timeout) = *timeout else {
568            return future.await;
569        };
570
571        let deadline = Instant::now() + timeout;
572
573        // The timer is created on the first timed call and reset for each one
574        // after that, and is deliberately never cancelled: resetting a timer
575        // which is still registered with the runtime to a later deadline is a
576        // lock-free store, where registering a fresh one locks the timer
577        // wheel. A deadline which fires with no call outstanding wakes the
578        // last caller once, spuriously and harmlessly.
579        let sleep = match sleep {
580            Some(sleep) => {
581                sleep.as_mut().reset(deadline);
582                sleep
583            }
584            sleep => sleep.insert(Box::pin(tokio::time::sleep_until(deadline))),
585        };
586
587        Timed {
588            future,
589            sleep: sleep.as_mut(),
590            timeout,
591        }
592        .await
593    }
594}
595
596/// Drive the connection until the reply with the given serial arrives,
597/// queueing everything else which shows up in the meantime.
598///
599/// This is a function over the fields it needs rather than a method, so that
600/// the timer of the connection stays borrowable next to it.
601async fn drive_until_reply(
602    connection: &mut tokio_dbus::Connection,
603    buffers: &mut Buffers,
604    queue: &mut VecDeque<MessageBuf>,
605    serial: Serial,
606) -> Result<MessageBuf> {
607    loop {
608        connection.wait(buffers).await?;
609        let message = buffers.recv.last_message()?;
610
611        match message.kind() {
612            MessageKind::MethodReturn { reply_serial } if reply_serial == serial => {
613                return Ok(message.to_owned());
614            }
615            MessageKind::Error {
616                error_name,
617                reply_serial,
618            } if reply_serial == serial => {
619                let text = message.body().read::<str>().unwrap_or_default();
620                return Err(Error::remote(error_name, text));
621            }
622            _ => {
623                let message = message.to_owned();
624                queue.push_back(message);
625            }
626        }
627    }
628}
629
630/// A future bounded by the reply deadline of the connection.
631///
632/// This is `tokio::time::timeout` with the timer borrowed rather than owned, so
633/// that however the wait ends, completion, cancellation or an unwinding panic,
634/// the timer stays in the connection for the next call to reuse.
635struct Timed<'a, F> {
636    future: Pin<&'a mut F>,
637    sleep: Pin<&'a mut Sleep>,
638    timeout: Duration,
639}
640
641impl<T, F> Future for Timed<'_, F>
642where
643    F: Future<Output = Result<T>>,
644{
645    type Output = Result<T>;
646
647    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
648        // NB: The future is polled first so that a reply which is ready wins
649        // over a deadline which elapsed while waiting.
650        if let Poll::Ready(result) = self.future.as_mut().poll(cx) {
651            return Poll::Ready(result);
652        }
653
654        if self.sleep.as_mut().poll(cx).is_ready() {
655            return Poll::Ready(Err(Error::new(ErrorKind::Timeout(self.timeout))));
656        }
657
658        Poll::Pending
659    }
660}
661
662/// The reply to a method call.
663pub struct Reply {
664    message: MessageBuf,
665}
666
667impl Reply {
668    /// The body of the reply, from which the return values are read.
669    pub fn body(&self) -> Body<'_> {
670        self.message.body()
671    }
672
673    /// Read a single return value.
674    pub fn read<T>(&self) -> Result<T>
675    where
676        T: Decode,
677    {
678        T::decode(&mut self.body())
679    }
680}
681
682impl fmt::Debug for Reply {
683    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
684        self.message.fmt(f)
685    }
686}
687
688/// A message which arrived on the connection and is not a reply.
689#[derive(Debug)]
690#[non_exhaustive]
691pub enum Incoming {
692    /// A method call which is expected to be replied to.
693    Call(Call),
694    /// A signal, which is never replied to.
695    Signal(SignalMessage),
696}
697
698impl Incoming {
699    fn new(message: MessageBuf) -> Option<Self> {
700        match message.kind() {
701            MessageKind::MethodCall { .. } => Some(Incoming::Call(Call { message })),
702            MessageKind::Signal { .. } => Some(Incoming::Signal(SignalMessage { message })),
703            // NB: A reply which nothing is waiting for anymore.
704            _ => None,
705        }
706    }
707}
708
709/// An incoming method call.
710pub struct Call {
711    message: MessageBuf,
712}
713
714impl Call {
715    /// The object the call is addressed to.
716    pub fn path(&self) -> &ObjectPath {
717        match self.message.kind() {
718            MessageKind::MethodCall { path, .. } => path,
719            _ => unreachable!("Only constructed from a method call"),
720        }
721    }
722
723    /// The method being called.
724    pub fn member(&self) -> &str {
725        match self.message.kind() {
726            MessageKind::MethodCall { member, .. } => member,
727            _ => unreachable!("Only constructed from a method call"),
728        }
729    }
730
731    /// The interface the method belongs to, if the caller named one.
732    pub fn interface(&self) -> Option<&str> {
733        self.message.interface()
734    }
735
736    /// The unique name of the caller.
737    pub fn sender(&self) -> Option<&str> {
738        self.message.sender()
739    }
740
741    /// The body of the call, from which the arguments are read.
742    pub fn body(&self) -> Body<'_> {
743        self.message.body()
744    }
745}
746
747impl fmt::Debug for Call {
748    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
749        f.debug_struct("Call")
750            .field("path", &self.path())
751            .field("interface", &self.interface())
752            .field("member", &self.member())
753            .finish()
754    }
755}
756
757/// An incoming signal.
758pub struct SignalMessage {
759    message: MessageBuf,
760}
761
762impl SignalMessage {
763    /// The object which emitted the signal.
764    pub fn path(&self) -> &ObjectPath {
765        match self.message.kind() {
766            MessageKind::Signal { path, .. } => path,
767            _ => unreachable!("Only constructed from a signal"),
768        }
769    }
770
771    /// The name of the signal.
772    pub fn member(&self) -> &str {
773        match self.message.kind() {
774            MessageKind::Signal { member, .. } => member,
775            _ => unreachable!("Only constructed from a signal"),
776        }
777    }
778
779    /// The interface the signal belongs to, if the sender named one.
780    pub fn interface(&self) -> Option<&str> {
781        self.message.interface()
782    }
783
784    /// The unique name of the sender.
785    pub fn sender(&self) -> Option<&str> {
786        self.message.sender()
787    }
788
789    /// The body of the signal, from which its arguments are read.
790    pub fn body(&self) -> Body<'_> {
791        self.message.body()
792    }
793}
794
795impl fmt::Debug for SignalMessage {
796    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
797        f.debug_struct("SignalMessage")
798            .field("path", &self.path())
799            .field("interface", &self.interface())
800            .field("member", &self.member())
801            .finish()
802    }
803}