1use core::time::Duration;
2
3#[cfg(not(feature = "std"))]
4use alloc::{sync::Arc, vec::Vec};
5#[cfg(feature = "std")]
6use std::sync::Arc;
7
8#[cfg(not(feature = "std"))]
9use core::cell::OnceCell as OnceLock;
10#[cfg(feature = "std")]
11use std::sync::OnceLock;
12
13use bytes::Bytes;
14
15use crate::tlv_type;
16use crate::{Name, PacketError, SignatureInfo};
17use ndn_tlv::TlvReader;
18
19#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
21pub struct Selector {
22 pub can_be_prefix: bool,
23 pub must_be_fresh: bool,
24}
25
26#[derive(Debug)]
32pub struct Interest {
33 pub(crate) raw: Bytes,
35
36 pub name: Arc<Name>,
38
39 selectors: OnceLock<Selector>,
41
42 nonce: OnceLock<Option<u32>>,
44
45 lifetime: OnceLock<Option<Duration>>,
47
48 app_params: OnceLock<Option<Bytes>>,
50
51 hop_limit: OnceLock<Option<u8>>,
53
54 forwarding_hint: OnceLock<Option<Vec<Arc<Name>>>>,
56
57 sig_info: OnceLock<Option<SignatureInfo>>,
59
60 sig_value: OnceLock<Option<Bytes>>,
62}
63
64impl Interest {
65 pub fn new(name: Name) -> Self {
67 Self {
68 raw: Bytes::new(),
69 name: Arc::new(name),
70 selectors: OnceLock::new(),
71 nonce: OnceLock::new(),
72 lifetime: OnceLock::new(),
73 app_params: OnceLock::new(),
74 hop_limit: OnceLock::new(),
75 forwarding_hint: OnceLock::new(),
76 sig_info: OnceLock::new(),
77 sig_value: OnceLock::new(),
78 }
79 }
80
81 pub fn decode(raw: Bytes) -> Result<Self, PacketError> {
83 let mut reader = TlvReader::new(raw.clone());
84 let (typ, value) = reader.read_tlv()?;
85 if typ != tlv_type::INTEREST {
86 return Err(PacketError::UnknownPacketType(typ));
87 }
88 let mut inner = TlvReader::new(value);
89
90 let (name_typ, name_val) = inner.read_tlv()?;
92 if name_typ != tlv_type::NAME {
93 return Err(PacketError::UnknownPacketType(name_typ));
94 }
95 let name = Name::decode(name_val)?;
96
97 if name.is_empty() {
100 return Err(PacketError::MalformedPacket(
101 "Interest Name must have at least one component".into(),
102 ));
103 }
104
105 Ok(Self {
113 raw,
114 name: Arc::new(name),
115 selectors: OnceLock::new(),
116 nonce: OnceLock::new(),
117 lifetime: OnceLock::new(),
118 app_params: OnceLock::new(),
119 hop_limit: OnceLock::new(),
120 forwarding_hint: OnceLock::new(),
121 sig_info: OnceLock::new(),
122 sig_value: OnceLock::new(),
123 })
124 }
125
126 pub fn selectors(&self) -> &Selector {
127 self.selectors
128 .get_or_init(|| decode_selectors(&self.raw).unwrap_or_default())
129 }
130
131 pub fn nonce(&self) -> Option<u32> {
132 *self
133 .nonce
134 .get_or_init(|| decode_nonce(&self.raw).ok().flatten())
135 }
136
137 pub fn lifetime(&self) -> Option<Duration> {
138 *self
139 .lifetime
140 .get_or_init(|| decode_lifetime(&self.raw).ok().flatten())
141 }
142
143 pub fn app_parameters(&self) -> Option<&Bytes> {
148 self.app_params
149 .get_or_init(|| decode_app_params(&self.raw).ok().flatten())
150 .as_ref()
151 }
152
153 pub fn forwarding_hint(&self) -> Option<&[Arc<Name>]> {
159 self.forwarding_hint
160 .get_or_init(|| decode_forwarding_hint(&self.raw).ok().flatten())
161 .as_deref()
162 }
163
164 pub fn hop_limit(&self) -> Option<u8> {
169 *self
170 .hop_limit
171 .get_or_init(|| decode_hop_limit(&self.raw).ok().flatten())
172 }
173
174 pub fn sig_info(&self) -> Option<&SignatureInfo> {
176 self.sig_info
177 .get_or_init(|| decode_interest_sig_info(&self.raw).ok().flatten())
178 .as_ref()
179 }
180
181 pub fn sig_value(&self) -> Option<&Bytes> {
183 self.sig_value
184 .get_or_init(|| decode_interest_sig_value(&self.raw).ok().flatten())
185 .as_ref()
186 }
187
188 pub fn signed_region(&self) -> Option<&[u8]> {
193 compute_interest_signed_region(&self.raw).ok().flatten()
194 }
195
196 pub fn raw(&self) -> &Bytes {
197 &self.raw
198 }
199}
200
201fn decode_selectors(raw: &Bytes) -> Result<Selector, PacketError> {
202 let mut sel = Selector::default();
203 let mut reader = TlvReader::new(raw.clone());
204 let (_, value) = reader.read_tlv()?; let mut inner = TlvReader::new(value);
206 while !inner.is_empty() {
207 let (typ, _) = inner.read_tlv()?;
208 match typ {
209 t if t == tlv_type::CAN_BE_PREFIX => sel.can_be_prefix = true,
210 t if t == tlv_type::MUST_BE_FRESH => sel.must_be_fresh = true,
211 _ => {}
212 }
213 }
214 Ok(sel)
215}
216
217fn decode_nonce(raw: &Bytes) -> Result<Option<u32>, PacketError> {
218 let mut reader = TlvReader::new(raw.clone());
219 let (_, value) = reader.read_tlv()?;
220 let mut inner = TlvReader::new(value);
221 while !inner.is_empty() {
222 let (typ, val) = inner.read_tlv()?;
223 if typ == tlv_type::NONCE {
224 if val.len() != 4 {
225 return Ok(None);
226 }
227 let n = u32::from_be_bytes([val[0], val[1], val[2], val[3]]);
228 return Ok(Some(n));
229 }
230 }
231 Ok(None)
232}
233
234fn decode_app_params(raw: &Bytes) -> Result<Option<Bytes>, PacketError> {
235 if raw.is_empty() {
236 return Ok(None);
237 }
238 let mut reader = TlvReader::new(raw.clone());
239 let (_, value) = reader.read_tlv()?;
240 let mut inner = TlvReader::new(value);
241 while !inner.is_empty() {
242 let (typ, val) = inner.read_tlv()?;
243 if typ == tlv_type::APP_PARAMETERS {
244 return Ok(Some(val));
245 }
246 }
247 Ok(None)
248}
249
250fn decode_forwarding_hint(raw: &Bytes) -> Result<Option<Vec<Arc<Name>>>, PacketError> {
251 if raw.is_empty() {
252 return Ok(None);
253 }
254 let mut reader = TlvReader::new(raw.clone());
255 let (_, value) = reader.read_tlv()?;
256 let mut inner = TlvReader::new(value);
257 while !inner.is_empty() {
258 let (typ, val) = inner.read_tlv()?;
259 if typ == tlv_type::FORWARDING_HINT {
260 let mut hint_reader = TlvReader::new(val);
262 let mut names = Vec::new();
263 while !hint_reader.is_empty() {
264 let (t, v) = hint_reader.read_tlv()?;
265 if t == tlv_type::NAME {
266 names.push(Arc::new(Name::decode(v)?));
267 }
268 }
269 if names.is_empty() {
270 return Ok(None);
271 }
272 return Ok(Some(names));
273 }
274 }
275 Ok(None)
276}
277
278fn decode_hop_limit(raw: &Bytes) -> Result<Option<u8>, PacketError> {
279 if raw.is_empty() {
280 return Ok(None);
281 }
282 let mut reader = TlvReader::new(raw.clone());
283 let (_, value) = reader.read_tlv()?;
284 let mut inner = TlvReader::new(value);
285 while !inner.is_empty() {
286 let (typ, val) = inner.read_tlv()?;
287 if typ == tlv_type::HOP_LIMIT {
288 if val.len() == 1 {
289 return Ok(Some(val[0]));
290 }
291 return Ok(None);
292 }
293 }
294 Ok(None)
295}
296
297fn decode_interest_sig_info(raw: &Bytes) -> Result<Option<SignatureInfo>, PacketError> {
298 if raw.is_empty() {
299 return Ok(None);
300 }
301 let mut reader = TlvReader::new(raw.clone());
302 let (_, value) = reader.read_tlv()?;
303 let mut inner = TlvReader::new(value);
304 while !inner.is_empty() {
305 let (typ, val) = inner.read_tlv()?;
306 if typ == tlv_type::INTEREST_SIGNATURE_INFO {
307 return Ok(Some(SignatureInfo::decode(val)?));
308 }
309 }
310 Ok(None)
311}
312
313fn decode_interest_sig_value(raw: &Bytes) -> Result<Option<Bytes>, PacketError> {
314 if raw.is_empty() {
315 return Ok(None);
316 }
317 let mut reader = TlvReader::new(raw.clone());
318 let (_, value) = reader.read_tlv()?;
319 let mut inner = TlvReader::new(value);
320 while !inner.is_empty() {
321 let (typ, val) = inner.read_tlv()?;
322 if typ == tlv_type::INTEREST_SIGNATURE_VALUE {
323 return Ok(Some(val));
324 }
325 }
326 Ok(None)
327}
328
329fn compute_interest_signed_region(raw: &Bytes) -> Result<Option<&[u8]>, PacketError> {
335 if raw.is_empty() {
336 return Ok(None);
337 }
338 let mut reader = TlvReader::new(raw.clone());
339 let (_, value) = reader.read_tlv()?;
340 let outer_header_len = raw.len() - value.len();
341 let mut inner = TlvReader::new(value);
342 let mut sig_info_end = 0usize;
343 while !inner.is_empty() {
344 let (typ, _) = inner.read_tlv()?;
345 if typ == tlv_type::INTEREST_SIGNATURE_INFO {
346 sig_info_end = outer_header_len + inner.position();
347 break;
348 }
349 }
350 if sig_info_end == 0 {
351 return Ok(None);
352 }
353 Ok(Some(&raw[outer_header_len..sig_info_end]))
355}
356
357fn decode_lifetime(raw: &Bytes) -> Result<Option<Duration>, PacketError> {
358 let mut reader = TlvReader::new(raw.clone());
359 let (_, value) = reader.read_tlv()?;
360 let mut inner = TlvReader::new(value);
361 while !inner.is_empty() {
362 let (typ, val) = inner.read_tlv()?;
363 if typ == tlv_type::INTEREST_LIFETIME {
364 let mut ms = 0u64;
365 for &b in val.iter() {
366 ms = (ms << 8) | b as u64;
367 }
368 return Ok(Some(Duration::from_millis(ms)));
369 }
370 }
371 Ok(None)
372}
373
374#[cfg(test)]
375mod tests {
376 use super::*;
377 use ndn_tlv::TlvWriter;
378
379 fn build_interest(
381 components: &[&[u8]],
382 nonce: Option<u32>,
383 lifetime_ms: Option<u64>,
384 can_be_prefix: bool,
385 must_be_fresh: bool,
386 ) -> Bytes {
387 build_interest_full(
388 components,
389 nonce,
390 lifetime_ms,
391 can_be_prefix,
392 must_be_fresh,
393 None,
394 )
395 }
396
397 fn build_interest_full(
398 components: &[&[u8]],
399 nonce: Option<u32>,
400 lifetime_ms: Option<u64>,
401 can_be_prefix: bool,
402 must_be_fresh: bool,
403 hop_limit: Option<u8>,
404 ) -> Bytes {
405 let mut w = TlvWriter::new();
406 w.write_nested(tlv_type::INTEREST, |w| {
407 w.write_nested(tlv_type::NAME, |w| {
408 for comp in components {
409 w.write_tlv(tlv_type::NAME_COMPONENT, comp);
410 }
411 });
412 if can_be_prefix {
413 w.write_tlv(tlv_type::CAN_BE_PREFIX, &[]);
414 }
415 if must_be_fresh {
416 w.write_tlv(tlv_type::MUST_BE_FRESH, &[]);
417 }
418 if let Some(n) = nonce {
419 w.write_tlv(tlv_type::NONCE, &n.to_be_bytes());
420 }
421 if let Some(ms) = lifetime_ms {
422 w.write_tlv(tlv_type::INTEREST_LIFETIME, &ms.to_be_bytes());
423 }
424 if let Some(h) = hop_limit {
425 w.write_tlv(tlv_type::HOP_LIMIT, &[h]);
426 }
427 });
428 w.finish()
429 }
430
431 #[test]
434 fn new_stores_name() {
435 let name =
436 Name::from_components([crate::NameComponent::generic(Bytes::from_static(b"test"))]);
437 let i = Interest::new(name.clone());
438 assert_eq!(*i.name, name);
439 }
440
441 #[test]
442 fn new_has_no_nonce_or_lifetime() {
443 let i = Interest::new(Name::root());
444 assert_eq!(i.nonce(), None);
445 assert_eq!(i.lifetime(), None);
446 }
447
448 #[test]
451 fn decode_name_only() {
452 let raw = build_interest(&[b"edu", b"ucla"], None, None, false, false);
453 let i = Interest::decode(raw).unwrap();
454 assert_eq!(i.name.len(), 2);
455 assert_eq!(i.name.components()[0].value.as_ref(), b"edu");
456 assert_eq!(i.name.components()[1].value.as_ref(), b"ucla");
457 }
458
459 #[test]
460 fn decode_with_nonce() {
461 let raw = build_interest(&[b"test"], Some(0xDEAD_BEEF), None, false, false);
462 let i = Interest::decode(raw).unwrap();
463 assert_eq!(i.nonce(), Some(0xDEAD_BEEF));
464 }
465
466 #[test]
467 fn decode_with_lifetime() {
468 let raw = build_interest(&[b"test"], None, Some(4000), false, false);
469 let i = Interest::decode(raw).unwrap();
470 assert_eq!(i.lifetime(), Some(Duration::from_millis(4000)));
471 }
472
473 #[test]
474 fn decode_with_can_be_prefix() {
475 let raw = build_interest(&[b"test"], None, None, true, false);
476 let i = Interest::decode(raw).unwrap();
477 assert!(i.selectors().can_be_prefix);
478 assert!(!i.selectors().must_be_fresh);
479 }
480
481 #[test]
482 fn decode_with_must_be_fresh() {
483 let raw = build_interest(&[b"test"], None, None, false, true);
484 let i = Interest::decode(raw).unwrap();
485 assert!(!i.selectors().can_be_prefix);
486 assert!(i.selectors().must_be_fresh);
487 }
488
489 #[test]
490 fn decode_with_all_fields() {
491 let raw = build_interest(
492 &[b"edu", b"ucla", b"data"],
493 Some(0x1234_5678),
494 Some(8000),
495 true,
496 true,
497 );
498 let i = Interest::decode(raw).unwrap();
499 assert_eq!(i.name.len(), 3);
500 assert_eq!(i.nonce(), Some(0x1234_5678));
501 assert_eq!(i.lifetime(), Some(Duration::from_millis(8000)));
502 assert!(i.selectors().can_be_prefix);
503 assert!(i.selectors().must_be_fresh);
504 }
505
506 #[test]
507 fn decode_raw_field_preserved() {
508 let raw = build_interest(&[b"test"], Some(42), None, false, false);
509 let i = Interest::decode(raw.clone()).unwrap();
510 assert_eq!(i.raw(), &raw);
511 }
512
513 #[test]
514 fn decode_wrong_outer_type_errors() {
515 let mut w = TlvWriter::new();
517 w.write_nested(tlv_type::DATA, |w| {
518 w.write_nested(tlv_type::NAME, |w| {
519 w.write_tlv(tlv_type::NAME_COMPONENT, b"test");
520 });
521 });
522 let raw = w.finish();
523 assert!(matches!(
524 Interest::decode(raw).unwrap_err(),
525 crate::PacketError::UnknownPacketType(0x06)
526 ));
527 }
528
529 #[test]
530 fn decode_with_forwarding_hint() {
531 let mut w = TlvWriter::new();
532 w.write_nested(tlv_type::INTEREST, |w| {
533 w.write_nested(tlv_type::NAME, |w| {
534 w.write_tlv(tlv_type::NAME_COMPONENT, b"test");
535 });
536 w.write_nested(tlv_type::FORWARDING_HINT, |w| {
537 w.write_nested(tlv_type::NAME, |w| {
538 w.write_tlv(tlv_type::NAME_COMPONENT, b"ndn");
539 w.write_tlv(tlv_type::NAME_COMPONENT, b"gateway");
540 });
541 });
542 });
543 let raw = w.finish();
544 let i = Interest::decode(raw).unwrap();
545 let hints = i.forwarding_hint().expect("forwarding_hint present");
546 assert_eq!(hints.len(), 1);
547 assert_eq!(hints[0].len(), 2);
548 assert_eq!(hints[0].components()[0].value.as_ref(), b"ndn");
549 }
550
551 #[test]
552 fn decode_without_forwarding_hint() {
553 let raw = build_interest(&[b"test"], None, None, false, false);
554 let i = Interest::decode(raw).unwrap();
555 assert!(i.forwarding_hint().is_none());
556 }
557
558 #[test]
559 fn decode_app_params_wrong_digest_accepted() {
560 let mut w = TlvWriter::new();
563 w.write_nested(tlv_type::INTEREST, |w| {
564 w.write_nested(tlv_type::NAME, |w| {
565 w.write_tlv(tlv_type::NAME_COMPONENT, b"test");
566 w.write_tlv(tlv_type::PARAMETERS_SHA256, &[0u8; 32]); });
568 w.write_tlv(tlv_type::APP_PARAMETERS, b"hello");
569 });
570 let raw = w.finish();
571 let i = Interest::decode(raw).expect("should accept despite wrong digest");
572 assert_eq!(
573 i.app_parameters().map(|b| b.as_ref()),
574 Some(b"hello".as_ref())
575 );
576 }
577
578 #[test]
579 fn decode_app_params_without_digest_accepted() {
580 let mut w = TlvWriter::new();
583 w.write_nested(tlv_type::INTEREST, |w| {
584 w.write_nested(tlv_type::NAME, |w| {
585 w.write_tlv(tlv_type::NAME_COMPONENT, b"test");
586 });
587 w.write_tlv(tlv_type::APP_PARAMETERS, b"hello");
588 });
589 let raw = w.finish();
590 let i = Interest::decode(raw).expect("should accept without digest component");
591 assert_eq!(
592 i.app_parameters().map(|b| b.as_ref()),
593 Some(b"hello".as_ref())
594 );
595 }
596
597 #[test]
598 fn decode_empty_name_rejected() {
599 let mut w = TlvWriter::new();
601 w.write_nested(tlv_type::INTEREST, |w| {
602 w.write_tlv(tlv_type::NAME, &[]); });
604 let raw = w.finish();
605 assert!(Interest::decode(raw).is_err());
606 }
607
608 #[test]
609 fn decode_truncated_errors() {
610 let raw = Bytes::from_static(&[0x05, 0x10, 0x07]); assert!(Interest::decode(raw).is_err());
612 }
613
614 #[test]
615 fn decode_with_hop_limit() {
616 let raw = build_interest_full(&[b"test"], None, None, false, false, Some(64));
617 let i = Interest::decode(raw).unwrap();
618 assert_eq!(i.hop_limit(), Some(64));
619 }
620
621 #[test]
622 fn decode_without_hop_limit() {
623 let raw = build_interest(&[b"test"], None, None, false, false);
624 let i = Interest::decode(raw).unwrap();
625 assert_eq!(i.hop_limit(), None);
626 }
627
628 #[test]
629 fn decode_hop_limit_zero() {
630 let raw = build_interest_full(&[b"test"], None, None, false, false, Some(0));
631 let i = Interest::decode(raw).unwrap();
632 assert_eq!(i.hop_limit(), Some(0));
633 }
634
635 fn build_signed_interest(components: &[&[u8]], sig_type_code: u8, sig_value: &[u8]) -> Bytes {
638 let mut w = TlvWriter::new();
639 w.write_nested(tlv_type::INTEREST, |w| {
640 w.write_nested(tlv_type::NAME, |w| {
641 for comp in components {
642 w.write_tlv(tlv_type::NAME_COMPONENT, comp);
643 }
644 });
645 w.write_nested(tlv_type::INTEREST_SIGNATURE_INFO, |w| {
646 w.write_tlv(tlv_type::SIGNATURE_TYPE, &[sig_type_code]);
647 });
648 w.write_tlv(tlv_type::INTEREST_SIGNATURE_VALUE, sig_value);
649 });
650 w.finish()
651 }
652
653 #[test]
654 fn decode_signed_interest_sig_info() {
655 let raw = build_signed_interest(&[b"test"], 5, &[0xAB, 0xCD]);
656 let i = Interest::decode(raw).unwrap();
657 let si = i.sig_info().expect("sig_info present");
658 assert_eq!(si.sig_type, crate::SignatureType::SignatureEd25519);
659 }
660
661 #[test]
662 fn decode_signed_interest_sig_value() {
663 let raw = build_signed_interest(&[b"test"], 5, &[0xDE, 0xAD]);
664 let i = Interest::decode(raw).unwrap();
665 let sv = i.sig_value().expect("sig_value present");
666 assert_eq!(sv.as_ref(), &[0xDE, 0xAD]);
667 }
668
669 #[test]
670 fn decode_signed_interest_signed_region() {
671 let raw = build_signed_interest(&[b"test"], 5, &[0xAB, 0xCD]);
672 let i = Interest::decode(raw.clone()).unwrap();
673 let region = i.signed_region().expect("signed region present");
674 assert!(!region.is_empty());
676 assert!(!region.ends_with(&[0xAB, 0xCD]));
678 assert_eq!(region[0], tlv_type::NAME as u8);
680 }
681
682 #[test]
683 fn unsigned_interest_has_no_sig_fields() {
684 let raw = build_interest(&[b"test"], None, None, false, false);
685 let i = Interest::decode(raw).unwrap();
686 assert!(i.sig_info().is_none());
687 assert!(i.sig_value().is_none());
688 assert!(i.signed_region().is_none());
689 }
690
691 #[test]
692 fn signed_interest_with_key_locator() {
693 let mut w = TlvWriter::new();
694 w.write_nested(tlv_type::INTEREST, |w| {
695 w.write_nested(tlv_type::NAME, |w| {
696 w.write_tlv(tlv_type::NAME_COMPONENT, b"test");
697 });
698 w.write_nested(tlv_type::INTEREST_SIGNATURE_INFO, |w| {
699 w.write_tlv(tlv_type::SIGNATURE_TYPE, &[5]);
700 w.write_nested(tlv_type::KEY_LOCATOR, |w| {
701 w.write_nested(tlv_type::NAME, |w| {
702 w.write_tlv(tlv_type::NAME_COMPONENT, b"key1");
703 });
704 });
705 });
706 w.write_tlv(tlv_type::INTEREST_SIGNATURE_VALUE, &[0xFF]);
707 });
708 let raw = w.finish();
709 let i = Interest::decode(raw).unwrap();
710 let si = i.sig_info().unwrap();
711 let kl = si.key_locator.as_ref().expect("key_locator present");
712 assert_eq!(kl.components()[0].value.as_ref(), b"key1");
713 }
714
715 #[test]
716 fn lazy_fields_decoded_once_and_cached() {
717 let raw = build_interest(&[b"x"], Some(99), Some(1000), true, false);
719 let i = Interest::decode(raw).unwrap();
720 assert_eq!(i.nonce(), i.nonce());
721 assert_eq!(i.lifetime(), i.lifetime());
722 assert_eq!(i.selectors(), i.selectors());
723 }
724}