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