matc/
messages.rs

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)]
96enum SecChannelOpcode {
97    None = 0x0,
98    Ack = 0x10,
99    PbkdfReq = 0x20,
100    PbkdfResp = 0x21,
101    Pake1 = 0x22,
102    Pake2 = 0x23,
103    Pake3 = 0x24,
104    Sigma1 = 0x30,
105    Sigma2 = 0x31,
106    Sigma3 = 0x32,
107    Status = 0x40,
108}*/
109
110#[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)?; // timed
527    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)?; // keep subscriptions
600    tlv.write_uint16(1, 10)?; // min interval
601    tlv.write_uint16(2, 30)?; // max interval
602    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)?; // urgent
610
611    tlv.write_struct_end()?;
612    tlv.write_struct_end()?;
613
614    tlv.write_bool(7, false)?;  // fabric filtered
615    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}