1 /* This test checks for the Telnet Server to negotiate with a Telnet Client for three common
2 Telnet options. It offers to ECHO, Suppress Go Ahead and asks the peer not to ECHO (Don't Echo).
3 The Telnet Client is programmed to acknowledge the ECHO and SGA, and Won't Echo.
4
5 Required configuration settings:
6
7 NX_TELNET_SERVER_OPTION_DISABLE not defined
8 NX_TELNET_SERVER_USER_CREATE_PACKET_POOL defined
9 */
10
11 #include "tx_api.h"
12 #include "nx_api.h"
13
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
23 #define DEMO_STACK_SIZE 4096
24
25
26 /* Define the ThreadX and NetX object control blocks... */
27
28 static TX_THREAD server_thread;
29 static TX_THREAD client_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
36 /* Define TELNET server object. */
37
38 static NX_TELNET_SERVER my_server;
39 static NX_TELNET_CLIENT my_client;
40
41 #define SERVER_ADDRESS IP_ADDRESS(1,2,3,4)
42 #define CLIENT_ADDRESS IP_ADDRESS(1,2,3,5)
43
44
45
46 /* Define the counters and flags used in the demo application... */
47
48 static ULONG error_counter;
49 static UINT server_option_negotiation;
50
51 /* Define timeout in ticks for connecting and sending/receiving data. */
52
53 #define TELNET_TIMEOUT 200
54
55
56 void thread_server_entry(ULONG thread_input);
57 void thread_client_entry(ULONG thread_input);
58
59 extern void _nx_ram_network_driver_512(struct NX_IP_DRIVER_STRUCT *driver_req);
60
61 static UCHAR send_buff[256];
62
63 /* Define the application's TELNET Server callback routines. */
64
65 void telnet_new_connection(NX_TELNET_SERVER *server_ptr, UINT logical_connection);
66 void telnet_receive_data(NX_TELNET_SERVER *server_ptr, UINT logical_connection, NX_PACKET *packet_ptr);
67 void telnet_connection_end(NX_TELNET_SERVER *server_ptr, UINT logical_connection);
68
69
70
71 /* Define what the initial system looks like. */
72 #ifdef CTEST
test_application_define(void * first_unused_memory)73 VOID test_application_define(void *first_unused_memory)
74 #else
75 void netx_telnet_server_options_negotiate_test_application_define(void *first_unused_memory)
76 #endif
77 {
78
79 UINT status;
80 CHAR *pointer;
81
82 error_counter = 0;
83
84 /* Setup the working pointer. */
85 pointer = (CHAR *) first_unused_memory;
86
87 /* Create the server thread. */
88 status = tx_thread_create(&server_thread, "Telnet Server thread", thread_server_entry, 0,
89 pointer, DEMO_STACK_SIZE,
90 12, 12, TX_NO_TIME_SLICE, TX_AUTO_START);
91 pointer = pointer + DEMO_STACK_SIZE;
92
93
94 if (status)
95 {
96 printf("Error creating Server thread 0x%x\n", status);
97 }
98
99 /* Initialize the NetX system. */
100 nx_system_initialize();
101
102 /* Create the server packet pool. */
103 nx_packet_pool_create(&pool_server, "Server NetX Packet Pool", 600, pointer, 8192);
104 pointer = pointer + 8192;
105
106 /* Create the Server IP instance. */
107 nx_ip_create(&ip_server, "Server NetX IP Instance", SERVER_ADDRESS,
108 0xFFFFFF00UL, &pool_server, _nx_ram_network_driver_512,
109 pointer, 4096, 1);
110
111 pointer = pointer + 4096;
112
113
114 /* Enable ARP and supply ARP cache memory for the server. */
115 nx_arp_enable(&ip_server, (void *) pointer, 1024);
116 pointer = pointer + 1024;
117
118 /* Enable TCP processing for both IP instances. */
119 nx_tcp_enable(&ip_server);
120 nx_icmp_enable(&ip_server);
121
122
123 /* Create the NetX Duo TELNET Server. */
124 status = nx_telnet_server_create(&my_server, "Telnet Server", &ip_server,
125 pointer, 2048, telnet_new_connection, telnet_receive_data,
126 telnet_connection_end);
127
128 /* Check for errors. */
129 if (status)
130 error_counter++;
131
132
133 pointer = pointer + 2048;
134
135 /* Create the Client thread. */
136 status = tx_thread_create(&client_thread, "Telnet Client thread", thread_client_entry, 0,
137 pointer, DEMO_STACK_SIZE,
138 12, 12, TX_NO_TIME_SLICE, TX_AUTO_START);
139
140 if (status)
141 {
142 error_counter++;
143 }
144
145 pointer = pointer + DEMO_STACK_SIZE;
146
147 /* Create the client packet pool. */
148 status = nx_packet_pool_create(&pool_client, "Client NetX Packet Pool", 600, pointer, 8192);
149 if (status)
150 {
151 error_counter++;
152 }
153 pointer = pointer + 8192;
154
155 /* Create the Client IP instance. */
156 status = nx_ip_create(&ip_client, "Client NetX IP Instance", CLIENT_ADDRESS,
157 0xFFFFFF00UL, &pool_client, _nx_ram_network_driver_512,
158 pointer, 4096, 1);
159 if (status)
160 {
161 error_counter++;
162 }
163
164 pointer = pointer + 4096;
165
166 /* Enable ARP and supply ARP cache memory for the client. */
167 nx_arp_enable(&ip_client, (void *) pointer, 1024);
168 pointer = pointer + 1024;
169
170 /* Enable TCP and ICMP processing for client IP instance. */
171 nx_tcp_enable(&ip_client);
172 nx_icmp_enable(&ip_client);
173
174
175 return;
176 }
177
thread_client_entry(ULONG thread_input)178 void thread_client_entry(ULONG thread_input)
179 {
180
181 UINT status;
182 NX_PACKET *my_packet, *my_packet2, *rcv_packet;
183
184 tx_thread_sleep(100);
185
186 /* Create a TELENT client instance. */
187 status = nx_telnet_client_create(&my_client, "TELNET Client", &ip_client, 6 * NX_IP_PERIODIC_RATE);
188 if (status)
189 error_counter++;
190
191 /* Connect the TELNET client to the TELNET Server at port 23 over IPv4. */
192 status = nx_telnet_client_connect(&my_client, SERVER_ADDRESS, NX_TELNET_SERVER_PORT, 200);
193 if (status)
194 error_counter++;
195
196
197 /* This should be the welcome message. */
198 status = nx_telnet_client_packet_receive(&my_client, &rcv_packet, TELNET_TIMEOUT);
199
200 if (status)
201 error_counter++;
202
203 /* To do verify this is just a hello message. */
204
205 nx_packet_release(rcv_packet);
206
207 /* Server should be negotiating options. */
208 status = nx_telnet_client_packet_receive(&my_client, &rcv_packet, TELNET_TIMEOUT);
209
210 if (status)
211 error_counter++;
212
213 /* Parse the options. Should be will echo don't echo and will suppress go ahead */
214
215 nx_packet_release(rcv_packet);
216
217 /* Prepare a Do ECHO reply */
218 send_buff[0] = 0xFF;
219 send_buff[1] = 0xFD;
220 send_buff[2] = 0x01;
221
222 /* Allocate a packet. */
223 status = nx_packet_allocate(&pool_client, &my_packet, NX_TCP_PACKET, NX_WAIT_FOREVER);
224 if (status)
225 error_counter++;
226
227 /* Build a simple 1-byte message. */
228 nx_packet_data_append(my_packet, send_buff, sizeof(send_buff), &pool_client, NX_WAIT_FOREVER);
229
230 /* Send the packet to the TELNET Server. */
231 status = nx_telnet_client_packet_send(&my_client, my_packet, TELNET_TIMEOUT);
232 if (status)
233 error_counter++;
234
235 /* Prepare a second reply: WONT ECHO, DO SUPPRESS GO AHEAD */
236 send_buff[0] = 0xFF;
237 send_buff[1] = 0xFC;
238 send_buff[2] = 0x01;
239 send_buff[0] = 0xFF;
240 send_buff[1] = 0xFD;
241 send_buff[2] = 0x03;
242
243 /* Allocate a packet. */
244 status = nx_packet_allocate(&pool_client, &my_packet2, NX_TCP_PACKET, NX_WAIT_FOREVER);
245 if (status)
246 error_counter++;
247
248 /* Load the reply in to the packet. */
249 nx_packet_data_append(my_packet2, send_buff, sizeof(send_buff), &pool_client, NX_WAIT_FOREVER);
250
251 /* Send the packet to the TELNET Server. */
252 status = nx_telnet_client_packet_send(&my_client, my_packet2, TELNET_TIMEOUT);
253 if (status)
254 error_counter++;
255
256 tx_thread_sleep(200);
257
258 /* Now disconnect form the TELNET Server. */
259 nx_telnet_client_disconnect(&my_client, 100);
260
261 /* Delete the TELNET Client. */
262 status = nx_telnet_client_delete(&my_client);
263 if (status)
264 error_counter++;
265
266 }
267
268 /* Define the Telnet Server thread. */
thread_server_entry(ULONG thread_input)269 void thread_server_entry(ULONG thread_input)
270 {
271
272 UINT status;
273
274
275 tx_thread_sleep(20);
276
277 /* Print out test information banner. */
278 printf("NetX Test: Telnet Server Negotiation Test............................");
279
280 /* Check for earlier error. */
281 if(error_counter)
282 {
283 printf("ERROR!\n");
284 test_control_return(1);
285 }
286
287 /* We have defined the NX_TELNET_CREATE_PACKET_POOL option for sending
288 Telnet options (not disabled). So set the telnet packet pool. */
289 status = nx_telnet_server_packet_pool_set(&my_server, &pool_server);
290
291 if (status != NX_SUCCESS)
292 {
293 error_counter++;
294 }
295
296 server_option_negotiation = NX_FALSE;
297
298 /* Start the TELNET Server. */
299 status = nx_telnet_server_start(&my_server);
300
301 /* Check for errors. */
302 if (status != NX_SUCCESS)
303 {
304 error_counter++;
305 }
306
307 do
308 {
309 /* Check on the result of optio negotiations while the client connection is live. */
310
311 NX_TELNET_CLIENT_REQUEST *client_req_ptr = &(my_server.nx_telnet_server_client_list[0]);
312 if ((client_req_ptr -> nx_telnet_client_agree_server_will_SGA_success == NX_TRUE) &&
313 (client_req_ptr -> nx_telnet_client_agree_server_will_echo_success == NX_TRUE))
314 {
315 /* negotiation successful. */
316 server_option_negotiation = NX_TRUE;
317 }
318
319 tx_thread_sleep(100);
320 }while (my_server.nx_telnet_server_open_connections == 1);
321
322 status = nx_telnet_server_stop(&my_server);
323
324 /* Check for errors. */
325 if (status != NX_SUCCESS)
326 {
327 error_counter++;
328
329 }
330
331 if (error_counter || !server_option_negotiation)
332 {
333
334 printf("ERROR!\n");
335 test_control_return(1);
336 }
337 else
338
339 {
340
341 printf("SUCCESS!\n");
342 test_control_return(0);
343 }
344
345 return;
346 }
347
348
349 /* This routine is called by the NetX Telnet Server whenever a new Telnet client
350 connection is established. */
telnet_new_connection(NX_TELNET_SERVER * server_ptr,UINT logical_connection)351 void telnet_new_connection(NX_TELNET_SERVER *server_ptr, UINT logical_connection)
352 {
353
354 UINT status;
355 NX_PACKET *packet_ptr;
356
357
358 /* Allocate a packet for client greeting. */
359 status = nx_packet_allocate(&pool_server, &packet_ptr, NX_TCP_PACKET, NX_NO_WAIT);
360
361 if (status != NX_SUCCESS)
362 {
363 error_counter++;
364 return;
365 }
366
367 if (pool_server.nx_packet_pool_available < 2)
368 {
369 printf("Packet pool getting low...\n");
370 }
371 /* Build a banner message and a prompt. */
372 nx_packet_data_append(packet_ptr, "**** Welcome to NetX TELNET Server ****\r\n\r\n\r\n", 45, &pool_server, NX_NO_WAIT);
373
374 /* Send the packet to the client. */
375 status = nx_telnet_server_packet_send(server_ptr, logical_connection, packet_ptr, TELNET_TIMEOUT);
376
377 if (status != NX_SUCCESS)
378 {
379 error_counter++;
380 nx_packet_release(packet_ptr);
381 }
382
383 return;
384 }
385
386
387 /* This routine is called by the NetX Telnet Server whenever data is present on a Telnet client
388 connection. */
telnet_receive_data(NX_TELNET_SERVER * server_ptr,UINT logical_connection,NX_PACKET * packet_ptr)389 void telnet_receive_data(NX_TELNET_SERVER *server_ptr, UINT logical_connection, NX_PACKET *packet_ptr)
390 {
391
392 UINT status;
393 UCHAR alpha;
394
395
396
397 /* This demo just echoes the character back and on <cr,lf> sends a new prompt back to the
398 client. A real system would most likely buffer the character(s) received in a buffer
399 associated with the supplied logical connection and process according to it. */
400
401
402 /* Just throw away carriage returns. */
403 if ((packet_ptr -> nx_packet_prepend_ptr[0] == '\r') && (packet_ptr -> nx_packet_length == 1))
404 {
405 nx_packet_release(packet_ptr);
406 return;
407 }
408
409
410 /* Setup new line on line feed. */
411 if ((packet_ptr -> nx_packet_prepend_ptr[0] == '\n') || (packet_ptr -> nx_packet_prepend_ptr[1] == '\n'))
412 {
413
414 /* Clean up the packet. */
415 packet_ptr -> nx_packet_length = 0;
416 packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET;
417 packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET;
418
419 /* Build the next prompt. */
420 nx_packet_data_append(packet_ptr, "\r\nNETX> ", 8, &pool_server, NX_NO_WAIT);
421
422 /* Send the packet to the client. */
423 status = nx_telnet_server_packet_send(server_ptr, logical_connection, packet_ptr, TELNET_TIMEOUT);
424
425 if (status)
426 {
427 nx_packet_release(packet_ptr);
428 error_counter++;
429 }
430
431 return;
432 }
433
434 /* Pickup first character (usually only one from client). */
435 alpha = packet_ptr -> nx_packet_prepend_ptr[0];
436
437 /* Echo character. */
438 status = nx_telnet_server_packet_send(server_ptr, logical_connection, packet_ptr, TELNET_TIMEOUT);
439
440 if (status != NX_SUCCESS)
441 {
442 error_counter++;
443 nx_packet_release(packet_ptr);
444 }
445
446 /* Check for a disconnection. */
447 if (alpha == 'q')
448 {
449
450 /* Initiate server disconnection. */
451 nx_telnet_server_disconnect(server_ptr, logical_connection);
452 }
453 }
454
455
456 /* This routine is called by the NetX Telnet Server whenever the client disconnects. */
telnet_connection_end(NX_TELNET_SERVER * server_ptr,UINT logical_connection)457 void telnet_connection_end(NX_TELNET_SERVER *server_ptr, UINT logical_connection)
458 {
459
460 /* Cleanup any application specific connection or buffer information. */
461 }
462
463 #else /* NX_TELNET_SERVER_USER_CREATE_PACKET_POOL */
464
465 #ifdef CTEST
test_application_define(void * first_unused_memory)466 VOID test_application_define(void *first_unused_memory)
467 #else
468 void netx_telnet_server_options_negotiate_test_application_define(void *first_unused_memory)
469 #endif
470 {
471 printf("NetX Test: Telnet Server Negotiation Test............................N/A\n");
472 test_control_return(3);
473 }
474 #endif /* NX_TELNET_SERVER_USER_CREATE_PACKET_POOL */
475
476