use crate::params::message;
use crate::wire::marshal::traits::{Marshal, SignatureBuffer};
use crate::wire::marshal::MarshalContext;
use crate::wire::unixfd::UnixFd;
use crate::wire::unmarshal::UnmarshalContext;
use crate::wire::validate_raw;
use crate::ByteOrder;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MessageType {
Signal,
Error,
Call,
Reply,
Invalid,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum HeaderFlags {
NoReplyExpected,
NoAutoStart,
AllowInteractiveAuthorization,
}
impl HeaderFlags {
pub fn into_raw(self) -> u8 {
match self {
HeaderFlags::NoReplyExpected => 1,
HeaderFlags::NoAutoStart => 2,
HeaderFlags::AllowInteractiveAuthorization => 4,
}
}
pub fn is_set(self, flags: u8) -> bool {
flags & self.into_raw() == 1
}
pub fn set(self, flags: &mut u8) {
*flags |= self.into_raw()
}
pub fn unset(self, flags: &mut u8) {
*flags &= 0xFF - self.into_raw()
}
pub fn toggle(self, flags: &mut u8) {
if self.is_set(*flags) {
self.unset(flags)
} else {
self.set(flags)
}
}
}
#[derive(Debug, Clone, Default)]
pub struct DynamicHeader {
pub interface: Option<String>,
pub member: Option<String>,
pub object: Option<String>,
pub destination: Option<String>,
pub serial: Option<u32>,
pub sender: Option<String>,
pub signature: Option<String>,
pub error_name: Option<String>,
pub response_serial: Option<u32>,
pub num_fds: Option<u32>,
}
impl DynamicHeader {
pub fn make_error_response<S: Into<String>>(
&self,
error_name: S,
error_msg: Option<String>,
) -> crate::message_builder::MarshalledMessage {
let mut err_resp = crate::message_builder::MarshalledMessage {
typ: MessageType::Reply,
dynheader: DynamicHeader {
interface: None,
member: None,
object: None,
destination: self.sender.clone(),
serial: None,
num_fds: None,
sender: None,
signature: None,
response_serial: self.serial,
error_name: Some(error_name.into()),
},
flags: 0,
body: crate::message_builder::MarshalledMessageBody::new(),
};
if let Some(text) = error_msg {
err_resp.body.push_param(text).unwrap();
}
err_resp
}
pub fn make_response(&self) -> crate::message_builder::MarshalledMessage {
crate::message_builder::MarshalledMessage {
typ: MessageType::Reply,
dynheader: DynamicHeader {
interface: None,
member: None,
object: None,
destination: self.sender.clone(),
serial: None,
num_fds: None,
sender: None,
signature: None,
response_serial: self.serial,
error_name: None,
},
flags: 0,
body: crate::message_builder::MarshalledMessageBody::new(),
}
}
}
#[derive(Default)]
pub struct MessageBuilder {
msg: MarshalledMessage,
}
pub struct CallBuilder {
msg: MarshalledMessage,
}
pub struct SignalBuilder {
msg: MarshalledMessage,
}
impl MessageBuilder {
pub fn new() -> MessageBuilder {
MessageBuilder {
msg: MarshalledMessage::new(),
}
}
pub fn with_byteorder(b: ByteOrder) -> MessageBuilder {
MessageBuilder {
msg: MarshalledMessage::with_byteorder(b),
}
}
pub fn call<S: Into<String>>(mut self, member: S) -> CallBuilder {
self.msg.typ = MessageType::Call;
self.msg.dynheader.member = Some(member.into());
CallBuilder { msg: self.msg }
}
pub fn signal<S1, S2, S3>(mut self, interface: S1, member: S2, object: S3) -> SignalBuilder
where
S1: Into<String>,
S2: Into<String>,
S3: Into<String>,
{
self.msg.typ = MessageType::Signal;
self.msg.dynheader.member = Some(member.into());
self.msg.dynheader.interface = Some(interface.into());
self.msg.dynheader.object = Some(object.into());
SignalBuilder { msg: self.msg }
}
}
impl CallBuilder {
pub fn on<S: Into<String>>(mut self, object_path: S) -> Self {
self.msg.dynheader.object = Some(object_path.into());
self
}
pub fn with_interface<S: Into<String>>(mut self, interface: S) -> Self {
self.msg.dynheader.interface = Some(interface.into());
self
}
pub fn at<S: Into<String>>(mut self, destination: S) -> Self {
self.msg.dynheader.destination = Some(destination.into());
self
}
pub fn build(self) -> MarshalledMessage {
self.msg
}
}
impl SignalBuilder {
pub fn to<S: Into<String>>(mut self, destination: S) -> Self {
self.msg.dynheader.destination = Some(destination.into());
self
}
pub fn build(self) -> MarshalledMessage {
self.msg
}
}
#[derive(Debug)]
pub struct MarshalledMessage {
pub body: MarshalledMessageBody,
pub dynheader: DynamicHeader,
pub typ: MessageType,
pub flags: u8,
}
impl Default for MarshalledMessage {
fn default() -> Self {
Self::new()
}
}
impl MarshalledMessage {
pub fn get_buf(&self) -> &[u8] {
&self.body.buf
}
pub fn get_sig(&self) -> &str {
&self.body.sig
}
pub fn new() -> Self {
MarshalledMessage {
typ: MessageType::Invalid,
dynheader: DynamicHeader::default(),
flags: 0,
body: MarshalledMessageBody::new(),
}
}
pub fn with_byteorder(b: ByteOrder) -> Self {
MarshalledMessage {
typ: MessageType::Invalid,
dynheader: DynamicHeader::default(),
flags: 0,
body: MarshalledMessageBody::with_byteorder(b),
}
}
pub fn reserve(&mut self, additional: usize) {
self.body.reserve(additional)
}
pub fn unmarshall_all<'a, 'e>(self) -> Result<message::Message<'a, 'e>, crate::Error> {
let params = if self.body.sig.is_empty() {
vec![]
} else {
let sigs: Vec<_> = crate::signature::Type::parse_description(&self.body.sig)?;
let (_, params) = crate::wire::unmarshal::unmarshal_body(
self.body.byteorder,
&sigs,
&self.body.buf,
&self.body.raw_fds,
0,
)?;
params
};
Ok(message::Message {
dynheader: self.dynheader,
params,
typ: self.typ,
flags: self.flags,
raw_fds: self.body.raw_fds,
})
}
}
#[derive(Debug)]
pub struct MarshalledMessageBody {
pub(crate) buf: Vec<u8>,
pub(crate) raw_fds: Vec<crate::wire::UnixFd>,
sig: SignatureBuffer,
pub(crate) byteorder: ByteOrder,
}
impl Default for MarshalledMessageBody {
fn default() -> Self {
Self::new()
}
}
pub fn marshal_as_variant<P: Marshal>(
p: P,
byteorder: ByteOrder,
buf: &mut Vec<u8>,
fds: &mut Vec<crate::wire::UnixFd>,
) -> Result<(), crate::Error> {
let mut ctx = MarshalContext {
fds,
buf,
byteorder,
};
let ctx = &mut ctx;
let mut sig_str = String::new();
P::signature().to_str(&mut sig_str);
crate::wire::marshal::base::marshal_base_param(&crate::params::Base::Signature(sig_str), ctx)
.unwrap();
p.marshal(ctx)?;
Ok(())
}
impl MarshalledMessageBody {
pub fn new() -> Self {
MarshalledMessageBody {
buf: Vec::new(),
raw_fds: Vec::new(),
sig: SignatureBuffer::new(),
byteorder: ByteOrder::LittleEndian,
}
}
pub fn with_byteorder(b: ByteOrder) -> Self {
MarshalledMessageBody {
buf: Vec::new(),
raw_fds: Vec::new(),
sig: SignatureBuffer::new(),
byteorder: b,
}
}
pub fn from_parts(
buf: Vec<u8>,
raw_fds: Vec<crate::wire::UnixFd>,
sig: String,
byteorder: ByteOrder,
) -> Self {
let sig = SignatureBuffer::from_string(sig);
Self {
buf,
raw_fds,
sig,
byteorder,
}
}
pub fn get_fds(&self) -> Vec<UnixFd> {
self.raw_fds.clone()
}
pub fn reset(&mut self) {
self.sig.clear();
self.buf.clear();
}
pub fn reserve(&mut self, additional: usize) {
self.buf.reserve(additional)
}
pub fn push_old_param(&mut self, p: &crate::params::Param) -> Result<(), crate::Error> {
let mut ctx = MarshalContext {
buf: &mut self.buf,
fds: &mut self.raw_fds,
byteorder: self.byteorder,
};
let ctx = &mut ctx;
crate::wire::marshal::container::marshal_param(p, ctx)?;
p.sig().to_str(self.sig.to_string_mut());
Ok(())
}
pub fn push_old_params(&mut self, ps: &[crate::params::Param]) -> Result<(), crate::Error> {
for p in ps {
self.push_old_param(p)?;
}
Ok(())
}
fn create_ctx(&mut self) -> MarshalContext {
MarshalContext {
buf: &mut self.buf,
fds: &mut self.raw_fds,
byteorder: self.byteorder,
}
}
pub fn push_param<P: Marshal>(&mut self, p: P) -> Result<(), crate::Error> {
let mut ctx = self.create_ctx();
p.marshal(&mut ctx)?;
P::sig_str(&mut self.sig);
Ok(())
}
pub fn push_param2<P1: Marshal, P2: Marshal>(
&mut self,
p1: P1,
p2: P2,
) -> Result<(), crate::Error> {
self.push_param(p1)?;
self.push_param(p2)?;
Ok(())
}
pub fn push_param3<P1: Marshal, P2: Marshal, P3: Marshal>(
&mut self,
p1: P1,
p2: P2,
p3: P3,
) -> Result<(), crate::Error> {
self.push_param(p1)?;
self.push_param(p2)?;
self.push_param(p3)?;
Ok(())
}
pub fn push_param4<P1: Marshal, P2: Marshal, P3: Marshal, P4: Marshal>(
&mut self,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
) -> Result<(), crate::Error> {
self.push_param(p1)?;
self.push_param(p2)?;
self.push_param(p3)?;
self.push_param(p4)?;
Ok(())
}
pub fn push_param5<P1: Marshal, P2: Marshal, P3: Marshal, P4: Marshal, P5: Marshal>(
&mut self,
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
) -> Result<(), crate::Error> {
self.push_param(p1)?;
self.push_param(p2)?;
self.push_param(p3)?;
self.push_param(p4)?;
self.push_param(p5)?;
Ok(())
}
pub fn push_params<P: Marshal>(&mut self, params: &[P]) -> Result<(), crate::Error> {
for p in params {
self.push_param(p)?;
}
Ok(())
}
pub fn push_variant<P: Marshal>(&mut self, p: P) -> Result<(), crate::Error> {
self.sig.push_static("v");
let mut ctx = self.create_ctx();
p.marshal_as_variant(&mut ctx)
}
pub fn validate(&self) -> Result<(), crate::wire::unmarshal::Error> {
if self.sig.is_empty() && self.buf.is_empty() {
return Ok(());
}
let types = crate::signature::Type::parse_description(&self.sig)?;
let mut used = 0;
for typ in types {
used += validate_raw::validate_marshalled(self.byteorder, used, &self.buf, &typ)
.map_err(|(_, e)| e)?;
}
if used == self.buf.len() {
Ok(())
} else {
Err(crate::wire::unmarshal::Error::NotAllBytesUsed)
}
}
#[inline]
pub fn parser(&self) -> MessageBodyParser {
MessageBodyParser::new(&self)
}
}
#[test]
fn test_marshal_trait() {
let mut body = MarshalledMessageBody::new();
let bytes: &[&[_]] = &[&[4u64]];
body.push_param(bytes).unwrap();
assert_eq!(
vec![12, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0],
body.buf
);
assert_eq!(body.sig.as_str(), "aat");
let mut body = MarshalledMessageBody::new();
let mut map = std::collections::HashMap::new();
map.insert("a", 4u32);
body.push_param(&map).unwrap();
assert_eq!(
vec![12, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, b'a', 0, 0, 0, 4, 0, 0, 0,],
body.buf
);
assert_eq!(body.sig.as_str(), "a{su}");
let mut body = MarshalledMessageBody::new();
body.push_param((11u64, "str", true)).unwrap();
assert_eq!(body.sig.as_str(), "(tsb)");
assert_eq!(
vec![11, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, b's', b't', b'r', 0, 1, 0, 0, 0,],
body.buf
);
struct MyStruct {
x: u64,
y: String,
}
use crate::wire::marshal::traits::Signature;
use crate::wire::marshal::MarshalContext;
impl Signature for &MyStruct {
fn signature() -> crate::signature::Type {
crate::signature::Type::Container(crate::signature::Container::Struct(
crate::signature::StructTypes::new(vec![u64::signature(), String::signature()])
.unwrap(),
))
}
fn alignment() -> usize {
8
}
}
impl Marshal for &MyStruct {
fn marshal(&self, ctx: &mut MarshalContext) -> Result<(), crate::Error> {
ctx.align_to(8);
self.x.marshal(ctx)?;
self.y.marshal(ctx)?;
Ok(())
}
}
let mut body = MarshalledMessageBody::new();
body.push_param(&MyStruct {
x: 100,
y: "A".to_owned(),
})
.unwrap();
assert_eq!(body.sig.as_str(), "(ts)");
assert_eq!(
vec![100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, b'A', 0,],
body.buf
);
let mut body = MarshalledMessageBody::new();
let emptymap: std::collections::HashMap<&str, u32> = std::collections::HashMap::new();
let mut map = std::collections::HashMap::new();
let mut map2 = std::collections::HashMap::new();
map.insert("a", 4u32);
map2.insert("a", &map);
body.push_param(&map2).unwrap();
body.push_param(&emptymap).unwrap();
assert_eq!(body.sig.as_str(), "a{sa{su}}a{su}");
assert_eq!(
vec![
28, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, b'a', 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
0, b'a', 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0
],
body.buf
);
let mut body_iter = MessageBodyParser::new(&body);
type WrongNestedDict =
std::collections::HashMap<String, std::collections::HashMap<String, u64>>;
assert_eq!(
body_iter.get::<WrongNestedDict>().err().unwrap(),
crate::wire::unmarshal::Error::WrongSignature
);
type WrongStruct = (u64, i32, String);
assert_eq!(
body_iter.get::<WrongStruct>().err().unwrap(),
crate::wire::unmarshal::Error::WrongSignature
);
type NestedDict = std::collections::HashMap<String, std::collections::HashMap<String, u32>>;
let newmap2: NestedDict = body_iter.get().unwrap();
assert_eq!(newmap2.len(), 1);
assert_eq!(newmap2.get("a").unwrap().len(), 1);
assert_eq!(*newmap2.get("a").unwrap().get("a").unwrap(), 4);
assert_eq!(
body_iter.get::<WrongNestedDict>().err().unwrap(),
crate::wire::unmarshal::Error::WrongSignature
);
assert_eq!(
body_iter.get::<WrongStruct>().err().unwrap(),
crate::wire::unmarshal::Error::WrongSignature
);
let newemptymap: std::collections::HashMap<&str, u32> = body_iter.get().unwrap();
assert_eq!(newemptymap.len(), 0);
let mut body_iter = body.parser();
assert_eq!(
body_iter.get2::<NestedDict, u16>().unwrap_err(),
crate::wire::unmarshal::Error::WrongSignature
);
assert_eq!(
body_iter
.get3::<NestedDict, std::collections::HashMap<&str, u32>, u32>()
.unwrap_err(),
crate::wire::unmarshal::Error::EndOfMessage
);
let (newmap2, newemptymap): (NestedDict, std::collections::HashMap<&str, u32>) =
body_iter.get2().unwrap();
assert_eq!(newmap2.len(), 1);
assert_eq!(newmap2.get("a").unwrap().len(), 1);
assert_eq!(*newmap2.get("a").unwrap().get("a").unwrap(), 4);
assert_eq!(newemptymap.len(), 0);
assert_eq!(
body_iter.get::<u16>().unwrap_err(),
crate::wire::unmarshal::Error::EndOfMessage
);
let mut body_iter = body.parser();
let newmap2: NestedDict = body_iter.get().unwrap();
let newemptymap = body_iter.get_param().unwrap();
assert_eq!(newmap2.len(), 1);
assert_eq!(newmap2.get("a").unwrap().len(), 1);
assert_eq!(*newmap2.get("a").unwrap().get("a").unwrap(), 4);
use crate::params::Container;
use crate::params::Param;
match newemptymap {
Param::Container(Container::Dict(dict)) => {
assert_eq!(dict.map.len(), 0);
assert_eq!(dict.key_sig, crate::signature::Base::String);
assert_eq!(
dict.value_sig,
crate::signature::Type::Base(crate::signature::Base::Uint32)
);
}
_ => panic!("Expected to get a dict"),
}
assert_eq!(
body_iter.get::<u16>().unwrap_err(),
crate::wire::unmarshal::Error::EndOfMessage
);
}
use crate::wire::unmarshal::traits::Unmarshal;
#[derive(Debug)]
pub struct MessageBodyParser<'body> {
buf_idx: usize,
sig_idx: usize,
sigs: Vec<crate::signature::Type>,
body: &'body MarshalledMessageBody,
}
impl<'ret, 'fds, 'body: 'ret + 'fds> MessageBodyParser<'body> {
pub fn new(body: &'body MarshalledMessageBody) -> Self {
let sigs = match crate::signature::Type::parse_description(&body.sig) {
Ok(sigs) => sigs,
Err(e) => match e {
crate::signature::Error::EmptySignature => Vec::new(),
_ => panic!("MarshalledMessageBody has bad signature: {:?}", e),
},
};
Self {
buf_idx: 0,
sig_idx: 0,
sigs,
body,
}
}
pub fn get_next_sig(&self) -> Option<&crate::signature::Type> {
self.sigs.get(self.sig_idx)
}
pub fn get_left_sigs(&self) -> Option<&[crate::signature::Type]> {
self.sigs.get(self.sig_idx..)
}
pub fn get<T: Unmarshal<'body, 'fds>>(&mut self) -> Result<T, crate::wire::unmarshal::Error> {
if self.sig_idx >= self.sigs.len() {
return Err(crate::wire::unmarshal::Error::EndOfMessage);
}
if self.sigs[self.sig_idx] != T::signature() {
return Err(crate::wire::unmarshal::Error::WrongSignature);
}
let mut ctx = UnmarshalContext {
byteorder: self.body.byteorder,
buf: &self.body.buf,
offset: self.buf_idx,
fds: &self.body.raw_fds,
};
match T::unmarshal(&mut ctx) {
Ok((bytes, res)) => {
self.buf_idx += bytes;
self.sig_idx += 1;
Ok(res)
}
Err(e) => Err(e),
}
}
fn get_mult_helper<T, F>(
&mut self,
count: usize,
get_calls: F,
) -> Result<T, crate::wire::unmarshal::Error>
where
F: FnOnce(&mut Self) -> Result<T, crate::wire::unmarshal::Error>,
{
if self.sig_idx + count > self.sigs.len() {
return Err(crate::wire::unmarshal::Error::EndOfMessage);
}
let start_sig_idx = self.sig_idx;
let start_buf_idx = self.buf_idx;
match get_calls(self) {
Ok(ret) => Ok(ret),
Err(err) => {
self.sig_idx = start_sig_idx;
self.buf_idx = start_buf_idx;
Err(err)
}
}
}
pub fn get2<T1, T2>(&mut self) -> Result<(T1, T2), crate::wire::unmarshal::Error>
where
T1: Unmarshal<'body, 'fds>,
T2: Unmarshal<'body, 'fds>,
{
let get_calls = |parser: &mut Self| {
let ret1 = parser.get()?;
let ret2 = parser.get()?;
Ok((ret1, ret2))
};
self.get_mult_helper(2, get_calls)
}
pub fn get3<T1, T2, T3>(&mut self) -> Result<(T1, T2, T3), crate::wire::unmarshal::Error>
where
T1: Unmarshal<'body, 'fds>,
T2: Unmarshal<'body, 'fds>,
T3: Unmarshal<'body, 'fds>,
{
let get_calls = |parser: &mut Self| {
let ret1 = parser.get()?;
let ret2 = parser.get()?;
let ret3 = parser.get()?;
Ok((ret1, ret2, ret3))
};
self.get_mult_helper(3, get_calls)
}
pub fn get4<T1, T2, T3, T4>(
&mut self,
) -> Result<(T1, T2, T3, T4), crate::wire::unmarshal::Error>
where
T1: Unmarshal<'body, 'fds>,
T2: Unmarshal<'body, 'fds>,
T3: Unmarshal<'body, 'fds>,
T4: Unmarshal<'body, 'fds>,
{
let get_calls = |parser: &mut Self| {
let ret1 = parser.get()?;
let ret2 = parser.get()?;
let ret3 = parser.get()?;
let ret4 = parser.get()?;
Ok((ret1, ret2, ret3, ret4))
};
self.get_mult_helper(4, get_calls)
}
pub fn get5<T1, T2, T3, T4, T5>(
&mut self,
) -> Result<(T1, T2, T3, T4, T5), crate::wire::unmarshal::Error>
where
T1: Unmarshal<'body, 'fds>,
T2: Unmarshal<'body, 'fds>,
T3: Unmarshal<'body, 'fds>,
T4: Unmarshal<'body, 'fds>,
T5: Unmarshal<'body, 'fds>,
{
let get_calls = |parser: &mut Self| {
let ret1 = parser.get()?;
let ret2 = parser.get()?;
let ret3 = parser.get()?;
let ret4 = parser.get()?;
let ret5 = parser.get()?;
Ok((ret1, ret2, ret3, ret4, ret5))
};
self.get_mult_helper(5, get_calls)
}
pub fn get_param(&mut self) -> Result<crate::params::Param, crate::wire::unmarshal::Error> {
if self.sig_idx >= self.sigs.len() {
return Err(crate::wire::unmarshal::Error::EndOfMessage);
}
let mut ctx = UnmarshalContext {
byteorder: self.body.byteorder,
buf: &self.body.buf,
offset: self.buf_idx,
fds: &self.body.raw_fds,
};
match crate::wire::unmarshal::container::unmarshal_with_sig(
&self.sigs[self.sig_idx],
&mut ctx,
) {
Ok((bytes, res)) => {
self.buf_idx += bytes;
self.sig_idx += 1;
Ok(res)
}
Err(e) => Err(e),
}
}
}