1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Duo Component */
17 /** */
18 /** TELNET Protocol (TELNET) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_TELNET_SOURCE_CODE
24
25
26 /* Force error checking to be disabled in this module */
27
28 #ifndef NX_DISABLE_ERROR_CHECKING
29 #define NX_DISABLE_ERROR_CHECKING
30 #endif
31
32 /* Include necessary system files. */
33
34 #include "nx_api.h"
35 #include "nx_ip.h"
36 #include "nxd_telnet_server.h"
37 #include "stdio.h"
38 #include "string.h"
39
40
41 /* Bring in externs for caller checking code. */
42
43 NX_CALLER_CHECKING_EXTERNS
44
45
46
47 /**************************************************************************/
48 /* */
49 /* FUNCTION RELEASE */
50 /* */
51 /* _nxe_telnet_server_create PORTABLE C */
52 /* 6.1 */
53 /* AUTHOR */
54 /* */
55 /* Yuxin Zhou, Microsoft Corporation */
56 /* */
57 /* DESCRIPTION */
58 /* */
59 /* This function checks for errors in the TELNET server create call. */
60 /* */
61 /* */
62 /* INPUT */
63 /* */
64 /* server_ptr Pointer to TELNET server */
65 /* server_name Name of TELNET server */
66 /* ip_ptr Pointer to IP instance */
67 /* stack_ptr Server thread's stack pointer */
68 /* stack_size Server thread's stack size */
69 /* new_connection Pointer to user's new */
70 /* connection function */
71 /* receive_data Pointer to user's receive */
72 /* data function */
73 /* connection_end Pointer to user's end of */
74 /* connection function */
75 /* */
76 /* OUTPUT */
77 /* */
78 /* status Completion status */
79 /* */
80 /* CALLS */
81 /* */
82 /* _nx_telnet_server_create Actual server create call */
83 /* */
84 /* CALLED BY */
85 /* */
86 /* Application Code */
87 /* */
88 /* RELEASE HISTORY */
89 /* */
90 /* DATE NAME DESCRIPTION */
91 /* */
92 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
93 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
94 /* resulting in version 6.1 */
95 /* */
96 /**************************************************************************/
_nxe_telnet_server_create(NX_TELNET_SERVER * server_ptr,CHAR * server_name,NX_IP * ip_ptr,VOID * stack_ptr,ULONG stack_size,void (* new_connection)(struct NX_TELNET_SERVER_STRUCT * telnet_server_ptr,UINT logical_connection),void (* receive_data)(struct NX_TELNET_SERVER_STRUCT * telnet_server_ptr,UINT logical_connection,NX_PACKET * packet_ptr),void (* connection_end)(struct NX_TELNET_SERVER_STRUCT * telnet_server_ptr,UINT logical_connection))97 UINT _nxe_telnet_server_create(NX_TELNET_SERVER *server_ptr, CHAR *server_name, NX_IP *ip_ptr, VOID *stack_ptr, ULONG stack_size,
98 void (*new_connection)(struct NX_TELNET_SERVER_STRUCT *telnet_server_ptr, UINT logical_connection),
99 void (*receive_data)(struct NX_TELNET_SERVER_STRUCT *telnet_server_ptr, UINT logical_connection, NX_PACKET *packet_ptr),
100 void (*connection_end)(struct NX_TELNET_SERVER_STRUCT *telnet_server_ptr, UINT logical_connection))
101 {
102
103 UINT status;
104
105
106 /* Check for invalid input pointers. */
107 if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) ||
108 (server_ptr == NX_NULL) || (server_ptr -> nx_telnet_server_id == NX_TELNET_SERVER_ID) ||
109 (stack_ptr == NX_NULL) || (new_connection == NX_NULL) || (receive_data == NX_NULL) || (connection_end == NX_NULL))
110 return(NX_PTR_ERROR);
111
112 /* Call actual server create function. */
113 status = _nx_telnet_server_create(server_ptr, server_name, ip_ptr, stack_ptr, stack_size, new_connection, receive_data, connection_end);
114
115 /* Return completion status. */
116 return(status);
117 }
118
119
120 /**************************************************************************/
121 /* */
122 /* FUNCTION RELEASE */
123 /* */
124 /* _nx_telnet_server_create PORTABLE C */
125 /* 6.1 */
126 /* AUTHOR */
127 /* */
128 /* Yuxin Zhou, Microsoft Corporation */
129 /* */
130 /* DESCRIPTION */
131 /* */
132 /* This function creates a TELNET server on the specified IP. In doing */
133 /* so this function creates a TCP socket for subsequent TELNET */
134 /* transfers and a thread for the TELNET server. */
135 /* */
136 /* */
137 /* INPUT */
138 /* */
139 /* server_ptr Pointer to TELNET server */
140 /* server_name Name of TELNET server */
141 /* ip_ptr Pointer to IP instance */
142 /* stack_ptr Server thread's stack pointer */
143 /* stack_size Server thread's stack size */
144 /* new_connection Pointer to user's new */
145 /* connection function */
146 /* receive_data Pointer to user's receive */
147 /* data function */
148 /* connection_end Pointer to user's end of */
149 /* connection function */
150 /* */
151 /* OUTPUT */
152 /* */
153 /* status Completion status */
154 /* */
155 /* CALLS */
156 /* */
157 /* nx_tcp_socket_create Create sockets */
158 /* nx_tcp_socket_delete Delete sockets */
159 /* nx_tcp_socket_receive_notify Register receive notify */
160 /* callback */
161 /* tx_event_flags_create Create event flags */
162 /* tx_event_flags_delete Delete event flags */
163 /* tx_thread_create Create TELNET server thread */
164 /* tx_thread_delete Delete TELNET server thread */
165 /* tx_timer_create Create TELNET server timer */
166 /* tx_timer_delete Delete TELNET server timer */
167 /* */
168 /* CALLED BY */
169 /* */
170 /* Application Code */
171 /* */
172 /* RELEASE HISTORY */
173 /* */
174 /* DATE NAME DESCRIPTION */
175 /* */
176 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
177 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
178 /* resulting in version 6.1 */
179 /* */
180 /**************************************************************************/
_nx_telnet_server_create(NX_TELNET_SERVER * server_ptr,CHAR * server_name,NX_IP * ip_ptr,VOID * stack_ptr,ULONG stack_size,void (* new_connection)(struct NX_TELNET_SERVER_STRUCT * telnet_server_ptr,UINT logical_connection),void (* receive_data)(struct NX_TELNET_SERVER_STRUCT * telnet_server_ptr,UINT logical_connection,NX_PACKET * packet_ptr),void (* connection_end)(struct NX_TELNET_SERVER_STRUCT * telnet_server_ptr,UINT logical_connection))181 UINT _nx_telnet_server_create(NX_TELNET_SERVER *server_ptr, CHAR *server_name, NX_IP *ip_ptr, VOID *stack_ptr, ULONG stack_size,
182 void (*new_connection)(struct NX_TELNET_SERVER_STRUCT *telnet_server_ptr, UINT logical_connection),
183 void (*receive_data)(struct NX_TELNET_SERVER_STRUCT *telnet_server_ptr, UINT logical_connection, NX_PACKET *packet_ptr),
184 void (*connection_end)(struct NX_TELNET_SERVER_STRUCT *telnet_server_ptr, UINT logical_connection))
185 {
186
187 UINT i;
188 UINT status;
189
190 /* Clear the TELNET server structure. */
191 memset((void *) server_ptr, 0, sizeof(NX_TELNET_SERVER));
192
193 /* Create the TELNET Server thread. */
194 status = tx_thread_create(&(server_ptr -> nx_telnet_server_thread), "TELNET Server Thread",
195 _nx_telnet_server_thread_entry, (ULONG) server_ptr, stack_ptr,
196 stack_size, NX_TELNET_SERVER_PRIORITY, NX_TELNET_SERVER_PRIORITY,
197 TX_NO_TIME_SLICE, TX_DONT_START);
198
199 /* Determine if an error occurred creating the thread. */
200 if (status != TX_SUCCESS)
201 {
202
203 /* Error creating the server thread. */
204 return(status);
205 }
206
207 /* Create the ThreadX event flags. These will be used to driver the TELNET server thread. */
208 status = tx_event_flags_create(&(server_ptr -> nx_telnet_server_event_flags), "TELNET Server Thread Events");
209
210 /* Determine if an error occurred creating the event flags. */
211 if (status != TX_SUCCESS)
212 {
213
214 /* Delete the server thread. */
215 tx_thread_delete(&(server_ptr -> nx_telnet_server_thread));
216
217 /* Error creating the server event flags. */
218 return(status);
219 }
220
221 /* Create the ThreadX activity timeout timer. This will be used to periodically check to see if
222 a client connection has gone silent and needs to be terminated. */
223 status = tx_timer_create(&(server_ptr -> nx_telnet_server_timer), "TELNET Server Timer",
224 _nx_telnet_server_timeout, (ULONG) server_ptr,
225 (NX_IP_PERIODIC_RATE * NX_TELNET_TIMEOUT_PERIOD),
226 (NX_IP_PERIODIC_RATE * NX_TELNET_TIMEOUT_PERIOD), TX_NO_ACTIVATE);
227
228 /* Determine if an error occurred creating the timer. */
229 if (status != TX_SUCCESS)
230 {
231
232 /* Delete the server thread. */
233 tx_thread_delete(&(server_ptr -> nx_telnet_server_thread));
234
235 /* Delete the server event flags. */
236 tx_event_flags_delete(&(server_ptr -> nx_telnet_server_event_flags));
237
238 /* Error creating the server timer. */
239 return(status);
240 }
241
242 /* Loop to create all the TELNET client sockets. */
243 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
244 {
245
246 /* Setup the logical index for this client request structure. */
247 server_ptr -> nx_telnet_server_client_list[i].nx_telnet_client_request_connection = i;
248
249 /* Create an TELNET client socket. */
250 status += nx_tcp_socket_create(ip_ptr, &(server_ptr -> nx_telnet_server_client_list[i].nx_telnet_client_request_socket), "TELNET Server Control Socket",
251 NX_TELNET_TOS, NX_TELNET_FRAGMENT_OPTION, NX_TELNET_TIME_TO_LIVE, NX_TELNET_SERVER_WINDOW_SIZE, NX_NULL, _nx_telnet_server_disconnect_present);
252
253 /* If no error is present, register the receive notify function. */
254 if (status == NX_SUCCESS)
255 {
256
257 /* Register the receive function. */
258 nx_tcp_socket_receive_notify(&(server_ptr -> nx_telnet_server_client_list[i].nx_telnet_client_request_socket),
259 _nx_telnet_server_data_present);
260 }
261
262 /* Make sure each socket points to the TELNET server. */
263 server_ptr -> nx_telnet_server_client_list[i].nx_telnet_client_request_socket.nx_tcp_socket_reserved_ptr = server_ptr;
264 }
265
266 /* Determine if an error has occurred. */
267 if (status != NX_SUCCESS)
268 {
269
270 /* Loop to delete any created sockets. */
271 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
272 {
273
274 /* Delete the TELNET socket. */
275 nx_tcp_socket_delete(&(server_ptr -> nx_telnet_server_client_list[i].nx_telnet_client_request_socket));
276 }
277
278 /* Delete the server thread. */
279 tx_thread_delete(&(server_ptr -> nx_telnet_server_thread));
280
281 /* Delete the event flag group. */
282 tx_event_flags_delete(&(server_ptr -> nx_telnet_server_event_flags));
283
284 /* Delete the timer. */
285 tx_timer_delete(&(server_ptr -> nx_telnet_server_timer));
286
287 /* Return the NetX error. */
288 return(status);
289 }
290
291
292 #ifndef NX_TELNET_SERVER_OPTION_DISABLE
293
294 #ifndef NX_TELNET_SERVER_USER_CREATE_PACKET_POOL
295
296 /* Create the packet pool for negotiating telnet options, and check the status */
297 status = nx_packet_pool_create(&(server_ptr -> nx_telnet_server_packet_pool), "Telnet Server Options",
298 NX_TELNET_SERVER_PACKET_PAYLOAD, &server_ptr -> nx_telnet_server_pool_area,
299 NX_TELNET_SERVER_PACKET_POOL_SIZE);
300
301 /* Determine if it was successful. */
302 if (status != NX_SUCCESS)
303 {
304 /* Loop to delete any created sockets. */
305 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
306 {
307
308 /* Delete the TELNET socket. */
309 nx_tcp_socket_delete(&(server_ptr -> nx_telnet_server_client_list[i].nx_telnet_client_request_socket));
310 }
311
312 /* Delete the server thread. */
313 tx_thread_delete(&(server_ptr -> nx_telnet_server_thread));
314
315 /* Delete the event flag group. */
316 tx_event_flags_delete(&(server_ptr -> nx_telnet_server_event_flags));
317
318 /* Delete the timer. */
319 tx_timer_delete(&(server_ptr -> nx_telnet_server_timer));
320
321 /* No, return error status. */
322 return(status);
323 }
324
325 server_ptr -> nx_telnet_server_packet_pool_ptr = &(server_ptr -> nx_telnet_server_packet_pool);
326 #endif /* NX_TELNET_SERVER_USER_CREATE_PACKET_POOL */
327 #endif /* NX_TELNET_SERVER_OPTION_DISABLE */
328
329 /* Save the Server name. */
330 server_ptr -> nx_telnet_server_name = server_name;
331
332 /* Save the IP pointer address. */
333 server_ptr -> nx_telnet_server_ip_ptr = ip_ptr;
334
335 /* Save the user-supplied new connection and receive data functions. */
336 server_ptr -> nx_telnet_new_connection = new_connection;
337 server_ptr -> nx_telnet_receive_data = receive_data;
338 server_ptr -> nx_telnet_connection_end = connection_end;
339
340 /* Set the server ID to indicate the TELNET server thread is ready. */
341 server_ptr -> nx_telnet_server_id = NX_TELNET_SERVER_ID;
342
343 server_ptr -> nx_telnet_server_open_connections = 0;
344
345
346 /* Return successful completion. */
347 return(NX_SUCCESS);
348 }
349
350
351 /**************************************************************************/
352 /* */
353 /* FUNCTION RELEASE */
354 /* */
355 /* _nxe_telnet_server_delete PORTABLE C */
356 /* 6.1 */
357 /* AUTHOR */
358 /* */
359 /* Yuxin Zhou, Microsoft Corporation */
360 /* */
361 /* DESCRIPTION */
362 /* */
363 /* This function checks for errors in the TELNET server delete call. */
364 /* */
365 /* */
366 /* INPUT */
367 /* */
368 /* server_ptr Pointer to TELNET server */
369 /* */
370 /* OUTPUT */
371 /* */
372 /* status Completion status */
373 /* */
374 /* CALLS */
375 /* */
376 /* _nx_telnet_server_delete Actual server delete call */
377 /* */
378 /* CALLED BY */
379 /* */
380 /* Application Code */
381 /* */
382 /* RELEASE HISTORY */
383 /* */
384 /* DATE NAME DESCRIPTION */
385 /* */
386 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
387 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
388 /* resulting in version 6.1 */
389 /* */
390 /**************************************************************************/
_nxe_telnet_server_delete(NX_TELNET_SERVER * server_ptr)391 UINT _nxe_telnet_server_delete(NX_TELNET_SERVER *server_ptr)
392 {
393
394 UINT status;
395
396
397 /* Check for invalid input pointers. */
398 if ((server_ptr == NX_NULL) || (server_ptr -> nx_telnet_server_id != NX_TELNET_SERVER_ID))
399 return(NX_PTR_ERROR);
400
401 /* Check for appropriate caller. */
402 NX_THREADS_ONLY_CALLER_CHECKING
403
404 /* Call actual server delete function. */
405 status = _nx_telnet_server_delete(server_ptr);
406
407 /* Return completion status. */
408 return(status);
409 }
410
411
412
413 /**************************************************************************/
414 /* */
415 /* FUNCTION RELEASE */
416 /* */
417 /* _nx_telnet_server_delete PORTABLE C */
418 /* 6.1 */
419 /* AUTHOR */
420 /* */
421 /* Yuxin Zhou, Microsoft Corporation */
422 /* */
423 /* DESCRIPTION */
424 /* */
425 /* This function deletes a previously created TELNET server on the */
426 /* specified IP. */
427 /* */
428 /* */
429 /* INPUT */
430 /* */
431 /* server_ptr Pointer to TELNET server */
432 /* */
433 /* OUTPUT */
434 /* */
435 /* status Completion status */
436 /* */
437 /* CALLS */
438 /* */
439 /* nx_tcp_server_socket_unaccept Unaccept server socket */
440 /* nx_tcp_server_socket_unlisten Unlisten on server */
441 /* nx_tcp_socket_delete Delete socket */
442 /* nx_tcp_socket_disconnect Disconnect socket */
443 /* tx_event_flags_delete Delete event flags */
444 /* tx_thread_delete Delete thread */
445 /* tx_thread_suspend Suspend thread */
446 /* tx_thread_terminate Terminate thread */
447 /* tx_timer_deactivate Deactivate timer */
448 /* tx_timer_delete Delete timer */
449 /* */
450 /* CALLED BY */
451 /* */
452 /* Application Code */
453 /* */
454 /* RELEASE HISTORY */
455 /* */
456 /* DATE NAME DESCRIPTION */
457 /* */
458 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
459 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
460 /* resulting in version 6.1 */
461 /* */
462 /**************************************************************************/
_nx_telnet_server_delete(NX_TELNET_SERVER * server_ptr)463 UINT _nx_telnet_server_delete(NX_TELNET_SERVER *server_ptr)
464 {
465
466 UINT i;
467 NX_TELNET_CLIENT_REQUEST *client_request_ptr;
468
469
470 /* Clear the server ID to indicate the TELNET server is no longer ready. */
471 server_ptr -> nx_telnet_server_id = 0;
472
473 /* Suspend the TELNET server thread. */
474 tx_thread_suspend(&(server_ptr -> nx_telnet_server_thread));
475
476 /* Terminate server thread. */
477 tx_thread_terminate(&(server_ptr -> nx_telnet_server_thread));
478
479 /* Delete server thread. */
480 tx_thread_delete(&(server_ptr -> nx_telnet_server_thread));
481
482 /* Delete the event flag group. */
483 tx_event_flags_delete(&(server_ptr -> nx_telnet_server_event_flags));
484
485 /* Deactivate and delete timer. */
486 tx_timer_deactivate(&(server_ptr -> nx_telnet_server_timer));
487 tx_timer_delete(&(server_ptr -> nx_telnet_server_timer));
488
489 /* If the Telnet Server is configured to send options and the packet
490 pool is created by the internally (by the Telnet server task)
491 we need to delete it. */
492 #ifndef NX_TELNET_SERVER_OPTION_DISABLE
493 #ifndef NX_TELNET_SERVER_USER_CREATE_PACKET_POOL
494 nx_packet_pool_delete(&server_ptr -> nx_telnet_server_packet_pool);
495 #endif /* NX_TELNET_SERVER_USER_CREATE_PACKET_POOL */
496 #endif /* NX_TELNET_SERVER_OPTION_DISABLE */
497
498 /* Walk through the server structure to close and delete any open sockets. */
499 i = 0;
500 client_request_ptr = &(server_ptr -> nx_telnet_server_client_list[0]);
501 while (i < NX_TELNET_MAX_CLIENTS)
502 {
503
504 /* Disconnect the socket. */
505 nx_tcp_socket_disconnect(&(client_request_ptr -> nx_telnet_client_request_socket), NX_NO_WAIT);
506
507 /* Unaccept the socket. */
508 nx_tcp_server_socket_unaccept(&(client_request_ptr -> nx_telnet_client_request_socket));
509
510 /* Delete the socket. */
511 nx_tcp_socket_delete(&(client_request_ptr -> nx_telnet_client_request_socket));
512
513 /* Increment the pointer into the client request list. */
514 client_request_ptr++;
515 i++;
516 }
517
518 /* Unlisten on the TELNET port. */
519 nx_tcp_server_socket_unlisten(server_ptr -> nx_telnet_server_ip_ptr, NX_TELNET_SERVER_PORT);
520
521 /* Return successful completion. */
522 return(NX_SUCCESS);
523 }
524
525
526 /**************************************************************************/
527 /* */
528 /* FUNCTION RELEASE */
529 /* */
530 /* _nxe_telnet_server_disconnect PORTABLE C */
531 /* 6.1 */
532 /* AUTHOR */
533 /* */
534 /* Yuxin Zhou, Microsoft Corporation */
535 /* */
536 /* DESCRIPTION */
537 /* */
538 /* This function checks for errors in the TELNET server disconnect */
539 /* call. */
540 /* */
541 /* */
542 /* INPUT */
543 /* */
544 /* server_ptr Pointer to TELNET server */
545 /* logical_connection Logical connection entry */
546 /* */
547 /* OUTPUT */
548 /* */
549 /* status Completion status */
550 /* */
551 /* CALLS */
552 /* */
553 /* _nx_telnet_server_disconnect Actual server disconnect call */
554 /* */
555 /* CALLED BY */
556 /* */
557 /* Application Code */
558 /* */
559 /* RELEASE HISTORY */
560 /* */
561 /* DATE NAME DESCRIPTION */
562 /* */
563 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
564 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
565 /* resulting in version 6.1 */
566 /* */
567 /**************************************************************************/
_nxe_telnet_server_disconnect(NX_TELNET_SERVER * server_ptr,UINT logical_connection)568 UINT _nxe_telnet_server_disconnect(NX_TELNET_SERVER *server_ptr, UINT logical_connection)
569 {
570
571 UINT status;
572
573
574 /* Check for invalid input pointers. */
575 if ((server_ptr == NX_NULL) || (server_ptr -> nx_telnet_server_id != NX_TELNET_SERVER_ID))
576 return(NX_PTR_ERROR);
577
578 /* Check for a valid logical connection. */
579 if (logical_connection >= NX_TELNET_MAX_CLIENTS)
580 return(NX_OPTION_ERROR);
581
582 /* Check for appropriate caller. */
583 NX_THREADS_ONLY_CALLER_CHECKING
584
585 /* Call actual server disconnect function. */
586 status = _nx_telnet_server_disconnect(server_ptr, logical_connection);
587
588 /* Return completion status. */
589 return(status);
590 }
591
592
593 /**************************************************************************/
594 /* */
595 /* FUNCTION RELEASE */
596 /* */
597 /* _nx_telnet_server_disconnect PORTABLE C */
598 /* 6.2.1 */
599 /* AUTHOR */
600 /* */
601 /* Yuxin Zhou, Microsoft Corporation */
602 /* */
603 /* DESCRIPTION */
604 /* */
605 /* This function processes server disconnect requests made by the */
606 /* application receive data callback function. */
607 /* */
608 /* INPUT */
609 /* */
610 /* server_ptr Pointer to TELNET server */
611 /* logical_connection Logical connection entry */
612 /* */
613 /* OUTPUT */
614 /* */
615 /* status Completion status */
616 /* */
617 /* CALLS */
618 /* */
619 /* nx_tcp_server_socket_relisten Relisten on Telnet port */
620 /* nx_tcp_server_socket_unaccept Socket unaccept */
621 /* nx_tcp_socket_disconnect Socket disconnect */
622 /* */
623 /* CALLED BY */
624 /* */
625 /* Application Code */
626 /* */
627 /* RELEASE HISTORY */
628 /* */
629 /* DATE NAME DESCRIPTION */
630 /* */
631 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
632 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
633 /* resulting in version 6.1 */
634 /* 03-08-2023 Wenhui Xie Modified comment(s), and */
635 /* corrected the processing of */
636 /* disconnection, */
637 /* resulting in version 6.2.1 */
638 /* */
639 /**************************************************************************/
_nx_telnet_server_disconnect(NX_TELNET_SERVER * server_ptr,UINT logical_connection)640 UINT _nx_telnet_server_disconnect(NX_TELNET_SERVER *server_ptr, UINT logical_connection)
641 {
642
643 UINT i;
644 UINT status;
645 NX_TELNET_CLIENT_REQUEST *client_ptr;
646
647 /* Set a pointer to the indicated client connection. */
648 client_ptr = &(server_ptr -> nx_telnet_server_client_list[logical_connection]);
649
650 /* Determine if the connection is alive. */
651 if (client_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_state >= NX_TCP_ESTABLISHED)
652 {
653
654 /* Disconnect the socket. */
655 nx_tcp_socket_disconnect(&(client_ptr -> nx_telnet_client_request_socket), NX_TELNET_SERVER_TIMEOUT);
656
657 /* Unaccept this socket. */
658 nx_tcp_server_socket_unaccept(&(client_ptr -> nx_telnet_client_request_socket));
659
660 /* Update number of current open connections. */
661 if (server_ptr -> nx_telnet_server_open_connections > 0)
662 server_ptr -> nx_telnet_server_open_connections--;
663
664 /* Clear the client request activity timeout. */
665 client_ptr -> nx_telnet_client_request_activity_timeout = 0;
666
667 /* Call the application's end connection callback routine. */
668 if (server_ptr -> nx_telnet_connection_end)
669 {
670
671 /* Yes, there is a connection end callback routine - call it! */
672 (server_ptr -> nx_telnet_connection_end)(server_ptr, client_ptr -> nx_telnet_client_request_connection);
673 }
674 }
675 else
676 {
677
678 /* Error, disconnecting an unconnected socket. */
679 return(NX_TELNET_NOT_CONNECTED);
680 }
681
682 /* Now look for a socket that is closed to relisten on. */
683 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
684 {
685
686 /* Set a pointer to client request structure. */
687 client_ptr = &(server_ptr -> nx_telnet_server_client_list[i]);
688
689 /* Now see if this socket is closed. */
690 if (client_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_state == NX_TCP_CLOSED)
691 {
692
693 /* Relisten on this socket. */
694 status = nx_tcp_server_socket_relisten(server_ptr -> nx_telnet_server_ip_ptr, NX_TELNET_SERVER_PORT,
695 &(client_ptr -> nx_telnet_client_request_socket));
696 /* Check for bad status. */
697 if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
698 {
699
700 /* Increment the error count and keep trying. */
701 server_ptr -> nx_telnet_server_relisten_errors++;
702 continue;
703 }
704
705 /* Break out of loop. */
706 break;
707 }
708 }
709
710 /* Return success. */
711 return(NX_SUCCESS);
712 }
713
714
715 /**************************************************************************/
716 /* */
717 /* FUNCTION RELEASE */
718 /* */
719 /* _nxe_telnet_server_packet_send PORTABLE C */
720 /* 6.1 */
721 /* AUTHOR */
722 /* */
723 /* Yuxin Zhou, Microsoft Corporation */
724 /* */
725 /* DESCRIPTION */
726 /* */
727 /* This function checks for errors in the TELNET server packet send */
728 /* call. */
729 /* */
730 /* */
731 /* INPUT */
732 /* */
733 /* server_ptr Pointer to TELNET server */
734 /* logical_connection Logical connection entry */
735 /* packet_ptr Packet pointer to send */
736 /* wait_option Suspension option */
737 /* */
738 /* OUTPUT */
739 /* */
740 /* status Completion status */
741 /* */
742 /* CALLS */
743 /* */
744 /* _nx_telnet_server_packet_send Actual server packet send call*/
745 /* */
746 /* CALLED BY */
747 /* */
748 /* Application Code */
749 /* */
750 /* RELEASE HISTORY */
751 /* */
752 /* DATE NAME DESCRIPTION */
753 /* */
754 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
755 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
756 /* resulting in version 6.1 */
757 /* */
758 /**************************************************************************/
_nxe_telnet_server_packet_send(NX_TELNET_SERVER * server_ptr,UINT logical_connection,NX_PACKET * packet_ptr,ULONG wait_option)759 UINT _nxe_telnet_server_packet_send(NX_TELNET_SERVER *server_ptr, UINT logical_connection, NX_PACKET *packet_ptr, ULONG wait_option)
760 {
761
762 UINT status;
763
764
765 /* Check for invalid input pointers. */
766 if ((server_ptr == NX_NULL) || (server_ptr -> nx_telnet_server_id != NX_TELNET_SERVER_ID) || (packet_ptr == NX_NULL))
767 return(NX_PTR_ERROR);
768
769 /* Check for a valid logical connection. */
770 if (logical_connection >= NX_TELNET_MAX_CLIENTS)
771 return(NX_OPTION_ERROR);
772
773 /* Check for appropriate caller. */
774 NX_THREADS_ONLY_CALLER_CHECKING
775
776 /* Call actual server packet send function. */
777 status = _nx_telnet_server_packet_send(server_ptr, logical_connection, packet_ptr, wait_option);
778
779 /* Return completion status. */
780 return(status);
781 }
782
783
784 /**************************************************************************/
785 /* */
786 /* FUNCTION RELEASE */
787 /* */
788 /* _nx_telnet_server_packet_send PORTABLE C */
789 /* 6.1 */
790 /* AUTHOR */
791 /* */
792 /* Yuxin Zhou, Microsoft Corporation */
793 /* */
794 /* DESCRIPTION */
795 /* */
796 /* This function processes packet send requests made from the */
797 /* application's receive data callback function. */
798 /* */
799 /* INPUT */
800 /* */
801 /* server_ptr Pointer to TELNET server */
802 /* logical_connection Logical connection entry */
803 /* packet_ptr Packet pointer to send */
804 /* wait_option Suspension option */
805 /* */
806 /* OUTPUT */
807 /* */
808 /* status Completion status */
809 /* */
810 /* CALLS */
811 /* */
812 /* nx_tcp_socket_send Send packet */
813 /* */
814 /* CALLED BY */
815 /* */
816 /* Application Code */
817 /* */
818 /* RELEASE HISTORY */
819 /* */
820 /* DATE NAME DESCRIPTION */
821 /* */
822 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
823 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
824 /* resulting in version 6.1 */
825 /* */
826 /**************************************************************************/
_nx_telnet_server_packet_send(NX_TELNET_SERVER * server_ptr,UINT logical_connection,NX_PACKET * packet_ptr,ULONG wait_option)827 UINT _nx_telnet_server_packet_send(NX_TELNET_SERVER *server_ptr, UINT logical_connection, NX_PACKET *packet_ptr, ULONG wait_option)
828 {
829
830 UINT status;
831 NX_TELNET_CLIENT_REQUEST *client_ptr;
832
833
834 /* Derive the pointer to the appropriate client connection. */
835 client_ptr = &(server_ptr -> nx_telnet_server_client_list[logical_connection]);
836
837 /* Send the packet to the client. */
838 status = nx_tcp_socket_send(&(client_ptr -> nx_telnet_client_request_socket), packet_ptr, wait_option);
839
840 /* Determine if the send was successful. */
841 if (status)
842 {
843
844 /* Map to a generic error. */
845 status = NX_TELNET_FAILED;
846 }
847
848 /* Return to caller. */
849 return(status);
850 }
851
852
853 /**************************************************************************/
854 /* */
855 /* FUNCTION RELEASE */
856 /* */
857 /* _nxe_telnet_server_start PORTABLE C */
858 /* 6.1 */
859 /* AUTHOR */
860 /* */
861 /* Yuxin Zhou, Microsoft Corporation */
862 /* */
863 /* DESCRIPTION */
864 /* */
865 /* This function checks for errors in the TELNET server start call. */
866 /* */
867 /* */
868 /* INPUT */
869 /* */
870 /* server_ptr Pointer to TELNET server */
871 /* */
872 /* OUTPUT */
873 /* */
874 /* status Completion status */
875 /* */
876 /* CALLS */
877 /* */
878 /* _nx_telnet_server_start Actual server start call */
879 /* */
880 /* CALLED BY */
881 /* */
882 /* Application Code */
883 /* */
884 /* RELEASE HISTORY */
885 /* */
886 /* DATE NAME DESCRIPTION */
887 /* */
888 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
889 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
890 /* resulting in version 6.1 */
891 /* */
892 /**************************************************************************/
_nxe_telnet_server_start(NX_TELNET_SERVER * server_ptr)893 UINT _nxe_telnet_server_start(NX_TELNET_SERVER *server_ptr)
894 {
895
896 UINT status;
897
898
899 /* Check for invalid input pointers. */
900 if ((server_ptr == NX_NULL) || (server_ptr -> nx_telnet_server_id != NX_TELNET_SERVER_ID))
901 return(NX_PTR_ERROR);
902
903 /* Call actual server start function. */
904 status = _nx_telnet_server_start(server_ptr);
905
906 /* Return completion status. */
907 return(status);
908 }
909
910
911 /**************************************************************************/
912 /* */
913 /* FUNCTION RELEASE */
914 /* */
915 /* _nx_telnet_server_start PORTABLE C */
916 /* 6.1 */
917 /* AUTHOR */
918 /* */
919 /* Yuxin Zhou, Microsoft Corporation */
920 /* */
921 /* DESCRIPTION */
922 /* */
923 /* This function starts a previously created TELNET server on the */
924 /* specified IP. */
925 /* */
926 /* */
927 /* INPUT */
928 /* */
929 /* server_ptr Pointer to TELNET server */
930 /* */
931 /* OUTPUT */
932 /* */
933 /* status Completion status */
934 /* NX_TELNET_NO_PACKET_POOL Telnet server packet pool not */
935 /* set yet */
936 /* */
937 /* CALLS */
938 /* */
939 /* nx_tcp_server_socket_listen Listen of TELNET clients */
940 /* tx_thread_resume Resume TELNET server thread */
941 /* tx_timer_activate Activate TELNET server timer */
942 /* */
943 /* CALLED BY */
944 /* */
945 /* Application Code */
946 /* */
947 /* RELEASE HISTORY */
948 /* */
949 /* DATE NAME DESCRIPTION */
950 /* */
951 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
952 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
953 /* resulting in version 6.1 */
954 /* */
955 /**************************************************************************/
_nx_telnet_server_start(NX_TELNET_SERVER * server_ptr)956 UINT _nx_telnet_server_start(NX_TELNET_SERVER *server_ptr)
957 {
958
959 UINT status;
960 ULONG events;
961
962 #ifndef NX_TELNET_SERVER_OPTION_DISABLE
963
964 /* Check for Telnet server packet pool we'll need to send options. */
965 if (server_ptr -> nx_telnet_server_packet_pool_ptr == NX_NULL)
966 {
967
968 /* The Telnet server packet pool is not set. */
969 return NX_TELNET_NO_PACKET_POOL;
970 }
971 #endif
972
973 /* Start listening on the TELNET socket. */
974 status = nx_tcp_server_socket_listen(server_ptr -> nx_telnet_server_ip_ptr, NX_TELNET_SERVER_PORT,
975 &(server_ptr -> nx_telnet_server_client_list[0].nx_telnet_client_request_socket),
976 NX_TELNET_MAX_CLIENTS, _nx_telnet_server_connection_present);
977
978 /* Determine if an error is present. */
979 if (status != NX_SUCCESS)
980 {
981
982 /* Error, return to caller. */
983 return(status);
984 }
985
986 /* Activate TELNET server timer. */
987 tx_timer_activate(&(server_ptr -> nx_telnet_server_timer));
988
989 /* Clear stop event. */
990 tx_event_flags_get(&(server_ptr -> nx_telnet_server_event_flags), NX_TELNET_STOP_EVENT, TX_OR_CLEAR, &events, TX_NO_WAIT);
991
992 /* Start the TELNET server thread. */
993 tx_thread_resume(&(server_ptr -> nx_telnet_server_thread));
994
995 /* Return successful completion. */
996 return(NX_SUCCESS);
997 }
998
999
1000 /**************************************************************************/
1001 /* */
1002 /* FUNCTION RELEASE */
1003 /* */
1004 /* _nxe_telnet_server_stop PORTABLE C */
1005 /* 6.1 */
1006 /* AUTHOR */
1007 /* */
1008 /* Yuxin Zhou, Microsoft Corporation */
1009 /* */
1010 /* DESCRIPTION */
1011 /* */
1012 /* This function checks for errors in the TELNET server stop call. */
1013 /* */
1014 /* */
1015 /* INPUT */
1016 /* */
1017 /* server_ptr Pointer to TELNET server */
1018 /* */
1019 /* OUTPUT */
1020 /* */
1021 /* status Completion status */
1022 /* */
1023 /* CALLS */
1024 /* */
1025 /* _nx_telnet_server_stop Actual server start call */
1026 /* */
1027 /* CALLED BY */
1028 /* */
1029 /* Application Code */
1030 /* */
1031 /* RELEASE HISTORY */
1032 /* */
1033 /* DATE NAME DESCRIPTION */
1034 /* */
1035 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1036 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1037 /* resulting in version 6.1 */
1038 /* */
1039 /**************************************************************************/
_nxe_telnet_server_stop(NX_TELNET_SERVER * server_ptr)1040 UINT _nxe_telnet_server_stop(NX_TELNET_SERVER *server_ptr)
1041 {
1042
1043 UINT status;
1044
1045
1046 /* Check for invalid input pointers. */
1047 if ((server_ptr == NX_NULL) || (server_ptr -> nx_telnet_server_id != NX_TELNET_SERVER_ID))
1048 return(NX_PTR_ERROR);
1049
1050 /* Check for appropriate caller. */
1051 NX_THREADS_ONLY_CALLER_CHECKING
1052
1053 /* Call actual server delete function. */
1054 status = _nx_telnet_server_stop(server_ptr);
1055
1056 /* Return completion status. */
1057 return(status);
1058 }
1059
1060
1061 /**************************************************************************/
1062 /* */
1063 /* FUNCTION RELEASE */
1064 /* */
1065 /* _nx_telnet_server_stop PORTABLE C */
1066 /* 6.1 */
1067 /* AUTHOR */
1068 /* */
1069 /* Yuxin Zhou, Microsoft Corporation */
1070 /* */
1071 /* DESCRIPTION */
1072 /* */
1073 /* This function stops a previously started TELNET server on the */
1074 /* specified IP. */
1075 /* */
1076 /* */
1077 /* INPUT */
1078 /* */
1079 /* server_ptr Pointer to TELNET server */
1080 /* */
1081 /* OUTPUT */
1082 /* */
1083 /* status Completion status */
1084 /* */
1085 /* CALLS */
1086 /* */
1087 /* tx_event_flags_set Set events for server thread */
1088 /* tx_timer_deactivate Deactivate TELNET server timer*/
1089 /* nx_tcp_server_socket_unaccept Unaccept server socket */
1090 /* nx_tcp_server_socket_unlisten Unlisten on server */
1091 /* nx_tcp_socket_disconnect Disconnect socket */
1092 /* */
1093 /* CALLED BY */
1094 /* */
1095 /* Application Code */
1096 /* */
1097 /* RELEASE HISTORY */
1098 /* */
1099 /* DATE NAME DESCRIPTION */
1100 /* */
1101 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1102 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1103 /* resulting in version 6.1 */
1104 /* */
1105 /**************************************************************************/
_nx_telnet_server_stop(NX_TELNET_SERVER * server_ptr)1106 UINT _nx_telnet_server_stop(NX_TELNET_SERVER *server_ptr)
1107 {
1108 UINT i;
1109 NX_TELNET_CLIENT_REQUEST *client_request_ptr;
1110
1111 /* Deactivate TELNET server timer. */
1112 tx_timer_deactivate(&(server_ptr -> nx_telnet_server_timer));
1113
1114 /* Suspend the TELNET server thread. */
1115 tx_event_flags_set(&(server_ptr -> nx_telnet_server_event_flags), NX_TELNET_STOP_EVENT, TX_OR);
1116
1117 /* Walk through the server structure to close and delete any open sockets. */
1118 i = 0;
1119 client_request_ptr = &(server_ptr -> nx_telnet_server_client_list[0]);
1120 while (i < NX_TELNET_MAX_CLIENTS)
1121 {
1122
1123 /* Disconnect the socket. */
1124 nx_tcp_socket_disconnect(&(client_request_ptr -> nx_telnet_client_request_socket), NX_NO_WAIT);
1125
1126 /* Unaccept the socket. */
1127 nx_tcp_server_socket_unaccept(&(client_request_ptr -> nx_telnet_client_request_socket));
1128
1129 /* Reset client request. */
1130 client_request_ptr -> nx_telnet_client_request_activity_timeout = 0;
1131
1132 /* Increment the pointer into the client request list. */
1133 client_request_ptr++;
1134 i++;
1135 }
1136
1137 /* Unlisten on the TELNET port. */
1138 nx_tcp_server_socket_unlisten(server_ptr -> nx_telnet_server_ip_ptr, NX_TELNET_SERVER_PORT);
1139
1140 /* Return successful completion. */
1141 return(NX_SUCCESS);
1142 }
1143
1144
1145 /**************************************************************************/
1146 /* */
1147 /* FUNCTION RELEASE */
1148 /* */
1149 /* _nxe_telnet_server_get_open_connection_count PORTABLE C */
1150 /* 6.1 */
1151 /* AUTHOR */
1152 /* */
1153 /* Yuxin Zhou, Microsoft Corporation */
1154 /* */
1155 /* DESCRIPTION */
1156 /* */
1157 /* This function checks for errors in the TELNET server get open */
1158 /* connection count service. */
1159 /* */
1160 /* */
1161 /* INPUT */
1162 /* */
1163 /* server_ptr Pointer to TELNET server */
1164 /* current_connections Pointer to # open connections */
1165 /* */
1166 /* OUTPUT */
1167 /* */
1168 /* status Completion status */
1169 /* */
1170 /* CALLS */
1171 /* */
1172 /* _nx_telnet_server_get_open_connection_count */
1173 /* Actual server get count call */
1174 /* */
1175 /* CALLED BY */
1176 /* */
1177 /* Application Code */
1178 /* */
1179 /* RELEASE HISTORY */
1180 /* */
1181 /* DATE NAME DESCRIPTION */
1182 /* */
1183 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1184 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1185 /* resulting in version 6.1 */
1186 /* */
1187 /**************************************************************************/
_nxe_telnet_server_get_open_connection_count(NX_TELNET_SERVER * server_ptr,UINT * current_connections)1188 UINT _nxe_telnet_server_get_open_connection_count(NX_TELNET_SERVER *server_ptr, UINT *current_connections)
1189 {
1190
1191 UINT status;
1192
1193
1194 /* Check for invalid input pointers. */
1195 if ((server_ptr == NX_NULL) || (current_connections == NX_NULL))
1196 return(NX_PTR_ERROR);
1197
1198 /* Check for appropriate caller. */
1199 NX_THREADS_ONLY_CALLER_CHECKING
1200
1201 /* Call actual server delete function. */
1202 status = _nx_telnet_server_get_open_connection_count(server_ptr, current_connections);
1203
1204 /* Return completion status. */
1205 return(status);
1206 }
1207
1208 /**************************************************************************/
1209 /* */
1210 /* FUNCTION RELEASE */
1211 /* */
1212 /* _nx_telnet_server_get_open_connection_count PORTABLE C */
1213 /* 6.1 */
1214 /* AUTHOR */
1215 /* */
1216 /* Yuxin Zhou, Microsoft Corporation */
1217 /* */
1218 /* DESCRIPTION */
1219 /* */
1220 /* This function returns the number of currently open connections. */
1221 /* */
1222 /* */
1223 /* INPUT */
1224 /* */
1225 /* server_ptr Pointer to TELNET server */
1226 /* current_connections Pointer to # open connections */
1227 /* */
1228 /* OUTPUT */
1229 /* */
1230 /* NX_SUCCESS Successful completion status */
1231 /* */
1232 /* CALLS */
1233 /* */
1234 /* None */
1235 /* */
1236 /* CALLED BY */
1237 /* */
1238 /* Application Code */
1239 /* */
1240 /* RELEASE HISTORY */
1241 /* */
1242 /* DATE NAME DESCRIPTION */
1243 /* */
1244 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1245 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1246 /* resulting in version 6.1 */
1247 /* */
1248 /**************************************************************************/
_nx_telnet_server_get_open_connection_count(NX_TELNET_SERVER * server_ptr,UINT * current_connections)1249 UINT _nx_telnet_server_get_open_connection_count(NX_TELNET_SERVER *server_ptr, UINT *current_connections)
1250 {
1251
1252 /* Retrieve server's record of open connections. */
1253 *current_connections = server_ptr -> nx_telnet_server_open_connections;
1254
1255 /* Return completion status. */
1256 return(NX_SUCCESS);
1257 }
1258
1259 /**************************************************************************/
1260 /* */
1261 /* FUNCTION RELEASE */
1262 /* */
1263 /* _nx_telnet_server_thread_entry PORTABLE C */
1264 /* 6.1 */
1265 /* AUTHOR */
1266 /* */
1267 /* Yuxin Zhou, Microsoft Corporation */
1268 /* */
1269 /* DESCRIPTION */
1270 /* */
1271 /* This function is the entry of the TELNET server. All basic */
1272 /* processing is initiated by this function. */
1273 /* */
1274 /* */
1275 /* INPUT */
1276 /* */
1277 /* telnet_server Pointer to TELNET server */
1278 /* */
1279 /* OUTPUT */
1280 /* */
1281 /* None */
1282 /* */
1283 /* CALLS */
1284 /* */
1285 /* _nx_telnet_server_connect_process Process connection */
1286 /* _nx_telnet_server_data_process Process received data */
1287 /* _nx_telnet_server_disconnect_process Process disconnection */
1288 /* _nx_telnet_server_timeout_processing Process activity timeout */
1289 /* tx_event_flags_get Get TELNET event(s) */
1290 /* tx_thread_suspend Suspend TELNET thread */
1291 /* */
1292 /* CALLED BY */
1293 /* */
1294 /* ThreadX */
1295 /* */
1296 /* RELEASE HISTORY */
1297 /* */
1298 /* DATE NAME DESCRIPTION */
1299 /* */
1300 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1301 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1302 /* resulting in version 6.1 */
1303 /* */
1304 /**************************************************************************/
_nx_telnet_server_thread_entry(ULONG telnet_server)1305 VOID _nx_telnet_server_thread_entry(ULONG telnet_server)
1306 {
1307
1308 NX_TELNET_SERVER *server_ptr;
1309 UINT status;
1310 ULONG events;
1311
1312
1313 /* Setup the server pointer. */
1314 server_ptr = (NX_TELNET_SERVER *) telnet_server;
1315
1316 /* Loop to process TELNET Server requests. */
1317 while(1)
1318 {
1319
1320 /* Wait for an TELNET client activity. */
1321 status = tx_event_flags_get(&(server_ptr -> nx_telnet_server_event_flags), NX_TELNET_ANY_EVENT, TX_OR_CLEAR, &events, TX_WAIT_FOREVER);
1322
1323 /* Check the return status. */
1324 if (status)
1325 {
1326
1327 /* If an error occurs, simply continue the loop. */
1328 continue;
1329 }
1330
1331 /* Check whether service is started. */
1332 if (events & NX_TELNET_STOP_EVENT)
1333 {
1334
1335 /* Suspend thread here. */
1336 tx_thread_suspend(&server_ptr -> nx_telnet_server_thread);
1337 continue;
1338 }
1339
1340 /* Otherwise, an event is present. Process according to the event. */
1341
1342 /* Check for a client connection event. */
1343 if (events & NX_TELNET_SERVER_CONNECT)
1344 {
1345
1346 /* Call the connect processing. */
1347 _nx_telnet_server_connect_process(server_ptr);
1348 }
1349
1350 /* Check for a TELNET client write data event. */
1351 if (events & NX_TELNET_SERVER_DATA)
1352 {
1353
1354 /* Call processing to handle server data. */
1355 _nx_telnet_server_data_process(server_ptr);
1356 }
1357
1358 /* Check for a client disconnect event. */
1359 if (events & NX_TELNET_SERVER_DISCONNECT)
1360 {
1361
1362 /* Call the disconnect processing. */
1363 _nx_telnet_server_disconnect_process(server_ptr);
1364 }
1365
1366 /* Check for a client activity timeout event. */
1367 if (events & NX_TELNET_SERVER_ACTIVITY_TIMEOUT)
1368 {
1369
1370 /* Call the activity timeout processing. */
1371 _nx_telnet_server_timeout_processing(server_ptr);
1372 }
1373 }
1374 }
1375
1376
1377 /**************************************************************************/
1378 /* */
1379 /* FUNCTION RELEASE */
1380 /* */
1381 /* _nx_telnet_server_connect_process PORTABLE C */
1382 /* 6.1 */
1383 /* AUTHOR */
1384 /* */
1385 /* Yuxin Zhou, Microsoft Corporation */
1386 /* */
1387 /* DESCRIPTION */
1388 /* */
1389 /* This function handles all TELNET client connections received. */
1390 /* */
1391 /* */
1392 /* INPUT */
1393 /* */
1394 /* server_ptr Pointer to TELNET server */
1395 /* */
1396 /* OUTPUT */
1397 /* */
1398 /* None */
1399 /* */
1400 /* CALLS */
1401 /* */
1402 /* nx_tcp_server_socket_accept Accept connection on socket */
1403 /* nx_tcp_server_socket_relisten Relisten for connection */
1404 /* nx_tcp_server_socket_unaccept Unaccept connection */
1405 /* */
1406 /* CALLED BY */
1407 /* */
1408 /* _nx_telnet_server_thread_entry TELNET server thread */
1409 /* */
1410 /* RELEASE HISTORY */
1411 /* */
1412 /* DATE NAME DESCRIPTION */
1413 /* */
1414 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1415 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1416 /* resulting in version 6.1 */
1417 /* */
1418 /**************************************************************************/
_nx_telnet_server_connect_process(NX_TELNET_SERVER * server_ptr)1419 VOID _nx_telnet_server_connect_process(NX_TELNET_SERVER *server_ptr)
1420 {
1421
1422 UINT i;
1423 UINT status;
1424 NX_TELNET_CLIENT_REQUEST *client_req_ptr;
1425
1426
1427 /* One of the client request sockets is in the process of connection. */
1428
1429 /* Search the connections to see which one. */
1430 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
1431 {
1432
1433 /* Setup pointer to client request structure. */
1434 client_req_ptr = &(server_ptr -> nx_telnet_server_client_list[i]);
1435
1436 /* Now see if this socket was the one that is in being connected. */
1437 if ((client_req_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_state > NX_TCP_CLOSED) &&
1438 (client_req_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_state < NX_TCP_ESTABLISHED) &&
1439 (client_req_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_connect_port))
1440 {
1441
1442 /* Yes, we have found the socket being connected. */
1443
1444 /* Increment the number of connection requests. */
1445 server_ptr -> nx_telnet_server_connection_requests++;
1446
1447 /* Attempt to accept on this socket. */
1448 status = nx_tcp_server_socket_accept(&(client_req_ptr -> nx_telnet_client_request_socket), NX_TELNET_SERVER_TIMEOUT);
1449
1450 /* Determine if it is successful. */
1451 if (status)
1452 {
1453
1454 /* Not successful, simply unaccept on this socket. */
1455 nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_telnet_client_request_socket));
1456 }
1457 else
1458 {
1459
1460 /* Reset the client request activity timeout. */
1461 client_req_ptr -> nx_telnet_client_request_activity_timeout = NX_TELNET_ACTIVITY_TIMEOUT;
1462
1463 /* Update number of current open connections. */
1464 server_ptr -> nx_telnet_server_open_connections++;
1465
1466 /* Call the application's new connection callback routine. */
1467 if (server_ptr -> nx_telnet_new_connection)
1468 {
1469 /* Yes, there is a new connection callback routine - call it! */
1470 (server_ptr -> nx_telnet_new_connection)(server_ptr, client_req_ptr -> nx_telnet_client_request_connection);
1471 }
1472
1473 /* Disable remote echo by default. */
1474 if(server_ptr -> nx_telnet_set_echo)
1475 server_ptr -> nx_telnet_set_echo(server_ptr, client_req_ptr -> nx_telnet_client_request_connection, NX_FALSE);
1476
1477 #ifndef NX_TELNET_SERVER_OPTION_DISABLE
1478
1479 /* Yes, send out server echo option requests. */
1480 status = _nx_telnet_server_send_option_requests(server_ptr, client_req_ptr);
1481 if(status != NX_SUCCESS)
1482 return;
1483 #endif /* NX_TELNET_SERVER_OPTION_DISABLE */
1484
1485 }
1486 }
1487 }
1488
1489 /* Now look for a socket that is closed to relisten on. */
1490 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
1491 {
1492
1493 /* Set a pointer to client request structure. */
1494 client_req_ptr = &(server_ptr -> nx_telnet_server_client_list[i]);
1495
1496 /* Now see if this socket is closed. */
1497 if (client_req_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_state == NX_TCP_CLOSED)
1498 {
1499
1500 /* Relisten on this socket. */
1501 status = nx_tcp_server_socket_relisten(server_ptr -> nx_telnet_server_ip_ptr, NX_TELNET_SERVER_PORT,
1502 &(client_req_ptr -> nx_telnet_client_request_socket));
1503 /* Check for bad status. */
1504 if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
1505 {
1506
1507 /* Increment the error count and keep trying. */
1508 server_ptr -> nx_telnet_server_relisten_errors++;
1509 continue;
1510 }
1511
1512 /* Break out of loop. */
1513 break;
1514 }
1515 }
1516 }
1517
1518
1519 /**************************************************************************/
1520 /* */
1521 /* FUNCTION RELEASE */
1522 /* */
1523 /* _nx_telnet_server_connection_present PORTABLE C */
1524 /* 6.1 */
1525 /* AUTHOR */
1526 /* */
1527 /* Yuxin Zhou, Microsoft Corporation */
1528 /* */
1529 /* DESCRIPTION */
1530 /* */
1531 /* This function handles all TELNET client connections received on */
1532 /* the socket. */
1533 /* */
1534 /* */
1535 /* INPUT */
1536 /* */
1537 /* socket_ptr Socket event occurred */
1538 /* port Port the connection occurred */
1539 /* */
1540 /* OUTPUT */
1541 /* */
1542 /* None */
1543 /* */
1544 /* CALLS */
1545 /* */
1546 /* tx_event_flags_set Set events for server thread */
1547 /* */
1548 /* CALLED BY */
1549 /* */
1550 /* NetX NetX connect callback */
1551 /* */
1552 /* RELEASE HISTORY */
1553 /* */
1554 /* DATE NAME DESCRIPTION */
1555 /* */
1556 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1557 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1558 /* resulting in version 6.1 */
1559 /* */
1560 /**************************************************************************/
_nx_telnet_server_connection_present(NX_TCP_SOCKET * socket_ptr,UINT port)1561 VOID _nx_telnet_server_connection_present(NX_TCP_SOCKET *socket_ptr, UINT port)
1562 {
1563
1564 NX_TELNET_SERVER *server_ptr;
1565
1566 NX_PARAMETER_NOT_USED(port);
1567
1568 /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
1569 server_ptr = socket_ptr -> nx_tcp_socket_reserved_ptr;
1570
1571 /* Set the connect event flag. */
1572 tx_event_flags_set(&(server_ptr -> nx_telnet_server_event_flags), NX_TELNET_SERVER_CONNECT, TX_OR);
1573 }
1574
1575
1576 /**************************************************************************/
1577 /* */
1578 /* FUNCTION RELEASE */
1579 /* */
1580 /* _nx_telnet_server_disconnect_present PORTABLE C */
1581 /* 6.1 */
1582 /* AUTHOR */
1583 /* */
1584 /* Yuxin Zhou, Microsoft Corporation */
1585 /* */
1586 /* DESCRIPTION */
1587 /* */
1588 /* This function handles all TELNET client disconnections received on */
1589 /* the socket. */
1590 /* */
1591 /* */
1592 /* INPUT */
1593 /* */
1594 /* socket_ptr Socket event occurred */
1595 /* */
1596 /* OUTPUT */
1597 /* */
1598 /* None */
1599 /* */
1600 /* CALLS */
1601 /* */
1602 /* tx_event_flags_set Set events for server thread */
1603 /* */
1604 /* CALLED BY */
1605 /* */
1606 /* NetX NetX connect callback */
1607 /* */
1608 /* RELEASE HISTORY */
1609 /* */
1610 /* DATE NAME DESCRIPTION */
1611 /* */
1612 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1613 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1614 /* resulting in version 6.1 */
1615 /* */
1616 /**************************************************************************/
_nx_telnet_server_disconnect_present(NX_TCP_SOCKET * socket_ptr)1617 VOID _nx_telnet_server_disconnect_present(NX_TCP_SOCKET *socket_ptr)
1618 {
1619
1620 NX_TELNET_SERVER *server_ptr;
1621
1622 /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
1623 server_ptr = socket_ptr -> nx_tcp_socket_reserved_ptr;
1624
1625 /* Set the disconnect event flag. */
1626 tx_event_flags_set(&(server_ptr -> nx_telnet_server_event_flags), NX_TELNET_SERVER_DISCONNECT, TX_OR);
1627 }
1628
1629
1630 /**************************************************************************/
1631 /* */
1632 /* FUNCTION RELEASE */
1633 /* */
1634 /* _nx_telnet_server_disconnect_process PORTABLE C */
1635 /* 6.1 */
1636 /* AUTHOR */
1637 /* */
1638 /* Yuxin Zhou, Microsoft Corporation */
1639 /* */
1640 /* DESCRIPTION */
1641 /* */
1642 /* This function processes all TELNET client disconnections received */
1643 /* on the socket. */
1644 /* */
1645 /* */
1646 /* INPUT */
1647 /* */
1648 /* server_ptr Pointer to TELNET server */
1649 /* */
1650 /* OUTPUT */
1651 /* */
1652 /* None */
1653 /* */
1654 /* CALLS */
1655 /* */
1656 /* nx_tcp_server_socket_relisten Relisten on Telnet port */
1657 /* nx_tcp_server_socket_unaccept Unaccept connection */
1658 /* nx_tcp_socket_disconnect Disconnect socket */
1659 /* */
1660 /* CALLED BY */
1661 /* */
1662 /* _nx_telnet_server_thread_entry TELNET server thread */
1663 /* */
1664 /* RELEASE HISTORY */
1665 /* */
1666 /* DATE NAME DESCRIPTION */
1667 /* */
1668 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1669 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1670 /* resulting in version 6.1 */
1671 /* */
1672 /**************************************************************************/
_nx_telnet_server_disconnect_process(NX_TELNET_SERVER * server_ptr)1673 VOID _nx_telnet_server_disconnect_process(NX_TELNET_SERVER *server_ptr)
1674 {
1675
1676 UINT i;
1677 UINT status;
1678 NX_TELNET_CLIENT_REQUEST *client_req_ptr;
1679 UINT reset_client_request;
1680
1681
1682 /* Now look for a socket that has a disconnect state. */
1683 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
1684 {
1685
1686 reset_client_request = NX_FALSE;
1687
1688 /* Setup pointer to client request structure. */
1689 client_req_ptr = &(server_ptr -> nx_telnet_server_client_list[i]);
1690
1691 /* Has the socket received a RST packet? If so NetX will put it in a CLOSED or LISTEN state
1692 and the socket activity timeout has not been reset yet. */
1693 if (client_req_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_state < NX_TCP_SYN_SENT)
1694 {
1695
1696 if (client_req_ptr -> nx_telnet_client_request_activity_timeout > 0)
1697 {
1698
1699 reset_client_request = NX_TRUE;
1700 }
1701 }
1702 else
1703 {
1704
1705 /* Now see if this socket has entered a disconnect state. */
1706 while (client_req_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_state > NX_TCP_ESTABLISHED)
1707 {
1708
1709 /* Yes, a disconnect is present, which signals an end of session for TELNET request. */
1710
1711 /* First, cleanup this socket. */
1712 nx_tcp_socket_disconnect(&(client_req_ptr -> nx_telnet_client_request_socket), NX_TELNET_SERVER_TIMEOUT);
1713
1714 reset_client_request = NX_TRUE;
1715 }
1716 }
1717
1718 /* If this connection is closed, update the telnet data and notify the application of a disconnect. */
1719 if (reset_client_request == NX_TRUE)
1720 {
1721
1722 /* Unaccept this socket. */
1723 nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_telnet_client_request_socket));
1724
1725 /* Reset the client request activity timeout. */
1726 client_req_ptr -> nx_telnet_client_request_activity_timeout = 0;
1727
1728 /* Update number of current open connections. */
1729 if (server_ptr -> nx_telnet_server_open_connections > 0)
1730 server_ptr -> nx_telnet_server_open_connections--;
1731
1732 /* Call the application's end connection callback routine. */
1733 if (server_ptr -> nx_telnet_connection_end)
1734 {
1735
1736 /* Yes, there is a connection end callback routine - call it! */
1737 (server_ptr -> nx_telnet_connection_end)(server_ptr, client_req_ptr -> nx_telnet_client_request_connection);
1738 }
1739 }
1740 }
1741
1742 /* Now look for a socket that is closed to relisten on. */
1743 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
1744 {
1745
1746 /* Setup pointer to client request structure. */
1747 client_req_ptr = &(server_ptr -> nx_telnet_server_client_list[i]);
1748
1749 /* Now see if this socket is closed. */
1750 if (client_req_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_state == NX_TCP_CLOSED)
1751 {
1752
1753 /* Relisten on this socket. */
1754 status = nx_tcp_server_socket_relisten(server_ptr -> nx_telnet_server_ip_ptr, NX_TELNET_SERVER_PORT,
1755 &(client_req_ptr -> nx_telnet_client_request_socket));
1756 /* Check for bad status. */
1757 if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
1758 {
1759
1760 /* Increment the error count and keep trying. */
1761 server_ptr -> nx_telnet_server_relisten_errors++;
1762 continue;
1763 }
1764
1765 /* Break out of loop. */
1766 break;
1767 }
1768 }
1769 }
1770
1771
1772 /**************************************************************************/
1773 /* */
1774 /* FUNCTION RELEASE */
1775 /* */
1776 /* _nx_telnet_server_data_present PORTABLE C */
1777 /* 6.1 */
1778 /* AUTHOR */
1779 /* */
1780 /* Yuxin Zhou, Microsoft Corporation */
1781 /* */
1782 /* DESCRIPTION */
1783 /* */
1784 /* This function notifies the TELNET server thread of data received */
1785 /* from a client on the socket. */
1786 /* */
1787 /* */
1788 /* INPUT */
1789 /* */
1790 /* socket_ptr Socket event occurred */
1791 /* */
1792 /* OUTPUT */
1793 /* */
1794 /* None */
1795 /* */
1796 /* CALLS */
1797 /* */
1798 /* tx_event_flags_set Set events for server thread */
1799 /* */
1800 /* CALLED BY */
1801 /* */
1802 /* NetX NetX connect callback */
1803 /* */
1804 /* RELEASE HISTORY */
1805 /* */
1806 /* DATE NAME DESCRIPTION */
1807 /* */
1808 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1809 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1810 /* resulting in version 6.1 */
1811 /* */
1812 /**************************************************************************/
_nx_telnet_server_data_present(NX_TCP_SOCKET * socket_ptr)1813 VOID _nx_telnet_server_data_present(NX_TCP_SOCKET *socket_ptr)
1814 {
1815
1816 NX_TELNET_SERVER *server_ptr;
1817
1818 /* Pickup server pointer. This is setup in the reserved field of the TCP socket. */
1819 server_ptr = socket_ptr -> nx_tcp_socket_reserved_ptr;
1820
1821 /* Set the data event flag. */
1822 tx_event_flags_set(&(server_ptr -> nx_telnet_server_event_flags), NX_TELNET_SERVER_DATA, TX_OR);
1823 }
1824
1825
1826 /**************************************************************************/
1827 /* */
1828 /* FUNCTION RELEASE */
1829 /* */
1830 /* _nx_telnet_server_data_process PORTABLE C */
1831 /* 6.1 */
1832 /* AUTHOR */
1833 /* */
1834 /* Yuxin Zhou, Microsoft Corporation */
1835 /* */
1836 /* DESCRIPTION */
1837 /* */
1838 /* This function processes all TELNET client data packets received on */
1839 /* the request socket. */
1840 /* */
1841 /* */
1842 /* INPUT */
1843 /* */
1844 /* server_ptr Pointer to TELNET server */
1845 /* */
1846 /* OUTPUT */
1847 /* */
1848 /* None */
1849 /* */
1850 /* CALLS */
1851 /* */
1852 /* nx_packet_release Release packet */
1853 /* nx_tcp_socket_receive Receive from socket */
1854 /* */
1855 /* CALLED BY */
1856 /* */
1857 /* _nx_telnet_server_thread_entry TELNET server thread */
1858 /* */
1859 /* RELEASE HISTORY */
1860 /* */
1861 /* DATE NAME DESCRIPTION */
1862 /* */
1863 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1864 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1865 /* resulting in version 6.1 */
1866 /* */
1867 /**************************************************************************/
_nx_telnet_server_data_process(NX_TELNET_SERVER * server_ptr)1868 VOID _nx_telnet_server_data_process(NX_TELNET_SERVER *server_ptr)
1869 {
1870
1871 UINT i;
1872 UINT status;
1873 NX_PACKET *packet_ptr;
1874 NX_TELNET_CLIENT_REQUEST *client_req_ptr;
1875 #ifndef NX_TELNET_SERVER_OPTION_DISABLE
1876 UCHAR data_char;
1877 UINT offset;
1878 #endif /* NX_TELNET_SERVER_OPTION_DISABLE */
1879
1880 /* Now look for a socket that has receive data. */
1881 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
1882 {
1883
1884 /* Setup pointer to client request structure. */
1885 client_req_ptr = &(server_ptr -> nx_telnet_server_client_list[i]);
1886
1887 /* Now see if this socket has data. If so, process all of it now! */
1888 while (client_req_ptr -> nx_telnet_client_request_socket.nx_tcp_socket_receive_queue_count)
1889 {
1890
1891 /* Reset the client request activity timeout. */
1892 client_req_ptr -> nx_telnet_client_request_activity_timeout = NX_TELNET_ACTIVITY_TIMEOUT;
1893
1894 /* Attempt to read a packet from this socket. */
1895 status = nx_tcp_socket_receive(&(client_req_ptr -> nx_telnet_client_request_socket), &packet_ptr, NX_NO_WAIT);
1896
1897 /* Check for not data present. */
1898 if (status != NX_SUCCESS)
1899 {
1900
1901 /* Break to look at the next socket. */
1902 break;
1903 }
1904
1905 #ifndef NX_TELNET_SERVER_OPTION_DISABLE
1906
1907 /* If the first byte of the packet data is the telnet "IAC" code,
1908 this is a telnet option packet. */
1909 if (*packet_ptr -> nx_packet_prepend_ptr == NX_TELNET_IAC)
1910 {
1911
1912 #ifndef NX_DISABLE_PACKET_CHAIN
1913 if (packet_ptr -> nx_packet_next)
1914 {
1915
1916 /* Chained packet is not supported. */
1917 nx_packet_release(packet_ptr);
1918 break;
1919 }
1920 #endif /* NX_DISABLE_PACKET_CHAIN */
1921
1922 /* We will use an offset to mark the beginning of each telnet option, if there is more
1923 than one, in the packet payload. */
1924 offset = 0;
1925
1926 /* Validate the packet length. */
1927 if (packet_ptr -> nx_packet_length == 1)
1928 {
1929 nx_packet_release(packet_ptr);
1930 break;
1931 }
1932
1933 /* Set the work pointer to just past the telnet IAC tag. */
1934 data_char = *(packet_ptr -> nx_packet_prepend_ptr + 1);
1935
1936 /* Verify the next byte is a valid Telnet option code. */
1937 if ((data_char >= NX_TELNET_WILL) && (data_char <= NX_TELNET_DONT))
1938 {
1939
1940 /* Process the entire packet for telnet options, ensuring we don't go off the end of the payload. */
1941 while((offset < packet_ptr -> nx_packet_length) && (*(packet_ptr -> nx_packet_prepend_ptr + offset) == NX_TELNET_IAC))
1942 {
1943
1944 /* Process this telnet option. The offset will be updated to the location
1945 of the next option (if there is one) on return of this function. */
1946 _nx_telnet_server_process_option(server_ptr, packet_ptr, &offset, client_req_ptr);
1947 }
1948 }
1949
1950 /* Are there any data left? */
1951 if ((offset < packet_ptr -> nx_packet_length) && (server_ptr -> nx_telnet_receive_data))
1952 {
1953
1954 /* Yes. Adjust packet. */
1955 packet_ptr -> nx_packet_prepend_ptr += offset;
1956 packet_ptr -> nx_packet_length -= offset;
1957
1958 /* Yes, there is a process data callback routine - call it! */
1959 (server_ptr -> nx_telnet_receive_data)(server_ptr, client_req_ptr -> nx_telnet_client_request_connection, packet_ptr);
1960 }
1961 else
1962 {
1963
1964 /* We're done with this packet. */
1965 nx_packet_release(packet_ptr);
1966 }
1967
1968 /* Check if the echo negotiation is successful. */
1969 if((client_req_ptr -> nx_telnet_client_agree_server_will_SGA_success == NX_TRUE) &&
1970 (client_req_ptr -> nx_telnet_client_agree_server_will_echo_success == NX_TRUE))
1971 {
1972
1973 /* Enable remote echo. */
1974 if(server_ptr -> nx_telnet_set_echo)
1975 server_ptr -> nx_telnet_set_echo(server_ptr, client_req_ptr -> nx_telnet_client_request_connection, NX_TRUE);
1976 }
1977 }
1978
1979 /* It's not an option packet. */
1980 else
1981 {
1982
1983 /* Check server receive callback. */
1984 if (server_ptr -> nx_telnet_receive_data)
1985 {
1986
1987 /* Yes, there is a process data callback routine - call it! */
1988 (server_ptr -> nx_telnet_receive_data)(server_ptr, client_req_ptr -> nx_telnet_client_request_connection, packet_ptr);
1989 }
1990 else
1991 {
1992
1993 /* Error, no application callback routine. */
1994
1995 /* Release the packet and continue the loop. */
1996 nx_packet_release(packet_ptr);
1997 }
1998 }
1999 #else
2000 if (*packet_ptr -> nx_packet_prepend_ptr == NX_TELNET_IAC)
2001 {
2002 nx_packet_release(packet_ptr);
2003 }
2004 /* Call the server receive callback. */
2005 else if (server_ptr -> nx_telnet_receive_data)
2006 {
2007
2008 /* Yes, there is a process data callback routine - call it! */
2009 (server_ptr -> nx_telnet_receive_data)(server_ptr, client_req_ptr -> nx_telnet_client_request_connection, packet_ptr);
2010 }
2011 else
2012 {
2013
2014 /* Error, no application callback routine. */
2015
2016 /* Release the packet and continue the loop. */
2017 nx_packet_release(packet_ptr);
2018 }
2019
2020 #endif /* NX_TELNET_SERVER_OPTION_DISABLE */
2021 }
2022 }
2023 }
2024
2025
2026 /**************************************************************************/
2027 /* */
2028 /* FUNCTION RELEASE */
2029 /* */
2030 /* _nx_telnet_server_timeout PORTABLE C */
2031 /* 6.1 */
2032 /* AUTHOR */
2033 /* */
2034 /* Yuxin Zhou, Microsoft Corporation */
2035 /* */
2036 /* DESCRIPTION */
2037 /* */
2038 /* This function is the periodic timer for this TELNET server. Its */
2039 /* duty is to inform the TELNET server that it is time to check for */
2040 /* activity timeouts. */
2041 /* */
2042 /* */
2043 /* INPUT */
2044 /* */
2045 /* telnet_server_address TELNET server's address */
2046 /* */
2047 /* OUTPUT */
2048 /* */
2049 /* None */
2050 /* */
2051 /* CALLS */
2052 /* */
2053 /* tx_event_flags_set Set events for server thread */
2054 /* */
2055 /* CALLED BY */
2056 /* */
2057 /* ThreadX ThreadX timer callback */
2058 /* */
2059 /* RELEASE HISTORY */
2060 /* */
2061 /* DATE NAME DESCRIPTION */
2062 /* */
2063 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2064 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2065 /* resulting in version 6.1 */
2066 /* */
2067 /**************************************************************************/
_nx_telnet_server_timeout(ULONG telnet_server_address)2068 VOID _nx_telnet_server_timeout(ULONG telnet_server_address)
2069 {
2070
2071 NX_TELNET_SERVER *server_ptr;
2072
2073 /* Pickup server pointer. */
2074 server_ptr = (NX_TELNET_SERVER *) telnet_server_address;
2075
2076 /* Set the data event flag. */
2077 tx_event_flags_set(&(server_ptr -> nx_telnet_server_event_flags), NX_TELNET_SERVER_ACTIVITY_TIMEOUT, TX_OR);
2078 }
2079
2080
2081 /**************************************************************************/
2082 /* */
2083 /* FUNCTION RELEASE */
2084 /* */
2085 /* _nx_telnet_server_timeout_processing PORTABLE C */
2086 /* 6.1 */
2087 /* AUTHOR */
2088 /* */
2089 /* Yuxin Zhou, Microsoft Corporation */
2090 /* */
2091 /* DESCRIPTION */
2092 /* */
2093 /* This function reviews all the active TELNET client connections and */
2094 /* looks for an activity timeout. If a connection has not had any */
2095 /* activity within NX_TELNET_ACTIVITY_TIMEOUT seconds, the connection */
2096 /* is deleted and its resources are made available to a new connection.*/
2097 /* */
2098 /* */
2099 /* INPUT */
2100 /* */
2101 /* server_ptr Pointer to TELNET server */
2102 /* */
2103 /* OUTPUT */
2104 /* */
2105 /* None */
2106 /* */
2107 /* CALLS */
2108 /* */
2109 /* nx_tcp_server_socket_relisten Relisten for another connect */
2110 /* nx_tcp_server_socket_unaccept Unaccept server connection */
2111 /* nx_tcp_socket_disconnect Disconnect socket */
2112 /* */
2113 /* CALLED BY */
2114 /* */
2115 /* _nx_telnet_server_thread_entry TELNET server thread */
2116 /* */
2117 /* RELEASE HISTORY */
2118 /* */
2119 /* DATE NAME DESCRIPTION */
2120 /* */
2121 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2122 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2123 /* resulting in version 6.1 */
2124 /* */
2125 /**************************************************************************/
_nx_telnet_server_timeout_processing(NX_TELNET_SERVER * server_ptr)2126 VOID _nx_telnet_server_timeout_processing(NX_TELNET_SERVER *server_ptr)
2127 {
2128
2129 UINT i;
2130 NX_TELNET_CLIENT_REQUEST *client_req_ptr;
2131
2132
2133 /* Now look through all the sockets. */
2134 for (i = 0; i < NX_TELNET_MAX_CLIENTS; i++)
2135 {
2136
2137 /* Set a pointer to client request structure. */
2138 client_req_ptr = &(server_ptr -> nx_telnet_server_client_list[i]);
2139
2140 /* Now see if this socket has an activity timeout active. */
2141 if (client_req_ptr -> nx_telnet_client_request_activity_timeout)
2142 {
2143
2144 /* Decrement the activity timeout for this client request. */
2145 if (client_req_ptr -> nx_telnet_client_request_activity_timeout > NX_TELNET_TIMEOUT_PERIOD)
2146 client_req_ptr -> nx_telnet_client_request_activity_timeout = client_req_ptr -> nx_telnet_client_request_activity_timeout - NX_TELNET_TIMEOUT_PERIOD;
2147 else
2148 client_req_ptr -> nx_telnet_client_request_activity_timeout = 0;
2149
2150 /* Determine if this entry has exceeded the activity timeout. */
2151 if (client_req_ptr -> nx_telnet_client_request_activity_timeout == 0)
2152 {
2153
2154 /* Yes, the activity timeout has been exceeded. Tear down and clean up the
2155 entire client request structure. */
2156
2157 /* Increment the activity timeout counter. */
2158 server_ptr -> nx_telnet_server_activity_timeouts++;
2159
2160 /* Now disconnect the command socket. */
2161 nx_tcp_socket_disconnect(&(client_req_ptr -> nx_telnet_client_request_socket), NX_NO_WAIT);
2162
2163 /* Unaccept the server socket. */
2164 nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_telnet_client_request_socket));
2165
2166 /* Relisten on this socket. This will probably fail, but it is needed just in case all available
2167 clients were in use at the time of the last relisten. */
2168 nx_tcp_server_socket_relisten(server_ptr -> nx_telnet_server_ip_ptr, NX_TELNET_SERVER_PORT,
2169 &(client_req_ptr -> nx_telnet_client_request_socket));
2170
2171 /* Update number of current open connections. */
2172 if (server_ptr -> nx_telnet_server_open_connections > 0)
2173 server_ptr -> nx_telnet_server_open_connections--;
2174
2175 /* Call the application's end connection callback routine. */
2176 if (server_ptr -> nx_telnet_connection_end)
2177 {
2178
2179 /* Yes, there is a connection end callback routine - call it! */
2180 (server_ptr -> nx_telnet_connection_end)(server_ptr, client_req_ptr -> nx_telnet_client_request_connection);
2181 }
2182 }
2183 }
2184 }
2185 }
2186
2187 #ifndef NX_TELNET_SERVER_OPTION_DISABLE
2188
2189 #ifdef NX_TELNET_SERVER_USER_CREATE_PACKET_POOL
2190 /**************************************************************************/
2191 /* */
2192 /* FUNCTION RELEASE */
2193 /* */
2194 /* _nxe_telnet_server_packet_pool_set PORTABLE C */
2195 /* 6.1 */
2196 /* AUTHOR */
2197 /* */
2198 /* Yuxin Zhou, Microsoft Corporation */
2199 /* */
2200 /* DESCRIPTION */
2201 /* */
2202 /* This function checks for errors in the TELNET server create packet */
2203 /* pool call. */
2204 /* */
2205 /* */
2206 /* INPUT */
2207 /* */
2208 /* server_ptr Pointer to TELNET server */
2209 /* pool_ptr Pointer to telnet packet pool */
2210 /* */
2211 /* OUTPUT */
2212 /* */
2213 /* status Completion status */
2214 /* NX_PTR_ERROR Invalid pointer input */
2215 /* */
2216 /* CALLS */
2217 /* */
2218 /* _nx_telnet_server_packet_pool_set Actual set packet pool call */
2219 /* */
2220 /* CALLED BY */
2221 /* */
2222 /* Application Code */
2223 /* */
2224 /* RELEASE HISTORY */
2225 /* */
2226 /* DATE NAME DESCRIPTION */
2227 /* */
2228 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2229 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2230 /* resulting in version 6.1 */
2231 /* */
2232 /**************************************************************************/
2233
_nxe_telnet_server_packet_pool_set(NX_TELNET_SERVER * server_ptr,NX_PACKET_POOL * pool_ptr)2234 UINT _nxe_telnet_server_packet_pool_set(NX_TELNET_SERVER *server_ptr, NX_PACKET_POOL *pool_ptr)
2235 {
2236
2237 UINT status;
2238
2239 /* Check for invalid pointer input. */
2240 if ((server_ptr == NX_NULL) || (pool_ptr == NX_NULL))
2241 {
2242 return NX_PTR_ERROR;
2243 }
2244
2245 /* Actual set packet pool service. */
2246 status = _nx_telnet_server_packet_pool_set(server_ptr, pool_ptr);
2247
2248 return status;
2249 }
2250
2251 /**************************************************************************/
2252 /* */
2253 /* FUNCTION RELEASE */
2254 /* */
2255 /* _nxe_telnet_server_packet_pool_set PORTABLE C */
2256 /* 6.1 */
2257 /* AUTHOR */
2258 /* */
2259 /* Yuxin Zhou, Microsoft Corporation */
2260 /* */
2261 /* DESCRIPTION */
2262 /* */
2263 /* This function sets the Telnet Server packet pool to the packet pool */
2264 /* created outside the Telnet Server domain. This permits the packet */
2265 /* pool memory to be in a different location from the Telnet Server. */
2266 /* */
2267 /* The Telnet Server only uses this packet pool for sending Telnet */
2268 /* options (requires NX_TELNET_SERVER_OPTION_DISABLE not be defined). */
2269 /* */
2270 /* Note: This will overwrite an existing Telnet Server packet pool if */
2271 /* one was previously set. */
2272 /* */
2273 /* INPUT */
2274 /* */
2275 /* server_ptr Pointer to TELNET server */
2276 /* pool_ptr Pointer to telnet packet pool */
2277 /* */
2278 /* OUTPUT */
2279 /* */
2280 /* NX_SUCCESS Telnet server packet pool */
2281 /* successfully set */
2282 /* */
2283 /* CALLS */
2284 /* */
2285 /* None */
2286 /* */
2287 /* CALLED BY */
2288 /* */
2289 /* Application Code */
2290 /* */
2291 /* RELEASE HISTORY */
2292 /* */
2293 /* DATE NAME DESCRIPTION */
2294 /* */
2295 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2296 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2297 /* resulting in version 6.1 */
2298 /* */
2299 /**************************************************************************/
_nx_telnet_server_packet_pool_set(NX_TELNET_SERVER * server_ptr,NX_PACKET_POOL * pool_ptr)2300 UINT _nx_telnet_server_packet_pool_set(NX_TELNET_SERVER *server_ptr, NX_PACKET_POOL *pool_ptr)
2301 {
2302
2303
2304 server_ptr -> nx_telnet_server_packet_pool_ptr = pool_ptr;
2305
2306 return NX_SUCCESS;
2307 }
2308
2309 #endif /* NX_TELNET_SERVER_USER_CREATE_PACKET_POOL */
2310 /**************************************************************************/
2311 /* */
2312 /* FUNCTION RELEASE */
2313 /* */
2314 /* _nx_telnet_server_create_option_packet PORTABLE C */
2315 /* 6.1 */
2316 /* AUTHOR */
2317 /* */
2318 /* Yuxin Zhou, Microsoft Corporation */
2319 /* */
2320 /* DESCRIPTION */
2321 /* */
2322 /* This function creates option packet for specified type and id. */
2323 /* */
2324 /* INPUT */
2325 /* */
2326 /* option_message_type Option type */
2327 /* option_id Option_id */
2328 /* stream Output buffer */
2329 /* */
2330 /* OUTPUT */
2331 /* */
2332 /* None */
2333 /* */
2334 /* CALLS */
2335 /* */
2336 /* None */
2337 /* */
2338 /* CALLED BY */
2339 /* */
2340 /* _nx_telnet_server_send_option_requests Send telnet option */
2341 /* */
2342 /* RELEASE HISTORY */
2343 /* */
2344 /* DATE NAME DESCRIPTION */
2345 /* */
2346 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2347 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2348 /* resulting in version 6.1 */
2349 /* */
2350 /**************************************************************************/
_nx_telnet_server_create_option_packet(UCHAR option_message_type,UCHAR option_id,UCHAR * stream)2351 VOID _nx_telnet_server_create_option_packet(UCHAR option_message_type, UCHAR option_id, UCHAR *stream)
2352 {
2353
2354 *(stream++) = NX_TELNET_IAC;
2355 *(stream++) = option_message_type;
2356 *stream = option_id;
2357 }
2358
2359 /**************************************************************************/
2360 /* */
2361 /* FUNCTION RELEASE */
2362 /* */
2363 /* _nx_telnet_server_send_option_requests PORTABLE C */
2364 /* 6.1 */
2365 /* AUTHOR */
2366 /* */
2367 /* Yuxin Zhou, Microsoft Corporation */
2368 /* */
2369 /* DESCRIPTION */
2370 /* */
2371 /* This function is called if 1) the server is configured to send out */
2372 /* options without waiting to receive client option requests, or 2)after*/
2373 /* receiving a client's initial option requests. This will send out */
2374 /* those option requests the server did not receive from the client */
2375 /* based on the server session option list. */
2376 /* */
2377 /* This function obtains mutex protection on the client session record */
2378 /* to update the record with options sent out from the server. */
2379 /* */
2380 /* INPUT */
2381 /* */
2382 /* server_ptr Pointer to telnet server */
2383 /* client_req_ptr Pointer to client record */
2384 /* */
2385 /* OUTPUT */
2386 /* */
2387 /* status Completion status */
2388 /* */
2389 /* CALLS */
2390 /* */
2391 /* nx_packet_allocate Allocate packet from pool */
2392 /* nx_packet_release Release packet back to pool */
2393 /* nx_packet_data_append Append data to packet payload */
2394 /* _nx_telnet_server_create_option_packet */
2395 /* Create telnet option message */
2396 /* _nx_telnet_server_packet_send Send telnet option to client */
2397 /* */
2398 /* CALLED BY */
2399 /* */
2400 /* _nx_telnet_server_data_process Top level telnet packet handler*/
2401 /* _nx_telnet_server_connect_process Telnet connection handler */
2402 /* */
2403 /* RELEASE HISTORY */
2404 /* */
2405 /* DATE NAME DESCRIPTION */
2406 /* */
2407 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2408 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2409 /* resulting in version 6.1 */
2410 /* */
2411 /**************************************************************************/
_nx_telnet_server_send_option_requests(NX_TELNET_SERVER * server_ptr,NX_TELNET_CLIENT_REQUEST * client_req_ptr)2412 UINT _nx_telnet_server_send_option_requests(NX_TELNET_SERVER *server_ptr, NX_TELNET_CLIENT_REQUEST *client_req_ptr)
2413 {
2414 UINT status;
2415 NX_PACKET *packet_ptr;
2416 UINT option_length;
2417 UINT packet_available;
2418 UCHAR option_stream[9];
2419
2420 status = NX_SUCCESS;
2421
2422 /* Indicate packet not available, nor needing to be released. */
2423 packet_available = NX_FALSE;
2424
2425 /* Allocate a packet for replies to send to this telnet client. */
2426 status = nx_packet_allocate(server_ptr -> nx_telnet_server_packet_pool_ptr, &packet_ptr, NX_TCP_PACKET, NX_NO_WAIT);
2427
2428 if (status != NX_SUCCESS)
2429 return status;
2430
2431 /* Now a packet is available, and if not used should be released. */
2432 packet_available = NX_TRUE;
2433
2434 /* Initialize option data to zero bytes. */
2435 option_length = 0;
2436
2437 client_req_ptr -> nx_telnet_client_agree_server_will_echo_success = NX_FALSE;
2438 client_req_ptr -> nx_telnet_client_agree_server_will_SGA_success = NX_FALSE;
2439
2440 /* Yes, create will echo request (3 bytes). */
2441 _nx_telnet_server_create_option_packet(NX_TELNET_WILL, NX_TELNET_ECHO, &option_stream[0]);
2442
2443 /* Yes, create dont echo request (3 bytes). */
2444 _nx_telnet_server_create_option_packet(NX_TELNET_DONT, NX_TELNET_ECHO, &option_stream[3]);
2445
2446 /* Yes, create will SGA request (3 bytes). */
2447 _nx_telnet_server_create_option_packet(NX_TELNET_WILL, NX_TELNET_SGA, &option_stream[6]);
2448
2449 /* Update the the packet payload for number of bytes for a telnet option request. */
2450 option_length = 9;
2451
2452 /* Add to the packet payload. */
2453 status = nx_packet_data_append(packet_ptr, option_stream, 9, server_ptr -> nx_telnet_server_packet_pool_ptr, NX_WAIT_FOREVER);
2454
2455 if (status)
2456 {
2457 nx_packet_release(packet_ptr);
2458 return(status);
2459 }
2460
2461 /* Check if we have a packet started, but not sent yet. */
2462 if (option_length > 0)
2463 {
2464
2465 /* Send the telnet packet out to the client. */
2466 status = _nx_telnet_server_packet_send(server_ptr, client_req_ptr -> nx_telnet_client_request_connection, packet_ptr, 100);
2467
2468 /* If errors sending, we need to release the packet. */
2469 if (status != NX_SUCCESS)
2470 {
2471 nx_packet_release(packet_ptr);
2472 return status;
2473 }
2474
2475 /* Indicate we need another packet, just sent out the last one. */
2476 packet_available = NX_FALSE;
2477 }
2478
2479 /* Check for unused packet (needs to be released). */
2480 if (packet_available == NX_TRUE)
2481 {
2482
2483 /* Release the packet we did not use. */
2484 nx_packet_release(packet_ptr);
2485 }
2486 return status;
2487 }
2488
2489 /**************************************************************************/
2490 /* */
2491 /* FUNCTION RELEASE */
2492 /* */
2493 /* _nx_telnet_server_process_option PORTABLE C */
2494 /* 6.1 */
2495 /* AUTHOR */
2496 /* */
2497 /* Yuxin Zhou, Microsoft Corporation */
2498 /* */
2499 /* DESCRIPTION */
2500 /* */
2501 /* This function examines the telnet option in the current packet and */
2502 /* determines if it is a new client request, an option with */
2503 /* subnegotiation data for the server, or a response to a previously */
2504 /* sent server telnet option request to the client. It then forwards */
2505 /* the telnet option information to the appropriate telnet processor. */
2506 /* */
2507 /* */
2508 /* INPUT */
2509 /* */
2510 /* server_ptr Pointer to TELNET server */
2511 /* packet_ptr Packet with telnet option */
2512 /* offset Option offset in packet */
2513 /* client_req_ptr Telnet client sending packet */
2514 /* */
2515 /* OUTPUT */
2516 /* */
2517 /* NX_TELNET_SESSION_OPTIONS_FULL Session option list is fill */
2518 /* NX_SUCCESS Option successfully processed */
2519 /* */
2520 /* CALLS */
2521 /* _nx_telnet_server_update_server_session_attributes */
2522 /* Updates server telnet features*/
2523 /* _nx_telnet_server_update_client_session_attributes */
2524 /* Updates client telnet features*/
2525 /* _nx_telnet_server_process_new_option Add new option to session list*/
2526 /* _nx_telnet_server_respond_to_pending_option */
2527 /* Send server reply to option */
2528 /* _nx_telnet_server_process_subnegotiation_data */
2529 /* Process received option specs */
2530 /* _nx_telnet_server_validate_option_change */
2531 /* Determine if option is dupe */
2532 /* Process received option specs */
2533 /* CALLED BY */
2534 /* */
2535 /* _nx_telnet_server_data_process Top level incoming telnet */
2536 /* packet handler */
2537 /* */
2538 /* RELEASE HISTORY */
2539 /* */
2540 /* DATE NAME DESCRIPTION */
2541 /* */
2542 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2543 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2544 /* resulting in version 6.1 */
2545 /* */
2546 /**************************************************************************/
2547
_nx_telnet_server_process_option(NX_TELNET_SERVER * server_ptr,NX_PACKET * packet_ptr,UINT * offset,NX_TELNET_CLIENT_REQUEST * client_req_ptr)2548 VOID _nx_telnet_server_process_option(NX_TELNET_SERVER *server_ptr, NX_PACKET *packet_ptr, UINT *offset,
2549 NX_TELNET_CLIENT_REQUEST *client_req_ptr)
2550 {
2551 UCHAR data_char;
2552 UCHAR *work_ptr;
2553
2554 NX_PARAMETER_NOT_USED(server_ptr);
2555
2556 /* Set the work pointer to see what option received. */
2557 work_ptr = (UCHAR *)(packet_ptr -> nx_packet_prepend_ptr + (*offset) + 2);
2558
2559 /* This option isn't complete, just move to the end of the packet. */
2560 if (work_ptr >= packet_ptr -> nx_packet_append_ptr)
2561 {
2562 *offset = packet_ptr -> nx_packet_length;
2563 return;
2564 }
2565
2566 data_char = *work_ptr;
2567
2568 /* If it is a echo option. */
2569 if(data_char == NX_TELNET_ECHO)
2570 {
2571
2572 /* Check whether the client replies with echo negotiation of the local echo disabled. */
2573 work_ptr--;
2574 data_char = *work_ptr;
2575 if(data_char == NX_TELNET_DO)
2576 {
2577
2578 /* Server will echo what received from the telnet connection. */
2579 client_req_ptr -> nx_telnet_client_agree_server_will_echo_success = NX_TRUE;
2580
2581 /* Move the offset to past the option. */
2582 (*offset)+=3;
2583 }
2584 else
2585 {
2586
2587 /* Move the offset to past the option. */
2588 (*offset)+=3;
2589 }
2590 }
2591
2592 /* If it is a SGA option. */
2593 else if(data_char == NX_TELNET_SGA)
2594 {
2595
2596 /* Check whether the client replies with SGA negotiation. */
2597 work_ptr--;
2598 data_char = *work_ptr;
2599 if(data_char == NX_TELNET_DO)
2600 {
2601
2602 /* Server will enable SGA option. */
2603 client_req_ptr -> nx_telnet_client_agree_server_will_SGA_success = NX_TRUE;
2604
2605 /* Move the offset to past the option. */
2606 (*offset)+=3;
2607 }
2608 else
2609 {
2610 /* Move the offset to past the option. */
2611 (*offset)+=3;
2612 return;
2613 }
2614 }
2615
2616 /* We have not implemented this option, just return. */
2617 else
2618 {
2619
2620 /* See next three bytes. */
2621 (*offset)+=3;
2622 return;
2623 }
2624 }
2625 #endif /* NX_TELNET_SERVER_OPTION_DISABLE */
2626