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}
429