1 use std::{
2     convert::{TryFrom, TryInto},
3     fmt,
4     io::Cursor,
5 };
6 
7 #[cfg(unix)]
8 use std::{
9     os::unix::io::{AsRawFd, RawFd},
10     sync::{Arc, RwLock},
11 };
12 
13 use enumflags2::BitFlags;
14 use static_assertions::assert_impl_all;
15 use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, UniqueName};
16 use zvariant::{DynamicType, EncodingContext, ObjectPath, Signature, Type};
17 
18 #[cfg(unix)]
19 use crate::OwnedFd;
20 use crate::{
21     utils::padding_for_8_bytes, EndianSig, Error, MessageField, MessageFieldCode, MessageFields,
22     MessageFlags, MessageHeader, MessagePrimaryHeader, MessageType, QuickMessageFields, Result,
23     MIN_MESSAGE_SIZE, NATIVE_ENDIAN_SIG,
24 };
25 
26 #[cfg(unix)]
27 const LOCK_PANIC_MSG: &str = "lock poisoned";
28 
29 macro_rules! dbus_context {
30     ($n_bytes_before: expr) => {
31         EncodingContext::<byteorder::NativeEndian>::new_dbus($n_bytes_before)
32     };
33 }
34 
35 /// A builder for [`Message`]
36 #[derive(Debug)]
37 pub struct MessageBuilder<'a> {
38     header: MessageHeader<'a>,
39 }
40 
41 impl<'a> MessageBuilder<'a> {
new(msg_type: MessageType) -> Self42     fn new(msg_type: MessageType) -> Self {
43         let primary = MessagePrimaryHeader::new(msg_type, 0);
44         let fields = MessageFields::new();
45         let header = MessageHeader::new(primary, fields);
46         Self { header }
47     }
48 
49     /// Create a message of type [`MessageType::MethodCall`].
method_call<'p: 'a, 'm: 'a, P, M>(path: P, method_name: M) -> Result<Self> where P: TryInto<ObjectPath<'p>>, M: TryInto<MemberName<'m>>, P::Error: Into<Error>, M::Error: Into<Error>,50     pub fn method_call<'p: 'a, 'm: 'a, P, M>(path: P, method_name: M) -> Result<Self>
51     where
52         P: TryInto<ObjectPath<'p>>,
53         M: TryInto<MemberName<'m>>,
54         P::Error: Into<Error>,
55         M::Error: Into<Error>,
56     {
57         Self::new(MessageType::MethodCall)
58             .path(path)?
59             .member(method_name)
60     }
61 
62     /// Create a message of type [`MessageType::Signal`].
signal<'p: 'a, 'i: 'a, 'm: 'a, P, I, M>(path: P, interface: I, name: M) -> Result<Self> where P: TryInto<ObjectPath<'p>>, I: TryInto<InterfaceName<'i>>, M: TryInto<MemberName<'m>>, P::Error: Into<Error>, I::Error: Into<Error>, M::Error: Into<Error>,63     pub fn signal<'p: 'a, 'i: 'a, 'm: 'a, P, I, M>(path: P, interface: I, name: M) -> Result<Self>
64     where
65         P: TryInto<ObjectPath<'p>>,
66         I: TryInto<InterfaceName<'i>>,
67         M: TryInto<MemberName<'m>>,
68         P::Error: Into<Error>,
69         I::Error: Into<Error>,
70         M::Error: Into<Error>,
71     {
72         Self::new(MessageType::Signal)
73             .path(path)?
74             .interface(interface)?
75             .member(name)
76     }
77 
78     /// Create a message of type [`MessageType::MethodReturn`].
method_return(reply_to: &MessageHeader<'_>) -> Result<Self>79     pub fn method_return(reply_to: &MessageHeader<'_>) -> Result<Self> {
80         Self::new(MessageType::MethodReturn).reply_to(reply_to)
81     }
82 
83     /// Create a message of type [`MessageType::Error`].
error<'e: 'a, E>(reply_to: &MessageHeader<'_>, name: E) -> Result<Self> where E: TryInto<ErrorName<'e>>, E::Error: Into<Error>,84     pub fn error<'e: 'a, E>(reply_to: &MessageHeader<'_>, name: E) -> Result<Self>
85     where
86         E: TryInto<ErrorName<'e>>,
87         E::Error: Into<Error>,
88     {
89         Self::new(MessageType::Error)
90             .error_name(name)?
91             .reply_to(reply_to)
92     }
93 
94     /// Add flags to the message.
95     ///
96     /// See [`MessageFlags`] documentation for the meaning of the flags.
97     ///
98     /// The function will return an error if invalid flags are given for the message type.
with_flags(mut self, flag: MessageFlags) -> Result<Self>99     pub fn with_flags(mut self, flag: MessageFlags) -> Result<Self> {
100         if self.header.message_type()? != MessageType::MethodCall
101             && BitFlags::from_flag(flag).contains(MessageFlags::NoReplyExpected)
102         {
103             return Err(Error::InvalidField);
104         }
105         let flags = self.header.primary().flags() | flag;
106         self.header.primary_mut().set_flags(flags);
107         Ok(self)
108     }
109 
110     /// Set the unique name of the sending connection.
sender<'s: 'a, S>(mut self, sender: S) -> Result<Self> where S: TryInto<UniqueName<'s>>, S::Error: Into<Error>,111     pub fn sender<'s: 'a, S>(mut self, sender: S) -> Result<Self>
112     where
113         S: TryInto<UniqueName<'s>>,
114         S::Error: Into<Error>,
115     {
116         self.header
117             .fields_mut()
118             .replace(MessageField::Sender(sender.try_into().map_err(Into::into)?));
119         Ok(self)
120     }
121 
122     /// Set the object to send a call to, or the object a signal is emitted from.
path<'p: 'a, P>(mut self, path: P) -> Result<Self> where P: TryInto<ObjectPath<'p>>, P::Error: Into<Error>,123     pub fn path<'p: 'a, P>(mut self, path: P) -> Result<Self>
124     where
125         P: TryInto<ObjectPath<'p>>,
126         P::Error: Into<Error>,
127     {
128         self.header
129             .fields_mut()
130             .replace(MessageField::Path(path.try_into().map_err(Into::into)?));
131         Ok(self)
132     }
133 
134     /// Set the interface to invoke a method call on, or that a signal is emitted from.
interface<'i: 'a, I>(mut self, interface: I) -> Result<Self> where I: TryInto<InterfaceName<'i>>, I::Error: Into<Error>,135     pub fn interface<'i: 'a, I>(mut self, interface: I) -> Result<Self>
136     where
137         I: TryInto<InterfaceName<'i>>,
138         I::Error: Into<Error>,
139     {
140         self.header.fields_mut().replace(MessageField::Interface(
141             interface.try_into().map_err(Into::into)?,
142         ));
143         Ok(self)
144     }
145 
146     /// Set the member, either the method name or signal name.
member<'m: 'a, M>(mut self, member: M) -> Result<Self> where M: TryInto<MemberName<'m>>, M::Error: Into<Error>,147     pub fn member<'m: 'a, M>(mut self, member: M) -> Result<Self>
148     where
149         M: TryInto<MemberName<'m>>,
150         M::Error: Into<Error>,
151     {
152         self.header
153             .fields_mut()
154             .replace(MessageField::Member(member.try_into().map_err(Into::into)?));
155         Ok(self)
156     }
157 
error_name<'e: 'a, E>(mut self, error: E) -> Result<Self> where E: TryInto<ErrorName<'e>>, E::Error: Into<Error>,158     fn error_name<'e: 'a, E>(mut self, error: E) -> Result<Self>
159     where
160         E: TryInto<ErrorName<'e>>,
161         E::Error: Into<Error>,
162     {
163         self.header.fields_mut().replace(MessageField::ErrorName(
164             error.try_into().map_err(Into::into)?,
165         ));
166         Ok(self)
167     }
168 
169     /// Set the name of the connection this message is intended for.
destination<'d: 'a, D>(mut self, destination: D) -> Result<Self> where D: TryInto<BusName<'d>>, D::Error: Into<Error>,170     pub fn destination<'d: 'a, D>(mut self, destination: D) -> Result<Self>
171     where
172         D: TryInto<BusName<'d>>,
173         D::Error: Into<Error>,
174     {
175         self.header.fields_mut().replace(MessageField::Destination(
176             destination.try_into().map_err(Into::into)?,
177         ));
178         Ok(self)
179     }
180 
reply_to(mut self, reply_to: &MessageHeader<'_>) -> Result<Self>181     fn reply_to(mut self, reply_to: &MessageHeader<'_>) -> Result<Self> {
182         let serial = reply_to.primary().serial_num().ok_or(Error::MissingField)?;
183         self.header
184             .fields_mut()
185             .replace(MessageField::ReplySerial(*serial));
186 
187         if let Some(sender) = reply_to.sender()? {
188             self.destination(sender.to_owned())
189         } else {
190             Ok(self)
191         }
192     }
193 
194     /// Build the [`Message`] with the given body.
195     ///
196     /// You may pass `()` as the body if the message has no body.
197     ///
198     /// The caller is currently required to ensure that the resulting message contains the headers
199     /// as compliant with the [specification]. Additional checks may be added to this builder over
200     /// time as needed.
201     ///
202     /// [specification]:
203     /// https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields
build<B>(self, body: &B) -> Result<Message> where B: serde::ser::Serialize + DynamicType,204     pub fn build<B>(self, body: &B) -> Result<Message>
205     where
206         B: serde::ser::Serialize + DynamicType,
207     {
208         let ctxt = dbus_context!(0);
209         let mut header = self.header;
210         // Note: this iterates the body twice, but we prefer efficient handling of large messages
211         // to efficient handling of ones that are complex to serialize.
212         let (body_len, fds_len) = {
213             #[cfg(unix)]
214             {
215                 zvariant::serialized_size_fds(ctxt, body)?
216             }
217             #[cfg(not(unix))]
218             {
219                 (zvariant::serialized_size(ctxt, body)?, 0)
220             }
221         };
222 
223         let mut signature = body.dynamic_signature();
224         if !signature.is_empty() {
225             if signature.starts_with(zvariant::STRUCT_SIG_START_STR) {
226                 // Remove leading and trailing STRUCT delimiters
227                 signature = signature.slice(1..signature.len() - 1);
228             }
229             header.fields_mut().add(MessageField::Signature(signature));
230         }
231 
232         let body_len_u32 = body_len.try_into().map_err(|_| Error::ExcessData)?;
233         let fds_len_u32 = fds_len.try_into().map_err(|_| Error::ExcessData)?;
234         header.primary_mut().set_body_len(body_len_u32);
235 
236         if fds_len != 0 {
237             header.fields_mut().add(MessageField::UnixFDs(fds_len_u32));
238         }
239 
240         let hdr_len = zvariant::serialized_size(ctxt, &header)?;
241 
242         let mut bytes: Vec<u8> = Vec::with_capacity(hdr_len + body_len);
243         let mut cursor = Cursor::new(&mut bytes);
244         zvariant::to_writer(&mut cursor, ctxt, &header)?;
245 
246         let (_, _fds) = {
247             #[cfg(unix)]
248             {
249                 zvariant::to_writer_fds(&mut cursor, ctxt, body)?
250             }
251             #[cfg(not(unix))]
252             {
253                 (zvariant::to_writer(&mut cursor, ctxt, body)?, 0)
254             }
255         };
256         let primary_header = header.into_primary();
257         let header: MessageHeader<'_> = zvariant::from_slice(&bytes, ctxt)?;
258         let quick_fields = QuickMessageFields::new(&bytes, &header)?;
259 
260         Ok(Message {
261             primary_header,
262             quick_fields,
263             bytes,
264             body_offset: hdr_len,
265             #[cfg(unix)]
266             fds: Arc::new(RwLock::new(Fds::Raw(_fds))),
267             recv_seq: MessageSequence::default(),
268         })
269     }
270 }
271 
272 #[cfg(unix)]
273 #[derive(Debug, Eq, PartialEq)]
274 enum Fds {
275     Owned(Vec<OwnedFd>),
276     Raw(Vec<RawFd>),
277 }
278 
279 #[cfg(unix)]
280 impl Clone for Fds {
clone(&self) -> Self281     fn clone(&self) -> Self {
282         Fds::Raw(match self {
283             Fds::Raw(v) => v.clone(),
284             Fds::Owned(v) => v.iter().map(|fd| fd.as_raw_fd()).collect(),
285         })
286     }
287 }
288 
289 /// A position in the stream of [`Message`] objects received by a single [`zbus::Connection`].
290 #[derive(Debug, Default, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
291 pub struct MessageSequence {
292     recv_seq: u64,
293 }
294 
295 /// A D-Bus Message.
296 ///
297 /// The content of the message are stored in serialized format. To deserialize the body of the
298 /// message, use the [`body`] method. You may also access the header and other details with the
299 /// various other getters.
300 ///
301 /// Also provided are constructors for messages of different types. These will mainly be useful for
302 /// very advanced use cases as typically you will want to create a message for immediate dispatch
303 /// and hence use the API provided by [`Connection`], even when using the low-level API.
304 ///
305 /// **Note**: The message owns the received FDs and will close them when dropped. You can call
306 /// [`take_fds`] after deserializing to `RawFD` using [`body`] if you want to take the ownership.
307 /// Moreover, a clone of a message with owned FDs will only receive unowned copies of the FDs.
308 ///
309 /// [`body`]: #method.body
310 /// [`take_fds`]: #method.take_fds
311 /// [`Connection`]: struct.Connection#method.call_method
312 #[derive(Clone)]
313 pub struct Message {
314     primary_header: MessagePrimaryHeader,
315     quick_fields: QuickMessageFields,
316     bytes: Vec<u8>,
317     body_offset: usize,
318     #[cfg(unix)]
319     fds: Arc<RwLock<Fds>>,
320     recv_seq: MessageSequence,
321 }
322 
323 assert_impl_all!(Message: Send, Sync, Unpin);
324 
325 // TODO: Handle non-native byte order: https://gitlab.freedesktop.org/dbus/zbus/-/issues/19
326 impl Message {
327     /// Create a message of type [`MessageType::MethodCall`].
328     ///
329     /// [`MessageType::MethodCall`]: enum.MessageType.html#variant.MethodCall
method<'s, 'd, 'p, 'i, 'm, S, D, P, I, M, B>( sender: Option<S>, destination: Option<D>, path: P, iface: Option<I>, method_name: M, body: &B, ) -> Result<Self> where S: TryInto<UniqueName<'s>>, D: TryInto<BusName<'d>>, P: TryInto<ObjectPath<'p>>, I: TryInto<InterfaceName<'i>>, M: TryInto<MemberName<'m>>, S::Error: Into<Error>, D::Error: Into<Error>, P::Error: Into<Error>, I::Error: Into<Error>, M::Error: Into<Error>, B: serde::ser::Serialize + DynamicType,330     pub fn method<'s, 'd, 'p, 'i, 'm, S, D, P, I, M, B>(
331         sender: Option<S>,
332         destination: Option<D>,
333         path: P,
334         iface: Option<I>,
335         method_name: M,
336         body: &B,
337     ) -> Result<Self>
338     where
339         S: TryInto<UniqueName<'s>>,
340         D: TryInto<BusName<'d>>,
341         P: TryInto<ObjectPath<'p>>,
342         I: TryInto<InterfaceName<'i>>,
343         M: TryInto<MemberName<'m>>,
344         S::Error: Into<Error>,
345         D::Error: Into<Error>,
346         P::Error: Into<Error>,
347         I::Error: Into<Error>,
348         M::Error: Into<Error>,
349         B: serde::ser::Serialize + DynamicType,
350     {
351         let mut b = MessageBuilder::method_call(path, method_name)?;
352 
353         if let Some(sender) = sender {
354             b = b.sender(sender)?;
355         }
356         if let Some(destination) = destination {
357             b = b.destination(destination)?;
358         }
359         if let Some(iface) = iface {
360             b = b.interface(iface)?;
361         }
362         b.build(body)
363     }
364 
365     /// Create a message of type [`MessageType::Signal`].
366     ///
367     /// [`MessageType::Signal`]: enum.MessageType.html#variant.Signal
signal<'s, 'd, 'p, 'i, 'm, S, D, P, I, M, B>( sender: Option<S>, destination: Option<D>, path: P, iface: I, signal_name: M, body: &B, ) -> Result<Self> where S: TryInto<UniqueName<'s>>, D: TryInto<BusName<'d>>, P: TryInto<ObjectPath<'p>>, I: TryInto<InterfaceName<'i>>, M: TryInto<MemberName<'m>>, S::Error: Into<Error>, D::Error: Into<Error>, P::Error: Into<Error>, I::Error: Into<Error>, M::Error: Into<Error>, B: serde::ser::Serialize + DynamicType,368     pub fn signal<'s, 'd, 'p, 'i, 'm, S, D, P, I, M, B>(
369         sender: Option<S>,
370         destination: Option<D>,
371         path: P,
372         iface: I,
373         signal_name: M,
374         body: &B,
375     ) -> Result<Self>
376     where
377         S: TryInto<UniqueName<'s>>,
378         D: TryInto<BusName<'d>>,
379         P: TryInto<ObjectPath<'p>>,
380         I: TryInto<InterfaceName<'i>>,
381         M: TryInto<MemberName<'m>>,
382         S::Error: Into<Error>,
383         D::Error: Into<Error>,
384         P::Error: Into<Error>,
385         I::Error: Into<Error>,
386         M::Error: Into<Error>,
387         B: serde::ser::Serialize + DynamicType,
388     {
389         let mut b = MessageBuilder::signal(path, iface, signal_name)?;
390 
391         if let Some(sender) = sender {
392             b = b.sender(sender)?;
393         }
394         if let Some(destination) = destination {
395             b = b.destination(destination)?;
396         }
397         b.build(body)
398     }
399 
400     /// Create a message of type [`MessageType::MethodReturn`].
401     ///
402     /// [`MessageType::MethodReturn`]: enum.MessageType.html#variant.MethodReturn
method_reply<'s, S, B>(sender: Option<S>, call: &Self, body: &B) -> Result<Self> where S: TryInto<UniqueName<'s>>, S::Error: Into<Error>, B: serde::ser::Serialize + DynamicType,403     pub fn method_reply<'s, S, B>(sender: Option<S>, call: &Self, body: &B) -> Result<Self>
404     where
405         S: TryInto<UniqueName<'s>>,
406         S::Error: Into<Error>,
407         B: serde::ser::Serialize + DynamicType,
408     {
409         let mut b = MessageBuilder::method_return(&call.header()?)?;
410         if let Some(sender) = sender {
411             b = b.sender(sender)?;
412         }
413         b.build(body)
414     }
415 
416     /// Create a message of type [`MessageType::MethodError`].
417     ///
418     /// [`MessageType::MethodError`]: enum.MessageType.html#variant.MethodError
method_error<'s, 'e, S, E, B>( sender: Option<S>, call: &Self, name: E, body: &B, ) -> Result<Self> where S: TryInto<UniqueName<'s>>, S::Error: Into<Error>, E: TryInto<ErrorName<'e>>, E::Error: Into<Error>, B: serde::ser::Serialize + DynamicType,419     pub fn method_error<'s, 'e, S, E, B>(
420         sender: Option<S>,
421         call: &Self,
422         name: E,
423         body: &B,
424     ) -> Result<Self>
425     where
426         S: TryInto<UniqueName<'s>>,
427         S::Error: Into<Error>,
428         E: TryInto<ErrorName<'e>>,
429         E::Error: Into<Error>,
430         B: serde::ser::Serialize + DynamicType,
431     {
432         let mut b = MessageBuilder::error(&call.header()?, name)?;
433         if let Some(sender) = sender {
434             b = b.sender(sender)?;
435         }
436         b.build(body)
437     }
438 
439     /// Create a message from its full contents
from_raw_parts( bytes: Vec<u8>, #[cfg(unix)] fds: Vec<OwnedFd>, recv_seq: u64, ) -> Result<Self>440     pub(crate) fn from_raw_parts(
441         bytes: Vec<u8>,
442         #[cfg(unix)] fds: Vec<OwnedFd>,
443         recv_seq: u64,
444     ) -> Result<Self> {
445         if EndianSig::try_from(bytes[0])? != NATIVE_ENDIAN_SIG {
446             return Err(Error::IncorrectEndian);
447         }
448 
449         let (primary_header, fields_len) = MessagePrimaryHeader::read(&bytes)?;
450         let header = zvariant::from_slice(&bytes, dbus_context!(0))?;
451         #[cfg(unix)]
452         let fds = Arc::new(RwLock::new(Fds::Owned(fds)));
453 
454         let header_len = MIN_MESSAGE_SIZE + fields_len as usize;
455         let body_offset = header_len + padding_for_8_bytes(header_len);
456         let quick_fields = QuickMessageFields::new(&bytes, &header)?;
457 
458         Ok(Self {
459             primary_header,
460             quick_fields,
461             bytes,
462             body_offset,
463             #[cfg(unix)]
464             fds,
465             recv_seq: MessageSequence { recv_seq },
466         })
467     }
468 
469     /// Take ownership of the associated file descriptors in the message.
470     ///
471     /// When a message is received over a AF_UNIX socket, it may contain associated FDs. To prevent
472     /// the message from closing those FDs on drop, call this method that returns all the received
473     /// FDs with their ownership.
474     ///
475     /// This function is Unix-specific.
476     ///
477     /// Note: the message will continue to reference the files, so you must keep them open for as
478     /// long as the message itself.
479     #[cfg(unix)]
take_fds(&self) -> Vec<OwnedFd>480     pub fn take_fds(&self) -> Vec<OwnedFd> {
481         let mut fds_lock = self.fds.write().expect(LOCK_PANIC_MSG);
482         if let Fds::Owned(ref mut fds) = *fds_lock {
483             // From now on, it's the caller responsibility to close the fds
484             let fds = std::mem::take(&mut *fds);
485             *fds_lock = Fds::Raw(fds.iter().map(|fd| fd.as_raw_fd()).collect());
486             fds
487         } else {
488             vec![]
489         }
490     }
491 
492     /// The signature of the body.
493     ///
494     /// **Note:** While zbus treats multiple arguments as a struct (to allow you to use the tuple
495     /// syntax), D-Bus does not. Since this method gives you the signature expected on the wire by
496     /// D-Bus, the trailing and leading STRUCT signature parenthesis will not be present in case of
497     /// multiple arguments.
body_signature(&self) -> Result<Signature<'_>>498     pub fn body_signature(&self) -> Result<Signature<'_>> {
499         match self
500             .header()?
501             .into_fields()
502             .into_field(MessageFieldCode::Signature)
503             .ok_or(Error::NoBodySignature)?
504         {
505             MessageField::Signature(signature) => Ok(signature),
506             _ => Err(Error::InvalidField),
507         }
508     }
509 
primary_header(&self) -> &MessagePrimaryHeader510     pub fn primary_header(&self) -> &MessagePrimaryHeader {
511         &self.primary_header
512     }
513 
modify_primary_header<F>(&mut self, mut modifier: F) -> Result<()> where F: FnMut(&mut MessagePrimaryHeader) -> Result<()>,514     pub(crate) fn modify_primary_header<F>(&mut self, mut modifier: F) -> Result<()>
515     where
516         F: FnMut(&mut MessagePrimaryHeader) -> Result<()>,
517     {
518         modifier(&mut self.primary_header)?;
519 
520         let mut cursor = Cursor::new(&mut self.bytes);
521         zvariant::to_writer(&mut cursor, dbus_context!(0), &self.primary_header)
522             .map(|_| ())
523             .map_err(Error::from)
524     }
525 
526     /// Deserialize the header.
527     ///
528     /// Note: prefer using the direct access methods if possible; they are more efficient.
header(&self) -> Result<MessageHeader<'_>>529     pub fn header(&self) -> Result<MessageHeader<'_>> {
530         zvariant::from_slice(&self.bytes, dbus_context!(0)).map_err(Error::from)
531     }
532 
533     /// Deserialize the fields.
534     ///
535     /// Note: prefer using the direct access methods if possible; they are more efficient.
fields(&self) -> Result<MessageFields<'_>>536     pub fn fields(&self) -> Result<MessageFields<'_>> {
537         let ctxt = dbus_context!(crate::PRIMARY_HEADER_SIZE);
538         zvariant::from_slice(&self.bytes[crate::PRIMARY_HEADER_SIZE..], ctxt).map_err(Error::from)
539     }
540 
541     /// The message type.
message_type(&self) -> MessageType542     pub fn message_type(&self) -> MessageType {
543         self.primary_header.msg_type()
544     }
545 
546     /// The object to send a call to, or the object a signal is emitted from.
path(&self) -> Option<ObjectPath<'_>>547     pub fn path(&self) -> Option<ObjectPath<'_>> {
548         self.quick_fields.path(self)
549     }
550 
551     /// The interface to invoke a method call on, or that a signal is emitted from.
interface(&self) -> Option<InterfaceName<'_>>552     pub fn interface(&self) -> Option<InterfaceName<'_>> {
553         self.quick_fields.interface(self)
554     }
555 
556     /// The member, either the method name or signal name.
member(&self) -> Option<MemberName<'_>>557     pub fn member(&self) -> Option<MemberName<'_>> {
558         self.quick_fields.member(self)
559     }
560 
561     /// The serial number of the message this message is a reply to.
reply_serial(&self) -> Option<u32>562     pub fn reply_serial(&self) -> Option<u32> {
563         self.quick_fields.reply_serial()
564     }
565 
566     /// Deserialize the body (without checking signature matching).
body_unchecked<'d, 'm: 'd, B>(&'m self) -> Result<B> where B: serde::de::Deserialize<'d> + Type,567     pub fn body_unchecked<'d, 'm: 'd, B>(&'m self) -> Result<B>
568     where
569         B: serde::de::Deserialize<'d> + Type,
570     {
571         {
572             #[cfg(unix)]
573             {
574                 zvariant::from_slice_fds(
575                     &self.bytes[self.body_offset..],
576                     Some(&self.fds()),
577                     dbus_context!(0),
578                 )
579             }
580             #[cfg(not(unix))]
581             {
582                 zvariant::from_slice(&self.bytes[self.body_offset..], dbus_context!(0))
583             }
584         }
585         .map_err(Error::from)
586     }
587 
588     /// Deserialize the body using the contained signature.
589     ///
590     /// # Example
591     ///
592     /// ```
593     /// # use std::convert::TryInto;
594     /// # use zbus::Message;
595     /// # (|| -> zbus::Result<()> {
596     /// let send_body = (7i32, (2i32, "foo"), vec!["bar"]);
597     /// let message = Message::method(None::<&str>, Some("zbus.test"), "/", Some("zbus.test"), "ping", &send_body)?;
598     /// let body : zvariant::Structure = message.body()?;
599     /// let fields = body.fields();
600     /// assert!(matches!(fields[0], zvariant::Value::I32(7)));
601     /// assert!(matches!(fields[1], zvariant::Value::Structure(_)));
602     /// assert!(matches!(fields[2], zvariant::Value::Array(_)));
603     ///
604     /// let reply_msg = Message::method_reply(None::<&str>, &message, &body)?;
605     /// let reply_value : (i32, (i32, &str), Vec<String>) = reply_msg.body()?;
606     ///
607     /// assert_eq!(reply_value.0, 7);
608     /// assert_eq!(reply_value.2.len(), 1);
609     /// # Ok(()) })().unwrap()
610     /// ```
body<'d, 'm: 'd, B>(&'m self) -> Result<B> where B: zvariant::DynamicDeserialize<'d>,611     pub fn body<'d, 'm: 'd, B>(&'m self) -> Result<B>
612     where
613         B: zvariant::DynamicDeserialize<'d>,
614     {
615         let body_sig = match self.body_signature() {
616             Ok(sig) => sig,
617             Err(Error::NoBodySignature) => Signature::from_static_str_unchecked(""),
618             Err(e) => return Err(e),
619         };
620 
621         {
622             #[cfg(unix)]
623             {
624                 zvariant::from_slice_fds_for_dynamic_signature(
625                     &self.bytes[self.body_offset..],
626                     Some(&self.fds()),
627                     dbus_context!(0),
628                     &body_sig,
629                 )
630             }
631             #[cfg(not(unix))]
632             {
633                 zvariant::from_slice_for_dynamic_signature(
634                     &self.bytes[self.body_offset..],
635                     dbus_context!(0),
636                     &body_sig,
637                 )
638             }
639         }
640         .map_err(Error::from)
641     }
642 
643     #[cfg(unix)]
fds(&self) -> Vec<RawFd>644     pub(crate) fn fds(&self) -> Vec<RawFd> {
645         match &*self.fds.read().expect(LOCK_PANIC_MSG) {
646             Fds::Raw(fds) => fds.clone(),
647             Fds::Owned(fds) => fds.iter().map(|f| f.as_raw_fd()).collect(),
648         }
649     }
650 
651     /// Get a reference to the byte encoding of the message.
as_bytes(&self) -> &[u8]652     pub fn as_bytes(&self) -> &[u8] {
653         &self.bytes
654     }
655 
656     /// Get a reference to the byte encoding of the body of the message.
body_as_bytes(&self) -> Result<&[u8]>657     pub fn body_as_bytes(&self) -> Result<&[u8]> {
658         Ok(&self.bytes[self.body_offset..])
659     }
660 
661     /// Get the receive ordering of a message.
662     ///
663     /// This may be used to identify how two events were ordered on the bus.  It only produces a
664     /// useful ordering for messages that were produced by the same [`zbus::Connection`].
665     ///
666     /// This is completely unrelated to the serial number on the message, which is set by the peer
667     /// and might not be ordered at all.
recv_position(&self) -> MessageSequence668     pub fn recv_position(&self) -> MessageSequence {
669         self.recv_seq
670     }
671 }
672 
673 impl fmt::Debug for Message {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result674     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
675         let mut msg = f.debug_struct("Msg");
676         let _ = self.header().map(|h| {
677             if let Ok(t) = h.message_type() {
678                 msg.field("type", &t);
679             }
680             if let Ok(Some(sender)) = h.sender() {
681                 msg.field("sender", &sender);
682             }
683             if let Ok(Some(serial)) = h.reply_serial() {
684                 msg.field("reply-serial", &serial);
685             }
686             if let Ok(Some(path)) = h.path() {
687                 msg.field("path", &path);
688             }
689             if let Ok(Some(iface)) = h.interface() {
690                 msg.field("iface", &iface);
691             }
692             if let Ok(Some(member)) = h.member() {
693                 msg.field("member", &member);
694             }
695         });
696         if let Ok(s) = self.body_signature() {
697             msg.field("body", &s);
698         }
699         #[cfg(unix)]
700         {
701             let fds = self.fds();
702             if !fds.is_empty() {
703                 msg.field("fds", &fds);
704             }
705         }
706         msg.finish()
707     }
708 }
709 
710 impl fmt::Display for Message {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result711     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
712         let header = self.header();
713         let (ty, error_name, sender, member) = if let Ok(h) = header.as_ref() {
714             (
715                 h.message_type().ok(),
716                 h.error_name().ok().flatten(),
717                 h.sender().ok().flatten(),
718                 h.member().ok().flatten(),
719             )
720         } else {
721             (None, None, None, None)
722         };
723 
724         match ty {
725             Some(MessageType::MethodCall) => {
726                 write!(f, "Method call")?;
727                 if let Some(m) = member {
728                     write!(f, " {}", m)?;
729                 }
730             }
731             Some(MessageType::MethodReturn) => {
732                 write!(f, "Method return")?;
733             }
734             Some(MessageType::Error) => {
735                 write!(f, "Error")?;
736                 if let Some(e) = error_name {
737                     write!(f, " {}", e)?;
738                 }
739 
740                 let msg = self.body_unchecked::<&str>();
741                 if let Ok(msg) = msg {
742                     write!(f, ": {}", msg)?;
743                 }
744             }
745             Some(MessageType::Signal) => {
746                 write!(f, "Signal")?;
747                 if let Some(m) = member {
748                     write!(f, " {}", m)?;
749                 }
750             }
751             _ => {
752                 write!(f, "Unknown message")?;
753             }
754         }
755 
756         if let Some(s) = sender {
757             write!(f, " from {}", s)?;
758         }
759 
760         Ok(())
761     }
762 }
763 
764 #[cfg(test)]
765 mod tests {
766     #[cfg(unix)]
767     use std::os::unix::io::AsRawFd;
768     use test_log::test;
769     #[cfg(unix)]
770     use zvariant::Fd;
771 
772     #[cfg(unix)]
773     use super::Fds;
774     use super::Message;
775     use crate::Error;
776 
777     #[test]
test()778     fn test() {
779         #[cfg(unix)]
780         let stdout = std::io::stdout();
781         let m = Message::method(
782             Some(":1.72"),
783             None::<()>,
784             "/",
785             None::<()>,
786             "do",
787             &(
788                 #[cfg(unix)]
789                 Fd::from(&stdout),
790                 "foo",
791             ),
792         )
793         .unwrap();
794         assert_eq!(
795             m.body_signature().unwrap().to_string(),
796             if cfg!(unix) { "hs" } else { "s" }
797         );
798         #[cfg(unix)]
799         assert_eq!(*m.fds.read().unwrap(), Fds::Raw(vec![stdout.as_raw_fd()]));
800 
801         let body: Result<u32, Error> = m.body();
802         assert!(matches!(
803             body.unwrap_err(),
804             Error::Variant(zvariant::Error::SignatureMismatch { .. })
805         ));
806 
807         assert_eq!(m.to_string(), "Method call do from :1.72");
808         let r = Message::method_reply(None::<()>, &m, &("all fine!")).unwrap();
809         assert_eq!(r.to_string(), "Method return");
810         let e = Message::method_error(
811             None::<()>,
812             &m,
813             "org.freedesktop.zbus.Error",
814             &("kaboom!", 32),
815         )
816         .unwrap();
817         assert_eq!(e.to_string(), "Error org.freedesktop.zbus.Error: kaboom!");
818     }
819 }
820