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 NX_TCP_SOCKET           server_socket;
21 static ULONG                   bsd_thread_area[DEMO_STACK_SIZE / sizeof(ULONG)];
22 static TX_SEMAPHORE            sema_0;
23 static TX_SEMAPHORE            sema_1;
24 #define BSD_THREAD_PRIORITY    2
25 #define NUM_CLIENTS            10
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 #ifdef FEATURE_NX_IPV6
40 static NXD_ADDRESS ipv6_address_ip0;
41 static NXD_ADDRESS ipv6_address_ip1;
42 #endif
43 static char *send_buffer = "Hello World";
44 static char *requests[4] = {"Request1", "Request2", "Request3", "Request4"};
45 static char *response[4] = {"Response1", "Response2", "Response3", "Response4"};
46 static void validate_bsd_structure(void);
47 #ifdef __PRODUCT_NETXDUO__
48 static char large_msg[1000];
49 #endif
50 /* Define what the initial system looks like.  */
51 
52 #ifdef CTEST
test_application_define(void * first_unused_memory)53 VOID test_application_define(void *first_unused_memory)
54 #else
55 void    netx_bsd_tcp_basic_blocking_test_application_define(void *first_unused_memory)
56 #endif
57 {
58 
59 CHAR    *pointer;
60 UINT    status;
61 
62 
63     /* Setup the working pointer.  */
64     pointer =  (CHAR *) first_unused_memory;
65 
66     error_counter =  0;
67 
68     /* Create the main thread.  */
69     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
70                      pointer, DEMO_STACK_SIZE,
71                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
72 
73     pointer =  pointer + DEMO_STACK_SIZE;
74 
75     /* Create the main thread.  */
76     tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
77                      pointer, DEMO_STACK_SIZE,
78                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
79 
80     pointer =  pointer + DEMO_STACK_SIZE;
81 
82 
83     /* Initialize the NetX system.  */
84     nx_system_initialize();
85 
86     /* Create a packet pool.  */
87     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256, packet_pool_area, sizeof(packet_pool_area));
88 
89 
90     if (status)
91         error_counter++;
92 
93     /* Create an IP instance.  */
94     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
95                     pointer, 2048, 1);
96     pointer =  pointer + 2048;
97 
98     /* Create another IP instance.  */
99     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver_256,
100                     pointer, 2048, 1);
101     pointer =  pointer + 2048;
102     if (status)
103         error_counter++;
104 
105     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
106     status =  nx_arp_enable(&ip_0, (void *) pointer, 1024);
107     pointer = pointer + 1024;
108     if (status)
109         error_counter++;
110 
111     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
112     status  =  nx_arp_enable(&ip_1, (void *) pointer, 1024);
113     pointer = pointer + 1024;
114     if (status)
115         error_counter++;
116 
117     /* Enable TCP processing for both IP instances.  */
118     status =  nx_tcp_enable(&ip_0);
119     status += nx_tcp_enable(&ip_1);
120 
121     /* Enable BSD */
122     status += bsd_initialize(&ip_0, &pool_0, (CHAR*)&bsd_thread_area[0], sizeof(bsd_thread_area), BSD_THREAD_PRIORITY);
123 
124     /* Check TCP enable status.  */
125     if (status)
126         error_counter++;
127 
128     status = tx_semaphore_create(&sema_0, "SEMA 0", 0);
129     status += tx_semaphore_create(&sema_1, "SEMA 1", 0);
130     if(status)
131         error_counter++;
132 }
133 typedef struct client_info_struct
134 {
135     int sockfd;
136     int message_id;
137 } client_info;
138 
139 static client_info client_data[NUM_CLIENTS];
140 static ULONG stack_space[NUM_CLIENTS][DEMO_STACK_SIZE / sizeof(ULONG)];
141 static TX_THREAD helper_thread[NUM_CLIENTS];
142 #ifdef FEATURE_NX_IPV6
143 static ULONG stack_space6[NUM_CLIENTS][DEMO_STACK_SIZE / sizeof(ULONG)];
144 static TX_THREAD helper_thread6[NUM_CLIENTS];
145 #endif
bsd_server_helper_thread_entry(ULONG thread_input)146 static VOID bsd_server_helper_thread_entry(ULONG thread_input)
147 {
148 int         ret;
149 int         sockfd, message_id;
150 char        buf[30];
151 int         sockaddr_len;
152 fd_set      read_fds, write_fds, except_fds;
153 struct timeval wait_time;
154 #ifdef FEATURE_NX_IPV6
155 struct sockaddr_in6 remote_address;
156 #else
157 struct sockaddr_in remote_address;
158 #endif
159 
160     sockfd = client_data[thread_input].sockfd;
161     message_id = client_data[thread_input].message_id;
162     /* Receive data from the client. */
163     if(message_id == 2)
164     {
165 #ifdef FEATURE_NX_IPV6
166         sockaddr_len = sizeof(struct sockaddr_in6);
167 #else
168         sockaddr_len = sizeof(struct sockaddr_in);
169 #endif
170         ret = recvfrom(sockfd, (char*)buf, sizeof(buf), 0, (struct sockaddr*)&remote_address, &sockaddr_len);
171 
172         if(ret < 0)
173             error_counter++;
174         if(nx_bsd_socket_array[sockfd - 0x20].nx_bsd_socket_family == AF_INET)
175         {
176             if(sockaddr_len != sizeof(struct sockaddr_in))
177                 error_counter++;
178             if(((struct sockaddr_in*)&remote_address) -> sin_family != AF_INET)
179                 error_counter++;
180             if(((struct sockaddr_in*)&remote_address) -> sin_addr.s_addr != htonl(0x01020305))
181                 error_counter++;
182         }
183 #ifdef FEATURE_NX_IPV6
184         else if(nx_bsd_socket_array[sockfd - 0x20].nx_bsd_socket_family == AF_INET6)
185         {
186             if(sockaddr_len != sizeof(struct sockaddr_in6))
187                 error_counter++;
188             if((remote_address.sin6_addr._S6_un._S6_u32[0] != htonl(ipv6_address_ip1.nxd_ip_address.v6[0])) ||
189                (remote_address.sin6_addr._S6_un._S6_u32[1] != htonl(ipv6_address_ip1.nxd_ip_address.v6[1])) ||
190                (remote_address.sin6_addr._S6_un._S6_u32[2] != htonl(ipv6_address_ip1.nxd_ip_address.v6[2])) ||
191                (remote_address.sin6_addr._S6_un._S6_u32[3] != htonl(ipv6_address_ip1.nxd_ip_address.v6[3])))
192                 error_counter++;
193         }
194 #endif
195     }
196     else
197     {
198 
199         /* Peek message test. */
200         ret = recv(sockfd, buf, sizeof(buf), MSG_PEEK);
201 
202         /* Validate the data. */
203         if((ret != (int)strlen(requests[message_id & 3])) || strncmp(buf, requests[message_id & 3], ret))
204             error_counter++;
205 
206         ret = recv(sockfd, buf, sizeof(buf), 0);
207     }
208     if(ret <= 0)
209         error_counter++;
210 
211     /* Validate the data. */
212     if((ret != (int)strlen(requests[message_id & 3])) || strncmp(buf, requests[message_id & 3], ret))
213         error_counter++;
214 
215     /* Invoke recvfrom with MSG_DONTWAIT flag. */
216     ret = recvfrom(sockfd, (char*)buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr*)&remote_address, &sockaddr_len);
217     if(ret >= 0)
218         error_counter++;
219     else if((errno != EWOULDBLOCK) || (errno != EAGAIN))
220         error_counter++;
221 
222     /* Invoke recv with MSG_DONTWAIT flag. */
223     ret = recv(sockfd, (char*)buf, sizeof(buf), MSG_DONTWAIT);
224     if(ret >= 0)
225         error_counter++;
226     else if((errno != EWOULDBLOCK) || (errno != EAGAIN))
227         error_counter++;
228 
229     /* Send a response back. */
230     ret = send(sockfd, response[message_id & 3], strlen(response[message_id & 3]), 0);
231     if(ret != (int)strlen(response[message_id & 3]))
232         error_counter++;
233 
234     tx_semaphore_get(&sema_1, 5 * NX_IP_PERIODIC_RATE);
235 
236 #ifdef __PRODUCT_NETXDUO__
237     /* Invoke send with MSG_DONTWAIT flag. The message is larger than tx_window. Partial data should be sent. */
238     ret = send(sockfd, large_msg, sizeof(large_msg), MSG_DONTWAIT);
239     if (ret <= 0)
240         error_counter++;
241 #endif
242 
243     FD_ZERO(&read_fds);
244     FD_ZERO(&write_fds);
245     FD_ZERO(&except_fds);
246     FD_SET(sockfd, &read_fds);
247     FD_SET(sockfd, &write_fds);
248     FD_SET(sockfd, &except_fds);
249 
250     ret = soc_close(sockfd);
251     if(ret < 0)
252         error_counter++;
253 
254     wait_time.tv_sec = 1;
255     wait_time.tv_usec = 0;
256     select(sockfd + 1, &read_fds, &write_fds, &except_fds, &wait_time);
257     if((FD_ISSET(sockfd, &read_fds) && FD_ISSET(sockfd, &write_fds) && FD_ISSET(sockfd, &except_fds)) == 0)
258         error_counter++;
259 
260     tx_semaphore_put(&sema_0);
261     return;
262 }
263 
264 
test_tcp_client4(void)265 static void test_tcp_client4(void)
266 {
267 int sockfd;
268 struct sockaddr_in remote_addr, local_addr;
269 #ifdef FEATURE_NX_IPV6
270 struct sockaddr_in6 local_addr6;
271 int port;
272 int sockfd1;
273 #endif
274 int bytes_sent;
275 int ret;
276 char buf;
277 
278     sockfd = socket(AF_INET, SOCK_STREAM, 0);
279     if(sockfd < 0)
280         error_counter++;
281 
282     local_addr.sin_family = AF_INET;
283     local_addr.sin_port = INADDR_ANY;
284     local_addr.sin_addr.s_addr = INADDR_ANY;
285 
286     ret = bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
287     if(ret < 0)
288         error_counter++;
289 
290     remote_addr.sin_family = AF_INET;
291     remote_addr.sin_port = htons(12);
292     remote_addr.sin_addr.s_addr = htonl(0x01020305);
293 
294     if(connect(sockfd, (struct sockaddr*)&remote_addr, sizeof(remote_addr)) < 0)
295         error_counter++;
296 
297     bytes_sent = send(sockfd, send_buffer, strlen(send_buffer), 0);
298 
299     if(bytes_sent != (int)strlen(send_buffer))
300         error_counter++;
301 
302 #ifdef FEATURE_NX_IPV6
303     /* Get the port bind to any. */
304     port = nx_bsd_socket_array[sockfd - NX_BSD_SOCKFD_START].nx_bsd_socket_tcp_socket -> nx_tcp_socket_port;
305 
306     sockfd1 = socket(AF_INET6, SOCK_STREAM, 0);
307     if(sockfd1 < 0)
308         error_counter++;
309 
310     memset(&local_addr6, 0, sizeof(local_addr6));
311     local_addr6.sin6_family = AF_INET6;
312     local_addr6.sin6_port = htons(port);
313 
314     /* Bind to the same port. */
315     ret = bind(sockfd1, (struct sockaddr*)&local_addr6, sizeof(local_addr6));
316     if(ret < 0)
317         error_counter++;
318 
319     ret = soc_close(sockfd1);
320     if(ret < 0)
321         error_counter++;
322 #endif
323 
324     /* Call recv before peer orderly shutdown. */
325     ret = recv(sockfd, &buf, 1, 0);
326     if (ret != 0)
327         error_counter++;
328 
329     /* Make sure the other side gets the message. */
330     tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
331 
332     /* Call recv after peer orderly shutdown. */
333     ret = recv(sockfd, &buf, 1, 0);
334     if (ret != 0)
335         error_counter++;
336 
337     ret = soc_close(sockfd);
338     if(ret < 0)
339         error_counter++;
340 
341 }
342 
test_tcp_server4(void)343 static void test_tcp_server4(void)
344 {
345 int                sockfd;
346 struct sockaddr_in remote_addr, local_addr;
347 int                address_length;
348 int                ret;
349 int                newsock;
350 int                i;
351 UINT               status;
352 
353 
354     sockfd = socket(AF_INET, SOCK_STREAM, 0);
355     if(sockfd < 0)
356         error_counter++;
357 
358     local_addr.sin_family = AF_INET;
359     local_addr.sin_port = htons(12345);
360     local_addr.sin_addr.s_addr = INADDR_ANY;
361 
362     ret = bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
363     if(ret < 0)
364         error_counter++;
365 
366     ret = listen(sockfd, 5);
367     if(ret < 0)
368         error_counter++;
369 
370     /* 3 iterations. */
371     for(i = 0; i < NUM_CLIENTS; i++)
372     {
373         address_length = sizeof(remote_addr);
374 
375         newsock = accept(sockfd, (struct sockaddr*)&remote_addr, &address_length);
376 
377         if(newsock <= 0)
378             error_counter++;
379         else if(address_length != sizeof(remote_addr))
380             error_counter++;
381         else if((remote_addr.sin_family != AF_INET) || (remote_addr.sin_addr.s_addr != htonl(0x01020305)))
382             error_counter++;
383 
384         address_length = sizeof(local_addr);
385         ret = getsockname(newsock, (struct sockaddr*)&local_addr, &address_length);
386         if(ret < 0)
387             error_counter++;
388         else if(address_length != sizeof(local_addr))
389             error_counter++;
390         else if(local_addr.sin_family != AF_INET)
391             error_counter++;
392         else if(local_addr.sin_port != htons(12345))
393             error_counter++;
394         else if(local_addr.sin_addr.s_addr != htonl(IP_ADDRESS(1, 2, 3, 4)))
395             error_counter++;
396 
397         address_length = sizeof(remote_addr);
398         ret = getpeername(newsock, (struct sockaddr*)&remote_addr, &address_length);
399         if(ret < 0)
400             error_counter++;
401         else if(address_length != sizeof(remote_addr))
402             error_counter++;
403         else if(remote_addr.sin_family != AF_INET)
404             error_counter++;
405         else if(remote_addr.sin_addr.s_addr != htonl(IP_ADDRESS(1,2,3,5)))
406             error_counter++;
407 
408 
409         /* Set the client data */
410         client_data[i].sockfd = newsock;
411         client_data[i].message_id = i;
412 
413         /* Create a helper thread to handle the new socket. */
414         status = tx_thread_create(&helper_thread[i], "helper thread", bsd_server_helper_thread_entry,
415                                   i, stack_space[i], DEMO_STACK_SIZE, 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
416         if(status != TX_SUCCESS)
417             error_counter++;
418 
419         tx_thread_relinquish();
420     }
421 
422     /* Close downt he socket. */
423     ret = soc_close(sockfd);
424     if(ret < 0)
425         error_counter++;
426 
427     for(i = 0; i < NUM_CLIENTS; i++)
428     {
429 
430         /* Wakeup server thread. */
431         tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
432     }
433 }
434 
435 
436 #ifdef FEATURE_NX_IPV6
test_tcp_client6(void)437 static void test_tcp_client6(void)
438 {
439 int                 sockfd;
440 struct sockaddr_in6 remote_addr;
441 int                 bytes_sent;
442 int                 ret;
443 
444     sockfd = socket(AF_INET6, SOCK_STREAM, 0);
445     if(sockfd < 0)
446         error_counter++;
447 
448 
449     remote_addr.sin6_family = AF_INET6;
450     remote_addr.sin6_port = htons(12);
451     remote_addr.sin6_addr._S6_un._S6_u32[0] = htonl(ipv6_address_ip1.nxd_ip_address.v6[0]);
452     remote_addr.sin6_addr._S6_un._S6_u32[1] = htonl(ipv6_address_ip1.nxd_ip_address.v6[1]);
453     remote_addr.sin6_addr._S6_un._S6_u32[2] = htonl(ipv6_address_ip1.nxd_ip_address.v6[2]);
454     remote_addr.sin6_addr._S6_un._S6_u32[3] = htonl(ipv6_address_ip1.nxd_ip_address.v6[3]);
455 
456     if(connect(sockfd, (struct sockaddr*)&remote_addr, sizeof(remote_addr)) < 0)
457         error_counter++;
458 
459     bytes_sent = send(sockfd, send_buffer, strlen(send_buffer), 0);
460 
461     if(bytes_sent != (INT)strlen(send_buffer))
462         error_counter++;
463 
464     /* Make sure the other side gets the message. */
465     tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
466 
467     ret = soc_close(sockfd);
468     if(ret < 0)
469         error_counter++;
470 
471 }
472 
test_tcp_server6(void)473 static void test_tcp_server6(void)
474 {
475 int                 sockfd;
476 struct sockaddr_in6 remote_addr, local_addr;
477 int                 address_length;
478 int                 ret;
479 int                 newsock;
480 int                 i;
481 UINT                status;
482 
483     sockfd = socket(AF_INET6, SOCK_STREAM, 0);
484     if(sockfd < 0)
485         error_counter++;
486 
487     memset(&local_addr, 0, sizeof(local_addr));
488     local_addr.sin6_family = AF_INET6;
489     local_addr.sin6_port = htons(12346);
490 
491 
492     ret = bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr));
493     if(ret < 0)
494         error_counter++;
495 
496     ret = listen(sockfd, 5);
497     if(ret < 0)
498         error_counter++;
499 
500     /* 3 iterations. */
501     for(i = 0; i < NUM_CLIENTS; i++)
502     {
503         address_length = sizeof(remote_addr);
504 
505         newsock = accept(sockfd, (struct sockaddr*)&remote_addr, &address_length);
506 
507         if(newsock <= 0)
508             error_counter++;
509 
510         if(address_length != sizeof(struct sockaddr_in6))
511             error_counter++;
512 
513         if((remote_addr.sin6_family != AF_INET6) ||
514            (remote_addr.sin6_addr._S6_un._S6_u32[0] != htonl(ipv6_address_ip1.nxd_ip_address.v6[0])) ||
515            (remote_addr.sin6_addr._S6_un._S6_u32[1] != htonl(ipv6_address_ip1.nxd_ip_address.v6[1])) ||
516            (remote_addr.sin6_addr._S6_un._S6_u32[2] != htonl(ipv6_address_ip1.nxd_ip_address.v6[2])) ||
517            (remote_addr.sin6_addr._S6_un._S6_u32[3] != htonl(ipv6_address_ip1.nxd_ip_address.v6[3])))
518             error_counter++;
519 
520         address_length = sizeof(local_addr);
521         ret = getsockname(newsock, (struct sockaddr*)&local_addr, &address_length);
522         if(ret < 0)
523             error_counter++;
524         else if(address_length != sizeof(local_addr))
525             error_counter++;
526         else if(local_addr.sin6_family != AF_INET6)
527             error_counter++;
528         else if(local_addr.sin6_port != htons(12346))
529             error_counter++;
530         else if((local_addr.sin6_addr._S6_un._S6_u32[0] != htonl(ipv6_address_ip0.nxd_ip_address.v6[0])) ||
531                 (local_addr.sin6_addr._S6_un._S6_u32[1] != htonl(ipv6_address_ip0.nxd_ip_address.v6[1])) ||
532                 (local_addr.sin6_addr._S6_un._S6_u32[2] != htonl(ipv6_address_ip0.nxd_ip_address.v6[2])) ||
533                 (local_addr.sin6_addr._S6_un._S6_u32[3] != htonl(ipv6_address_ip0.nxd_ip_address.v6[3])))
534             error_counter++;
535 
536         address_length = sizeof(remote_addr);
537         ret = getpeername(newsock, (struct sockaddr*)&remote_addr, &address_length);
538         if(ret < 0)
539             error_counter++;
540         else if(address_length != sizeof(remote_addr))
541             error_counter++;
542         else if(remote_addr.sin6_family != AF_INET6)
543             error_counter++;
544         else if((remote_addr.sin6_family != AF_INET6) ||
545                 (remote_addr.sin6_addr._S6_un._S6_u32[0] != htonl(ipv6_address_ip1.nxd_ip_address.v6[0])) ||
546                 (remote_addr.sin6_addr._S6_un._S6_u32[1] != htonl(ipv6_address_ip1.nxd_ip_address.v6[1])) ||
547                 (remote_addr.sin6_addr._S6_un._S6_u32[2] != htonl(ipv6_address_ip1.nxd_ip_address.v6[2])) ||
548                 (remote_addr.sin6_addr._S6_un._S6_u32[3] != htonl(ipv6_address_ip1.nxd_ip_address.v6[3])))
549             error_counter++;
550 
551 
552 
553         /* Set the client data */
554         client_data[i].sockfd = newsock;
555         client_data[i].message_id = i;
556 
557         /* Create a helper thread to handle the new socket. */
558         status = tx_thread_create(&helper_thread6[i], "helper thread", bsd_server_helper_thread_entry,
559                          i, stack_space6[i], DEMO_STACK_SIZE, 2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);
560         if(status)
561             error_counter++;
562 
563         tx_thread_relinquish();
564     }
565 
566     /* Close downt he socket. */
567     ret = soc_close(sockfd);
568     if(ret < 0)
569         error_counter++;
570 
571     for(i = 0; i < NUM_CLIENTS; i++)
572     {
573 
574         /* Wakeup server thread. */
575         tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
576     }
577 }
578 
579 #endif
580 
close_before_accept_test()581 static void    close_before_accept_test()
582 {
583 int     server_fd, client_fd;
584 int     ret;
585 struct  sockaddr_in remote_addr, local_addr;
586 
587     /* Setup server socket. */
588     server_fd = socket(AF_INET, SOCK_STREAM, 0);
589     if(server_fd < 0)
590         error_counter++;
591 
592     local_addr.sin_family = AF_INET;
593     local_addr.sin_port = htons(12345);
594     local_addr.sin_addr.s_addr = INADDR_ANY;
595 
596     ret = bind(server_fd, (struct sockaddr*)&local_addr, sizeof(local_addr));
597     if(ret < 0)
598         error_counter++;
599 
600     ret = listen(server_fd, 5);
601     if(ret < 0)
602         error_counter++;
603 
604     /* Setup client socket. */
605     client_fd = socket(AF_INET, SOCK_STREAM, 0);
606     if(client_fd < 0)
607         error_counter++;
608 
609     remote_addr.sin_family = AF_INET;
610     remote_addr.sin_port = htons(12345);
611     remote_addr.sin_addr.s_addr = htonl(0x01020304);
612 
613     if(connect(client_fd, (struct sockaddr*)&remote_addr, sizeof(remote_addr)) < 0)
614         error_counter++;
615 
616     /* Close before calling accept. */
617     soc_close(server_fd);
618     soc_close(client_fd);
619 }
620 
621 
622 /* Define the test threads.  */
ntest_0_entry(ULONG thread_input)623 static void    ntest_0_entry(ULONG thread_input)
624 {
625 int                sockfd;
626 struct sockaddr_in remote_addr;
627 #ifdef FEATURE_NX_IPV6
628 char mac_ip0[6];
629 char mac_ip1[6];
630 UINT status;
631 #endif
632 int                ret;
633 
634 
635     printf("NetX Test:   Basic BSD TCP Basic Blocking Test.............");
636 
637     /* Check for earlier error.  */
638     if (error_counter)
639     {
640 
641         printf("ERROR!\n");
642         test_control_return(1);
643     }
644 #ifdef FEATURE_NX_IPV6
645     /* First set up IPv6 addresses. */
646     ipv6_address_ip0.nxd_ip_version = NX_IP_VERSION_V6;
647     ipv6_address_ip0.nxd_ip_address.v6[0] = 0xfe800000;
648     ipv6_address_ip0.nxd_ip_address.v6[1] = 0x00000000;
649     ipv6_address_ip0.nxd_ip_address.v6[2] = 0x021122ff;
650     ipv6_address_ip0.nxd_ip_address.v6[3] = 0xfe334456;
651 
652     ipv6_address_ip1.nxd_ip_version = NX_IP_VERSION_V6;
653     ipv6_address_ip1.nxd_ip_address.v6[0] = 0xfe800000;
654     ipv6_address_ip1.nxd_ip_address.v6[1] = 0x00000000;
655     ipv6_address_ip1.nxd_ip_address.v6[2] = 0x021122ff;
656     ipv6_address_ip1.nxd_ip_address.v6[3] = 0xfe334457;
657 
658     status = nxd_ipv6_address_set(&ip_0, 0, &ipv6_address_ip0, 64, NX_NULL);
659     status += nxd_ipv6_address_set(&ip_1, 0, &ipv6_address_ip1, 64, NX_NULL);
660 
661     status += nxd_ipv6_enable(&ip_0);
662     status += nxd_ipv6_enable(&ip_1);
663 
664     mac_ip0[0] = (CHAR)(ip_0.nx_ip_interface[0].nx_interface_physical_address_msw >> 8);
665     mac_ip0[1] = ip_0.nx_ip_interface[0].nx_interface_physical_address_msw & 0xFF;
666     mac_ip0[2] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 24) & 0xff;
667     mac_ip0[3] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 16) & 0xff;
668     mac_ip0[4] = (ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw >> 8) & 0xff;
669     mac_ip0[5] = ip_0.nx_ip_interface[0].nx_interface_physical_address_lsw  & 0xff;
670 
671     mac_ip1[0] = (CHAR)(ip_1.nx_ip_interface[0].nx_interface_physical_address_msw >> 8);
672     mac_ip1[1] = ip_1.nx_ip_interface[0].nx_interface_physical_address_msw & 0xFF;
673     mac_ip1[2] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 24) & 0xff;
674     mac_ip1[3] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 16) & 0xff;
675     mac_ip1[4] = (ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw >> 8) & 0xff;
676     mac_ip1[5] = ip_1.nx_ip_interface[0].nx_interface_physical_address_lsw  & 0xff;
677 
678     status += nxd_nd_cache_entry_set(&ip_0, ipv6_address_ip1.nxd_ip_address.v6, 0,  mac_ip1);
679     status += nxd_nd_cache_entry_set(&ip_1, ipv6_address_ip0.nxd_ip_address.v6, 0,  mac_ip0);
680 
681     if(status)
682         error_counter++;
683 #endif
684 
685     close_before_accept_test();
686 
687     tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
688     test_tcp_client4();
689 
690     tx_semaphore_put(&sema_1);
691     test_tcp_server4();
692 
693 #ifdef FEATURE_NX_IPV6
694     tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
695     test_tcp_client6();
696 
697     tx_semaphore_put(&sema_1);
698     test_tcp_server6();
699 #endif
700 
701     tx_semaphore_get(&sema_0, 5 * NX_IP_PERIODIC_RATE);
702     /* Now open another socket and attempt to connect to the correct remote
703        host but an unexpected port so we expect an unsuccessful connections. */
704     sockfd = socket(AF_INET, SOCK_STREAM, 0);
705     if(sockfd < 0)
706         error_counter++;
707 
708     remote_addr.sin_family = AF_INET;
709     remote_addr.sin_port = htons(13);
710     remote_addr.sin_addr.s_addr = htonl(0x01020305);
711 
712     if(connect(sockfd, (struct sockaddr*)&remote_addr, sizeof(remote_addr)) >= 0)
713         error_counter++;
714     if(errno != ECONNREFUSED)
715         error_counter++;
716 
717     ret = soc_close(sockfd);
718     if(ret < 0)
719         error_counter++;
720 
721     /* Now open another socket and attempt to connect to the an incorrect
722        remote host so we expect an unsuccessful connections. */
723     sockfd = socket(AF_INET, SOCK_STREAM, 0);
724     if(sockfd < 0)
725         error_counter++;
726 
727 
728     remote_addr.sin_family = AF_INET;
729     remote_addr.sin_port = htons(13);
730     remote_addr.sin_addr.s_addr = htonl(0x01020306);
731 
732     if(connect(sockfd, (struct sockaddr*)&remote_addr, sizeof(remote_addr)) >= 0)
733         error_counter++;
734 
735     if(errno != ETIMEDOUT)
736         error_counter++;
737     ret = soc_close(sockfd);
738     if(ret < 0)
739         error_counter++;
740 
741     /* After the previous failed connection, make sure we can still open a socket. */
742     sockfd = socket(AF_INET, SOCK_STREAM, 0);
743     if(sockfd < 0)
744         error_counter++;
745 
746     ret = soc_close(sockfd);
747     if(ret < 0)
748         error_counter++;
749 
750     validate_bsd_structure();
751 
752     if(error_counter)
753         printf("ERROR!\n");
754     else
755         printf("SUCCESS!\n");
756 
757     if(error_counter)
758         test_control_return(1);
759 
760     test_control_return(0);
761 }
762 
763 static NX_TCP_SOCKET tcp_sockets[NUM_CLIENTS];
multiple_client4(void)764 static void    multiple_client4(void)
765 {
766 
767 int           i;
768 UINT          status = NX_SUCCESS;
769 NX_PACKET     *packet_ptr;
770     for(i = 0; i < NUM_CLIENTS; i++)
771     {
772         status +=  nx_tcp_socket_create(&ip_1, &tcp_sockets[i], "Server Socket",
773                                         NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 100,
774                                         NX_NULL, NX_NULL);
775         status +=  nx_tcp_client_socket_bind(&tcp_sockets[i], NX_ANY_PORT, 0);
776     }
777     if(status != NX_SUCCESS)
778         error_counter++;
779 
780     status = NX_SUCCESS;
781     for(i = 0; i < NUM_CLIENTS; i++)
782     {
783         status += nx_tcp_client_socket_connect(&tcp_sockets[i], IP_ADDRESS(1, 2, 3, 4), 12345, NX_IP_PERIODIC_RATE);
784 
785     }
786     if(status != NX_SUCCESS)
787         error_counter++;
788 
789     status = NX_SUCCESS;
790 
791     /* Send messages to each server */
792     for(i = 0; i < NUM_CLIENTS; i++)
793     {
794         status += nx_packet_allocate(&pool_0, &packet_ptr, NX_TCP_PACKET, NX_NO_WAIT);
795         status += nx_packet_data_append(packet_ptr, requests[i & 3], strlen(requests[i & 3]),
796                                         &pool_0, NX_NO_WAIT);
797         status += nx_tcp_socket_send(&tcp_sockets[i], packet_ptr, NX_IP_PERIODIC_RATE);
798 
799     }
800 
801     if(status != NX_SUCCESS)
802         error_counter++;
803 
804     status = NX_SUCCESS;
805     /* Receive 3 messages. */
806 
807     for(i = 0; i < NUM_CLIENTS; i++)
808     {
809         status = nx_tcp_socket_receive(&tcp_sockets[i], &packet_ptr, 2 * NX_IP_PERIODIC_RATE);
810         if(status != NX_SUCCESS)
811         {
812             error_counter++;
813             continue;
814         }
815 
816         /* Validate the received data. */
817         else if(packet_ptr -> nx_packet_length != strlen(response[i & 3]))
818             error_counter++;
819         else if(strncmp((char*)packet_ptr -> nx_packet_prepend_ptr, response[i & 3], packet_ptr -> nx_packet_length))
820             error_counter++;
821         nx_packet_release(packet_ptr);
822     }
823 
824     for(i = 0; i < NUM_CLIENTS; i++)
825     {
826 
827         /* Wakeup server thread. */
828         tx_semaphore_put(&sema_1);
829     }
830 
831     /* Shutdown the socket. */
832     for(i = 0; i < NUM_CLIENTS; i++)
833     {
834 
835         status = nx_tcp_socket_disconnect(&tcp_sockets[i], 1 * NX_IP_PERIODIC_RATE);
836         if(status == NX_NOT_CONNECTED || status == NX_DISCONNECT_FAILED)
837             status = 0;
838 
839         if(tcp_sockets[i].nx_tcp_socket_bound_next)
840             status += nx_tcp_client_socket_unbind(&tcp_sockets[i]);
841 
842 
843         status += nx_tcp_socket_delete(&tcp_sockets[i]);
844 
845         if(status != NX_SUCCESS)
846             error_counter++;
847     }
848 
849 
850 }
851 
852 
853 #ifdef FEATURE_NX_IPV6
multiple_client6(void)854 static void    multiple_client6(void)
855 {
856 
857 int           i;
858 UINT          status = NX_SUCCESS;
859 NX_PACKET     *packet_ptr;
860     for(i = 0; i < NUM_CLIENTS; i++)
861     {
862         status +=  nx_tcp_socket_create(&ip_1, &tcp_sockets[i], "Server Socket",
863                                         NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 100,
864                                         NX_NULL, NX_NULL);
865         status +=  nx_tcp_client_socket_bind(&tcp_sockets[i], NX_ANY_PORT, 0);
866     }
867     if(status != NX_SUCCESS)
868         error_counter++;
869 
870     status = NX_SUCCESS;
871     for(i = 0; i < NUM_CLIENTS; i++)
872     {
873         status += nxd_tcp_client_socket_connect(&tcp_sockets[i], &ipv6_address_ip0, 12346, NX_IP_PERIODIC_RATE);
874     }
875     if(status != NX_SUCCESS)
876         error_counter++;
877 
878     status = NX_SUCCESS;
879 
880     /* Send messages to each server */
881     for(i = 0; i < NUM_CLIENTS; i++)
882     {
883         status += nx_packet_allocate(&pool_0, &packet_ptr, NX_TCP_PACKET, NX_NO_WAIT);
884         status += nx_packet_data_append(packet_ptr, requests[i & 3], strlen(requests[i & 3]),
885                                         &pool_0, NX_NO_WAIT);
886         status += nx_tcp_socket_send(&tcp_sockets[i], packet_ptr, NX_IP_PERIODIC_RATE);
887 
888     }
889 
890     if(status != NX_SUCCESS)
891         error_counter++;
892 
893     status = NX_SUCCESS;
894     /* Receive 3 messages. */
895 
896     for(i = 0; i < NUM_CLIENTS; i++)
897     {
898         status = nx_tcp_socket_receive(&tcp_sockets[i], &packet_ptr, 2 * NX_IP_PERIODIC_RATE);
899         if(status != NX_SUCCESS)
900         {
901             error_counter++;
902             continue;
903         }
904 
905         /* Validate the received data. */
906         else if(packet_ptr -> nx_packet_length != strlen(response[i & 3]))
907             error_counter++;
908         else if(strncmp((char *)packet_ptr -> nx_packet_prepend_ptr, response[i & 3], packet_ptr -> nx_packet_length))
909             error_counter++;
910         nx_packet_release(packet_ptr);
911     }
912 
913     for(i = 0; i < NUM_CLIENTS; i++)
914     {
915 
916         /* Wakeup server thread. */
917         tx_semaphore_put(&sema_1);
918     }
919 
920     /* Shutdown the socket. */
921     for(i = 0; i < NUM_CLIENTS; i++)
922     {
923 
924         nx_tcp_socket_disconnect(&tcp_sockets[i], 1 * NX_IP_PERIODIC_RATE);
925 
926         if(tcp_sockets[i].nx_tcp_socket_bound_next)
927             status = nx_tcp_client_socket_unbind(&tcp_sockets[i]);
928         status += nx_tcp_socket_delete(&tcp_sockets[i]);
929 
930         if(status != NX_SUCCESS)
931             error_counter++;
932     }
933 
934 }
935 #endif
936 
netx_tcp_server(void)937 static void    netx_tcp_server(void)
938 {
939 NX_PACKET       *packet_ptr;
940 UINT             status;
941     /* Create a socket.  */
942     status =  nx_tcp_socket_create(&ip_1, &server_socket, "Server Socket",
943                                    NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 100,
944                                    NX_NULL, NX_NULL);
945 
946     /* Check for error.  */
947     if (status)
948         error_counter++;
949 
950     /* Setup this thread to listen.  */
951     status =  nx_tcp_server_socket_listen(&ip_1, 12, &server_socket, 5, NX_NULL);
952 
953     /* Check for error.  */
954     if (status)
955         error_counter++;
956 
957     /* Accept a client socket connection.  */
958     status =  nx_tcp_server_socket_accept(&server_socket, 1 * NX_IP_PERIODIC_RATE);
959 
960     /* Check for error.  */
961     if (status)
962         error_counter++;
963 
964     /* Receive a TCP message from the socket.  */
965     status =  nx_tcp_socket_receive(&server_socket, &packet_ptr, 2 * NX_IP_PERIODIC_RATE);
966 
967     /* Check for error.  */
968     if ((status) || (packet_ptr -> nx_packet_length != strlen(send_buffer)))
969         error_counter++;
970     else
971     {
972         if(memcmp(packet_ptr -> nx_packet_prepend_ptr, send_buffer, strlen(send_buffer)))
973            error_counter++;
974 
975         nx_packet_release(packet_ptr);
976     }
977 
978     tx_semaphore_put(&sema_0);
979 
980     /* Disconnect the server socket.  */
981     status =  nx_tcp_socket_disconnect(&server_socket, 1 * NX_IP_PERIODIC_RATE);
982 
983     /* Check for error.  */
984     if (status)
985         error_counter++;
986 
987     /* Unaccept the server socket.  */
988     status =  nx_tcp_server_socket_unaccept(&server_socket);
989 
990     /* Check for error.  */
991     if (status)
992         error_counter++;
993 
994     /* Setup server socket for listening again.  */
995     status =  nx_tcp_server_socket_unlisten(&ip_1, 12);
996 
997     /* Check for error.  */
998     if (status)
999         error_counter++;
1000 
1001     nx_tcp_socket_delete(&server_socket);
1002 }
1003 
ntest_1_entry(ULONG thread_input)1004 static void    ntest_1_entry(ULONG thread_input)
1005 {
1006 
1007 UINT            status;
1008 ULONG           actual_status;
1009 
1010 
1011 
1012     /* Ensure the IP instance has been initialized.  */
1013     status =  nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status, 1 * NX_IP_PERIODIC_RATE);
1014 
1015     /* Check status...  */
1016     if (status != NX_SUCCESS)
1017     {
1018 
1019         printf("ERROR!\n");
1020         test_control_return(3);
1021     }
1022 
1023     tx_semaphore_put(&sema_0);
1024 
1025     netx_tcp_server();
1026 
1027     /* Server run first. */
1028     tx_semaphore_get(&sema_1, 5 * NX_IP_PERIODIC_RATE);
1029 
1030     /* Simulate a multiple client conneting to the same server. */
1031     multiple_client4();
1032 
1033 #ifdef FEATURE_NX_IPV6
1034     tx_semaphore_put(&sema_0);
1035     netx_tcp_server();
1036 
1037     tx_semaphore_get(&sema_1, 5 * NX_IP_PERIODIC_RATE);
1038     multiple_client6();
1039 #endif
1040 
1041     /* Client finished. */
1042     tx_semaphore_put(&sema_0);
1043 }
1044 
1045 
1046 extern TX_BLOCK_POOL nx_bsd_socket_block_pool;
validate_bsd_structure(void)1047 static void validate_bsd_structure(void)
1048 {
1049 int i;
1050     /* Make sure every BSD socket should be free by now. */
1051 
1052     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
1053     {
1054         if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)
1055         {
1056             error_counter++;
1057         }
1058 
1059         if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket ||
1060            nx_bsd_socket_array[i].nx_bsd_socket_udp_socket)
1061         {
1062             error_counter++;
1063         }
1064     }
1065 
1066     /* Make sure all the NX SOCKET control blocks are released. */
1067     if(nx_bsd_socket_block_pool.tx_block_pool_available !=
1068        nx_bsd_socket_block_pool.tx_block_pool_total)
1069     {
1070         error_counter++;
1071     }
1072 
1073     /* Make sure all the sockets are released */
1074     if(ip_0.nx_ip_tcp_created_sockets_ptr ||
1075        ip_0.nx_ip_udp_created_sockets_ptr)
1076     {
1077         error_counter++;
1078         return;
1079     }
1080 }
1081 
1082 #else
1083 extern void       test_control_return(UINT status);
1084 
1085 #ifdef CTEST
test_application_define(void * first_unused_memory)1086 VOID test_application_define(void *first_unused_memory)
1087 #else
1088 void    netx_bsd_tcp_basic_blocking_test_application_define(void *first_unused_memory)
1089 #endif
1090 {
1091 
1092     /* Print out test information banner.  */
1093     printf("NetX Test:   Basic BSD TCP Basic Blocking Test.............N/A\n");
1094 
1095     test_control_return(3);
1096 }
1097 #endif
1098