1 /* 8.2 :TCP in LISTEN state,
2 TCP MUST send RST in response to incoming segment with ACK and remain in the same state,
3 SEQ number of RST is taken from SEG.ACK. */
4
5 /* Procedure
6 1. Connection.
7 2. Server calls disconnect command.
8 3. Server calls unaccept and relisten command.
9 4. Client sends a segment that is carrying an ACK flag.
10 5. Server sends a RST segment with SEQ number taken from SEG.ACK.
11 6. Clean up.Print the resuit. */
12
13 #include "tx_api.h"
14 #include "nx_api.h"
15 #include "nx_tcp.h"
16 #include "nx_ip.h"
17 #include "nx_ram_network_driver_test_1500.h"
18
19 extern void test_control_return(UINT status);
20
21 #if !defined(NX_DISABLE_RESET_DISCONNECT) && !defined(NX_DISABLE_IPV4)
22
23 #define MSG "ABCDEFGHIJKLMNOPQRSTUVWXYZ "
24 #define DEMO_STACK_SIZE 2048
25
26 /* Define the ThreadX and NetX object control blocks... */
27
28 static TX_THREAD ntest_0;
29 static TX_THREAD ntest_1;
30
31 static NX_PACKET_POOL pool_0;
32 static NX_IP ip_0;
33 static NX_IP ip_1;
34 static NX_TCP_SOCKET client_socket;
35 static NX_TCP_SOCKET server_socket;
36
37 /* Define the counters used in the demo application... */
38
39 static ULONG error_counter;
40 static ULONG rst_counter;
41 static ULONG data_packet_counter;
42 static ULONG ack_segment;
43
44 /* Define thread prototypes. */
45
46 static void ntest_0_entry(ULONG thread_input);
47 static void ntest_1_entry(ULONG thread_input);
48 static void ntest_0_connect_received(NX_TCP_SOCKET *server_socket, UINT port);
49 static void ntest_0_disconnect_received(NX_TCP_SOCKET *server_socket);
50 extern void _nx_ram_network_driver_1500(struct NX_IP_DRIVER_STRUCT *driver_req);
51 extern UINT (*advanced_packet_process_callback)(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
52 static UINT my_packet_process_8_02(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr);
53 static void my_tcp_packet_receive_8_02(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
54 static void my_tcp_packet_receive_8_02_2(NX_IP *ip_ptr, NX_PACKET *packet_ptr);
55
56 /* Define what the initial system looks like. */
57
58 #ifdef CTEST
test_application_define(void * first_unused_memory)59 VOID test_application_define(void *first_unused_memory)
60 #else
61 void netx_8_02_application_define(void *first_unused_memory)
62 #endif
63 {
64 CHAR *pointer;
65 UINT status;
66
67 /* Setup the working pointer. */
68 pointer = (CHAR *) first_unused_memory;
69
70 error_counter = 0;
71 rst_counter = 0;
72 data_packet_counter = 0;
73
74 /* Create the main thread. */
75 tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
76 pointer, DEMO_STACK_SIZE,
77 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
78
79 pointer = pointer + DEMO_STACK_SIZE;
80
81 /* Create the main thread. */
82 tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
83 pointer, DEMO_STACK_SIZE,
84 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
85
86 pointer = pointer + DEMO_STACK_SIZE;
87
88 /* Initialize the NetX system. */
89 nx_system_initialize();
90
91 /* Create a packet pool. */
92 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, pointer, 8192);
93 pointer = pointer + 8192;
94
95 if(status)
96 error_counter++;
97
98 /* Create an IP instance. */
99 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
100 pointer, 2048, 1);
101 pointer = pointer + 2048;
102
103 /* Create another IP instance. */
104 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_1500,
105 pointer, 2048, 1);
106 pointer = pointer + 2048;
107
108 if(status)
109 error_counter++;
110
111 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
112 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
113 pointer = pointer + 1024;
114
115 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
116 status += nx_arp_enable(&ip_1, (void *) pointer, 1024);
117 pointer = pointer + 1024;
118
119 /* Check ARP enable status. */
120 if(status)
121 error_counter++;
122
123 /* Enable TCP processing for both IP instances. */
124 status = nx_tcp_enable(&ip_0);
125 status += nx_tcp_enable(&ip_1);
126
127 /* Check TCP enable status. */
128 if(status)
129 error_counter++;
130 }
131
132 /* Define the test threads. */
133
ntest_0_entry(ULONG thread_input)134 static void ntest_0_entry(ULONG thread_input)
135 {
136 UINT status;
137 ULONG actual_status;
138
139 /* Print out some test information banners. */
140 printf("NetX Test: TCP Spec 8.02 Test........................................");
141
142 /* Check for earlier error. */
143 if(error_counter)
144 {
145 printf("ERROR!\n");
146 test_control_return(1);
147 }
148
149 /* Ensure the IP instance has been initialized. */
150 status = nx_ip_status_check(&ip_0, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE);
151
152 /* Check status... */
153 if(status != NX_SUCCESS)
154 error_counter++;
155
156 /* Create a socket. */
157 status = nx_tcp_socket_create(&ip_0, &server_socket, "Server Socket",
158 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
159 100, NX_NULL, ntest_0_disconnect_received);
160
161 /* Check for error. */
162 if(status)
163 error_counter++;
164
165 /* Setup this thread to listen. */
166 status = nx_tcp_server_socket_listen(&ip_0, 12, &server_socket, 5, ntest_0_connect_received);
167
168 /* Check for error. */
169 if(status)
170 error_counter++;
171
172 /* Accept a client socket connection. */
173 status = nx_tcp_server_socket_accept(&server_socket, NX_IP_PERIODIC_RATE);
174
175 /* Check for error. */
176 if(status)
177 error_counter++;
178
179 /* Set the callback function to my_packet_process_8_02. */
180 advanced_packet_process_callback = my_packet_process_8_02;
181
182 /* Disconnect the server socket. */
183 status = nx_tcp_socket_disconnect(&server_socket, NX_NO_WAIT);
184
185 /* Set the port to NULL. */
186 status = nx_tcp_server_socket_unaccept(&server_socket);
187
188 /* Check for error. */
189 if(status)
190 error_counter++;
191
192 /* Setup server socket state to LISTEN */
193 status = nx_tcp_server_socket_relisten(&ip_0, 12, &server_socket);
194
195 if(status)
196 error_counter++;
197
198 if (server_socket.nx_tcp_socket_state != NX_TCP_LISTEN_STATE)
199 error_counter++;
200
201 /* Set the receive function to my_tcp_packet_receive_8_02. */
202 ip_0.nx_ip_tcp_packet_receive = my_tcp_packet_receive_8_02;
203
204 /* suspend the thread ntest_0 */
205 tx_thread_suspend(&ntest_0);
206
207 /* Check whether the server socket is in LISTEN state. */
208 if((data_packet_counter == 1) && (rst_counter == 2))
209 {
210 if (server_socket.nx_tcp_socket_state != NX_TCP_LISTEN_STATE)
211 error_counter++;
212 }
213 else
214 error_counter++;
215
216 /* Unlisten on the server port. */
217 status = nx_tcp_server_socket_unlisten(&ip_0, 12);
218
219 /* Check for error. */
220 if (status)
221 error_counter++;
222
223 /* Delete the socket. */
224 status = nx_tcp_socket_delete(&server_socket);
225
226 /* Check for error. */
227 if(status)
228 error_counter++;
229 }
230
ntest_1_entry(ULONG thread_input)231 static void ntest_1_entry(ULONG thread_input)
232 {
233 UINT status;
234 NX_PACKET *my_packet;
235
236
237 /* Create a socket. */
238 status = nx_tcp_socket_create(&ip_1, &client_socket, "Client Socket",
239 NX_IP_NORMAL, NX_FRAGMENT_OKAY,
240 NX_IP_TIME_TO_LIVE, 200,
241 NX_NULL, NX_NULL);
242
243 /* Check for error. */
244 if(status)
245 error_counter++;
246
247 /* Bind the socket. */
248 status = nx_tcp_client_socket_bind(&client_socket, 12, NX_IP_PERIODIC_RATE);
249
250 /* Check for error. */
251 if(status)
252 error_counter++;
253
254 /* Attempt to connect the socket. */
255 status = nx_tcp_client_socket_connect(&client_socket, IP_ADDRESS(1, 2, 3, 4), 12, 5 * NX_IP_PERIODIC_RATE);
256
257 /* Check for error. */
258 if(status)
259 error_counter++;
260
261 /* Replace the TCP receive function with my_tcp_packet_receive_8_02 for ip_1. */
262 ip_1.nx_ip_tcp_packet_receive = my_tcp_packet_receive_8_02_2;
263
264 /* Allocate a packet. */
265 status = nx_packet_allocate(&pool_0, &my_packet, NX_TCP_PACKET, NX_IP_PERIODIC_RATE);
266
267 /* Check status. */
268 if(status)
269 error_counter++;
270
271 status = nx_packet_data_append(my_packet, MSG, 20, &pool_0, NX_IP_PERIODIC_RATE);
272
273 /* Check status. */
274 if(status)
275 error_counter++;
276
277 /* Send the packet out! */
278 status = nx_tcp_socket_send(&client_socket, my_packet, NX_IP_PERIODIC_RATE);
279
280 /* Check status. */
281 if(status)
282 error_counter++;
283
284 /* Resume the thread ntest_0. */
285 tx_thread_resume(&ntest_0);
286
287 /* Unbind the socket. */
288 status = nx_tcp_client_socket_unbind(&client_socket);
289
290 /* Check for error. */
291 if(status)
292 error_counter++;
293
294 /* Delete the socket. */
295 status = nx_tcp_socket_delete(&client_socket);
296
297 /* Check for error. */
298 if(status)
299 error_counter++;
300
301 /*Check the program status. */
302 if((error_counter == 0) && (data_packet_counter == 1) && (rst_counter == 2))
303 {
304 printf("SUCCESS!\n");
305 test_control_return(0);
306 }
307 else
308 {
309 printf("ERROR!\n");
310 test_control_return(1);
311 }
312 }
313
ntest_0_connect_received(NX_TCP_SOCKET * socket_ptr,UINT port)314 static void ntest_0_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port)
315 {
316
317 /* Check for the proper socket and port. */
318 if((socket_ptr != &server_socket) || (port != 12))
319 error_counter++;
320 }
321
ntest_0_disconnect_received(NX_TCP_SOCKET * socket)322 static void ntest_0_disconnect_received(NX_TCP_SOCKET *socket)
323 {
324
325 /* Check for proper disconnected socket. */
326 if(socket != &server_socket)
327 error_counter++;
328 }
329
my_packet_process_8_02(NX_IP * ip_ptr,NX_PACKET * packet_ptr,UINT * operation_ptr,UINT * delay_ptr)330 static UINT my_packet_process_8_02(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT *operation_ptr, UINT *delay_ptr)
331 {
332
333 NX_TCP_HEADER *tcp_header_ptr;
334
335 if(packet_ptr -> nx_packet_length < 40)
336 return NX_TRUE;
337
338 /* Point to the TCP header */
339 tcp_header_ptr = (NX_TCP_HEADER *)((packet_ptr -> nx_packet_prepend_ptr) + 20);
340
341 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
342
343 if (tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_RST_BIT)
344 {
345 *operation_ptr = NX_RAMDRIVER_OP_DROP;
346 rst_counter++;
347
348 advanced_packet_process_callback = NULL;
349 }
350
351 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
352
353 return NX_TRUE;
354 }
355
my_tcp_packet_receive_8_02(NX_IP * ip_ptr,NX_PACKET * packet_ptr)356 static void my_tcp_packet_receive_8_02(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
357 {
358
359 NX_TCP_HEADER *tcp_header_ptr;
360
361 tcp_header_ptr = (NX_TCP_HEADER *)packet_ptr->nx_packet_prepend_ptr;
362
363 if ((packet_ptr -> nx_packet_length - 20 == 20) && !memcmp(packet_ptr -> nx_packet_prepend_ptr + 20, MSG, 20))
364 {
365 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
366
367 if ((tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_ACK_BIT) && !(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT) && !(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_RST_BIT))
368 {
369 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_acknowledgment_number);
370 ack_segment = tcp_header_ptr -> nx_tcp_acknowledgment_number;
371 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_acknowledgment_number);
372
373 data_packet_counter++;
374 }
375
376 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
377
378 /* Deal packets with default routing. */
379 ip_0.nx_ip_tcp_packet_receive = _nx_tcp_packet_receive;
380
381 }
382
383 /* Let server receives the packet. */
384 _nx_tcp_packet_receive(ip_ptr, packet_ptr);
385 }
386
my_tcp_packet_receive_8_02_2(NX_IP * ip_ptr,NX_PACKET * packet_ptr)387 static void my_tcp_packet_receive_8_02_2(NX_IP *ip_ptr, NX_PACKET *packet_ptr)
388 {
389
390 NX_TCP_HEADER *tcp_header_ptr;
391
392 tcp_header_ptr = (NX_TCP_HEADER*)packet_ptr->nx_packet_prepend_ptr;
393 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
394
395 if (tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_RST_BIT)
396 {
397
398 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_sequence_number);
399
400 if (tcp_header_ptr -> nx_tcp_sequence_number == ack_segment)
401 rst_counter++;
402
403 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_sequence_number);
404
405 ip_1.nx_ip_tcp_packet_receive = _nx_tcp_packet_receive;
406 }
407
408 NX_CHANGE_ULONG_ENDIAN(tcp_header_ptr -> nx_tcp_header_word_3);
409
410 /* Let server receives the packet. */
411 _nx_tcp_packet_receive(ip_ptr, packet_ptr);
412 }
413
414 #else
415
416 #ifdef CTEST
test_application_define(void * first_unused_memory)417 VOID test_application_define(void *first_unused_memory)
418 #else
419 void netx_8_02_application_define(void *first_unused_memory)
420 #endif
421 {
422
423 /* Print out test information banner. */
424 printf("NetX Test: TCP Spec 8.02 Test........................................N/A\n");
425 test_control_return(3);
426
427 }
428 #endif
429