1use std::convert::TryFrom;
2
3use enumflags2::{bitflags, BitFlags};
4use once_cell::sync::OnceCell;
5use serde::{Deserialize, Serialize};
6use serde_repr::{Deserialize_repr, Serialize_repr};
7
8use static_assertions::assert_impl_all;
9use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, UniqueName};
10use zvariant::{EncodingContext, ObjectPath, Signature, Type};
11
12use crate::{Error, MessageField, MessageFieldCode, MessageFields};
13
14pub(crate) const PRIMARY_HEADER_SIZE: usize = 12;
15pub(crate) const MIN_MESSAGE_SIZE: usize = PRIMARY_HEADER_SIZE + 4;
16pub(crate) const MAX_MESSAGE_SIZE: usize = 128 * 1024 * 1024; // 128 MiB
17
18/// D-Bus code for endianness.
19#[repr(u8)]
20#[derive(Debug, Copy, Clone, Deserialize_repr, PartialEq, Eq, Serialize_repr, Type)]
21pub enum EndianSig {
22 /// The D-Bus message is in big-endian (network) byte order.
23 Big = b'B',
24
25 /// The D-Bus message is in little-endian byte order.
26 Little = b'l',
27}
28
29assert_impl_all!(EndianSig: Send, Sync, Unpin);
30
31// Such a shame I've to do this manually
32impl TryFrom<u8> for EndianSig {
33 type Error = Error;
34
35 fn try_from(val: u8) -> Result<EndianSig, Error> {
36 match val {
37 b'B' => Ok(EndianSig::Big),
38 b'l' => Ok(EndianSig::Little),
39 _ => Err(Error::IncorrectEndian),
40 }
41 }
42}
43
44#[cfg(target_endian = "big")]
45/// Signature of the target's native endian.
46pub const NATIVE_ENDIAN_SIG: EndianSig = EndianSig::Big;
47#[cfg(target_endian = "little")]
48/// Signature of the target's native endian.
49pub const NATIVE_ENDIAN_SIG: EndianSig = EndianSig::Little;
50
51/// Message header representing the D-Bus type of the message.
52#[repr(u8)]
53#[derive(Debug, Copy, Clone, Deserialize_repr, PartialEq, Eq, Hash, Serialize_repr, Type)]
54pub enum MessageType {
55 /// Invalid message type. All unknown types on received messages are treated as invalid.
56 Invalid = 0,
57 /// Method call. This message type may prompt a reply (and typically does).
58 MethodCall = 1,
59 /// A reply to a method call.
60 MethodReturn = 2,
61 /// An error in response to a method call.
62 Error = 3,
63 /// Signal emission.
64 Signal = 4,
65}
66
67assert_impl_all!(MessageType: Send, Sync, Unpin);
68
69// Such a shame I've to do this manually
70impl From<u8> for MessageType {
71 fn from(val: u8) -> MessageType {
72 match val {
73 1 => MessageType::MethodCall,
74 2 => MessageType::MethodReturn,
75 3 => MessageType::Error,
76 4 => MessageType::Signal,
77 _ => MessageType::Invalid,
78 }
79 }
80}
81
82/// Pre-defined flags that can be passed in Message header.
83#[bitflags]
84#[repr(u8)]
85#[derive(Debug, Copy, Clone, PartialEq, Eq, Type)]
86pub enum MessageFlags {
87 /// This message does not expect method return replies or error replies, even if it is of a
88 /// type that can have a reply; the reply should be omitted.
89 ///
90 /// Note that `MessageType::MethodCall` is the only message type currently defined in the
91 /// specification that can expect a reply, so the presence or absence of this flag in the other
92 /// three message types that are currently documented is meaningless: replies to those message
93 /// types should not be sent, whether this flag is present or not.
94 NoReplyExpected = 0x1,
95 /// The bus must not launch an owner for the destination name in response to this message.
96 NoAutoStart = 0x2,
97 /// This flag may be set on a method call message to inform the receiving side that the caller
98 /// is prepared to wait for interactive authorization, which might take a considerable time to
99 /// complete. For instance, if this flag is set, it would be appropriate to query the user for
100 /// passwords or confirmation via Polkit or a similar framework.
101 AllowInteractiveAuth = 0x4,
102}
103
104assert_impl_all!(MessageFlags: Send, Sync, Unpin);
105
106#[derive(Clone, Debug)]
107struct SerialNum(OnceCell<u32>);
108
109// FIXME: Can use `zvariant::Type` macro after `zvariant` provides a blanket implementation for
110// `OnceCell<T>`.
111impl zvariant::Type for SerialNum {
112 fn signature() -> Signature<'static> {
113 u32::signature()
114 }
115}
116
117// Unfortunately Serde doesn't provide a blanket impl. for `Cell<T>` so we have to implement
118// manually.
119//
120// https://github.com/serde-rs/serde/issues/1952
121impl Serialize for SerialNum {
122 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
123 where
124 S: serde::Serializer,
125 {
126 // `Message` serializes the PrimaryHeader at construct time before the user has the
127 // time to tweak it and set a correct serial_num. We should probably avoid this but
128 // for now, let's silently use a default serialized value.
129 self.0
130 .get()
131 .cloned()
132 .unwrap_or_default()
133 .serialize(serializer)
134 }
135}
136
137impl<'de> Deserialize<'de> for SerialNum {
138 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
139 where
140 D: serde::Deserializer<'de>,
141 {
142 Ok(SerialNum(OnceCell::from(u32::deserialize(deserializer)?)))
143 }
144}
145
146/// The primary message header, which is present in all D-Bus messages.
147///
148/// This header contains all the essential information about a message, regardless of its type.
149#[derive(Clone, Debug, Serialize, Deserialize, Type)]
150pub struct MessagePrimaryHeader {
151 endian_sig: EndianSig,
152 msg_type: MessageType,
153 flags: BitFlags<MessageFlags>,
154 protocol_version: u8,
155 body_len: u32,
156 serial_num: SerialNum,
157}
158
159assert_impl_all!(MessagePrimaryHeader: Send, Sync, Unpin);
160
161impl MessagePrimaryHeader {
162 /// Create a new `MessagePrimaryHeader` instance.
163 pub fn new(msg_type: MessageType, body_len: u32) -> Self {
164 Self {
165 endian_sig: NATIVE_ENDIAN_SIG,
166 msg_type,
167 flags: BitFlags::empty(),
168 protocol_version: 1,
169 body_len,
170 serial_num: SerialNum(OnceCell::new()),
171 }
172 }
173
174 pub(crate) fn read(buf: &[u8]) -> Result<(MessagePrimaryHeader, u32), Error> {
175 let ctx = EncodingContext::<byteorder::NativeEndian>::new_dbus(0);
176 let primary_header = zvariant::from_slice(buf, ctx)?;
177 let fields_len = zvariant::from_slice(&buf[PRIMARY_HEADER_SIZE..], ctx)?;
178 Ok((primary_header, fields_len))
179 }
180
181 /// D-Bus code for bytorder encoding of the message.
182 pub fn endian_sig(&self) -> EndianSig {
183 self.endian_sig
184 }
185
186 /// Set the D-Bus code for bytorder encoding of the message.
187 pub fn set_endian_sig(&mut self, sig: EndianSig) {
188 self.endian_sig = sig;
189 }
190
191 /// The message type.
192 pub fn msg_type(&self) -> MessageType {
193 self.msg_type
194 }
195
196 /// Set the message type.
197 pub fn set_msg_type(&mut self, msg_type: MessageType) {
198 self.msg_type = msg_type;
199 }
200
201 /// The message flags.
202 pub fn flags(&self) -> BitFlags<MessageFlags> {
203 self.flags
204 }
205
206 /// Set the message flags.
207 pub fn set_flags(&mut self, flags: BitFlags<MessageFlags>) {
208 self.flags = flags;
209 }
210
211 /// The major version of the protocol the message is compliant to.
212 ///
213 /// Currently only `1` is valid.
214 pub fn protocol_version(&self) -> u8 {
215 self.protocol_version
216 }
217
218 /// Set the major version of the protocol the message is compliant to.
219 ///
220 /// Currently only `1` is valid.
221 pub fn set_protocol_version(&mut self, version: u8) {
222 self.protocol_version = version;
223 }
224
225 /// The byte length of the message body.
226 pub fn body_len(&self) -> u32 {
227 self.body_len
228 }
229
230 /// Set the byte length of the message body.
231 pub fn set_body_len(&mut self, len: u32) {
232 self.body_len = len;
233 }
234
235 /// The serial number of the message (if set).
236 ///
237 /// This is used to match a reply to a method call.
238 ///
239 /// **Note:** There is no setter provided for this in the public API since this is set by the
240 /// [`Connection`](struct.Connection.html) the message is sent over.
241 pub fn serial_num(&self) -> Option<&u32> {
242 self.serial_num.0.get()
243 }
244
245 pub(crate) fn serial_num_or_init<F>(&mut self, f: F) -> &u32
246 where
247 F: FnOnce() -> u32,
248 {
249 self.serial_num.0.get_or_init(f)
250 }
251}
252
253/// The message header, containing all the metadata about the message.
254///
255/// This includes both the [`MessagePrimaryHeader`] and [`MessageFields`].
256///
257/// [`MessagePrimaryHeader`]: struct.MessagePrimaryHeader.html
258/// [`MessageFields`]: struct.MessageFields.html
259#[derive(Debug, Clone, Serialize, Deserialize, Type)]
260pub struct MessageHeader<'m> {
261 primary: MessagePrimaryHeader,
262 #[serde(borrow)]
263 fields: MessageFields<'m>,
264}
265
266assert_impl_all!(MessageHeader<'_>: Send, Sync, Unpin);
267
268macro_rules! get_field {
269 ($self:ident, $kind:ident) => {
270 get_field!($self, $kind, (|v| v))
271 };
272 ($self:ident, $kind:ident, $closure:tt) => {
273 #[allow(clippy::redundant_closure_call)]
274 match $self.fields().get_field(MessageFieldCode::$kind) {
275 Some(MessageField::$kind(value)) => Ok(Some($closure(value))),
276 Some(_) => Err(Error::InvalidField),
277 None => Ok(None),
278 }
279 };
280}
281
282macro_rules! get_field_u32 {
283 ($self:ident, $kind:ident) => {
284 get_field!($self, $kind, (|v: &u32| *v))
285 };
286}
287
288impl<'m> MessageHeader<'m> {
289 /// Create a new `MessageHeader` instance.
290 pub fn new(primary: MessagePrimaryHeader, fields: MessageFields<'m>) -> Self {
291 Self { primary, fields }
292 }
293
294 /// Get a reference to the primary header.
295 pub fn primary(&self) -> &MessagePrimaryHeader {
296 &self.primary
297 }
298
299 /// Get a mutable reference to the primary header.
300 pub fn primary_mut(&mut self) -> &mut MessagePrimaryHeader {
301 &mut self.primary
302 }
303
304 /// Get the primary header, consuming `self`.
305 pub fn into_primary(self) -> MessagePrimaryHeader {
306 self.primary
307 }
308
309 /// Get a reference to the message fields.
310 pub fn fields<'s>(&'s self) -> &'s MessageFields<'m> {
311 &self.fields
312 }
313
314 /// Get a mutable reference to the message fields.
315 pub fn fields_mut<'s>(&'s mut self) -> &'s mut MessageFields<'m> {
316 &mut self.fields
317 }
318
319 /// Get the message fields, consuming `self`.
320 pub fn into_fields(self) -> MessageFields<'m> {
321 self.fields
322 }
323
324 /// The message type
325 pub fn message_type(&self) -> Result<MessageType, Error> {
326 Ok(self.primary().msg_type())
327 }
328
329 /// The object to send a call to, or the object a signal is emitted from.
330 pub fn path<'s>(&'s self) -> Result<Option<&ObjectPath<'m>>, Error> {
331 get_field!(self, Path)
332 }
333
334 /// The interface to invoke a method call on, or that a signal is emitted from.
335 pub fn interface<'s>(&'s self) -> Result<Option<&InterfaceName<'m>>, Error> {
336 get_field!(self, Interface)
337 }
338
339 /// The member, either the method name or signal name.
340 pub fn member<'s>(&'s self) -> Result<Option<&MemberName<'m>>, Error> {
341 get_field!(self, Member)
342 }
343
344 /// The name of the error that occurred, for errors.
345 pub fn error_name<'s>(&'s self) -> Result<Option<&ErrorName<'m>>, Error> {
346 get_field!(self, ErrorName)
347 }
348
349 /// The serial number of the message this message is a reply to.
350 pub fn reply_serial(&self) -> Result<Option<u32>, Error> {
351 get_field_u32!(self, ReplySerial)
352 }
353
354 /// The name of the connection this message is intended for.
355 pub fn destination<'s>(&'s self) -> Result<Option<&BusName<'m>>, Error> {
356 get_field!(self, Destination)
357 }
358
359 /// Unique name of the sending connection.
360 pub fn sender<'s>(&'s self) -> Result<Option<&UniqueName<'m>>, Error> {
361 get_field!(self, Sender)
362 }
363
364 /// The signature of the message body.
365 pub fn signature(&self) -> Result<Option<&Signature<'m>>, Error> {
366 get_field!(self, Signature)
367 }
368
369 /// The number of Unix file descriptors that accompany the message.
370 pub fn unix_fds(&self) -> Result<Option<u32>, Error> {
371 get_field_u32!(self, UnixFDs)
372 }
373}
374
375#[cfg(test)]
376mod tests {
377 use crate::{MessageField, MessageFields, MessageHeader, MessagePrimaryHeader, MessageType};
378
379 use std::{
380 convert::{TryFrom, TryInto},
381 error::Error,
382 result::Result,
383 };
384 use test_log::test;
385 use zbus_names::{InterfaceName, MemberName};
386 use zvariant::{ObjectPath, Signature};
387
388 #[test]
389 fn header() -> Result<(), Box<dyn Error>> {
390 let path = ObjectPath::try_from("/some/path")?;
391 let iface = InterfaceName::try_from("some.interface")?;
392 let member = MemberName::try_from("Member")?;
393 let mut f = MessageFields::new();
394 f.add(MessageField::Path(path.clone()));
395 f.add(MessageField::Interface(iface.clone()));
396 f.add(MessageField::Member(member.clone()));
397 f.add(MessageField::Sender(":1.84".try_into()?));
398 let h = MessageHeader::new(MessagePrimaryHeader::new(MessageType::Signal, 77), f);
399
400 assert_eq!(h.message_type()?, MessageType::Signal);
401 assert_eq!(h.path()?, Some(&path));
402 assert_eq!(h.interface()?, Some(&iface));
403 assert_eq!(h.member()?, Some(&member));
404 assert_eq!(h.error_name()?, None);
405 assert_eq!(h.destination()?, None);
406 assert_eq!(h.reply_serial()?, None);
407 assert_eq!(h.sender()?.unwrap(), ":1.84");
408 assert_eq!(h.signature()?, None);
409 assert_eq!(h.unix_fds()?, None);
410
411 let mut f = MessageFields::new();
412 f.add(MessageField::ErrorName("org.zbus.Error".try_into()?));
413 f.add(MessageField::Destination(":1.11".try_into()?));
414 f.add(MessageField::ReplySerial(88));
415 f.add(MessageField::Signature(Signature::from_str_unchecked(
416 "say",
417 )));
418 f.add(MessageField::UnixFDs(12));
419 let h = MessageHeader::new(MessagePrimaryHeader::new(MessageType::MethodReturn, 77), f);
420
421 assert_eq!(h.message_type()?, MessageType::MethodReturn);
422 assert_eq!(h.path()?, None);
423 assert_eq!(h.interface()?, None);
424 assert_eq!(h.member()?, None);
425 assert_eq!(h.error_name()?.unwrap(), "org.zbus.Error");
426 assert_eq!(h.destination()?.unwrap(), ":1.11");
427 assert_eq!(h.reply_serial()?, Some(88));
428 assert_eq!(h.sender()?, None);
429 assert_eq!(h.signature()?, Some(&Signature::from_str_unchecked("say")));
430 assert_eq!(h.unix_fds()?, Some(12));
431
432 Ok(())
433 }
434}
435