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