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