1 /* 2 * FreeRTOS+TCP <DEVELOPMENT BRANCH> 3 * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 * this software and associated documentation files (the "Software"), to deal in 9 * the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 * the Software, and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * http://aws.amazon.com/freertos 25 * http://www.FreeRTOS.org 26 */ 27 28 /* 29 * FreeRTOS_TCP_WIN.c 30 * Module which handles the TCP windowing schemes for FreeRTOS-PLUS-TCP 31 */ 32 33 #ifndef FREERTOS_TCP_WIN_H 34 #define FREERTOS_TCP_WIN_H 35 36 /* *INDENT-OFF* */ 37 #ifdef __cplusplus 38 extern "C" { 39 #endif 40 /* *INDENT-ON* */ 41 42 /** @brief A very simple timer that registers the time that a packet was sent. It is used to trigger re-sending. */ 43 typedef struct xTCPTimerStruct 44 { 45 TickType_t uxBorn; /**< The time at which a packet was sent ( using xTaskGetTickCount() ). */ 46 } TCPTimer_t; 47 48 /** @brief This struct collects the properties of a TCP segment. A segment is a chunk of data which 49 * is sent in a single TCP packet, at most 1460 bytes. */ 50 typedef struct xTCP_SEGMENT 51 { 52 uint32_t ulSequenceNumber; /**< The sequence number of the first byte in this packet */ 53 int32_t lMaxLength; /**< Maximum space, number of bytes which can be stored in this segment */ 54 int32_t lDataLength; /**< Actual number of bytes */ 55 int32_t lStreamPos; /**< reference to the [t|r]xStream of the socket */ 56 TCPTimer_t xTransmitTimer; /**< saves a timestamp at the moment this segment gets transmitted (TX only) */ 57 union 58 { 59 struct 60 { 61 uint32_t 62 ucTransmitCount : 8, /**< Number of times the segment has been transmitted, used to calculate the RTT */ 63 ucDupAckCount : 8, /**< Counts the number of times that a higher segment was ACK'd. After 3 times a Fast Retransmission takes place */ 64 bOutstanding : 1, /**< It the peer's turn, we're just waiting for an ACK */ 65 bAcked : 1, /**< This segment has been acknowledged */ 66 bIsForRx : 1; /**< pdTRUE if segment is used for reception */ 67 } bits; 68 uint32_t ulFlags; 69 } u; /**< A collection of boolean flags. */ 70 #if ( ipconfigUSE_TCP_WIN != 0 ) 71 struct xLIST_ITEM xQueueItem; /**< TX only: segments can be linked in one of three queues: xPriorityQueue, xTxQueue, and xWaitQueue */ 72 struct xLIST_ITEM xSegmentItem; /**< With this item the segment can be connected to a list, depending on who is owning it */ 73 #endif 74 } TCPSegment_t; 75 76 /** @brief This struct describes the windows sizes, both for incoming and outgoing. */ 77 typedef struct xTCP_WINSIZE 78 { 79 uint32_t ulRxWindowLength; /**< The TCP window size of the incoming stream. */ 80 uint32_t ulTxWindowLength; /**< The TCP window size of the outgoing stream. */ 81 } TCPWinSize_t; 82 83 /** @brief If TCP time-stamps are being used, they will occupy 12 bytes in 84 * each packet, and thus the message space will become smaller. 85 * Keep this as a multiple of 4 */ 86 #if ( ipconfigUSE_TCP_WIN == 1 ) 87 #define ipSIZE_TCP_OPTIONS 16U 88 #else 89 #define ipSIZE_TCP_OPTIONS 12U 90 #endif 91 92 /** @brief Every TCP connection owns a TCP window for the administration of all packets 93 * It owns two sets of segment descriptors, incoming and outgoing 94 */ 95 typedef struct xTCP_WINDOW 96 { 97 union 98 { 99 struct 100 { 101 uint32_t 102 bHasInit : 1, /**< The window structure has been initialised */ 103 bSendFullSize : 1, /**< May only send packets with a size equal to MSS (for optimisation) */ 104 bTimeStamps : 1; /**< Socket is supposed to use TCP time-stamps. This depends on the */ 105 } bits; /**< party which opens the connection */ 106 uint32_t ulFlags; 107 } u; /**< A collection of boolean flags. */ 108 TCPWinSize_t xSize; /**< The TCP window sizes of the incoming and outgoing streams. */ 109 struct 110 { 111 uint32_t ulFirstSequenceNumber; /**< Logging & debug: the first segment received/sent in this connection 112 * for Tx: initial send sequence number (ISS) 113 * for Rx: initial receive sequence number (IRS) */ 114 uint32_t ulCurrentSequenceNumber; /**< Tx/Rx: the oldest sequence number not yet confirmed, also SND.UNA / RCV.NXT 115 * In other words: the sequence number of the left side of the sliding window */ 116 uint32_t ulFINSequenceNumber; /**< The sequence number which carried the FIN flag */ 117 uint32_t ulHighestSequenceNumber; /**< Sequence number of the right-most byte + 1 */ 118 } rx, /**< Sequence number of the incoming data stream. */ 119 tx; /**< Sequence number of the outgoing data stream. */ 120 uint32_t ulOurSequenceNumber; /**< The SEQ number we're sending out */ 121 uint32_t ulUserDataLength; /**< Number of bytes in Rx buffer which may be passed to the user, after having received a 'missing packet' */ 122 uint32_t ulNextTxSequenceNumber; /**< The sequence number given to the next byte to be added for transmission */ 123 int32_t lSRTT; /**< Smoothed Round Trip Time, it may increment quickly and it decrements slower */ 124 uint8_t ucOptionLength; /**< Number of valid bytes in ulOptionsData[] */ 125 #if ( ipconfigUSE_TCP_WIN == 1 ) 126 List_t xPriorityQueue; /**< Priority queue: segments which must be sent immediately */ 127 List_t xTxQueue; /**< Transmit queue: segments queued for transmission */ 128 List_t xWaitQueue; /**< Waiting queue: outstanding segments */ 129 TCPSegment_t * pxHeadSegment; /**< points to a segment which has not been transmitted and it's size is still growing (user data being added) */ 130 uint32_t ulOptionsData[ ipSIZE_TCP_OPTIONS / sizeof( uint32_t ) ]; /**< Contains the options we send out */ 131 List_t xTxSegments; /**< A linked list of all transmission segments, sorted on sequence number */ 132 List_t xRxSegments; /**< A linked list of reception segments, order depends on sequence of arrival */ 133 #else 134 /* For tiny TCP, there is only 1 outstanding TX segment */ 135 TCPSegment_t xTxSegment; /**< Priority queue */ 136 #endif 137 uint16_t usOurPortNumber; /**< Mostly for debugging/logging: our TCP port number */ 138 uint16_t usPeerPortNumber; /**< debugging/logging: the peer's TCP port number */ 139 uint16_t usMSS; /**< Current accepted MSS */ 140 uint16_t usMSSInit; /**< MSS as configured by the socket owner */ 141 } TCPWindow_t; 142 143 144 /*============================================================================= 145 * 146 * Creation and destruction 147 * 148 *=============================================================================*/ 149 150 /* Create and initialize a window */ 151 void vTCPWindowCreate( TCPWindow_t * pxWindow, 152 uint32_t ulRxWindowLength, 153 uint32_t ulTxWindowLength, 154 uint32_t ulAckNumber, 155 uint32_t ulSequenceNumber, 156 uint32_t ulMSS ); 157 158 /* Destroy a window (always returns NULL) 159 * It will free some resources: a collection of segments */ 160 void vTCPWindowDestroy( TCPWindow_t const * pxWindow ); 161 162 /* Initialize a window */ 163 void vTCPWindowInit( TCPWindow_t * pxWindow, 164 uint32_t ulAckNumber, 165 uint32_t ulSequenceNumber, 166 uint32_t ulMSS ); 167 168 /* Clean up allocated segments. Should only be called when FreeRTOS+TCP will no longer be used. */ 169 void vTCPSegmentCleanup( void ); 170 171 /*============================================================================= 172 * 173 * Rx functions 174 * 175 *=============================================================================*/ 176 177 /* if true may be passed directly to user (segment expected and window is empty) 178 * But pxWindow->ackno should always be used to set "BUF->ackno" */ 179 int32_t lTCPWindowRxCheck( TCPWindow_t * pxWindow, 180 uint32_t ulSequenceNumber, 181 uint32_t ulLength, 182 uint32_t ulSpace, 183 uint32_t * pulSkipCount ); 184 185 /* This function will be called as soon as a FIN is received. It will return true 186 * if there are no 'open' reception segments */ 187 BaseType_t xTCPWindowRxEmpty( const TCPWindow_t * pxWindow ); 188 189 /*============================================================================= 190 * 191 * Tx functions 192 * 193 *=============================================================================*/ 194 195 /* Adds data to the Tx-window */ 196 int32_t lTCPWindowTxAdd( TCPWindow_t * pxWindow, 197 uint32_t ulLength, 198 int32_t lPosition, 199 int32_t lMax ); 200 201 /* Check data to be sent and calculate the time period we may sleep */ 202 BaseType_t xTCPWindowTxHasData( TCPWindow_t const * pxWindow, 203 uint32_t ulWindowSize, 204 TickType_t * pulDelay ); 205 206 /* See if anything is left to be sent 207 * Function will be called when a FIN has been received. Only when the TX window is clean, 208 * it will return pdTRUE */ 209 BaseType_t xTCPWindowTxDone( const TCPWindow_t * pxWindow ); 210 211 /* Fetches data to be sent. 212 * 'plPosition' will point to a location with the circular data buffer: txStream */ 213 uint32_t ulTCPWindowTxGet( TCPWindow_t * pxWindow, 214 uint32_t ulWindowSize, 215 int32_t * plPosition ); 216 217 /* Receive a normal ACK */ 218 uint32_t ulTCPWindowTxAck( TCPWindow_t * pxWindow, 219 uint32_t ulSequenceNumber ); 220 221 /* Receive a SACK option */ 222 uint32_t ulTCPWindowTxSack( TCPWindow_t * pxWindow, 223 uint32_t ulFirst, 224 uint32_t ulLast ); 225 226 /** 227 * @brief Check if a > b, where a and b are rolling counters. 228 * 229 * @param[in] a: The value on the left-hand side. 230 * @param[in] b: The value on the right-hand side. 231 * 232 * @return pdTRUE if a > b, otherwise pdFALSE. 233 * 234 * @note GreaterThan is calculated as "( a - ( b + 1U ) ) < 0x80000000". 235 */ 236 BaseType_t xSequenceGreaterThan( uint32_t a, 237 uint32_t b ); 238 239 /** 240 * @brief Check if a < b, where a and b are rolling counters. 241 * 242 * @param[in] a: The value on the left-hand side. 243 * @param[in] b: The value on the right-hand side. 244 * 245 * @return pdTRUE if a < b, otherwise pdFALSE. 246 * 247 * @note LessThan is implemented as "( b - ( a + 1 ) ) < 0x80000000". 248 */ 249 BaseType_t xSequenceLessThan( uint32_t a, 250 uint32_t b ); 251 252 /* *INDENT-OFF* */ 253 #ifdef __cplusplus 254 } /* extern "C" */ 255 #endif 256 /* *INDENT-ON* */ 257 258 #endif /* FREERTOS_TCP_WIN_H */ 259