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