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