1use core::{marker::PhantomData, ops::Range};
2
3use crate::{
4 BuildError, ChannelId, Fcf, FloodHops, MicSize, NodeHint, OptionNumber, PacketType, PublicKey,
5 Scf, SecInfo, UnsealedPacket, options::OptionEncoder,
6};
7
8pub mod state {
10 pub struct NeedsSource;
12 pub struct NeedsCounter;
14 pub struct Configuring;
16 pub struct Complete;
18}
19
20pub struct PacketBuilder<'a> {
25 buf: &'a mut [u8],
26}
27
28impl<'a> PacketBuilder<'a> {
29 pub fn new(buf: &'a mut [u8]) -> Self {
31 Self { buf }
32 }
33
34 pub fn broadcast(self) -> BroadcastBuilder<'a, state::NeedsSource> {
36 Builder::new(self.buf, PacketType::Broadcast)
37 }
38
39 pub fn mac_ack(self, ack_trailer: [u8; 8]) -> MacAckBuilder<'a, state::Configuring> {
46 let mut builder = Builder::new(self.buf, PacketType::MacAck);
47 builder.ack_tag = Some(ack_trailer);
48 builder
49 }
50
51 pub fn unicast(self, dst: NodeHint) -> UnicastBuilder<'a, state::NeedsSource> {
53 let mut builder = Builder::new(self.buf, PacketType::Unicast);
54 builder.dst = Some(dst);
55 builder
56 }
57
58 pub fn multicast(self, channel: ChannelId) -> MulticastBuilder<'a, state::NeedsSource> {
60 let mut builder = Builder::new(self.buf, PacketType::Multicast);
61 builder.channel = Some(channel);
62 builder
63 }
64
65 pub fn blind_unicast(
67 self,
68 channel: ChannelId,
69 dst: NodeHint,
70 ) -> BlindUnicastBuilder<'a, state::NeedsSource> {
71 let mut builder = Builder::new(self.buf, PacketType::BlindUnicast);
72 builder.channel = Some(channel);
73 builder.dst = Some(dst);
74 builder
75 }
76}
77
78pub type BroadcastBuilder<'a, S> = Builder<'a, BroadcastKind, S>;
80pub type MacAckBuilder<'a, S> = Builder<'a, MacAckKind, S>;
82pub type UnicastBuilder<'a, S> = Builder<'a, UnicastKind, S>;
84pub type MulticastBuilder<'a, S> = Builder<'a, MulticastKind, S>;
86pub type BlindUnicastBuilder<'a, S> = Builder<'a, BlindUnicastKind, S>;
88
89pub struct BroadcastKind;
91pub struct MacAckKind;
93pub struct UnicastKind;
95pub struct MulticastKind;
97pub struct BlindUnicastKind;
99
100enum SourceValue {
101 Hint(NodeHint),
102 Full(PublicKey),
103}
104
105pub struct Builder<'a, K, S> {
107 buf: &'a mut [u8],
108 packet_type: PacketType,
109 options_len: usize,
110 options_scratch: Option<Range<usize>>,
111 last_option_number: Option<u16>,
112 option_error: Option<BuildError>,
113 source: Option<SourceValue>,
114 dst: Option<NodeHint>,
115 channel: Option<ChannelId>,
116 ack_tag: Option<[u8; 8]>,
117 frame_counter: Option<u32>,
118 encrypted: bool,
119 mic_size: MicSize,
120 salt: Option<u16>,
121 flood_hops: Option<FloodHops>,
122 payload: Option<Range<usize>>,
123 blind_addr: Option<Range<usize>>,
124 _marker: PhantomData<(K, S)>,
125}
126
127impl<'a, K, S> Builder<'a, K, S> {
128 fn new(buf: &'a mut [u8], packet_type: PacketType) -> Self {
129 Self {
130 buf,
131 packet_type,
132 options_len: 0,
133 options_scratch: None,
134 last_option_number: None,
135 option_error: None,
136 source: None,
137 dst: None,
138 channel: None,
139 ack_tag: None,
140 frame_counter: None,
141 encrypted: matches!(
142 packet_type,
143 PacketType::BlindUnicast | PacketType::BlindUnicastAckReq
144 ),
145 mic_size: MicSize::Mic16,
146 salt: None,
147 flood_hops: None,
148 payload: None,
149 blind_addr: None,
150 _marker: PhantomData,
151 }
152 }
153
154 fn with_state<NS>(self) -> Builder<'a, K, NS> {
155 Builder {
156 buf: self.buf,
157 packet_type: self.packet_type,
158 options_len: self.options_len,
159 options_scratch: self.options_scratch,
160 last_option_number: self.last_option_number,
161 option_error: self.option_error,
162 source: self.source,
163 dst: self.dst,
164 channel: self.channel,
165 ack_tag: self.ack_tag,
166 frame_counter: self.frame_counter,
167 encrypted: self.encrypted,
168 mic_size: self.mic_size,
169 salt: self.salt,
170 flood_hops: self.flood_hops,
171 payload: self.payload,
172 blind_addr: self.blind_addr,
173 _marker: PhantomData,
174 }
175 }
176
177 fn push_option(&mut self, number: u16, value: &[u8]) {
178 if self.option_error.is_some() {
179 return;
180 }
181 if let Some(last) = self.last_option_number {
182 if number < last {
183 self.option_error = Some(BuildError::OptionOutOfOrder);
184 return;
185 }
186 }
187 let mut live = match self.last_option_number {
188 Some(last_number) => {
189 OptionEncoder::with_last_number(&mut self.buf[1 + self.options_len..], last_number)
190 }
191 None => OptionEncoder::new(&mut self.buf[1 + self.options_len..]),
192 };
193 match live.put(number, value) {
194 Ok(()) => {
195 self.options_len += live.finish();
196 self.last_option_number = Some(number);
197 }
198 Err(err) => self.option_error = Some(err.into()),
199 }
200 }
201
202 fn stash_options(&mut self) -> Result<(), BuildError> {
205 if self.options_len == 0 {
206 return Ok(());
207 }
208 let payload_len = self.payload.as_ref().map(|p| p.end - p.start).unwrap_or(0);
209 let scratch_end = self
210 .buf
211 .len()
212 .checked_sub(payload_len)
213 .ok_or(BuildError::BufferTooSmall)?;
214 let scratch_start = scratch_end
215 .checked_sub(self.options_len)
216 .ok_or(BuildError::BufferTooSmall)?;
217 if scratch_start < 1 + self.options_len {
218 return Err(BuildError::BufferTooSmall);
219 }
220 self.buf.copy_within(1..1 + self.options_len, scratch_start);
221 self.options_scratch = Some(scratch_start..scratch_end);
222 Ok(())
223 }
224
225 fn emit_options(
228 &mut self,
229 cursor: &mut usize,
230 has_payload: bool,
231 ) -> Result<Range<usize>, BuildError> {
232 let start = *cursor;
233 if let Some(scratch) = self.options_scratch.clone() {
234 let len = scratch.end - scratch.start;
235 let end = start.checked_add(len).ok_or(BuildError::BufferTooSmall)?;
236 if end > self.buf.len() {
237 return Err(BuildError::BufferTooSmall);
238 }
239 self.buf.copy_within(scratch, start);
240 *cursor = end;
241 }
242 if has_payload {
243 let marker_slot = *cursor;
244 if marker_slot >= self.buf.len() {
245 return Err(BuildError::BufferTooSmall);
246 }
247 self.buf[marker_slot] = 0xFF;
248 *cursor = marker_slot + 1;
249 }
250 Ok(start..*cursor)
251 }
252
253 fn write_common_prefix(&mut self) -> Result<usize, BuildError> {
254 if let Some(err) = self.option_error {
255 return Err(err);
256 }
257 self.stash_options()?;
258 let full_source = matches!(self.source, Some(SourceValue::Full(_)));
259 let fcf = Fcf::new(self.packet_type, full_source, self.flood_hops.is_some());
260 if self.buf.is_empty() {
261 return Err(BuildError::BufferTooSmall);
262 }
263 self.buf[0] = fcf.0;
264 let mut cursor = 1;
265 if let Some(fhops) = self.flood_hops {
266 self.buf
267 .get_mut(cursor)
268 .ok_or(BuildError::BufferTooSmall)
269 .map(|slot| *slot = fhops.0)?;
270 cursor += 1;
271 }
272 Ok(cursor)
273 }
274
275 fn write_source(&mut self, cursor: &mut usize) -> Result<(), BuildError> {
276 match self.source {
277 Some(SourceValue::Hint(hint)) => {
278 let end = *cursor + 3;
279 self.buf
280 .get_mut(*cursor..end)
281 .ok_or(BuildError::BufferTooSmall)?
282 .copy_from_slice(&hint.0);
283 *cursor = end;
284 }
285 Some(SourceValue::Full(key)) => {
286 let end = *cursor + 32;
287 self.buf
288 .get_mut(*cursor..end)
289 .ok_or(BuildError::BufferTooSmall)?
290 .copy_from_slice(&key.0);
291 *cursor = end;
292 }
293 None => return Err(BuildError::MissingSource),
294 }
295 Ok(())
296 }
297
298 fn stage_payload(&mut self, data: &[u8]) {
299 let scratch_start = match self.buf.len().checked_sub(data.len()) {
300 Some(value) => value,
301 None => {
302 self.option_error = Some(BuildError::BufferTooSmall);
303 return;
304 }
305 };
306 if let Some(slot) = self.buf.get_mut(scratch_start..scratch_start + data.len()) {
307 slot.copy_from_slice(data);
308 self.payload = Some(scratch_start..scratch_start + data.len());
309 } else {
310 self.option_error = Some(BuildError::BufferTooSmall);
311 }
312 }
313
314 fn has_body_bytes(&self) -> bool {
322 self.payload.as_ref().is_some_and(|range| !range.is_empty())
323 }
324
325 fn copy_staged_payload(&mut self, cursor: &mut usize) -> Result<Range<usize>, BuildError> {
326 let payload = self.payload.clone().ok_or(BuildError::MissingPayload)?;
327 let len = payload.end - payload.start;
328 let start = *cursor;
329 let end = start + len;
330 if end > self.buf.len() {
331 return Err(BuildError::BufferTooSmall);
332 }
333 self.buf.copy_within(payload, start);
334 *cursor = end;
335 Ok(start..end)
336 }
337
338 fn stage_blind_addr(&mut self, cursor: &mut usize) -> Result<Range<usize>, BuildError> {
339 let dst = self.dst.ok_or(BuildError::MissingDestination)?;
340 let start = *cursor;
341 let dst_end = start + 3;
342 self.buf
343 .get_mut(start..dst_end)
344 .ok_or(BuildError::BufferTooSmall)?
345 .copy_from_slice(&dst.0);
346 *cursor = dst_end;
347 self.write_source(cursor)?;
348 let end = *cursor;
349 Ok(start..end)
350 }
351}
352
353impl<'a> BroadcastBuilder<'a, state::NeedsSource> {
354 pub fn source_hint(mut self, hint: NodeHint) -> BroadcastBuilder<'a, state::Configuring> {
356 self.source = Some(SourceValue::Hint(hint));
357 self.with_state()
358 }
359
360 pub fn source_full(mut self, key: &PublicKey) -> BroadcastBuilder<'a, state::Configuring> {
362 self.source = Some(SourceValue::Full(*key));
363 self.with_state()
364 }
365}
366
367impl<'a> UnicastBuilder<'a, state::NeedsSource> {
368 pub fn source_hint(mut self, hint: NodeHint) -> UnicastBuilder<'a, state::NeedsCounter> {
370 self.source = Some(SourceValue::Hint(hint));
371 self.with_state()
372 }
373
374 pub fn source_full(mut self, key: &PublicKey) -> UnicastBuilder<'a, state::NeedsCounter> {
376 self.source = Some(SourceValue::Full(*key));
377 self.with_state()
378 }
379}
380
381impl<'a> MulticastBuilder<'a, state::NeedsSource> {
382 pub fn source_hint(mut self, hint: NodeHint) -> MulticastBuilder<'a, state::NeedsCounter> {
384 self.source = Some(SourceValue::Hint(hint));
385 self.with_state()
386 }
387
388 pub fn source_full(mut self, key: &PublicKey) -> MulticastBuilder<'a, state::NeedsCounter> {
390 self.source = Some(SourceValue::Full(*key));
391 self.with_state()
392 }
393}
394
395impl<'a> BlindUnicastBuilder<'a, state::NeedsSource> {
396 pub fn source_hint(mut self, hint: NodeHint) -> BlindUnicastBuilder<'a, state::NeedsCounter> {
398 self.source = Some(SourceValue::Hint(hint));
399 self.with_state()
400 }
401
402 pub fn source_full(mut self, key: &PublicKey) -> BlindUnicastBuilder<'a, state::NeedsCounter> {
404 self.source = Some(SourceValue::Full(*key));
405 self.with_state()
406 }
407}
408
409impl<'a> UnicastBuilder<'a, state::NeedsCounter> {
410 pub fn frame_counter(mut self, counter: u32) -> UnicastBuilder<'a, state::Configuring> {
412 self.frame_counter = Some(counter);
413 self.with_state()
414 }
415}
416
417impl<'a> MulticastBuilder<'a, state::NeedsCounter> {
418 pub fn frame_counter(mut self, counter: u32) -> MulticastBuilder<'a, state::Configuring> {
420 self.frame_counter = Some(counter);
421 self.with_state()
422 }
423}
424
425impl<'a> BlindUnicastBuilder<'a, state::NeedsCounter> {
426 pub fn frame_counter(mut self, counter: u32) -> BlindUnicastBuilder<'a, state::Configuring> {
428 self.frame_counter = Some(counter);
429 self.with_state()
430 }
431}
432
433macro_rules! impl_configuring_common {
434 ($name:ident<$state:ty>) => {
435 impl<'a> $name<'a, $state> {
436 pub fn flood_hops(mut self, remaining: u8) -> Self {
438 if let Some(value) = FloodHops::new(remaining, 0) {
439 self.flood_hops = Some(value);
440 }
441 self
442 }
443
444 pub fn region_code(mut self, code: [u8; 2]) -> Self {
446 self.push_option(OptionNumber::RegionCode.as_u16(), &code);
447 self
448 }
449
450 pub fn trace_route(mut self) -> Self {
452 self.push_option(OptionNumber::TraceRoute.as_u16(), &[]);
453 self
454 }
455
456 pub fn trace_signal(mut self) -> Self {
459 self.push_option(OptionNumber::TraceSignal.as_u16(), &[]);
460 self
461 }
462
463 pub fn source_route(mut self, hops: &[crate::RouterHint]) -> Self {
465 let mut encoded = [0u8; 30];
466 let needed = hops.len() * 2;
467 if needed > encoded.len() {
468 self.option_error = Some(BuildError::BufferTooSmall);
469 return self;
470 }
471 for (index, hop) in hops.iter().enumerate() {
472 encoded[index * 2..index * 2 + 2].copy_from_slice(&hop.0);
473 }
474 self.push_option(OptionNumber::SourceRoute.as_u16(), &encoded[..needed]);
475 self
476 }
477
478 pub fn option(mut self, number: OptionNumber, value: &[u8]) -> Self {
480 self.push_option(number.as_u16(), value);
481 self
482 }
483 }
484 };
485}
486
487impl_configuring_common!(BroadcastBuilder<state::Configuring>);
488impl_configuring_common!(MacAckBuilder<state::Configuring>);
489impl_configuring_common!(UnicastBuilder<state::Configuring>);
490impl_configuring_common!(MulticastBuilder<state::Configuring>);
491impl_configuring_common!(BlindUnicastBuilder<state::Configuring>);
492
493impl<'a> UnicastBuilder<'a, state::Configuring> {
494 pub fn ack_requested(mut self) -> Self {
496 self.packet_type = PacketType::UnicastAckReq;
497 self
498 }
499
500 pub fn encrypted(mut self) -> Self {
502 self.encrypted = true;
503 self
504 }
505
506 pub fn mic_size(mut self, size: MicSize) -> Self {
508 self.mic_size = size;
509 self
510 }
511
512 pub fn salt(mut self, salt: u16) -> Self {
514 self.salt = Some(salt);
515 self
516 }
517
518 pub fn payload(mut self, data: &[u8]) -> UnicastBuilder<'a, state::Complete> {
520 self.stage_payload(data);
521 self.with_state()
522 }
523}
524
525impl<'a> MulticastBuilder<'a, state::Configuring> {
526 pub fn encrypted(mut self) -> Self {
528 self.encrypted = true;
529 self
530 }
531
532 pub fn mic_size(mut self, size: MicSize) -> Self {
534 self.mic_size = size;
535 self
536 }
537
538 pub fn salt(mut self, salt: u16) -> Self {
540 self.salt = Some(salt);
541 self
542 }
543
544 pub fn payload(mut self, data: &[u8]) -> MulticastBuilder<'a, state::Complete> {
546 self.stage_payload(data);
547 self.with_state()
548 }
549}
550
551impl<'a> BlindUnicastBuilder<'a, state::Configuring> {
552 pub fn ack_requested(mut self) -> Self {
554 self.packet_type = PacketType::BlindUnicastAckReq;
555 self
556 }
557
558 pub fn encrypted(mut self) -> Self {
560 self.encrypted = true;
561 self
562 }
563
564 pub fn unencrypted(mut self) -> Self {
570 self.encrypted = false;
571 self
572 }
573
574 pub fn mic_size(mut self, size: MicSize) -> Self {
576 self.mic_size = size;
577 self
578 }
579
580 pub fn salt(mut self, salt: u16) -> Self {
582 self.salt = Some(salt);
583 self
584 }
585
586 pub fn payload(mut self, data: &[u8]) -> BlindUnicastBuilder<'a, state::Complete> {
588 self.stage_payload(data);
589 self.with_state()
590 }
591}
592
593impl<'a> BroadcastBuilder<'a, state::Configuring> {
594 pub fn payload(mut self, data: &[u8]) -> BroadcastBuilder<'a, state::Complete> {
596 self.stage_payload(data);
597 self.with_state()
598 }
599
600 pub fn build(mut self) -> Result<&'a [u8], BuildError> {
604 let has_payload = self.has_body_bytes();
605 let mut cursor = self.write_common_prefix()?;
606 self.write_source(&mut cursor)?;
607 self.emit_options(&mut cursor, has_payload)?;
608 if has_payload {
609 let _ = self.copy_staged_payload(&mut cursor)?;
610 }
611 Ok(&self.buf[..cursor])
612 }
613}
614
615impl<'a> BroadcastBuilder<'a, state::Complete> {
616 pub fn build(self) -> Result<&'a [u8], BuildError> {
618 self.with_state::<state::Configuring>().build()
619 }
620}
621
622impl<'a> MacAckBuilder<'a, state::Configuring> {
623 pub fn build(mut self) -> Result<&'a [u8], BuildError> {
629 let mut cursor = self.write_common_prefix()?;
630 self.emit_options(&mut cursor, false)?;
631 let ack_trailer = self.ack_tag.ok_or(BuildError::MissingAckTag)?;
632 self.buf
633 .get_mut(cursor..cursor + 8)
634 .ok_or(BuildError::BufferTooSmall)?
635 .copy_from_slice(&ack_trailer);
636 cursor += 8;
637 Ok(&self.buf[..cursor])
638 }
639}
640
641impl<'a> UnicastBuilder<'a, state::Complete> {
642 pub fn build(self) -> Result<UnsealedPacket<'a>, BuildError> {
643 self.with_state::<state::Configuring>().build()
644 }
645}
646
647impl<'a> UnicastBuilder<'a, state::Configuring> {
648 pub fn build(mut self) -> Result<UnsealedPacket<'a>, BuildError> {
650 let has_payload = self.has_body_bytes();
651 let mut cursor = self.write_common_prefix()?;
652 let dst = self.dst.ok_or(BuildError::MissingDestination)?;
653 self.buf
654 .get_mut(cursor..cursor + 3)
655 .ok_or(BuildError::BufferTooSmall)?
656 .copy_from_slice(&dst.0);
657 cursor += 3;
658 self.write_source(&mut cursor)?;
659 let scf = Scf::new(self.encrypted, self.mic_size, self.salt.is_some());
660 let sec_info = SecInfo {
661 scf,
662 frame_counter: self.frame_counter.ok_or(BuildError::MissingFrameCounter)?,
663 salt: self.salt,
664 };
665 let sec_start = cursor;
666 cursor += sec_info.encode(
667 self.buf
668 .get_mut(cursor..)
669 .ok_or(BuildError::BufferTooSmall)?,
670 )?;
671 let opts_range = self.emit_options(&mut cursor, has_payload)?;
672 let body_start = cursor;
673 let body_range = if has_payload {
674 self.copy_staged_payload(&mut cursor)?
675 } else {
676 body_start..body_start
677 };
678 let mic_start = cursor;
679 let mic_end = mic_start + self.mic_size.byte_len();
680 self.buf
681 .get_mut(mic_start..mic_end)
682 .ok_or(BuildError::BufferTooSmall)?
683 .fill(0);
684 cursor = mic_end;
685 Ok(UnsealedPacket::new(
686 self.buf,
687 cursor,
688 body_range,
689 None,
690 mic_start..mic_end,
691 sec_start..sec_start + sec_info.wire_len(),
692 opts_range,
693 ))
694 }
695}
696
697impl<'a> MulticastBuilder<'a, state::Complete> {
698 pub fn build(self) -> Result<UnsealedPacket<'a>, BuildError> {
699 self.with_state::<state::Configuring>().build()
700 }
701}
702
703impl<'a> MulticastBuilder<'a, state::Configuring> {
704 pub fn build(mut self) -> Result<UnsealedPacket<'a>, BuildError> {
707 let mut cursor = self.write_common_prefix()?;
708 let channel = self.channel.ok_or(BuildError::MissingChannel)?;
709 self.buf
710 .get_mut(cursor..cursor + 2)
711 .ok_or(BuildError::BufferTooSmall)?
712 .copy_from_slice(&channel.0);
713 cursor += 2;
714 let scf = Scf::new(self.encrypted, self.mic_size, self.salt.is_some());
715 let sec_info = SecInfo {
716 scf,
717 frame_counter: self.frame_counter.ok_or(BuildError::MissingFrameCounter)?,
718 salt: self.salt,
719 };
720 let sec_start = cursor;
721 cursor += sec_info.encode(
722 self.buf
723 .get_mut(cursor..)
724 .ok_or(BuildError::BufferTooSmall)?,
725 )?;
726 let opts_range = self.emit_options(&mut cursor, true)?;
728 let body_start = cursor;
729 self.write_source(&mut cursor)?;
730 let payload_range = self.copy_staged_payload(&mut cursor)?;
731 let body_range = if self.encrypted {
732 body_start..payload_range.end
733 } else {
734 payload_range
735 };
736 let mic_start = cursor;
737 let mic_end = mic_start + self.mic_size.byte_len();
738 self.buf
739 .get_mut(mic_start..mic_end)
740 .ok_or(BuildError::BufferTooSmall)?
741 .fill(0);
742 cursor = mic_end;
743 Ok(UnsealedPacket::new(
744 self.buf,
745 cursor,
746 body_range,
747 None,
748 mic_start..mic_end,
749 sec_start..sec_start + sec_info.wire_len(),
750 opts_range,
751 ))
752 }
753}
754
755impl<'a> BlindUnicastBuilder<'a, state::Complete> {
756 pub fn build(self) -> Result<UnsealedPacket<'a>, BuildError> {
757 self.with_state::<state::Configuring>().build()
758 }
759}
760
761impl<'a> BlindUnicastBuilder<'a, state::Configuring> {
762 pub fn build(mut self) -> Result<UnsealedPacket<'a>, BuildError> {
765 let mut cursor = self.write_common_prefix()?;
766 let channel = self.channel.ok_or(BuildError::MissingChannel)?;
767 self.buf
768 .get_mut(cursor..cursor + 2)
769 .ok_or(BuildError::BufferTooSmall)?
770 .copy_from_slice(&channel.0);
771 cursor += 2;
772 let scf = Scf::new(self.encrypted, self.mic_size, self.salt.is_some());
773 let sec_info = SecInfo {
774 scf,
775 frame_counter: self.frame_counter.ok_or(BuildError::MissingFrameCounter)?,
776 salt: self.salt,
777 };
778 let sec_start = cursor;
779 cursor += sec_info.encode(
780 self.buf
781 .get_mut(cursor..)
782 .ok_or(BuildError::BufferTooSmall)?,
783 )?;
784 let opts_range = self.emit_options(&mut cursor, true)?;
786 let blind_addr_range = self.stage_blind_addr(&mut cursor)?;
787 let body_range = self.copy_staged_payload(&mut cursor)?;
788 let mic_start = cursor;
789 let mic_end = mic_start + self.mic_size.byte_len();
790 self.buf
791 .get_mut(mic_start..mic_end)
792 .ok_or(BuildError::BufferTooSmall)?
793 .fill(0);
794 cursor = mic_end;
795 Ok(UnsealedPacket::new(
796 self.buf,
797 cursor,
798 body_range,
799 Some(blind_addr_range),
800 mic_start..mic_end,
801 sec_start..sec_start + sec_info.wire_len(),
802 opts_range,
803 ))
804 }
805}