async_rustbus/rustbus_core/message_builder/
mod.rs

1//! Build new messages that you want to send over a connection
2
3use std::convert::TryInto;
4use std::num::NonZeroU32;
5
6use super::wire::marshal::traits::{Marshal, Signature, SignatureBuffer};
7use super::wire::marshal::MarshalContext;
8use super::wire::unmarshal::{traits::Unmarshal, UnmarshalContext, HEADER_LEN};
9use crate::utils::align_num;
10
11pub use super::org_message_builder::{HeaderFlags, MessageType};
12use super::path::ObjectPath;
13use super::signature::{Base, Container, Type};
14use super::ByteOrder;
15
16use rustbus::params::validation::Error as ValidationErr;
17use rustbus::params::validation::{
18    validate_busname, validate_errorname, validate_interface, validate_membername,
19    validate_signature,
20};
21use rustbus::wire::util::{insert_u32, unmarshal_signature, write_signature};
22
23mod body;
24
25pub use body::{MarshalledMessageBody, MessageBodyParser};
26
27/// Starting point for new messages. Create either a call or a signal
28#[derive(Default)]
29pub struct MessageBuilder {
30    msg: MarshalledMessage,
31}
32
33/// Created by MessageBuilder::call. Use it to make a new call to a service
34pub struct CallBuilder {
35    msg: MarshalledMessage,
36}
37
38/// Created by MessageBuilder::signal. Use it to make a new signal
39pub struct SignalBuilder {
40    msg: MarshalledMessage,
41}
42
43impl MessageBuilder {
44    /// New messagebuilder with the default little endian byteorder
45    pub fn new() -> MessageBuilder {
46        MessageBuilder {
47            msg: MarshalledMessage::new(),
48        }
49    }
50
51    /// New messagebuilder with a chosen byteorder
52    pub fn with_byteorder(b: ByteOrder) -> MessageBuilder {
53        MessageBuilder {
54            msg: MarshalledMessage::with_byteorder(b),
55        }
56    }
57
58    pub fn call<S: Into<String>>(mut self, member: S) -> CallBuilder {
59        self.msg.typ = MessageType::Call;
60        self.msg.dynheader.member = Some(member.into());
61        CallBuilder { msg: self.msg }
62    }
63    pub fn signal<S1, S2, S3>(mut self, interface: S1, member: S2, object: S3) -> SignalBuilder
64    where
65        S1: Into<String>,
66        S2: Into<String>,
67        S3: Into<String>,
68    {
69        self.msg.typ = MessageType::Signal;
70        self.msg.dynheader.member = Some(member.into());
71        self.msg.dynheader.interface = Some(interface.into());
72        self.msg.dynheader.object = Some(object.into());
73        SignalBuilder { msg: self.msg }
74    }
75}
76
77impl CallBuilder {
78    pub fn on<S: Into<String>>(mut self, object_path: S) -> Self {
79        self.msg.dynheader.object = Some(object_path.into());
80        self
81    }
82
83    pub fn with_interface<S: Into<String>>(mut self, interface: S) -> Self {
84        self.msg.dynheader.interface = Some(interface.into());
85        self
86    }
87
88    pub fn at<S: Into<String>>(mut self, destination: S) -> Self {
89        self.msg.dynheader.destination = Some(destination.into());
90        self
91    }
92
93    pub fn build(self) -> MarshalledMessage {
94        self.msg
95    }
96}
97
98impl SignalBuilder {
99    pub fn to<S: Into<String>>(mut self, destination: S) -> Self {
100        self.msg.dynheader.destination = Some(destination.into());
101        self
102    }
103
104    pub fn build(self) -> MarshalledMessage {
105        self.msg
106    }
107}
108
109/// Message received by a connection or in preparation before being sent over a connection.
110///
111/// This represents a message while it is being built before it is sent over the connection.
112/// The body accepts everything that implements the Marshal trait (e.g. all basic types, strings, slices, Hashmaps,.....)
113/// And you can of course write an Marshal impl for your own datastructures. See the doc on the Marshal trait what you have
114/// to look out for when doing this though.
115#[derive(Debug)]
116pub struct MarshalledMessage {
117    pub body: MarshalledMessageBody,
118
119    pub dynheader: DynamicHeader,
120
121    pub typ: MessageType,
122    pub flags: u8,
123}
124
125impl Default for MarshalledMessage {
126    fn default() -> Self {
127        Self::new()
128    }
129}
130
131impl MarshalledMessage {
132    pub fn get_buf(&self) -> &[u8] {
133        self.body.buf()
134    }
135    pub fn get_sig(&self) -> &str {
136        self.body.sig()
137    }
138
139    /// New message with the default little endian byteorder
140    pub fn new() -> Self {
141        MarshalledMessage {
142            typ: MessageType::Invalid,
143            dynheader: DynamicHeader::default(),
144
145            flags: 0,
146            body: MarshalledMessageBody::new(),
147        }
148    }
149
150    /// New messagebody with a chosen byteorder
151    pub fn with_byteorder(b: ByteOrder) -> Self {
152        MarshalledMessage {
153            typ: MessageType::Invalid,
154            dynheader: DynamicHeader::default(),
155
156            flags: 0,
157            body: MarshalledMessageBody::with_byteorder(b),
158        }
159    }
160
161    /// Reserves space for `additional` bytes in the internal buffer. This is useful to reduce the amount of allocations done while marshalling,
162    /// if you can predict somewhat accuratly how many bytes you will be marshalling.
163    pub fn reserve(&mut self, additional: usize) {
164        self.body.reserve(additional)
165    }
166    pub fn marshal_header(
167        &self,
168        serial: NonZeroU32,
169        hdr_buf: &mut Vec<u8>,
170    ) -> Result<(), super::Error> {
171        hdr_buf.clear();
172        let mut _fds = Vec::new();
173        let mut ctx = MarshalContext {
174            byteorder: self.body.byteorder(),
175            fds: &mut _fds,
176            buf: hdr_buf,
177        };
178        let bo_byte: u8 = match ctx.byteorder {
179            ByteOrder::LittleEndian => b'l',
180            ByteOrder::BigEndian => b'B',
181        };
182        bo_byte.marshal(&mut ctx).unwrap();
183        let t_byte: u8 = match self.typ {
184            MessageType::Invalid => 0,
185            MessageType::Call => 1,
186            MessageType::Reply => 2,
187            MessageType::Error => 3,
188            MessageType::Signal => 4,
189        };
190        t_byte.marshal(&mut ctx).unwrap();
191        self.flags.marshal(&mut ctx).unwrap();
192        1u8.marshal(&mut ctx).unwrap();
193        (self.body.buf().len() as u32).marshal(&mut ctx).unwrap();
194        u32::from(serial).marshal(&mut ctx).unwrap();
195        0u32.marshal(&mut ctx).unwrap();
196        if let Some(obj) = &self.dynheader.object {
197            let path = ObjectPath::from_str(obj)
198                .map_err(|_| super::Error::Validation(ValidationErr::InvalidObjectPath))?;
199            (1u8, HdrVar::Path(path)).marshal(&mut ctx).unwrap();
200        }
201        if let Some(iface) = &self.dynheader.interface {
202            validate_interface(iface)?;
203            (2u8, HdrVar::Str(iface)).marshal(&mut ctx).unwrap();
204        }
205        if let Some(member) = &self.dynheader.member {
206            validate_membername(member)?;
207            (3u8, HdrVar::Str(member)).marshal(&mut ctx).unwrap();
208        }
209        if let Some(err) = &self.dynheader.error_name {
210            validate_errorname(err)?;
211            (4u8, HdrVar::Str(err)).marshal(&mut ctx).unwrap();
212        }
213        if let Some(rsp_idx) = &self.dynheader.response_serial {
214            (5u8, HdrVar::U32((*rsp_idx).into()))
215                .marshal(&mut ctx)
216                .unwrap();
217        }
218        if let Some(dest) = &self.dynheader.destination {
219            validate_busname(dest)?;
220            (6u8, HdrVar::Str(dest)).marshal(&mut ctx).unwrap();
221        }
222        if let Some(sender) = &self.dynheader.sender {
223            validate_busname(sender)?;
224            (7u8, HdrVar::Str(sender)).marshal(&mut ctx).unwrap();
225        }
226        if !self.body.buf().is_empty() {
227            let sig = self.body.sig();
228            debug_assert!(SigStr::new(sig).is_ok());
229            let ss = unsafe { SigStr::new_no_val(sig) };
230            (8u8, HdrVar::Sig(ss)).marshal(&mut ctx).unwrap();
231        }
232        let fd_cnt = self.body.fds().len() as u32;
233        if fd_cnt != 0 {
234            (9u8, HdrVar::U32(fd_cnt)).marshal(&mut ctx).unwrap();
235        }
236        let len = ctx.buf.len() - (HEADER_LEN + 4);
237        insert_u32(ctx.byteorder, len as u32, &mut ctx.buf[HEADER_LEN..]);
238        ctx.align_to(8);
239        Ok(())
240    }
241}
242
243/// The dynamic part of a dbus message header
244#[derive(Debug, Clone, Default)]
245pub struct DynamicHeader {
246    pub interface: Option<String>,
247    pub member: Option<String>,
248    pub object: Option<String>,
249    pub destination: Option<String>,
250    pub serial: Option<NonZeroU32>,
251    pub sender: Option<String>,
252    pub signature: Option<String>,
253    pub error_name: Option<String>,
254    pub response_serial: Option<NonZeroU32>,
255    pub num_fds: Option<u32>,
256}
257
258impl DynamicHeader {
259    /// Make a correctly addressed error response with the correct response serial
260    pub fn make_error_response<S: Into<String>>(
261        &self,
262        error_name: S,
263        error_msg: Option<String>,
264    ) -> MarshalledMessage {
265        let mut err_resp = MarshalledMessage {
266            typ: MessageType::Error,
267            dynheader: DynamicHeader {
268                interface: None,
269                member: None,
270                object: None,
271                destination: self.sender.clone(),
272                serial: None,
273                num_fds: None,
274                sender: None,
275                signature: None,
276                response_serial: self.serial,
277                error_name: Some(error_name.into()),
278            },
279            flags: 0,
280            body: MarshalledMessageBody::new(),
281        };
282        if let Some(text) = error_msg {
283            err_resp.body.push_param(text).unwrap();
284        }
285        err_resp
286    }
287    /// Make a correctly addressed response with the correct response serial
288    pub fn make_response(&self) -> MarshalledMessage {
289        MarshalledMessage {
290            typ: MessageType::Reply,
291            dynheader: DynamicHeader {
292                interface: None,
293                member: None,
294                object: None,
295                destination: self.sender.clone(),
296                serial: None,
297                num_fds: None,
298                sender: None,
299                signature: None,
300                response_serial: self.serial,
301                error_name: None,
302            },
303            flags: 0,
304            body: MarshalledMessageBody::new(),
305        }
306    }
307    pub fn validate(&self) -> bool {
308        if let Some(iface) = &self.interface {
309            if validate_interface(iface).is_err() {
310                return false;
311            }
312        }
313        if let Some(path) = &self.object {
314            if ObjectPath::from_str(path).is_err() {
315                return false;
316            }
317        }
318        if let Some(member) = &self.member {
319            if validate_membername(member).is_err() {
320                return false;
321            }
322        }
323        if let Some(err) = &self.error_name {
324            if validate_errorname(err).is_err() {
325                return false;
326            }
327        }
328        if let Some(dest) = &self.destination {
329            if validate_busname(dest).is_err() {
330                return false;
331            }
332        }
333        if let Some(sender) = &self.sender {
334            if validate_busname(sender).is_err() {
335                return false;
336            }
337        }
338        if let Some(sig) = &self.signature {
339            if validate_signature(sig).is_err() {
340                return false;
341            }
342        }
343        true
344    }
345}
346impl Signature for DynamicHeader {
347    fn signature() -> super::signature::Type {
348        Type::Container(Container::Dict(
349            Base::Byte,
350            Box::new(Type::Container(Container::Variant)),
351        ))
352    }
353    fn alignment() -> usize {
354        4
355    }
356}
357
358use super::wire::unmarshal;
359impl<'buf, 'fds> Unmarshal<'buf, 'fds> for DynamicHeader {
360    fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
361        let start = ctx.offset;
362        let (_, len) = u32::unmarshal(ctx)?;
363        let len = len as usize;
364
365        let end = align_num(ctx.offset + len, 8);
366        if end > ctx.buf.len() {
367            return Err(unmarshal::Error::NotEnoughBytes);
368        }
369        let mut fields: [Option<HdrVar>; 10] = Default::default();
370        let mut array_used = 0;
371        while array_used < len {
372            let (u, (idx, var)) = <(u8, HdrVar)>::unmarshal(ctx)?;
373            fields[idx as usize] = Some(var);
374            array_used += u;
375        }
376        if array_used != len {
377            return Err(unmarshal::Error::NotEnoughBytesForCollection);
378        }
379        let mut ret = DynamicHeader::default();
380        if let Some(var) = &fields[1] {
381            match var {
382                HdrVar::Path(p) => ret.object = Some(p.to_string()),
383                _ => return Err(unmarshal::Error::InvalidHeaderField),
384            }
385        }
386        if let Some(var) = &fields[2] {
387            match var {
388                HdrVar::Str(p) => ret.interface = Some(p.to_string()),
389                _ => return Err(unmarshal::Error::InvalidHeaderField),
390            }
391        }
392        if let Some(var) = &fields[3] {
393            match var {
394                HdrVar::Str(p) => ret.member = Some(p.to_string()),
395                _ => return Err(unmarshal::Error::InvalidHeaderField),
396            }
397        }
398        if let Some(var) = &fields[4] {
399            match var {
400                HdrVar::Str(p) => ret.error_name = Some(p.to_string()),
401                _ => return Err(unmarshal::Error::InvalidHeaderField),
402            }
403        }
404        if let Some(var) = &fields[5] {
405            match var {
406                HdrVar::U32(p) if *p != 0 => ret.response_serial = Some((*p).try_into().unwrap()),
407                _ => return Err(unmarshal::Error::InvalidHeaderField),
408            }
409        }
410        if let Some(var) = &fields[6] {
411            match var {
412                HdrVar::Str(p) => ret.destination = Some(p.to_string()),
413                _ => return Err(unmarshal::Error::InvalidHeaderField),
414            }
415        }
416        if let Some(var) = &fields[7] {
417            match var {
418                HdrVar::Str(p) => ret.sender = Some(p.to_string()),
419                _ => return Err(unmarshal::Error::InvalidHeaderField),
420            }
421        }
422        if let Some(var) = &fields[8] {
423            match var {
424                HdrVar::Sig(p) => ret.signature = Some(p.to_string()),
425                _ => return Err(unmarshal::Error::InvalidHeaderField),
426            }
427        }
428        if let Some(var) = &fields[9] {
429            match var {
430                HdrVar::U32(p) => ret.num_fds = Some(*p),
431                _ => return Err(unmarshal::Error::InvalidHeaderField),
432            }
433        }
434        if !ret.validate() {
435            Err(unmarshal::Error::InvalidHeaderField)
436        } else {
437            ctx.align_to(8)?;
438            Ok((ctx.offset - start, ret))
439        }
440    }
441}
442
443#[derive(Debug)]
444#[doc(hidden)]
445pub struct SigStr(str);
446
447impl SigStr {
448    fn new(sig: &str) -> Result<&Self, ValidationErr> {
449        validate_signature(sig)?;
450        Ok(unsafe { Self::new_no_val(sig) })
451    }
452    unsafe fn new_no_val(sig: &str) -> &Self {
453        &*(sig as *const str as *const SigStr)
454    }
455}
456use std::ops::Deref;
457impl Deref for SigStr {
458    type Target = str;
459    fn deref(&self) -> &Self::Target {
460        &self.0
461    }
462}
463
464impl Signature for &SigStr {
465    fn signature() -> Type {
466        Type::Base(Base::Signature)
467    }
468    fn alignment() -> usize {
469        Self::signature().get_alignment()
470    }
471    fn sig_str(s_buf: &mut SignatureBuffer) {
472        s_buf.push_static("g");
473    }
474}
475impl<'buf, 'fds> Unmarshal<'buf, 'fds> for &'buf SigStr {
476    fn unmarshal(ctx: &mut UnmarshalContext<'fds, 'buf>) -> unmarshal::UnmarshalResult<Self> {
477        let (used, sig) = unmarshal_signature(&ctx.buf[ctx.offset..])?;
478        ctx.offset += used;
479        let ret = SigStr::new(sig)?;
480        Ok((used, ret))
481    }
482}
483impl Marshal for &SigStr {
484    fn marshal(&self, ctx: &mut MarshalContext) -> Result<(), super::Error> {
485        write_signature(&self.0, ctx.buf);
486        Ok(())
487    }
488}
489
490use super::dbus_variant_var;
491dbus_variant_var!(HdrVar, Path => &'buf ObjectPath; Str => &'buf str; U32 => u32; Sig => &'buf SigStr);