use std::collections::BTreeSet;
use bytes::{BytesMut, BufMut};
use num_traits::{FromPrimitive, ToPrimitive};
use crate::{Value, DecodeError, EncodeError};
use crate::header::Header;
use crate::value::{decode_algin, encode_algin};
#[derive(Debug, Clone, FromPrimitive, ToPrimitive)]
pub enum MessageType {
MethodCall = 1,
MethodReturn = 2,
Error = 3,
Signal = 4
}
bitflags! {
pub struct MessageFlags: u8 {
const NO_REPLY_EXPECTED = 0x01;
const NO_AUTO_START = 0x02;
const ALLOW_INTERACTIVE_AUTHORIZATION = 0x04;
}
}
#[derive(Debug, Clone)]
pub struct Message {
header: MessageHeader,
body: Vec<Value>,
}
impl Message {
pub fn decode(buf: &BytesMut, offset: &mut usize)
-> Result<Message, DecodeError> {
if buf.len() < 16 {
return Err(DecodeError::TooShort)
}
let is_le = match buf[*offset] {
0x6c => true,
0x42 => false,
_ => return Err(DecodeError::Endianness)
};
*offset += 1;
let signature = "yyyuua(yv)";
let mut header = Value::decode(buf, offset, is_le, 0, 0, signature)?;
if header.len() != 6 {
return Err(DecodeError::Header);
}
let message_type = if let Value::Byte(b) = header.remove(0) {
if let Some(message_type) = MessageType::from_u8(b) {
message_type
} else {
return Err(DecodeError::Header);
}
} else {
return Err(DecodeError::Header);
};
let message_flags = if let Value::Byte(b) = header.remove(0) {
if let Some(message_flags) = MessageFlags::from_bits(b) {
message_flags
} else {
return Err(DecodeError::Header);
}
} else {
return Err(DecodeError::Header);
};
let version = if let Value::Byte(b) = header.remove(0) {
b
} else {
return Err(DecodeError::Header);
};
let body_length = if let Value::Uint32(u) = header.remove(0) {
u
} else {
return Err(DecodeError::Header);
};
let serial = if let Value::Uint32(u) = header.remove(0) {
u
} else {
return Err(DecodeError::Header);
};
let mut headers = BTreeSet::new();
if let Value::Array(a, sig) = header.remove(0) {
if sig != "(yv)" {
return Err(DecodeError::Header)
}
for h in a {
headers.insert(Header::from(h)?);
}
} else {
return Err(DecodeError::Header)
}
decode_algin(buf, offset, 8)?;
let body = if body_length == 0 {
Vec::<Value>::new()
} else {
let mut signature = None;
for h in &headers {
if let Header::Signature(s) = h {
signature = Some(s);
break;
}
}
if let Some(s) = signature {
Value::decode(buf, offset, is_le, 0, 0,s)?
} else {
return Err(DecodeError::BodySignatureMissing)
}
};
let header = MessageHeader {
is_le,
message_type,
message_flags,
version,
serial,
headers
};
Ok(Message{header, body})
}
pub fn encode(&self, buf: &mut BytesMut) -> Result<(), EncodeError> {
buf.reserve(16);
let header = &self.header;
let is_le = header.is_le;
if is_le {
buf.put_u8(0x6c)
} else {
buf.put_u8(0x42)
}
buf.put_u8(header.message_type.to_u8().unwrap());
buf.put_u8(header.message_flags.bits);
buf.put_u8(header.version);
let mut buf_body = BytesMut::with_capacity(1024);
let mut sig_body = String::new();
for v in &self.body {
v.get_signature(&mut sig_body);
v.encode(&mut buf_body, header.is_le)?;
}
let mut headers = header.headers.clone();
if !sig_body.is_empty() {
headers.insert(Header::Signature(sig_body));
}
if is_le {
buf.put_u32_le(buf_body.len() as u32);
buf.put_u32_le(header.serial);
} else {
buf.put_u32(buf_body.len() as u32);
buf.put_u32(header.serial);
}
let headers = headers.into_iter().map(|h| h.into_value()).collect();
let headers = Value::Array(headers, "(yv)".to_string());
headers.encode(buf, is_le)?;
encode_algin(buf, 8);
buf.extend(buf_body);
Ok(())
}
pub fn method_call(destination: &str, path: &str, interface: &str,
member: &str) -> Message {
let mut headers = BTreeSet::new();
headers.insert(Header::Destination(destination.to_string()));
headers.insert(Header::Path(path.to_string()));
headers.insert(Header::Interface(interface.to_string()));
headers.insert(Header::Member(member.to_string()));
let header = MessageHeader {
is_le: true,
message_type: MessageType::MethodCall,
message_flags: MessageFlags::empty(),
version: 1,
serial: 0,
headers,
};
Message {
header,
body: Vec::new()
}
}
pub fn signal(path: &str, interface: &str, member: &str) -> Message {
let mut headers = BTreeSet::new();
headers.insert(Header::Path(path.to_string()));
headers.insert(Header::Interface(interface.to_string()));
headers.insert(Header::Member(member.to_string()));
let header = MessageHeader {
is_le: true,
message_type: MessageType::Signal,
message_flags: MessageFlags::NO_REPLY_EXPECTED,
version: 1,
serial: 0,
headers
};
Message {
header,
body: Vec::new()
}
}
pub fn get_serial(&self) -> u32 {
self.header.get_serial()
}
pub fn set_serial(&mut self, serial: u32) {
self.header.serial = serial;
}
pub fn get_reply_serial(&self) -> Option<u32> {
self.header.get_reply_serial()
}
pub fn get_path(&self) -> Option<&String> {
self.header.get_path()
}
pub fn has_interface(&self) -> bool {
self.header.has_interface()
}
pub fn get_interface(&self) -> Option<&String> {
self.header.get_interface()
}
pub fn has_member(&self) -> bool {
self.header.has_member()
}
pub fn get_member(&self) -> Option<&String> {
self.header.get_member()
}
pub fn has_error_name(&self) -> bool {
self.header.has_error_name()
}
pub fn get_error_name(&self) -> Option<&String> {
self.header.get_error_name()
}
pub fn get_sender(&self) -> Option<&String> {
self.header.get_sender()
}
pub fn get_destination(&self) -> Option<&String> {
self.header.get_destination()
}
pub fn has_signature(&self) -> bool {
self.header.has_signature()
}
pub fn get_signature(&self) -> Option<&String> {
self.header.get_signature()
}
pub fn add_value(&mut self, value: Value) {
self.body.push(value);
}
pub fn method_return(&self) -> Result<Message, ()> {
self.header.method_return()
}
pub fn unknown_path(&self) -> Result<Message, ()> {
self.header.unknown_path()
}
pub fn unknown_interface(&self) -> Result<Message, ()> {
self.header.unknown_interface()
}
pub fn unknown_method(&self) -> Result<Message, ()> {
self.header.unknown_method()
}
pub fn invalid_args(&self, reason: &str) -> Result<Message, ()> {
self.error("org.freedesktop.DBus.Error.InvalidArgs".to_string(),
reason.to_string())
}
pub fn error(&self, name: String, message: String) -> Result<Message, ()> {
self.header.error(name, message)
}
pub fn get_body(&self) -> &Vec<Value> {
&self.body
}
pub fn get_type(&self) -> MessageType {
self.header.message_type.clone()
}
pub fn split(self) -> (MessageHeader, Vec<Value>) {
(self.header, self.body)
}
}
#[derive(Debug, Clone)]
pub struct MessageHeader {
pub is_le: bool,
pub message_type: MessageType,
pub message_flags: MessageFlags,
pub version: u8,
pub serial: u32,
pub headers: BTreeSet<Header>
}
impl MessageHeader {
pub fn get_path(&self) -> Option<&String> {
for h in &self.headers {
if let Header::Path(path) = h {
return Some(path)
}
}
None
}
pub fn get_interface(&self) -> Option<&String> {
for h in &self.headers {
if let Header::Interface(interface) = h {
return Some(interface)
}
}
None
}
pub fn has_interface(&self) -> bool {
for h in &self.headers {
if let Header::Interface(_) = h {
return true
}
}
false
}
pub fn get_member(&self) -> Option<&String> {
for h in &self.headers {
if let Header::Member(member) = h {
return Some(member)
}
}
None
}
pub fn has_member(&self) -> bool {
for h in &self.headers {
if let Header::Member(_) = h {
return true
}
}
false
}
pub fn get_error_name(&self) -> Option<&String> {
for h in &self.headers {
if let Header::ErrorName(error_name) = h {
return Some(error_name)
}
}
None
}
pub fn has_error_name(&self) -> bool {
for h in &self.headers {
if let Header::ErrorName(_) = h {
return true
}
}
false
}
pub fn get_destination(&self) -> Option<&String> {
for h in &self.headers {
if let Header::Destination(destination) = h {
return Some(destination)
}
}
None
}
pub fn get_sender(&self) -> Option<&String> {
for h in &self.headers {
if let Header::Sender(sender) = h {
return Some(sender)
}
}
None
}
pub fn get_serial(&self) -> u32 {
self.serial
}
pub fn get_reply_serial(&self) -> Option<u32> {
for h in &self.headers {
if let Header::ReplySerial(serial) = h {
return Some(*serial)
}
}
None
}
pub fn get_signature(&self) -> Option<&String> {
for h in &self.headers {
if let Header::Signature(signature) = h {
return Some(signature)
}
}
None
}
pub fn has_signature(&self) -> bool {
for h in &self.headers {
if let Header::Signature(_) = h {
return true
}
}
false
}
pub fn method_return(&self) -> Result<Message, ()> {
if let MessageType::MethodCall = self.message_type {
let message_type = MessageType::MethodReturn;
let message_flags = MessageFlags::NO_REPLY_EXPECTED;
let mut headers = BTreeSet::<Header>::new();
if let Some(sender) = self.get_sender() {
headers.insert(Header::Destination(sender.clone()));
} else {
return Err(())
}
if let Some(destination) = self.get_destination() {
headers.insert(Header::Sender(destination.clone()));
} else {
return Err(())
}
headers.insert(Header::ReplySerial(self.get_serial()));
let header = MessageHeader {
is_le: self.is_le,
message_type,
message_flags,
version: 1,
serial: 0,
headers
};
Ok(Message {
header,
body: Vec::new()
})
} else {
Err(())
}
}
pub fn unknown_path(&self) -> Result<Message, ()> {
if let Some(path) = self.get_path() {
let message = format!("does not have a path {}", path);
self.error("org.freedesktop.DBus.Error.UnknownPath".to_string(),
message)
} else {
Err(())
}
}
pub fn unknown_interface(&self) -> Result<Message, ()> {
if let Some(interface) = self.get_interface() {
let message = format!("does not have an interface {}", interface);
self.error(
"org.freedesktop.DBus.Error.UnknownInterface".to_string(),
message)
} else {
Err(())
}
}
pub fn unknown_method(&self) -> Result<Message, ()> {
if let Some(member) = self.get_member() {
let message = format!("does not have a member {}", member);
self.error("org.freedesktop.DBus.Error.UnknownMethod".to_string(),
message)
} else {
Err(())
}
}
pub fn invalid_args(&self, reason: &str) -> Result<Message, ()> {
self.error("org.freedesktop.DBus.Error.InvalidArgs".to_string(),
reason.to_string())
}
pub fn error(&self, name: String, message: String) -> Result<Message, ()> {
let message_type = MessageType::Error;
let message_flags = MessageFlags::NO_REPLY_EXPECTED;
let mut headers = BTreeSet::<Header>::new();
if let Some(sender) = self.get_sender() {
headers.insert(Header::Destination(sender.clone()));
} else {
return Err(())
}
if let Some(destination) = self.get_destination() {
headers.insert(Header::Sender(destination.clone()));
} else {
return Err(())
}
headers.insert(Header::ReplySerial(self.get_serial()));
headers.insert(Header::ErrorName(name));
let header = MessageHeader {
is_le: self.is_le,
message_type,
message_flags,
version: 1,
serial: 0,
headers,
};
Ok(Message {
header,
body: vec![Value::String(message)]
})
}
}