1 /* This NetX test concentrates on the basic BSD TCP blocking operation. */
2 /* The BSD APIs involved in this test are: socket(), connect(), send(), soc_close() */
3
4 #include "tx_api.h"
5 #include "nx_api.h"
6 #if defined(NX_BSD_ENABLE) && !defined(NX_DISABLE_IPV4)
7 #include "nx_icmpv6.h"
8 #include "nxd_bsd.h"
9 #define DEMO_STACK_SIZE 4096
10
11
12 /* Define the ThreadX and NetX object control blocks... */
13
14 static TX_THREAD ntest_0;
15 static TX_THREAD ntest_1;
16
17 static NX_PACKET_POOL pool_0;
18 static NX_IP ip_0;
19 static NX_IP ip_1;
20 static ULONG bsd_thread_area[DEMO_STACK_SIZE / sizeof(ULONG)];
21 static TX_SEMAPHORE sema_0;
22 static TX_SEMAPHORE sema_1;
23 static TX_SEMAPHORE sema_2;
24 #define BSD_THREAD_PRIORITY 2
25 #define NUM_CLIENTS NX_BSD_MAX_SOCKETS
26 /* Define the counters used in the test application... */
27
28 static ULONG error_counter;
29 static ULONG packet_pool_area[(256 + sizeof(NX_PACKET)) * (NUM_CLIENTS + 4) * 8 / 4];
30
31 /* Define thread prototypes. */
32
33 static void ntest_0_entry(ULONG thread_input);
34 static void ntest_1_entry(ULONG thread_input);
35 extern void test_control_return(UINT status);
36 extern void _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
37 static void validate_bsd_structure(void);
38 extern NX_BSD_SOCKET nx_bsd_socket_array[NX_BSD_MAX_SOCKETS];
39 static char *requests[4] = {"Request1", "Request2", "Request3", "Request4"};
40 static char *response[4] = {"Response1", "Response2", "Response3", "Response4"};
41 static void validate_bsd_structure(void);
42 /* Define what the initial system looks like. */
43
44 #ifdef CTEST
test_application_define(void * first_unused_memory)45 VOID test_application_define(void *first_unused_memory)
46 #else
47 void netx_bsd_tcp_accept_blocking_timeout_test_application_define(void *first_unused_memory)
48 #endif
49 {
50
51 CHAR *pointer;
52 UINT status;
53
54
55 /* Setup the working pointer. */
56 pointer = (CHAR *) first_unused_memory;
57
58 error_counter = 0;
59
60 /* Create the main thread. */
61 tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
62 pointer, DEMO_STACK_SIZE,
63 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
64
65 pointer = pointer + DEMO_STACK_SIZE;
66
67 /* Create the main thread. */
68 tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
69 pointer, DEMO_STACK_SIZE,
70 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
71
72 pointer = pointer + DEMO_STACK_SIZE;
73
74
75 /* Initialize the NetX system. */
76 nx_system_initialize();
77
78 /* Create a packet pool. */
79 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, packet_pool_area, sizeof(packet_pool_area));
80
81
82 if (status)
83 error_counter++;
84
85 /* Create an IP instance. */
86 status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
87 pointer, 2048, 1);
88 pointer = pointer + 2048;
89
90 /* Create another IP instance. */
91 status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
92 pointer, 2048, 1);
93 pointer = pointer + 2048;
94 if (status)
95 error_counter++;
96
97 /* Enable ARP and supply ARP cache memory for IP Instance 0. */
98 status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
99 pointer = pointer + 1024;
100 if (status)
101 error_counter++;
102
103 /* Enable ARP and supply ARP cache memory for IP Instance 1. */
104 status = nx_arp_enable(&ip_1, (void *) pointer, 1024);
105 pointer = pointer + 1024;
106 if (status)
107 error_counter++;
108
109 /* Enable TCP processing for both IP instances. */
110 status = nx_tcp_enable(&ip_0);
111 status += nx_tcp_enable(&ip_1);
112
113 /* Enable BSD */
114 status += bsd_initialize(&ip_0, &pool_0, (CHAR*)&bsd_thread_area[0], sizeof(bsd_thread_area), BSD_THREAD_PRIORITY);
115
116 /* Check TCP enable status. */
117 if (status)
118 error_counter++;
119
120 status = tx_semaphore_create(&sema_0, "SEMA 0", 0);
121 status += tx_semaphore_create(&sema_1, "SEMA 1", 0);
122 status += tx_semaphore_create(&sema_2, "SEMA 2", 0);
123 if(status)
124 error_counter++;
125 }
126 typedef struct client_info_struct
127 {
128 int sockfd;
129 int message_id;
130 } client_info;
131
132 static client_info client_data[NUM_CLIENTS];
133 static ULONG stack_space[NUM_CLIENTS][DEMO_STACK_SIZE / sizeof(ULONG)];
134 static TX_THREAD helper_thread[NUM_CLIENTS];
135
bsd_server_helper_thread_entry(ULONG thread_input)136 static VOID bsd_server_helper_thread_entry(ULONG thread_input)
137 {
138 int ret;
139 int sockfd, message_id;
140 char buf[30];
141
142 sockfd = client_data[thread_input].sockfd;
143 message_id = client_data[thread_input].message_id;
144 /* Receive data from the client. */
145 ret = recv(sockfd, buf, sizeof(buf), 0);
146 if(ret <= 0)
147 error_counter++;
148
149 /* Validate the data. */
150 if((ret != (int)strlen(requests[message_id & 3])) || strncmp(buf, requests[message_id & 3], ret))
151 error_counter++;
152
153 /* Send a response back. */
154 ret = send(sockfd, response[message_id & 3], strlen(response[message_id & 3]), 0);
155 if(ret != (int)strlen(response[message_id & 3]))
156 error_counter++;
157
158 /* Wait until client received. */
159 if((sockfd - NX_BSD_SOCKFD_START + 1) != (NUM_CLIENTS / 2))
160 tx_semaphore_get(&sema_1, 5 * NX_IP_PERIODIC_RATE);
161 else
162 tx_semaphore_get(&sema_2, 5 * NX_IP_PERIODIC_RATE);
163
164 ret = soc_close(sockfd);
165 if(ret < 0)
166 error_counter++;
167
168 tx_semaphore_put(&sema_0);
169 return;
170 }
171
172
173
test_tcp_server4(void)174 static void test_tcp_server4(void)
175 {
176 int sockfd;
177 struct sockaddr_in remote_addr, local_addr;
178 int address_length;
179 int ret;
180 int newsock;
181 int i;
182 UINT status;
183 int accept_no_memory = 0;
184
185
186
187 sockfd = socket(AF_INET, SOCK_STREAM, 0);
188 if(sockfd < 0)
189 error_counter++;
190
191 local_addr.sin_family = AF_INET;
192 local_addr.sin_port = htons(12345);
193 local_addr.sin_addr.s_addr = INADDR_ANY;
194
195 ret = bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
196 if(ret < 0)
197 error_counter++;
198
199 ret = listen(sockfd, 5);
200 if(ret < 0)
201 error_counter++;
202
203 /* 3 iterations. */
204 for(i = 0; i < NUM_CLIENTS; i++)
205 {
206 address_length = sizeof(remote_addr);
207
208 newsock = accept(sockfd, (struct sockaddr*)&remote_addr, &address_length);
209
210 if(newsock <= 0)
211 {
212 if(i != (NUM_CLIENTS - 1))
213 error_counter++;
214 else
215 {
216 if(errno != ENOMEM)
217 error_counter++;
218 else
219 {
220 accept_no_memory = 1;
221 tx_thread_sleep(10);
222 i--;
223 continue;
224 }
225 }
226 }
227 else if(address_length != sizeof(remote_addr))
228 error_counter++;
229 else if((remote_addr.sin_family != AF_INET) || (remote_addr.sin_addr.s_addr != htonl(0x01020305)))
230 error_counter++;
231
232
233 /* Set the client data */
234 client_data[i].sockfd = newsock;
235 client_data[i].message_id = i;
236
237 /* Create a helper thread to handle the new socket. */
238 status = tx_thread_create(&helper_thread[i], "helper thread", bsd_server_helper_thread_entry,
239 i, stack_space[i], DEMO_STACK_SIZE, 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
240 if(status != TX_SUCCESS)
241 error_counter++;
242
243
244 tx_thread_relinquish();
245 }
246
247 if(accept_no_memory != 1)
248 error_counter++;
249
250 /* Close downt he socket. */
251 ret = soc_close(sockfd);
252 if(ret < 0)
253 error_counter++;
254
255 for(i = 0; i < NUM_CLIENTS; i++)
256 {
257
258 /* Wakeup server thread. */
259 tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
260 }
261 }
262
263
264 /* Define the test threads. */
ntest_0_entry(ULONG thread_input)265 static void ntest_0_entry(ULONG thread_input)
266 {
267
268 printf("NetX Test: Basic BSD TCP Accept Blocking Timeout Test....");
269
270 /* Check for earlier error. */
271 if (error_counter)
272 {
273
274 printf("ERROR!\n");
275 test_control_return(1);
276 }
277
278 /* Wakeup client. */
279 tx_semaphore_put(&sema_1);
280
281 test_tcp_server4();
282
283 /* Wait until client finish. */
284 tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
285
286 validate_bsd_structure();
287
288 if(error_counter)
289 printf("ERROR!\n");
290 else
291 printf("SUCCESS!\n");
292
293 if(error_counter)
294 test_control_return(1);
295
296 test_control_return(0);
297 }
298
299 static NX_TCP_SOCKET tcp_sockets[NUM_CLIENTS];
multiple_client4(void)300 static void multiple_client4(void)
301 {
302
303 int i;
304 UINT status = NX_SUCCESS;
305 NX_PACKET *packet_ptr;
306 for(i = 0; i < NUM_CLIENTS; i++)
307 {
308 status += nx_tcp_socket_create(&ip_1, &tcp_sockets[i], "Server Socket",
309 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 100,
310 NX_NULL, NX_NULL);
311 status += nx_tcp_client_socket_bind(&tcp_sockets[i], NX_ANY_PORT, 0);
312 }
313 if(status != NX_SUCCESS)
314 error_counter++;
315
316 status = NX_SUCCESS;
317 for(i = 0; i < (NUM_CLIENTS - 1); i++)
318 {
319 status += nx_tcp_client_socket_connect(&tcp_sockets[i], IP_ADDRESS(1, 2, 3, 4), 12345, NX_IP_PERIODIC_RATE);
320
321 }
322 if(status != NX_SUCCESS)
323 error_counter++;
324
325 /* Now we should be able to try another connection */
326 status = nx_tcp_client_socket_connect(&tcp_sockets[NUM_CLIENTS - 1], IP_ADDRESS(1, 2, 3, 4), 12345, NX_IP_PERIODIC_RATE);
327 if(status == NX_SUCCESS)
328 {
329 /* At this point, we anticpate the BSD system to run out of resource and is unable to make
330 this connection. */
331 error_counter++;
332 }
333 else
334 {
335 /* Let's delete the socket. */
336 if(tcp_sockets[NUM_CLIENTS - 1].nx_tcp_socket_bound_next)
337 {
338 status = nx_tcp_client_socket_unbind(&tcp_sockets[NUM_CLIENTS - 1]);
339 if(status)
340 error_counter++;
341 }
342
343 status = nx_tcp_socket_delete(&tcp_sockets[NUM_CLIENTS - 1]);
344
345 /* Recreate the socket. */
346 status += nx_tcp_socket_create(&ip_1, &tcp_sockets[NUM_CLIENTS - 1], "Server Socket",
347 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 100,
348 NX_NULL, NX_NULL);
349 status += nx_tcp_client_socket_bind(&tcp_sockets[NUM_CLIENTS - 1], NX_ANY_PORT, 0);
350 if(status)
351 error_counter++;
352 }
353
354 status = NX_SUCCESS;
355
356 /* Send messages to each server */
357 for(i = 0; i < (NUM_CLIENTS - 1); i++)
358 {
359 status += nx_packet_allocate(&pool_0, &packet_ptr, NX_TCP_PACKET, NX_NO_WAIT);
360 status += nx_packet_data_append(packet_ptr, requests[i & 3], strlen(requests[i & 3]),
361 &pool_0, NX_NO_WAIT);
362 status += nx_tcp_socket_send(&tcp_sockets[i], packet_ptr, NX_IP_PERIODIC_RATE);
363
364 }
365
366 if(status != NX_SUCCESS)
367 error_counter++;
368
369 status = NX_SUCCESS;
370
371 /* Receive messages. */
372
373 for(i = 0; i < NUM_CLIENTS - 1; i++)
374 {
375 status = nx_tcp_socket_receive(&tcp_sockets[i], &packet_ptr, 2 * NX_IP_PERIODIC_RATE);
376 if(status != NX_SUCCESS)
377 {
378 error_counter++;
379 continue;
380 }
381
382 /* Validate the received data. */
383 else if(packet_ptr -> nx_packet_length != strlen(response[i & 3]))
384 error_counter++;
385 else if(strncmp((char*)packet_ptr -> nx_packet_prepend_ptr, response[i & 3], packet_ptr -> nx_packet_length))
386 error_counter++;
387 nx_packet_release(packet_ptr);
388 }
389
390 /* Wakeup server thread. */
391 tx_semaphore_put(&sema_2);
392
393 /* Shutdown one socket (the one in the middle of the group. */
394 status = nx_tcp_socket_disconnect(&tcp_sockets[NUM_CLIENTS/2], NX_IP_PERIODIC_RATE);
395 if(status == NX_NOT_CONNECTED || status == NX_DISCONNECT_FAILED)
396 status = 0;
397
398 if(tcp_sockets[NUM_CLIENTS/2].nx_tcp_socket_bound_next)
399 status += nx_tcp_client_socket_unbind(&tcp_sockets[NUM_CLIENTS/2]);
400
401 status += nx_tcp_socket_delete(&tcp_sockets[NUM_CLIENTS/2]);
402 if(status != NX_SUCCESS)
403 error_counter++;
404
405 /* Now we should be able to try another connection */
406 status = nx_tcp_client_socket_connect(&tcp_sockets[NUM_CLIENTS - 1], IP_ADDRESS(1, 2, 3, 4), 12345, NX_IP_PERIODIC_RATE);
407 if(status != NX_SUCCESS)
408 {
409 /* At this point, we anticpate the BSD system to run out of resource and is unable to make
410 this connection. */
411 error_counter++;
412 }
413
414 status = nx_packet_allocate(&pool_0, &packet_ptr, NX_TCP_PACKET, NX_NO_WAIT);
415 status += nx_packet_data_append(packet_ptr, requests[(NUM_CLIENTS - 1) & 3], strlen(requests[(NUM_CLIENTS - 1) & 3]),
416 &pool_0, NX_NO_WAIT);
417 status += nx_tcp_socket_send(&tcp_sockets[NUM_CLIENTS - 1], packet_ptr, NX_IP_PERIODIC_RATE);
418 if(status != NX_SUCCESS)
419 error_counter++;
420
421 status = nx_tcp_socket_receive(&tcp_sockets[NUM_CLIENTS - 1], &packet_ptr, 2 * NX_IP_PERIODIC_RATE);
422 if(status != NX_SUCCESS)
423 error_counter++;
424 /* Validate the received data. */
425 else if(packet_ptr -> nx_packet_length != strlen(response[(NUM_CLIENTS - 1) & 3]))
426 error_counter++;
427 else if(strncmp((char*)packet_ptr -> nx_packet_prepend_ptr, response[(NUM_CLIENTS - 1) & 3], packet_ptr -> nx_packet_length))
428 error_counter++;
429 if(status == NX_SUCCESS)
430 nx_packet_release(packet_ptr);
431
432 /* Wakeup server thread. */
433 for(i = 0; i < NUM_CLIENTS - 2; i++)
434 {
435
436 /* Wakeup server thread. */
437 tx_semaphore_put(&sema_1);
438 }
439 tx_semaphore_put(&sema_2);
440
441
442 /* Shutdown the socket. */
443 for(i = 0; i < NUM_CLIENTS; i++)
444 {
445 if(i == NUM_CLIENTS / 2)
446 continue;
447
448 status = nx_tcp_socket_disconnect(&tcp_sockets[i], 1 * NX_IP_PERIODIC_RATE);
449 if(status == NX_NOT_CONNECTED || status == NX_DISCONNECT_FAILED)
450 status = 0;
451
452 if(tcp_sockets[i].nx_tcp_socket_bound_next)
453 status += nx_tcp_client_socket_unbind(&tcp_sockets[i]);
454
455
456 status += nx_tcp_socket_delete(&tcp_sockets[i]);
457
458 if(status != NX_SUCCESS)
459 error_counter++;
460 }
461 }
462
463
ntest_1_entry(ULONG thread_input)464 static void ntest_1_entry(ULONG thread_input)
465 {
466
467 UINT status;
468 ULONG actual_status;
469
470
471
472 /* Ensure the IP instance has been initialized. */
473 status = nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status, 1 * NX_IP_PERIODIC_RATE);
474
475 /* Check status... */
476 if (status != NX_SUCCESS)
477 {
478
479 printf("ERROR!\n");
480 test_control_return(3);
481 }
482
483 /* Server run first. */
484 tx_semaphore_get(&sema_1, 5 * NX_IP_PERIODIC_RATE);
485
486 /* Simulate a multiple client conneting to the same server. */
487 multiple_client4();
488
489 /* Client finished. */
490 tx_semaphore_put(&sema_0);
491 }
492
493
494 extern TX_BLOCK_POOL nx_bsd_socket_block_pool;
validate_bsd_structure(void)495 static void validate_bsd_structure(void)
496 {
497 int i;
498 /* Make sure every BSD socket should be free by now. */
499
500 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
501 {
502 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)
503 {
504 error_counter++;
505 }
506
507 if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket ||
508 nx_bsd_socket_array[i].nx_bsd_socket_udp_socket)
509 {
510 error_counter++;
511 }
512 }
513
514 /* Make sure all the NX SOCKET control blocks are released. */
515 if(nx_bsd_socket_block_pool.tx_block_pool_available !=
516 nx_bsd_socket_block_pool.tx_block_pool_total)
517 {
518 error_counter++;
519 }
520
521 /* Make sure all the sockets are released */
522 if(ip_0.nx_ip_tcp_created_sockets_ptr ||
523 ip_0.nx_ip_udp_created_sockets_ptr)
524 {
525 error_counter++;
526 return;
527 }
528 }
529
530 #else
531 extern void test_control_return(UINT status);
532
533 #ifdef CTEST
test_application_define(void * first_unused_memory)534 VOID test_application_define(void *first_unused_memory)
535 #else
536 void netx_bsd_tcp_accept_blocking_timeout_test_application_define(void *first_unused_memory)
537 #endif
538 {
539
540 /* Print out test information banner. */
541 printf("NetX Test: Basic BSD TCP Accept Blocking Timeout Test....N/A\n");
542
543 test_control_return(3);
544 }
545 #endif
546