forked from vikshanker/sponge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
fsm_connect.cc
113 lines (87 loc) · 3.8 KB
/
fsm_connect.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include "tcp_config.hh"
#include "tcp_expectation.hh"
#include "tcp_fsm_test_harness.hh"
#include "tcp_header.hh"
#include "tcp_segment.hh"
#include "util.hh"
#include <cstdint>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <stdexcept>
#include <string>
using namespace std;
using State = TCPTestHarness::State;
int main() {
try {
TCPConfig cfg{};
auto rd = get_random_generator();
// NB: In Riad's version of this test, the ACK was not ignored, but per
// pg 68 of the RFC, I think that it should be.
//
// test #1: START -> SYN_SENT -> ACK (ignored) -> SYN -> SYN_RECV
{
TCPTestHarness test_1(cfg);
// tell the FSM to connect, make sure we get a SYN
test_1.execute(Connect{});
test_1.execute(Tick(1));
TCPSegment seg1 = test_1.expect_seg(ExpectOneSegment{}.with_syn(true).with_ack(false),
"test 1 failed: could not parse SYN segment or invalid flags");
test_1.execute(ExpectState{State::SYN_SENT});
// send ACK only (no SYN yet)
test_1.send_ack(WrappingInt32{0}, seg1.header().seqno + 1);
test_1.execute(Tick(1));
test_1.execute(ExpectState{State::SYN_SENT});
// now send SYN
const WrappingInt32 isn(rd());
test_1.send_syn(isn);
test_1.execute(Tick(1));
test_1.execute(ExpectState{State::SYN_RCVD});
test_1.execute(ExpectOneSegment{}.with_ack(true).with_syn(false).with_ackno(isn + 1));
test_1.execute(ExpectBytesInFlight{1UL});
}
// test #2: START -> SYN_SENT -> SYN -> ACK -> ESTABLISHED
{
TCPTestHarness test_2(cfg);
test_2.execute(Connect{});
test_2.execute(Tick(1));
TCPSegment seg = test_2.expect_seg(ExpectOneSegment{}.with_syn(true).with_ack(false),
"test 2 failed: could not parse SYN segment or invalid flags");
auto &seg_hdr = seg.header();
test_2.execute(ExpectState{State::SYN_SENT});
// send SYN (no ACK yet)
const WrappingInt32 isn(rd());
test_2.send_syn(isn);
test_2.execute(Tick(1));
test_2.expect_seg(ExpectOneSegment{}.with_syn(false).with_ack(true).with_ackno(isn + 1),
"test 2 failed: bad ACK for SYN");
test_2.execute(ExpectState{State::SYN_RCVD});
// now send ACK
test_2.send_ack(isn + 1, seg_hdr.seqno + 1);
test_2.execute(Tick(1));
test_2.execute(ExpectNoSegment{}, "test 2 failed: got spurious ACK after ACKing SYN");
test_2.execute(ExpectState{State::ESTABLISHED});
}
// test #3: START -> SYN_SENT -> SYN/ACK -> ESTABLISHED
{
TCPTestHarness test_3(cfg);
test_3.execute(Connect{});
test_3.execute(Tick(1));
TCPSegment seg = test_3.expect_seg(ExpectOneSegment{}.with_syn(true).with_ack(false),
"test 3 failed: could not parse SYN segment or invalid flags");
auto &seg_hdr = seg.header();
test_3.execute(ExpectState{State::SYN_SENT});
// send SYN (no ACK yet)
const WrappingInt32 isn(rd());
test_3.send_syn(isn, seg_hdr.seqno + 1);
test_3.execute(Tick(1));
test_3.execute(ExpectOneSegment{}.with_ack(true).with_ackno(isn + 1).with_syn(false),
"test 3 failed: bad ACK for SYN");
test_3.execute(ExpectState{State::ESTABLISHED});
}
} catch (const exception &e) {
cerr << e.what() << endl;
return 1;
}
return EXIT_SUCCESS;
}