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