1use anyhow::{Context, Result};
2use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
3use core::fmt;
4use rand::RngCore;
5use std::io::{Read, Write};
6
7use crate::tlv::{self, TlvItem, TlvItemEnc, TlvItemValueEnc};
8
9#[derive(Debug)]
10pub struct MessageHeader {
11 pub flags: u8,
12 pub security_flags: u8,
13 pub session_id: u16,
14 pub message_counter: u32,
15 pub source_node_id: Option<Vec<u8>>,
16 pub destination_node_id: Option<Vec<u8>>,
17}
18
19impl MessageHeader {
20 const FLAG_SRC_PRESENT: u8 = 4;
21 const DSIZ_64: u8 = 1;
22 const DSIZ_16: u8 = 2;
23 pub fn encode(&self) -> Result<Vec<u8>> {
24 let mut flags: u8 = 0;
25 if self.source_node_id.as_ref().is_some_and(|x| x.len() == 8) {
26 flags |= Self::FLAG_SRC_PRESENT;
27 }
28 if let Some(destination_node_id) = &self.destination_node_id {
29 if destination_node_id.len() == 2 {
30 flags |= Self::DSIZ_16
31 } else if destination_node_id.len() == 8 {
32 flags |= Self::DSIZ_64
33 }
34 }
35 let mut out = Vec::with_capacity(1024);
36 out.write_u8(flags)?;
37 out.write_u16::<LittleEndian>(self.session_id)?;
38 out.write_u8(self.security_flags)?;
39 out.write_u32::<LittleEndian>(self.message_counter)?;
40 if let Some(sn) = &self.source_node_id {
41 if sn.len() == 8 {
42 out.write_all(sn)?;
43 }
44 }
45 if let Some(destination_node_id) = &self.destination_node_id {
46 out.write_all(destination_node_id)?;
47 }
48 Ok(out)
49 }
50 pub fn decode(data: &[u8]) -> Result<(Self, Vec<u8>)> {
51 let mut cursor = std::io::Cursor::new(data);
52 let flags = cursor.read_u8()?;
53 let session_id = cursor.read_u16::<LittleEndian>()?;
54 let security_flags = cursor.read_u8()?;
55 let message_counter = cursor.read_u32::<LittleEndian>()?;
56 let source_node_id = if (flags & Self::FLAG_SRC_PRESENT) != 0 {
57 let mut sn = vec![0; 8];
58 cursor.read_exact(sn.as_mut())?;
59 Some(sn)
60 } else {
61 None
62 };
63 let destination_node_id = if (flags & 3) != 0 {
64 let dst_size = match flags & 3 {
65 Self::DSIZ_64 => 8,
66 Self::DSIZ_16 => 2,
67 _ => 0,
68 };
69 if dst_size > 0 {
70 let mut dn = vec![0; dst_size];
71 cursor.read_exact(dn.as_mut())?;
72 Some(dn)
73 } else {
74 None
75 }
76 } else {
77 None
78 };
79 let mut rest = Vec::new();
80 cursor.read_to_end(&mut rest)?;
81 Ok((
82 Self {
83 flags,
84 security_flags,
85 session_id,
86 message_counter,
87 source_node_id,
88 destination_node_id,
89 },
90 rest,
91 ))
92 }
93}
94
95#[derive(Debug)]
111pub struct ProtocolMessageHeader {
112 exchange_flags: u8,
113 pub opcode: u8,
114 pub exchange_id: u16,
115 pub protocol_id: u16,
116 pub ack_counter: u32,
117}
118
119impl ProtocolMessageHeader {
120 pub const FLAG_INITIATOR: u8 = 1;
121 pub const FLAG_ACK: u8 = 2;
122 pub const FLAG_RELIABILITY: u8 = 4;
123
124 pub const OPCODE_ACK: u8 = 0x10;
125 pub const OPCODE_PBKDF_REQ: u8 = 0x20;
126 pub const OPCODE_PBKDF_RESP: u8 = 0x21;
127 pub const OPCODE_PASE_PAKE1: u8 = 0x22;
128 pub const OPCODE_PASE_PAKE2: u8 = 0x23;
129 pub const OPCODE_PASE_PAKE3: u8 = 0x24;
130 pub const OPCODE_CASE_SIGMA1: u8 = 0x30;
131 pub const OPCODE_CASE_SIGMA2: u8 = 0x31;
132 pub const OPCODE_CASE_SIGMA3: u8 = 0x32;
133 pub const OPCODE_STATUS: u8 = 0x40;
134
135 pub const INTERACTION_OPCODE_STATUS_RESP: u8 = 0x1;
136 pub const INTERACTION_OPCODE_READ_REQ: u8 = 0x2;
137 pub const INTERACTION_OPCODE_REPORT_DATA: u8 = 0x5;
138 pub const INTERACTION_OPCODE_INVOKE_REQ: u8 = 0x8;
139 pub const INTERACTION_OPCODE_INVOKE_RESP: u8 = 0x9;
140 pub const INTERACTION_OPCODE_TIMED_REQ: u8 = 0xa;
141
142 pub const PROTOCOL_ID_SECURE_CHANNEL: u16 = 0;
143 pub const PROTOCOL_ID_INTERACTION: u16 = 1;
144
145 pub fn encode(&self) -> Result<Vec<u8>> {
146 let mut out = Vec::with_capacity(1024);
147 out.write_u8(self.exchange_flags)?;
148 out.write_u8(self.opcode)?;
149 out.write_u16::<LittleEndian>(self.exchange_id)?;
150 out.write_u16::<LittleEndian>(self.protocol_id)?;
151 if (self.exchange_flags & Self::FLAG_ACK) != 0 {
152 out.write_u32::<LittleEndian>(self.ack_counter)?;
153 }
154 Ok(out)
155 }
156 pub fn decode(data: &[u8]) -> Result<(Self, Vec<u8>)> {
157 let mut cursor = std::io::Cursor::new(data);
158 let exchange_flags = cursor.read_u8()?;
159 let opcode = cursor.read_u8()?;
160 let exchange_id = cursor.read_u16::<LittleEndian>()?;
161 let protocol_id = cursor.read_u16::<LittleEndian>()?;
162 let mut ack_counter = 0;
163 if (exchange_flags & Self::FLAG_ACK) != 0 {
164 ack_counter = cursor.read_u32::<LittleEndian>()?;
165 }
166 let mut rest = Vec::new();
167 cursor.read_to_end(&mut rest)?;
168 Ok((
169 Self {
170 exchange_flags,
171 opcode,
172 exchange_id,
173 protocol_id,
174 ack_counter,
175 },
176 rest,
177 ))
178 }
179}
180
181
182#[derive(Debug, Clone, Copy)]
183pub enum SecureChannelGeneralCode {
184 Success = 0,
185 Failure = 1,
186 BadPrecondition = 2,
187 OutOfRange = 3,
188 BadRequest = 4,
189 Unsupported = 5,
190 Unexpected = 6,
191 ResourceExhausted = 7,
192 Busy = 8,
193 Timeout = 9,
194 Continue = 10,
195 Aborted = 11,
196 InvalidArgument = 12,
197 NotFound = 13,
198 AlreadyExists = 14,
199 PermissionDenied = 15,
200 DataLoss = 16,
201 MessageTooLarge = 17,
202 Unknown = 0xffff
203}
204
205impl From<u16> for SecureChannelGeneralCode {
206 fn from(value: u16) -> Self {
207 match value {
208 0 => SecureChannelGeneralCode::Success,
209 1 => SecureChannelGeneralCode::Failure,
210 2 => SecureChannelGeneralCode::BadPrecondition,
211 3 => SecureChannelGeneralCode::OutOfRange,
212 4 => SecureChannelGeneralCode::BadRequest,
213 5 => SecureChannelGeneralCode::Unsupported,
214 6 => SecureChannelGeneralCode::Unexpected,
215 7 => SecureChannelGeneralCode::ResourceExhausted,
216 8 => SecureChannelGeneralCode::Busy,
217 9 => SecureChannelGeneralCode::Timeout,
218 10 => SecureChannelGeneralCode::Continue,
219 11 => SecureChannelGeneralCode::Aborted,
220 12 => SecureChannelGeneralCode::InvalidArgument,
221 13 => SecureChannelGeneralCode::NotFound,
222 14 => SecureChannelGeneralCode::AlreadyExists,
223 15 => SecureChannelGeneralCode::PermissionDenied,
224 16 => SecureChannelGeneralCode::DataLoss,
225 17 => SecureChannelGeneralCode::MessageTooLarge,
226 _ => SecureChannelGeneralCode::Unknown
227 }
228 }
229}
230
231impl std::fmt::Display for SecureChannelGeneralCode {
232 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
233 match self {
234 SecureChannelGeneralCode::Success => write!(f, "SUCCESS"),
235 SecureChannelGeneralCode::Failure => write!(f, "FAILURE"),
236 SecureChannelGeneralCode::BadPrecondition => write!(f, "BAD_PRECONDITION"),
237 SecureChannelGeneralCode::OutOfRange => write!(f, "OUT_OF_RANGE"),
238 SecureChannelGeneralCode::BadRequest => write!(f, "BAD_REQUEST"),
239 SecureChannelGeneralCode::Unsupported => write!(f, "UNSUPPORTED"),
240 SecureChannelGeneralCode::Unexpected => write!(f, "UNEXPECTED"),
241 SecureChannelGeneralCode::ResourceExhausted => write!(f, "RESOURCE_EXHAUSTED"),
242 SecureChannelGeneralCode::Busy => write!(f, "BUSY"),
243 SecureChannelGeneralCode::Timeout => write!(f, "TIMEOUT"),
244 SecureChannelGeneralCode::Continue => write!(f, "CONTINUE"),
245 SecureChannelGeneralCode::Aborted => write!(f, "ABORTED"),
246 SecureChannelGeneralCode::InvalidArgument => write!(f, "INVALID_ARGUMENT"),
247 SecureChannelGeneralCode::NotFound => write!(f, "NOT_FOUND"),
248 SecureChannelGeneralCode::AlreadyExists => write!(f, "ALREADY_EXISTS"),
249 SecureChannelGeneralCode::PermissionDenied => write!(f, "PERMISSION_DENIED"),
250 SecureChannelGeneralCode::DataLoss => write!(f, "DATA_LOSS"),
251 SecureChannelGeneralCode::MessageTooLarge => write!(f, "MESSAGE_TOO_LARGE"),
252 SecureChannelGeneralCode::Unknown => write!(f, "UNKNOWN {}", *self as u16),
253 }
254 }
255}
256
257#[derive(Debug, Clone, Copy)]
258pub enum SecureChannelProtocolCode {
259 SessionEstablishmentSuccess = 0,
260 NoSharedTrustRoots = 1,
261 InvalidParameter = 2,
262 CloseSession = 3,
263 Busy = 4,
264 RequiredCatMismatch = 5,
265 Unknown = 0xffff
266}
267
268impl std::fmt::Display for SecureChannelProtocolCode {
269 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
270 match self {
271 SecureChannelProtocolCode::SessionEstablishmentSuccess => write!(f, "SESSION_ESTABLISHMENT_SUCCESS"),
272 SecureChannelProtocolCode::NoSharedTrustRoots => write!(f, "NO_SHARED_TRUST_ROOTS"),
273 SecureChannelProtocolCode::InvalidParameter => write!(f, "INVALID_PARAMETER"),
274 SecureChannelProtocolCode::CloseSession => write!(f, "CLOSE_SESSION"),
275 SecureChannelProtocolCode::Busy => write!(f, "BUSY"),
276 SecureChannelProtocolCode::RequiredCatMismatch => write!(f, "REQUIRED_CAT_MISMATCH"),
277 SecureChannelProtocolCode::Unknown => write!(f, "UNKNOWN {}", *self as u16),
278 }
279 }
280}
281
282impl From<u16> for SecureChannelProtocolCode {
283 fn from(value: u16) -> Self {
284 match value {
285 0 => SecureChannelProtocolCode::SessionEstablishmentSuccess,
286 1 => SecureChannelProtocolCode::NoSharedTrustRoots,
287 2 => SecureChannelProtocolCode::InvalidParameter,
288 3 => SecureChannelProtocolCode::CloseSession,
289 4 => SecureChannelProtocolCode::Busy,
290 5 => SecureChannelProtocolCode::RequiredCatMismatch,
291 _ => SecureChannelProtocolCode::Unknown,
292 }
293 }
294}
295
296#[derive(Debug, Clone, Copy)]
297pub struct StatusReportInfo {
298 general_code: u16,
299 protocol_id: u32,
300 protocol_code: u16,
301}
302impl std::fmt::Display for StatusReportInfo {
303 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
304 if self.general_code == 0 {
305 return write!(f, "StatusReportInfo: OK");
306 }
307 let gc = Into::<SecureChannelGeneralCode>::into(self.general_code);
308 match self.protocol_id as u16{
309 ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL => {
310 let pc = Into::<SecureChannelProtocolCode>::into(self.protocol_code);
311 write!(
312 f,
313 "StatusReportInfo: general_code={}, protocol_id={}, protocol_code={}",
314 gc, self.protocol_id, pc
315 )
316
317 },
318 _ => {
319 write!(f, "StatusReportInfo: general_code={}, protocol_id={}, protocol_code={}",
320 gc, self.protocol_id, self.protocol_code
321 )
322 }
323
324 }
325 }
326}
327impl StatusReportInfo {
328 fn parse(data: &[u8]) -> Result<Self> {
329 let mut cursor = std::io::Cursor::new(data);
330 let general_code = cursor.read_u16::<LittleEndian>()?;
331 let protocol_id = cursor.read_u32::<LittleEndian>()?;
332 let protocol_code = cursor.read_u16::<LittleEndian>()?;
333 Ok(Self {
334 general_code,
335 protocol_id,
336 protocol_code,
337 })
338 }
339 pub fn is_ok(&self) -> bool {
340 self.general_code == 0 && self.protocol_id == 0 && self.protocol_code == 0
341 }
342}
343
344pub struct Message {
345 pub message_header: MessageHeader,
346 pub protocol_header: ProtocolMessageHeader,
347 pub payload: Vec<u8>,
348 pub tlv: TlvItem,
349 pub status_report_info: Option<StatusReportInfo>,
350}
351
352impl fmt::Debug for Message {
353 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
354 f.debug_struct("Message")
355 .field("message_header", &self.message_header)
356 .field("protocol_header", &self.protocol_header)
357 .field("payload", &hex::encode(&self.payload))
358 .field("tlv", &self.tlv)
359 .field("status_report_info", &self.status_report_info)
360 .finish()
361 }
362}
363
364impl Message {
365 pub fn decode(data: &[u8]) -> Result<Self> {
366 let (message_header, rest) = MessageHeader::decode(data)?;
367 let (protocol_header, rest) = ProtocolMessageHeader::decode(&rest)?;
368 if (protocol_header.protocol_id == ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL)
369 && (protocol_header.opcode == ProtocolMessageHeader::OPCODE_STATUS)
370 {
371 let status_report_info = StatusReportInfo::parse(&rest)?;
372 return Ok(Self {
373 message_header,
374 protocol_header,
375 payload: rest,
376 tlv: TlvItem {
377 tag: 0,
378 value: tlv::TlvItemValue::Invalid(),
379 },
380 status_report_info: Some(status_report_info),
381 });
382 }
383 let tlv = tlv::decode_tlv(&rest)?;
384 Ok(Self {
385 message_header,
386 protocol_header,
387 payload: rest,
388 tlv,
389 status_report_info: None,
390 })
391 }
392}
393
394pub fn ack(exchange: u16, ack: i64) -> Result<Vec<u8>> {
395 let mut flags = ProtocolMessageHeader::FLAG_INITIATOR;
396 flags |= ProtocolMessageHeader::FLAG_ACK;
397 ProtocolMessageHeader {
398 exchange_flags: flags,
399 opcode: ProtocolMessageHeader::OPCODE_ACK,
400 exchange_id: exchange,
401 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
402 ack_counter: ack as u32,
403 }
404 .encode()
405}
406
407pub fn pbkdf_req(exchange: u16) -> Result<Vec<u8>> {
408 let mut b = ProtocolMessageHeader {
409 exchange_flags: ProtocolMessageHeader::FLAG_INITIATOR
410 | ProtocolMessageHeader::FLAG_RELIABILITY,
411 opcode: ProtocolMessageHeader::OPCODE_PBKDF_REQ,
412 exchange_id: exchange,
413 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
414 ack_counter: 0,
415 }
416 .encode()?;
417 let mut tlv = tlv::TlvBuffer::new();
418 tlv.write_anon_struct()?;
419 let mut initiator_random = [0u8; 32];
420 rand::thread_rng().fill_bytes(&mut initiator_random);
421 tlv.write_octetstring(0x1, &initiator_random)?;
422 tlv.write_uint16(2, 1)?;
423 tlv.write_uint8(3, 0)?;
424 tlv.write_bool(4, false)?;
425 tlv.write_struct_end()?;
426 b.write_all(&tlv.data)?;
427 Ok(b)
428}
429
430pub fn pake1(exchange: u16, key: &[u8], ack: i64) -> Result<Vec<u8>> {
431 let mut flags = ProtocolMessageHeader::FLAG_INITIATOR | ProtocolMessageHeader::FLAG_RELIABILITY;
432 if ack >= 0 {
433 flags |= ProtocolMessageHeader::FLAG_ACK
434 }
435 let mut b = ProtocolMessageHeader {
436 exchange_flags: flags,
437 opcode: ProtocolMessageHeader::OPCODE_PASE_PAKE1,
438 exchange_id: exchange,
439 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
440 ack_counter: ack as u32,
441 }
442 .encode()?;
443
444 let tlv = TlvItemEnc {
445 tag: 0,
446 value: TlvItemValueEnc::StructAnon(vec![TlvItemEnc {
447 tag: 1,
448 value: TlvItemValueEnc::OctetString(key.to_owned()),
449 }]),
450 }
451 .encode()?;
452 b.write_all(&tlv)?;
453
454 Ok(b)
455}
456
457pub fn pake3(exchange: u16, key: &[u8], ack: i64) -> Result<Vec<u8>> {
458 let mut flags = 0x5;
459 if ack >= 0 {
460 flags |= 2
461 }
462 let mut b = ProtocolMessageHeader {
463 exchange_flags: flags,
464 opcode: ProtocolMessageHeader::OPCODE_PASE_PAKE3,
465 exchange_id: exchange,
466 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
467 ack_counter: ack as u32,
468 }
469 .encode()?;
470 let mut tlv = tlv::TlvBuffer::new();
471 tlv.write_anon_struct()?;
472 tlv.write_octetstring(0x1, key)?;
473 tlv.write_struct_end()?;
474
475 b.write_all(&tlv.data)?;
476 Ok(b)
477}
478
479pub fn sigma1(exchange: u16, payload: &[u8]) -> Result<Vec<u8>> {
480 let mut b = ProtocolMessageHeader {
481 exchange_flags: 5,
482 opcode: ProtocolMessageHeader::OPCODE_CASE_SIGMA1,
483 exchange_id: exchange,
484 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
485 ack_counter: 0,
486 }
487 .encode()?;
488 b.write_all(payload)?;
489 Ok(b)
490}
491
492pub fn sigma3(exchange: u16, payload: &[u8]) -> Result<Vec<u8>> {
493 let mut b = ProtocolMessageHeader {
494 exchange_flags: 5,
495 opcode: ProtocolMessageHeader::OPCODE_CASE_SIGMA3,
496 exchange_id: exchange,
497 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
498 ack_counter: 0,
499 }
500 .encode()?;
501 b.write_all(payload)?;
502 Ok(b)
503}
504
505pub fn im_invoke_request(
506 endpoint: u16,
507 cluster: u32,
508 command: u32,
509 exchange_id: u16,
510 payload: &[u8],
511 timed: bool,
512) -> Result<Vec<u8>> {
513 let b = ProtocolMessageHeader {
514 exchange_flags: 5,
515 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_INVOKE_REQ,
516 exchange_id,
517 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
518 ack_counter: 0,
519 }
520 .encode()?;
521
522 let mut tlv = tlv::TlvBuffer::from_vec(b);
523 tlv.write_anon_struct()?;
524 tlv.write_bool(0x0, false)?;
525 tlv.write_bool(0x1, timed)?; tlv.write_array(2)?;
527 tlv.write_anon_struct()?;
528 tlv.write_list(0)?;
529 tlv.write_uint16(0, endpoint)?;
530 tlv.write_uint32(1, cluster)?;
531 tlv.write_uint32(2, command)?;
532 tlv.write_struct_end()?;
533 tlv.write_struct(1)?;
534 tlv.write_raw(payload)?;
535 tlv.write_struct_end()?;
536 tlv.write_struct_end()?;
537 tlv.write_struct_end()?;
538 tlv.write_uint8(0xff, 10)?;
539 tlv.write_struct_end()?;
540 Ok(tlv.data)
541}
542
543pub fn im_timed_request(exchange_id: u16, timeout: u16) -> Result<Vec<u8>> {
544 let b = ProtocolMessageHeader {
545 exchange_flags: 5,
546 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_TIMED_REQ,
547 exchange_id,
548 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
549 ack_counter: 0,
550 }
551 .encode()?;
552
553 let mut tlv = tlv::TlvBuffer::from_vec(b);
554 tlv.write_anon_struct()?;
555 tlv.write_uint16(0, timeout)?;
556 tlv.write_uint8(0xff, 10)?;
557 tlv.write_struct_end()?;
558 Ok(tlv.data)
559}
560
561pub fn im_read_request(endpoint: u16, cluster: u32, attr: u32, exchange: u16) -> Result<Vec<u8>> {
562 let b = ProtocolMessageHeader {
563 exchange_flags: 5,
564 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_READ_REQ,
565 exchange_id: exchange,
566 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
567 ack_counter: 0,
568 }
569 .encode()?;
570
571 let mut tlv = tlv::TlvBuffer::from_vec(b);
572 tlv.write_anon_struct()?;
573 tlv.write_array(0)?;
574 tlv.write_anon_list()?;
575 tlv.write_uint16(2, endpoint)?;
576 tlv.write_uint32(3, cluster)?;
577 tlv.write_uint32(4, attr)?;
578 tlv.write_struct_end()?;
579 tlv.write_struct_end()?;
580 tlv.write_bool(3, true)?;
581 tlv.write_uint8(0xff, 10)?;
582 tlv.write_struct_end()?;
583 Ok(tlv.data)
584}
585
586pub fn parse_im_invoke_resp(resp: &TlvItem) -> Result<(u32, u32)> {
587 let common_status = resp
588 .get_int(&[1, 0, 1, 1, 0])
589 .context("parse_im_invoke_resp: status not found")?;
590 if common_status == 0 {
591 return Ok((0, 0));
592 }
593 let stat = resp
594 .get_int(&[1, 0, 1, 1, 1])
595 .context("parse_im_invoke_resp: unexpected response")?;
596 Ok((common_status as u32, stat as u32))
597}
598
599#[cfg(test)]
600mod tests {
601 use super::Message;
602
603 #[test]
604 pub fn test_1() {
605 let msg = "04000000a5a0b90d3320764c7d52ef86052060d5000015300120cabe444262d4e5dd568c755ed77e0829b9983c4d62b480b579811ec383eb69c625020837240300280418";
606 let msg = hex::decode(msg).unwrap();
607 let m = Message::decode(&msg).unwrap();
608 println!("{:?}", m);
609
610 let msg = "04000000000000000000000000000000012001000000153001203052998af1897150086e6c84003c074df93a796b4f68a9221ee4e40325014aaf25020100240300280418";
611 let msg = hex::decode(msg).unwrap();
612 let m = Message::decode(&msg).unwrap();
613 println!("{:?}", m);
614 }
615}