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 pub 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_SUBSCRIBE_REQ: u8 = 0x3;
138 pub const INTERACTION_OPCODE_REPORT_DATA: u8 = 0x5;
139 pub const INTERACTION_OPCODE_INVOKE_REQ: u8 = 0x8;
140 pub const INTERACTION_OPCODE_INVOKE_RESP: u8 = 0x9;
141 pub const INTERACTION_OPCODE_TIMED_REQ: u8 = 0xa;
142
143 pub const PROTOCOL_ID_SECURE_CHANNEL: u16 = 0;
144 pub const PROTOCOL_ID_INTERACTION: u16 = 1;
145
146 pub fn encode(&self) -> Result<Vec<u8>> {
147 let mut out = Vec::with_capacity(1024);
148 out.write_u8(self.exchange_flags)?;
149 out.write_u8(self.opcode)?;
150 out.write_u16::<LittleEndian>(self.exchange_id)?;
151 out.write_u16::<LittleEndian>(self.protocol_id)?;
152 if (self.exchange_flags & Self::FLAG_ACK) != 0 {
153 out.write_u32::<LittleEndian>(self.ack_counter)?;
154 }
155 Ok(out)
156 }
157 pub fn decode(data: &[u8]) -> Result<(Self, Vec<u8>)> {
158 let mut cursor = std::io::Cursor::new(data);
159 let exchange_flags = cursor.read_u8()?;
160 let opcode = cursor.read_u8()?;
161 let exchange_id = cursor.read_u16::<LittleEndian>()?;
162 let protocol_id = cursor.read_u16::<LittleEndian>()?;
163 let mut ack_counter = 0;
164 if (exchange_flags & Self::FLAG_ACK) != 0 {
165 ack_counter = cursor.read_u32::<LittleEndian>()?;
166 }
167 let mut rest = Vec::new();
168 cursor.read_to_end(&mut rest)?;
169 Ok((
170 Self {
171 exchange_flags,
172 opcode,
173 exchange_id,
174 protocol_id,
175 ack_counter,
176 },
177 rest,
178 ))
179 }
180}
181
182
183#[derive(Debug, Clone, Copy)]
184pub enum SecureChannelGeneralCode {
185 Success = 0,
186 Failure = 1,
187 BadPrecondition = 2,
188 OutOfRange = 3,
189 BadRequest = 4,
190 Unsupported = 5,
191 Unexpected = 6,
192 ResourceExhausted = 7,
193 Busy = 8,
194 Timeout = 9,
195 Continue = 10,
196 Aborted = 11,
197 InvalidArgument = 12,
198 NotFound = 13,
199 AlreadyExists = 14,
200 PermissionDenied = 15,
201 DataLoss = 16,
202 MessageTooLarge = 17,
203 Unknown = 0xffff
204}
205
206impl From<u16> for SecureChannelGeneralCode {
207 fn from(value: u16) -> Self {
208 match value {
209 0 => SecureChannelGeneralCode::Success,
210 1 => SecureChannelGeneralCode::Failure,
211 2 => SecureChannelGeneralCode::BadPrecondition,
212 3 => SecureChannelGeneralCode::OutOfRange,
213 4 => SecureChannelGeneralCode::BadRequest,
214 5 => SecureChannelGeneralCode::Unsupported,
215 6 => SecureChannelGeneralCode::Unexpected,
216 7 => SecureChannelGeneralCode::ResourceExhausted,
217 8 => SecureChannelGeneralCode::Busy,
218 9 => SecureChannelGeneralCode::Timeout,
219 10 => SecureChannelGeneralCode::Continue,
220 11 => SecureChannelGeneralCode::Aborted,
221 12 => SecureChannelGeneralCode::InvalidArgument,
222 13 => SecureChannelGeneralCode::NotFound,
223 14 => SecureChannelGeneralCode::AlreadyExists,
224 15 => SecureChannelGeneralCode::PermissionDenied,
225 16 => SecureChannelGeneralCode::DataLoss,
226 17 => SecureChannelGeneralCode::MessageTooLarge,
227 _ => SecureChannelGeneralCode::Unknown
228 }
229 }
230}
231
232impl std::fmt::Display for SecureChannelGeneralCode {
233 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234 match self {
235 SecureChannelGeneralCode::Success => write!(f, "SUCCESS"),
236 SecureChannelGeneralCode::Failure => write!(f, "FAILURE"),
237 SecureChannelGeneralCode::BadPrecondition => write!(f, "BAD_PRECONDITION"),
238 SecureChannelGeneralCode::OutOfRange => write!(f, "OUT_OF_RANGE"),
239 SecureChannelGeneralCode::BadRequest => write!(f, "BAD_REQUEST"),
240 SecureChannelGeneralCode::Unsupported => write!(f, "UNSUPPORTED"),
241 SecureChannelGeneralCode::Unexpected => write!(f, "UNEXPECTED"),
242 SecureChannelGeneralCode::ResourceExhausted => write!(f, "RESOURCE_EXHAUSTED"),
243 SecureChannelGeneralCode::Busy => write!(f, "BUSY"),
244 SecureChannelGeneralCode::Timeout => write!(f, "TIMEOUT"),
245 SecureChannelGeneralCode::Continue => write!(f, "CONTINUE"),
246 SecureChannelGeneralCode::Aborted => write!(f, "ABORTED"),
247 SecureChannelGeneralCode::InvalidArgument => write!(f, "INVALID_ARGUMENT"),
248 SecureChannelGeneralCode::NotFound => write!(f, "NOT_FOUND"),
249 SecureChannelGeneralCode::AlreadyExists => write!(f, "ALREADY_EXISTS"),
250 SecureChannelGeneralCode::PermissionDenied => write!(f, "PERMISSION_DENIED"),
251 SecureChannelGeneralCode::DataLoss => write!(f, "DATA_LOSS"),
252 SecureChannelGeneralCode::MessageTooLarge => write!(f, "MESSAGE_TOO_LARGE"),
253 SecureChannelGeneralCode::Unknown => write!(f, "UNKNOWN {}", *self as u16),
254 }
255 }
256}
257
258#[derive(Debug, Clone, Copy)]
259pub enum SecureChannelProtocolCode {
260 SessionEstablishmentSuccess = 0,
261 NoSharedTrustRoots = 1,
262 InvalidParameter = 2,
263 CloseSession = 3,
264 Busy = 4,
265 RequiredCatMismatch = 5,
266 Unknown = 0xffff
267}
268
269impl std::fmt::Display for SecureChannelProtocolCode {
270 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
271 match self {
272 SecureChannelProtocolCode::SessionEstablishmentSuccess => write!(f, "SESSION_ESTABLISHMENT_SUCCESS"),
273 SecureChannelProtocolCode::NoSharedTrustRoots => write!(f, "NO_SHARED_TRUST_ROOTS"),
274 SecureChannelProtocolCode::InvalidParameter => write!(f, "INVALID_PARAMETER"),
275 SecureChannelProtocolCode::CloseSession => write!(f, "CLOSE_SESSION"),
276 SecureChannelProtocolCode::Busy => write!(f, "BUSY"),
277 SecureChannelProtocolCode::RequiredCatMismatch => write!(f, "REQUIRED_CAT_MISMATCH"),
278 SecureChannelProtocolCode::Unknown => write!(f, "UNKNOWN {}", *self as u16),
279 }
280 }
281}
282
283impl From<u16> for SecureChannelProtocolCode {
284 fn from(value: u16) -> Self {
285 match value {
286 0 => SecureChannelProtocolCode::SessionEstablishmentSuccess,
287 1 => SecureChannelProtocolCode::NoSharedTrustRoots,
288 2 => SecureChannelProtocolCode::InvalidParameter,
289 3 => SecureChannelProtocolCode::CloseSession,
290 4 => SecureChannelProtocolCode::Busy,
291 5 => SecureChannelProtocolCode::RequiredCatMismatch,
292 _ => SecureChannelProtocolCode::Unknown,
293 }
294 }
295}
296
297#[derive(Debug, Clone, Copy)]
298pub struct StatusReportInfo {
299 general_code: u16,
300 protocol_id: u32,
301 protocol_code: u16,
302}
303impl std::fmt::Display for StatusReportInfo {
304 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
305 if self.general_code == 0 {
306 return write!(f, "StatusReportInfo: OK");
307 }
308 let gc = Into::<SecureChannelGeneralCode>::into(self.general_code);
309 match self.protocol_id as u16{
310 ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL => {
311 let pc = Into::<SecureChannelProtocolCode>::into(self.protocol_code);
312 write!(
313 f,
314 "StatusReportInfo: general_code={}, protocol_id={}, protocol_code={}",
315 gc, self.protocol_id, pc
316 )
317
318 },
319 _ => {
320 write!(f, "StatusReportInfo: general_code={}, protocol_id={}, protocol_code={}",
321 gc, self.protocol_id, self.protocol_code
322 )
323 }
324
325 }
326 }
327}
328impl StatusReportInfo {
329 fn parse(data: &[u8]) -> Result<Self> {
330 let mut cursor = std::io::Cursor::new(data);
331 let general_code = cursor.read_u16::<LittleEndian>()?;
332 let protocol_id = cursor.read_u32::<LittleEndian>()?;
333 let protocol_code = cursor.read_u16::<LittleEndian>()?;
334 Ok(Self {
335 general_code,
336 protocol_id,
337 protocol_code,
338 })
339 }
340 pub fn is_ok(&self) -> bool {
341 self.general_code == 0 && self.protocol_id == 0 && self.protocol_code == 0
342 }
343}
344
345pub struct Message {
346 pub message_header: MessageHeader,
347 pub protocol_header: ProtocolMessageHeader,
348 pub payload: Vec<u8>,
349 pub tlv: TlvItem,
350 pub status_report_info: Option<StatusReportInfo>,
351}
352
353impl fmt::Debug for Message {
354 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
355 f.debug_struct("Message")
356 .field("message_header", &self.message_header)
357 .field("protocol_header", &self.protocol_header)
358 .field("payload", &hex::encode(&self.payload))
359 .field("tlv", &self.tlv)
360 .field("status_report_info", &self.status_report_info)
361 .finish()
362 }
363}
364
365impl Message {
366 pub fn decode(data: &[u8]) -> Result<Self> {
367 let (message_header, rest) = MessageHeader::decode(data)?;
368 let (protocol_header, rest) = ProtocolMessageHeader::decode(&rest)?;
369 if (protocol_header.protocol_id == ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL)
370 && (protocol_header.opcode == ProtocolMessageHeader::OPCODE_STATUS)
371 {
372 let status_report_info = StatusReportInfo::parse(&rest)?;
373 return Ok(Self {
374 message_header,
375 protocol_header,
376 payload: rest,
377 tlv: TlvItem {
378 tag: 0,
379 value: tlv::TlvItemValue::Invalid(),
380 },
381 status_report_info: Some(status_report_info),
382 });
383 }
384 let tlv = tlv::decode_tlv(&rest)?;
385 Ok(Self {
386 message_header,
387 protocol_header,
388 payload: rest,
389 tlv,
390 status_report_info: None,
391 })
392 }
393}
394
395pub fn ack(exchange: u16, ack: i64) -> Result<Vec<u8>> {
396 let mut flags = ProtocolMessageHeader::FLAG_INITIATOR;
397 flags |= ProtocolMessageHeader::FLAG_ACK;
398 ProtocolMessageHeader {
399 exchange_flags: flags,
400 opcode: ProtocolMessageHeader::OPCODE_ACK,
401 exchange_id: exchange,
402 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
403 ack_counter: ack as u32,
404 }
405 .encode()
406}
407
408pub fn pbkdf_req(exchange: u16) -> Result<Vec<u8>> {
409 let mut b = ProtocolMessageHeader {
410 exchange_flags: ProtocolMessageHeader::FLAG_INITIATOR
411 | ProtocolMessageHeader::FLAG_RELIABILITY,
412 opcode: ProtocolMessageHeader::OPCODE_PBKDF_REQ,
413 exchange_id: exchange,
414 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
415 ack_counter: 0,
416 }
417 .encode()?;
418 let mut tlv = tlv::TlvBuffer::new();
419 tlv.write_anon_struct()?;
420 let mut initiator_random = [0u8; 32];
421 rand::thread_rng().fill_bytes(&mut initiator_random);
422 tlv.write_octetstring(0x1, &initiator_random)?;
423 tlv.write_uint16(2, 1)?;
424 tlv.write_uint8(3, 0)?;
425 tlv.write_bool(4, false)?;
426 tlv.write_struct_end()?;
427 b.write_all(&tlv.data)?;
428 Ok(b)
429}
430
431pub fn pake1(exchange: u16, key: &[u8], ack: i64) -> Result<Vec<u8>> {
432 let mut flags = ProtocolMessageHeader::FLAG_INITIATOR | ProtocolMessageHeader::FLAG_RELIABILITY;
433 if ack >= 0 {
434 flags |= ProtocolMessageHeader::FLAG_ACK
435 }
436 let mut b = ProtocolMessageHeader {
437 exchange_flags: flags,
438 opcode: ProtocolMessageHeader::OPCODE_PASE_PAKE1,
439 exchange_id: exchange,
440 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
441 ack_counter: ack as u32,
442 }
443 .encode()?;
444
445 let tlv = TlvItemEnc {
446 tag: 0,
447 value: TlvItemValueEnc::StructAnon(vec![TlvItemEnc {
448 tag: 1,
449 value: TlvItemValueEnc::OctetString(key.to_owned()),
450 }]),
451 }
452 .encode()?;
453 b.write_all(&tlv)?;
454
455 Ok(b)
456}
457
458pub fn pake3(exchange: u16, key: &[u8], ack: i64) -> Result<Vec<u8>> {
459 let mut flags = 0x5;
460 if ack >= 0 {
461 flags |= 2
462 }
463 let mut b = ProtocolMessageHeader {
464 exchange_flags: flags,
465 opcode: ProtocolMessageHeader::OPCODE_PASE_PAKE3,
466 exchange_id: exchange,
467 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
468 ack_counter: ack as u32,
469 }
470 .encode()?;
471 let mut tlv = tlv::TlvBuffer::new();
472 tlv.write_anon_struct()?;
473 tlv.write_octetstring(0x1, key)?;
474 tlv.write_struct_end()?;
475
476 b.write_all(&tlv.data)?;
477 Ok(b)
478}
479
480pub fn sigma1(exchange: u16, payload: &[u8]) -> Result<Vec<u8>> {
481 let mut b = ProtocolMessageHeader {
482 exchange_flags: 5,
483 opcode: ProtocolMessageHeader::OPCODE_CASE_SIGMA1,
484 exchange_id: exchange,
485 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
486 ack_counter: 0,
487 }
488 .encode()?;
489 b.write_all(payload)?;
490 Ok(b)
491}
492
493pub fn sigma3(exchange: u16, payload: &[u8], ack: u32) -> Result<Vec<u8>> {
494 let mut b = ProtocolMessageHeader {
495 exchange_flags: 5 | ProtocolMessageHeader::FLAG_ACK,
496 opcode: ProtocolMessageHeader::OPCODE_CASE_SIGMA3,
497 exchange_id: exchange,
498 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
499 ack_counter: ack,
500 }
501 .encode()?;
502 b.write_all(payload)?;
503 Ok(b)
504}
505
506pub fn im_invoke_request(
507 endpoint: u16,
508 cluster: u32,
509 command: u32,
510 exchange_id: u16,
511 payload: &[u8],
512 timed: bool,
513) -> Result<Vec<u8>> {
514 let b = ProtocolMessageHeader {
515 exchange_flags: 5,
516 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_INVOKE_REQ,
517 exchange_id,
518 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
519 ack_counter: 0,
520 }
521 .encode()?;
522
523 let mut tlv = tlv::TlvBuffer::from_vec(b);
524 tlv.write_anon_struct()?;
525 tlv.write_bool(0x0, false)?;
526 tlv.write_bool(0x1, timed)?; tlv.write_array(2)?;
528 tlv.write_anon_struct()?;
529 tlv.write_list(0)?;
530 tlv.write_uint16(0, endpoint)?;
531 tlv.write_uint32(1, cluster)?;
532 tlv.write_uint32(2, command)?;
533 tlv.write_struct_end()?;
534 tlv.write_struct(1)?;
535 tlv.write_raw(payload)?;
536 tlv.write_struct_end()?;
537 tlv.write_struct_end()?;
538 tlv.write_struct_end()?;
539 tlv.write_uint8(0xff, 10)?;
540 tlv.write_struct_end()?;
541 Ok(tlv.data)
542}
543
544pub fn im_timed_request(exchange_id: u16, timeout: u16) -> Result<Vec<u8>> {
545 let b = ProtocolMessageHeader {
546 exchange_flags: 5,
547 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_TIMED_REQ,
548 exchange_id,
549 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
550 ack_counter: 0,
551 }
552 .encode()?;
553
554 let mut tlv = tlv::TlvBuffer::from_vec(b);
555 tlv.write_anon_struct()?;
556 tlv.write_uint16(0, timeout)?;
557 tlv.write_uint8(0xff, 10)?;
558 tlv.write_struct_end()?;
559 Ok(tlv.data)
560}
561
562pub fn im_read_request(endpoint: u16, cluster: u32, attr: u32, exchange: u16) -> Result<Vec<u8>> {
563 let b = ProtocolMessageHeader {
564 exchange_flags: 5,
565 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_READ_REQ,
566 exchange_id: exchange,
567 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
568 ack_counter: 0,
569 }
570 .encode()?;
571
572 let mut tlv = tlv::TlvBuffer::from_vec(b);
573 tlv.write_anon_struct()?;
574 tlv.write_array(0)?;
575 tlv.write_anon_list()?;
576 tlv.write_uint16(2, endpoint)?;
577 tlv.write_uint32(3, cluster)?;
578 tlv.write_uint32(4, attr)?;
579 tlv.write_struct_end()?;
580 tlv.write_struct_end()?;
581 tlv.write_bool(3, true)?;
582 tlv.write_uint8(0xff, 10)?;
583 tlv.write_struct_end()?;
584 Ok(tlv.data)
585}
586
587pub fn im_subscribe_request(endpoint: u16, cluster: u32, exchange: u16, event: u32) -> Result<Vec<u8>> {
588 let b = ProtocolMessageHeader {
589 exchange_flags: 5,
590 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_SUBSCRIBE_REQ,
591 exchange_id: exchange,
592 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
593 ack_counter: 0,
594 }
595 .encode()?;
596
597 let mut tlv = tlv::TlvBuffer::from_vec(b);
598 tlv.write_anon_struct()?;
599 tlv.write_bool(0, false)?; tlv.write_uint16(1, 10)?; tlv.write_uint16(2, 30)?; tlv.write_array(4)?;
603
604
605 tlv.write_anon_list()?;
606 tlv.write_uint16(1, endpoint)?;
607 tlv.write_uint32(2, cluster)?;
608 tlv.write_uint32(3, event)?;
609 tlv.write_bool(4, true)?; tlv.write_struct_end()?;
612 tlv.write_struct_end()?;
613
614 tlv.write_bool(7, false)?; tlv.write_uint8(0xff, 10)?;
616 tlv.write_struct_end()?;
617 Ok(tlv.data)
618}
619
620pub fn im_status_response(exchange: u16, flags: u8, ack: u32) -> Result<Vec<u8>> {
621 let b = ProtocolMessageHeader {
622 exchange_flags: 4 | flags,
623 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_STATUS_RESP,
624 exchange_id: exchange,
625 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
626 ack_counter: ack,
627 }
628 .encode()?;
629
630 let mut tlv = tlv::TlvBuffer::from_vec(b);
631 tlv.write_anon_struct()?;
632 tlv.write_uint8(0, 0)?;
633 tlv.write_struct_end()?;
634 Ok(tlv.data)
635}
636
637pub fn parse_im_invoke_resp(resp: &TlvItem) -> Result<(u32, u32)> {
638 let common_status = resp
639 .get_int(&[1, 0, 1, 1, 0])
640 .context("parse_im_invoke_resp: status not found")?;
641 if common_status == 0 {
642 return Ok((0, 0));
643 }
644 let stat = resp
645 .get_int(&[1, 0, 1, 1, 1])
646 .context("parse_im_invoke_resp: unexpected response")?;
647 Ok((common_status as u32, stat as u32))
648}
649
650#[cfg(test)]
651mod tests {
652 use super::Message;
653
654 #[test]
655 pub fn test_1() {
656 let msg = "04000000a5a0b90d3320764c7d52ef86052060d5000015300120cabe444262d4e5dd568c755ed77e0829b9983c4d62b480b579811ec383eb69c625020837240300280418";
657 let msg = hex::decode(msg).unwrap();
658 let m = Message::decode(&msg).unwrap();
659 println!("{:?}", m);
660
661 let msg = "04000000000000000000000000000000012001000000153001203052998af1897150086e6c84003c074df93a796b4f68a9221ee4e40325014aaf25020100240300280418";
662 let msg = hex::decode(msg).unwrap();
663 let m = Message::decode(&msg).unwrap();
664 println!("{:?}", m);
665 }
666}