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)]
306pub struct StatusReportInfo {
307 general_code: u16,
308 protocol_id: u32,
309 protocol_code: u16,
310 protocol_data: Vec<u8>,
311}
312impl std::fmt::Display for StatusReportInfo {
313 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
314 if self.general_code == 0 {
315 return write!(f, "StatusReportInfo: OK");
316 }
317 let gc = Into::<SecureChannelGeneralCode>::into(self.general_code);
318 match self.protocol_id as u16{
319 ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL => {
320 let pc = Into::<SecureChannelProtocolCode>::into(self.protocol_code);
321 write!(
322 f,
323 "StatusReportInfo: general_code={}, protocol_id={}, protocol_code={}",
324 gc, self.protocol_id, pc
325 )
326
327 },
328 _ => {
329 write!(f, "StatusReportInfo: general_code={}, protocol_id={}, protocol_code={}",
330 gc, self.protocol_id, self.protocol_code
331 )
332 }
333
334 }
335 }
336}
337impl StatusReportInfo {
338 pub fn parse(data: &[u8]) -> Result<Self> {
339 let mut cursor = std::io::Cursor::new(data);
340 let general_code = cursor.read_u16::<LittleEndian>()?;
341 let protocol_id = cursor.read_u32::<LittleEndian>()?;
342 let protocol_code = cursor.read_u16::<LittleEndian>()?;
343 let mut protocol_data = Vec::new();
344 cursor.read_to_end(&mut protocol_data).ok();
345 Ok(Self {
346 general_code,
347 protocol_id,
348 protocol_code,
349 protocol_data,
350 })
351 }
352 pub fn is_ok(&self) -> bool {
353 self.general_code == 0 && self.protocol_id == 0 && self.protocol_code == 0
354 }
355 pub fn is_busy(&self) -> bool {
356 self.general_code == SecureChannelGeneralCode::Busy as u16
357 && self.protocol_id == ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL as u32
358 && self.protocol_code == SecureChannelProtocolCode::Busy as u16
359 }
360 pub fn minimum_wait_time_ms(&self) -> Option<u32> {
363 if !self.is_busy() { return None; }
364 match self.protocol_data.len() {
365 n if n >= 4 => Some(u32::from_le_bytes(self.protocol_data[..4].try_into().ok()?)),
366 2 => Some(u16::from_le_bytes(self.protocol_data[..2].try_into().ok()?) as u32),
367 _ => None,
368 }
369 }
370}
371
372pub struct Message {
373 pub message_header: MessageHeader,
374 pub protocol_header: ProtocolMessageHeader,
375 pub payload: Vec<u8>,
376 pub tlv: TlvItem,
377 pub status_report_info: Option<StatusReportInfo>,
378}
379
380impl fmt::Debug for Message {
381 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
382 f.debug_struct("Message")
383 .field("message_header", &self.message_header)
384 .field("protocol_header", &self.protocol_header)
385 .field("payload", &hex::encode(&self.payload))
386 .field("tlv", &self.tlv)
387 .field("status_report_info", &self.status_report_info)
388 .finish()
389 }
390}
391
392impl Message {
393 pub fn decode(data: &[u8]) -> Result<Self> {
394 let (message_header, rest) = MessageHeader::decode(data)?;
395 let (protocol_header, rest) = ProtocolMessageHeader::decode(&rest)?;
396 if (protocol_header.protocol_id == ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL)
397 && (protocol_header.opcode == ProtocolMessageHeader::OPCODE_STATUS)
398 {
399 let status_report_info = StatusReportInfo::parse(&rest)?;
400 return Ok(Self {
401 message_header,
402 protocol_header,
403 payload: rest,
404 tlv: TlvItem {
405 tag: 0,
406 value: tlv::TlvItemValue::Invalid(),
407 },
408 status_report_info: Some(status_report_info),
409 });
410 }
411 let tlv = tlv::decode_tlv(&rest)?;
412 Ok(Self {
413 message_header,
414 protocol_header,
415 payload: rest,
416 tlv,
417 status_report_info: None,
418 })
419 }
420}
421
422pub fn ack(exchange: u16, ack: i64) -> Result<Vec<u8>> {
423 let mut flags = ProtocolMessageHeader::FLAG_INITIATOR;
424 flags |= ProtocolMessageHeader::FLAG_ACK;
425 ProtocolMessageHeader {
426 exchange_flags: flags,
427 opcode: ProtocolMessageHeader::OPCODE_ACK,
428 exchange_id: exchange,
429 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
430 ack_counter: ack as u32,
431 }
432 .encode()
433}
434
435pub fn pbkdf_req(exchange: u16) -> Result<Vec<u8>> {
436 let mut b = ProtocolMessageHeader {
437 exchange_flags: ProtocolMessageHeader::FLAG_INITIATOR
438 | ProtocolMessageHeader::FLAG_RELIABILITY,
439 opcode: ProtocolMessageHeader::OPCODE_PBKDF_REQ,
440 exchange_id: exchange,
441 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
442 ack_counter: 0,
443 }
444 .encode()?;
445 let mut tlv = tlv::TlvBuffer::new();
446 tlv.write_anon_struct()?;
447 let mut initiator_random = [0u8; 32];
448 rand::thread_rng().fill_bytes(&mut initiator_random);
449 tlv.write_octetstring(0x1, &initiator_random)?;
450 tlv.write_uint16(2, 1)?;
451 tlv.write_uint8(3, 0)?;
452 tlv.write_bool(4, false)?;
453 tlv.write_struct_end()?;
454 b.write_all(&tlv.data)?;
455 Ok(b)
456}
457
458pub fn pake1(exchange: u16, key: &[u8], ack: i64) -> Result<Vec<u8>> {
459 let mut flags = ProtocolMessageHeader::FLAG_INITIATOR | ProtocolMessageHeader::FLAG_RELIABILITY;
460 if ack >= 0 {
461 flags |= ProtocolMessageHeader::FLAG_ACK
462 }
463 let mut b = ProtocolMessageHeader {
464 exchange_flags: flags,
465 opcode: ProtocolMessageHeader::OPCODE_PASE_PAKE1,
466 exchange_id: exchange,
467 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
468 ack_counter: ack as u32,
469 }
470 .encode()?;
471
472 let tlv = TlvItemEnc {
473 tag: 0,
474 value: TlvItemValueEnc::StructAnon(vec![TlvItemEnc {
475 tag: 1,
476 value: TlvItemValueEnc::OctetString(key.to_owned()),
477 }]),
478 }
479 .encode()?;
480 b.write_all(&tlv)?;
481
482 Ok(b)
483}
484
485pub fn pake3(exchange: u16, key: &[u8], ack: i64) -> Result<Vec<u8>> {
486 let mut flags = 0x5;
487 if ack >= 0 {
488 flags |= 2
489 }
490 let mut b = ProtocolMessageHeader {
491 exchange_flags: flags,
492 opcode: ProtocolMessageHeader::OPCODE_PASE_PAKE3,
493 exchange_id: exchange,
494 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
495 ack_counter: ack as u32,
496 }
497 .encode()?;
498 let mut tlv = tlv::TlvBuffer::new();
499 tlv.write_anon_struct()?;
500 tlv.write_octetstring(0x1, key)?;
501 tlv.write_struct_end()?;
502
503 b.write_all(&tlv.data)?;
504 Ok(b)
505}
506
507pub fn status_report_success(exchange: u16) -> Result<Vec<u8>> {
508 let mut b = ProtocolMessageHeader {
509 exchange_flags: ProtocolMessageHeader::FLAG_INITIATOR,
510 opcode: ProtocolMessageHeader::OPCODE_STATUS,
511 exchange_id: exchange,
512 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
513 ack_counter: 0,
514 }
515 .encode()?;
516 b.write_u16::<LittleEndian>(0)?; b.write_u32::<LittleEndian>(0)?; b.write_u16::<LittleEndian>(0)?; Ok(b)
520}
521
522pub fn sigma1(exchange: u16, payload: &[u8]) -> Result<Vec<u8>> {
523 let mut b = ProtocolMessageHeader {
524 exchange_flags: 5,
525 opcode: ProtocolMessageHeader::OPCODE_CASE_SIGMA1,
526 exchange_id: exchange,
527 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
528 ack_counter: 0,
529 }
530 .encode()?;
531 b.write_all(payload)?;
532 Ok(b)
533}
534
535pub fn sigma3(exchange: u16, payload: &[u8], ack: u32) -> Result<Vec<u8>> {
536 let mut b = ProtocolMessageHeader {
537 exchange_flags: 5 | ProtocolMessageHeader::FLAG_ACK,
538 opcode: ProtocolMessageHeader::OPCODE_CASE_SIGMA3,
539 exchange_id: exchange,
540 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_SECURE_CHANNEL,
541 ack_counter: ack,
542 }
543 .encode()?;
544 b.write_all(payload)?;
545 Ok(b)
546}
547
548pub fn im_invoke_request(
549 endpoint: u16,
550 cluster: u32,
551 command: u32,
552 exchange_id: u16,
553 payload: &[u8],
554 timed: bool,
555) -> Result<Vec<u8>> {
556 let b = ProtocolMessageHeader {
557 exchange_flags: 5,
558 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_INVOKE_REQ,
559 exchange_id,
560 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
561 ack_counter: 0,
562 }
563 .encode()?;
564
565 let mut tlv = tlv::TlvBuffer::from_vec(b);
566 tlv.write_anon_struct()?;
567 tlv.write_bool(0x0, false)?;
568 tlv.write_bool(0x1, timed)?; tlv.write_array(2)?;
570 tlv.write_anon_struct()?;
571 tlv.write_list(0)?;
572 tlv.write_uint16(0, endpoint)?;
573 tlv.write_uint32(1, cluster)?;
574 tlv.write_uint32(2, command)?;
575 tlv.write_struct_end()?;
576 tlv.write_struct(1)?;
577 tlv.write_raw(payload)?;
578 tlv.write_struct_end()?;
579 tlv.write_struct_end()?;
580 tlv.write_struct_end()?;
581 tlv.write_uint8(0xff, 10)?;
582 tlv.write_struct_end()?;
583 Ok(tlv.data)
584}
585
586pub fn im_timed_request(exchange_id: u16, timeout: u16) -> Result<Vec<u8>> {
587 let b = ProtocolMessageHeader {
588 exchange_flags: 5,
589 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_TIMED_REQ,
590 exchange_id,
591 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
592 ack_counter: 0,
593 }
594 .encode()?;
595
596 let mut tlv = tlv::TlvBuffer::from_vec(b);
597 tlv.write_anon_struct()?;
598 tlv.write_uint16(0, timeout)?;
599 tlv.write_uint8(0xff, 10)?;
600 tlv.write_struct_end()?;
601 Ok(tlv.data)
602}
603
604pub fn im_read_request(endpoint: u16, cluster: u32, attr: u32, exchange: u16) -> Result<Vec<u8>> {
605 let b = ProtocolMessageHeader {
606 exchange_flags: 5,
607 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_READ_REQ,
608 exchange_id: exchange,
609 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
610 ack_counter: 0,
611 }
612 .encode()?;
613
614 let mut tlv = tlv::TlvBuffer::from_vec(b);
615 tlv.write_anon_struct()?;
616 tlv.write_array(0)?;
617 tlv.write_anon_list()?;
618 tlv.write_uint16(2, endpoint)?;
619 tlv.write_uint32(3, cluster)?;
620 tlv.write_uint32(4, attr)?;
621 tlv.write_struct_end()?;
622 tlv.write_struct_end()?;
623 tlv.write_bool(3, true)?;
624 tlv.write_uint8(0xff, 10)?;
625 tlv.write_struct_end()?;
626 Ok(tlv.data)
627}
628
629pub fn im_write_request(endpoint: u16, cluster: u32, attr: u32, exchange: u16, data: &[u8]) -> Result<Vec<u8>> {
630 let b = ProtocolMessageHeader {
631 exchange_flags: 5,
632 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_WRITE_REQ,
633 exchange_id: exchange,
634 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
635 ack_counter: 0,
636 }
637 .encode()?;
638
639 let mut tlv = tlv::TlvBuffer::from_vec(b);
640 tlv.write_anon_struct()?;
641 tlv.write_bool(1, false)?; tlv.write_array(2)?;
644 tlv.write_anon_struct()?;
645 tlv.write_list(1)?;
647 tlv.write_uint16(2, endpoint)?;
648 tlv.write_uint32(3, cluster)?;
649 tlv.write_uint32(4, attr)?;
650 tlv.write_struct_end()?;
651 tlv.write_raw(data)?;
652 tlv.write_struct_end()?;
653 tlv.write_struct_end()?;
654 tlv.write_bool(3, false)?;
655 tlv.write_uint8(0xff, 10)?; tlv.write_struct_end()?;
657 Ok(tlv.data)
658}
659
660pub fn im_subscribe_request_attr(endpoint: Option<u16>, cluster: Option<u32>, attr: Option<u32>, exchange: u16, keep_subscriptions: bool) -> Result<Vec<u8>> {
664 let b = ProtocolMessageHeader {
665 exchange_flags: 5,
666 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_SUBSCRIBE_REQ,
667 exchange_id: exchange,
668 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
669 ack_counter: 0,
670 }
671 .encode()?;
672
673 let mut tlv = tlv::TlvBuffer::from_vec(b);
674 tlv.write_anon_struct()?;
675 tlv.write_bool(0, keep_subscriptions)?; tlv.write_uint16(1, 10)?; tlv.write_uint16(2, 30)?; tlv.write_array(3)?; tlv.write_anon_list()?;
681 if let Some(endpoint) = endpoint {
682 tlv.write_uint16(2, endpoint)?;
683 }
684 if let Some(cluster) = cluster {
685 tlv.write_uint32(3, cluster)?;
686 }
687 if let Some(attr) = attr {
688 tlv.write_uint32(4, attr)?;
689 }
690
691 tlv.write_struct_end()?; tlv.write_struct_end()?; tlv.write_bool(7, false)?; tlv.write_uint8(0xff, 10)?; tlv.write_struct_end()?;
697 Ok(tlv.data)
698}
699
700pub fn im_subscribe_request_event(endpoint: Option<u16>, cluster: Option<u32>, event: Option<u32>, exchange: u16, keep_subscriptions: bool) -> Result<Vec<u8>> {
703 let b = ProtocolMessageHeader {
704 exchange_flags: 5,
705 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_SUBSCRIBE_REQ,
706 exchange_id: exchange,
707 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
708 ack_counter: 0,
709 }
710 .encode()?;
711
712 let mut tlv = tlv::TlvBuffer::from_vec(b);
713 tlv.write_anon_struct()?;
714 tlv.write_bool(0, keep_subscriptions)?;
715 tlv.write_uint16(1, 0)?;
716 tlv.write_uint16(2, 60)?;
717 tlv.write_array(4)?; tlv.write_anon_list()?;
720 if let Some(endpoint) = endpoint {
721 tlv.write_uint16(1, endpoint)?;
722 }
723 if let Some(cluster) = cluster {
724 tlv.write_uint32(2, cluster)?;
725 }
726 if let Some(event) = event {
727 tlv.write_uint32(3, event)?;
728 }
729 tlv.write_bool(4, true)?; tlv.write_struct_end()?; tlv.write_struct_end()?; tlv.write_bool(7, false)?;
735 tlv.write_uint8(0xff, 10)?;
736 tlv.write_struct_end()?;
737 Ok(tlv.data)
738}
739
740pub fn im_unsubscribe_all(exchange: u16) -> Result<Vec<u8>> {
743 let b = ProtocolMessageHeader {
744 exchange_flags: 5,
745 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_SUBSCRIBE_REQ,
746 exchange_id: exchange,
747 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
748 ack_counter: 0,
749 }
750 .encode()?;
751
752 let mut tlv = tlv::TlvBuffer::from_vec(b);
753 tlv.write_anon_struct()?;
754 tlv.write_bool(0, false)?; tlv.write_uint16(1, 0)?; tlv.write_uint16(2, 0)?; tlv.write_array(3)?; tlv.write_struct_end()?;
759 tlv.write_bool(7, false)?; tlv.write_uint8(0xff, 10)?; tlv.write_struct_end()?;
762 Ok(tlv.data)
763}
764
765pub fn im_status_flags_for(incoming_exchange_flags: u8) -> u8 {
770 if incoming_exchange_flags & ProtocolMessageHeader::FLAG_INITIATOR == 0 {
771 ProtocolMessageHeader::FLAG_INITIATOR | ProtocolMessageHeader::FLAG_ACK
772 } else {
773 ProtocolMessageHeader::FLAG_ACK
774 }
775}
776
777pub fn im_status_response(exchange: u16, flags: u8, ack: u32) -> Result<Vec<u8>> {
778 let b = ProtocolMessageHeader {
779 exchange_flags: 4 | flags,
780 opcode: ProtocolMessageHeader::INTERACTION_OPCODE_STATUS_RESP,
781 exchange_id: exchange,
782 protocol_id: ProtocolMessageHeader::PROTOCOL_ID_INTERACTION,
783 ack_counter: ack,
784 }
785 .encode()?;
786
787 let mut tlv = tlv::TlvBuffer::from_vec(b);
788 tlv.write_anon_struct()?;
789 tlv.write_uint8(0, 0)?;
790 tlv.write_uint8(0xff, 10)?; tlv.write_struct_end()?;
792 Ok(tlv.data)
793}
794
795pub fn parse_im_invoke_resp(resp: &TlvItem) -> Result<(u32, u32)> {
796 let common_status = resp
797 .get_int(&[1, 0, 1, 1, 0])
798 .context("parse_im_invoke_resp: status not found")?;
799 if common_status == 0 {
800 return Ok((0, 0));
801 }
802 let stat = resp
803 .get_int(&[1, 0, 1, 1, 1])
804 .context("parse_im_invoke_resp: unexpected response")?;
805 Ok((common_status as u32, stat as u32))
806}
807
808#[cfg(test)]
809mod tests {
810 use super::Message;
811
812 #[test]
813 pub fn test_1() {
814 let msg = "04000000a5a0b90d3320764c7d52ef86052060d5000015300120cabe444262d4e5dd568c755ed77e0829b9983c4d62b480b579811ec383eb69c625020837240300280418";
815 let msg = hex::decode(msg).unwrap();
816 let m = Message::decode(&msg).unwrap();
817 println!("{:?}", m);
818
819 let msg = "04000000000000000000000000000000012001000000153001203052998af1897150086e6c84003c074df93a796b4f68a9221ee4e40325014aaf25020100240300280418";
820 let msg = hex::decode(msg).unwrap();
821 let m = Message::decode(&msg).unwrap();
822 println!("{:?}", m);
823 }
824}