1use core::time::Duration;
8
9use netstack3_base::{Control, SegmentHeader, SeqNum, UnscaledWindowSize, WindowScale, WindowSize};
10use replace_with::replace_with_and;
11
12use super::{
13 ConnectionDirection, ConnectionUpdateAction, ConnectionUpdateError, EstablishmentLifecycle,
14};
15
16#[derive(Debug, Clone)]
19pub(crate) struct Connection {
20 state: State,
22}
23
24impl Connection {
25 pub fn new(segment: &SegmentHeader, payload_len: usize, self_connected: bool) -> Option<Self> {
26 Some(Self {
27 state: if self_connected {
30 Untracked {}.into()
31 } else {
32 State::new(segment, payload_len)?
33 },
34 })
35 }
36
37 pub fn expiry_duration(&self, establishment_lifecycle: EstablishmentLifecycle) -> Duration {
38 self.state.expiry_duration(establishment_lifecycle)
39 }
40
41 pub fn update(
42 &mut self,
43 segment: &SegmentHeader,
44 payload_len: usize,
45 dir: ConnectionDirection,
46 ) -> Result<ConnectionUpdateAction, ConnectionUpdateError> {
47 let valid =
48 replace_with_and(&mut self.state, |state| state.update(segment, payload_len, dir));
49
50 if !valid {
51 return Err(ConnectionUpdateError::InvalidPacket);
52 }
53
54 match self.state {
55 State::Closed(_) => Ok(ConnectionUpdateAction::RemoveEntry),
56 State::Untracked(_)
57 | State::SynSent(_)
58 | State::WaitingOnOpeningAck(_)
59 | State::Closing(_)
60 | State::Established(_) => Ok(ConnectionUpdateAction::NoAction),
61 }
62 }
63}
64
65#[derive(Debug, Clone, PartialEq, Eq)]
72pub(crate) enum State {
73 Untracked(Untracked),
78
79 Closed(Closed),
84
85 SynSent(SynSent),
93
94 WaitingOnOpeningAck(WaitingOnOpeningAck),
101
102 Established(Established),
109
110 Closing(Closing),
120}
121
122impl State {
123 fn new(segment: &SegmentHeader, payload_len: usize) -> Option<Self> {
124 match segment.control {
130 Some(Control::SYN) => {}
131 None | Some(Control::FIN) | Some(Control::RST) => return None,
132 }
133
134 Some(
135 SynSent {
136 iss: segment.seq,
137 logical_len: segment.len(payload_len),
138 advertised_window_scale: segment.options.window_scale(),
139 window_size: WindowSize::from_u32(u16::from(segment.wnd).into()).unwrap(),
143 }
144 .into(),
145 )
146 }
147
148 fn expiry_duration(&self, establishment_lifecycle: EstablishmentLifecycle) -> Duration {
149 const MAXIMUM_SEGMENT_LIFETIME: Duration = Duration::from_secs(120);
150
151 match self {
156 State::Untracked(_) => {
157 match establishment_lifecycle {
158 EstablishmentLifecycle::SeenOriginal | EstablishmentLifecycle::SeenReply => {
161 MAXIMUM_SEGMENT_LIFETIME
162 }
163 EstablishmentLifecycle::Established => Duration::from_secs(6 * 60 * 60),
164 }
165 }
166 State::Closed(_) => Duration::ZERO,
167 State::SynSent(_) => MAXIMUM_SEGMENT_LIFETIME,
168 State::WaitingOnOpeningAck(_) => MAXIMUM_SEGMENT_LIFETIME,
169 State::Established(Established { original, reply }) => {
170 if original.unacked_data || reply.unacked_data {
174 MAXIMUM_SEGMENT_LIFETIME
175 } else {
176 Duration::from_secs(5 * 60 * 60 * 24)
177 }
178 }
179 State::Closing(_) => MAXIMUM_SEGMENT_LIFETIME,
180 }
181 }
182
183 fn update(
189 self,
190 segment: &SegmentHeader,
191 payload_len: usize,
192 dir: ConnectionDirection,
193 ) -> (State, bool) {
194 match self {
195 State::Untracked(s) => s.update(segment, payload_len, dir),
196 State::Closed(s) => s.update(segment, payload_len, dir),
197 State::SynSent(s) => s.update(segment, payload_len, dir),
198 State::WaitingOnOpeningAck(s) => s.update(segment, payload_len, dir),
199 State::Established(s) => s.update(segment, payload_len, dir),
200 State::Closing(s) => s.update(segment, payload_len, dir),
201 }
202 }
203}
204
205macro_rules! state_from_state_struct {
206 ($struct:ident) => {
207 impl From<$struct> for State {
208 fn from(value: $struct) -> Self {
209 Self::$struct(value)
210 }
211 }
212 };
213}
214
215#[derive(Debug, Clone, PartialEq, Eq)]
239struct Peer {
240 window_scale: WindowScale,
242
243 max_wnd: WindowSize,
248
249 max_wnd_seq: SeqNum,
255
256 max_next_seq: SeqNum,
262
263 unacked_data: bool,
270
271 fin_state: FinState,
273}
274
275impl Peer {
276 fn ack_segment_valid(
278 sender: &Self,
279 receiver: &Self,
280 seq: SeqNum,
281 len: u32,
282 ack: SeqNum,
283 ) -> bool {
284 if seq.after(receiver.max_wnd_seq) {
289 return false;
290 }
291
292 if (seq + len).before(sender.max_next_seq - receiver.max_wnd) {
294 return false;
295 }
296
297 if ack.after(receiver.max_next_seq) {
299 return false;
300 }
301
302 if ack.before(receiver.max_next_seq - receiver.max_ack_window()) {
304 return false;
305 }
306
307 true
308 }
309
310 fn update_sender(
313 self,
314 seq: SeqNum,
315 len: u32,
316 ack: SeqNum,
317 wnd: UnscaledWindowSize,
318 fin_seen: bool,
319 ) -> Self {
320 let Self { window_scale, max_wnd, max_wnd_seq, max_next_seq, unacked_data, fin_state } =
321 self;
322
323 let window_size = {
327 let window_size = wnd << window_scale;
328 core::cmp::max(window_size, WindowSize::from_u32(1).unwrap())
331 };
332
333 let wnd_seq = ack + window_size;
335 let end = seq + len;
337 let sender_max_next_seq = if max_next_seq.before(end) { end } else { max_next_seq };
339
340 Peer {
341 window_scale,
342 max_wnd: core::cmp::max(max_wnd, window_size),
343 max_wnd_seq: if max_wnd_seq.before(wnd_seq) { wnd_seq } else { max_wnd_seq },
344 max_next_seq: sender_max_next_seq,
345 unacked_data: if sender_max_next_seq.after(max_next_seq) { true } else { unacked_data },
346 fin_state: if fin_seen { fin_state.update_fin_sent(end - 1) } else { fin_state },
347 }
348 }
349
350 fn update_receiver(self, ack: SeqNum) -> Self {
353 let Self { window_scale, max_wnd, max_wnd_seq, max_next_seq, unacked_data, fin_state } =
354 self;
355
356 Peer {
357 window_scale,
358 max_wnd,
359 max_wnd_seq,
360 max_next_seq,
361 unacked_data: if ack == max_next_seq { false } else { unacked_data },
364 fin_state: fin_state.update_ack_received(ack),
365 }
366 }
367
368 fn max_ack_window(&self) -> u32 {
369 66000u32 << (self.window_scale.get() as u32)
377 }
378}
379
380#[derive(Debug, Clone, PartialEq, Eq)]
382enum FinState {
383 NotSent,
385
386 Sent(SeqNum),
390
391 Acked,
393}
394
395impl FinState {
396 fn update_fin_sent(self, seq: SeqNum) -> Self {
401 match self {
402 FinState::NotSent => FinState::Sent(seq),
403 FinState::Sent(s) => {
404 if s.before(seq) { FinState::Sent(s) } else { FinState::Sent(seq) }
407 }
408 FinState::Acked => FinState::Acked,
409 }
410 }
411
412 fn update_ack_received(self, ack: SeqNum) -> Self {
416 match self {
417 FinState::NotSent => FinState::NotSent,
418 FinState::Sent(seq) => {
419 if ack.after(seq) {
420 FinState::Acked
421 } else {
422 FinState::Sent(seq)
423 }
424 }
425 FinState::Acked => FinState::Acked,
426 }
427 }
428
429 fn acked(&self) -> bool {
431 match self {
432 FinState::NotSent => false,
433 FinState::Sent(_) => false,
434 FinState::Acked => true,
435 }
436 }
437}
438
439#[derive(Debug, PartialEq, Eq)]
441enum EstablishedUpdateResult {
442 Success { new_original: Peer, new_reply: Peer, fin_seen: bool },
447
448 Reset,
450
451 Invalid { original: Peer, reply: Peer },
455}
456
457fn swap_peers(original: Peer, reply: Peer, dir: ConnectionDirection) -> (Peer, Peer) {
458 match dir {
459 ConnectionDirection::Original => (original, reply),
460 ConnectionDirection::Reply => (reply, original),
461 }
462}
463
464struct UpdatePeers {
467 original: Peer,
468 reply: Peer,
469}
470
471fn do_established_update(
476 UpdatePeers { original, reply }: UpdatePeers,
477 segment: &SegmentHeader,
478 payload_len: usize,
479 dir: ConnectionDirection,
480) -> EstablishedUpdateResult {
481 let logical_len = segment.len(payload_len);
482 let SegmentHeader { seq, ack, wnd, control, options: _, push: _ } = segment;
483
484 let (sender, receiver) = swap_peers(original, reply, dir);
485
486 let ack = match ack {
491 Some(ack) => ack,
492 None => {
493 let (original, reply) = swap_peers(sender, receiver, dir);
494 return EstablishedUpdateResult::Invalid { original, reply };
495 }
496 };
497
498 if !Peer::ack_segment_valid(&sender, &receiver, *seq, logical_len, *ack) {
499 let (original, reply) = swap_peers(sender, receiver, dir);
500 return EstablishedUpdateResult::Invalid { original, reply };
501 }
502
503 let fin_seen = match control {
504 Some(Control::SYN) => {
505 let (original, reply) = swap_peers(sender, receiver, dir);
506 return EstablishedUpdateResult::Invalid { original, reply };
507 }
508 Some(Control::RST) => return EstablishedUpdateResult::Reset,
509 Some(Control::FIN) => true,
510 None => false,
511 };
512
513 let new_sender = sender.update_sender(*seq, logical_len, *ack, *wnd, fin_seen);
514 let new_receiver = receiver.update_receiver(*ack);
515
516 let (new_original, new_reply) = swap_peers(new_sender, new_receiver, dir);
517 EstablishedUpdateResult::Success { new_original, new_reply, fin_seen }
518}
519
520#[derive(Debug, Clone, PartialEq, Eq)]
524pub(crate) struct Untracked {}
525state_from_state_struct!(Untracked);
526
527impl Untracked {
528 fn update(
529 self,
530 _segment: &SegmentHeader,
531 _payload_len: usize,
532 _dir: ConnectionDirection,
533 ) -> (State, bool) {
534 (Self {}.into(), true)
535 }
536}
537
538#[derive(Debug, Clone, PartialEq, Eq)]
542pub(crate) struct Closed {}
543state_from_state_struct!(Closed);
544
545impl Closed {
546 fn update(
547 self,
548 _segment: &SegmentHeader,
549 _payload_len: usize,
550 _dir: ConnectionDirection,
551 ) -> (State, bool) {
552 (self.into(), true)
553 }
554}
555
556#[derive(Debug, Clone, PartialEq, Eq)]
572pub(crate) struct SynSent {
573 iss: SeqNum,
575
576 logical_len: u32,
578
579 advertised_window_scale: Option<WindowScale>,
581
582 window_size: WindowSize,
589}
590state_from_state_struct!(SynSent);
591
592impl SynSent {
593 fn update(
594 self,
595 segment: &SegmentHeader,
596 payload_len: usize,
597 dir: ConnectionDirection,
598 ) -> (State, bool) {
599 let Self { iss, logical_len, advertised_window_scale, window_size } = self;
600
601 match dir {
602 ConnectionDirection::Original => {
607 if let Some(_) = segment.ack {
608 return (self.into(), false);
609 }
610
611 match segment.control {
612 None | Some(Control::FIN) | Some(Control::RST) => {
613 return (self.into(), false);
614 }
615 Some(Control::SYN) => {}
616 };
617
618 if segment.seq != iss || segment.options.window_scale() != advertised_window_scale {
619 return (self.into(), false);
620 }
621
622 let seg_window_size = WindowSize::from_u32(u16::from(segment.wnd).into()).unwrap();
625
626 (
627 SynSent {
628 iss: iss,
629 logical_len: u32::max(segment.len(payload_len), logical_len),
630 advertised_window_scale: advertised_window_scale,
631 window_size: core::cmp::max(seg_window_size, window_size),
632 }
633 .into(),
634 true,
635 )
636 }
637
638 ConnectionDirection::Reply => {
639 match segment.ack {
643 None => {}
644 Some(ack) => {
645 if !(ack.after(iss) && ack.before(iss + logical_len + 1)) {
646 return (self.into(), false);
647 }
648 }
649 };
650
651 match segment.control {
652 None | Some(Control::FIN) => (self.into(), false),
653 Some(Control::RST) => match segment.ack {
663 None => (self.into(), false),
664 Some(_) => (Closed {}.into(), true),
665 },
666
667 Some(Control::SYN) => {
668 let Some(ack) = segment.ack else {
669 log::warn!(
672 "Unsupported TCP simultaneous open. Giving up on detailed tracking"
673 );
674
675 return (Untracked {}.into(), true);
676 };
677
678 let reply_window_scale = segment.options.window_scale();
679 let reply_window_size =
680 WindowSize::from_u32(u16::from(segment.wnd).into()).unwrap();
681
682 let (original_window_scale, reply_window_scale) =
688 match (advertised_window_scale, reply_window_scale) {
689 (Some(original), Some(reply)) => (original, reply),
690 _ => (WindowScale::ZERO, WindowScale::ZERO),
691 };
692
693 let original_max_next_seq = iss + logical_len;
694
695 (
696 WaitingOnOpeningAck {
697 original: Peer {
698 window_scale: original_window_scale,
699 max_wnd: window_size,
700 max_wnd_seq: segment.seq + window_size,
708 max_next_seq: original_max_next_seq,
709 unacked_data: ack.before(original_max_next_seq),
710 fin_state: FinState::NotSent,
711 },
712 reply: Peer {
713 window_scale: reply_window_scale,
714 max_wnd: reply_window_size,
715 max_wnd_seq: ack + reply_window_size,
716 max_next_seq: segment.seq + segment.len(payload_len),
717 unacked_data: true,
721 fin_state: FinState::NotSent,
722 },
723 }
724 .into(),
725 true,
726 )
727 }
728 }
729 }
730 }
731 }
732}
733
734#[derive(Debug, Clone, PartialEq, Eq)]
750pub(crate) struct WaitingOnOpeningAck {
751 original: Peer,
754
755 reply: Peer,
757}
758state_from_state_struct!(WaitingOnOpeningAck);
759
760impl WaitingOnOpeningAck {
761 fn update(
762 self,
763 segment: &SegmentHeader,
764 payload_len: usize,
765 dir: ConnectionDirection,
766 ) -> (State, bool) {
767 let Self { original, reply } = self;
768
769 let (original, reply, fin_seen) = match do_established_update(
770 UpdatePeers { original, reply },
771 segment,
772 payload_len,
773 dir.clone(),
774 ) {
775 EstablishedUpdateResult::Success { new_original, new_reply, fin_seen } => {
776 (new_original, new_reply, fin_seen)
777 }
778 EstablishedUpdateResult::Invalid { original, reply } => {
779 return (Self { original, reply }.into(), false);
780 }
781 EstablishedUpdateResult::Reset => return (Closed {}.into(), true),
782 };
783
784 let new_state = if fin_seen {
785 Closing { original, reply }.into()
786 } else {
787 match dir {
788 ConnectionDirection::Original => Established { original, reply }.into(),
792 ConnectionDirection::Reply => WaitingOnOpeningAck { original, reply }.into(),
793 }
794 };
795
796 (new_state, true)
797 }
798}
799
800#[derive(Debug, Clone, PartialEq, Eq)]
808pub(crate) struct Established {
809 original: Peer,
810 reply: Peer,
811}
812state_from_state_struct!(Established);
813
814impl Established {
815 fn update(
816 self,
817 segment: &SegmentHeader,
818 payload_len: usize,
819 dir: ConnectionDirection,
820 ) -> (State, bool) {
821 let Self { original, reply } = self;
822
823 let (original, reply, fin_seen) = match do_established_update(
824 UpdatePeers { original, reply },
825 segment,
826 payload_len,
827 dir.clone(),
828 ) {
829 EstablishedUpdateResult::Success { new_original, new_reply, fin_seen } => {
830 (new_original, new_reply, fin_seen)
831 }
832 EstablishedUpdateResult::Invalid { original, reply } => {
833 return (Self { original, reply }.into(), false);
834 }
835 EstablishedUpdateResult::Reset => return (Closed {}.into(), true),
836 };
837
838 let new_state = if fin_seen {
839 Closing { original, reply }.into()
840 } else {
841 Established { original, reply }.into()
842 };
843
844 (new_state, true)
845 }
846}
847
848#[derive(Debug, Clone, PartialEq, Eq)]
859pub(crate) struct Closing {
860 original: Peer,
861 reply: Peer,
862}
863state_from_state_struct!(Closing);
864
865impl Closing {
866 fn update(
867 self,
868 segment: &SegmentHeader,
869 payload_len: usize,
870 dir: ConnectionDirection,
871 ) -> (State, bool) {
872 let Self { original, reply } = self;
873
874 let (original, reply) = match do_established_update(
890 UpdatePeers { original, reply },
891 segment,
892 payload_len,
893 dir.clone(),
894 ) {
895 EstablishedUpdateResult::Success { new_original, new_reply, fin_seen: _ } => {
896 (new_original, new_reply)
897 }
898 EstablishedUpdateResult::Invalid { original, reply } => {
899 return (Self { original, reply }.into(), false);
900 }
901 EstablishedUpdateResult::Reset => return (Closed {}.into(), true),
902 };
903
904 if original.fin_state.acked() && reply.fin_state.acked() {
905 (Closed {}.into(), true)
916 } else {
917 (Closing { original, reply }.into(), true)
918 }
919 }
920}
921
922#[cfg(test)]
923mod tests {
924 use super::{
925 Closed, Closing, Established, EstablishedUpdateResult, FinState, Peer, State, SynSent,
926 Untracked, UpdatePeers, WaitingOnOpeningAck, do_established_update,
927 };
928
929 use assert_matches::assert_matches;
930 use netstack3_base::{
931 Control, HandshakeOptions, SegmentHeader, SeqNum, UnscaledWindowSize, WindowScale,
932 WindowSize,
933 };
934 use test_case::test_case;
935
936 use crate::conntrack::ConnectionDirection;
937
938 const ORIGINAL_ISS: SeqNum = SeqNum::new(0);
939 const REPLY_ISS: SeqNum = SeqNum::new(8192);
940 const ORIGINAL_WND: u16 = 16;
941 const REPLY_WND: u16 = 17;
942 const ORIGINAL_WS: u8 = 3;
943 const REPLY_WS: u8 = 4;
944 const ORIGINAL_PAYLOAD_LEN: usize = 12;
945 const REPLY_PAYLOAD_LEN: usize = 13;
946
947 impl Peer {
948 pub fn arbitrary() -> Peer {
949 Peer {
950 max_next_seq: SeqNum::new(0),
951 window_scale: WindowScale::new(0).unwrap(),
952 max_wnd_seq: SeqNum::new(0),
953 unacked_data: false,
954 max_wnd: WindowSize::new(0).unwrap(),
955 fin_state: FinState::NotSent,
956 }
957 }
958 }
959
960 #[test_case(None)]
961 #[test_case(Some(Control::FIN))]
962 #[test_case(Some(Control::RST))]
963 fn syn_sent_original_non_syn_segment(control: Option<Control>) {
964 let state = SynSent {
965 iss: ORIGINAL_ISS,
966 logical_len: 3,
967 advertised_window_scale: None,
968 window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
969 };
970
971 let segment = SegmentHeader {
972 seq: ORIGINAL_ISS,
973 wnd: UnscaledWindowSize::from(ORIGINAL_WND),
974 control,
975 ..Default::default()
976 };
977
978 let expected_state = state.clone().into();
979 assert_eq!(
980 state.update(&segment, ORIGINAL_PAYLOAD_LEN, ConnectionDirection::Original),
981 (expected_state, false)
982 );
983 }
984
985 #[test_case(SegmentHeader {
986 seq: ORIGINAL_ISS + 1,
988 wnd: UnscaledWindowSize::from(ORIGINAL_WND),
989 control: Some(Control::SYN),
990 options: HandshakeOptions {
991 window_scale: WindowScale::new(ORIGINAL_WS),
993 ..Default::default()
994 }.into(),
995 ..Default::default()
996 }; "different ISS")]
997 #[test_case(SegmentHeader {
998 seq: ORIGINAL_ISS,
1000 wnd: UnscaledWindowSize::from(ORIGINAL_WND),
1001 control: Some(Control::SYN),
1002 options: HandshakeOptions {
1003 window_scale: WindowScale::new(ORIGINAL_WS + 1),
1005 ..Default::default()
1006 }.into(),
1007 ..Default::default()
1008 }; "different window scale")]
1009 #[test_case(SegmentHeader {
1010 seq: ORIGINAL_ISS,
1011 ack: Some(SeqNum::new(10)),
1013 wnd: UnscaledWindowSize::from(ORIGINAL_WND),
1014 control: Some(Control::SYN),
1015 options: HandshakeOptions {
1016 window_scale: WindowScale::new(2),
1017 ..Default::default()
1018 }.into(),
1019 ..Default::default()
1020 }; "ack not allowed")]
1021 fn syn_sent_original_syn_not_retransmit(segment: SegmentHeader) {
1022 let state = SynSent {
1023 iss: ORIGINAL_ISS,
1024 logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1025 advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1026 window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1027 };
1028
1029 let expected_state = state.clone().into();
1030 assert_eq!(
1031 state.update(&segment, ORIGINAL_PAYLOAD_LEN, ConnectionDirection::Original),
1032 (expected_state, false)
1033 );
1034 }
1035
1036 #[test]
1037 fn syn_sent_original_syn_retransmit() {
1038 let state = SynSent {
1039 iss: ORIGINAL_ISS,
1040 logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1041 advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1042 window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1043 };
1044
1045 let segment = SegmentHeader {
1046 seq: ORIGINAL_ISS,
1047 wnd: UnscaledWindowSize::from(ORIGINAL_WND + 10),
1048 control: Some(Control::SYN),
1049 options: HandshakeOptions {
1050 window_scale: WindowScale::new(ORIGINAL_WS),
1051 ..Default::default()
1052 }
1053 .into(),
1054 ..Default::default()
1055 };
1056
1057 let result = assert_matches!(
1058 state.update(
1059 &segment,
1060 ORIGINAL_PAYLOAD_LEN + 10,
1061 ConnectionDirection::Original
1062 ),
1063 (State::SynSent(s), true) => s
1064 );
1065
1066 assert_eq!(
1067 result,
1068 SynSent {
1069 iss: ORIGINAL_ISS,
1070 logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 10 + 1,
1071 advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1072 window_size: WindowSize::from_u32(ORIGINAL_WND as u32 + 10).unwrap(),
1073 }
1074 )
1075 }
1076
1077 #[test_case(None)]
1078 #[test_case(Some(Control::FIN))]
1079 fn syn_sent_reply_non_syn_segment(control: Option<Control>) {
1080 let state = SynSent {
1081 iss: ORIGINAL_ISS,
1082 logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1083 advertised_window_scale: None,
1084 window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1085 };
1086
1087 let segment = SegmentHeader {
1088 seq: ORIGINAL_ISS,
1089 wnd: UnscaledWindowSize::from(ORIGINAL_WND),
1090 control,
1091 ..Default::default()
1092 };
1093
1094 let expected_state = state.clone().into();
1095 assert_eq!(
1096 state.update(&segment, REPLY_PAYLOAD_LEN, ConnectionDirection::Reply),
1097 (expected_state, false)
1098 );
1099 }
1100
1101 #[test_case(ORIGINAL_ISS, None; "small invalid")]
1102 #[test_case(
1103 ORIGINAL_ISS + 1, Some(Closed {}.into());
1104 "smallest valid"
1105 )]
1106 #[test_case(
1107 ORIGINAL_ISS + ORIGINAL_PAYLOAD_LEN as u32 + 1,
1108 Some(Closed {}.into());
1109 "largest valid"
1110 )]
1111 #[test_case(
1112 ORIGINAL_ISS + ORIGINAL_PAYLOAD_LEN as u32 + 2,
1113 None;
1114 "large invalid"
1115 )]
1116 fn syn_sent_reply_rst_segment(ack: SeqNum, new_state: Option<State>) {
1117 let state = SynSent {
1118 iss: ORIGINAL_ISS,
1119 logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1120 advertised_window_scale: None,
1121 window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1122 };
1123
1124 let segment = SegmentHeader {
1125 seq: ORIGINAL_ISS,
1126 ack: Some(ack),
1127 wnd: UnscaledWindowSize::from(ORIGINAL_WND),
1128 control: Some(Control::RST),
1129 ..Default::default()
1130 };
1131
1132 let (expected_state, valid) = match new_state {
1133 Some(state) => (state, true),
1134 None => (state.clone().into(), false),
1135 };
1136
1137 assert_eq!(
1138 state.update(&segment, 0, ConnectionDirection::Reply),
1139 (expected_state, valid)
1140 );
1141 }
1142
1143 #[test]
1144 fn syn_sent_reply_simultaneous_open() {
1145 let state = SynSent {
1146 iss: ORIGINAL_ISS,
1147 logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1148 advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1149 window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1150 };
1151
1152 let segment = SegmentHeader {
1153 seq: ORIGINAL_ISS,
1154 wnd: UnscaledWindowSize::from(ORIGINAL_WND + 10),
1155 control: Some(Control::SYN),
1156 ..Default::default()
1157 };
1158
1159 assert_eq!(
1160 state.update(&segment, 0, ConnectionDirection::Reply),
1161 (Untracked {}.into(), true)
1162 );
1163 }
1164
1165 #[test_case(ORIGINAL_ISS; "too low")]
1166 #[test_case(ORIGINAL_ISS + ORIGINAL_PAYLOAD_LEN + 2; "too high")]
1167 fn syn_sent_reply_syn_ack_not_in_range(ack: SeqNum) {
1168 let state = SynSent {
1169 iss: ORIGINAL_ISS,
1170 logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1171 advertised_window_scale: None,
1172 window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1173 };
1174
1175 let segment = SegmentHeader {
1176 seq: REPLY_ISS,
1177 ack: Some(ack),
1178 wnd: UnscaledWindowSize::from(REPLY_WND),
1179 control: Some(Control::SYN),
1180 ..Default::default()
1181 };
1182
1183 let expected_state = state.clone().into();
1184 assert_eq!(
1185 state.update(&segment, REPLY_PAYLOAD_LEN, ConnectionDirection::Reply),
1186 (expected_state, false)
1187 );
1188 }
1189
1190 #[test_case(None)]
1191 #[test_case(Some(WindowScale::new(REPLY_WS).unwrap()))]
1192 fn syn_sent_reply_syn_ack(reply_window_scale: Option<WindowScale>) {
1193 let state = SynSent {
1194 iss: ORIGINAL_ISS,
1195 logical_len: ORIGINAL_PAYLOAD_LEN as u32 + 1,
1196 advertised_window_scale: WindowScale::new(ORIGINAL_WS),
1197 window_size: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1198 };
1199
1200 let segment = SegmentHeader {
1201 seq: REPLY_ISS,
1202 ack: Some(ORIGINAL_ISS + 1),
1203 wnd: UnscaledWindowSize::from(REPLY_WND),
1204 control: Some(Control::SYN),
1205 options: HandshakeOptions { window_scale: reply_window_scale, ..Default::default() }
1206 .into(),
1207 ..Default::default()
1208 };
1209
1210 let new_state = assert_matches!(
1211 state.update(
1212 &segment,
1213 REPLY_PAYLOAD_LEN,
1214 ConnectionDirection::Reply
1215 ),
1216 (State::WaitingOnOpeningAck(s), true) => s
1217 );
1218
1219 let (original_window_scale, reply_window_scale) = match reply_window_scale {
1220 Some(s) => (WindowScale::new(ORIGINAL_WS).unwrap(), s),
1221 None => (WindowScale::ZERO, WindowScale::ZERO),
1222 };
1223
1224 assert_eq!(
1225 new_state,
1226 WaitingOnOpeningAck {
1227 original: Peer {
1228 window_scale: original_window_scale,
1229 max_wnd: WindowSize::from_u32(ORIGINAL_WND as u32).unwrap(),
1230 max_wnd_seq: REPLY_ISS + ORIGINAL_WND as u32,
1231 max_next_seq: ORIGINAL_ISS + ORIGINAL_PAYLOAD_LEN + 1,
1232 unacked_data: true,
1233 fin_state: FinState::NotSent,
1234 },
1235 reply: Peer {
1236 window_scale: reply_window_scale,
1237 max_wnd: WindowSize::from_u32(REPLY_WND as u32).unwrap(),
1238 max_wnd_seq: ORIGINAL_ISS + 1 + REPLY_WND as u32,
1239 max_next_seq: REPLY_ISS + REPLY_PAYLOAD_LEN + 1,
1240 unacked_data: true,
1241 fin_state: FinState::NotSent,
1242 }
1243 }
1244 );
1245 }
1246
1247 #[test_case(FinState::NotSent, SeqNum::new(9) => FinState::Sent(SeqNum::new(9)))]
1248 #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(8) => FinState::Sent(SeqNum::new(8)))]
1249 #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(9) => FinState::Sent(SeqNum::new(9)))]
1250 #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(10) => FinState::Sent(SeqNum::new(9)))]
1251 #[test_case(FinState::Acked, SeqNum::new(9) => FinState::Acked)]
1252 fn fin_state_update_fin_sent(fin_state: FinState, seq: SeqNum) -> FinState {
1253 fin_state.update_fin_sent(seq)
1254 }
1255
1256 #[test_case(FinState::NotSent, SeqNum::new(10) => FinState::NotSent)]
1257 #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(9) => FinState::Sent(SeqNum::new(9)))]
1258 #[test_case(FinState::Sent(SeqNum::new(9)), SeqNum::new(10) => FinState::Acked)]
1259 #[test_case(FinState::Acked, SeqNum::new(10) => FinState::Acked)]
1260 fn fin_state_update_ack_received(fin_state: FinState, ack: SeqNum) -> FinState {
1261 fin_state.update_ack_received(ack)
1262 }
1263
1264 const RECV_MAX_NEXT_SEQ: SeqNum = SeqNum::new(66_001);
1265 const RECV_MAX_WND_SEQ: SeqNum = SeqNum::new(1424);
1266
1267 #[test_case(SeqNum::new(424), 200, SeqNum::new(1) => true; "success low seq/ack")]
1268 #[test_case(RECV_MAX_WND_SEQ, 0, RECV_MAX_NEXT_SEQ => true; "success high seq/ack")]
1269 #[test_case(RECV_MAX_WND_SEQ + 1, 0, SeqNum::new(1) => false; "bad equation I")]
1270 #[test_case(SeqNum::new(424), 199, SeqNum::new(1) => false; "bad equation II")]
1271 #[test_case(SeqNum::new(424), 200, RECV_MAX_NEXT_SEQ + 1 => false; "bad equation III")]
1272 #[test_case(SeqNum::new(424), 200, SeqNum::new(0) => false; "bad equation IV")]
1273 fn ack_segment_valid_test(seq: SeqNum, len: u32, ack: SeqNum) -> bool {
1274 let sender = Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() };
1275
1276 let receiver = Peer {
1278 window_scale: WindowScale::new(0).unwrap(),
1279 max_wnd: WindowSize::new(400).unwrap(),
1280 max_next_seq: RECV_MAX_NEXT_SEQ,
1281 max_wnd_seq: RECV_MAX_WND_SEQ,
1282 ..Peer::arbitrary()
1283 };
1284
1285 Peer::ack_segment_valid(&sender, &receiver, seq, len, ack)
1286 }
1287
1288 struct PeerUpdateSenderArgs {
1289 seq: SeqNum,
1290 len: u32,
1291 ack: SeqNum,
1292 wnd: UnscaledWindowSize,
1293 fin_seen: bool,
1294 }
1295
1296 #[test_case(
1297 Peer {
1298 window_scale: WindowScale::new(3).unwrap(),
1299 max_wnd: WindowSize::new(16).unwrap(),
1300 max_wnd_seq: SeqNum::new(127),
1301 max_next_seq: SeqNum::new(1024),
1302 unacked_data: false,
1303 fin_state: FinState::NotSent,
1304 },
1305 PeerUpdateSenderArgs {
1306 seq: SeqNum::new(1025),
1307 len: 10,
1308 ack: SeqNum::new(100),
1309 wnd: UnscaledWindowSize::from_u32(4),
1310 fin_seen: false
1311 } => Peer {
1312 window_scale: WindowScale::new(3).unwrap(),
1313 max_wnd: WindowSize::new(32).unwrap(),
1314 max_wnd_seq: SeqNum::new(132),
1315 max_next_seq: SeqNum::new(1035),
1316 unacked_data: true,
1317 fin_state: FinState::NotSent,
1318 }; "packet larger"
1319 )]
1320 #[test_case(
1321 Peer {
1322 window_scale: WindowScale::new(3).unwrap(),
1323 max_wnd: WindowSize::new(16).unwrap(),
1324 max_wnd_seq: SeqNum::new(127),
1325 max_next_seq: SeqNum::new(1024),
1326 unacked_data: false,
1327 fin_state: FinState::NotSent,
1328 },
1329 PeerUpdateSenderArgs {
1330 seq: SeqNum::new(1000),
1331 len: 10,
1332 ack: SeqNum::new(0),
1333 wnd: UnscaledWindowSize::from_u32(0),
1334 fin_seen: false
1335 } => Peer {
1336 window_scale: WindowScale::new(3).unwrap(),
1337 max_wnd: WindowSize::new(16).unwrap(),
1338 max_wnd_seq: SeqNum::new(127),
1339 max_next_seq: SeqNum::new(1024),
1340 unacked_data: false,
1341 fin_state: FinState::NotSent,
1342 }; "packet smaller"
1343 )]
1344 #[test_case(
1345 Peer {
1346 window_scale: WindowScale::new(3).unwrap(),
1347 max_wnd: WindowSize::new(16).unwrap(),
1348 max_wnd_seq: SeqNum::new(127),
1349 max_next_seq: SeqNum::new(1024),
1350 unacked_data: false,
1351 fin_state: FinState::NotSent,
1352 },
1353 PeerUpdateSenderArgs {
1354 seq: SeqNum::new(1000),
1355 len: 10,
1356 ack: SeqNum::new(0),
1357 wnd: UnscaledWindowSize::from_u32(0),
1358 fin_seen: true
1359 } => Peer {
1360 window_scale: WindowScale::new(3).unwrap(),
1361 max_wnd: WindowSize::new(16).unwrap(),
1362 max_wnd_seq: SeqNum::new(127),
1363 max_next_seq: SeqNum::new(1024),
1364 unacked_data: false,
1365 fin_state: FinState::Sent(SeqNum::new(1000 + 9)),
1366 }; "fin sent"
1367 )]
1368 fn peer_update_sender_test(peer: Peer, args: PeerUpdateSenderArgs) -> Peer {
1369 peer.update_sender(args.seq, args.len, args.ack, args.wnd, args.fin_seen)
1370 }
1371
1372 #[test_case(
1373 Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() },
1374 SeqNum::new(1024) => Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() };
1375 "unset unacked data"
1376 )]
1377 #[test_case(
1378 Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() },
1379 SeqNum::new(1023) => Peer { max_next_seq: SeqNum::new(1024), ..Peer::arbitrary() };
1380 "don't unset unacked data"
1381 )]
1382 #[test_case(
1383 Peer { fin_state: FinState::Sent(SeqNum::new(9)), ..Peer::arbitrary() },
1384 SeqNum::new(10) => Peer { fin_state: FinState::Acked, ..Peer::arbitrary() };
1385 "update fin state"
1386 )]
1387 fn peer_update_receiver_test(peer: Peer, ack: SeqNum) -> Peer {
1388 peer.update_receiver(ack)
1389 }
1390
1391 #[test]
1394 fn peer_max_ack_window() {
1395 let max_peer = Peer { window_scale: WindowScale::MAX, ..Peer::arbitrary() };
1396 let min_peer = Peer { window_scale: WindowScale::new(0).unwrap(), ..Peer::arbitrary() };
1397
1398 assert_eq!(max_peer.max_ack_window(), 1_081_344_000u32);
1399 assert_eq!(min_peer.max_ack_window(), 66_000u32);
1400 }
1401
1402 enum EstablishedUpdateTestResult {
1403 Success { new_original: Peer, new_reply: Peer, fin_seen: bool },
1404 Invalid,
1405 Reset,
1406 }
1407
1408 struct EstablishedUpdateTestArgs {
1409 segment: SegmentHeader,
1410 payload_len: usize,
1411 dir: ConnectionDirection,
1412 expected: EstablishedUpdateTestResult,
1413 }
1414
1415 #[test_case(
1416 EstablishedUpdateTestArgs {
1417 segment: SegmentHeader {
1418 seq: SeqNum::new(1400),
1419 ack: Some(SeqNum::new(66_001)),
1420 wnd: UnscaledWindowSize::from(10),
1421 ..Default::default()
1422 },
1423 payload_len: 24,
1424 dir: ConnectionDirection::Original,
1425 expected: EstablishedUpdateTestResult::Success {
1426 new_original: Peer {
1427 window_scale: WindowScale::new(2).unwrap(),
1428 max_wnd: WindowSize::new(40).unwrap(),
1430 max_wnd_seq: SeqNum::new(70_000),
1431 max_next_seq: SeqNum::new(1424),
1433 unacked_data: true,
1435 fin_state: FinState::NotSent,
1436 },
1437 new_reply: Peer {
1438 window_scale: WindowScale::new(0).unwrap(),
1439 max_wnd: WindowSize::new(400).unwrap(),
1440 max_wnd_seq: SeqNum::new(1424),
1441 max_next_seq: SeqNum::new(66_001),
1442 unacked_data: false,
1444 fin_state: FinState::NotSent,
1445 },
1446 fin_seen: false,
1447 }
1448 }; "success original"
1449 )]
1450 #[test_case(
1451 EstablishedUpdateTestArgs {
1452 segment: SegmentHeader {
1453 seq: SeqNum::new(66_100),
1454 ack: Some(SeqNum::new(1024)),
1455 wnd: UnscaledWindowSize::from(10),
1456 control: Some(Control::FIN),
1457 ..Default::default()
1458 },
1459 payload_len: 0,
1460 dir: ConnectionDirection::Reply,
1461 expected: EstablishedUpdateTestResult::Success {
1462 new_original: Peer {
1464 window_scale: WindowScale::new(2).unwrap(),
1465 max_wnd: WindowSize::new(0).unwrap(),
1466 max_wnd_seq: SeqNum::new(70_000),
1467 max_next_seq: SeqNum::new(1024),
1468 unacked_data: false,
1469 fin_state: FinState::NotSent,
1470 },
1471 new_reply: Peer {
1472 window_scale: WindowScale::new(0).unwrap(),
1473 max_wnd: WindowSize::new(400).unwrap(),
1474 max_wnd_seq: SeqNum::new(1424),
1475 max_next_seq: SeqNum::new(66_101),
1476 unacked_data: true,
1477 fin_state: FinState::Sent(SeqNum::new(66_100)),
1478 },
1479 fin_seen: true,
1480 }
1481 }; "success reply"
1482 )]
1483 #[test_case(
1484 EstablishedUpdateTestArgs {
1485 segment: SegmentHeader {
1486 seq: SeqNum::new(1400),
1487 ack: Some(SeqNum::new(66_001)),
1488 wnd: UnscaledWindowSize::from(10),
1489 control: Some(Control::RST),
1490 ..Default::default()
1491 },
1492 payload_len: 24,
1493 dir: ConnectionDirection::Original,
1494 expected: EstablishedUpdateTestResult::Reset,
1495 }; "RST"
1496 )]
1497 #[test_case(
1498 EstablishedUpdateTestArgs {
1499 segment: SegmentHeader {
1500 seq: SeqNum::new(1400),
1501 wnd: UnscaledWindowSize::from(10),
1502 ..Default::default()
1503 },
1504 payload_len: 24,
1506 dir: ConnectionDirection::Original,
1507 expected: EstablishedUpdateTestResult::Invalid,
1508 }; "missing ack"
1509 )]
1510 #[test_case(
1511 EstablishedUpdateTestArgs {
1512 segment: SegmentHeader {
1513 seq: SeqNum::new(0),
1515 wnd: UnscaledWindowSize::from(10),
1516 ..Default::default()
1517 },
1518 payload_len: 24,
1520 dir: ConnectionDirection::Original,
1521 expected: EstablishedUpdateTestResult::Invalid,
1522 }; "invalid equation bounds"
1523 )]
1524 #[test_case(
1525 EstablishedUpdateTestArgs {
1526 segment: SegmentHeader {
1527 seq: SeqNum::new(1400),
1528 ack: Some(SeqNum::new(66_001)),
1529 wnd: UnscaledWindowSize::from(10),
1530 control: Some(Control::SYN),
1531 ..Default::default()
1532 },
1533 payload_len: 24,
1534 dir: ConnectionDirection::Original,
1535 expected: EstablishedUpdateTestResult::Invalid,
1536 }; "SYN not allowed"
1537 )]
1538 fn do_established_update_test(args: EstablishedUpdateTestArgs) {
1539 let original = Peer {
1540 window_scale: WindowScale::new(2).unwrap(),
1541 max_wnd: WindowSize::new(0).unwrap(),
1542 max_wnd_seq: SeqNum::new(70_000),
1543 max_next_seq: SeqNum::new(1024),
1544 unacked_data: false,
1545 fin_state: FinState::NotSent,
1546 };
1547
1548 let reply = Peer {
1549 window_scale: WindowScale::new(0).unwrap(),
1550 max_wnd: WindowSize::new(400).unwrap(),
1551 max_wnd_seq: SeqNum::new(1424),
1552 max_next_seq: SeqNum::new(66_001),
1553 unacked_data: true,
1554 fin_state: FinState::NotSent,
1555 };
1556
1557 let expected_result = match args.expected {
1558 EstablishedUpdateTestResult::Success { new_original, new_reply, fin_seen } => {
1559 EstablishedUpdateResult::Success { new_original, new_reply, fin_seen }
1560 }
1561 EstablishedUpdateTestResult::Invalid => EstablishedUpdateResult::Invalid {
1562 original: original.clone(),
1563 reply: reply.clone(),
1564 },
1565 EstablishedUpdateTestResult::Reset => EstablishedUpdateResult::Reset,
1566 };
1567
1568 assert_eq!(
1569 do_established_update(
1570 UpdatePeers { original: original, reply: reply },
1571 &args.segment,
1572 args.payload_len,
1573 args.dir,
1574 ),
1575 expected_result
1576 );
1577 }
1578
1579 struct StateUpdateTestArgs {
1580 segment: SegmentHeader,
1581 payload_len: usize,
1582 dir: ConnectionDirection,
1583 expected: Option<State>,
1584 }
1585
1586 #[test_case(
1587 StateUpdateTestArgs {
1588 segment: SegmentHeader {
1589 seq: SeqNum::new(1400),
1590 ack: Some(SeqNum::new(66_001)),
1591 wnd: UnscaledWindowSize::from(10),
1592 ..Default::default()
1593 },
1594 payload_len: 24,
1595 dir: ConnectionDirection::Original,
1596 expected: Some(Established {
1597 original: Peer {
1598 window_scale: WindowScale::new(2).unwrap(),
1599 max_wnd: WindowSize::new(40).unwrap(),
1600 max_wnd_seq: SeqNum::new(70_000),
1601 max_next_seq: SeqNum::new(1424),
1602 unacked_data: true,
1603 fin_state: FinState::NotSent,
1604 },
1605 reply: Peer {
1606 window_scale: WindowScale::new(0).unwrap(),
1607 max_wnd: WindowSize::new(400).unwrap(),
1608 max_wnd_seq: SeqNum::new(1424),
1609 max_next_seq: SeqNum::new(66_001),
1610 unacked_data: false,
1611 fin_state: FinState::NotSent,
1612 },
1613 }.into()),
1614 }; "established"
1615 )]
1616 #[test_case(
1617 StateUpdateTestArgs {
1618 segment: SegmentHeader {
1619 seq: SeqNum::new(66_100),
1620 ack: Some(SeqNum::new(1024)),
1621 wnd: UnscaledWindowSize::from(10),
1622 control: Some(Control::FIN),
1623 ..Default::default()
1624 },
1625 payload_len: 0,
1626 dir: ConnectionDirection::Reply,
1627 expected: Some(Closing {
1628 original: Peer {
1629 window_scale: WindowScale::new(2).unwrap(),
1630 max_wnd: WindowSize::new(0).unwrap(),
1631 max_wnd_seq: SeqNum::new(70_000),
1632 max_next_seq: SeqNum::new(1024),
1633 unacked_data: false,
1634 fin_state: FinState::NotSent,
1635 },
1636 reply: Peer {
1637 window_scale: WindowScale::new(0).unwrap(),
1638 max_wnd: WindowSize::new(400).unwrap(),
1639 max_wnd_seq: SeqNum::new(1424),
1640 max_next_seq: SeqNum::new(66_101),
1641 unacked_data: true,
1642 fin_state: FinState::Sent(SeqNum::new(66_100)),
1643 },
1644 }.into()),
1645 }; "closing"
1646 )]
1647 #[test_case(
1648 StateUpdateTestArgs {
1649 segment: SegmentHeader {
1650 seq: SeqNum::new(66_100),
1651 ack: Some(SeqNum::new(1024)),
1652 wnd: UnscaledWindowSize::from(10),
1653 ..Default::default()
1654 },
1655 payload_len: 0,
1656 dir: ConnectionDirection::Reply,
1657 expected: Some(WaitingOnOpeningAck {
1658 original: Peer {
1659 window_scale: WindowScale::new(2).unwrap(),
1660 max_wnd: WindowSize::new(0).unwrap(),
1661 max_wnd_seq: SeqNum::new(70_000),
1662 max_next_seq: SeqNum::new(1024),
1663 unacked_data: false,
1664 fin_state: FinState::NotSent,
1665 },
1666 reply: Peer {
1667 window_scale: WindowScale::new(0).unwrap(),
1668 max_wnd: WindowSize::new(400).unwrap(),
1669 max_wnd_seq: SeqNum::new(1424),
1670 max_next_seq: SeqNum::new(66_100),
1671 unacked_data: true,
1672 fin_state: FinState::NotSent,
1673 },
1674 }.into())
1675 }; "update in place"
1676 )]
1677 #[test_case(
1678 StateUpdateTestArgs {
1679 segment: SegmentHeader {
1680 seq: SeqNum::new(100_000),
1682 ack: Some(SeqNum::new(1024)),
1683 wnd: UnscaledWindowSize::from(10),
1684 ..Default::default()
1685 },
1686 payload_len: 0,
1687 dir: ConnectionDirection::Reply,
1688 expected: None
1689 }; "invalid"
1690 )]
1691 #[test_case(
1692 StateUpdateTestArgs {
1693 segment: SegmentHeader {
1694 seq: SeqNum::new(1400),
1695 ack: Some(SeqNum::new(66_001)),
1696 wnd: UnscaledWindowSize::from(10),
1697 control: Some(Control::RST),
1698 ..Default::default()
1699 },
1700 payload_len: 24,
1701 dir: ConnectionDirection::Original,
1702 expected: Some(Closed {}.into()),
1703 }; "rst"
1704 )]
1705 fn waiting_on_opening_ack_test(args: StateUpdateTestArgs) {
1706 let state = WaitingOnOpeningAck {
1707 original: Peer {
1708 window_scale: WindowScale::new(2).unwrap(),
1709 max_wnd: WindowSize::new(0).unwrap(),
1710 max_wnd_seq: SeqNum::new(70_000),
1711 max_next_seq: SeqNum::new(1024),
1712 unacked_data: false,
1713 fin_state: FinState::NotSent,
1714 },
1715 reply: Peer {
1716 window_scale: WindowScale::new(0).unwrap(),
1717 max_wnd: WindowSize::new(400).unwrap(),
1718 max_wnd_seq: SeqNum::new(1424),
1719 max_next_seq: SeqNum::new(66_001),
1720 unacked_data: true,
1721 fin_state: FinState::NotSent,
1722 },
1723 };
1724
1725 let (new_state, valid) = match args.expected {
1726 Some(new_state) => (new_state, true),
1727 None => (state.clone().into(), false),
1728 };
1729
1730 assert_eq!(state.update(&args.segment, args.payload_len, args.dir), (new_state, valid));
1731 }
1732
1733 #[test_case(
1734 StateUpdateTestArgs {
1735 segment: SegmentHeader {
1736 seq: SeqNum::new(1400),
1737 ack: Some(SeqNum::new(66_001)),
1738 wnd: UnscaledWindowSize::from(10),
1739 ..Default::default()
1740 },
1741 payload_len: 24,
1742 dir: ConnectionDirection::Original,
1743 expected: Some(Established {
1744 original: Peer {
1745 window_scale: WindowScale::new(2).unwrap(),
1746 max_wnd: WindowSize::new(40).unwrap(),
1747 max_wnd_seq: SeqNum::new(70_000),
1748 max_next_seq: SeqNum::new(1424),
1749 unacked_data: true,
1751 fin_state: FinState::NotSent,
1752 },
1753 reply: Peer {
1754 window_scale: WindowScale::new(0).unwrap(),
1755 max_wnd: WindowSize::new(400).unwrap(),
1756 max_wnd_seq: SeqNum::new(1424),
1757 max_next_seq: SeqNum::new(66_001),
1758 unacked_data: false,
1760 fin_state: FinState::NotSent,
1761 },
1762 }.into()),
1763 }; "update original"
1764 )]
1765 #[test_case(
1766 StateUpdateTestArgs {
1767 segment: SegmentHeader {
1768 seq: SeqNum::new(66_100),
1769 ack: Some(SeqNum::new(1024)),
1770 wnd: UnscaledWindowSize::from(10),
1771 control: Some(Control::FIN),
1772 ..Default::default()
1773 },
1774 payload_len: 0,
1775 dir: ConnectionDirection::Reply,
1776 expected: Some(Closing {
1777 original: Peer {
1778 window_scale: WindowScale::new(2).unwrap(),
1779 max_wnd: WindowSize::new(0).unwrap(),
1780 max_wnd_seq: SeqNum::new(70_000),
1781 max_next_seq: SeqNum::new(1024),
1782 unacked_data: false,
1783 fin_state: FinState::NotSent,
1784 },
1785 reply: Peer {
1786 window_scale: WindowScale::new(0).unwrap(),
1787 max_wnd: WindowSize::new(400).unwrap(),
1788 max_wnd_seq: SeqNum::new(1424),
1789 max_next_seq: SeqNum::new(66_101),
1790 unacked_data: true,
1791 fin_state: FinState::Sent(SeqNum::new(66_100)),
1792 },
1793 }.into()),
1794 }; "closing"
1795 )]
1796 #[test_case(
1797 StateUpdateTestArgs {
1798 segment: SegmentHeader {
1799 seq: SeqNum::new(1400),
1800 ack: Some(SeqNum::new(100_000)),
1802 wnd: UnscaledWindowSize::from(10),
1803 ..Default::default()
1804 },
1805 payload_len: 24,
1806 dir: ConnectionDirection::Original,
1807 expected: None,
1808 }; "invalid"
1809 )]
1810 #[test_case(
1811 StateUpdateTestArgs {
1812 segment: SegmentHeader {
1813 seq: SeqNum::new(1400),
1814 ack: Some(SeqNum::new(66_001)),
1815 wnd: UnscaledWindowSize::from(10),
1816 control: Some(Control::RST),
1817 ..Default::default()
1818 },
1819 payload_len: 24,
1820 dir: ConnectionDirection::Original,
1821 expected: Some(Closed {}.into()),
1822 }; "rst"
1823 )]
1824 fn established_test(args: StateUpdateTestArgs) {
1825 let state = Established {
1826 original: Peer {
1827 window_scale: WindowScale::new(2).unwrap(),
1828 max_wnd: WindowSize::new(0).unwrap(),
1829 max_wnd_seq: SeqNum::new(70_000),
1830 max_next_seq: SeqNum::new(1024),
1831 unacked_data: false,
1832 fin_state: FinState::NotSent,
1833 },
1834 reply: Peer {
1835 window_scale: WindowScale::new(0).unwrap(),
1836 max_wnd: WindowSize::new(400).unwrap(),
1837 max_wnd_seq: SeqNum::new(1424),
1838 max_next_seq: SeqNum::new(66_001),
1839 unacked_data: true,
1840 fin_state: FinState::NotSent,
1841 },
1842 };
1843
1844 let (new_state, valid) = match args.expected {
1845 Some(new_state) => (new_state, true),
1846 None => (state.clone().into(), false),
1847 };
1848
1849 assert_eq!(state.update(&args.segment, args.payload_len, args.dir), (new_state, valid));
1850 }
1851
1852 #[test_case(
1853 StateUpdateTestArgs {
1854 segment: SegmentHeader {
1855 seq: SeqNum::new(1400),
1856 ack: Some(SeqNum::new(66_001)),
1857 wnd: UnscaledWindowSize::from(10),
1858 ..Default::default()
1859 },
1860 payload_len: 24,
1861 dir: ConnectionDirection::Original,
1862 expected: Some(Closing {
1863 original: Peer {
1864 window_scale: WindowScale::new(2).unwrap(),
1865 max_wnd: WindowSize::new(40).unwrap(),
1866 max_wnd_seq: SeqNum::new(70_000),
1867 max_next_seq: SeqNum::new(1424),
1868 unacked_data: true,
1869 fin_state: FinState::NotSent,
1870 },
1871 reply: Peer {
1872 window_scale: WindowScale::new(0).unwrap(),
1873 max_wnd: WindowSize::new(400).unwrap(),
1874 max_wnd_seq: SeqNum::new(1424),
1875 max_next_seq: SeqNum::new(66_001),
1876 unacked_data: false,
1877 fin_state: FinState::Acked,
1878 },
1879 }.into()),
1880 }; "update original"
1881 )]
1882 #[test_case(
1883 StateUpdateTestArgs {
1884 segment: SegmentHeader {
1885 seq: SeqNum::new(1400),
1886 ack: Some(SeqNum::new(100_000)),
1888 wnd: UnscaledWindowSize::from(10),
1889 ..Default::default()
1890 },
1891 payload_len: 24,
1892 dir: ConnectionDirection::Original,
1893 expected: None,
1894 }; "invalid"
1895 )]
1896 #[test_case(
1897 StateUpdateTestArgs {
1898 segment: SegmentHeader {
1899 seq: SeqNum::new(1400),
1900 ack: Some(SeqNum::new(66_001)),
1901 wnd: UnscaledWindowSize::from(10),
1902 control: Some(Control::RST),
1903 ..Default::default()
1904 },
1905 payload_len: 0,
1906 dir: ConnectionDirection::Original,
1907 expected: Some (Closed {}.into())
1908 }; "rst"
1909 )]
1910 fn closing_test(args: StateUpdateTestArgs) {
1911 let state = Closing {
1912 original: Peer {
1913 window_scale: WindowScale::new(2).unwrap(),
1914 max_wnd: WindowSize::new(0).unwrap(),
1915 max_wnd_seq: SeqNum::new(70_000),
1916 max_next_seq: SeqNum::new(1024),
1917 unacked_data: true,
1918 fin_state: FinState::NotSent,
1919 },
1920 reply: Peer {
1921 window_scale: WindowScale::new(0).unwrap(),
1922 max_wnd: WindowSize::new(400).unwrap(),
1923 max_wnd_seq: SeqNum::new(1424),
1924 max_next_seq: SeqNum::new(66_001),
1925 unacked_data: false,
1926 fin_state: FinState::Acked,
1927 },
1928 };
1929
1930 let (new_state, valid) = match args.expected {
1931 Some(new_state) => (new_state, true),
1932 None => (state.clone().into(), false),
1933 };
1934
1935 assert_eq!(state.update(&args.segment, args.payload_len, args.dir), (new_state, valid));
1936 }
1937
1938 #[test]
1939 fn closing_complete_test() {
1940 let state = Closing {
1941 original: Peer {
1942 window_scale: WindowScale::new(2).unwrap(),
1943 max_wnd: WindowSize::new(0).unwrap(),
1944 max_wnd_seq: SeqNum::new(70_000),
1945 max_next_seq: SeqNum::new(1024),
1946 unacked_data: true,
1947 fin_state: FinState::Sent(SeqNum::new(1023)),
1948 },
1949 reply: Peer {
1950 window_scale: WindowScale::new(0).unwrap(),
1951 max_wnd: WindowSize::new(400).unwrap(),
1952 max_wnd_seq: SeqNum::new(1424),
1953 max_next_seq: SeqNum::new(66_001),
1954 unacked_data: false,
1955 fin_state: FinState::Acked,
1956 },
1957 };
1958
1959 let segment = SegmentHeader {
1960 seq: SeqNum::new(66_100),
1961 ack: Some(SeqNum::new(1024)),
1962 wnd: UnscaledWindowSize::from(10),
1963 ..Default::default()
1964 };
1965
1966 assert_matches!(
1967 state.update(&segment, 0, ConnectionDirection::Reply),
1968 (State::Closed(_), true)
1969 );
1970 }
1971}