1use crate::MessageElement;
13use crate::{
14 DataEndpoint, TelemetryError, TelemetryResult, config::DataType, is_reliable_type,
15 message_meta, packet::Packet,
16};
17
18use crate::config::StandardSmallPayload;
19use crate::packet::{hash_bytes_u64, sender_address_u32};
20#[cfg(feature = "std")]
21use alloc::collections::BTreeMap;
22#[cfg(feature = "cryptography")]
23use alloc::vec;
24use alloc::{sync::Arc, vec::Vec};
25use crc32fast::Hasher as Crc32Hasher;
26#[cfg(feature = "std")]
27use std::sync::{Mutex, OnceLock};
28
29#[derive(Clone, Debug, PartialEq, Eq)]
33pub struct TelemetryEnvelope {
34 pub ty: DataType,
36 pub endpoints: Arc<[DataEndpoint]>,
38 pub sender: Arc<str>,
40 pub source_address: u32,
42 pub timestamp_ms: u64,
44 pub wire_shape: Option<MessageElement>,
46 pub target_senders: Arc<[u64]>,
48}
49
50#[derive(Clone, Copy, Debug, PartialEq, Eq)]
52pub struct ReliableHeader {
53 pub flags: u8,
54 pub seq: u32,
55 pub ack: u32,
56}
57
58pub const RELIABLE_FLAG_ACK_ONLY: u8 = 0x01;
60
61pub const RELIABLE_FLAG_UNORDERED: u8 = 0x02;
63
64pub const RELIABLE_FLAG_UNSEQUENCED: u8 = 0x80;
66
67pub const RELIABLE_HEADER_BYTES: usize = 1 + 4 + 4;
69pub const CRC32_BYTES: usize = 4;
71
72const FLAG_COMPRESSED_PAYLOAD: u8 = 0x01;
103const FLAG_RELIABLE_HEADER_PRESENT: u8 = 0x02;
104const FLAG_WIRE_CONTRACT: u8 = 0x04;
105const FLAG_PACKET_NONCE: u8 = 0x08;
106#[cfg(feature = "cryptography")]
107const FLAG_E2E_ENCRYPTED_PAYLOAD: u8 = 0x10;
108const FLAG_ENDPOINT_BITMAP_PRESENT: u8 = 0x20;
109const FLAG_ENDPOINT_LIST_PRESENT: u8 = 0x80;
110const FLAG_COMPACT_RELIABLE_HEADER: u8 = 0x40;
111const CONTRACT_FLAG_TARGETS: u8 = 0x01;
112const CONTRACT_FLAG_SHAPE: u8 = 0x02;
113const CONTRACT_FLAG_RELIABLE_HEADER: u8 = 0x04;
114const RELIABLE_WIRE_FLAG_SEQ_PRESENT: u8 = 0x04;
115const RELIABLE_WIRE_FLAG_ACK_PRESENT: u8 = 0x08;
116const RELIABLE_PUBLIC_FLAGS_MASK: u8 =
117 RELIABLE_FLAG_ACK_ONLY | RELIABLE_FLAG_UNORDERED | RELIABLE_FLAG_UNSEQUENCED;
118#[cfg(feature = "cryptography")]
119const E2E_NONCE_LEN: usize = 12;
120#[cfg(feature = "cryptography")]
121const E2E_TAG_CAP: usize = 32;
122
123#[derive(Clone, Debug, PartialEq, Eq)]
124struct WireContract {
125 shape: Option<MessageElement>,
126 target_senders: Option<Arc<[u64]>>,
127 has_reliable_header: bool,
128}
129
130#[inline]
132fn write_uleb128<T>(mut v: u64, out: &mut Vec<T>)
133where
134 T: From<u8>,
135{
136 loop {
137 let mut byte = (v & 0x7F) as u8;
138 v >>= 7;
139 if v != 0 {
140 byte |= 0x80;
141 }
142 out.push(T::from(byte));
143 if v == 0 {
144 break;
145 }
146 }
147}
148
149#[inline]
151fn read_uleb128(r: &mut ByteReader) -> Result<u64, TelemetryError> {
152 crate::varint::read_u64(r.buf, &mut r.off)
153}
154
155#[inline]
157fn uleb128_size(mut v: u64) -> usize {
158 let mut n = 1;
159 while v >= 0x80 {
160 v >>= 7;
161 n += 1;
162 }
163 n
164}
165
166#[inline]
168fn bitmap_popcount(bm: &[u8]) -> usize {
169 bm.iter().map(|b| b.count_ones() as usize).sum()
170}
171
172#[derive(Clone, Copy)]
177struct ByteReader<'a> {
178 buf: &'a [u8],
179 off: usize,
180}
181
182impl<'a> ByteReader<'a> {
183 fn new(buf: &'a [u8]) -> Self {
185 Self { buf, off: 0 }
186 }
187
188 fn remaining(&self) -> usize {
190 self.buf.len().saturating_sub(self.off)
191 }
192
193 #[inline(always)]
195 fn read_bytes(&mut self, n: usize) -> Result<&'a [u8], TelemetryError> {
196 if self.remaining() < n {
197 return Err(TelemetryError::Unpack("short read"));
198 }
199 let s = &self.buf[self.off..self.off + n];
200 self.off += n;
201 Ok(s)
202 }
203}
204
205#[inline]
206fn write_u32_le(v: u32, out: &mut Vec<u8>) {
207 out.extend_from_slice(&v.to_le_bytes());
208}
209
210#[inline]
211fn read_u32_le(r: &mut ByteReader) -> Result<u32, TelemetryError> {
212 let b = r.read_bytes(4)?;
213 Ok(u32::from_le_bytes([b[0], b[1], b[2], b[3]]))
214}
215
216#[inline]
217fn write_wire_shape(shape: MessageElement, out: &mut Vec<u8>) -> Result<(), TelemetryError> {
218 let dt = crate::config::message_data_type_code(shape.data_type());
219 let class = crate::config::message_class_code(shape.message_type());
220 let mut packed = dt | (class << 4);
221 if matches!(shape, MessageElement::Static(_, _, _)) {
222 packed |= 1 << 6;
223 }
224 out.push(packed);
225 if let MessageElement::Static(count, _, _) = shape {
226 let count = u64::try_from(count).map_err(|_| TelemetryError::Pack("wire shape count"))?;
227 write_uleb128(count, out);
228 }
229 Ok(())
230}
231
232#[inline]
233fn decode_wire_shape(r: &mut ByteReader) -> Result<MessageElement, TelemetryError> {
234 let packed = r.read_bytes(1)?[0];
235 let dt = crate::config::message_data_type_from_code(packed & 0x0F)
236 .ok_or(TelemetryError::Unpack("wire shape type"))?;
237 let class = crate::config::message_class_from_code((packed >> 4) & 0x03)
238 .ok_or(TelemetryError::Unpack("wire shape class"))?;
239 if (packed & (1 << 6)) != 0 {
240 let count = usize::try_from(read_uleb128(r)?)
241 .map_err(|_| TelemetryError::Unpack("wire shape count"))?;
242 Ok(MessageElement::Static(count, dt, class))
243 } else {
244 Ok(MessageElement::Dynamic(dt, class))
245 }
246}
247
248#[inline]
249fn write_wire_contract(
250 shape: Option<MessageElement>,
251 target_senders: &[u64],
252 has_reliable_header: bool,
253 out: &mut Vec<u8>,
254) -> Result<(), TelemetryError> {
255 let mut flags = 0u8;
259 if !target_senders.is_empty() {
260 flags |= CONTRACT_FLAG_TARGETS;
261 }
262 if shape.is_some() {
263 flags |= CONTRACT_FLAG_SHAPE;
264 }
265 if has_reliable_header {
266 flags |= CONTRACT_FLAG_RELIABLE_HEADER;
267 }
268 out.push(flags);
269 if let Some(shape) = shape {
270 write_wire_shape(shape, out)?;
271 }
272 if !target_senders.is_empty() {
273 write_uleb128(target_senders.len() as u64, out);
274 for hash in target_senders {
275 out.extend_from_slice(&hash.to_le_bytes());
276 }
277 }
278 Ok(())
279}
280
281fn wire_contract_size(shape: Option<MessageElement>, target_senders: &[u64]) -> usize {
283 1 + shape.map_or(0, |shape| match shape {
284 MessageElement::Static(count, _, _) => 1 + uleb128_size(count as u64),
285 _ => 1,
286 }) + if target_senders.is_empty() {
287 0
288 } else {
289 uleb128_size(target_senders.len() as u64) + target_senders.len() * 8
290 }
291}
292
293#[inline]
294fn decode_wire_contract(
295 r: &mut ByteReader,
296 has_contract: bool,
297) -> Result<WireContract, TelemetryError> {
298 if !has_contract {
299 return Ok(WireContract {
300 shape: None,
301 target_senders: None,
302 has_reliable_header: false,
303 });
304 }
305 let contract_len = usize::try_from(read_uleb128(r)?)
306 .map_err(|_| TelemetryError::Unpack("wire contract length"))?;
307 let contract_bytes = r.read_bytes(contract_len)?;
308 let mut cr = ByteReader::new(contract_bytes);
309 let flags = cr.read_bytes(1)?[0];
313 let shape = if (flags & CONTRACT_FLAG_SHAPE) != 0 {
314 Some(decode_wire_shape(&mut cr)?)
315 } else {
316 None
317 };
318 let target_senders: Option<Arc<[u64]>> = if (flags & CONTRACT_FLAG_TARGETS) != 0 {
319 let count = usize::try_from(read_uleb128(&mut cr)?)
320 .map_err(|_| TelemetryError::Unpack("wire contract target count"))?;
321 if count > cr.remaining() / 8 {
322 return Err(TelemetryError::Unpack("wire contract target count"));
323 }
324 if count == 0 {
325 None
326 } else {
327 let mut targets = Arc::<[u64]>::new_uninit_slice(count);
328 for slot in Arc::get_mut(&mut targets).expect("new target storage is unique") {
329 let bytes = cr.read_bytes(8)?;
330 slot.write(u64::from_le_bytes([
331 bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
332 ]));
333 }
334 Some(unsafe { targets.assume_init() })
336 }
337 } else {
338 None
339 };
340 if cr.remaining() != 0 {
341 return Err(TelemetryError::Unpack("wire contract trailing bytes"));
342 }
343 Ok(WireContract {
344 shape,
345 target_senders,
346 has_reliable_header: (flags & CONTRACT_FLAG_RELIABLE_HEADER) != 0,
347 })
348}
349
350#[inline]
351fn crc32_bytes(data: &[u8]) -> u32 {
352 let mut hasher = Crc32Hasher::new();
353 hasher.update(data);
354 hasher.finalize()
355}
356
357#[inline]
358fn append_crc32(out: &mut Vec<u8>) {
359 let crc = crc32_bytes(out);
360 out.extend_from_slice(&crc.to_le_bytes());
361}
362
363fn join_frame_with_crc(header: &[u8], payload: &[u8]) -> Arc<[u8]> {
366 let mut hasher = Crc32Hasher::new();
367 hasher.update(header);
368 hasher.update(payload);
369 let crc = hasher.finalize().to_le_bytes();
370 let mut frame = Arc::<[u8]>::new_uninit_slice(header.len() + payload.len() + crc.len());
371 let bytes = Arc::get_mut(&mut frame).unwrap();
372 for (slot, value) in bytes
373 .iter_mut()
374 .zip(header.iter().chain(payload).chain(&crc))
375 {
376 slot.write(*value);
377 }
378 unsafe { frame.assume_init() }
381}
382
383#[inline]
384fn split_crc32(buf: &[u8]) -> Result<(&[u8], u32), TelemetryError> {
385 if buf.len() < CRC32_BYTES {
386 return Err(TelemetryError::Unpack("short buffer"));
387 }
388 let data_len = buf.len() - CRC32_BYTES;
389 let crc = u32::from_le_bytes([
390 buf[data_len],
391 buf[data_len + 1],
392 buf[data_len + 2],
393 buf[data_len + 3],
394 ]);
395 Ok((&buf[..data_len], crc))
396}
397
398#[inline]
399fn verify_crc32(buf: &[u8]) -> Result<&[u8], TelemetryError> {
400 let (data, expected) = split_crc32(buf)?;
401 let actual = crc32_bytes(data);
402 if actual != expected {
403 return Err(TelemetryError::Unpack("crc32 mismatch"));
404 }
405 Ok(data)
406}
407
408#[cfg(feature = "cryptography")]
409#[inline]
410fn e2e_nonce_for_packet(pkt: &Packet) -> [u8; E2E_NONCE_LEN] {
411 let mut nonce = [0u8; E2E_NONCE_LEN];
412 nonce[..4].copy_from_slice(&pkt.data_type().as_u32().to_le_bytes());
413 nonce[4..10].copy_from_slice(&(pkt.timestamp() & 0x0000_FFFF_FFFF_FFFF).to_le_bytes()[..6]);
414 nonce[10..].copy_from_slice(&pkt.nonce().to_le_bytes());
415 nonce
416}
417
418#[cfg(feature = "cryptography")]
419fn write_encrypted_payload(
420 pkt: &Packet,
421 key_id: u32,
422 plaintext_wire_payload: &[u8],
423 out: &mut Vec<u8>,
424) -> TelemetryResult<()> {
425 let aad_end = out.len();
426 let nonce = e2e_nonce_for_packet(pkt);
427 let mut ciphertext = vec![0u8; plaintext_wire_payload.len()];
428 let mut tag = [0u8; E2E_TAG_CAP];
429 let (ciphertext_len, tag_len) = crate::crypto::seal_with_registered_crypto(
430 key_id,
431 &nonce,
432 &out[..aad_end],
433 plaintext_wire_payload,
434 &mut ciphertext,
435 &mut tag,
436 )?;
437 if ciphertext_len > ciphertext.len() || tag_len > tag.len() {
438 return Err(TelemetryError::SizeMismatchError);
439 }
440 write_uleb128(u64::from(key_id), out);
441 write_uleb128(plaintext_wire_payload.len() as u64, out);
442 write_uleb128(nonce.len() as u64, out);
443 out.extend_from_slice(&nonce);
444 write_uleb128(tag_len as u64, out);
445 out.extend_from_slice(&tag[..tag_len]);
446 out.extend_from_slice(&ciphertext[..ciphertext_len]);
447 Ok(())
448}
449
450#[cfg(feature = "cryptography")]
451fn read_encrypted_payload(
452 r: &mut ByteReader,
453 aad: &[u8],
454 plaintext_len: usize,
455) -> TelemetryResult<Vec<u8>> {
456 let key_id = u32::try_from(read_uleb128(r)?)
457 .map_err(|_| TelemetryError::Unpack("e2e key id too large"))?;
458 let wire_payload_len = usize::try_from(read_uleb128(r)?)
459 .map_err(|_| TelemetryError::Unpack("e2e payload length"))?;
460 if wire_payload_len > plaintext_len {
461 return Err(TelemetryError::Unpack("bad e2e payload length"));
462 }
463 let nonce_len = usize::try_from(read_uleb128(r)?)
464 .map_err(|_| TelemetryError::Unpack("e2e nonce length"))?;
465 if nonce_len == 0 || nonce_len > 64 {
466 return Err(TelemetryError::Unpack("bad e2e nonce length"));
467 }
468 let nonce = r.read_bytes(nonce_len)?;
469 let tag_len =
470 usize::try_from(read_uleb128(r)?).map_err(|_| TelemetryError::Unpack("e2e tag length"))?;
471 if tag_len == 0 || tag_len > E2E_TAG_CAP {
472 return Err(TelemetryError::Unpack("bad e2e tag length"));
473 }
474 let tag = r.read_bytes(tag_len)?;
475 let ciphertext_len = r.remaining();
476 let ciphertext = r.read_bytes(ciphertext_len)?;
477 let mut plaintext = vec![0u8; wire_payload_len];
478 let opened_len = crate::crypto::open_with_registered_crypto(
479 key_id,
480 nonce,
481 aad,
482 ciphertext,
483 tag,
484 &mut plaintext,
485 )?;
486 if opened_len != wire_payload_len {
487 return Err(TelemetryError::SizeMismatchError);
488 }
489 Ok(plaintext)
490}
491
492#[inline]
493fn write_reliable_header(h: ReliableHeader, out: &mut Vec<u8>) {
494 out.push(h.flags);
495 write_u32_le(h.seq, out);
496 write_u32_le(h.ack, out);
497}
498
499#[inline]
500fn reliable_compact_size(h: ReliableHeader) -> usize {
501 let seq_present = (h.flags & RELIABLE_FLAG_ACK_ONLY) == 0 || h.seq != 0;
502 let ack_present = h.ack != 0 || (h.flags & RELIABLE_FLAG_ACK_ONLY) != 0;
503 1 + if seq_present {
504 uleb128_size(h.seq as u64)
505 } else {
506 0
507 } + if ack_present {
508 uleb128_size(h.ack as u64)
509 } else {
510 0
511 }
512}
513
514#[inline]
515fn should_compact_reliable_header(h: ReliableHeader) -> bool {
516 reliable_compact_size(h) < RELIABLE_HEADER_BYTES
517}
518
519#[inline]
520fn reliable_wire_size(h: ReliableHeader, compact: bool) -> usize {
521 if compact {
522 reliable_compact_size(h)
523 } else {
524 RELIABLE_HEADER_BYTES
525 }
526}
527
528pub(crate) fn write_reliable_header_encoded(h: ReliableHeader, compact: bool, out: &mut Vec<u8>) {
529 if !compact {
530 write_reliable_header(h, out);
531 return;
532 }
533
534 let seq_present = (h.flags & RELIABLE_FLAG_ACK_ONLY) == 0 || h.seq != 0;
535 let ack_present = h.ack != 0 || (h.flags & RELIABLE_FLAG_ACK_ONLY) != 0;
536 let mut wire_flags = h.flags & RELIABLE_PUBLIC_FLAGS_MASK;
537 if seq_present {
538 wire_flags |= RELIABLE_WIRE_FLAG_SEQ_PRESENT;
539 }
540 if ack_present {
541 wire_flags |= RELIABLE_WIRE_FLAG_ACK_PRESENT;
542 }
543 out.push(wire_flags);
544 if seq_present {
545 write_uleb128(h.seq as u64, out);
546 }
547 if ack_present {
548 write_uleb128(h.ack as u64, out);
549 }
550}
551
552#[inline]
553fn read_reliable_header(r: &mut ByteReader) -> Result<ReliableHeader, TelemetryError> {
554 let flags = r.read_bytes(1)?[0];
555 let seq = read_u32_le(r)?;
556 let ack = read_u32_le(r)?;
557 Ok(ReliableHeader { flags, seq, ack })
558}
559
560fn read_reliable_header_compact(r: &mut ByteReader) -> Result<ReliableHeader, TelemetryError> {
561 let wire_flags = r.read_bytes(1)?[0];
562 let seq = if (wire_flags & RELIABLE_WIRE_FLAG_SEQ_PRESENT) != 0 {
563 u32::try_from(read_uleb128(r)?)
564 .map_err(|_| TelemetryError::Unpack("reliable seq too large"))?
565 } else {
566 0
567 };
568 let ack = if (wire_flags & RELIABLE_WIRE_FLAG_ACK_PRESENT) != 0 {
569 u32::try_from(read_uleb128(r)?)
570 .map_err(|_| TelemetryError::Unpack("reliable ack too large"))?
571 } else {
572 0
573 };
574 Ok(ReliableHeader {
575 flags: wire_flags & RELIABLE_PUBLIC_FLAGS_MASK,
576 seq,
577 ack,
578 })
579}
580
581#[inline]
582fn read_reliable_header_encoded(
583 r: &mut ByteReader,
584 compact: bool,
585) -> Result<ReliableHeader, TelemetryError> {
586 if compact {
587 read_reliable_header_compact(r)
588 } else {
589 read_reliable_header(r)
590 }
591}
592
593#[cfg(feature = "std")]
594static ADDRESS_BOOK: OnceLock<Mutex<BTreeMap<u32, Arc<str>>>> = OnceLock::new();
595
596#[cfg(feature = "std")]
597fn address_book() -> &'static Mutex<BTreeMap<u32, Arc<str>>> {
598 ADDRESS_BOOK.get_or_init(|| Mutex::new(BTreeMap::new()))
599}
600
601#[inline]
602pub(crate) fn source_address_for_sender(sender: &str) -> u32 {
603 let addr = sender_address_u32(sender);
604 remember_source_address(addr, sender);
605 addr
606}
607
608#[cfg(feature = "std")]
609pub(crate) fn remember_source_address(addr: u32, sender: &str) {
610 address_book()
611 .lock()
612 .expect("wire address book poisoned")
613 .entry(addr)
614 .or_insert_with(|| Arc::<str>::from(sender));
615}
616
617#[cfg(not(feature = "std"))]
618pub(crate) fn remember_source_address(_addr: u32, _sender: &str) {}
619
620#[cfg(feature = "std")]
621fn sender_name_for_address(addr: u32) -> Arc<str> {
622 address_book()
623 .lock()
624 .expect("wire address book poisoned")
625 .get(&addr)
626 .cloned()
627 .unwrap_or_else(|| format_sender_address(addr))
628}
629
630#[cfg(not(feature = "std"))]
631fn sender_name_for_address(addr: u32) -> Arc<str> {
632 format_sender_address(addr)
633}
634
635fn format_sender_address(addr: u32) -> Arc<str> {
636 let mut bytes = [0u8; 16];
638 let mut start = bytes.len();
639 let mut remaining = addr;
640 loop {
641 start -= 1;
642 bytes[start] = b'0' + (remaining % 10) as u8;
643 remaining /= 10;
644 if remaining == 0 {
645 break;
646 }
647 }
648 start -= 6;
649 bytes[start..start + 6].copy_from_slice(b"@addr:");
650 Arc::from(core::str::from_utf8(&bytes[start..]).expect("numeric alias is ASCII"))
651}
652
653const EP_BITMAP_BITS: usize = 256;
659#[cfg(test)]
660use crate::MAX_VALUE_DATA_ENDPOINT;
661
662const EP_BITMAP_BYTES: usize = EP_BITMAP_BITS.div_ceil(8);
664
665#[inline]
670fn build_endpoint_bitmap(eps: &[DataEndpoint]) -> [u8; EP_BITMAP_BYTES] {
671 let mut bm = [0u8; EP_BITMAP_BYTES];
672 for &ep in eps {
673 let idx = ep.as_u32() as usize;
674 debug_assert!(idx < EP_BITMAP_BITS, "endpoint discriminant out of range");
675 if idx < EP_BITMAP_BITS {
676 let byte = idx / 8;
677 let bit = idx % 8;
678 bm[byte] |= 1u8 << bit;
679 }
680 }
681 bm
682}
683
684fn expand_endpoint_bitmap(bm: &[u8]) -> TelemetryResult<Arc<[DataEndpoint]>> {
686 if bm.len() != EP_BITMAP_BYTES {
687 return Err(TelemetryError::Unpack("bad endpoint bitmap size"));
688 }
689 let count = bitmap_popcount(bm);
692 let mut endpoints = Arc::<[DataEndpoint]>::new_uninit_slice(count);
693 let slots = Arc::get_mut(&mut endpoints).expect("new endpoint storage is unique");
694 let mut written = 0;
695 for (byte_index, &byte) in bm.iter().enumerate() {
696 let mut bits = byte;
697 while bits != 0 {
698 let idx = byte_index * 8 + bits.trailing_zeros() as usize;
699 slots[written].write(
700 DataEndpoint::try_from_u32(idx as u32)
701 .ok_or(TelemetryError::Unpack("bad endpoint bit set"))?,
702 );
703 written += 1;
704 bits &= bits - 1;
705 }
706 }
707 debug_assert_eq!(written, count);
709 Ok(unsafe { endpoints.assume_init() })
710}
711
712pub(crate) fn unique_sorted_endpoints(
713 endpoints: &[DataEndpoint],
714) -> impl Iterator<Item = DataEndpoint> + '_ {
715 let mut previous = None;
716 core::iter::from_fn(move || {
717 let next = endpoints
718 .iter()
719 .copied()
720 .filter(|endpoint| previous.is_none_or(|previous| *endpoint > previous))
721 .min();
722 previous = next.or(previous);
725 next
726 })
727}
728
729fn endpoint_arc_from_iter(
730 count: usize,
731 endpoints: impl Iterator<Item = DataEndpoint>,
732) -> TelemetryResult<Arc<[DataEndpoint]>> {
733 let mut output = Arc::<[DataEndpoint]>::new_uninit_slice(count);
734 let slots = Arc::get_mut(&mut output).unwrap();
735 let mut written = 0;
736 for endpoint in endpoints {
737 if written == count {
738 return Err(TelemetryError::Unpack("endpoint count mismatch"));
739 }
740 slots[written].write(endpoint);
741 written += 1;
742 }
743 if written != count {
744 return Err(TelemetryError::Unpack("endpoint count mismatch"));
745 }
746 Ok(unsafe { output.assume_init() })
748}
749fn endpoint_list_size(eps: &[DataEndpoint]) -> usize {
750 unique_sorted_endpoints(eps)
751 .map(|ep| uleb128_size(u64::from(ep.0)))
752 .sum()
753}
754fn explicit_endpoint_list(eps: &[DataEndpoint]) -> bool {
755 eps.iter().any(|ep| ep.0 >= EP_BITMAP_BITS as u32) || endpoint_list_size(eps) < EP_BITMAP_BYTES
756}
757fn endpoints_match_schema(ty: DataType, eps: &[DataEndpoint]) -> bool {
758 let meta = message_meta(ty);
759 unique_sorted_endpoints(eps).eq(unique_sorted_endpoints(meta.endpoints_ref()))
760}
761fn read_endpoint_list<'a>(r: &mut ByteReader<'a>, count: usize) -> TelemetryResult<&'a [u8]> {
762 let start = r.off;
763 let mut previous = None;
764 for _ in 0..count {
765 let id = u32::try_from(read_uleb128(r)?)
766 .map_err(|_| TelemetryError::Unpack("endpoint too large"))?;
767 if previous.is_some_and(|previous| id <= previous) {
768 return Err(TelemetryError::Unpack(
769 "endpoint list is not unique and sorted",
770 ));
771 }
772 previous = Some(id);
773 }
774 Ok(&r.buf[start..r.off])
775}
776fn endpoint_list_iter(bytes: &[u8]) -> impl Iterator<Item = DataEndpoint> + '_ {
777 let mut r = ByteReader::new(bytes);
778 core::iter::from_fn(move || {
779 if r.remaining() == 0 {
780 return None;
781 }
782 read_uleb128(&mut r)
783 .ok()
784 .and_then(|id| u32::try_from(id).ok())
785 .map(DataEndpoint)
786 })
787}
788
789#[inline]
790fn schema_endpoints_from_type(ty: DataType, nep: usize) -> TelemetryResult<Arc<[DataEndpoint]>> {
791 let meta = message_meta(ty);
794 let schema = meta.endpoints_ref();
795 if schema.len() == nep
796 && schema
797 .windows(2)
798 .all(|pair| pair[0].as_u32() < pair[1].as_u32())
799 && schema
800 .iter()
801 .all(|ep| DataEndpoint::try_from_u32(ep.as_u32()).is_some())
802 {
803 #[cfg(feature = "std")]
806 return Ok(meta.endpoints);
807 #[cfg(not(feature = "std"))]
808 return Ok(Arc::from(schema));
809 }
810 endpoint_arc_from_iter(nep, unique_sorted_endpoints(schema))
811}
812
813#[inline]
814fn endpoints_from_wire_or_schema(
815 r: &mut ByteReader<'_>,
816 bitmap_present: bool,
817 list_present: bool,
818 ty: Option<DataType>,
819 nep: usize,
820) -> TelemetryResult<Arc<[DataEndpoint]>> {
821 if list_present {
822 if bitmap_present {
823 return Err(TelemetryError::Unpack("ambiguous endpoint encoding"));
824 }
825 let bytes = read_endpoint_list(r, nep)?;
826 #[cfg(feature = "std")]
827 if let Some(meta) = ty.and_then(crate::config::try_get_message_meta)
828 && endpoint_list_iter(bytes).eq(meta.endpoints.iter().copied())
829 {
830 return Ok(meta.endpoints);
831 }
832 return endpoint_arc_from_iter(nep, endpoint_list_iter(bytes));
833 }
834 if bitmap_present {
835 let bm = r.read_bytes(EP_BITMAP_BYTES)?;
836 let endpoints = expand_endpoint_bitmap(bm)?;
837 if endpoints.len() != nep {
838 return Err(TelemetryError::Unpack("endpoint count mismatch"));
839 }
840 Ok(endpoints)
841 } else {
842 let ty = ty.ok_or(TelemetryError::InvalidType)?;
843 schema_endpoints_from_type(ty, nep)
844 }
845}
846
847#[inline]
848fn data_type_id_from_wire(ty_v: u64) -> TelemetryResult<u32> {
849 let ty_u32 = u32::try_from(ty_v).map_err(|_| TelemetryError::Unpack("type too large"))?;
850 Ok(ty_u32)
851}
852
853pub fn pack_packet(pkt: &Packet) -> Arc<[u8]> {
866 if is_reliable_type(pkt.data_type()) {
867 let hdr = ReliableHeader {
870 flags: RELIABLE_FLAG_UNSEQUENCED,
871 seq: 0,
872 ack: 0,
873 };
874 return pack_packet_with_reliable(pkt, hdr);
875 }
876 pack_packet_inner(pkt, None)
877}
878
879pub fn pack_packet_with_reliable(pkt: &Packet, header: ReliableHeader) -> Arc<[u8]> {
883 pack_packet_inner(pkt, Some(header))
884}
885
886pub fn pack_reliable_ack(sender: &str, ty: DataType, timestamp_ms: u64, ack: u32) -> Arc<[u8]> {
891 let source_address = source_address_for_sender(sender);
892
893 let mut out = Vec::with_capacity(32 + EP_BITMAP_BYTES + CRC32_BYTES);
895
896 let flags: u8 = FLAG_ENDPOINT_LIST_PRESENT | FLAG_RELIABLE_HEADER_PRESENT;
897 out.push(flags);
898 out.push(0u8); write_uleb128(ty.as_u32() as u64, &mut out);
901 write_uleb128(0u64, &mut out); write_uleb128(timestamp_ms, &mut out);
903 write_uleb128(source_address as u64, &mut out);
904
905 let reliable = ReliableHeader {
906 flags: RELIABLE_FLAG_ACK_ONLY,
907 seq: 0,
908 ack,
909 };
910 if should_compact_reliable_header(reliable) {
911 out[0] |= FLAG_COMPACT_RELIABLE_HEADER;
912 write_reliable_header_encoded(reliable, true, &mut out);
913 } else {
914 write_reliable_header_encoded(reliable, false, &mut out);
915 }
916 append_crc32(&mut out);
917
918 Arc::<[u8]>::from(out)
919}
920
921fn pack_packet_inner(pkt: &Packet, reliable: Option<ReliableHeader>) -> Arc<[u8]> {
922 pack_packet_inner_with_contract(
923 pkt,
924 reliable,
925 pkt.wire_shape(),
926 pkt.wire_target_senders(),
927 None,
928 )
929 .expect("plaintext packet packing failed")
930}
931
932pub(crate) fn pack_packet_with_wire_contract(
952 pkt: &Packet,
953 reliable: Option<ReliableHeader>,
954 shape: Option<MessageElement>,
955 target_senders: &[u64],
956) -> TelemetryResult<Arc<[u8]>> {
957 pack_packet_inner_with_contract(pkt, reliable, shape, target_senders, None)
958}
959
960#[derive(Clone, Copy, Debug)]
961#[cfg_attr(not(feature = "cryptography"), allow(dead_code))]
962pub(crate) struct E2eSealConfig {
963 pub key_id: u32,
964}
965
966#[cfg(feature = "cryptography")]
967pub(crate) fn pack_packet_with_wire_contract_e2e(
968 pkt: &Packet,
969 reliable: Option<ReliableHeader>,
970 shape: Option<MessageElement>,
971 target_senders: &[u64],
972 e2e: E2eSealConfig,
973) -> TelemetryResult<Arc<[u8]>> {
974 pack_packet_inner_with_contract(pkt, reliable, shape, target_senders, Some(e2e))
975}
976
977fn pack_packet_inner_with_contract(
978 pkt: &Packet,
979 reliable: Option<ReliableHeader>,
980 shape: Option<MessageElement>,
981 target_senders: &[u64],
982 e2e: Option<E2eSealConfig>,
983) -> TelemetryResult<Arc<[u8]>> {
984 with_packet_frame_parts(
985 pkt,
986 reliable,
987 shape,
988 target_senders,
989 e2e,
990 |header, payload| Ok(join_frame_with_crc(header, payload)),
991 )
992}
993
994pub(crate) fn with_plain_packet_parts<T>(
997 pkt: &Packet,
998 consume: impl FnOnce(&[u8], &[u8]) -> TelemetryResult<T>,
999) -> TelemetryResult<T> {
1000 let reliable = is_reliable_type(pkt.data_type()).then_some(ReliableHeader {
1001 flags: RELIABLE_FLAG_UNSEQUENCED,
1002 seq: 0,
1003 ack: 0,
1004 });
1005 with_packet_frame_parts(
1006 pkt,
1007 reliable,
1008 pkt.wire_shape(),
1009 pkt.wire_target_senders(),
1010 None,
1011 consume,
1012 )
1013}
1014
1015fn packet_endpoint_bitmap_present(
1016 pkt: &Packet,
1017 shape: Option<MessageElement>,
1018 target_senders: &[u64],
1019) -> bool {
1020 let carries_wire_contract = shape.is_some() || !target_senders.is_empty();
1021 let endpoints_are_schema_default = endpoints_match_schema(pkt.data_type(), pkt.endpoints());
1022 let fixed_control_endpoints = matches!(
1027 pkt.data_type(),
1028 DataType::ReliableAck | DataType::ReliablePartialAck | DataType::ReliablePacketRequest
1029 );
1030 pkt.data_type().0 > DataType::P2pMessage.0
1033 || !endpoints_are_schema_default
1034 || (carries_wire_contract && !fixed_control_endpoints)
1035}
1036
1037fn with_packet_frame_parts<T>(
1038 pkt: &Packet,
1039 reliable: Option<ReliableHeader>,
1040 shape: Option<MessageElement>,
1041 target_senders: &[u64],
1042 #[cfg_attr(not(feature = "cryptography"), allow(unused_variables))] e2e: Option<E2eSealConfig>,
1043 consume: impl FnOnce(&[u8], &[u8]) -> TelemetryResult<T>,
1044) -> TelemetryResult<T> {
1045 let carries_wire_contract = shape.is_some() || !target_senders.is_empty();
1046 let endpoint_bitmap_present = packet_endpoint_bitmap_present(pkt, shape, target_senders);
1047 let endpoint_list_present = endpoint_bitmap_present && explicit_endpoint_list(pkt.endpoints());
1048 let nep_unique = unique_sorted_endpoints(pkt.endpoints()).count();
1049 let endpoint_bytes = if endpoint_list_present {
1050 endpoint_list_size(pkt.endpoints())
1051 } else if endpoint_bitmap_present {
1052 EP_BITMAP_BYTES
1053 } else {
1054 0
1055 };
1056
1057 let source_address = source_address_for_sender(pkt.sender());
1058
1059 let payload = pkt.payload();
1061 let (payload_compressed, payload_wire) = payload_compression::compress_if_beneficial(payload);
1062
1063 let reliable_is_compact = reliable.is_some_and(should_compact_reliable_header);
1067 let reliable_len = if let Some(hdr) = reliable {
1068 reliable_wire_size(hdr, reliable_is_compact)
1069 } else {
1070 0
1071 };
1072 let contract_bytes = wire_contract_size(shape, target_senders);
1073 let contract_len = if carries_wire_contract {
1074 uleb128_size(contract_bytes as u64) + contract_bytes
1075 } else {
1076 0
1077 };
1078 let capacity = header_size_bytes(pkt)
1079 + endpoint_bytes
1080 + contract_len
1081 + reliable_len
1082 + payload_wire.len()
1083 + CRC32_BYTES;
1084 #[cfg(feature = "cryptography")]
1085 let capacity = capacity
1086 + e2e.map_or(0, |seal| {
1087 uleb128_size(u64::from(seal.key_id))
1088 + uleb128_size(payload_wire.len() as u64)
1089 + uleb128_size(E2E_NONCE_LEN as u64)
1090 + E2E_NONCE_LEN
1091 + uleb128_size(E2E_TAG_CAP as u64)
1092 + E2E_TAG_CAP
1093 });
1094 #[cfg(feature = "cryptography")]
1098 let encrypted = e2e.is_some();
1099 #[cfg(not(feature = "cryptography"))]
1100 let encrypted = false;
1101 let scratch_capacity = if encrypted {
1102 capacity
1103 } else {
1104 capacity - payload_wire.len() - CRC32_BYTES
1105 };
1106 let mut out = Vec::with_capacity(scratch_capacity);
1107 #[cfg(debug_assertions)]
1108 let initial_capacity = out.capacity();
1109
1110 let mut flags: u8 = 0;
1112 if payload_compressed {
1113 flags |= FLAG_COMPRESSED_PAYLOAD;
1114 }
1115 if carries_wire_contract {
1116 flags |= FLAG_WIRE_CONTRACT;
1117 }
1118 if pkt.nonce() != 0 {
1119 flags |= FLAG_PACKET_NONCE;
1120 }
1121 if endpoint_list_present {
1122 flags |= FLAG_ENDPOINT_LIST_PRESENT;
1123 } else if endpoint_bitmap_present {
1124 flags |= FLAG_ENDPOINT_BITMAP_PRESENT;
1125 }
1126 if reliable.is_some() {
1127 flags |= FLAG_RELIABLE_HEADER_PRESENT;
1128 }
1129 if reliable_is_compact {
1130 flags |= FLAG_COMPACT_RELIABLE_HEADER;
1131 }
1132 #[cfg(feature = "cryptography")]
1133 if e2e.is_some() {
1134 flags |= FLAG_E2E_ENCRYPTED_PAYLOAD;
1135 }
1136 out.push(flags);
1137
1138 assert!(
1139 nep_unique <= u8::MAX as usize,
1140 "too many endpoints selected to fit in NEP u8"
1141 );
1142 out.push(nep_unique as u8);
1143
1144 write_uleb128(pkt.data_type().as_u32() as u64, &mut out);
1146 write_uleb128(pkt.data_size() as u64, &mut out);
1147 write_uleb128(pkt.timestamp(), &mut out);
1148 if pkt.nonce() != 0 {
1149 write_uleb128(pkt.nonce() as u64, &mut out);
1150 }
1151
1152 write_uleb128(source_address as u64, &mut out);
1153
1154 if endpoint_list_present {
1155 for endpoint in unique_sorted_endpoints(pkt.endpoints()) {
1156 write_uleb128(u64::from(endpoint.0), &mut out);
1157 }
1158 } else if endpoint_bitmap_present {
1159 out.extend_from_slice(&build_endpoint_bitmap(pkt.endpoints()));
1160 }
1161 if (flags & FLAG_WIRE_CONTRACT) != 0 {
1162 write_uleb128(contract_bytes as u64, &mut out);
1166 write_wire_contract(shape, target_senders, reliable.is_some(), &mut out)?;
1167 }
1168 if let Some(hdr) = reliable {
1169 write_reliable_header_encoded(hdr, reliable_is_compact, &mut out);
1170 }
1171 #[cfg(feature = "cryptography")]
1172 if let Some(e2e) = e2e {
1173 write_encrypted_payload(pkt, e2e.key_id, &payload_wire, &mut out)?;
1174 return consume(&out, &[]);
1175 }
1176 #[cfg(debug_assertions)]
1177 debug_assert_eq!(
1178 out.capacity(),
1179 initial_capacity,
1180 "packet header grew its buffer"
1181 );
1182 consume(&out, &payload_wire)
1183}
1184
1185pub fn unpack_packet(buf: &[u8]) -> Result<Packet, TelemetryError> {
1211 unpack_packet_with_role(buf, false)
1212}
1213
1214pub(crate) fn unpack_packet_with_role(buf: &[u8], managed: bool) -> Result<Packet, TelemetryError> {
1215 let data = verify_crc32(buf)?;
1216 if data.is_empty() {
1217 return Err(TelemetryError::Unpack("short prelude"));
1218 }
1219 let mut r = ByteReader::new(data);
1220
1221 let flags = r.read_bytes(1)?[0];
1222 let payload_is_compressed = (flags & FLAG_COMPRESSED_PAYLOAD) != 0;
1223 let endpoint_bitmap_present = (flags & FLAG_ENDPOINT_BITMAP_PRESENT) != 0;
1224 let compact_reliable_header = (flags & FLAG_COMPACT_RELIABLE_HEADER) != 0;
1225 #[cfg(feature = "cryptography")]
1226 let payload_is_encrypted = (flags & FLAG_E2E_ENCRYPTED_PAYLOAD) != 0;
1227 #[cfg(not(feature = "cryptography"))]
1228 if (flags & 0x10) != 0 {
1229 return Err(TelemetryError::Unpack("e2e crypto unsupported"));
1230 }
1231
1232 let nep = r.read_bytes(1)?[0] as usize;
1233
1234 let ty_v = read_uleb128(&mut r)?;
1235 let dsz = read_uleb128(&mut r)? as usize; let ts_v = read_uleb128(&mut r)?;
1237 let nonce = if (flags & FLAG_PACKET_NONCE) != 0 {
1238 u16::try_from(read_uleb128(&mut r)?)
1239 .map_err(|_| TelemetryError::Unpack("packet nonce too large"))?
1240 } else {
1241 0
1242 };
1243 let source_address = u32::try_from(read_uleb128(&mut r)?)
1244 .map_err(|_| TelemetryError::Unpack("source address too large"))?;
1245 let sender_str = sender_name_for_address(source_address);
1246 let ty_u32 = data_type_id_from_wire(ty_v)?;
1247 let known_ty = DataType::try_from_u32(ty_u32);
1248 let endpoint_bytes = if endpoint_bitmap_present {
1249 EP_BITMAP_BYTES
1250 } else {
1251 0
1252 };
1253
1254 if !payload_is_compressed {
1257 if r.remaining() < endpoint_bytes + dsz {
1258 return Err(TelemetryError::Unpack("short buffer"));
1259 }
1260 } else if r.remaining() < endpoint_bytes + 1 {
1261 return Err(TelemetryError::Unpack("short buffer"));
1262 }
1263
1264 let eps = endpoints_from_wire_or_schema(
1265 &mut r,
1266 endpoint_bitmap_present,
1267 flags & FLAG_ENDPOINT_LIST_PRESENT != 0,
1268 known_ty,
1269 nep,
1270 )?;
1271
1272 let contract = decode_wire_contract(&mut r, (flags & FLAG_WIRE_CONTRACT) != 0)?;
1273 let ty = known_ty
1274 .or_else(|| contract.shape.map(|_| DataType(ty_u32)))
1275 .ok_or(TelemetryError::InvalidType)?;
1276
1277 let mut reliable_hdr: Option<ReliableHeader> = None;
1279 if flags & FLAG_RELIABLE_HEADER_PRESENT != 0 || contract.has_reliable_header {
1280 let hdr = read_reliable_header_encoded(&mut r, compact_reliable_header)?;
1281 if (hdr.flags & RELIABLE_FLAG_ACK_ONLY) != 0 {
1282 return Err(TelemetryError::Unpack("reliable control frame"));
1283 }
1284 reliable_hdr = Some(hdr);
1285 }
1286
1287 let payload_copies = if payload_is_compressed { 3 } else { 1 };
1291 #[cfg(feature = "cryptography")]
1292 let payload_copies = payload_copies + usize::from(payload_is_encrypted);
1293 let small_ack = matches!(ty, DataType::ReliableAck | DataType::ReliablePartialAck)
1294 && dsz <= 32
1295 && payload_copies == 1;
1296 if crate::memory_admission::supports_work_kinds()
1297 && !small_ack
1298 && buf.len() <= 128
1299 && flags & 0x11 == 0
1300 && crate::memory_admission::protected_control_shape(
1301 ty,
1302 nep,
1303 contract
1304 .target_senders
1305 .as_ref()
1306 .map_or(0, |owners| owners.len()),
1307 contract.shape,
1308 reliable_hdr.is_some(),
1309 managed,
1310 )
1311 {
1312 crate::memory_admission::check_small_protected_decode(buf.len())?;
1313 } else {
1314 crate::memory_admission::check(
1315 if small_ack {
1316 512
1317 } else {
1318 dsz.saturating_mul(payload_copies).saturating_add(512)
1319 },
1320 dsz.saturating_add(32),
1321 )?;
1322 }
1323 let payload: StandardSmallPayload = {
1325 #[cfg(feature = "cryptography")]
1326 let payload_wire_owned;
1327 #[cfg(feature = "cryptography")]
1328 let payload_wire: &[u8] = if payload_is_encrypted {
1329 let aad_end = r.off;
1330 payload_wire_owned = read_encrypted_payload(&mut r, &data[..aad_end], dsz)?;
1331 &payload_wire_owned
1332 } else if !payload_is_compressed {
1333 r.read_bytes(dsz)?
1334 } else {
1335 let comp_len = r.remaining();
1336 r.read_bytes(comp_len)?
1337 };
1338
1339 #[cfg(not(feature = "cryptography"))]
1340 let payload_wire: &[u8] = if !payload_is_compressed {
1341 r.read_bytes(dsz)?
1342 } else {
1343 let comp_len = r.remaining();
1344 r.read_bytes(comp_len)?
1345 };
1346
1347 if payload_is_compressed {
1348 let decompressed = payload_compression::decompress(payload_wire, dsz)?;
1349 crate::memory_admission::check(dsz.saturating_add(512), dsz.saturating_add(32))?;
1350 StandardSmallPayload::new(&decompressed)
1351 } else {
1352 if payload_wire.len() != dsz {
1353 return Err(TelemetryError::Unpack("payload length mismatch"));
1354 }
1355 StandardSmallPayload::new(payload_wire)
1356 }
1357 };
1358
1359 let _ = reliable_hdr;
1363 Packet::new_with_owned_wire_contract(
1364 ty,
1365 eps,
1366 sender_str,
1367 ts_v,
1368 nonce,
1369 payload,
1370 contract.shape,
1371 contract.target_senders,
1372 )
1373}
1374
1375pub fn peek_envelope(buf: &[u8]) -> TelemetryResult<TelemetryEnvelope> {
1396 Ok(peek_routing_envelope(buf)?.into_owned())
1397}
1398
1399#[derive(Clone, Debug)]
1403pub(crate) struct RoutingEnvelope<'a> {
1404 pub ty: DataType,
1405 bitmap: [u64; EP_BITMAP_BYTES / 8],
1406 endpoint_list: Option<&'a [u8]>,
1407 schema_endpoints: Option<crate::MessageMeta>,
1408 pub source_address: u32,
1409 pub timestamp_ms: u64,
1410 pub wire_shape: Option<MessageElement>,
1411 pub is_reliable: bool,
1412 targets: &'a [u8],
1413 has_reliable_header: bool,
1414}
1415pub(crate) struct RoutingEndpointIter<'a> {
1416 envelope: &'a RoutingEnvelope<'a>,
1417 word: usize,
1418 bits: u64,
1419 list_offset: usize,
1420 previous: Option<DataEndpoint>,
1421 finished: bool,
1422}
1423impl Iterator for RoutingEndpointIter<'_> {
1424 type Item = DataEndpoint;
1425 #[inline(never)]
1426 fn next(&mut self) -> Option<DataEndpoint> {
1427 if self.finished {
1428 return None;
1429 }
1430 if let Some(bytes) = self.envelope.endpoint_list {
1431 let mut reader = ByteReader {
1432 buf: bytes,
1433 off: self.list_offset,
1434 };
1435 if reader.remaining() == 0 {
1436 self.finished = true;
1437 return None;
1438 }
1439 let endpoint = read_uleb128(&mut reader)
1440 .ok()
1441 .and_then(|id| u32::try_from(id).ok())
1442 .map(DataEndpoint);
1443 self.list_offset = reader.off;
1444 return endpoint;
1445 }
1446 if let Some(meta) = &self.envelope.schema_endpoints {
1447 let next = meta
1448 .endpoints_ref()
1449 .iter()
1450 .copied()
1451 .filter(|ep| self.previous.is_none_or(|previous| *ep > previous))
1452 .min();
1453 self.previous = next;
1454 self.finished = next.is_none();
1455 return next;
1456 }
1457 while self.bits == 0 {
1458 self.word += 1;
1459 if self.word == self.envelope.bitmap.len() {
1460 self.finished = true;
1461 return None;
1462 }
1463 self.bits = self.envelope.bitmap[self.word];
1464 }
1465 let bit = self.bits.trailing_zeros();
1466 self.bits &= self.bits - 1;
1467 Some(DataEndpoint((self.word * 64 + bit as usize) as u32))
1468 }
1469}
1470
1471impl RoutingEnvelope<'_> {
1472 pub fn endpoints(&self) -> RoutingEndpointIter<'_> {
1473 RoutingEndpointIter {
1474 envelope: self,
1475 word: 0,
1476 bits: self.bitmap[0],
1477 list_offset: 0,
1478 previous: None,
1479 finished: false,
1480 }
1481 }
1482 pub fn target_senders(&self) -> impl ExactSizeIterator<Item = u64> + '_ {
1483 self.targets
1484 .as_chunks::<8>()
1485 .0
1486 .iter()
1487 .map(|bytes| u64::from_le_bytes(*bytes))
1488 }
1489 fn into_owned(self) -> TelemetryEnvelope {
1490 TelemetryEnvelope {
1491 ty: self.ty,
1492 endpoints: self.endpoints().collect::<Arc<[_]>>(),
1493 sender: sender_name_for_address(self.source_address),
1494 source_address: self.source_address,
1495 timestamp_ms: self.timestamp_ms,
1496 wire_shape: self.wire_shape,
1497 target_senders: self.target_senders().collect::<Arc<[_]>>(),
1498 }
1499 }
1500}
1501
1502fn read_routing_envelope<'a>(r: &mut ByteReader<'a>) -> TelemetryResult<RoutingEnvelope<'a>> {
1503 let flags = r.read_bytes(1)?[0];
1504 let nep = r.read_bytes(1)?[0] as usize;
1505 let ty_v = read_uleb128(r)?;
1506 let _data_size = read_uleb128(r)?;
1507 let timestamp_ms = read_uleb128(r)?;
1508 if flags & FLAG_PACKET_NONCE != 0 {
1509 let _ = read_uleb128(r)?;
1510 }
1511 let source_address = u32::try_from(read_uleb128(r)?)
1512 .map_err(|_| TelemetryError::Unpack("source address too large"))?;
1513 let ty_u32 = data_type_id_from_wire(ty_v)?;
1514 let metadata = crate::config::try_get_message_meta(DataType(ty_u32));
1515 let known_ty = metadata.as_ref().map(|_| DataType(ty_u32));
1516 let is_reliable = flags & FLAG_RELIABLE_HEADER_PRESENT != 0;
1517 let mut bitmap = [0u64; EP_BITMAP_BYTES / 8];
1520 let mut endpoint_list = None;
1521 let mut schema_endpoints = None;
1522 if flags & FLAG_ENDPOINT_LIST_PRESENT != 0 {
1523 if flags & FLAG_ENDPOINT_BITMAP_PRESENT != 0 {
1524 return Err(TelemetryError::Unpack("ambiguous endpoint encoding"));
1525 }
1526 let bytes = read_endpoint_list(r, nep)?;
1527 endpoint_list = Some(bytes);
1528 } else if flags & FLAG_ENDPOINT_BITMAP_PRESENT != 0 {
1529 let bytes = r.read_bytes(EP_BITMAP_BYTES)?;
1530 for (word, chunk) in bitmap.iter_mut().zip(bytes.as_chunks::<8>().0) {
1531 *word = u64::from_le_bytes(*chunk);
1532 }
1533 if bitmap
1534 .iter()
1535 .map(|word| word.count_ones() as usize)
1536 .sum::<usize>()
1537 != nep
1538 {
1539 return Err(TelemetryError::Unpack("endpoint count mismatch"));
1540 }
1541 for (index, &word) in bitmap.iter().enumerate() {
1542 let mut bits = word;
1543 while bits != 0 {
1544 let id = index * 64 + bits.trailing_zeros() as usize;
1545 if !crate::config::endpoint_exists(DataEndpoint(id as u32)) {
1546 return Err(TelemetryError::Unpack("bad endpoint bit set"));
1547 }
1548 bits &= bits - 1;
1549 }
1550 }
1551 } else {
1552 let meta = metadata.ok_or(TelemetryError::InvalidType)?;
1553 if unique_sorted_endpoints(meta.endpoints_ref()).count() != nep {
1554 return Err(TelemetryError::Unpack("endpoint count mismatch"));
1555 }
1556 schema_endpoints = Some(meta);
1557 }
1558 let mut shape = None;
1559 let mut targets: &'a [u8] = &[];
1560 let mut has_reliable_header = false;
1561 if flags & FLAG_WIRE_CONTRACT != 0 {
1562 let len = usize::try_from(read_uleb128(r)?)
1563 .map_err(|_| TelemetryError::Unpack("wire contract length"))?;
1564 let mut cr = ByteReader::new(r.read_bytes(len)?);
1565 let contract_flags = cr.read_bytes(1)?[0];
1566 if contract_flags & CONTRACT_FLAG_SHAPE != 0 {
1567 shape = Some(decode_wire_shape(&mut cr)?);
1568 }
1569 if contract_flags & CONTRACT_FLAG_TARGETS != 0 {
1570 let count = usize::try_from(read_uleb128(&mut cr)?)
1571 .map_err(|_| TelemetryError::Unpack("wire contract target count"))?;
1572 let bytes = count
1573 .checked_mul(8)
1574 .ok_or(TelemetryError::Unpack("wire contract target count"))?;
1575 targets = cr.read_bytes(bytes)?;
1576 }
1577 if cr.remaining() != 0 {
1578 return Err(TelemetryError::Unpack("wire contract trailing bytes"));
1579 }
1580 has_reliable_header = contract_flags & CONTRACT_FLAG_RELIABLE_HEADER != 0;
1581 }
1582 if nep == 0 {
1583 if !is_reliable && !has_reliable_header {
1584 return Err(TelemetryError::EmptyEndpoints);
1585 }
1586 let mut header = ByteReader {
1587 buf: r.buf,
1588 off: r.off,
1589 };
1590 let reliable =
1591 read_reliable_header_encoded(&mut header, flags & FLAG_COMPACT_RELIABLE_HEADER != 0)?;
1592 if reliable.flags & RELIABLE_FLAG_ACK_ONLY == 0 {
1593 return Err(TelemetryError::EmptyEndpoints);
1594 }
1595 }
1596 let ty = known_ty.unwrap_or(DataType(ty_u32));
1597 Ok(RoutingEnvelope {
1598 ty,
1599 bitmap,
1600 endpoint_list,
1601 schema_endpoints,
1602 source_address,
1603 timestamp_ms,
1604 wire_shape: shape,
1605 is_reliable,
1606 targets,
1607 has_reliable_header,
1608 })
1609}
1610
1611pub(crate) fn scheduling_type(buf: &[u8]) -> Option<DataType> {
1615 let mut reader = ByteReader::new(buf.get(..buf.len().min(12))?);
1616 reader.read_bytes(2).ok()?;
1617 let id = data_type_id_from_wire(read_uleb128(&mut reader).ok()?).ok()?;
1618 DataType::try_from_u32(id)
1619}
1620
1621pub(crate) fn peek_routing_envelope(buf: &[u8]) -> TelemetryResult<RoutingEnvelope<'_>> {
1622 let data = verify_crc32(buf)?;
1623 read_routing_envelope(&mut ByteReader::new(data))
1624}
1625
1626pub struct TelemetryFrameInfo {
1628 pub envelope: TelemetryEnvelope,
1629 pub reliable: Option<ReliableHeader>,
1630}
1631
1632impl TelemetryFrameInfo {
1633 #[inline]
1634 pub fn ack_only(&self) -> bool {
1636 self.reliable
1637 .map(|h| (h.flags & RELIABLE_FLAG_ACK_ONLY) != 0)
1638 .unwrap_or(false)
1639 }
1640}
1641
1642pub(crate) struct RoutingFrameInfo<'a> {
1643 pub envelope: RoutingEnvelope<'a>,
1644 pub reliable: Option<ReliableHeader>,
1645}
1646impl RoutingFrameInfo<'_> {
1647 pub fn ack_only(&self) -> bool {
1648 self.reliable
1649 .is_some_and(|header| header.flags & RELIABLE_FLAG_ACK_ONLY != 0)
1650 }
1651}
1652#[cfg(all(feature = "discovery", not(feature = "std")))]
1655pub(crate) fn peek_plain_schema_payload(buf: &[u8]) -> TelemetryResult<Option<(u32, &[u8])>> {
1656 let mut prelude = ByteReader::new(buf);
1659 prelude.read_bytes(2)?;
1660 if data_type_id_from_wire(read_uleb128(&mut prelude)?)? != DataType::DiscoverySchema.as_u32() {
1661 return Ok(None);
1662 }
1663 let data = verify_crc32(buf)?;
1664 let mut reader = ByteReader::new(data);
1665 let envelope = read_routing_envelope(&mut reader)?;
1666 if envelope.ty != DataType::DiscoverySchema
1667 || data[0] & (FLAG_COMPRESSED_PAYLOAD | 0x10) != 0
1668 || envelope.target_senders().len() != 0
1669 || envelope
1670 .wire_shape
1671 .is_some_and(|shape| shape != crate::message_meta(DataType::DiscoverySchema).element)
1672 {
1673 return Ok(None);
1674 }
1675 if envelope.is_reliable || envelope.has_reliable_header {
1676 let reliable =
1677 read_reliable_header_encoded(&mut reader, data[0] & FLAG_COMPACT_RELIABLE_HEADER != 0)?;
1678 if reliable.flags != RELIABLE_FLAG_UNSEQUENCED || reliable.seq != 0 || reliable.ack != 0 {
1681 return Ok(None);
1682 }
1683 }
1684 let mut prelude = ByteReader::new(data);
1687 prelude.read_bytes(2)?;
1688 read_uleb128(&mut prelude)?;
1689 let size = usize::try_from(read_uleb128(&mut prelude)?)
1690 .map_err(|_| TelemetryError::Unpack("schema payload too large"))?;
1691 if reader.remaining() != size {
1692 return Err(TelemetryError::Unpack("schema payload length mismatch"));
1693 }
1694 Ok(Some((envelope.source_address, reader.read_bytes(size)?)))
1695}
1696
1697pub(crate) fn peek_routing_frame_info(buf: &[u8]) -> TelemetryResult<RoutingFrameInfo<'_>> {
1698 let data = verify_crc32(buf)?;
1699 let mut reader = ByteReader::new(data);
1700 let envelope = read_routing_envelope(&mut reader)?;
1701 let reliable = if envelope.is_reliable || envelope.has_reliable_header {
1702 Some(read_reliable_header_encoded(
1703 &mut reader,
1704 data[0] & FLAG_COMPACT_RELIABLE_HEADER != 0,
1705 )?)
1706 } else {
1707 None
1708 };
1709 Ok(RoutingFrameInfo { envelope, reliable })
1710}
1711
1712fn peek_frame_info_inner(buf: &[u8]) -> TelemetryResult<TelemetryFrameInfo> {
1713 let mut r = ByteReader::new(buf);
1714 let header = read_routing_envelope(&mut r)?;
1715 let reliable = if header.is_reliable || header.has_reliable_header {
1716 Some(read_reliable_header_encoded(
1717 &mut r,
1718 buf[0] & FLAG_COMPACT_RELIABLE_HEADER != 0,
1719 )?)
1720 } else {
1721 None
1722 };
1723 Ok(TelemetryFrameInfo {
1724 envelope: header.into_owned(),
1725 reliable,
1726 })
1727}
1728
1729pub fn peek_frame_info(buf: &[u8]) -> TelemetryResult<TelemetryFrameInfo> {
1735 let data = verify_crc32(buf)?;
1736 peek_frame_info_inner(data)
1737}
1738
1739pub fn peek_frame_info_unchecked(buf: &[u8]) -> TelemetryResult<TelemetryFrameInfo> {
1745 let (data, _crc) = split_crc32(buf)?;
1746 peek_frame_info_inner(data)
1747}
1748
1749pub fn reliable_header_offset(buf: &[u8]) -> TelemetryResult<Option<usize>> {
1764 Ok(reliable_header_span(buf)?.map(|(off, _, _)| off))
1765}
1766
1767pub(crate) fn reliable_header_span(
1768 buf: &[u8],
1769) -> TelemetryResult<Option<(usize, usize, ReliableHeader)>> {
1770 if buf.len() < CRC32_BYTES + 1 {
1771 return Err(TelemetryError::Unpack("short prelude"));
1772 }
1773 let data_len = buf.len().saturating_sub(CRC32_BYTES);
1774 let mut r = ByteReader::new(&buf[..data_len]);
1775
1776 let flags = r.read_bytes(1)?[0];
1777 let endpoint_bitmap_present = (flags & FLAG_ENDPOINT_BITMAP_PRESENT) != 0;
1778 let compact_reliable_header = (flags & FLAG_COMPACT_RELIABLE_HEADER) != 0;
1779
1780 let nep = r.read_bytes(1)?[0] as usize;
1781
1782 let ty_v = read_uleb128(&mut r)?;
1783 let _dsz = read_uleb128(&mut r)? as usize;
1784 let _ts_v = read_uleb128(&mut r)?;
1785 if (flags & FLAG_PACKET_NONCE) != 0 {
1786 let _ = read_uleb128(&mut r)?;
1787 }
1788 let _source_address = u32::try_from(read_uleb128(&mut r)?)
1789 .map_err(|_| TelemetryError::Unpack("source address too large"))?;
1790 let endpoint_bytes = if endpoint_bitmap_present {
1791 EP_BITMAP_BYTES
1792 } else {
1793 0
1794 };
1795
1796 if r.remaining() < endpoint_bytes {
1797 return Err(TelemetryError::Unpack("short buffer"));
1798 }
1799
1800 if flags & FLAG_ENDPOINT_LIST_PRESENT != 0 {
1801 if endpoint_bitmap_present {
1802 return Err(TelemetryError::Unpack("ambiguous endpoint encoding"));
1803 }
1804 read_endpoint_list(&mut r, nep)?;
1805 } else if endpoint_bitmap_present {
1806 r.read_bytes(EP_BITMAP_BYTES)?;
1807 }
1808 let contract = decode_wire_contract(&mut r, (flags & FLAG_WIRE_CONTRACT) != 0)?;
1809 let ty_u32 = data_type_id_from_wire(ty_v)?;
1810 let _ty = DataType(ty_u32);
1811 if flags & FLAG_RELIABLE_HEADER_PRESENT == 0 && !contract.has_reliable_header {
1812 return Ok(None);
1813 }
1814
1815 let off = r.off;
1816 let hdr = read_reliable_header_encoded(&mut r, compact_reliable_header)?;
1817 Ok(Some((off, r.off - off, hdr)))
1818}
1819
1820pub fn rewrite_reliable_header(
1836 buf: &mut [u8],
1837 flags: u8,
1838 seq: u32,
1839 ack: u32,
1840) -> TelemetryResult<bool> {
1841 let Some((off, old_len, _)) = reliable_header_span(buf)? else {
1842 return Ok(false);
1843 };
1844 let hdr = ReliableHeader { flags, seq, ack };
1845 let compact = should_compact_reliable_header(hdr);
1846 if reliable_wire_size(hdr, compact) != old_len {
1847 return Err(TelemetryError::Unpack(
1848 "reliable header rewrite changes wire size",
1849 ));
1850 }
1851 let data_len = buf.len().saturating_sub(CRC32_BYTES);
1852 if data_len.saturating_sub(off) < old_len {
1853 return Err(TelemetryError::Unpack("short buffer"));
1854 }
1855 if compact {
1856 buf[0] |= FLAG_COMPACT_RELIABLE_HEADER;
1857 } else {
1858 buf[0] &= !FLAG_COMPACT_RELIABLE_HEADER;
1859 }
1860 let mut encoded = Vec::with_capacity(old_len);
1861 write_reliable_header_encoded(hdr, compact, &mut encoded);
1862 buf[off..off + old_len].copy_from_slice(&encoded);
1863 if buf.len() < CRC32_BYTES {
1864 return Err(TelemetryError::Unpack("short buffer"));
1865 }
1866 let crc = crc32_bytes(&buf[..data_len]);
1867 buf[data_len..data_len + CRC32_BYTES].copy_from_slice(&crc.to_le_bytes());
1868 Ok(true)
1869}
1870
1871pub(crate) fn rewrite_reliable_header_owned(
1872 buf: &[u8],
1873 flags: u8,
1874 seq: u32,
1875 ack: u32,
1876) -> TelemetryResult<Option<Arc<[u8]>>> {
1877 let Some((off, old_len, _)) = reliable_header_span(buf)? else {
1878 return Ok(None);
1879 };
1880 let data_len = buf.len().saturating_sub(CRC32_BYTES);
1881 if data_len < off + old_len {
1882 return Err(TelemetryError::Unpack("short buffer"));
1883 }
1884 let hdr = ReliableHeader { flags, seq, ack };
1885 let compact = should_compact_reliable_header(hdr);
1886 let mut encoded = Vec::with_capacity(reliable_wire_size(hdr, compact));
1887 write_reliable_header_encoded(hdr, compact, &mut encoded);
1888
1889 let mut out = Vec::with_capacity(data_len - old_len + encoded.len() + CRC32_BYTES);
1890 out.extend_from_slice(&buf[..off]);
1891 if compact {
1892 out[0] |= FLAG_COMPACT_RELIABLE_HEADER;
1893 } else {
1894 out[0] &= !FLAG_COMPACT_RELIABLE_HEADER;
1895 }
1896 out.extend_from_slice(&encoded);
1897 out.extend_from_slice(&buf[off + old_len..data_len]);
1898 let crc = crc32_bytes(&out);
1899 out.extend_from_slice(&crc.to_le_bytes());
1900 Ok(Some(Arc::from(out)))
1901}
1902
1903pub fn header_size_bytes(pkt: &Packet) -> usize {
1919 let prelude = 2; let source_address = sender_address_u32(pkt.sender());
1922
1923 prelude
1924 + uleb128_size(pkt.data_type().as_u32() as u64)
1925 + uleb128_size(pkt.data_size() as u64)
1926 + uleb128_size(pkt.timestamp())
1927 + if pkt.nonce() != 0 {
1928 uleb128_size(pkt.nonce() as u64)
1929 } else {
1930 0
1931 }
1932 + uleb128_size(source_address as u64)
1933}
1934
1935pub fn packet_wire_size(pkt: &Packet) -> usize {
1948 let shape = pkt.wire_shape();
1949 let targets = pkt.wire_target_senders();
1950 let contract_bytes = wire_contract_size(shape, targets);
1951 let contract_len = if shape.is_some() || !targets.is_empty() {
1952 uleb128_size(contract_bytes as u64) + contract_bytes
1953 } else {
1954 0
1955 };
1956 let endpoint_len = if packet_endpoint_bitmap_present(pkt, shape, targets) {
1957 if explicit_endpoint_list(pkt.endpoints()) {
1958 endpoint_list_size(pkt.endpoints())
1959 } else {
1960 EP_BITMAP_BYTES
1961 }
1962 } else {
1963 0
1964 };
1965 let (_, payload_wire) = payload_compression::compress_if_beneficial(pkt.payload());
1966 let reliable_len = if is_reliable_type(pkt.data_type()) {
1967 let header = ReliableHeader {
1968 flags: RELIABLE_FLAG_UNSEQUENCED,
1969 seq: 0,
1970 ack: 0,
1971 };
1972 reliable_wire_size(header, should_compact_reliable_header(header))
1973 } else {
1974 0
1975 };
1976 header_size_bytes(pkt)
1979 + endpoint_len
1980 + contract_len
1981 + reliable_len
1982 + payload_wire.len()
1983 + CRC32_BYTES
1984}
1985
1986#[inline]
1987pub fn packet_id_from_wire(buf: &[u8]) -> Result<u64, TelemetryError> {
1989 let data = verify_crc32(buf)?;
1990 if data.len() < 2 {
1991 return Err(TelemetryError::Unpack("short prelude"));
1992 }
1993
1994 let mut r = ByteReader::new(data);
1995
1996 let flags = r.read_bytes(1)?[0];
1997 let payload_is_compressed = (flags & FLAG_COMPRESSED_PAYLOAD) != 0;
1998 let compact_reliable_header = (flags & FLAG_COMPACT_RELIABLE_HEADER) != 0;
1999 #[cfg(feature = "cryptography")]
2000 let payload_is_encrypted = (flags & FLAG_E2E_ENCRYPTED_PAYLOAD) != 0;
2001 #[cfg(not(feature = "cryptography"))]
2002 if (flags & 0x10) != 0 {
2003 return Err(TelemetryError::Unpack("e2e crypto unsupported"));
2004 }
2005
2006 let _nep = r.read_bytes(1)?[0] as usize;
2007
2008 let _ = read_uleb128(&mut r)?;
2009 let dsz = read_uleb128(&mut r)? as usize; let ts_v = read_uleb128(&mut r)?;
2011 let nonce = if (flags & FLAG_PACKET_NONCE) != 0 {
2012 u16::try_from(read_uleb128(&mut r)?)
2013 .map_err(|_| TelemetryError::Unpack("packet nonce too large"))?
2014 } else {
2015 0
2016 };
2017 let source_address = u32::try_from(read_uleb128(&mut r)?)
2018 .map_err(|_| TelemetryError::Unpack("source address too large"))?;
2019 let mut envelope_reader = ByteReader::new(data);
2022 let envelope = read_routing_envelope(&mut envelope_reader)?;
2023 r = envelope_reader;
2024 let ty = envelope.ty;
2025
2026 if envelope.is_reliable || envelope.has_reliable_header {
2028 let hdr = read_reliable_header_encoded(&mut r, compact_reliable_header)?;
2029 if (hdr.flags & RELIABLE_FLAG_ACK_ONLY) != 0 {
2030 return Err(TelemetryError::Unpack("reliable control frame"));
2031 }
2032 }
2033
2034 #[cfg(feature = "cryptography")]
2036 let payload_wire_owned;
2037 #[cfg(feature = "cryptography")]
2038 let payload_wire: &[u8] = if payload_is_encrypted {
2039 let aad_end = r.off;
2040 payload_wire_owned =
2041 read_encrypted_payload(&mut r, data.get(..aad_end).unwrap_or(&[]), dsz)?;
2042 &payload_wire_owned
2043 } else if !payload_is_compressed {
2044 if r.remaining() < dsz {
2045 return Err(TelemetryError::Unpack("short buffer"));
2046 }
2047 r.read_bytes(dsz)?
2048 } else {
2049 let comp_len = r.remaining();
2050 if comp_len < 1 {
2051 return Err(TelemetryError::Unpack("short buffer"));
2052 }
2053 r.read_bytes(comp_len)?
2054 };
2055 #[cfg(not(feature = "cryptography"))]
2056 let payload_wire: &[u8] = if !payload_is_compressed {
2057 if r.remaining() < dsz {
2058 return Err(TelemetryError::Unpack("short buffer"));
2059 }
2060 r.read_bytes(dsz)?
2061 } else {
2062 let comp_len = r.remaining();
2063 if comp_len < 1 {
2064 return Err(TelemetryError::Unpack("short buffer"));
2065 }
2066 r.read_bytes(comp_len)?
2067 };
2068 let payload_decompressed;
2069 let payload_bytes: &[u8] = if payload_is_compressed {
2070 payload_decompressed = payload_compression::decompress(payload_wire, dsz)?;
2071 &payload_decompressed
2072 } else {
2073 if payload_wire.len() != dsz {
2074 return Err(TelemetryError::Unpack("payload length mismatch"));
2075 }
2076 payload_wire
2077 };
2078
2079 let mut h: u64 = 0x9E37_79B9_7F4A_7C15;
2081
2082 h = hash_bytes_u64(h, &source_address.to_le_bytes());
2084
2085 h = hash_bytes_u64(h, &ty.0.to_le_bytes());
2087
2088 for ep in envelope.endpoints() {
2090 h = hash_bytes_u64(h, &ep.0.to_le_bytes());
2091 }
2092
2093 h = hash_bytes_u64(h, &ts_v.to_le_bytes());
2095 h = hash_bytes_u64(h, &nonce.to_le_bytes());
2096 h = hash_bytes_u64(h, &(dsz as u64).to_le_bytes());
2097
2098 h = hash_bytes_u64(h, payload_bytes);
2100 Ok(h)
2101}
2102
2103mod payload_compression {
2104 use crate::TelemetryError;
2105 use alloc::borrow::Cow;
2106 #[cfg(feature = "compression")]
2107 use alloc::vec;
2108 use alloc::vec::Vec;
2109
2110 #[cfg(feature = "compression")]
2111 use crate::config::runtime_payload_compress_threshold;
2112 #[cfg(feature = "compression")]
2113 use zstd_safe::CompressionLevel;
2114
2115 #[cfg(feature = "compression")]
2123 pub fn compress_if_beneficial(payload: &'_ [u8]) -> (bool, Cow<'_, [u8]>) {
2124 if payload.len() < runtime_payload_compress_threshold() {
2125 return (false, Cow::Borrowed(payload));
2126 }
2127
2128 let Some(compressed) = compress_to_vec_bounded(payload, payload.len().saturating_sub(2))
2130 else {
2131 return (false, Cow::Borrowed(payload));
2132 };
2133
2134 if compressed.len() + 1 >= payload.len() {
2136 (false, Cow::Borrowed(payload))
2137 } else {
2138 (true, Cow::Owned(compressed))
2139 }
2140 }
2141
2142 #[cfg(feature = "compression")]
2143 fn compress_to_vec_bounded(input: &[u8], max_output: usize) -> Option<Vec<u8>> {
2144 if input.is_empty() || max_output == 0 {
2145 return None;
2146 }
2147
2148 let mut out = vec![0u8; max_output];
2149 let level: CompressionLevel = 1;
2151 let written = zstd_safe::compress(&mut out[..], input, level).ok()?;
2152 out.truncate(written);
2153 Some(out)
2154 }
2155
2156 #[cfg(feature = "compression")]
2166 pub fn decompress(compressed: &[u8], expected_len: usize) -> Result<Vec<u8>, TelemetryError> {
2167 let mut out = vec![0u8; expected_len];
2168 let written = zstd_safe::decompress(&mut out[..], compressed)
2169 .map_err(|_| TelemetryError::Unpack("decompression failed"))?;
2170 if written != expected_len {
2171 return Err(TelemetryError::Unpack("decompressed size mismatch"));
2172 }
2173 Ok(out)
2174 }
2175
2176 #[cfg(not(feature = "compression"))]
2178 pub fn compress_if_beneficial<'a>(payload: &'a [u8]) -> (bool, Cow<'a, [u8]>) {
2180 (false, Cow::Borrowed(payload))
2181 }
2182
2183 #[cfg(not(feature = "compression"))]
2184 pub fn decompress(_compressed: &[u8], _expected_len: usize) -> Result<Vec<u8>, TelemetryError> {
2186 Err(TelemetryError::Unpack(
2187 "compressed payloads not supported (compression feature disabled)",
2188 ))
2189 }
2190}
2191
2192#[cfg(test)]
2193mod endpoint_decode_tests {
2194 use super::*;
2195
2196 #[test]
2197 fn numeric_sender_alias_keeps_packet_wire_and_receipt_identity() {
2198 let ty = DataType::ReliableAck;
2199 let make = |sender: &str| {
2200 Packet::new_with_wire_contract(
2201 ty,
2202 message_meta(ty).endpoints_ref(),
2203 sender,
2204 200,
2205 9,
2206 Arc::from(42u64.to_le_bytes()),
2207 Some(MessageElement::Static(
2208 2,
2209 crate::MessageDataType::UInt32,
2210 crate::MessageClass::Data,
2211 )),
2212 Arc::from([123u64]),
2213 )
2214 .unwrap()
2215 };
2216 let named = make("FC");
2217 let alias = alloc::format!("@addr:{}", sender_address_u32("FC"));
2218 let unresolved = make(&alias);
2219 assert_eq!(unresolved.packet_id(), named.packet_id());
2220 let named_wire = pack_packet(&named);
2221 let alias_wire = pack_packet(&unresolved);
2222 assert_eq!(alias_wire, named_wire);
2223 assert_eq!(packet_id_from_wire(&alias_wire).unwrap(), named.packet_id());
2224 assert_eq!(
2225 unpack_packet(&alias_wire).unwrap().packet_id(),
2226 named.packet_id()
2227 );
2228 }
2229
2230 #[test]
2231 fn scheduling_type_is_bounded_and_never_replaces_frame_validation() {
2232 let pkt = Packet::new_with_wire_contract(
2233 DataType::ReliableAck,
2234 message_meta(DataType::ReliableAck).endpoints_ref(),
2235 "E2EACK:GS",
2236 100,
2237 1,
2238 Arc::from(42u64.to_le_bytes()),
2239 Some(MessageElement::Static(
2240 2,
2241 crate::MessageDataType::UInt32,
2242 crate::MessageClass::Data,
2243 )),
2244 Arc::from([123u64]),
2245 )
2246 .unwrap();
2247 let mut bytes = pack_packet(&pkt).to_vec();
2248 assert_eq!(scheduling_type(&bytes), Some(DataType::ReliableAck));
2249 let last = bytes.len() - 1;
2250 bytes[last] ^= 1;
2251 assert_eq!(scheduling_type(&bytes), Some(DataType::ReliableAck));
2252 assert!(peek_routing_envelope(&bytes).is_err());
2253 assert!(unpack_packet(&bytes).is_err());
2254 assert_eq!(scheduling_type(&[0, 0, 0x80]), None);
2255 assert_eq!(scheduling_type(&[0xff; 1024]), None);
2256 assert_eq!(scheduling_type(&[]), None);
2257 }
2258
2259 #[test]
2260 fn receipt_contract_omits_redundant_builtin_endpoint_bitmap() {
2261 for ty in [
2262 DataType::ReliableAck,
2263 DataType::ReliablePartialAck,
2264 DataType::ReliablePacketRequest,
2265 ] {
2266 let shape = Some(MessageElement::Static(
2267 2,
2268 crate::MessageDataType::UInt32,
2269 crate::MessageClass::Data,
2270 ));
2271 let targets: Arc<[u64]> = Arc::from([0xa7fcbb129e92435f, 0x41426f62de53eb28]);
2272 let payload: Arc<[u8]> = Arc::from(0x9c2a63d6d7d44100u64.to_le_bytes());
2273 let make = |eps: &[DataEndpoint]| {
2274 Packet::new_with_wire_contract(
2275 ty,
2276 eps,
2277 "E2EACK:GS",
2278 1791737696510,
2279 1234,
2280 payload.clone(),
2281 shape,
2282 targets.clone(),
2283 )
2284 .unwrap()
2285 };
2286 let packet = make(message_meta(ty).endpoints_ref());
2287 let packed = pack_packet(&packet);
2288 assert_eq!(packed[0] & FLAG_ENDPOINT_BITMAP_PRESENT, 0);
2289 assert_ne!(packed[0] & FLAG_WIRE_CONTRACT, 0);
2290 let routing = peek_routing_envelope(&packed).unwrap();
2291 assert_eq!(routing.endpoints().collect::<Vec<_>>(), packet.endpoints());
2292 assert_eq!(
2293 routing.target_senders().collect::<Vec<_>>(),
2294 targets.as_ref()
2295 );
2296 let decoded = unpack_packet(&packed).unwrap();
2297 assert_eq!(decoded.packet_id(), packet.packet_id());
2298 assert_eq!(decoded.payload(), packet.payload());
2299 assert_eq!(decoded.wire_target_senders(), targets.as_ref());
2300 let explicit = pack_packet(&make(&[DataEndpoint::Discovery]));
2302 assert_ne!(explicit[0] & FLAG_ENDPOINT_LIST_PRESENT, 0);
2303 assert_eq!(
2304 explicit.len(),
2305 packed.len() + uleb128_size(u64::from(DataEndpoint::Discovery.0))
2306 );
2307 assert_eq!(
2308 unpack_packet(&explicit).unwrap().endpoints(),
2309 &[DataEndpoint::Discovery]
2310 );
2311 }
2312 }
2313
2314 #[test]
2315 fn borrowed_routing_header_preserves_targets_and_validates_truncated_contracts() {
2316 let targets: Arc<[u64]> = Arc::from([1, u64::MAX, 42]);
2317 let packet = Packet::new_with_wire_contract(
2318 DataType::DiscoverySchema,
2319 &[DataEndpoint::Discovery],
2320 "PEER",
2321 1234,
2322 7,
2323 Arc::from([1u8, 2, 3]),
2324 Some(MessageElement::Dynamic(
2325 crate::MessageDataType::Binary,
2326 crate::MessageClass::Data,
2327 )),
2328 targets.clone(),
2329 )
2330 .unwrap();
2331 let packed = pack_packet(&packet);
2332 let routing = peek_routing_envelope(&packed).unwrap();
2333 let full = unpack_packet(&packed).unwrap();
2334 assert_eq!(routing.ty, full.data_type());
2335 assert_eq!(routing.endpoints().collect::<Vec<_>>(), full.endpoints());
2336 assert_eq!(
2337 routing.target_senders().collect::<Vec<_>>(),
2338 targets.as_ref()
2339 );
2340 assert_eq!(routing.timestamp_ms, full.timestamp());
2341 let data = verify_crc32(&packed).unwrap();
2343 let mut reader = ByteReader::new(data);
2344 read_routing_envelope(&mut reader).unwrap();
2345 for end in 0..reader.off {
2346 let mut truncated = data[..end].to_vec();
2347 append_crc32(&mut truncated);
2348 assert!(
2349 peek_routing_envelope(&truncated).is_err(),
2350 "accepted cut at {end}"
2351 );
2352 }
2353 }
2354
2355 #[test]
2356 fn large_packet_with_long_prefix_does_not_grow_packing_buffer() {
2357 let payload: Vec<u8> = (0..3500)
2358 .map(|i| ((i * 73 + i / 251) % 256) as u8)
2359 .collect();
2360 let packet = Packet::new(
2361 DataType::DiscoverySchema,
2362 &[DataEndpoint::Discovery],
2363 "LONG_PREFIX_SENDER",
2364 u64::MAX,
2365 payload.into(),
2366 )
2367 .unwrap()
2368 .with_nonce(u16::MAX);
2369 assert!(header_size_bytes(&packet) > 16);
2370 let packed = pack_packet(&packet);
2371 let unpacked = unpack_packet(&packed).unwrap();
2372 assert_eq!(unpacked.payload(), packet.payload());
2373 assert_eq!(unpacked.timestamp(), u64::MAX);
2374 assert_eq!(unpacked.nonce(), u16::MAX);
2375 }
2376
2377 #[test]
2378 fn bitmap_decode_preserves_sorted_unique_destinations() {
2379 let input = [
2380 DataEndpoint::TelemetryError,
2381 DataEndpoint::TimeSync,
2382 DataEndpoint::Discovery,
2383 DataEndpoint::TimeSync,
2384 ];
2385 let decoded = expand_endpoint_bitmap(&build_endpoint_bitmap(&input)).unwrap();
2386 assert_eq!(
2387 &*decoded,
2388 &[
2389 DataEndpoint::TimeSync,
2390 DataEndpoint::Discovery,
2391 DataEndpoint::TelemetryError
2392 ]
2393 );
2394 assert!(
2395 expand_endpoint_bitmap(&[0; EP_BITMAP_BYTES])
2396 .unwrap()
2397 .is_empty()
2398 );
2399 assert!(expand_endpoint_bitmap(&[0; EP_BITMAP_BYTES - 1]).is_err());
2400 }
2401
2402 #[test]
2403 fn bitmap_decode_rejects_unregistered_endpoint_bits() {
2404 if let Some(id) =
2405 (0..=MAX_VALUE_DATA_ENDPOINT).find(|id| DataEndpoint::try_from_u32(*id).is_none())
2406 {
2407 let mut bitmap = [0; EP_BITMAP_BYTES];
2408 bitmap[id as usize / 8] = 1 << (id % 8);
2409 assert!(expand_endpoint_bitmap(&bitmap).is_err());
2410 }
2411 }
2412}