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, ¤t_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