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; #[repr(u8)]
24#[derive(Debug, Copy, Clone, Deserialize_repr, PartialEq, Eq, Serialize_repr, VariantType)]
25pub enum EndianSig {
26 Big = b'B',
28
29 Little = b'l',
31}
32
33impl 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")]
47pub const NATIVE_ENDIAN_SIG: EndianSig = EndianSig::Big;
49#[cfg(target_endian = "little")]
50pub 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#[repr(u8)]
73#[derive(
74 Debug, Copy, Clone, Deserialize_repr, PartialEq, Eq, Hash, Serialize_repr, VariantType,
75)]
76pub enum Type {
77 MethodCall = 1,
79 MethodReturn = 2,
81 Error = 3,
83 Signal = 4,
85}
86
87#[bitflags]
89#[repr(u8)]
90#[derive(Debug, Copy, Clone, PartialEq, Eq, VariantType)]
91pub enum Flags {
92 NoReplyExpected = 0x1,
100 NoAutoStart = 0x2,
102 AllowInteractiveAuth = 0x4,
107}
108
109#[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 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 pub fn endian_sig(&self) -> EndianSig {
159 self.endian_sig
160 }
161
162 pub fn set_endian_sig(&mut self, sig: EndianSig) {
164 self.endian_sig = sig;
165 }
166
167 pub fn msg_type(&self) -> Type {
169 self.msg_type
170 }
171
172 pub fn set_msg_type(&mut self, msg_type: Type) {
174 self.msg_type = msg_type;
175 }
176
177 pub fn flags(&self) -> BitFlags<Flags> {
179 self.flags
180 }
181
182 pub fn set_flags(&mut self, flags: BitFlags<Flags>) {
184 self.flags = flags;
185 }
186
187 pub fn protocol_version(&self) -> u8 {
191 self.protocol_version
192 }
193
194 pub fn set_protocol_version(&mut self, version: u8) {
198 self.protocol_version = version;
199 }
200
201 pub fn body_len(&self) -> u32 {
203 self.body_len
204 }
205
206 pub fn set_body_len(&mut self, len: u32) {
208 self.body_len = len;
209 }
210
211 pub fn serial_num(&self) -> NonZeroU32 {
215 self.serial_num
216 }
217
218 pub fn set_serial_num(&mut self, serial_num: NonZeroU32) {
222 self.serial_num = serial_num;
223 }
224}
225
226#[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 pub(super) fn new(primary: PrimaryHeader, fields: Fields<'m>) -> Self {
241 Self { primary, fields }
242 }
243
244 pub fn primary(&self) -> &PrimaryHeader {
246 &self.primary
247 }
248
249 pub fn primary_mut(&mut self) -> &mut PrimaryHeader {
251 &mut self.primary
252 }
253
254 pub fn into_primary(self) -> PrimaryHeader {
256 self.primary
257 }
258
259 pub(super) fn fields_mut(&mut self) -> &mut Fields<'m> {
261 &mut self.fields
262 }
263
264 pub fn message_type(&self) -> Type {
266 self.primary().msg_type()
267 }
268
269 pub fn path(&self) -> Option<&ObjectPath<'m>> {
271 self.fields.path.as_ref()
272 }
273
274 pub fn interface(&self) -> Option<&InterfaceName<'m>> {
276 self.fields.interface.as_ref()
277 }
278
279 pub fn member(&self) -> Option<&MemberName<'m>> {
281 self.fields.member.as_ref()
282 }
283
284 pub fn error_name(&self) -> Option<&ErrorName<'m>> {
286 self.fields.error_name.as_ref()
287 }
288
289 pub fn reply_serial(&self) -> Option<NonZeroU32> {
291 self.fields.reply_serial
292 }
293
294 pub fn destination(&self) -> Option<&BusName<'m>> {
296 self.fields.destination.as_ref()
297 }
298
299 pub fn sender(&self) -> Option<&UniqueName<'m>> {
301 self.fields.sender.as_ref()
302 }
303
304 pub fn signature(&self) -> &Signature {
306 &self.fields.signature
307 }
308
309 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}