NetTest - Clean up TCP code a little, add lost packet checks
[tpg/acess2.git] / Tools / NetTest_Runner / test_tcp.c
1 /*
2  * Acess2 Network Stack Tester
3  * - By John Hodge (thePowersGang)
4  *
5  * test_tcp.c
6  * - Tests for the behavior of the "Transmission Control Protocol"
7  */
8 #include "test.h"
9 #include "tests.h"
10 #include "net.h"
11 #include "stack.h"
12 #include "arp.h"
13 #include "tcp.h"
14 #include <string.h>
15
16 #define TEST_ASSERT_rx()        TEST_ASSERT( rxlen = Net_Receive(0, sizeof(rxbuf), rxbuf, ERX_TIMEOUT) )
17 #define TEST_ASSERT_no_rx()     TEST_ASSERT( Net_Receive(0, sizeof(rxbuf), rxbuf, NRX_TIMEOUT) == 0 )
18
19 bool Test_TCP_Basic(void)
20 {
21         TEST_SETNAME(__func__);
22         size_t  rxlen, ofs, len;
23         char rxbuf[MTU];
24         const int       ERX_TIMEOUT = 1000;     // Expect RX timeout (timeout=failure)
25         const int       NRX_TIMEOUT = 250;      // Not expect RX timeout (timeout=success)
26         const int       RETX_TIMEOUT = 1000;    // OS PARAM - Retransmit timeout
27         const int       LOST_TIMEOUT = 1000;    // OS PARAM - Time before sending an ACK 
28         const int       DACK_TIMEOUT = 500;     // OS PARAM - Timeout for delayed ACKs
29         const size_t    DACK_BYTES = 4096;      // OS PARAM - Threshold for delayed ACKs
30
31         tTCPConn        testconn = {
32                 .IFNum = 0, .AF = 4,
33                 .RAddr = BLOB(TEST_IP),
34                 .LAddr = BLOB(HOST_IP),
35                 .RPort = 80,
36                 .LPort = 11200,
37                 .Window = 0x1000,
38                 .LSeq = 0x1000,
39                 .RSeq = 0,
40         };
41
42         const char testblob[] = "HelloWorld, this is some random testing data for TCP\xFF\x00\x66\x12\x12";
43         const size_t    testblob_len = sizeof(testblob);
44         
45         // 1. Test packets to closed port
46         // > RFC793 Pg.65
47         
48         // 1.1. Send SYN packet
49         TCP_SendC(&testconn, TCP_SYN, testblob_len, testblob);
50         testconn.RSeq = 0;
51         testconn.LSeq += testblob_len;
52         // Expect RST,ACK with SEQ=0
53         TEST_ASSERT_rx();
54         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_RST|TCP_ACK) );
55         TEST_ASSERT_REL(ofs, ==, rxlen);
56         
57         // 1.2. Send a SYN,ACK packet
58         testconn.RSeq = 12345;
59         TCP_SendC(&testconn, TCP_SYN|TCP_ACK, 0, NULL);
60         // Expect a TCP_RST with SEQ=ACK
61         TEST_ASSERT_rx();
62         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_RST) );
63         TEST_ASSERT_REL(ofs, ==, rxlen);
64         testconn.LSeq ++;
65         
66         // 1.3. Send a RST packet
67         TCP_SendC(&testconn, TCP_RST, 0, NULL);
68         // Expect nothing
69         TEST_ASSERT_no_rx();
70         testconn.LSeq ++;
71         
72         // 1.3. Send a RST,ACK packet
73         TCP_SendC(&testconn, TCP_RST|TCP_ACK, 0, NULL);
74         // Expect nothing
75         TEST_ASSERT_no_rx();
76         testconn.LSeq ++;
77
78         
79         // 2. Establishing connection with a server
80         testconn.RPort = 7;
81         testconn.LPort = 11239;
82         Stack_SendCommand("tcp_echo_server %i", testconn.RPort);
83
84         // >>> STATE: LISTEN
85
86         // 2.1. Send RST
87         TCP_SendC(&testconn, TCP_RST, 0, NULL);
88         // - Expect nothing
89         TEST_ASSERT_no_rx();
90         // 2.2. Send ACK
91         TCP_SendC(&testconn, TCP_ACK, 0, NULL);
92         // - Expect RST
93         TEST_ASSERT_rx();
94         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_RST) );
95         TEST_ASSERT_REL(ofs, ==, rxlen);
96
97         // 2.3. Begin hanshake (SYN)
98         // TODO: Test "If the SYN bit is set, check the security."
99         TCP_SendC(&testconn, TCP_SYN, 0, NULL);
100         testconn.LSeq ++;
101         // - Expect SYN,ACK with ACK == SEQ+1
102         TEST_ASSERT_rx();
103         TCP_SkipCheck_Seq(true);
104         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_SYN|TCP_ACK) );
105         testconn.RSeq = TCP_Pkt_GetSeq(rxlen, rxbuf, testconn.AF) + 1;
106
107         // >>> STATE: SYN-RECEIVED
108         // TODO: Test other transitions from SYN-RECEIVED
109         
110         // 2.4. Complete handshake, TCP ACK
111         TCP_SendC(&testconn, TCP_ACK, 0, NULL);
112         // - Expect nothing
113         TEST_ASSERT_no_rx();
114
115         // >>> STATE: ESTABLISHED
116         
117         // 2.5. Send data
118         TCP_SendC(&testconn, TCP_ACK|TCP_PSH, testblob_len, testblob);
119         testconn.LSeq += testblob_len;
120
121         // Expect echoed reponse with ACK
122         TEST_ASSERT_rx();
123         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK|TCP_PSH) );
124         TEST_ASSERT_REL( len, ==, testblob_len );
125         TEST_ASSERT( memcmp(rxbuf + ofs, testblob, testblob_len) == 0 );
126         testconn.RSeq += testblob_len;
127
128         // Send something short
129         const char testblob2[] = "test blob two.";
130         const size_t    testblob2_len = sizeof(testblob2);
131         TCP_SendC(&testconn, TCP_ACK|TCP_PSH, testblob2_len, testblob2);
132         testconn.LSeq += testblob2_len;
133         // Expect response with data and ACK
134         TEST_ASSERT_rx();
135         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK|TCP_PSH) );
136         TEST_ASSERT_REL( len, ==, testblob2_len );
137         TEST_ASSERT( memcmp(rxbuf + ofs, testblob2, testblob2_len) == 0 );
138         
139         // Wait for just under retransmit time, expecting nothing
140         #if TEST_TIMERS
141         TEST_ASSERT( 0 == Net_Receive(0, sizeof(rxbuf), rxbuf, RETX_TIMEOUT-100) );
142         // Now expect the previous message
143         TEST_ASSERT_rx();
144         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK|TCP_PSH) );
145         TEST_ASSERT_REL( len, ==, testblob2_len );
146         TEST_ASSERT( memcmp(rxbuf + ofs, testblob2, testblob2_len) == 0 );
147         #else
148         TEST_WARN("Not testing retransmit timer");
149         #endif
150         testconn.RSeq += testblob2_len;
151         
152         // Send explicit acknowledgement
153         TCP_SendC(&testconn, TCP_ACK, 0, NULL);
154         TEST_ASSERT_no_rx();
155         
156         // TODO: Test delayed ACKs (Timeout and data)
157         // > Requires inhibiting the server's echo response?
158         
159         // === Test out-of-order packets ===
160         testconn.LSeq += testblob2_len; // raise sequence number
161         TCP_SendC(&testconn, TCP_ACK|TCP_PSH, testblob_len, testblob);
162         // - previous data has not been sent, expect no response for ()
163         // TODO: Should this ACK be delayed?
164         //TEST_ASSERT_no_rx();
165         // - Expect an ACK of the highest received packet
166         testconn.LSeq -= testblob2_len;
167         TEST_ASSERT_rx();
168         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK) );
169         TEST_ASSERT_REL( len, ==, 0 );
170         // - Send missing data
171         TCP_SendC(&testconn, TCP_ACK, testblob2_len, testblob2);
172         testconn.LSeq += testblob_len+testblob2_len;    // raise sequence number
173         // - Expect echo response with all sent data
174         TEST_ASSERT_rx();
175         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK|TCP_PSH) );
176         TEST_ASSERT_REL( len, ==, testblob_len+testblob2_len );
177         TEST_ASSERT( memcmp(rxbuf + ofs, testblob2, testblob2_len) == 0 );
178         TEST_ASSERT( memcmp(rxbuf + ofs+testblob2_len, testblob, testblob_len) == 0 );
179         testconn.RSeq += len;
180         
181         // 2.6. Close connection (TCP FIN)
182         TCP_SendC(&testconn, TCP_ACK|TCP_FIN, 0, NULL);
183         testconn.LSeq ++;       // Empty = 1 byte
184         // Expect ACK? (Does acess do delayed ACKs here?)
185         TEST_ASSERT_rx();
186         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_ACK) );
187         TEST_ASSERT_REL( len, ==, 0 );
188         // >>> STATE: CLOSE WAIT
189         
190         // Expect FIN
191         TEST_ASSERT_rx();
192         TEST_ASSERT( TCP_Pkt_CheckC(rxlen, rxbuf, &ofs, &len, &testconn, TCP_FIN) );
193         TEST_ASSERT_REL( len, ==, 0 );
194         
195         // >>> STATE: LAST-ACK
196
197         // 2.7 Send ACK of FIN
198         TCP_SendC(&testconn, TCP_ACK, 0, NULL);
199         // Expect no response
200         TEST_ASSERT_no_rx();
201         
202         // >>> STATE: CLOSED
203         
204         return true;
205 }
206
207 bool Test_TCP_SYN_RECEIVED(void)
208 {
209         // 1. Get into SYN-RECEIVED
210         
211         // 2. Send various non-ACK packets
212         return false;
213 }

UCC git Repository :: git.ucc.asn.au