zerodds_discovery/security/
codec.rs1extern crate alloc;
11use alloc::vec::Vec;
12
13use zerodds_security::error::{SecurityError, SecurityErrorKind, SecurityResult};
14use zerodds_security::generic_message::ParticipantGenericMessage;
15
16pub const ENCAPSULATION_CDR_LE: [u8; 2] = [0x00, 0x01];
18
19pub const ENCAPSULATION_HEADER_LEN: usize = 4;
21
22#[must_use]
25pub fn encode_generic_message(msg: &ParticipantGenericMessage) -> Vec<u8> {
26 let body = msg.to_cdr_le();
27 let mut out = Vec::with_capacity(ENCAPSULATION_HEADER_LEN + body.len());
28 out.extend_from_slice(&ENCAPSULATION_CDR_LE);
29 out.extend_from_slice(&[0, 0]); out.extend_from_slice(&body);
31 out
32}
33
34pub fn decode_generic_message(bytes: &[u8]) -> SecurityResult<ParticipantGenericMessage> {
42 if bytes.len() < ENCAPSULATION_HEADER_LEN {
43 return Err(SecurityError::new(
44 SecurityErrorKind::BadArgument,
45 "generic_message: encapsulation-header truncated",
46 ));
47 }
48 let kind = [bytes[0], bytes[1]];
49 if kind != ENCAPSULATION_CDR_LE && kind != [0x00, 0x00] {
50 return Err(SecurityError::new(
51 SecurityErrorKind::BadArgument,
52 "generic_message: only CDR_LE encapsulation supported",
53 ));
54 }
55 ParticipantGenericMessage::from_cdr_le(&bytes[ENCAPSULATION_HEADER_LEN..])
56}
57
58#[cfg(test)]
59#[allow(clippy::expect_used, clippy::unwrap_used)]
60mod tests {
61 use super::*;
62 use zerodds_security::generic_message::{MessageIdentity, class_id};
63 use zerodds_security::token::DataHolder;
64
65 fn sample() -> ParticipantGenericMessage {
66 ParticipantGenericMessage {
67 message_identity: MessageIdentity {
68 source_guid: [0xAA; 16],
69 sequence_number: 7,
70 },
71 related_message_identity: MessageIdentity::default(),
72 destination_participant_key: [0xBB; 16],
73 destination_endpoint_key: [0; 16],
74 source_endpoint_key: [0xCC; 16],
75 message_class_id: class_id::AUTH_REQUEST.into(),
76 message_data: alloc::vec![DataHolder::new("DDS:Auth:PKI-DH:1.2+AuthReq")],
77 }
78 }
79
80 #[test]
81 fn roundtrip_preserves_message() {
82 let msg = sample();
83 let bytes = encode_generic_message(&msg);
84 let back = decode_generic_message(&bytes).unwrap();
85 assert_eq!(msg, back);
86 }
87
88 #[test]
89 fn encode_starts_with_cdr_le_encapsulation() {
90 let bytes = encode_generic_message(&sample());
91 assert_eq!(&bytes[..4], &[0x00, 0x01, 0x00, 0x00]);
92 }
93
94 #[test]
95 fn decode_rejects_truncated_header() {
96 let err = decode_generic_message(&[0x00, 0x01]).unwrap_err();
97 assert_eq!(err.kind, SecurityErrorKind::BadArgument);
98 }
99
100 #[test]
101 fn decode_rejects_unknown_encapsulation() {
102 let err = decode_generic_message(&[0x00, 0x99, 0, 0, 0, 0, 0, 0]).unwrap_err();
103 assert_eq!(err.kind, SecurityErrorKind::BadArgument);
104 }
105}