1use crate::alloc::borrow::ToOwned;
8use core::borrow::Borrow;
9use core::convert::TryFrom as _;
10use core::fmt::Debug;
11use core::mem::MaybeUninit;
12use core::num::{NonZeroU16, TryFromIntError};
13use core::ops::Range;
14
15use arrayvec::ArrayVec;
16use log::info;
17use net_types::ip::IpAddress;
18use packet::records::options::OptionSequenceBuilder;
19use packet::InnerSerializer;
20use packet_formats::tcp::options::{TcpOption, TcpSackBlock};
21use packet_formats::tcp::{TcpSegment, TcpSegmentBuilder, TcpSegmentBuilderWithOptions};
22use thiserror::Error;
23
24use super::base::{Control, Mss};
25use super::seqnum::{SeqNum, UnscaledWindowSize, WindowScale, WindowSize};
26
27#[derive(Debug, PartialEq, Eq, Clone)]
29pub struct Segment<P> {
30 header: SegmentHeader,
32 data: P,
37}
38
39#[derive(Debug, PartialEq, Eq, Clone)]
41pub struct SegmentHeader {
42 pub seq: SeqNum,
44 pub ack: Option<SeqNum>,
46 pub wnd: UnscaledWindowSize,
48 pub control: Option<Control>,
50 pub push: bool,
52 pub options: Options,
54}
55
56#[derive(Debug, PartialEq, Eq, Clone)]
58pub enum Options {
59 Handshake(HandshakeOptions),
61 Segment(SegmentOptions),
63}
64
65impl Default for Options {
66 fn default() -> Self {
67 Self::Segment(SegmentOptions::default())
70 }
71}
72
73impl From<HandshakeOptions> for Options {
74 fn from(value: HandshakeOptions) -> Self {
75 Self::Handshake(value)
76 }
77}
78
79impl From<SegmentOptions> for Options {
80 fn from(value: SegmentOptions) -> Self {
81 Self::Segment(value)
82 }
83}
84
85impl Options {
86 pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
88 match self {
89 Options::Handshake(o) => either::Either::Left(o.iter()),
90 Options::Segment(o) => either::Either::Right(o.iter()),
91 }
92 }
93
94 fn as_handshake(&self) -> Option<&HandshakeOptions> {
95 match self {
96 Self::Handshake(h) => Some(h),
97 Self::Segment(_) => None,
98 }
99 }
100
101 fn as_handshake_mut(&mut self) -> Option<&mut HandshakeOptions> {
102 match self {
103 Self::Handshake(h) => Some(h),
104 Self::Segment(_) => None,
105 }
106 }
107
108 fn as_segment(&self) -> Option<&SegmentOptions> {
109 match self {
110 Self::Handshake(_) => None,
111 Self::Segment(s) => Some(s),
112 }
113 }
114
115 fn as_segment_mut(&mut self) -> Option<&mut SegmentOptions> {
116 match self {
117 Self::Handshake(_) => None,
118 Self::Segment(s) => Some(s),
119 }
120 }
121
122 pub fn new_with_handshake(handshake: bool) -> Self {
125 if handshake {
126 Self::Handshake(Default::default())
127 } else {
128 Self::Segment(Default::default())
129 }
130 }
131
132 pub fn from_iter<'a>(handshake: bool, iter: impl IntoIterator<Item = TcpOption<'a>>) -> Self {
137 let mut options = Self::new_with_handshake(handshake);
138 for option in iter {
139 match option {
140 TcpOption::Mss(mss) => {
141 if let Some(h) = options.as_handshake_mut() {
142 h.mss = NonZeroU16::new(mss).map(Mss);
143 }
144 }
145 TcpOption::WindowScale(ws) => {
146 if let Some(h) = options.as_handshake_mut() {
147 if ws > WindowScale::MAX.get() {
152 info!(
153 "received an out-of-range window scale: {}, want < {}",
154 ws,
155 WindowScale::MAX.get()
156 );
157 }
158 h.window_scale = Some(WindowScale::new(ws).unwrap_or(WindowScale::MAX));
159 }
160 }
161 TcpOption::SackPermitted => {
162 if let Some(h) = options.as_handshake_mut() {
163 h.sack_permitted = true;
164 }
165 }
166 TcpOption::Sack(sack) => {
167 if let Some(seg) = options.as_segment_mut() {
168 seg.sack_blocks = SackBlocks::from_option(sack);
169 }
170 }
171 TcpOption::Timestamp { ts_val: _, ts_echo_reply: _ } => {}
173 }
174 }
175 options
176 }
177
178 pub fn window_scale(&self) -> Option<WindowScale> {
180 self.as_handshake().and_then(|h| h.window_scale)
181 }
182
183 pub fn mss(&self) -> Option<Mss> {
185 self.as_handshake().and_then(|h| h.mss)
186 }
187
188 pub fn sack_permitted(&self) -> bool {
191 self.as_handshake().is_some_and(|o| o.sack_permitted)
192 }
193
194 pub fn sack_blocks(&self) -> &SackBlocks {
198 const EMPTY_REF: &'static SackBlocks = &SackBlocks::EMPTY;
199 self.as_segment().map(|s| &s.sack_blocks).unwrap_or(EMPTY_REF)
200 }
201}
202
203#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
205pub struct HandshakeOptions {
206 pub mss: Option<Mss>,
208
209 pub window_scale: Option<WindowScale>,
211
212 pub sack_permitted: bool,
214}
215
216impl HandshakeOptions {
217 pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
219 let Self { mss, window_scale, sack_permitted } = self;
220 mss.map(|mss| TcpOption::Mss(mss.get().get()))
221 .into_iter()
222 .chain(window_scale.map(|ws| TcpOption::WindowScale(ws.get())))
223 .chain((*sack_permitted).then_some(TcpOption::SackPermitted))
224 }
225}
226
227#[derive(Debug, Default, PartialEq, Eq, Clone)]
229pub struct SegmentOptions {
230 pub sack_blocks: SackBlocks,
232}
233
234impl SegmentOptions {
235 pub fn iter(&self) -> impl Iterator<Item = TcpOption<'_>> + Debug + Clone {
237 let Self { sack_blocks } = self;
238 sack_blocks.as_option().into_iter()
239 }
240}
241
242const MAX_SACK_BLOCKS: usize = 4;
243#[derive(Debug, Default, PartialEq, Eq, Clone)]
245pub struct SackBlocks(ArrayVec<TcpSackBlock, MAX_SACK_BLOCKS>);
246
247impl SackBlocks {
248 pub const EMPTY: Self = SackBlocks(ArrayVec::new_const());
250
251 pub const MAX_BLOCKS: usize = MAX_SACK_BLOCKS;
257
258 pub fn as_option(&self) -> Option<TcpOption<'_>> {
262 let Self(inner) = self;
263 if inner.is_empty() {
264 return None;
265 }
266
267 Some(TcpOption::Sack(inner.as_slice()))
268 }
269
270 pub fn iter_skip_invalid(&self) -> impl Iterator<Item = SackBlock> + '_ {
273 self.try_iter().filter_map(|r| match r {
274 Ok(s) => Some(s),
275 Err(InvalidSackBlockError(_, _)) => None,
276 })
277 }
278
279 pub fn try_iter(&self) -> impl Iterator<Item = Result<SackBlock, InvalidSackBlockError>> + '_ {
282 let Self(inner) = self;
283 inner.iter().map(|block| SackBlock::try_from(*block))
284 }
285
286 pub fn from_option(blocks: &[TcpSackBlock]) -> Self {
291 Self(blocks.iter().take(Self::MAX_BLOCKS).copied().collect())
292 }
293
294 pub fn is_empty(&self) -> bool {
296 let Self(inner) = self;
297 inner.is_empty()
298 }
299
300 pub fn clear(&mut self) {
302 let Self(inner) = self;
303 inner.clear()
304 }
305}
306
307impl FromIterator<SackBlock> for SackBlocks {
311 fn from_iter<T: IntoIterator<Item = SackBlock>>(iter: T) -> Self {
312 Self(iter.into_iter().take(Self::MAX_BLOCKS).map(|b| b.into()).collect())
313 }
314}
315
316mod sack_block {
317 use super::*;
318
319 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
324 pub struct SackBlock {
325 left: SeqNum,
327 right: SeqNum,
328 }
329
330 impl SackBlock {
331 pub fn try_new(left: SeqNum, right: SeqNum) -> Result<Self, InvalidSackBlockError> {
335 if right.after(left) {
336 Ok(Self { left, right })
337 } else {
338 Err(InvalidSackBlockError(left, right))
339 }
340 }
341
342 pub unsafe fn new_unchecked(left: SeqNum, right: SeqNum) -> Self {
349 Self { left, right }
350 }
351
352 pub fn into_range(self) -> Range<SeqNum> {
354 let Self { left, right } = self;
355 Range { start: left, end: right }
356 }
357
358 pub fn into_range_u32(self) -> Range<u32> {
361 let Self { left, right } = self;
362 Range { start: left.into(), end: right.into() }
363 }
364
365 pub fn left(&self) -> SeqNum {
367 self.left
368 }
369
370 pub fn right(&self) -> SeqNum {
372 self.right
373 }
374
375 pub fn into_parts(self) -> (SeqNum, SeqNum) {
378 let Self { left, right } = self;
379 (left, right)
380 }
381 }
382
383 #[derive(Debug, Eq, PartialEq, Clone, Copy)]
386 pub struct InvalidSackBlockError(pub SeqNum, pub SeqNum);
387
388 impl From<SackBlock> for TcpSackBlock {
389 fn from(value: SackBlock) -> Self {
390 let SackBlock { left, right } = value;
391 TcpSackBlock::new(left.into(), right.into())
392 }
393 }
394
395 impl TryFrom<TcpSackBlock> for SackBlock {
396 type Error = InvalidSackBlockError;
397
398 fn try_from(value: TcpSackBlock) -> Result<Self, Self::Error> {
399 Self::try_new(value.left_edge().into(), value.right_edge().into())
400 }
401 }
402
403 impl From<SackBlock> for Range<SeqNum> {
404 fn from(value: SackBlock) -> Self {
405 value.into_range()
406 }
407 }
408
409 impl TryFrom<Range<SeqNum>> for SackBlock {
410 type Error = InvalidSackBlockError;
411
412 fn try_from(value: Range<SeqNum>) -> Result<Self, Self::Error> {
413 let Range { start, end } = value;
414 Self::try_new(start, end)
415 }
416 }
417}
418pub use sack_block::{InvalidSackBlockError, SackBlock};
419
420pub const MAX_PAYLOAD_AND_CONTROL_LEN: usize = 1 << 31;
422const MAX_PAYLOAD_AND_CONTROL_LEN_U32: u32 = MAX_PAYLOAD_AND_CONTROL_LEN as u32;
424
425impl<P: Payload> Segment<P> {
426 pub fn new(header: SegmentHeader, data: P) -> (Self, usize) {
431 let SegmentHeader { seq, ack, wnd, control, push, options } = header;
432 let has_control_len = control.map(Control::has_sequence_no).unwrap_or(false);
433
434 let data_len = data.len();
435 let discarded_len =
436 data_len.saturating_sub(MAX_PAYLOAD_AND_CONTROL_LEN - usize::from(has_control_len));
437
438 let push = push && data_len != 0;
440
441 let (control, data) = if discarded_len > 0 {
442 let (control, control_len) = if control == Some(Control::FIN) {
445 (None, 0)
446 } else {
447 (control, has_control_len.into())
448 };
449 (control, data.slice(0..MAX_PAYLOAD_AND_CONTROL_LEN_U32 - control_len))
452 } else {
453 (control, data)
454 };
455
456 (
457 Segment { header: SegmentHeader { seq, ack, wnd, control, push, options }, data: data },
458 discarded_len,
459 )
460 }
461
462 pub fn header(&self) -> &SegmentHeader {
464 &self.header
465 }
466
467 pub fn data(&self) -> &P {
469 &self.data
470 }
471
472 pub fn into_parts(self) -> (SegmentHeader, P) {
475 let Self { header, data } = self;
476 (header, data)
477 }
478
479 pub fn map_payload<R, F: FnOnce(P) -> R>(self, f: F) -> Segment<R> {
481 let Segment { header, data } = self;
482 Segment { header, data: f(data) }
483 }
484
485 pub fn len(&self) -> u32 {
491 self.header.len(self.data.len())
492 }
493
494 pub fn overlap(self, rnxt: SeqNum, rwnd: WindowSize) -> Option<Segment<P>> {
496 let len = self.len();
497 let Segment { header: SegmentHeader { seq, ack, wnd, control, options, push }, data } =
498 self;
499
500 let overlap = match (len, rwnd) {
512 (0, WindowSize::ZERO) => seq == rnxt,
513 (0, rwnd) => !rnxt.after(seq) && seq.before(rnxt + rwnd),
514 (_len, WindowSize::ZERO) => false,
515 (len, rwnd) => {
516 (!rnxt.after(seq) && seq.before(rnxt + rwnd))
517 || (!(seq + len).before(rnxt) && !(seq + len).after(rnxt + rwnd))
528 }
529 };
530 overlap.then(move || {
531 let cmp = |lhs: &SeqNum, rhs: &SeqNum| (*lhs - *rhs).cmp(&0);
534 let new_seq = core::cmp::max_by(seq, rnxt, cmp);
535 let new_len = core::cmp::min_by(seq + len, rnxt + rwnd, cmp) - new_seq;
536 let start = u32::try_from(new_seq - seq).unwrap();
541 let new_len = u32::try_from(new_len).unwrap();
550 let (new_control, new_data) = {
551 match control {
552 Some(Control::SYN) => {
553 if start == 0 {
554 (Some(Control::SYN), data.slice(start..start + new_len - 1))
555 } else {
556 (None, data.slice(start - 1..start + new_len - 1))
557 }
558 }
559 Some(Control::FIN) => {
560 if len == start + new_len {
561 if new_len > 0 {
562 (Some(Control::FIN), data.slice(start..start + new_len - 1))
563 } else {
564 (None, data.slice(start - 1..start - 1))
565 }
566 } else {
567 (None, data.slice(start..start + new_len))
568 }
569 }
570 Some(Control::RST) | None => (control, data.slice(start..start + new_len)),
571 }
572 };
573 Segment {
574 header: SegmentHeader {
575 seq: new_seq,
576 ack,
577 wnd,
578 control: new_control,
579 options,
580 push,
581 },
582 data: new_data,
583 }
584 })
585 }
586
587 pub fn new_empty(header: SegmentHeader) -> Self {
589 let (seg, truncated) = Self::new(header, P::new_empty());
592 debug_assert_eq!(truncated, 0);
593 seg
594 }
595
596 pub fn ack(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize) -> Self {
598 Self::ack_with_options(seq, ack, wnd, Options::default())
599 }
600
601 pub fn ack_with_options(
603 seq: SeqNum,
604 ack: SeqNum,
605 wnd: UnscaledWindowSize,
606 options: Options,
607 ) -> Self {
608 Segment::new_empty(SegmentHeader {
609 seq,
610 ack: Some(ack),
611 wnd,
612 control: None,
613 push: false,
614 options,
615 })
616 }
617
618 pub fn syn(seq: SeqNum, wnd: UnscaledWindowSize, options: Options) -> Self {
620 Segment::new_empty(SegmentHeader {
621 seq,
622 ack: None,
623 wnd,
624 control: Some(Control::SYN),
625 push: false,
626 options,
627 })
628 }
629
630 pub fn syn_ack(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize, options: Options) -> Self {
632 Segment::new_empty(SegmentHeader {
633 seq,
634 ack: Some(ack),
635 wnd,
636 control: Some(Control::SYN),
637 push: false,
638 options,
639 })
640 }
641
642 pub fn rst(seq: SeqNum) -> Self {
644 Segment::new_empty(SegmentHeader {
645 seq,
646 ack: None,
647 wnd: UnscaledWindowSize::from(0),
648 control: Some(Control::RST),
649 push: false,
650 options: Options::default(),
651 })
652 }
653
654 pub fn rst_ack(seq: SeqNum, ack: SeqNum) -> Self {
656 Segment::new_empty(SegmentHeader {
657 seq,
658 ack: Some(ack),
659 wnd: UnscaledWindowSize::from(0),
660 control: Some(Control::RST),
661 push: false,
662 options: Options::default(),
663 })
664 }
665}
666
667impl Segment<()> {
668 pub fn into_empty<P: Payload>(self) -> Segment<P> {
671 self.map_payload(|()| P::new_empty())
672 }
673}
674
675impl SegmentHeader {
676 pub fn len(&self, payload_len: usize) -> u32 {
682 let has_control_len = self.control.map(Control::has_sequence_no).unwrap_or(false);
686 u32::try_from(payload_len).unwrap() + u32::from(has_control_len)
687 }
688
689 pub fn from_builder<A: IpAddress>(
692 builder: &TcpSegmentBuilder<A>,
693 ) -> Result<Self, MalformedFlags> {
694 Self::from_builder_options(builder, Options::new_with_handshake(builder.syn_set()))
695 }
696
697 pub fn from_builder_options<A: IpAddress>(
699 builder: &TcpSegmentBuilder<A>,
700 options: Options,
701 ) -> Result<Self, MalformedFlags> {
702 Ok(SegmentHeader {
703 seq: SeqNum::new(builder.seq_num()),
704 ack: builder.ack_num().map(SeqNum::new),
705 control: Flags {
706 syn: builder.syn_set(),
707 fin: builder.fin_set(),
708 rst: builder.rst_set(),
709 }
710 .control()?,
711 wnd: UnscaledWindowSize::from(builder.window_size()),
712 push: builder.psh_set(),
713 options: options,
714 })
715 }
716}
717
718pub trait PayloadLen {
720 fn len(&self) -> usize;
722}
723
724pub trait Payload: PayloadLen + Sized {
726 fn slice(self, range: Range<u32>) -> Self;
735
736 fn partial_copy(&self, offset: usize, dst: &mut [u8]);
742
743 fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]);
749
750 fn new_empty() -> Self;
754}
755
756impl PayloadLen for &[u8] {
757 fn len(&self) -> usize {
758 <[u8]>::len(self)
759 }
760}
761
762impl Payload for &[u8] {
763 fn slice(self, Range { start, end }: Range<u32>) -> Self {
764 let start = usize::try_from(start).unwrap_or_else(|TryFromIntError { .. }| {
769 panic!("range start index {} out of range for slice of length {}", start, self.len())
770 });
771 let end = usize::try_from(end).unwrap_or_else(|TryFromIntError { .. }| {
772 panic!("range end index {} out of range for slice of length {}", end, self.len())
773 });
774 &self[start..end]
775 }
776
777 fn partial_copy(&self, offset: usize, dst: &mut [u8]) {
778 dst.copy_from_slice(&self[offset..offset + dst.len()])
779 }
780
781 fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]) {
782 let src = &self[offset..offset + dst.len()];
785 let uninit_src: &[MaybeUninit<u8>] = unsafe { core::mem::transmute(src) };
787 dst.copy_from_slice(&uninit_src);
788 }
789
790 fn new_empty() -> Self {
791 &[]
792 }
793}
794
795impl PayloadLen for () {
796 fn len(&self) -> usize {
797 0
798 }
799}
800
801impl Payload for () {
802 fn slice(self, Range { start, end }: Range<u32>) -> Self {
803 if start != 0 {
804 panic!("range start index {} out of range for slice of length 0", start);
805 }
806 if end != 0 {
807 panic!("range end index {} out of range for slice of length 0", end);
808 }
809 ()
810 }
811
812 fn partial_copy(&self, offset: usize, dst: &mut [u8]) {
813 if dst.len() != 0 || offset != 0 {
814 panic!(
815 "source slice length (0) does not match destination slice length ({})",
816 dst.len()
817 );
818 }
819 }
820
821 fn partial_copy_uninit(&self, offset: usize, dst: &mut [MaybeUninit<u8>]) {
822 if dst.len() != 0 || offset != 0 {
823 panic!(
824 "source slice length (0) does not match destination slice length ({})",
825 dst.len()
826 );
827 }
828 }
829
830 fn new_empty() -> Self {
831 ()
832 }
833}
834
835impl<I: PayloadLen, B> PayloadLen for InnerSerializer<I, B> {
836 fn len(&self) -> usize {
837 PayloadLen::len(self.inner())
838 }
839}
840
841#[derive(Error, Debug, PartialEq, Eq)]
842#[error("multiple mutually exclusive flags are set: syn: {syn}, fin: {fin}, rst: {rst}")]
843pub struct MalformedFlags {
844 syn: bool,
845 fin: bool,
846 rst: bool,
847}
848
849struct Flags {
850 syn: bool,
851 fin: bool,
852 rst: bool,
853}
854
855impl Flags {
856 fn control(&self) -> Result<Option<Control>, MalformedFlags> {
857 if usize::from(self.syn) + usize::from(self.fin) + usize::from(self.rst) > 1 {
858 return Err(MalformedFlags { syn: self.syn, fin: self.fin, rst: self.rst });
859 }
860
861 let syn = self.syn.then_some(Control::SYN);
862 let fin = self.fin.then_some(Control::FIN);
863 let rst = self.rst.then_some(Control::RST);
864
865 Ok(syn.or(fin).or(rst))
866 }
867}
868
869impl<'a> TryFrom<TcpSegment<&'a [u8]>> for Segment<&'a [u8]> {
870 type Error = MalformedFlags;
871
872 fn try_from(from: TcpSegment<&'a [u8]>) -> Result<Self, Self::Error> {
873 let syn = from.syn();
874 let options = Options::from_iter(syn, from.iter_options());
875 let (to, discarded) = Segment::new(
876 SegmentHeader {
877 seq: from.seq_num().into(),
878 ack: from.ack_num().map(Into::into),
879 wnd: UnscaledWindowSize::from(from.window_size()),
880 control: Flags { syn, fin: from.fin(), rst: from.rst() }.control()?,
881 push: from.psh(),
882 options,
883 },
884 from.into_body(),
885 );
886 debug_assert_eq!(discarded, 0);
887 Ok(to)
888 }
889}
890
891impl<A> TryFrom<&TcpSegmentBuilder<A>> for SegmentHeader
892where
893 A: IpAddress,
894{
895 type Error = MalformedFlags;
896
897 fn try_from(from: &TcpSegmentBuilder<A>) -> Result<Self, Self::Error> {
898 SegmentHeader::from_builder(from)
899 }
900}
901
902impl<'a, A, I> TryFrom<&TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<TcpOption<'a>, I>>>
903 for SegmentHeader
904where
905 A: IpAddress,
906 I: Iterator + Clone,
907 I::Item: Borrow<TcpOption<'a>>,
908{
909 type Error = MalformedFlags;
910
911 fn try_from(
912 from: &TcpSegmentBuilderWithOptions<A, OptionSequenceBuilder<TcpOption<'a>, I>>,
913 ) -> Result<Self, Self::Error> {
914 let prefix_builder = from.prefix_builder();
915 let handshake = prefix_builder.syn_set();
916 Self::from_builder_options(
917 prefix_builder,
918 Options::from_iter(
919 handshake,
920 from.iter_options().map(|option| option.borrow().to_owned()),
921 ),
922 )
923 }
924}
925
926#[cfg(any(test, feature = "testutils"))]
927mod testutils {
928 use super::*;
929
930 impl Default for SegmentHeader {
932 fn default() -> Self {
933 Self {
934 seq: SeqNum::new(0),
935 ack: None,
936 control: None,
937 wnd: UnscaledWindowSize::from(0),
938 options: Options::default(),
939 push: false,
940 }
941 }
942 }
943
944 impl<P: Payload> Segment<P> {
945 #[track_caller]
948 pub fn new_assert_no_discard(header: SegmentHeader, data: P) -> Self {
949 let (seg, discard) = Self::new(header, data);
950 assert_eq!(discard, 0);
951 seg
952 }
953 }
954
955 impl<'a> Segment<&'a [u8]> {
956 pub fn with_fake_data(seq: SeqNum, ack: SeqNum, data: &'a [u8]) -> Self {
958 Self::new_assert_no_discard(
959 SegmentHeader {
960 seq,
961 ack: Some(ack),
962 control: None,
963 wnd: UnscaledWindowSize::from(u16::MAX),
964 options: Options::default(),
965 push: false,
966 },
967 data,
968 )
969 }
970 }
971
972 impl<P: Payload> Segment<P> {
973 pub fn with_data(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize, data: P) -> Segment<P> {
975 Segment::new_assert_no_discard(
976 SegmentHeader {
977 seq,
978 ack: Some(ack),
979 control: None,
980 wnd,
981 push: false,
982 options: Options::default(),
983 },
984 data,
985 )
986 }
987
988 pub fn piggybacked_fin(
990 seq: SeqNum,
991 ack: SeqNum,
992 wnd: UnscaledWindowSize,
993 data: P,
994 ) -> Segment<P> {
995 Segment::new_assert_no_discard(
996 SegmentHeader {
997 seq,
998 ack: Some(ack),
999 control: Some(Control::FIN),
1000 wnd,
1001 push: false,
1002 options: Options::default(),
1003 },
1004 data,
1005 )
1006 }
1007
1008 pub fn fin(seq: SeqNum, ack: SeqNum, wnd: UnscaledWindowSize) -> Self {
1010 Segment::new_empty(SegmentHeader {
1011 seq,
1012 ack: Some(ack),
1013 control: Some(Control::FIN),
1014 wnd,
1015 push: false,
1016 options: Options::default(),
1017 })
1018 }
1019 }
1020}
1021
1022#[cfg(test)]
1023mod test {
1024 use assert_matches::assert_matches;
1025 use ip_test_macro::ip_test;
1026 use net_declare::{net_ip_v4, net_ip_v6};
1027 use net_types::ip::{Ipv4, Ipv6};
1028 use packet_formats::ip::IpExt;
1029 use test_case::test_case;
1030
1031 use super::*;
1032
1033 #[test_case(None, &[][..] => (0, &[][..]); "empty")]
1034 #[test_case(None, &[1][..] => (1, &[1][..]); "no control")]
1035 #[test_case(Some(Control::SYN), &[][..] => (1, &[][..]); "empty slice with syn")]
1036 #[test_case(Some(Control::SYN), &[1][..] => (2, &[1][..]); "non-empty slice with syn")]
1037 #[test_case(Some(Control::FIN), &[][..] => (1, &[][..]); "empty slice with fin")]
1038 #[test_case(Some(Control::FIN), &[1][..] => (2, &[1][..]); "non-empty slice with fin")]
1039 #[test_case(Some(Control::RST), &[][..] => (0, &[][..]); "empty slice with rst")]
1040 #[test_case(Some(Control::RST), &[1][..] => (1, &[1][..]); "non-empty slice with rst")]
1041 fn segment_len(control: Option<Control>, data: &[u8]) -> (u32, &[u8]) {
1042 let (seg, truncated) = Segment::new(
1043 SegmentHeader {
1044 seq: SeqNum::new(1),
1045 ack: Some(SeqNum::new(1)),
1046 wnd: UnscaledWindowSize::from(0),
1047 control,
1048 push: false,
1049 options: Options::default(),
1050 },
1051 data,
1052 );
1053 assert_eq!(truncated, 0);
1054 (seg.len(), seg.data)
1055 }
1056
1057 #[test_case(&[1, 2, 3, 4, 5][..], 0..4 => [1, 2, 3, 4])]
1058 #[test_case((), 0..0 => [0, 0, 0, 0])]
1059 fn payload_slice_copy(data: impl Payload, range: Range<u32>) -> [u8; 4] {
1060 let sliced = data.slice(range);
1061 let mut buffer = [0; 4];
1062 sliced.partial_copy(0, &mut buffer[..sliced.len()]);
1063 buffer
1064 }
1065
1066 #[derive(Debug, PartialEq, Eq)]
1067 struct TestPayload(Range<u32>);
1068
1069 impl TestPayload {
1070 fn new(len: usize) -> Self {
1071 Self(0..u32::try_from(len).unwrap())
1072 }
1073 }
1074
1075 impl PayloadLen for TestPayload {
1076 fn len(&self) -> usize {
1077 self.0.len()
1078 }
1079 }
1080
1081 impl Payload for TestPayload {
1082 fn slice(self, range: Range<u32>) -> Self {
1083 let Self(this) = self;
1084 assert!(range.start >= this.start && range.end <= this.end);
1085 TestPayload(range)
1086 }
1087
1088 fn partial_copy(&self, _offset: usize, _dst: &mut [u8]) {
1089 unimplemented!("TestPayload doesn't carry any data");
1090 }
1091
1092 fn partial_copy_uninit(&self, _offset: usize, _dst: &mut [MaybeUninit<u8>]) {
1093 unimplemented!("TestPayload doesn't carry any data");
1094 }
1095
1096 fn new_empty() -> Self {
1097 Self(0..0)
1098 }
1099 }
1100
1101 #[test_case(100, Some(Control::SYN) => (100, Some(Control::SYN), 0))]
1102 #[test_case(100, Some(Control::FIN) => (100, Some(Control::FIN), 0))]
1103 #[test_case(100, Some(Control::RST) => (100, Some(Control::RST), 0))]
1104 #[test_case(100, None => (100, None, 0))]
1105 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN)
1106 => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 0))]
1107 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::FIN)
1108 => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::FIN), 0))]
1109 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::RST)
1110 => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::RST), 0))]
1111 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN - 1, None
1112 => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, None, 0))]
1113 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::SYN)
1114 => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 1))]
1115 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::FIN)
1116 => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 1))]
1117 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST)
1118 => (MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST), 0))]
1119 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN, None
1120 => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 0))]
1121 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::SYN)
1122 => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 2))]
1123 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::FIN)
1124 => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 2))]
1125 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, Some(Control::RST)
1126 => (MAX_PAYLOAD_AND_CONTROL_LEN, Some(Control::RST), 1))]
1127 #[test_case(MAX_PAYLOAD_AND_CONTROL_LEN + 1, None
1128 => (MAX_PAYLOAD_AND_CONTROL_LEN, None, 1))]
1129 #[test_case(u32::MAX as usize, Some(Control::SYN)
1130 => (MAX_PAYLOAD_AND_CONTROL_LEN - 1, Some(Control::SYN), 1 << 31))]
1131 fn segment_truncate(len: usize, control: Option<Control>) -> (usize, Option<Control>, usize) {
1132 let (seg, truncated) = Segment::new(
1133 SegmentHeader {
1134 seq: SeqNum::new(0),
1135 ack: None,
1136 wnd: UnscaledWindowSize::from(0),
1137 control,
1138 push: false,
1139 options: Options::default(),
1140 },
1141 TestPayload::new(len),
1142 );
1143 (seg.data.len(), seg.header.control, truncated)
1144 }
1145
1146 struct OverlapTestArgs {
1147 seg_seq: u32,
1148 control: Option<Control>,
1149 data_len: u32,
1150 rcv_nxt: u32,
1151 rcv_wnd: usize,
1152 }
1153 #[test_case(OverlapTestArgs{
1154 seg_seq: 1,
1155 control: None,
1156 data_len: 0,
1157 rcv_nxt: 0,
1158 rcv_wnd: 0,
1159 } => None)]
1160 #[test_case(OverlapTestArgs{
1161 seg_seq: 1,
1162 control: None,
1163 data_len: 0,
1164 rcv_nxt: 1,
1165 rcv_wnd: 0,
1166 } => Some((SeqNum::new(1), None, 0..0)))]
1167 #[test_case(OverlapTestArgs{
1168 seg_seq: 1,
1169 control: None,
1170 data_len: 0,
1171 rcv_nxt: 2,
1172 rcv_wnd: 0,
1173 } => None)]
1174 #[test_case(OverlapTestArgs{
1175 seg_seq: 1,
1176 control: Some(Control::SYN),
1177 data_len: 0,
1178 rcv_nxt: 2,
1179 rcv_wnd: 0,
1180 } => None)]
1181 #[test_case(OverlapTestArgs{
1182 seg_seq: 1,
1183 control: Some(Control::SYN),
1184 data_len: 0,
1185 rcv_nxt: 1,
1186 rcv_wnd: 0,
1187 } => None)]
1188 #[test_case(OverlapTestArgs{
1189 seg_seq: 1,
1190 control: Some(Control::SYN),
1191 data_len: 0,
1192 rcv_nxt: 0,
1193 rcv_wnd: 0,
1194 } => None)]
1195 #[test_case(OverlapTestArgs{
1196 seg_seq: 1,
1197 control: Some(Control::FIN),
1198 data_len: 0,
1199 rcv_nxt: 2,
1200 rcv_wnd: 0,
1201 } => None)]
1202 #[test_case(OverlapTestArgs{
1203 seg_seq: 1,
1204 control: Some(Control::FIN),
1205 data_len: 0,
1206 rcv_nxt: 1,
1207 rcv_wnd: 0,
1208 } => None)]
1209 #[test_case(OverlapTestArgs{
1210 seg_seq: 1,
1211 control: Some(Control::FIN),
1212 data_len: 0,
1213 rcv_nxt: 0,
1214 rcv_wnd: 0,
1215 } => None)]
1216 #[test_case(OverlapTestArgs{
1217 seg_seq: 0,
1218 control: None,
1219 data_len: 0,
1220 rcv_nxt: 1,
1221 rcv_wnd: 1,
1222 } => None)]
1223 #[test_case(OverlapTestArgs{
1224 seg_seq: 1,
1225 control: None,
1226 data_len: 0,
1227 rcv_nxt: 1,
1228 rcv_wnd: 1,
1229 } => Some((SeqNum::new(1), None, 0..0)))]
1230 #[test_case(OverlapTestArgs{
1231 seg_seq: 2,
1232 control: None,
1233 data_len: 0,
1234 rcv_nxt: 1,
1235 rcv_wnd: 1,
1236 } => None)]
1237 #[test_case(OverlapTestArgs{
1238 seg_seq: 0,
1239 control: None,
1240 data_len: 1,
1241 rcv_nxt: 1,
1242 rcv_wnd: 1,
1243 } => Some((SeqNum::new(1), None, 1..1)))]
1244 #[test_case(OverlapTestArgs{
1245 seg_seq: 0,
1246 control: Some(Control::SYN),
1247 data_len: 0,
1248 rcv_nxt: 1,
1249 rcv_wnd: 1,
1250 } => Some((SeqNum::new(1), None, 0..0)))]
1251 #[test_case(OverlapTestArgs{
1252 seg_seq: 2,
1253 control: None,
1254 data_len: 1,
1255 rcv_nxt: 1,
1256 rcv_wnd: 1,
1257 } => None)]
1258 #[test_case(OverlapTestArgs{
1259 seg_seq: 0,
1260 control: None,
1261 data_len: 2,
1262 rcv_nxt: 1,
1263 rcv_wnd: 1,
1264 } => Some((SeqNum::new(1), None, 1..2)))]
1265 #[test_case(OverlapTestArgs{
1266 seg_seq: 1,
1267 control: None,
1268 data_len: 2,
1269 rcv_nxt: 1,
1270 rcv_wnd: 1,
1271 } => Some((SeqNum::new(1), None, 0..1)))]
1272 #[test_case(OverlapTestArgs{
1273 seg_seq: 0,
1274 control: Some(Control::SYN),
1275 data_len: 1,
1276 rcv_nxt: 1,
1277 rcv_wnd: 1,
1278 } => Some((SeqNum::new(1), None, 0..1)))]
1279 #[test_case(OverlapTestArgs{
1280 seg_seq: 1,
1281 control: Some(Control::SYN),
1282 data_len: 1,
1283 rcv_nxt: 1,
1284 rcv_wnd: 1,
1285 } => Some((SeqNum::new(1), Some(Control::SYN), 0..0)))]
1286 #[test_case(OverlapTestArgs{
1287 seg_seq: 0,
1288 control: Some(Control::FIN),
1289 data_len: 1,
1290 rcv_nxt: 1,
1291 rcv_wnd: 1,
1292 } => Some((SeqNum::new(1), Some(Control::FIN), 1..1)))]
1293 #[test_case(OverlapTestArgs{
1294 seg_seq: 1,
1295 control: Some(Control::FIN),
1296 data_len: 1,
1297 rcv_nxt: 1,
1298 rcv_wnd: 1,
1299 } => Some((SeqNum::new(1), None, 0..1)))]
1300 #[test_case(OverlapTestArgs{
1301 seg_seq: 1,
1302 control: None,
1303 data_len: MAX_PAYLOAD_AND_CONTROL_LEN_U32,
1304 rcv_nxt: 1,
1305 rcv_wnd: 10,
1306 } => Some((SeqNum::new(1), None, 0..10)))]
1307 #[test_case(OverlapTestArgs{
1308 seg_seq: 10,
1309 control: None,
1310 data_len: MAX_PAYLOAD_AND_CONTROL_LEN_U32,
1311 rcv_nxt: 1,
1312 rcv_wnd: 10,
1313 } => Some((SeqNum::new(10), None, 0..1)))]
1314 #[test_case(OverlapTestArgs{
1315 seg_seq: 1,
1316 control: None,
1317 data_len: 10,
1318 rcv_nxt: 1,
1319 rcv_wnd: 1 << 30 - 1,
1320 } => Some((SeqNum::new(1), None, 0..10)))]
1321 #[test_case(OverlapTestArgs{
1322 seg_seq: 10,
1323 control: None,
1324 data_len: 10,
1325 rcv_nxt: 1,
1326 rcv_wnd: 1 << 30 - 1,
1327 } => Some((SeqNum::new(10), None, 0..10)))]
1328 #[test_case(OverlapTestArgs{
1329 seg_seq: 1,
1330 control: Some(Control::FIN),
1331 data_len: 1,
1332 rcv_nxt: 3,
1333 rcv_wnd: 10,
1334 } => Some((SeqNum::new(3), None, 1..1)); "regression test for https://fxbug.dev/42061750")]
1335 fn segment_overlap(
1336 OverlapTestArgs { seg_seq, control, data_len, rcv_nxt, rcv_wnd }: OverlapTestArgs,
1337 ) -> Option<(SeqNum, Option<Control>, Range<u32>)> {
1338 let (seg, discarded) = Segment::new(
1339 SegmentHeader {
1340 seq: SeqNum::new(seg_seq),
1341 ack: None,
1342 control,
1343 wnd: UnscaledWindowSize::from(0),
1344 push: false,
1345 options: Options::default(),
1346 },
1347 TestPayload(0..data_len),
1348 );
1349 assert_eq!(discarded, 0);
1350 seg.overlap(SeqNum::new(rcv_nxt), WindowSize::new(rcv_wnd).unwrap()).map(
1351 |Segment { header: SegmentHeader { seq, control, .. }, data: TestPayload(range) }| {
1352 (seq, control, range)
1353 },
1354 )
1355 }
1356
1357 pub trait TestIpExt: IpExt {
1358 const SRC_IP: Self::Addr;
1359 const DST_IP: Self::Addr;
1360 }
1361
1362 impl TestIpExt for Ipv4 {
1363 const SRC_IP: Self::Addr = net_ip_v4!("192.0.2.1");
1364 const DST_IP: Self::Addr = net_ip_v4!("192.0.2.2");
1365 }
1366
1367 impl TestIpExt for Ipv6 {
1368 const SRC_IP: Self::Addr = net_ip_v6!("2001:db8::1");
1369 const DST_IP: Self::Addr = net_ip_v6!("2001:db8::2");
1370 }
1371
1372 const SRC_PORT: NonZeroU16 = NonZeroU16::new(1234).unwrap();
1373 const DST_PORT: NonZeroU16 = NonZeroU16::new(9876).unwrap();
1374
1375 #[ip_test(I)]
1376 fn from_segment_builder<I: TestIpExt>() {
1377 let mut builder =
1378 TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1379 builder.syn(true);
1380
1381 let converted_header =
1382 SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1383
1384 let expected_header = SegmentHeader {
1385 seq: SeqNum::new(1),
1386 ack: Some(SeqNum::new(2)),
1387 wnd: UnscaledWindowSize::from(3u16),
1388 control: Some(Control::SYN),
1389 options: HandshakeOptions::default().into(),
1390 push: false,
1391 };
1392
1393 assert_eq!(converted_header, expected_header);
1394 }
1395
1396 #[ip_test(I)]
1397 fn from_segment_builder_failure<I: TestIpExt>() {
1398 let mut builder =
1399 TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1400 builder.syn(true);
1401 builder.fin(true);
1402
1403 assert_matches!(
1404 SegmentHeader::try_from(&builder),
1405 Err(MalformedFlags { syn: true, fin: true, rst: false })
1406 );
1407 }
1408
1409 #[ip_test(I)]
1410 fn from_segment_builder_with_options_handshake<I: TestIpExt>() {
1411 let mut builder =
1412 TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1413 builder.syn(true);
1414
1415 let builder = TcpSegmentBuilderWithOptions::new(
1416 builder,
1417 [TcpOption::Mss(1024), TcpOption::WindowScale(10), TcpOption::SackPermitted],
1418 )
1419 .expect("failed to create tcp segment builder");
1420
1421 let converted_header =
1422 SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1423
1424 let expected_header = SegmentHeader {
1425 seq: SeqNum::new(1),
1426 ack: Some(SeqNum::new(2)),
1427 wnd: UnscaledWindowSize::from(3u16),
1428 control: Some(Control::SYN),
1429 push: false,
1430 options: HandshakeOptions {
1431 mss: Some(Mss(NonZeroU16::new(1024).unwrap())),
1432 window_scale: Some(WindowScale::new(10).unwrap()),
1433 sack_permitted: true,
1434 }
1435 .into(),
1436 };
1437
1438 assert_eq!(converted_header, expected_header);
1439 }
1440
1441 #[ip_test(I)]
1442 fn from_segment_builder_with_options_segment<I: TestIpExt>() {
1443 let mut builder =
1444 TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1445 builder.psh(true);
1446
1447 let sack_blocks = [TcpSackBlock::new(1, 2), TcpSackBlock::new(4, 6)];
1448 let builder =
1449 TcpSegmentBuilderWithOptions::new(builder, [TcpOption::Sack(&sack_blocks[..])])
1450 .expect("failed to create tcp segment builder");
1451
1452 let converted_header =
1453 SegmentHeader::try_from(&builder).expect("failed to convert serializer");
1454
1455 let expected_header = SegmentHeader {
1456 seq: SeqNum::new(1),
1457 ack: Some(SeqNum::new(2)),
1458 wnd: UnscaledWindowSize::from(3u16),
1459 control: None,
1460 push: true,
1461 options: SegmentOptions {
1462 sack_blocks: SackBlocks::from_iter([
1463 SackBlock::try_new(SeqNum::new(1), SeqNum::new(2)).unwrap(),
1464 SackBlock::try_new(SeqNum::new(4), SeqNum::new(6)).unwrap(),
1465 ]),
1466 }
1467 .into(),
1468 };
1469
1470 assert_eq!(converted_header, expected_header);
1471 }
1472
1473 #[ip_test(I)]
1474 fn from_segment_builder_with_options_failure<I: TestIpExt>() {
1475 let mut builder =
1476 TcpSegmentBuilder::new(I::SRC_IP, I::DST_IP, SRC_PORT, DST_PORT, 1, Some(2), 3);
1477 builder.syn(true);
1478 builder.fin(true);
1479
1480 let builder = TcpSegmentBuilderWithOptions::new(
1481 builder,
1482 [TcpOption::Mss(1024), TcpOption::WindowScale(10)],
1483 )
1484 .expect("failed to create tcp segment builder");
1485
1486 assert_matches!(
1487 SegmentHeader::try_from(&builder),
1488 Err(MalformedFlags { syn: true, fin: true, rst: false })
1489 );
1490 }
1491
1492 #[test_case(Flags {
1493 syn: false,
1494 fin: false,
1495 rst: false,
1496 } => Ok(None))]
1497 #[test_case(Flags {
1498 syn: true,
1499 fin: false,
1500 rst: false,
1501 } => Ok(Some(Control::SYN)))]
1502 #[test_case(Flags {
1503 syn: false,
1504 fin: true,
1505 rst: false,
1506 } => Ok(Some(Control::FIN)))]
1507 #[test_case(Flags {
1508 syn: false,
1509 fin: false,
1510 rst: true,
1511 } => Ok(Some(Control::RST)))]
1512 #[test_case(Flags {
1513 syn: true,
1514 fin: true,
1515 rst: false,
1516 } => Err(MalformedFlags {
1517 syn: true,
1518 fin: true,
1519 rst: false,
1520 }))]
1521 #[test_case(Flags {
1522 syn: true,
1523 fin: false,
1524 rst: true,
1525 } => Err(MalformedFlags {
1526 syn: true,
1527 fin: false,
1528 rst: true,
1529 }))]
1530 #[test_case(Flags {
1531 syn: false,
1532 fin: true,
1533 rst: true,
1534 } => Err(MalformedFlags {
1535 syn: false,
1536 fin: true,
1537 rst: true,
1538 }))]
1539 #[test_case(Flags {
1540 syn: true,
1541 fin: true,
1542 rst: true,
1543 } => Err(MalformedFlags {
1544 syn: true,
1545 fin: true,
1546 rst: true,
1547 }))]
1548 fn flags_to_control(input: Flags) -> Result<Option<Control>, MalformedFlags> {
1549 input.control()
1550 }
1551
1552 #[test]
1553 fn sack_block_try_new() {
1554 assert_matches!(SackBlock::try_new(SeqNum::new(1), SeqNum::new(2)), Ok(_));
1555 assert_matches!(
1556 SackBlock::try_new(SeqNum::new(0u32.wrapping_sub(1)), SeqNum::new(2)),
1557 Ok(_)
1558 );
1559 assert_eq!(
1560 SackBlock::try_new(SeqNum::new(1), SeqNum::new(1)),
1561 Err(InvalidSackBlockError(SeqNum::new(1), SeqNum::new(1)))
1562 );
1563 assert_eq!(
1564 SackBlock::try_new(SeqNum::new(2), SeqNum::new(1)),
1565 Err(InvalidSackBlockError(SeqNum::new(2), SeqNum::new(1)))
1566 );
1567 assert_eq!(
1568 SackBlock::try_new(SeqNum::new(0), SeqNum::new(0u32.wrapping_sub(1))),
1569 Err(InvalidSackBlockError(SeqNum::new(0), SeqNum::new(0u32.wrapping_sub(1))))
1570 );
1571 }
1572
1573 #[test]
1574 fn psh_bit_cleared_if_no_data() {
1575 let seg =
1576 Segment::new_assert_no_discard(SegmentHeader { push: true, ..Default::default() }, ());
1577 assert_eq!(seg.header().push, false);
1578 let seg = Segment::new_assert_no_discard(
1579 SegmentHeader { push: true, ..Default::default() },
1580 &[1u8, 2, 3, 4][..],
1581 );
1582 assert_eq!(seg.header().push, true);
1583 }
1584}