1 /* This test checks for the Telnet Server to keep track of the length of inactivity on all its connections
2    If the timeout is exceeded it should close the connection.
3 
4    The following symbols and options must be set:
5 
6    NX_TELNET_SERVER_USER_CREATE_PACKET_POOL  defined
7    NX_TELNET_TIMEOUT_PERIOD = 2
8    NX_TELNET_ACTIVITY_TIMEOUT = 10
9 
10 */
11 
12 #include  "tx_api.h"
13 #include  "nx_api.h"
14 
15 extern void    test_control_return(UINT);
16 
17 #if defined(NX_TELNET_SERVER_USER_CREATE_PACKET_POOL) && !defined(NX_DISABLE_IPV4)
18 
19 #include  "nxd_telnet_client.h"
20 #include  "nxd_telnet_server.h"
21 
22 #define     DEMO_STACK_SIZE         4096
23 
24 
25 /* Define the ThreadX and NetX object control blocks...  */
26 
27 static TX_THREAD               server_thread;
28 static TX_THREAD               client1_thread;
29 static TX_THREAD               client2_thread;
30 static NX_PACKET_POOL          pool_server;
31 static NX_PACKET_POOL          pool_client;
32 static NX_IP                   ip_server;
33 static NX_IP                   ip_client;
34 
35 /* Define TELNET objects.  */
36 
37 static NX_TELNET_SERVER        my_server;
38 static NX_TELNET_CLIENT        my_client1;
39 static NX_TELNET_CLIENT        my_client2;
40 
41 static UCHAR                   send_buff[256];
42 static UCHAR                   recv_buff[256];
43 
44 
45 #define         SERVER_ADDRESS          IP_ADDRESS(1,2,3,4)
46 #define         CLIENT_ADDRESS          IP_ADDRESS(1,2,3,5)
47 
48 
49 /* Define the counters used in the demo application...  */
50 
51 static  ULONG              clients_connected = 0;
52 static  ULONG              total_disconnects = 0;
53 static  ULONG              total_connections = 0;
54 static  ULONG              error_counter = 0;
55 
56 
57 /* Define timeout in ticks for connecting and sending/receiving data. */
58 
59 #define                 TELNET_TIMEOUT          200
60 #define                 SHORT_TELNET_TIMEOUT    50
61 
62 /* Define function prototypes.  */
63 
64 static void    thread_server_entry(ULONG thread_input);
65 static void    thread_client1_entry(ULONG thread_input);
66 static void    thread_client2_entry(ULONG thread_input);
67 
68 /* Replace the 'ram' driver with your actual Ethernet driver. */
69 extern void    _nx_ram_network_driver_512(struct NX_IP_DRIVER_STRUCT *driver_req);
70 
71 /* Define the application's TELNET Server callback routines.  */
72 
73 static void    telnet_new_connection(NX_TELNET_SERVER *server_ptr, UINT logical_connection);
74 static void    telnet_receive_data(NX_TELNET_SERVER *server_ptr, UINT logical_connection, NX_PACKET *packet_ptr);
75 static void    telnet_connection_end(NX_TELNET_SERVER *server_ptr, UINT logical_connection);
76 
77 
78 /* Define what the initial system looks like.  */
79 #ifdef CTEST
test_application_define(void * first_unused_memory)80 VOID test_application_define(void *first_unused_memory)
81 #else
82 void    netx_telnet_activity_timeout_test_application_define(void *first_unused_memory)
83 #endif
84 {
85 
86 UINT    status;
87 CHAR    *pointer;
88 
89 
90     /* Setup the working pointer.  */
91     pointer =  (CHAR *) first_unused_memory;
92 
93     /* Create the server thread.  */
94     tx_thread_create(&server_thread, "server thread", thread_server_entry, 0,
95             pointer, DEMO_STACK_SIZE,
96             4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
97 
98     pointer =  pointer + DEMO_STACK_SIZE;
99 
100     /* Create the client 1 thread.  */
101     tx_thread_create(&client1_thread, "client 1 thread", thread_client1_entry, 0,
102             pointer, DEMO_STACK_SIZE,
103             6, 6, TX_NO_TIME_SLICE, TX_AUTO_START);
104 
105     pointer =  pointer + DEMO_STACK_SIZE;
106 
107 
108     /* Create the client 2 thread.  */
109     tx_thread_create(&client2_thread, "client 2 thread", thread_client2_entry, 0,
110             pointer, DEMO_STACK_SIZE,
111             6, 6, TX_NO_TIME_SLICE, TX_AUTO_START);
112 
113     pointer =  pointer + DEMO_STACK_SIZE;
114 
115 
116     /* Initialize the NetX system.  */
117     nx_system_initialize();
118 
119     /* Create packet pool.  */
120     status = nx_packet_pool_create(&pool_server, "Server NetX Packet Pool", 600, pointer, 8192);
121     pointer = pointer + 8192;
122     if(status)
123         error_counter++;
124 
125     /* Create an IP instance.  */
126     status = nx_ip_create(&ip_server, "Server NetX IP Instance", SERVER_ADDRESS,
127                           0xFFFFFF00UL, &pool_server, _nx_ram_network_driver_512,
128                           pointer, 4096, 1);
129     pointer =  pointer + 4096;
130     if(status)
131         error_counter++;
132 
133     /* Create another packet pool. */
134     status = nx_packet_pool_create(&pool_client, "Client NetX Packet Pool", 600, pointer, 8192);
135     pointer = pointer + 8192;
136     if(status)
137         error_counter++;
138 
139     /* Create another IP instance.  */
140     status = nx_ip_create(&ip_client, "Client NetX IP Instance", CLIENT_ADDRESS,
141                           0xFFFFFF00UL, &pool_client, _nx_ram_network_driver_512,
142                           pointer, 4096, 1);
143     pointer = pointer + 4096;
144     if(status)
145         error_counter++;
146 
147     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
148     status = nx_arp_enable(&ip_server, (void *) pointer, 1024);
149     pointer = pointer + 1024;
150     if(status)
151         error_counter++;
152 
153     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
154     status = nx_arp_enable(&ip_client, (void *) pointer, 1024);
155     pointer = pointer + 1024;
156     if(status)
157         error_counter++;
158 
159     /* Enable TCP processing for both IP instances.  */
160     status = nx_tcp_enable(&ip_server);
161     status += nx_tcp_enable(&ip_client);
162     if(status)
163         error_counter++;
164 
165     /* Create the NetX Duo TELNET Server.  */
166     status =  nx_telnet_server_create(&my_server, "Telnet Server", &ip_server,
167                     pointer, 2048, telnet_new_connection, telnet_receive_data,
168                     telnet_connection_end);
169 
170     pointer = pointer + 2048;
171 
172     /* Check for errors.  */
173     if (status)
174         error_counter++;
175 
176     status = nx_telnet_server_packet_pool_set(&my_server, &pool_server);
177 
178     /* Check for errors.  */
179     if (status)
180         error_counter++;
181 }
182 
183 /* Define the Server thread.  */
thread_server_entry(ULONG thread_input)184 void    thread_server_entry(ULONG thread_input)
185 {
186 
187 UINT    status;
188 UINT    current_connections;
189 
190 
191     tx_thread_sleep(20);
192 
193     /* Print out test information banner.  */
194     printf("NetX Test:   Telnet Activity Timeout Test..............................");
195 
196     /* Check for earlier error. */
197     if(error_counter)
198     {
199         printf("ERROR!\n");
200         test_control_return(1);
201     }
202 
203     /* Start the TELNET Server.  */
204     status =  nx_telnet_server_start(&my_server);
205     if (status)
206         error_counter++;
207 
208     /* Wait a few beats to let clients connect. */
209     while(!clients_connected)
210     {
211         tx_thread_sleep(50);
212     }
213 
214     /* Check on the number of current connections. */
215     do
216     {
217 
218         nx_telnet_server_get_open_connection_count(&my_server, &current_connections);
219         tx_thread_sleep(50);
220 
221     }while (current_connections > 0);
222 
223     /* Kill remaining clients connections if any. */
224     status =  nx_telnet_server_stop(&my_server);
225 
226     if (status)
227         error_counter++;
228 
229     tx_thread_sleep(1 * NX_IP_PERIODIC_RATE);
230 
231     status = nx_telnet_server_delete(&my_server);
232     if (status)
233         error_counter++;
234 
235     if ((my_server.nx_telnet_server_activity_timeouts != 1) ||
236         (total_connections != 2) ||
237         (total_disconnects != 2))
238     {
239         error_counter++;
240     }
241 
242     /* Wait for thread2 to complete. */
243     while(clients_connected)
244         tx_thread_sleep(100);
245 
246     if (error_counter)
247     {
248         printf("ERROR!\n");
249         test_control_return(1);
250     }
251     else
252     {
253         printf("SUCCESS!\n");
254         test_control_return(0);
255     }
256 
257 }
258 
259 /* This routine is called by the NetX Telnet Server whenever a new Telnet client
260    connection is established.  */
telnet_new_connection(NX_TELNET_SERVER * server_ptr,UINT logical_connection)261 void  telnet_new_connection(NX_TELNET_SERVER *server_ptr, UINT logical_connection)
262 {
263 
264 UINT        status;
265 NX_PACKET   *packet_ptr;
266 
267 
268     total_connections++;
269 
270     /* Allocate a packet for client greeting. */
271     status =  nx_packet_allocate(&pool_server, &packet_ptr, NX_TCP_PACKET, NX_NO_WAIT);
272     if (status)
273         error_counter++;
274 
275     /* Build a banner message and a prompt.  */
276     nx_packet_data_append(packet_ptr, "**** Welcome to NetX TELNET Server ****\r\n\r\n\r\n", 45,
277                           &pool_server, NX_NO_WAIT);
278 
279     nx_packet_data_append(packet_ptr, "NETX> ", 6, &pool_server, NX_NO_WAIT);
280 
281     /* Send the packet to the client.  */
282     status =  nx_telnet_server_packet_send(server_ptr, logical_connection, packet_ptr, TELNET_TIMEOUT);
283 
284     if (status)
285     {
286         error_counter++;
287         nx_packet_release(packet_ptr);
288     }
289 }
290 
291 
292 /* This routine is called by the NetX Telnet Server whenever data is present on a Telnet client
293    connection.  */
telnet_receive_data(NX_TELNET_SERVER * server_ptr,UINT logical_connection,NX_PACKET * packet_ptr)294 void  telnet_receive_data(NX_TELNET_SERVER *server_ptr, UINT logical_connection, NX_PACKET *packet_ptr)
295 {
296 
297 UINT    status;
298 UCHAR   alpha;
299 ULONG   bytes_copied;
300 
301 
302     /* This demo just echoes the character back and on <cr,lf> sends a new prompt back to the
303        client.  A real system would most likely buffer the character(s) received in a buffer
304        associated with the supplied logical connection and process according to it.  */
305 
306 
307     /* Just throw away carriage returns.  */
308     if ((packet_ptr -> nx_packet_prepend_ptr[0] == '\r') && (packet_ptr -> nx_packet_length == 1))
309     {
310 
311         nx_packet_release(packet_ptr);
312         return;
313     }
314 
315     /* Setup new line on line feed.  */
316     if ((packet_ptr -> nx_packet_prepend_ptr[0] == '\n') || (packet_ptr -> nx_packet_prepend_ptr[1] == '\n'))
317     {
318 
319         /* Clean up the packet.  */
320         packet_ptr -> nx_packet_length =  0;
321         packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_data_start + NX_TCP_PACKET;
322         packet_ptr -> nx_packet_append_ptr =   packet_ptr -> nx_packet_data_start + NX_TCP_PACKET;
323 
324         /* Build the next prompt.  */
325         nx_packet_data_append(packet_ptr, "\r\nNETX> ", 8, &pool_server, NX_NO_WAIT);
326 
327         /* Send the packet to the client.  */
328         status =  nx_telnet_server_packet_send(server_ptr, logical_connection, packet_ptr, TELNET_TIMEOUT);
329         if (status)
330         {
331             error_counter++;
332             nx_packet_release(packet_ptr);
333         }
334 
335         return;
336     }
337 
338     /* Verify data. */
339     status = nx_packet_data_retrieve(packet_ptr, recv_buff, &bytes_copied);
340     if (status)
341     {
342         error_counter++;
343     }
344 
345     if (bytes_copied != sizeof(send_buff))
346     {
347         error_counter++;
348     }
349 
350     if (memcmp(send_buff, recv_buff, sizeof(send_buff)) != 0)
351     {
352         error_counter++;
353     }
354 
355     /* Pickup first character (usually only one from client).  */
356     alpha =  packet_ptr -> nx_packet_prepend_ptr[0];
357 
358     /* Echo character.  */
359     status =  nx_telnet_server_packet_send(server_ptr, logical_connection, packet_ptr, TELNET_TIMEOUT);
360     if (status)
361     {
362 
363         error_counter++;
364         nx_packet_release(packet_ptr);
365     }
366 
367     /* Check for a disconnection.  */
368     if (alpha == 'q')
369     {
370 
371         /* Initiate server disconnection.  */
372         nx_telnet_server_disconnect(server_ptr, logical_connection);
373     }
374 }
375 
376 
377 /* This routine is called by the NetX Telnet Server whenever the client disconnects.  */
telnet_connection_end(NX_TELNET_SERVER * server_ptr,UINT logical_connection)378 void  telnet_connection_end(NX_TELNET_SERVER *server_ptr, UINT logical_connection)
379 {
380 
381     total_disconnects++;
382 
383     /* Cleanup any application specific connection or buffer information.  */
384     return;
385 }
386 
387 
388 /* Define the client1 thread.  */
thread_client1_entry(ULONG thread_input)389 void    thread_client1_entry(ULONG thread_input)
390 {
391 
392 NX_PACKET  *my_packet;
393 UINT        status;
394 UINT        i;
395 UINT        packets_sent= 0;
396 
397     tx_thread_sleep(100);
398 
399     /* Create a TELENT client instance.  */
400     status =  nx_telnet_client_create(&my_client1, "TELNET Client1", &ip_client, 6 * NX_IP_PERIODIC_RATE);
401     if (status)
402         error_counter++;
403 
404     /* Connect the TELNET client to the TELNET Server at port 23 over IPv4.  */
405     status =  nx_telnet_client_connect(&my_client1, SERVER_ADDRESS, NX_TELNET_SERVER_PORT, TELNET_TIMEOUT);
406     if (status)
407         error_counter++;
408     else
409         clients_connected++;
410 
411     /* Initialize the buffers. */
412     for (i = 0; i < sizeof(send_buff); i++)
413     {
414         send_buff[i] = (UCHAR)(i & 0xFF);
415     }
416     send_buff[0] = 0xFF;
417     send_buff[1] = 0xFF;
418     send_buff[2] = 0xFF;
419     memset(recv_buff, 0, sizeof(recv_buff));
420 
421     while (packets_sent< 2)
422     {
423 
424         /* Allocate a packet.  */
425         status =  nx_packet_allocate(&pool_client, &my_packet, NX_TCP_PACKET, NX_WAIT_FOREVER);
426         if (status)
427             error_counter++;
428 
429         /* Build a simple 1-byte message.  */
430         nx_packet_data_append(my_packet, send_buff, sizeof(send_buff), &pool_client, NX_WAIT_FOREVER);
431 
432         /* Send the packet to the TELNET Server.  */
433         status =  nx_telnet_client_packet_send(&my_client1, my_packet, TELNET_TIMEOUT);
434         if (status)
435             error_counter++;
436 
437         /* Pickup the Server header.  */
438         status =  nx_telnet_client_packet_receive(&my_client1, &my_packet, TELNET_TIMEOUT);
439         if (status)
440             error_counter++;
441 
442         /* At this point the packet should contain the Server's banner
443            message sent by the Server callback function below.  Just
444            release it for this demo.  */
445         nx_packet_release(my_packet);
446 
447         /* Pickup the Server echo of the character.  */
448         status =  nx_telnet_client_packet_receive(&my_client1, &my_packet, 4000);
449         if (status)
450             error_counter++;
451 
452         /* At this point the packet should contain the character 'a' that
453            we sent earlier.  Just release the packet for now.  */
454         nx_packet_release(my_packet);
455 
456         packets_sent++;
457     }
458 
459     /* Now disconnect form the TELNET Server.  */
460     nx_telnet_client_disconnect(&my_client1, TELNET_TIMEOUT);
461     clients_connected--;
462 
463     /* Delete the TELNET Client.  */
464     status =  nx_telnet_client_delete(&my_client1);
465     if (status)
466         error_counter++;
467 
468 }
469 
470 
471 /* Define the client2 thread.  */
thread_client2_entry(ULONG thread_input)472 void    thread_client2_entry(ULONG thread_input)
473 {
474 
475 NX_PACKET  *my_packet;
476 UINT        status;
477 UINT        i;
478 
479     tx_thread_sleep(110);
480 
481     /* Create a TELENT client instance.  */
482     status =  nx_telnet_client_create(&my_client2, "TELNET Client2", &ip_client, 6 * NX_IP_PERIODIC_RATE);
483     if (status)
484         error_counter++;
485 
486     /* Connect the TELNET client to the TELNET Server at port 23 over IPv4.  */
487     status =  nx_telnet_client_connect(&my_client2, SERVER_ADDRESS, NX_TELNET_SERVER_PORT, TELNET_TIMEOUT);
488     if (status)
489         error_counter++;
490     else
491         clients_connected++;
492 
493     /* Initialize the buffers. */
494     for (i = 0; i < sizeof(send_buff); i++)
495     {
496         send_buff[i] = (UCHAR)(i & 0xFF);
497     }
498     send_buff[0] = 0xFF;
499     send_buff[1] = 0xFF;
500     send_buff[2] = 0xFF;
501     memset(recv_buff, 0, sizeof(recv_buff));
502 
503     /* Allocate a packet.  */
504     status =  nx_packet_allocate(&pool_client, &my_packet, NX_TCP_PACKET, NX_WAIT_FOREVER);
505     if (status)
506         error_counter++;
507 
508     /* Build a simple 1-byte message.  */
509     nx_packet_data_append(my_packet, send_buff, sizeof(send_buff), &pool_client, NX_WAIT_FOREVER);
510 
511     /* Put in a long sleep time exceeding the activity timeout. */
512     tx_thread_sleep(1200);
513 
514     /* Send the packet to the TELNET Server.  */
515     status =  nx_telnet_client_packet_send(&my_client2, my_packet, TELNET_TIMEOUT);
516 
517     /* The server should have disconnected so check for 0x38/Not connected error*/
518     if (status == NX_NOT_CONNECTED)
519     {
520 
521         /* Disconnect form the TELNET Server.  */
522         nx_telnet_client_disconnect(&my_client2, TELNET_TIMEOUT);
523         clients_connected--;
524 
525         /* Delete TELNET Client2.  */
526         status =  nx_telnet_client_delete(&my_client2);
527         if (status)
528             error_counter++;
529 
530         return;
531     }
532 
533     /* This call should not succeed. */
534     error_counter++;
535 
536     /* Now disconnect form the TELNET Server.  */
537     nx_telnet_client_disconnect(&my_client2, TELNET_TIMEOUT);
538     clients_connected--;
539 
540     /* Delete the TELNET Client.  */
541     status =  nx_telnet_client_delete(&my_client2);
542 
543 }
544 
545 
546 #else /* NX_TELNET_SERVER_USER_CREATE_PACKET_POOL */
547 
548 #ifdef CTEST
test_application_define(void * first_unused_memory)549 VOID test_application_define(void *first_unused_memory)
550 #else
551 void    netx_telnet_activity_timeout_test_application_define(void *first_unused_memory)
552 #endif
553 {
554     printf("NetX Test:   Telnet Activity Timeout Test..............................N/A\n");
555     test_control_return(3);
556 }
557 #endif /* NX_TELNET_SERVER_USER_CREATE_PACKET_POOL */
558 
559 
560 
561 
562 
563