zbus/message/
mod.rs

1//! D-Bus Message.
2use std::{fmt, num::NonZeroU32, sync::Arc};
3
4use static_assertions::assert_impl_all;
5use zbus_names::{ErrorName, InterfaceName, MemberName};
6use zvariant::{serialized, Endian};
7
8use crate::{utils::padding_for_8_bytes, zvariant::ObjectPath, Error, Result};
9
10mod builder;
11pub use builder::Builder;
12
13mod field;
14pub(crate) use field::{Field, FieldCode};
15
16mod fields;
17pub(crate) use fields::Fields;
18use fields::QuickFields;
19
20mod body;
21pub use body::Body;
22
23pub(crate) mod header;
24use header::MIN_MESSAGE_SIZE;
25pub use header::{EndianSig, Flags, Header, PrimaryHeader, Type, NATIVE_ENDIAN_SIG};
26
27/// A position in the stream of [`Message`] objects received by a single [`zbus::Connection`].
28///
29/// Note: the relative ordering of values obtained from distinct [`zbus::Connection`] objects is
30/// not specified; only sequence numbers originating from the same connection should be compared.
31#[derive(Debug, Default, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
32pub struct Sequence {
33    recv_seq: u64,
34}
35
36impl Sequence {
37    /// A sequence number that is higher than any other; used by errors that terminate a stream.
38    pub(crate) const LAST: Self = Self { recv_seq: u64::MAX };
39}
40
41/// A D-Bus Message.
42///
43/// The content of the message are stored in serialized format. To get the body of the message, use
44/// the [`Message::body`] method, and use [`Body`] methods to deserialize it. You may also access
45/// the header and other details with the various other getters.
46///
47/// Also provided are constructors for messages of different types. These will mainly be useful for
48/// very advanced use cases as typically you will want to create a message for immediate dispatch
49/// and hence use the API provided by [`Connection`], even when using the low-level API.
50///
51/// **Note**: The message owns the received FDs and will close them when dropped. You can
52/// deserialize to [`zvariant::OwnedFd`] the body (that you get using [`Message::body`]) if you want
53/// to keep the FDs around after the containing message is dropped.
54///
55/// [`Connection`]: struct.Connection#method.call_method
56#[derive(Clone)]
57pub struct Message {
58    pub(super) inner: Arc<Inner>,
59}
60
61pub(super) struct Inner {
62    pub(crate) primary_header: PrimaryHeader,
63    pub(crate) quick_fields: QuickFields,
64    pub(crate) bytes: serialized::Data<'static, 'static>,
65    pub(crate) body_offset: usize,
66    pub(crate) recv_seq: Sequence,
67}
68
69assert_impl_all!(Message: Send, Sync, Unpin);
70
71impl Message {
72    /// Create a builder for message of type [`Type::MethodCall`].
73    pub fn method<'b, 'p: 'b, 'm: 'b, P, M>(path: P, method_name: M) -> Result<Builder<'b>>
74    where
75        P: TryInto<ObjectPath<'p>>,
76        M: TryInto<MemberName<'m>>,
77        P::Error: Into<Error>,
78        M::Error: Into<Error>,
79    {
80        #[allow(deprecated)]
81        Builder::method_call(path, method_name)
82    }
83
84    /// Create a builder for message of type [`Type::Signal`].
85    pub fn signal<'b, 'p: 'b, 'i: 'b, 'm: 'b, P, I, M>(
86        path: P,
87        iface: I,
88        signal_name: M,
89    ) -> Result<Builder<'b>>
90    where
91        P: TryInto<ObjectPath<'p>>,
92        I: TryInto<InterfaceName<'i>>,
93        M: TryInto<MemberName<'m>>,
94        P::Error: Into<Error>,
95        I::Error: Into<Error>,
96        M::Error: Into<Error>,
97    {
98        #[allow(deprecated)]
99        Builder::signal(path, iface, signal_name)
100    }
101
102    /// Create a builder for message of type [`Type::MethodReturn`].
103    pub fn method_reply(call: &Self) -> Result<Builder<'_>> {
104        #[allow(deprecated)]
105        Builder::method_return(&call.header())
106    }
107
108    /// Create a builder for message of type [`Type::Error`].
109    pub fn method_error<'b, 'e: 'b, E>(call: &Self, name: E) -> Result<Builder<'b>>
110    where
111        E: TryInto<ErrorName<'e>>,
112        E::Error: Into<Error>,
113    {
114        #[allow(deprecated)]
115        Builder::error(&call.header(), name)
116    }
117
118    /// Create a message from bytes.
119    ///
120    /// **Note:** Since the constructed message is not construct by zbus, the receive sequence,
121    /// which can be acquired from [`Message::recv_position`], is not applicable and hence set
122    /// to `0`.
123    ///
124    /// # Safety
125    ///
126    /// This method is unsafe as bytes may have an invalid encoding.
127    pub unsafe fn from_bytes(bytes: serialized::Data<'static, 'static>) -> Result<Self> {
128        Self::from_raw_parts(bytes, 0)
129    }
130
131    /// Create a message from its full contents
132    pub(crate) fn from_raw_parts(
133        bytes: serialized::Data<'static, 'static>,
134        recv_seq: u64,
135    ) -> Result<Self> {
136        let endian = Endian::from(EndianSig::try_from(bytes[0])?);
137        if endian != bytes.context().endian() {
138            return Err(Error::IncorrectEndian);
139        }
140
141        let (primary_header, fields_len) = PrimaryHeader::read_from_data(&bytes)?;
142        let (header, _) = bytes.deserialize()?;
143
144        let header_len = MIN_MESSAGE_SIZE + fields_len as usize;
145        let body_offset = header_len + padding_for_8_bytes(header_len);
146        let quick_fields = QuickFields::new(&bytes, &header)?;
147
148        Ok(Self {
149            inner: Arc::new(Inner {
150                primary_header,
151                quick_fields,
152                bytes,
153                body_offset,
154                recv_seq: Sequence { recv_seq },
155            }),
156        })
157    }
158
159    pub fn primary_header(&self) -> &PrimaryHeader {
160        &self.inner.primary_header
161    }
162
163    /// The message header.
164    ///
165    /// Note: This method does not deserialize the header but it does currently allocate so its not
166    /// zero-cost. While the allocation is small and will hopefully be removed in the future, it's
167    /// best to keep the header around if you need to access it a lot.
168    pub fn header(&self) -> Header<'_> {
169        let mut fields = Fields::new();
170        let quick_fields = &self.inner.quick_fields;
171        if let Some(p) = quick_fields.path(self) {
172            fields.add(Field::Path(p));
173        }
174        if let Some(i) = quick_fields.interface(self) {
175            fields.add(Field::Interface(i));
176        }
177        if let Some(m) = quick_fields.member(self) {
178            fields.add(Field::Member(m));
179        }
180        if let Some(e) = quick_fields.error_name(self) {
181            fields.add(Field::ErrorName(e));
182        }
183        if let Some(r) = quick_fields.reply_serial() {
184            fields.add(Field::ReplySerial(r));
185        }
186        if let Some(d) = quick_fields.destination(self) {
187            fields.add(Field::Destination(d));
188        }
189        if let Some(s) = quick_fields.sender(self) {
190            fields.add(Field::Sender(s));
191        }
192        if let Some(s) = quick_fields.signature(self) {
193            fields.add(Field::Signature(s));
194        }
195        if let Some(u) = quick_fields.unix_fds() {
196            fields.add(Field::UnixFDs(u));
197        }
198
199        Header::new(self.inner.primary_header.clone(), fields)
200    }
201
202    /// The message type.
203    pub fn message_type(&self) -> Type {
204        self.inner.primary_header.msg_type()
205    }
206
207    /// The object to send a call to, or the object a signal is emitted from.
208    #[deprecated(
209        since = "4.0.0",
210        note = "Use `Message::header` with `message::Header::path` instead"
211    )]
212    pub fn path(&self) -> Option<ObjectPath<'_>> {
213        self.inner.quick_fields.path(self)
214    }
215
216    /// The interface to invoke a method call on, or that a signal is emitted from.
217    #[deprecated(
218        since = "4.0.0",
219        note = "Use `Message::header` with `message::Header::interface` instead"
220    )]
221    pub fn interface(&self) -> Option<InterfaceName<'_>> {
222        self.inner.quick_fields.interface(self)
223    }
224
225    /// The member, either the method name or signal name.
226    #[deprecated(
227        since = "4.0.0",
228        note = "Use `Message::header` with `message::Header::member` instead"
229    )]
230    pub fn member(&self) -> Option<MemberName<'_>> {
231        self.inner.quick_fields.member(self)
232    }
233
234    /// The serial number of the message this message is a reply to.
235    #[deprecated(
236        since = "4.0.0",
237        note = "Use `Message::header` with `message::Header::reply_serial` instead"
238    )]
239    pub fn reply_serial(&self) -> Option<NonZeroU32> {
240        self.inner.quick_fields.reply_serial()
241    }
242
243    /// The body that you can deserialize using [`Body::deserialize`].
244    ///
245    /// # Example
246    ///
247    /// ```
248    /// # use zbus::message::Message;
249    /// # (|| -> zbus::Result<()> {
250    /// let send_body = (7i32, (2i32, "foo"), vec!["bar"]);
251    /// let message = Message::method("/", "ping")?
252    ///     .destination("zbus.test")?
253    ///     .interface("zbus.test")?
254    ///     .build(&send_body)?;
255    /// let body = message.body();
256    /// let body: zbus::zvariant::Structure = body.deserialize()?;
257    /// let fields = body.fields();
258    /// assert!(matches!(fields[0], zvariant::Value::I32(7)));
259    /// assert!(matches!(fields[1], zvariant::Value::Structure(_)));
260    /// assert!(matches!(fields[2], zvariant::Value::Array(_)));
261    ///
262    /// let reply_body = Message::method_reply(&message)?.build(&body)?.body();
263    /// let reply_value : (i32, (i32, &str), Vec<String>) = reply_body.deserialize()?;
264    ///
265    /// assert_eq!(reply_value.0, 7);
266    /// assert_eq!(reply_value.2.len(), 1);
267    /// # Ok(()) })().unwrap()
268    /// ```
269    pub fn body(&self) -> Body {
270        Body::new(
271            self.inner.bytes.slice(self.inner.body_offset..),
272            self.clone(),
273        )
274    }
275
276    /// Get a reference to the underlying byte encoding of the message.
277    pub fn data(&self) -> &serialized::Data<'static, 'static> {
278        &self.inner.bytes
279    }
280
281    /// Get the receive ordering of a message.
282    ///
283    /// This may be used to identify how two events were ordered on the bus.  It only produces a
284    /// useful ordering for messages that were produced by the same [`zbus::Connection`].
285    ///
286    /// This is completely unrelated to the serial number on the message, which is set by the peer
287    /// and might not be ordered at all.
288    pub fn recv_position(&self) -> Sequence {
289        self.inner.recv_seq
290    }
291}
292
293impl fmt::Debug for Message {
294    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
295        let mut msg = f.debug_struct("Msg");
296        let h = self.header();
297        msg.field("type", &h.message_type());
298        msg.field("serial", &self.primary_header().serial_num());
299        if let Some(sender) = h.sender() {
300            msg.field("sender", &sender);
301        }
302        if let Some(serial) = h.reply_serial() {
303            msg.field("reply-serial", &serial);
304        }
305        if let Some(path) = h.path() {
306            msg.field("path", &path);
307        }
308        if let Some(iface) = h.interface() {
309            msg.field("iface", &iface);
310        }
311        if let Some(member) = h.member() {
312            msg.field("member", &member);
313        }
314        if let Some(s) = self.body().signature() {
315            msg.field("body", &s);
316        }
317        #[cfg(unix)]
318        {
319            msg.field("fds", &self.data().fds());
320        }
321        msg.finish()
322    }
323}
324
325impl fmt::Display for Message {
326    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327        let header = self.header();
328        let (ty, error_name, sender, member) = (
329            header.message_type(),
330            header.error_name(),
331            header.sender(),
332            header.member(),
333        );
334
335        match ty {
336            Type::MethodCall => {
337                write!(f, "Method call")?;
338                if let Some(m) = member {
339                    write!(f, " {m}")?;
340                }
341            }
342            Type::MethodReturn => {
343                write!(f, "Method return")?;
344            }
345            Type::Error => {
346                write!(f, "Error")?;
347                if let Some(e) = error_name {
348                    write!(f, " {e}")?;
349                }
350
351                let body = self.body();
352                let msg = body.deserialize_unchecked::<&str>();
353                if let Ok(msg) = msg {
354                    write!(f, ": {msg}")?;
355                }
356            }
357            Type::Signal => {
358                write!(f, "Signal")?;
359                if let Some(m) = member {
360                    write!(f, " {m}")?;
361                }
362            }
363        }
364
365        if let Some(s) = sender {
366            write!(f, " from {s}")?;
367        }
368
369        Ok(())
370    }
371}
372
373#[cfg(test)]
374mod tests {
375    #[cfg(unix)]
376    use std::os::fd::{AsFd, AsRawFd};
377    use test_log::test;
378    #[cfg(unix)]
379    use zvariant::Fd;
380
381    use super::Message;
382    use crate::Error;
383
384    #[test]
385    fn test() {
386        #[cfg(unix)]
387        let stdout = std::io::stdout();
388        let m = Message::method("/", "do")
389            .unwrap()
390            .sender(":1.72")
391            .unwrap()
392            .build(&(
393                #[cfg(unix)]
394                Fd::from(&stdout),
395                "foo",
396            ))
397            .unwrap();
398        assert_eq!(
399            m.body().signature().unwrap().to_string(),
400            if cfg!(unix) { "hs" } else { "s" }
401        );
402        #[cfg(unix)]
403        {
404            let fds = m.data().fds();
405            assert_eq!(fds.len(), 1);
406            // FDs get dup'ed so it has to be a different FD now.
407            assert_ne!(fds[0].as_fd().as_raw_fd(), stdout.as_raw_fd());
408        }
409
410        let body: Result<u32, Error> = m.body().deserialize();
411        assert!(matches!(
412            body.unwrap_err(),
413            Error::Variant(zvariant::Error::SignatureMismatch { .. })
414        ));
415
416        assert_eq!(m.to_string(), "Method call do from :1.72");
417        let r = Message::method_reply(&m)
418            .unwrap()
419            .build(&("all fine!"))
420            .unwrap();
421        assert_eq!(r.to_string(), "Method return");
422        let e = Message::method_error(&m, "org.freedesktop.zbus.Error")
423            .unwrap()
424            .build(&("kaboom!", 32))
425            .unwrap();
426        assert_eq!(e.to_string(), "Error org.freedesktop.zbus.Error: kaboom!");
427    }
428}