1use crate::message_builder::DynamicHeader;
8use crate::message_builder::MarshalledMessage;
9use crate::message_builder::MarshalledMessageBody;
10use crate::message_builder::MessageType;
11use crate::params;
12use crate::signature;
13use crate::wire::errors::UnmarshalError;
14use crate::wire::util::*;
15use crate::wire::HeaderField;
16use crate::ByteOrder;
17
18mod param;
19pub use param::base;
20pub use param::container;
21pub mod iter;
22pub mod traits;
23
24use container::*;
25
26#[derive(Debug, Clone, Copy)]
27pub struct Header {
28 pub byteorder: ByteOrder,
29 pub typ: MessageType,
30 pub flags: u8,
31 pub version: u8,
32 pub body_len: u32,
33 pub serial: u32,
34}
35
36pub struct UnmarshalContext<'fds, 'buf> {
37 pub fds: &'fds [crate::wire::UnixFd],
38 pub buf: &'buf [u8],
39 pub byteorder: ByteOrder,
40 pub offset: usize,
41}
42
43impl UnmarshalContext<'_, '_> {
44 pub fn align_to(&mut self, alignment: usize) -> Result<usize, UnmarshalError> {
45 let padding = crate::wire::util::align_offset(alignment, self.buf, self.offset)?;
46
47 if self.offset + padding > self.buf.len() {
48 Err(UnmarshalError::NotEnoughBytes)
49 } else {
50 self.offset += padding;
51 Ok(padding)
52 }
53 }
54}
55
56impl From<crate::params::validation::Error> for UnmarshalError {
57 fn from(e: crate::params::validation::Error) -> Self {
58 UnmarshalError::Validation(e)
59 }
60}
61impl From<crate::signature::Error> for UnmarshalError {
62 fn from(e: crate::signature::Error) -> Self {
63 UnmarshalError::Validation(crate::params::validation::Error::InvalidSignature(e))
64 }
65}
66
67impl UnmarshalError {
68 #[inline]
70 pub fn is_end_of_message(&self) -> bool {
71 self == &UnmarshalError::EndOfMessage
72 }
73}
74
75pub const HEADER_LEN: usize = 12;
76
77pub type UnmarshalResult<T> = std::result::Result<(usize, T), UnmarshalError>;
78
79pub fn unmarshal_header(buf: &[u8], offset: usize) -> UnmarshalResult<Header> {
80 if buf.len() < offset + HEADER_LEN {
81 return Err(UnmarshalError::NotEnoughBytes);
82 }
83 let header_slice = &buf[offset..offset + HEADER_LEN];
84
85 let byteorder = match header_slice[0] {
86 b'l' => ByteOrder::LittleEndian,
87 b'B' => ByteOrder::BigEndian,
88 _ => return Err(UnmarshalError::InvalidByteOrder),
89 };
90
91 let typ = match header_slice[1] {
92 1 => MessageType::Call,
93 2 => MessageType::Reply,
94 3 => MessageType::Error,
95 4 => MessageType::Signal,
96 _ => return Err(UnmarshalError::InvalidMessageType),
97 };
98 let flags = header_slice[2];
99 let version = header_slice[3];
100 let (_, body_len) = parse_u32(&header_slice[4..8], byteorder)?;
101 let (_, serial) = parse_u32(&header_slice[8..12], byteorder)?;
102
103 Ok((
104 HEADER_LEN,
105 Header {
106 byteorder,
107 typ,
108 flags,
109 version,
110 body_len,
111 serial,
112 },
113 ))
114}
115
116pub fn unmarshal_dynamic_header(
117 header: &Header,
118 buf: &[u8],
119 offset: usize,
120) -> UnmarshalResult<DynamicHeader> {
121 let (fields_bytes_used, fields) = unmarshal_header_fields(header, buf, offset)?;
122 let mut hdr = DynamicHeader {
123 serial: Some(header.serial),
124 ..Default::default()
125 };
126 collect_header_fields(&fields, &mut hdr);
127 Ok((fields_bytes_used, hdr))
128}
129
130pub fn unmarshal_body<'a, 'e>(
131 byteorder: ByteOrder,
132 sigs: &[crate::signature::Type],
133 buf: &[u8],
134 fds: &[crate::wire::UnixFd],
135 offset: usize,
136) -> UnmarshalResult<Vec<params::Param<'a, 'e>>> {
137 let mut params = Vec::new();
138 let mut body_bytes_used = 0;
139 let mut ctx = UnmarshalContext {
140 fds,
141 buf,
142 byteorder,
143 offset,
144 };
145 for param_sig in sigs {
146 let (bytes, new_param) = unmarshal_with_sig(param_sig, &mut ctx)?;
147 params.push(new_param);
148 body_bytes_used += bytes;
149 }
150 Ok((body_bytes_used, params))
151}
152
153pub fn unmarshal_next_message(
154 header: &Header,
155 dynheader: DynamicHeader,
156 buf: &[u8],
157 offset: usize,
158) -> UnmarshalResult<MarshalledMessage> {
159 let sig = dynheader.signature.clone().unwrap_or_else(|| "".to_owned());
160 let padding = align_offset(8, buf, offset)?;
161
162 if header.body_len == 0 {
163 let msg = MarshalledMessage {
164 dynheader,
165 body: MarshalledMessageBody::from_parts(vec![], vec![], sig, header.byteorder),
166 typ: header.typ,
167 flags: header.flags,
168 };
169 Ok((padding, msg))
170 } else {
171 let offset = offset + padding;
172
173 if buf[offset..].len() < (header.body_len as usize) {
174 return Err(UnmarshalError::NotEnoughBytes);
175 }
176
177 let msg = MarshalledMessage {
178 dynheader,
179 body: MarshalledMessageBody::from_parts(
180 buf[offset..].to_vec(),
181 vec![],
182 sig,
183 header.byteorder,
184 ),
185 typ: header.typ,
186 flags: header.flags,
187 };
188 Ok((padding + header.body_len as usize, msg))
189 }
190}
191
192fn unmarshal_header_fields(
193 header: &Header,
194 buf: &[u8],
195 offset: usize,
196) -> UnmarshalResult<Vec<HeaderField>> {
197 let (_, header_fields_bytes) = parse_u32(&buf[offset..], header.byteorder)?;
198 let offset = offset + 4;
199
200 if offset + header_fields_bytes as usize > buf.len() {
201 return Err(UnmarshalError::NotEnoughBytes);
202 }
203
204 let mut fields = Vec::new();
205 let mut bytes_used_counter = 0;
206
207 while bytes_used_counter < header_fields_bytes as usize {
208 match unmarshal_header_field(header, buf, offset + bytes_used_counter) {
209 Ok((bytes_used, field)) => {
210 fields.push(field);
211 bytes_used_counter += bytes_used;
212 }
213 Err(UnmarshalError::UnknownHeaderField) => {
214 bytes_used_counter += 1;
216
217 match crate::wire::validate_raw::validate_marshalled(
220 header.byteorder,
221 offset + bytes_used_counter,
222 buf,
223 &crate::signature::Type::Container(crate::signature::Container::Variant),
224 ) {
225 Ok(bytes) => {
226 bytes_used_counter += bytes;
228 }
229 Err((_bytes, err)) => return Err(err),
231 }
232 }
233 Err(e) => return Err(e),
234 }
235 }
236 params::validate_header_fields(header.typ, &fields)
237 .map_err(|_| UnmarshalError::InvalidHeaderFields)?;
238
239 Ok((header_fields_bytes as usize + 4, fields))
240}
241
242fn unmarshal_header_field(
243 header: &Header,
244 buf: &[u8],
245 offset: usize,
246) -> UnmarshalResult<HeaderField> {
247 let padding = align_offset(8, buf, offset)?;
249 let offset = offset + padding;
250
251 if buf.len() <= offset {
253 return Err(UnmarshalError::NotEnoughBytes);
254 }
255 let typ = buf[offset];
256 let typ_bytes_used = 1;
257 let offset = offset + typ_bytes_used;
258
259 let (sig_bytes_used, sig_str) = unmarshal_signature(&buf[offset..])?;
260 let mut sig =
261 signature::Type::parse_description(sig_str).map_err(|_| UnmarshalError::NoSignature)?;
262 let offset = offset + sig_bytes_used;
263
264 if sig.len() != 1 {
265 return Err(UnmarshalError::NoSignature);
267 }
268 let sig = sig.remove(0);
269 let (field_bytes_used, field) = match typ {
270 1 => match sig {
271 signature::Type::Base(signature::Base::ObjectPath) => {
272 let (b, objpath) = unmarshal_string(header.byteorder, &buf[offset..])?;
273 crate::params::validate_object_path(&objpath)?;
274 (b, Ok(HeaderField::Path(objpath)))
275 }
276 _ => (0, Err(UnmarshalError::WrongSignature)),
277 },
278 2 => match sig {
279 signature::Type::Base(signature::Base::String) => {
280 let (b, int) = unmarshal_string(header.byteorder, &buf[offset..])?;
281 (b, Ok(HeaderField::Interface(int)))
282 }
283 _ => (0, Err(UnmarshalError::WrongSignature)),
284 },
285 3 => match sig {
286 signature::Type::Base(signature::Base::String) => {
287 let (b, mem) = unmarshal_string(header.byteorder, &buf[offset..])?;
288 (b, Ok(HeaderField::Member(mem)))
289 }
290 _ => (0, Err(UnmarshalError::WrongSignature)),
291 },
292 4 => match sig {
293 signature::Type::Base(signature::Base::String) => {
294 let (b, name) = unmarshal_string(header.byteorder, &buf[offset..])?;
295 (b, Ok(HeaderField::ErrorName(name)))
296 }
297 _ => (0, Err(UnmarshalError::WrongSignature)),
298 },
299 5 => match sig {
300 signature::Type::Base(signature::Base::Uint32) => {
301 let (b, serial) = parse_u32(&buf[offset..], header.byteorder)?;
302 (b, Ok(HeaderField::ReplySerial(serial)))
303 }
304 _ => (0, Err(UnmarshalError::WrongSignature)),
305 },
306 6 => match sig {
307 signature::Type::Base(signature::Base::String) => {
308 let (b, dest) = unmarshal_string(header.byteorder, &buf[offset..])?;
309 (b, Ok(HeaderField::Destination(dest)))
310 }
311 _ => (0, Err(UnmarshalError::WrongSignature)),
312 },
313 7 => match sig {
314 signature::Type::Base(signature::Base::String) => {
315 let (b, snd) = unmarshal_string(header.byteorder, &buf[offset..])?;
316 (b, Ok(HeaderField::Sender(snd)))
317 }
318 _ => (0, Err(UnmarshalError::WrongSignature)),
319 },
320 8 => match sig {
321 signature::Type::Base(signature::Base::Signature) => {
322 let (b, sig) = unmarshal_signature(&buf[offset..])?;
323 if !sig.is_empty() {
325 crate::params::validate_signature(sig)?;
326 }
327 (b, Ok(HeaderField::Signature(sig.to_owned())))
328 }
329 _ => (0, Err(UnmarshalError::WrongSignature)),
330 },
331 9 => match sig {
332 signature::Type::Base(signature::Base::Uint32) => {
333 let (b, fds) = parse_u32(&buf[offset..], header.byteorder)?;
334 (b, Ok(HeaderField::UnixFds(fds)))
335 }
336 _ => (0, Err(UnmarshalError::WrongSignature)),
337 },
338 0 => (0, Err(UnmarshalError::InvalidHeaderField)),
339 _ => (0, Err(UnmarshalError::UnknownHeaderField)),
340 };
341 let sum_bytes_used = padding + typ_bytes_used + sig_bytes_used + field_bytes_used;
342 match field {
343 Ok(field) => Ok((sum_bytes_used, field)),
344 Err(e) => Err(e),
345 }
346}
347
348fn collect_header_fields(header_fields: &[HeaderField], hdr: &mut DynamicHeader) {
349 for h in header_fields {
350 match h {
351 HeaderField::Destination(d) => hdr.destination = Some(d.clone()),
352 HeaderField::ErrorName(e) => hdr.error_name = Some(e.clone()),
353 HeaderField::Interface(s) => hdr.interface = Some(s.clone()),
354 HeaderField::Member(m) => hdr.member = Some(m.clone()),
355 HeaderField::Path(p) => hdr.object = Some(p.clone()),
356 HeaderField::ReplySerial(r) => hdr.response_serial = Some(*r),
357 HeaderField::Sender(s) => hdr.sender = Some(s.clone()),
358 HeaderField::Signature(s) => hdr.signature = Some(s.clone()),
359 HeaderField::UnixFds(u) => hdr.num_fds = Some(*u),
360 }
361 }
362}