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