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