1 | use std::convert::TryFrom; |
2 | |
3 | use enumflags2::{bitflags , BitFlags}; |
4 | use once_cell::sync::OnceCell; |
5 | use serde::{Deserialize, Serialize}; |
6 | use serde_repr::{Deserialize_repr, Serialize_repr}; |
7 | |
8 | use static_assertions::assert_impl_all; |
9 | use zbus_names::{BusName, ErrorName, InterfaceName, MemberName, UniqueName}; |
10 | use zvariant::{EncodingContext, ObjectPath, Signature, Type}; |
11 | |
12 | use crate::{Error, MessageField, MessageFieldCode, MessageFields}; |
13 | |
14 | pub(crate) const PRIMARY_HEADER_SIZE: usize = 12; |
15 | pub(crate) const MIN_MESSAGE_SIZE: usize = PRIMARY_HEADER_SIZE + 4; |
16 | pub(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)] |
21 | pub 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 | |
29 | assert_impl_all!(EndianSig: Send, Sync, Unpin); |
30 | |
31 | // Such a shame I've to do this manually |
32 | impl 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. |
46 | pub const NATIVE_ENDIAN_SIG: EndianSig = EndianSig::Big; |
47 | #[cfg (target_endian = "little" )] |
48 | /// Signature of the target's native endian. |
49 | pub 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)] |
54 | pub 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 | |
67 | assert_impl_all!(MessageType: Send, Sync, Unpin); |
68 | |
69 | // Such a shame I've to do this manually |
70 | impl 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)] |
86 | pub 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 | |
104 | assert_impl_all!(MessageFlags: Send, Sync, Unpin); |
105 | |
106 | #[derive (Clone, Debug)] |
107 | struct SerialNum(OnceCell<u32>); |
108 | |
109 | // FIXME: Can use `zvariant::Type` macro after `zvariant` provides a blanket implementation for |
110 | // `OnceCell<T>`. |
111 | impl 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 |
121 | impl 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 | |
137 | impl<'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)] |
150 | pub 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 | |
159 | assert_impl_all!(MessagePrimaryHeader: Send, Sync, Unpin); |
160 | |
161 | impl 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)] |
260 | pub struct MessageHeader<'m> { |
261 | primary: MessagePrimaryHeader, |
262 | #[serde(borrow)] |
263 | fields: MessageFields<'m>, |
264 | } |
265 | |
266 | assert_impl_all!(MessageHeader<'_>: Send, Sync, Unpin); |
267 | |
268 | macro_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 | |
282 | macro_rules! get_field_u32 { |
283 | ($self:ident, $kind:ident) => { |
284 | get_field!($self, $kind, (|v: &u32| *v)) |
285 | }; |
286 | } |
287 | |
288 | impl<'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)] |
376 | mod 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 | |