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