xref: /FreeRTOS-Plus-TCP-v4.0.0/source/include/FreeRTOS_TCP_WIN.h (revision 1ab6eb88857cf1011bf1f8349b43a1c34c7ced0f)
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