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)78VOID _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