zbus/message/
header.rs

1use std::{
2    num::NonZeroU32,
3    sync::atomic::{AtomicU32, Ordering::Relaxed},
4};
5
6use enumflags2::{bitflags, BitFlags};
7use serde::{Deserialize, Serialize};
8use serde_repr::{Deserialize_repr, Serialize_repr};
9
10use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, UniqueName};
11use zvariant::{
12    serialized::{self, Context},
13    Endian, ObjectPath, Signature, Type as VariantType,
14};
15
16use crate::{message::Fields, Error};
17
18pub(crate) const PRIMARY_HEADER_SIZE: usize = 12;
19pub(crate) const MIN_MESSAGE_SIZE: usize = PRIMARY_HEADER_SIZE + 4;
20pub(crate) const MAX_MESSAGE_SIZE: usize = 128 * 1024 * 1024; // 128 MiB
21
22/// D-Bus code for endianness.
23#[repr(u8)]
24#[derive(Debug, Copy, Clone, Deserialize_repr, PartialEq, Eq, Serialize_repr, VariantType)]
25pub enum EndianSig {
26    /// The D-Bus message is in big-endian (network) byte order.
27    Big = b'B',
28
29    /// The D-Bus message is in little-endian byte order.
30    Little = b'l',
31}
32
33// Such a shame I've to do this manually
34impl TryFrom<u8> for EndianSig {
35    type Error = Error;
36
37    fn try_from(val: u8) -> Result<EndianSig, Error> {
38        match val {
39            b'B' => Ok(EndianSig::Big),
40            b'l' => Ok(EndianSig::Little),
41            _ => Err(Error::IncorrectEndian),
42        }
43    }
44}
45
46#[cfg(target_endian = "big")]
47/// Signature of the target's native endian.
48pub const NATIVE_ENDIAN_SIG: EndianSig = EndianSig::Big;
49#[cfg(target_endian = "little")]
50/// Signature of the target's native endian.
51pub const NATIVE_ENDIAN_SIG: EndianSig = EndianSig::Little;
52
53impl From<Endian> for EndianSig {
54    fn from(endian: Endian) -> Self {
55        match endian {
56            Endian::Little => EndianSig::Little,
57            Endian::Big => EndianSig::Big,
58        }
59    }
60}
61
62impl From<EndianSig> for Endian {
63    fn from(endian_sig: EndianSig) -> Self {
64        match endian_sig {
65            EndianSig::Little => Endian::Little,
66            EndianSig::Big => Endian::Big,
67        }
68    }
69}
70
71/// Message header representing the D-Bus type of the message.
72#[repr(u8)]
73#[derive(
74    Debug, Copy, Clone, Deserialize_repr, PartialEq, Eq, Hash, Serialize_repr, VariantType,
75)]
76pub enum Type {
77    /// Method call. This message type may prompt a reply (and typically does).
78    MethodCall = 1,
79    /// A reply to a method call.
80    MethodReturn = 2,
81    /// An error in response to a method call.
82    Error = 3,
83    /// Signal emission.
84    Signal = 4,
85}
86
87/// Pre-defined flags that can be passed in message headers.
88#[bitflags]
89#[repr(u8)]
90#[derive(Debug, Copy, Clone, PartialEq, Eq, VariantType)]
91pub enum Flags {
92    /// This message does not expect method return replies or error replies, even if it is of a
93    /// type that can have a reply; the reply should be omitted.
94    ///
95    /// Note that `Type::MethodCall` is the only message type currently defined in the
96    /// specification that can expect a reply, so the presence or absence of this flag in the other
97    /// three message types that are currently documented is meaningless: replies to those message
98    /// types should not be sent, whether this flag is present or not.
99    NoReplyExpected = 0x1,
100    /// The bus must not launch an owner for the destination name in response to this message.
101    NoAutoStart = 0x2,
102    /// This flag may be set on a method call message to inform the receiving side that the caller
103    /// is prepared to wait for interactive authorization, which might take a considerable time to
104    /// complete. For instance, if this flag is set, it would be appropriate to query the user for
105    /// passwords or confirmation via Polkit or a similar framework.
106    AllowInteractiveAuth = 0x4,
107}
108
109/// The primary message header, which is present in all D-Bus messages.
110///
111/// This header contains all the essential information about a message, regardless of its type.
112#[derive(Clone, Debug, Serialize, Deserialize, VariantType)]
113pub struct PrimaryHeader {
114    endian_sig: EndianSig,
115    msg_type: Type,
116    flags: BitFlags<Flags>,
117    protocol_version: u8,
118    body_len: u32,
119    serial_num: NonZeroU32,
120}
121
122impl PrimaryHeader {
123    /// Create a new `PrimaryHeader` instance.
124    pub fn new(msg_type: Type, body_len: u32) -> Self {
125        let mut serial_num = SERIAL_NUM.fetch_add(1, Relaxed);
126        if serial_num == 0 {
127            serial_num = SERIAL_NUM.fetch_add(1, Relaxed);
128        }
129
130        Self {
131            endian_sig: NATIVE_ENDIAN_SIG,
132            msg_type,
133            flags: BitFlags::empty(),
134            protocol_version: 1,
135            body_len,
136            serial_num: serial_num.try_into().unwrap(),
137        }
138    }
139
140    pub(crate) fn read(buf: &[u8]) -> Result<(PrimaryHeader, u32), Error> {
141        let endian = Endian::from(EndianSig::try_from(buf[0])?);
142        let ctx = Context::new_dbus(endian, 0);
143        let data = serialized::Data::new(buf, ctx);
144
145        Self::read_from_data(&data)
146    }
147
148    pub(crate) fn read_from_data(
149        data: &serialized::Data<'_, '_>,
150    ) -> Result<(PrimaryHeader, u32), Error> {
151        let (primary_header, size) = data.deserialize()?;
152        assert_eq!(size, PRIMARY_HEADER_SIZE);
153        let (fields_len, _) = data.slice(PRIMARY_HEADER_SIZE..).deserialize()?;
154        Ok((primary_header, fields_len))
155    }
156
157    /// D-Bus code for endian encoding of the message.
158    pub fn endian_sig(&self) -> EndianSig {
159        self.endian_sig
160    }
161
162    /// Set the D-Bus code for endian encoding of the message.
163    pub fn set_endian_sig(&mut self, sig: EndianSig) {
164        self.endian_sig = sig;
165    }
166
167    /// The message type.
168    pub fn msg_type(&self) -> Type {
169        self.msg_type
170    }
171
172    /// Set the message type.
173    pub fn set_msg_type(&mut self, msg_type: Type) {
174        self.msg_type = msg_type;
175    }
176
177    /// The message flags.
178    pub fn flags(&self) -> BitFlags<Flags> {
179        self.flags
180    }
181
182    /// Set the message flags.
183    pub fn set_flags(&mut self, flags: BitFlags<Flags>) {
184        self.flags = flags;
185    }
186
187    /// The major version of the protocol the message is compliant to.
188    ///
189    /// Currently only `1` is valid.
190    pub fn protocol_version(&self) -> u8 {
191        self.protocol_version
192    }
193
194    /// Set the major version of the protocol the message is compliant to.
195    ///
196    /// Currently only `1` is valid.
197    pub fn set_protocol_version(&mut self, version: u8) {
198        self.protocol_version = version;
199    }
200
201    /// The byte length of the message body.
202    pub fn body_len(&self) -> u32 {
203        self.body_len
204    }
205
206    /// Set the byte length of the message body.
207    pub fn set_body_len(&mut self, len: u32) {
208        self.body_len = len;
209    }
210
211    /// The serial number of the message.
212    ///
213    /// This is used to match a reply to a method call.
214    pub fn serial_num(&self) -> NonZeroU32 {
215        self.serial_num
216    }
217
218    /// Set the serial number of the message.
219    ///
220    /// This is used to match a reply to a method call.
221    pub fn set_serial_num(&mut self, serial_num: NonZeroU32) {
222        self.serial_num = serial_num;
223    }
224}
225
226/// The message header, containing all the metadata about the message.
227///
228/// This includes both the [`PrimaryHeader`] and the dynamic fields.
229///
230/// [`PrimaryHeader`]: struct.PrimaryHeader.html
231#[derive(Debug, Clone, Serialize, Deserialize, VariantType)]
232pub struct Header<'m> {
233    primary: PrimaryHeader,
234    #[serde(borrow)]
235    fields: Fields<'m>,
236}
237
238impl<'m> Header<'m> {
239    /// Create a new `Header` instance.
240    pub(super) fn new(primary: PrimaryHeader, fields: Fields<'m>) -> Self {
241        Self { primary, fields }
242    }
243
244    /// Get a reference to the primary header.
245    pub fn primary(&self) -> &PrimaryHeader {
246        &self.primary
247    }
248
249    /// Get a mutable reference to the primary header.
250    pub fn primary_mut(&mut self) -> &mut PrimaryHeader {
251        &mut self.primary
252    }
253
254    /// Get the primary header, consuming `self`.
255    pub fn into_primary(self) -> PrimaryHeader {
256        self.primary
257    }
258
259    /// Get a mutable reference to the message fields.
260    pub(super) fn fields_mut(&mut self) -> &mut Fields<'m> {
261        &mut self.fields
262    }
263
264    /// The message type.
265    pub fn message_type(&self) -> Type {
266        self.primary().msg_type()
267    }
268
269    /// The object to send a call to, or the object a signal is emitted from.
270    pub fn path(&self) -> Option<&ObjectPath<'m>> {
271        self.fields.path.as_ref()
272    }
273
274    /// The interface to invoke a method call on, or that a signal is emitted from.
275    pub fn interface(&self) -> Option<&InterfaceName<'m>> {
276        self.fields.interface.as_ref()
277    }
278
279    /// The member, either the method name or signal name.
280    pub fn member(&self) -> Option<&MemberName<'m>> {
281        self.fields.member.as_ref()
282    }
283
284    /// The name of the error that occurred, for errors.
285    pub fn error_name(&self) -> Option<&ErrorName<'m>> {
286        self.fields.error_name.as_ref()
287    }
288
289    /// The serial number of the message this message is a reply to.
290    pub fn reply_serial(&self) -> Option<NonZeroU32> {
291        self.fields.reply_serial
292    }
293
294    /// The name of the connection this message is intended for.
295    pub fn destination(&self) -> Option<&BusName<'m>> {
296        self.fields.destination.as_ref()
297    }
298
299    /// Unique name of the sending connection.
300    pub fn sender(&self) -> Option<&UniqueName<'m>> {
301        self.fields.sender.as_ref()
302    }
303
304    /// The signature of the message body.
305    pub fn signature(&self) -> &Signature {
306        &self.fields.signature
307    }
308
309    /// The number of Unix file descriptors that accompany the message.
310    pub fn unix_fds(&self) -> Option<u32> {
311        self.fields.unix_fds
312    }
313}
314
315static SERIAL_NUM: AtomicU32 = AtomicU32::new(0);
316
317#[cfg(test)]
318mod tests {
319    use crate::message::{Fields, Header, PrimaryHeader, Type};
320
321    use std::{borrow::Cow, error::Error};
322    use test_log::test;
323    use zbus_names::{InterfaceName, MemberName};
324    use zvariant::{ObjectPath, Signature};
325
326    #[test]
327    fn header() -> Result<(), Box<dyn Error>> {
328        let path = ObjectPath::try_from("/some/path")?;
329        let iface = InterfaceName::try_from("some.interface")?;
330        let member = MemberName::try_from("Member")?;
331        let mut f = Fields::new();
332        f.path = Some(path.clone());
333        f.interface = Some(iface.clone());
334        f.member = Some(member.clone());
335        f.sender = Some(":1.84".try_into()?);
336        let h = Header::new(PrimaryHeader::new(Type::Signal, 77), f);
337
338        assert_eq!(h.message_type(), Type::Signal);
339        assert_eq!(h.path(), Some(&path));
340        assert_eq!(h.interface(), Some(&iface));
341        assert_eq!(h.member(), Some(&member));
342        assert_eq!(h.error_name(), None);
343        assert_eq!(h.destination(), None);
344        assert_eq!(h.reply_serial(), None);
345        assert_eq!(h.sender().unwrap(), ":1.84");
346        assert_eq!(h.signature(), &Signature::Unit);
347        assert_eq!(h.unix_fds(), None);
348
349        let mut f = Fields::new();
350        f.error_name = Some("org.zbus.Error".try_into()?);
351        f.destination = Some(":1.11".try_into()?);
352        f.reply_serial = Some(88.try_into()?);
353        f.signature = Cow::Owned("say".try_into().unwrap());
354        f.unix_fds = Some(12);
355        let h = Header::new(PrimaryHeader::new(Type::MethodReturn, 77), f);
356
357        assert_eq!(h.message_type(), Type::MethodReturn);
358        assert_eq!(h.path(), None);
359        assert_eq!(h.interface(), None);
360        assert_eq!(h.member(), None);
361        assert_eq!(h.error_name().unwrap(), "org.zbus.Error");
362        assert_eq!(h.destination().unwrap(), ":1.11");
363        assert_eq!(h.reply_serial().map(Into::into), Some(88));
364        assert_eq!(h.sender(), None);
365        assert_eq!(h.signature(), &Signature::try_from("say").unwrap());
366        assert_eq!(h.unix_fds(), Some(12));
367
368        Ok(())
369    }
370}