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 Component                                                        */
16 /**                                                                       */
17 /**   Transmission Control Protocol (TCP)                                 */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "nx_api.h"
28 #include "nx_ip.h"
29 #include "nx_packet.h"
30 #include "nx_tcp.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _nx_tcp_periodic_processing                         PORTABLE C      */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Yuxin Zhou, Microsoft Corporation                                   */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function processes periodic TCP processing for detecting       */
46 /*    TCP transmit timeouts.  If a transmit timeout occurs, the packet    */
47 /*    is simply resent and a new timeout is setup.                        */
48 /*                                                                        */
49 /*    Note this requires that NX_ENABLE_TCP_KEEPALIVE is enabled when the */
50 /*    NetX library is built.                                              */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    ip_ptr                                Pointer to IP control block   */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    None                                                                */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    _nx_tcp_packet_send_ack               Send ACK probe message        */
63 /*    _nx_tcp_socket_connection_reset       Reset the connection          */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    _nx_ip_thread_entry                   IP helper thread              */
68 /*                                                                        */
69 /*  RELEASE HISTORY                                                       */
70 /*                                                                        */
71 /*    DATE              NAME                      DESCRIPTION             */
72 /*                                                                        */
73 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
74 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
75 /*                                            resulting in version 6.1    */
76 /*                                                                        */
77 /**************************************************************************/
_nx_tcp_periodic_processing(NX_IP * ip_ptr)78 VOID  _nx_tcp_periodic_processing(NX_IP *ip_ptr)
79 {
80 
81 #ifdef NX_ENABLE_TCP_KEEPALIVE
82 NX_TCP_SOCKET *socket_ptr;
83 ULONG          sockets;
84 UINT           keepalive_enabled = NX_FALSE;
85 
86 
87     /* Pickup the number of created TCP sockets.  */
88     sockets =  ip_ptr -> nx_ip_tcp_created_sockets_count;
89 
90     /* Pickup the first socket.  */
91     socket_ptr =  ip_ptr -> nx_ip_tcp_created_sockets_ptr;
92 
93     /* Get the keepalive status of the current socket. */
94     if (socket_ptr)
95     {
96 
97         keepalive_enabled = socket_ptr -> nx_tcp_socket_keepalive_enabled;
98     }
99 
100     /* Loop through the created sockets.  */
101     while ((sockets--) && socket_ptr)
102     {
103 
104         /* Is keep alive enabled on this socket? */
105         if (keepalive_enabled)
106         {
107 
108             /* Yes; Check for the socket having a TCP Keepalive timer active.  */
109             if ((socket_ptr -> nx_tcp_socket_state == NX_TCP_ESTABLISHED) && (socket_ptr -> nx_tcp_socket_keepalive_timeout))
110             {
111 
112                 /* Decrement the socket's keepalive timeout timer.  */
113                 socket_ptr -> nx_tcp_socket_keepalive_timeout--;
114 
115                 /* Determine if the keepalive timeout has expired.  */
116                 if (!socket_ptr -> nx_tcp_socket_keepalive_timeout)
117                 {
118 
119                     /* Yes, the timeout has expired.  Increment the retries and
120                        determine if there are any retries left.  */
121                     socket_ptr -> nx_tcp_socket_keepalive_retries++;
122                     if (socket_ptr -> nx_tcp_socket_keepalive_retries <= NX_TCP_KEEPALIVE_RETRIES)
123                     {
124 
125                         /* Yes, there are more retries left.  Set the next timeout expiration
126                            to the retry time instead of the initial time.  */
127                         socket_ptr -> nx_tcp_socket_keepalive_timeout =  NX_TCP_KEEPALIVE_RETRY;
128 
129                         /* Send Keepalive ACK probe to see if the other side of the connection
130                            is still there.  We need to decrement the ACK number first for the
131                            probe message and then restore the value immediately after the ACK
132                            is sent.  */
133                         _nx_tcp_packet_send_ack(socket_ptr, (socket_ptr -> nx_tcp_socket_tx_sequence - 1));
134                     }
135                     else
136                     {
137 
138                         /* The Keepalive timer retries have failed, enter a CLOSED state
139                            via the reset processing.  */
140                         _nx_tcp_socket_connection_reset(socket_ptr);
141                     }
142                 }
143             }
144         }
145 
146         /* Move to the next TCP socket.  */
147         socket_ptr =  socket_ptr -> nx_tcp_socket_created_next;
148 
149         /* Get the socket's keep alive status. */
150         keepalive_enabled = socket_ptr -> nx_tcp_socket_keepalive_enabled;
151     }
152 #else
153     NX_PARAMETER_NOT_USED(ip_ptr);
154 #endif
155 }
156 
157