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_discovery_request_shape(
1301 ty,
1302 dsz == 0 && r.remaining() == 0,
1303 eps.as_ref() == [DataEndpoint::Discovery],
1304 contract
1305 .target_senders
1306 .as_ref()
1307 .map_or(0, |owners| owners.len()),
1308 contract.shape,
1309 ) || crate::memory_admission::protected_control_shape(
1310 ty,
1311 nep,
1312 contract
1313 .target_senders
1314 .as_ref()
1315 .map_or(0, |owners| owners.len()),
1316 contract.shape,
1317 reliable_hdr.is_some(),
1318 managed,
1319 ))
1320 {
1321 crate::memory_admission::check_small_protected_decode(buf.len())?;
1322 } else {
1323 crate::memory_admission::check(
1324 if small_ack {
1325 512
1326 } else {
1327 dsz.saturating_mul(payload_copies).saturating_add(512)
1328 },
1329 dsz.saturating_add(32),
1330 )?;
1331 }
1332 let payload: StandardSmallPayload = {
1334 #[cfg(feature = "cryptography")]
1335 let payload_wire_owned;
1336 #[cfg(feature = "cryptography")]
1337 let payload_wire: &[u8] = if payload_is_encrypted {
1338 let aad_end = r.off;
1339 payload_wire_owned = read_encrypted_payload(&mut r, &data[..aad_end], dsz)?;
1340 &payload_wire_owned
1341 } else if !payload_is_compressed {
1342 r.read_bytes(dsz)?
1343 } else {
1344 let comp_len = r.remaining();
1345 r.read_bytes(comp_len)?
1346 };
1347
1348 #[cfg(not(feature = "cryptography"))]
1349 let payload_wire: &[u8] = if !payload_is_compressed {
1350 r.read_bytes(dsz)?
1351 } else {
1352 let comp_len = r.remaining();
1353 r.read_bytes(comp_len)?
1354 };
1355
1356 if payload_is_compressed {
1357 let decompressed = payload_compression::decompress(payload_wire, dsz)?;
1358 crate::memory_admission::check(dsz.saturating_add(512), dsz.saturating_add(32))?;
1359 StandardSmallPayload::new(&decompressed)
1360 } else {
1361 if payload_wire.len() != dsz {
1362 return Err(TelemetryError::Unpack("payload length mismatch"));
1363 }
1364 StandardSmallPayload::new(payload_wire)
1365 }
1366 };
1367
1368 let _ = reliable_hdr;
1372 Packet::new_with_owned_wire_contract(
1373 ty,
1374 eps,
1375 sender_str,
1376 ts_v,
1377 nonce,
1378 payload,
1379 contract.shape,
1380 contract.target_senders,
1381 )
1382}
1383
1384pub fn peek_envelope(buf: &[u8]) -> TelemetryResult<TelemetryEnvelope> {
1405 Ok(peek_routing_envelope(buf)?.into_owned())
1406}
1407
1408#[derive(Clone, Debug)]
1412pub(crate) struct RoutingEnvelope<'a> {
1413 pub ty: DataType,
1414 bitmap: [u64; EP_BITMAP_BYTES / 8],
1415 endpoint_list: Option<&'a [u8]>,
1416 schema_endpoints: Option<crate::MessageMeta>,
1417 pub source_address: u32,
1418 pub timestamp_ms: u64,
1419 pub wire_shape: Option<MessageElement>,
1420 pub is_reliable: bool,
1421 payload_is_empty: bool,
1422 targets: &'a [u8],
1423 has_reliable_header: bool,
1424}
1425pub(crate) struct RoutingEndpointIter<'a> {
1426 envelope: &'a RoutingEnvelope<'a>,
1427 word: usize,
1428 bits: u64,
1429 list_offset: usize,
1430 previous: Option<DataEndpoint>,
1431 finished: bool,
1432}
1433impl Iterator for RoutingEndpointIter<'_> {
1434 type Item = DataEndpoint;
1435 #[inline(never)]
1436 fn next(&mut self) -> Option<DataEndpoint> {
1437 if self.finished {
1438 return None;
1439 }
1440 if let Some(bytes) = self.envelope.endpoint_list {
1441 let mut reader = ByteReader {
1442 buf: bytes,
1443 off: self.list_offset,
1444 };
1445 if reader.remaining() == 0 {
1446 self.finished = true;
1447 return None;
1448 }
1449 let endpoint = read_uleb128(&mut reader)
1450 .ok()
1451 .and_then(|id| u32::try_from(id).ok())
1452 .map(DataEndpoint);
1453 self.list_offset = reader.off;
1454 return endpoint;
1455 }
1456 if let Some(meta) = &self.envelope.schema_endpoints {
1457 let next = meta
1458 .endpoints_ref()
1459 .iter()
1460 .copied()
1461 .filter(|ep| self.previous.is_none_or(|previous| *ep > previous))
1462 .min();
1463 self.previous = next;
1464 self.finished = next.is_none();
1465 return next;
1466 }
1467 while self.bits == 0 {
1468 self.word += 1;
1469 if self.word == self.envelope.bitmap.len() {
1470 self.finished = true;
1471 return None;
1472 }
1473 self.bits = self.envelope.bitmap[self.word];
1474 }
1475 let bit = self.bits.trailing_zeros();
1476 self.bits &= self.bits - 1;
1477 Some(DataEndpoint((self.word * 64 + bit as usize) as u32))
1478 }
1479}
1480
1481impl RoutingEnvelope<'_> {
1482 pub fn endpoints(&self) -> RoutingEndpointIter<'_> {
1483 RoutingEndpointIter {
1484 envelope: self,
1485 word: 0,
1486 bits: self.bitmap[0],
1487 list_offset: 0,
1488 previous: None,
1489 finished: false,
1490 }
1491 }
1492 pub fn target_senders(&self) -> impl ExactSizeIterator<Item = u64> + '_ {
1493 self.targets
1494 .as_chunks::<8>()
1495 .0
1496 .iter()
1497 .map(|bytes| u64::from_le_bytes(*bytes))
1498 }
1499 fn into_owned(self) -> TelemetryEnvelope {
1500 TelemetryEnvelope {
1501 ty: self.ty,
1502 endpoints: self.endpoints().collect::<Arc<[_]>>(),
1503 sender: sender_name_for_address(self.source_address),
1504 source_address: self.source_address,
1505 timestamp_ms: self.timestamp_ms,
1506 wire_shape: self.wire_shape,
1507 target_senders: self.target_senders().collect::<Arc<[_]>>(),
1508 }
1509 }
1510}
1511
1512fn read_routing_envelope<'a>(r: &mut ByteReader<'a>) -> TelemetryResult<RoutingEnvelope<'a>> {
1513 let flags = r.read_bytes(1)?[0];
1514 let nep = r.read_bytes(1)?[0] as usize;
1515 let ty_v = read_uleb128(r)?;
1516 let payload_is_empty = read_uleb128(r)? == 0;
1517 let timestamp_ms = read_uleb128(r)?;
1518 if flags & FLAG_PACKET_NONCE != 0 {
1519 let _ = read_uleb128(r)?;
1520 }
1521 let source_address = u32::try_from(read_uleb128(r)?)
1522 .map_err(|_| TelemetryError::Unpack("source address too large"))?;
1523 let ty_u32 = data_type_id_from_wire(ty_v)?;
1524 let metadata = crate::config::try_get_message_meta(DataType(ty_u32));
1525 let known_ty = metadata.as_ref().map(|_| DataType(ty_u32));
1526 let is_reliable = flags & FLAG_RELIABLE_HEADER_PRESENT != 0;
1527 let mut bitmap = [0u64; EP_BITMAP_BYTES / 8];
1530 let mut endpoint_list = None;
1531 let mut schema_endpoints = None;
1532 if flags & FLAG_ENDPOINT_LIST_PRESENT != 0 {
1533 if flags & FLAG_ENDPOINT_BITMAP_PRESENT != 0 {
1534 return Err(TelemetryError::Unpack("ambiguous endpoint encoding"));
1535 }
1536 let bytes = read_endpoint_list(r, nep)?;
1537 endpoint_list = Some(bytes);
1538 } else if flags & FLAG_ENDPOINT_BITMAP_PRESENT != 0 {
1539 let bytes = r.read_bytes(EP_BITMAP_BYTES)?;
1540 for (word, chunk) in bitmap.iter_mut().zip(bytes.as_chunks::<8>().0) {
1541 *word = u64::from_le_bytes(*chunk);
1542 }
1543 if bitmap
1544 .iter()
1545 .map(|word| word.count_ones() as usize)
1546 .sum::<usize>()
1547 != nep
1548 {
1549 return Err(TelemetryError::Unpack("endpoint count mismatch"));
1550 }
1551 for (index, &word) in bitmap.iter().enumerate() {
1552 let mut bits = word;
1553 while bits != 0 {
1554 let id = index * 64 + bits.trailing_zeros() as usize;
1555 if !crate::config::endpoint_exists(DataEndpoint(id as u32)) {
1556 return Err(TelemetryError::Unpack("bad endpoint bit set"));
1557 }
1558 bits &= bits - 1;
1559 }
1560 }
1561 } else {
1562 let meta = metadata.ok_or(TelemetryError::InvalidType)?;
1563 if unique_sorted_endpoints(meta.endpoints_ref()).count() != nep {
1564 return Err(TelemetryError::Unpack("endpoint count mismatch"));
1565 }
1566 schema_endpoints = Some(meta);
1567 }
1568 let mut shape = None;
1569 let mut targets: &'a [u8] = &[];
1570 let mut has_reliable_header = false;
1571 if flags & FLAG_WIRE_CONTRACT != 0 {
1572 let len = usize::try_from(read_uleb128(r)?)
1573 .map_err(|_| TelemetryError::Unpack("wire contract length"))?;
1574 let mut cr = ByteReader::new(r.read_bytes(len)?);
1575 let contract_flags = cr.read_bytes(1)?[0];
1576 if contract_flags & CONTRACT_FLAG_SHAPE != 0 {
1577 shape = Some(decode_wire_shape(&mut cr)?);
1578 }
1579 if contract_flags & CONTRACT_FLAG_TARGETS != 0 {
1580 let count = usize::try_from(read_uleb128(&mut cr)?)
1581 .map_err(|_| TelemetryError::Unpack("wire contract target count"))?;
1582 let bytes = count
1583 .checked_mul(8)
1584 .ok_or(TelemetryError::Unpack("wire contract target count"))?;
1585 targets = cr.read_bytes(bytes)?;
1586 }
1587 if cr.remaining() != 0 {
1588 return Err(TelemetryError::Unpack("wire contract trailing bytes"));
1589 }
1590 has_reliable_header = contract_flags & CONTRACT_FLAG_RELIABLE_HEADER != 0;
1591 }
1592 if nep == 0 {
1593 if !is_reliable && !has_reliable_header {
1594 return Err(TelemetryError::EmptyEndpoints);
1595 }
1596 let mut header = ByteReader {
1597 buf: r.buf,
1598 off: r.off,
1599 };
1600 let reliable =
1601 read_reliable_header_encoded(&mut header, flags & FLAG_COMPACT_RELIABLE_HEADER != 0)?;
1602 if reliable.flags & RELIABLE_FLAG_ACK_ONLY == 0 {
1603 return Err(TelemetryError::EmptyEndpoints);
1604 }
1605 }
1606 let ty = known_ty.unwrap_or(DataType(ty_u32));
1607 Ok(RoutingEnvelope {
1608 ty,
1609 bitmap,
1610 endpoint_list,
1611 schema_endpoints,
1612 source_address,
1613 timestamp_ms,
1614 wire_shape: shape,
1615 is_reliable,
1616 payload_is_empty,
1617 targets,
1618 has_reliable_header,
1619 })
1620}
1621
1622pub(crate) fn scheduling_type(buf: &[u8]) -> Option<DataType> {
1626 let mut reader = ByteReader::new(buf.get(..buf.len().min(12))?);
1627 reader.read_bytes(2).ok()?;
1628 let id = data_type_id_from_wire(read_uleb128(&mut reader).ok()?).ok()?;
1629 DataType::try_from_u32(id)
1630}
1631
1632pub(crate) fn peek_routing_envelope(buf: &[u8]) -> TelemetryResult<RoutingEnvelope<'_>> {
1633 let data = verify_crc32(buf)?;
1634 read_routing_envelope(&mut ByteReader::new(data))
1635}
1636
1637pub struct TelemetryFrameInfo {
1639 pub envelope: TelemetryEnvelope,
1640 pub reliable: Option<ReliableHeader>,
1641}
1642
1643impl TelemetryFrameInfo {
1644 #[inline]
1645 pub fn ack_only(&self) -> bool {
1647 self.reliable
1648 .map(|h| (h.flags & RELIABLE_FLAG_ACK_ONLY) != 0)
1649 .unwrap_or(false)
1650 }
1651}
1652
1653pub(crate) struct RoutingFrameInfo<'a> {
1654 pub envelope: RoutingEnvelope<'a>,
1655 pub reliable: Option<ReliableHeader>,
1656 pub empty_payload: bool,
1657}
1658impl RoutingFrameInfo<'_> {
1659 pub fn ack_only(&self) -> bool {
1660 self.reliable
1661 .is_some_and(|header| header.flags & RELIABLE_FLAG_ACK_ONLY != 0)
1662 }
1663}
1664#[cfg(feature = "discovery")]
1667pub(crate) fn peek_plain_discovery_payload(
1668 buf: &[u8],
1669 expected: DataType,
1670) -> TelemetryResult<Option<(u32, &[u8])>> {
1671 let mut prelude = ByteReader::new(buf);
1674 prelude.read_bytes(2)?;
1675 if data_type_id_from_wire(read_uleb128(&mut prelude)?)? != expected.as_u32() {
1676 return Ok(None);
1677 }
1678 let data = verify_crc32(buf)?;
1679 let mut reader = ByteReader::new(data);
1680 let envelope = read_routing_envelope(&mut reader)?;
1681 if envelope.ty != expected
1682 || data[0] & (FLAG_COMPRESSED_PAYLOAD | 0x10) != 0
1683 || envelope.target_senders().len() != 0
1684 || envelope
1685 .wire_shape
1686 .is_some_and(|shape| shape != crate::message_meta(expected).element)
1687 {
1688 return Ok(None);
1689 }
1690 if envelope.is_reliable || envelope.has_reliable_header {
1691 let reliable =
1692 read_reliable_header_encoded(&mut reader, data[0] & FLAG_COMPACT_RELIABLE_HEADER != 0)?;
1693 if reliable.flags != RELIABLE_FLAG_UNSEQUENCED || reliable.seq != 0 || reliable.ack != 0 {
1696 return Ok(None);
1697 }
1698 }
1699 let mut prelude = ByteReader::new(data);
1702 prelude.read_bytes(2)?;
1703 read_uleb128(&mut prelude)?;
1704 let size = usize::try_from(read_uleb128(&mut prelude)?)
1705 .map_err(|_| TelemetryError::Unpack("discovery payload too large"))?;
1706 if reader.remaining() != size {
1707 return Err(TelemetryError::Unpack("discovery payload length mismatch"));
1708 }
1709 Ok(Some((envelope.source_address, reader.read_bytes(size)?)))
1710}
1711
1712pub(crate) fn peek_routing_frame_info(buf: &[u8]) -> TelemetryResult<RoutingFrameInfo<'_>> {
1713 let data = verify_crc32(buf)?;
1714 let mut reader = ByteReader::new(data);
1715 let envelope = read_routing_envelope(&mut reader)?;
1716 let reliable = if envelope.is_reliable || envelope.has_reliable_header {
1717 Some(read_reliable_header_encoded(
1718 &mut reader,
1719 data[0] & FLAG_COMPACT_RELIABLE_HEADER != 0,
1720 )?)
1721 } else {
1722 None
1723 };
1724 let empty_payload = envelope.payload_is_empty && reader.remaining() == 0;
1725 Ok(RoutingFrameInfo {
1726 envelope,
1727 reliable,
1728 empty_payload,
1729 })
1730}
1731
1732fn peek_frame_info_inner(buf: &[u8]) -> TelemetryResult<TelemetryFrameInfo> {
1733 let mut r = ByteReader::new(buf);
1734 let header = read_routing_envelope(&mut r)?;
1735 let reliable = if header.is_reliable || header.has_reliable_header {
1736 Some(read_reliable_header_encoded(
1737 &mut r,
1738 buf[0] & FLAG_COMPACT_RELIABLE_HEADER != 0,
1739 )?)
1740 } else {
1741 None
1742 };
1743 Ok(TelemetryFrameInfo {
1744 envelope: header.into_owned(),
1745 reliable,
1746 })
1747}
1748
1749pub fn peek_frame_info(buf: &[u8]) -> TelemetryResult<TelemetryFrameInfo> {
1755 let data = verify_crc32(buf)?;
1756 peek_frame_info_inner(data)
1757}
1758
1759pub fn peek_frame_info_unchecked(buf: &[u8]) -> TelemetryResult<TelemetryFrameInfo> {
1765 let (data, _crc) = split_crc32(buf)?;
1766 peek_frame_info_inner(data)
1767}
1768
1769pub fn reliable_header_offset(buf: &[u8]) -> TelemetryResult<Option<usize>> {
1784 Ok(reliable_header_span(buf)?.map(|(off, _, _)| off))
1785}
1786
1787pub(crate) fn reliable_header_span(
1788 buf: &[u8],
1789) -> TelemetryResult<Option<(usize, usize, ReliableHeader)>> {
1790 if buf.len() < CRC32_BYTES + 1 {
1791 return Err(TelemetryError::Unpack("short prelude"));
1792 }
1793 let data_len = buf.len().saturating_sub(CRC32_BYTES);
1794 let mut r = ByteReader::new(&buf[..data_len]);
1795
1796 let flags = r.read_bytes(1)?[0];
1797 let endpoint_bitmap_present = (flags & FLAG_ENDPOINT_BITMAP_PRESENT) != 0;
1798 let compact_reliable_header = (flags & FLAG_COMPACT_RELIABLE_HEADER) != 0;
1799
1800 let nep = r.read_bytes(1)?[0] as usize;
1801
1802 let ty_v = read_uleb128(&mut r)?;
1803 let _dsz = read_uleb128(&mut r)? as usize;
1804 let _ts_v = read_uleb128(&mut r)?;
1805 if (flags & FLAG_PACKET_NONCE) != 0 {
1806 let _ = read_uleb128(&mut r)?;
1807 }
1808 let _source_address = u32::try_from(read_uleb128(&mut r)?)
1809 .map_err(|_| TelemetryError::Unpack("source address too large"))?;
1810 let endpoint_bytes = if endpoint_bitmap_present {
1811 EP_BITMAP_BYTES
1812 } else {
1813 0
1814 };
1815
1816 if r.remaining() < endpoint_bytes {
1817 return Err(TelemetryError::Unpack("short buffer"));
1818 }
1819
1820 if flags & FLAG_ENDPOINT_LIST_PRESENT != 0 {
1821 if endpoint_bitmap_present {
1822 return Err(TelemetryError::Unpack("ambiguous endpoint encoding"));
1823 }
1824 read_endpoint_list(&mut r, nep)?;
1825 } else if endpoint_bitmap_present {
1826 r.read_bytes(EP_BITMAP_BYTES)?;
1827 }
1828 let contract = decode_wire_contract(&mut r, (flags & FLAG_WIRE_CONTRACT) != 0)?;
1829 let ty_u32 = data_type_id_from_wire(ty_v)?;
1830 let _ty = DataType(ty_u32);
1831 if flags & FLAG_RELIABLE_HEADER_PRESENT == 0 && !contract.has_reliable_header {
1832 return Ok(None);
1833 }
1834
1835 let off = r.off;
1836 let hdr = read_reliable_header_encoded(&mut r, compact_reliable_header)?;
1837 Ok(Some((off, r.off - off, hdr)))
1838}
1839
1840pub fn rewrite_reliable_header(
1856 buf: &mut [u8],
1857 flags: u8,
1858 seq: u32,
1859 ack: u32,
1860) -> TelemetryResult<bool> {
1861 let Some((off, old_len, _)) = reliable_header_span(buf)? else {
1862 return Ok(false);
1863 };
1864 let hdr = ReliableHeader { flags, seq, ack };
1865 let compact = should_compact_reliable_header(hdr);
1866 if reliable_wire_size(hdr, compact) != old_len {
1867 return Err(TelemetryError::Unpack(
1868 "reliable header rewrite changes wire size",
1869 ));
1870 }
1871 let data_len = buf.len().saturating_sub(CRC32_BYTES);
1872 if data_len.saturating_sub(off) < old_len {
1873 return Err(TelemetryError::Unpack("short buffer"));
1874 }
1875 if compact {
1876 buf[0] |= FLAG_COMPACT_RELIABLE_HEADER;
1877 } else {
1878 buf[0] &= !FLAG_COMPACT_RELIABLE_HEADER;
1879 }
1880 let mut encoded = Vec::with_capacity(old_len);
1881 write_reliable_header_encoded(hdr, compact, &mut encoded);
1882 buf[off..off + old_len].copy_from_slice(&encoded);
1883 if buf.len() < CRC32_BYTES {
1884 return Err(TelemetryError::Unpack("short buffer"));
1885 }
1886 let crc = crc32_bytes(&buf[..data_len]);
1887 buf[data_len..data_len + CRC32_BYTES].copy_from_slice(&crc.to_le_bytes());
1888 Ok(true)
1889}
1890
1891pub(crate) fn rewrite_reliable_header_owned(
1892 buf: &[u8],
1893 flags: u8,
1894 seq: u32,
1895 ack: u32,
1896) -> TelemetryResult<Option<Arc<[u8]>>> {
1897 let Some((off, old_len, _)) = reliable_header_span(buf)? else {
1898 return Ok(None);
1899 };
1900 let data_len = buf.len().saturating_sub(CRC32_BYTES);
1901 if data_len < off + old_len {
1902 return Err(TelemetryError::Unpack("short buffer"));
1903 }
1904 let hdr = ReliableHeader { flags, seq, ack };
1905 let compact = should_compact_reliable_header(hdr);
1906 let mut encoded = Vec::with_capacity(reliable_wire_size(hdr, compact));
1907 write_reliable_header_encoded(hdr, compact, &mut encoded);
1908
1909 let mut out = Vec::with_capacity(data_len - old_len + encoded.len() + CRC32_BYTES);
1910 out.extend_from_slice(&buf[..off]);
1911 if compact {
1912 out[0] |= FLAG_COMPACT_RELIABLE_HEADER;
1913 } else {
1914 out[0] &= !FLAG_COMPACT_RELIABLE_HEADER;
1915 }
1916 out.extend_from_slice(&encoded);
1917 out.extend_from_slice(&buf[off + old_len..data_len]);
1918 let crc = crc32_bytes(&out);
1919 out.extend_from_slice(&crc.to_le_bytes());
1920 Ok(Some(Arc::from(out)))
1921}
1922
1923pub fn header_size_bytes(pkt: &Packet) -> usize {
1939 let prelude = 2; let source_address = sender_address_u32(pkt.sender());
1942
1943 prelude
1944 + uleb128_size(pkt.data_type().as_u32() as u64)
1945 + uleb128_size(pkt.data_size() as u64)
1946 + uleb128_size(pkt.timestamp())
1947 + if pkt.nonce() != 0 {
1948 uleb128_size(pkt.nonce() as u64)
1949 } else {
1950 0
1951 }
1952 + uleb128_size(source_address as u64)
1953}
1954
1955pub fn packet_wire_size(pkt: &Packet) -> usize {
1968 let shape = pkt.wire_shape();
1969 let targets = pkt.wire_target_senders();
1970 let contract_bytes = wire_contract_size(shape, targets);
1971 let contract_len = if shape.is_some() || !targets.is_empty() {
1972 uleb128_size(contract_bytes as u64) + contract_bytes
1973 } else {
1974 0
1975 };
1976 let endpoint_len = if packet_endpoint_bitmap_present(pkt, shape, targets) {
1977 if explicit_endpoint_list(pkt.endpoints()) {
1978 endpoint_list_size(pkt.endpoints())
1979 } else {
1980 EP_BITMAP_BYTES
1981 }
1982 } else {
1983 0
1984 };
1985 let (_, payload_wire) = payload_compression::compress_if_beneficial(pkt.payload());
1986 let reliable_len = if is_reliable_type(pkt.data_type()) {
1987 let header = ReliableHeader {
1988 flags: RELIABLE_FLAG_UNSEQUENCED,
1989 seq: 0,
1990 ack: 0,
1991 };
1992 reliable_wire_size(header, should_compact_reliable_header(header))
1993 } else {
1994 0
1995 };
1996 header_size_bytes(pkt)
1999 + endpoint_len
2000 + contract_len
2001 + reliable_len
2002 + payload_wire.len()
2003 + CRC32_BYTES
2004}
2005
2006#[inline]
2007pub fn packet_id_from_wire(buf: &[u8]) -> Result<u64, TelemetryError> {
2009 let data = verify_crc32(buf)?;
2010 if data.len() < 2 {
2011 return Err(TelemetryError::Unpack("short prelude"));
2012 }
2013
2014 let mut r = ByteReader::new(data);
2015
2016 let flags = r.read_bytes(1)?[0];
2017 let payload_is_compressed = (flags & FLAG_COMPRESSED_PAYLOAD) != 0;
2018 let compact_reliable_header = (flags & FLAG_COMPACT_RELIABLE_HEADER) != 0;
2019 #[cfg(feature = "cryptography")]
2020 let payload_is_encrypted = (flags & FLAG_E2E_ENCRYPTED_PAYLOAD) != 0;
2021 #[cfg(not(feature = "cryptography"))]
2022 if (flags & 0x10) != 0 {
2023 return Err(TelemetryError::Unpack("e2e crypto unsupported"));
2024 }
2025
2026 let _nep = r.read_bytes(1)?[0] as usize;
2027
2028 let _ = read_uleb128(&mut r)?;
2029 let dsz = read_uleb128(&mut r)? as usize; let ts_v = read_uleb128(&mut r)?;
2031 let nonce = if (flags & FLAG_PACKET_NONCE) != 0 {
2032 u16::try_from(read_uleb128(&mut r)?)
2033 .map_err(|_| TelemetryError::Unpack("packet nonce too large"))?
2034 } else {
2035 0
2036 };
2037 let source_address = u32::try_from(read_uleb128(&mut r)?)
2038 .map_err(|_| TelemetryError::Unpack("source address too large"))?;
2039 let mut envelope_reader = ByteReader::new(data);
2042 let envelope = read_routing_envelope(&mut envelope_reader)?;
2043 r = envelope_reader;
2044 let ty = envelope.ty;
2045
2046 if envelope.is_reliable || envelope.has_reliable_header {
2048 let hdr = read_reliable_header_encoded(&mut r, compact_reliable_header)?;
2049 if (hdr.flags & RELIABLE_FLAG_ACK_ONLY) != 0 {
2050 return Err(TelemetryError::Unpack("reliable control frame"));
2051 }
2052 }
2053
2054 #[cfg(feature = "cryptography")]
2056 let payload_wire_owned;
2057 #[cfg(feature = "cryptography")]
2058 let payload_wire: &[u8] = if payload_is_encrypted {
2059 let aad_end = r.off;
2060 payload_wire_owned =
2061 read_encrypted_payload(&mut r, data.get(..aad_end).unwrap_or(&[]), dsz)?;
2062 &payload_wire_owned
2063 } else if !payload_is_compressed {
2064 if r.remaining() < dsz {
2065 return Err(TelemetryError::Unpack("short buffer"));
2066 }
2067 r.read_bytes(dsz)?
2068 } else {
2069 let comp_len = r.remaining();
2070 if comp_len < 1 {
2071 return Err(TelemetryError::Unpack("short buffer"));
2072 }
2073 r.read_bytes(comp_len)?
2074 };
2075 #[cfg(not(feature = "cryptography"))]
2076 let payload_wire: &[u8] = if !payload_is_compressed {
2077 if r.remaining() < dsz {
2078 return Err(TelemetryError::Unpack("short buffer"));
2079 }
2080 r.read_bytes(dsz)?
2081 } else {
2082 let comp_len = r.remaining();
2083 if comp_len < 1 {
2084 return Err(TelemetryError::Unpack("short buffer"));
2085 }
2086 r.read_bytes(comp_len)?
2087 };
2088 let payload_decompressed;
2089 let payload_bytes: &[u8] = if payload_is_compressed {
2090 payload_decompressed = payload_compression::decompress(payload_wire, dsz)?;
2091 &payload_decompressed
2092 } else {
2093 if payload_wire.len() != dsz {
2094 return Err(TelemetryError::Unpack("payload length mismatch"));
2095 }
2096 payload_wire
2097 };
2098
2099 let mut h: u64 = 0x9E37_79B9_7F4A_7C15;
2101
2102 h = hash_bytes_u64(h, &source_address.to_le_bytes());
2104
2105 h = hash_bytes_u64(h, &ty.0.to_le_bytes());
2107
2108 for ep in envelope.endpoints() {
2110 h = hash_bytes_u64(h, &ep.0.to_le_bytes());
2111 }
2112
2113 h = hash_bytes_u64(h, &ts_v.to_le_bytes());
2115 h = hash_bytes_u64(h, &nonce.to_le_bytes());
2116 h = hash_bytes_u64(h, &(dsz as u64).to_le_bytes());
2117
2118 h = hash_bytes_u64(h, payload_bytes);
2120 Ok(h)
2121}
2122
2123mod payload_compression {
2124 use crate::TelemetryError;
2125 use alloc::borrow::Cow;
2126 #[cfg(feature = "compression")]
2127 use alloc::vec;
2128 use alloc::vec::Vec;
2129
2130 #[cfg(feature = "compression")]
2131 use crate::config::runtime_payload_compress_threshold;
2132 #[cfg(feature = "compression")]
2133 use zstd_safe::CompressionLevel;
2134
2135 #[cfg(feature = "compression")]
2143 pub fn compress_if_beneficial(payload: &'_ [u8]) -> (bool, Cow<'_, [u8]>) {
2144 if payload.len() < runtime_payload_compress_threshold() {
2145 return (false, Cow::Borrowed(payload));
2146 }
2147
2148 let Some(compressed) = compress_to_vec_bounded(payload, payload.len().saturating_sub(2))
2150 else {
2151 return (false, Cow::Borrowed(payload));
2152 };
2153
2154 if compressed.len() + 1 >= payload.len() {
2156 (false, Cow::Borrowed(payload))
2157 } else {
2158 (true, Cow::Owned(compressed))
2159 }
2160 }
2161
2162 #[cfg(feature = "compression")]
2163 fn compress_to_vec_bounded(input: &[u8], max_output: usize) -> Option<Vec<u8>> {
2164 if input.is_empty() || max_output == 0 {
2165 return None;
2166 }
2167
2168 let mut out = vec![0u8; max_output];
2169 let level: CompressionLevel = 1;
2171 let written = zstd_safe::compress(&mut out[..], input, level).ok()?;
2172 out.truncate(written);
2173 Some(out)
2174 }
2175
2176 #[cfg(feature = "compression")]
2186 pub fn decompress(compressed: &[u8], expected_len: usize) -> Result<Vec<u8>, TelemetryError> {
2187 let mut out = vec![0u8; expected_len];
2188 let written = zstd_safe::decompress(&mut out[..], compressed)
2189 .map_err(|_| TelemetryError::Unpack("decompression failed"))?;
2190 if written != expected_len {
2191 return Err(TelemetryError::Unpack("decompressed size mismatch"));
2192 }
2193 Ok(out)
2194 }
2195
2196 #[cfg(not(feature = "compression"))]
2198 pub fn compress_if_beneficial<'a>(payload: &'a [u8]) -> (bool, Cow<'a, [u8]>) {
2200 (false, Cow::Borrowed(payload))
2201 }
2202
2203 #[cfg(not(feature = "compression"))]
2204 pub fn decompress(_compressed: &[u8], _expected_len: usize) -> Result<Vec<u8>, TelemetryError> {
2206 Err(TelemetryError::Unpack(
2207 "compressed payloads not supported (compression feature disabled)",
2208 ))
2209 }
2210}
2211
2212#[cfg(test)]
2213mod endpoint_decode_tests {
2214 use super::*;
2215
2216 #[test]
2217 fn numeric_sender_alias_keeps_packet_wire_and_receipt_identity() {
2218 let ty = DataType::ReliableAck;
2219 let make = |sender: &str| {
2220 Packet::new_with_wire_contract(
2221 ty,
2222 message_meta(ty).endpoints_ref(),
2223 sender,
2224 200,
2225 9,
2226 Arc::from(42u64.to_le_bytes()),
2227 Some(MessageElement::Static(
2228 2,
2229 crate::MessageDataType::UInt32,
2230 crate::MessageClass::Data,
2231 )),
2232 Arc::from([123u64]),
2233 )
2234 .unwrap()
2235 };
2236 let named = make("FC");
2237 let alias = alloc::format!("@addr:{}", sender_address_u32("FC"));
2238 let unresolved = make(&alias);
2239 assert_eq!(unresolved.packet_id(), named.packet_id());
2240 let named_wire = pack_packet(&named);
2241 let alias_wire = pack_packet(&unresolved);
2242 assert_eq!(alias_wire, named_wire);
2243 assert_eq!(packet_id_from_wire(&alias_wire).unwrap(), named.packet_id());
2244 assert_eq!(
2245 unpack_packet(&alias_wire).unwrap().packet_id(),
2246 named.packet_id()
2247 );
2248 }
2249
2250 #[test]
2251 fn scheduling_type_is_bounded_and_never_replaces_frame_validation() {
2252 let pkt = Packet::new_with_wire_contract(
2253 DataType::ReliableAck,
2254 message_meta(DataType::ReliableAck).endpoints_ref(),
2255 "E2EACK:GS",
2256 100,
2257 1,
2258 Arc::from(42u64.to_le_bytes()),
2259 Some(MessageElement::Static(
2260 2,
2261 crate::MessageDataType::UInt32,
2262 crate::MessageClass::Data,
2263 )),
2264 Arc::from([123u64]),
2265 )
2266 .unwrap();
2267 let mut bytes = pack_packet(&pkt).to_vec();
2268 assert_eq!(scheduling_type(&bytes), Some(DataType::ReliableAck));
2269 let last = bytes.len() - 1;
2270 bytes[last] ^= 1;
2271 assert_eq!(scheduling_type(&bytes), Some(DataType::ReliableAck));
2272 assert!(peek_routing_envelope(&bytes).is_err());
2273 assert!(unpack_packet(&bytes).is_err());
2274 assert_eq!(scheduling_type(&[0, 0, 0x80]), None);
2275 assert_eq!(scheduling_type(&[0xff; 1024]), None);
2276 assert_eq!(scheduling_type(&[]), None);
2277 }
2278
2279 #[test]
2280 fn receipt_contract_omits_redundant_builtin_endpoint_bitmap() {
2281 for ty in [
2282 DataType::ReliableAck,
2283 DataType::ReliablePartialAck,
2284 DataType::ReliablePacketRequest,
2285 ] {
2286 let shape = Some(MessageElement::Static(
2287 2,
2288 crate::MessageDataType::UInt32,
2289 crate::MessageClass::Data,
2290 ));
2291 let targets: Arc<[u64]> = Arc::from([0xa7fcbb129e92435f, 0x41426f62de53eb28]);
2292 let payload: Arc<[u8]> = Arc::from(0x9c2a63d6d7d44100u64.to_le_bytes());
2293 let make = |eps: &[DataEndpoint]| {
2294 Packet::new_with_wire_contract(
2295 ty,
2296 eps,
2297 "E2EACK:GS",
2298 1791737696510,
2299 1234,
2300 payload.clone(),
2301 shape,
2302 targets.clone(),
2303 )
2304 .unwrap()
2305 };
2306 let packet = make(message_meta(ty).endpoints_ref());
2307 let packed = pack_packet(&packet);
2308 assert_eq!(packed[0] & FLAG_ENDPOINT_BITMAP_PRESENT, 0);
2309 assert_ne!(packed[0] & FLAG_WIRE_CONTRACT, 0);
2310 let routing = peek_routing_envelope(&packed).unwrap();
2311 assert_eq!(routing.endpoints().collect::<Vec<_>>(), packet.endpoints());
2312 assert_eq!(
2313 routing.target_senders().collect::<Vec<_>>(),
2314 targets.as_ref()
2315 );
2316 let decoded = unpack_packet(&packed).unwrap();
2317 assert_eq!(decoded.packet_id(), packet.packet_id());
2318 assert_eq!(decoded.payload(), packet.payload());
2319 assert_eq!(decoded.wire_target_senders(), targets.as_ref());
2320 let explicit = pack_packet(&make(&[DataEndpoint::Discovery]));
2322 assert_ne!(explicit[0] & FLAG_ENDPOINT_LIST_PRESENT, 0);
2323 assert_eq!(
2324 explicit.len(),
2325 packed.len() + uleb128_size(u64::from(DataEndpoint::Discovery.0))
2326 );
2327 assert_eq!(
2328 unpack_packet(&explicit).unwrap().endpoints(),
2329 &[DataEndpoint::Discovery]
2330 );
2331 }
2332 }
2333
2334 #[test]
2335 fn borrowed_routing_header_preserves_targets_and_validates_truncated_contracts() {
2336 let targets: Arc<[u64]> = Arc::from([1, u64::MAX, 42]);
2337 let packet = Packet::new_with_wire_contract(
2338 DataType::DiscoverySchema,
2339 &[DataEndpoint::Discovery],
2340 "PEER",
2341 1234,
2342 7,
2343 Arc::from([1u8, 2, 3]),
2344 Some(MessageElement::Dynamic(
2345 crate::MessageDataType::Binary,
2346 crate::MessageClass::Data,
2347 )),
2348 targets.clone(),
2349 )
2350 .unwrap();
2351 let packed = pack_packet(&packet);
2352 let routing = peek_routing_envelope(&packed).unwrap();
2353 let full = unpack_packet(&packed).unwrap();
2354 assert_eq!(routing.ty, full.data_type());
2355 assert_eq!(routing.endpoints().collect::<Vec<_>>(), full.endpoints());
2356 assert_eq!(
2357 routing.target_senders().collect::<Vec<_>>(),
2358 targets.as_ref()
2359 );
2360 assert_eq!(routing.timestamp_ms, full.timestamp());
2361 let data = verify_crc32(&packed).unwrap();
2363 let mut reader = ByteReader::new(data);
2364 read_routing_envelope(&mut reader).unwrap();
2365 for end in 0..reader.off {
2366 let mut truncated = data[..end].to_vec();
2367 append_crc32(&mut truncated);
2368 assert!(
2369 peek_routing_envelope(&truncated).is_err(),
2370 "accepted cut at {end}"
2371 );
2372 }
2373 }
2374
2375 #[test]
2376 fn large_packet_with_long_prefix_does_not_grow_packing_buffer() {
2377 let payload: Vec<u8> = (0..3500)
2378 .map(|i| ((i * 73 + i / 251) % 256) as u8)
2379 .collect();
2380 let packet = Packet::new(
2381 DataType::DiscoverySchema,
2382 &[DataEndpoint::Discovery],
2383 "LONG_PREFIX_SENDER",
2384 u64::MAX,
2385 payload.into(),
2386 )
2387 .unwrap()
2388 .with_nonce(u16::MAX);
2389 assert!(header_size_bytes(&packet) > 16);
2390 let packed = pack_packet(&packet);
2391 let unpacked = unpack_packet(&packed).unwrap();
2392 assert_eq!(unpacked.payload(), packet.payload());
2393 assert_eq!(unpacked.timestamp(), u64::MAX);
2394 assert_eq!(unpacked.nonce(), u16::MAX);
2395 }
2396
2397 #[test]
2398 fn bitmap_decode_preserves_sorted_unique_destinations() {
2399 let input = [
2400 DataEndpoint::TelemetryError,
2401 DataEndpoint::TimeSync,
2402 DataEndpoint::Discovery,
2403 DataEndpoint::TimeSync,
2404 ];
2405 let decoded = expand_endpoint_bitmap(&build_endpoint_bitmap(&input)).unwrap();
2406 assert_eq!(
2407 &*decoded,
2408 &[
2409 DataEndpoint::TimeSync,
2410 DataEndpoint::Discovery,
2411 DataEndpoint::TelemetryError
2412 ]
2413 );
2414 assert!(
2415 expand_endpoint_bitmap(&[0; EP_BITMAP_BYTES])
2416 .unwrap()
2417 .is_empty()
2418 );
2419 assert!(expand_endpoint_bitmap(&[0; EP_BITMAP_BYTES - 1]).is_err());
2420 }
2421
2422 #[test]
2423 fn bitmap_decode_rejects_unregistered_endpoint_bits() {
2424 if let Some(id) =
2425 (0..=MAX_VALUE_DATA_ENDPOINT).find(|id| DataEndpoint::try_from_u32(*id).is_none())
2426 {
2427 let mut bitmap = [0; EP_BITMAP_BYTES];
2428 bitmap[id as usize / 8] = 1 << (id % 8);
2429 assert!(expand_endpoint_bitmap(&bitmap).is_err());
2430 }
2431 }
2432}