xref: /FreeRTOS-Plus-TCP-v3.1.0/source/FreeRTOS_TCP_State_Handling.c (revision 37bdfe577f3b728058de714e2e747d3c78803f26)
1 /*
2  * FreeRTOS+TCP V3.1.0
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  * @file FreeRTOS_TCP_State_Handling.c
30  * @brief Module which handles the TCP protocol state transition for FreeRTOS+TCP.
31  *
32  * Endianness: in this module all ports and IP addresses are stored in
33  * host byte-order, except fields in the IP-packets
34  */
35 
36 /* Standard includes. */
37 #include <stdint.h>
38 #include <stdio.h>
39 
40 /* FreeRTOS includes. */
41 #include "FreeRTOS.h"
42 #include "task.h"
43 #include "queue.h"
44 #include "semphr.h"
45 
46 /* FreeRTOS+TCP includes. */
47 #include "FreeRTOS_IP.h"
48 #include "FreeRTOS_Sockets.h"
49 #include "FreeRTOS_IP_Private.h"
50 #include "FreeRTOS_UDP_IP.h"
51 #include "FreeRTOS_DHCP.h"
52 #include "NetworkInterface.h"
53 #include "NetworkBufferManagement.h"
54 #include "FreeRTOS_ARP.h"
55 
56 #include "FreeRTOS_TCP_Reception.h"
57 #include "FreeRTOS_TCP_Transmission.h"
58 #include "FreeRTOS_TCP_State_Handling.h"
59 #include "FreeRTOS_TCP_Utils.h"
60 
61 /* Just make sure the contents doesn't get compiled if TCP is not enabled. */
62 #if ipconfigUSE_TCP == 1
63 
64 /*
65  *  Called to handle the closure of a TCP connection.
66  */
67     static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t * pxSocket,
68                                        const NetworkBufferDescriptor_t * pxNetworkBuffer );
69 
70 /*
71  * Called from prvTCPHandleState() as long as the TCP status is eSYN_RECEIVED to
72  * eCONNECT_SYN.
73  */
74     static BaseType_t prvHandleSynReceived( FreeRTOS_Socket_t * pxSocket,
75                                             const NetworkBufferDescriptor_t * pxNetworkBuffer,
76                                             uint32_t ulReceiveLength,
77                                             UBaseType_t uxOptionsLength );
78 
79 /*
80  * Called from prvTCPHandleState() as long as the TCP status is eESTABLISHED.
81  */
82     static BaseType_t prvHandleEstablished( FreeRTOS_Socket_t * pxSocket,
83                                             NetworkBufferDescriptor_t ** ppxNetworkBuffer,
84                                             uint32_t ulReceiveLength,
85                                             UBaseType_t uxOptionsLength );
86 
87 /*
88  * After a listening socket receives a new connection, it may duplicate itself.
89  * The copying takes place in prvTCPSocketCopy.
90  */
91     static BaseType_t prvTCPSocketCopy( FreeRTOS_Socket_t * pxNewSocket,
92                                         FreeRTOS_Socket_t * pxSocket );
93 
94 /**
95  * @brief Check whether the socket is active or not.
96  *
97  * @param[in] ucStatus: The status of the socket.
98  *
99  * @return pdTRUE if the socket must be checked. Non-active sockets
100  *         are waiting for user action, either connect() or close().
101  */
prvTCPSocketIsActive(eIPTCPState_t eStatus)102     BaseType_t prvTCPSocketIsActive( eIPTCPState_t eStatus )
103     {
104         BaseType_t xResult;
105 
106         switch( eStatus )
107         {
108             case eCLOSED:
109             case eCLOSE_WAIT:
110             case eFIN_WAIT_2:
111             case eCLOSING:
112             case eTIME_WAIT:
113                 xResult = pdFALSE;
114                 break;
115 
116             case eTCP_LISTEN:
117             case eCONNECT_SYN:
118             case eSYN_FIRST:
119             case eSYN_RECEIVED:
120             case eESTABLISHED:
121             case eFIN_WAIT_1:
122             case eLAST_ACK:
123             default:
124                 xResult = pdTRUE;
125                 break;
126         }
127 
128         return xResult;
129     }
130 /*-----------------------------------------------------------*/
131 
132 
133 
134     #if ( ipconfigTCP_HANG_PROTECTION == 1 )
135 
136 /**
137  * @brief Some of the TCP states may only last a certain amount of time.
138  *        This function checks if the socket is 'hanging', i.e. staying
139  *        too long in the same state.
140  *
141  * @param[in] The socket to be checked.
142  *
143  * @return pdFALSE if no checks are needed, pdTRUE if checks were done, or negative
144  *         in case the socket has reached a critical time-out. The socket will go to
145  *         the eCLOSE_WAIT state.
146  */
prvTCPStatusAgeCheck(FreeRTOS_Socket_t * pxSocket)147         BaseType_t prvTCPStatusAgeCheck( FreeRTOS_Socket_t * pxSocket )
148         {
149             BaseType_t xResult;
150 
151             eIPTCPState_t eState = pxSocket->u.xTCP.eTCPState;
152 
153             switch( eState )
154             {
155                 case eESTABLISHED:
156 
157                     /* If the 'ipconfigTCP_KEEP_ALIVE' option is enabled, sockets in
158                      *  state ESTABLISHED can be protected using keep-alive messages. */
159                     xResult = pdFALSE;
160                     break;
161 
162                 case eCLOSED:
163                 case eTCP_LISTEN:
164                 case eCLOSE_WAIT:
165                     /* These 3 states may last for ever, up to the owner. */
166                     xResult = pdFALSE;
167                     break;
168 
169                 case eCONNECT_SYN:
170                 case eSYN_FIRST:
171                 case eSYN_RECEIVED:
172                 case eFIN_WAIT_1:
173                 case eFIN_WAIT_2:
174                 case eCLOSING:
175                 case eLAST_ACK:
176                 case eTIME_WAIT:
177                 default:
178 
179                     /* All other (non-connected) states will get anti-hanging
180                      * protection. */
181                     xResult = pdTRUE;
182                     break;
183             }
184 
185             if( xResult != pdFALSE )
186             {
187                 /* How much time has past since the last active moment which is
188                  * defined as A) a state change or B) a packet has arrived. */
189                 TickType_t xAge = xTaskGetTickCount() - pxSocket->u.xTCP.xLastActTime;
190 
191                 /* ipconfigTCP_HANG_PROTECTION_TIME is in units of seconds. */
192                 if( xAge > ( ( TickType_t ) ipconfigTCP_HANG_PROTECTION_TIME * ( TickType_t ) configTICK_RATE_HZ ) )
193                 {
194                     #if ( ipconfigHAS_DEBUG_PRINTF == 1 )
195                         {
196                             FreeRTOS_debug_printf( ( "Inactive socket closed: port %u rem %xip:%u status %s\n",
197                                                      pxSocket->usLocalPort,
198                                                      ( unsigned ) pxSocket->u.xTCP.ulRemoteIP,
199                                                      pxSocket->u.xTCP.usRemotePort,
200                                                      FreeRTOS_GetTCPStateName( ( UBaseType_t ) pxSocket->u.xTCP.eTCPState ) ) );
201                         }
202                     #endif /* ipconfigHAS_DEBUG_PRINTF */
203 
204                     /* Move to eCLOSE_WAIT, user may close the socket. */
205                     vTCPStateChange( pxSocket, eCLOSE_WAIT );
206 
207                     /* When 'bPassQueued' true, this socket is an orphan until it
208                      * gets connected. */
209                     if( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED )
210                     {
211                         /* vTCPStateChange() has called vSocketCloseNextTime()
212                          * in case the socket is not yet owned by the application.
213                          * Return a negative value to inform the caller that
214                          * the socket will be closed in the next cycle. */
215                         xResult = -1;
216                     }
217                 }
218             }
219 
220             return xResult;
221         }
222         /*-----------------------------------------------------------*/
223 
224     #endif /* if ( ipconfigTCP_HANG_PROTECTION == 1 ) */
225 
226 /**
227  * @brief prvTCPHandleFin() will be called to handle connection closure. The
228  *        closure starts when either a FIN has been received and accepted,
229  *        or when the socket has sent a FIN flag to the peer. Before being
230  *        called, it has been checked that both reception and transmission
231  *        are complete.
232  *
233  * @param[in] pxSocket: Socket owning the the connection.
234  * @param[in] pxNetworkBuffer: The network buffer carrying the TCP packet.
235  *
236  * @return Length of the packet to be sent.
237  */
prvTCPHandleFin(FreeRTOS_Socket_t * pxSocket,const NetworkBufferDescriptor_t * pxNetworkBuffer)238     static BaseType_t prvTCPHandleFin( FreeRTOS_Socket_t * pxSocket,
239                                        const NetworkBufferDescriptor_t * pxNetworkBuffer )
240     {
241         /* Map the ethernet buffer onto the ProtocolHeader_t struct for easy access to the fields. */
242 
243         /* MISRA Ref 11.3.1 [Misaligned access] */
244 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
245         /* coverity[misra_c_2012_rule_11_3_violation] */
246         ProtocolHeaders_t * pxProtocolHeaders = ( ( ProtocolHeaders_t * )
247                                                   &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) );
248         TCPHeader_t * pxTCPHeader = &( pxProtocolHeaders->xTCPHeader );
249         uint8_t ucIntermediateResult = 0, ucTCPFlags = pxTCPHeader->ucTCPFlags;
250         TCPWindow_t * pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
251         BaseType_t xSendLength = 0;
252         uint32_t ulAckNr = FreeRTOS_ntohl( pxTCPHeader->ulAckNr );
253 
254         if( ( ucTCPFlags & tcpTCP_FLAG_FIN ) != 0U )
255         {
256             pxTCPWindow->rx.ulCurrentSequenceNumber = pxTCPWindow->rx.ulFINSequenceNumber + 1U;
257         }
258 
259         if( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED )
260         {
261             /* We haven't yet replied with a FIN, do so now. */
262             pxTCPWindow->tx.ulFINSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;
263             pxSocket->u.xTCP.bits.bFinSent = pdTRUE_UNSIGNED;
264         }
265         else
266         {
267             /* We did send a FIN already, see if it's ACK'd. */
268             if( ulAckNr == ( pxTCPWindow->tx.ulFINSequenceNumber + 1U ) )
269             {
270                 pxSocket->u.xTCP.bits.bFinAcked = pdTRUE_UNSIGNED;
271             }
272         }
273 
274         if( pxSocket->u.xTCP.bits.bFinAcked == pdFALSE_UNSIGNED )
275         {
276             pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber;
277             pxTCPHeader->ucTCPFlags = ( uint8_t ) tcpTCP_FLAG_ACK | ( uint8_t ) tcpTCP_FLAG_FIN;
278 
279             /* And wait for the final ACK. */
280             vTCPStateChange( pxSocket, eLAST_ACK );
281         }
282         else
283         {
284             /* Our FIN has been ACK'd, the outgoing sequence number is now fixed. */
285             pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber + 1U;
286 
287             if( pxSocket->u.xTCP.bits.bFinRecv == pdFALSE_UNSIGNED )
288             {
289                 /* We have sent out a FIN but the peer hasn't replied with a FIN
290                  * yet. Do nothing for the moment. */
291                 pxTCPHeader->ucTCPFlags = 0U;
292             }
293             else
294             {
295                 if( pxSocket->u.xTCP.bits.bFinLast == pdFALSE_UNSIGNED )
296                 {
297                     /* This is the third of the three-way hand shake: the last
298                      * ACK. */
299                     pxTCPHeader->ucTCPFlags = tcpTCP_FLAG_ACK;
300                 }
301                 else
302                 {
303                     /* The other party started the closure, so we just wait for the
304                      * last ACK. */
305                     pxTCPHeader->ucTCPFlags = 0U;
306                 }
307 
308                 /* And wait for the user to close this socket. */
309                 vTCPStateChange( pxSocket, eCLOSE_WAIT );
310             }
311         }
312 
313         pxTCPWindow->ulOurSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;
314 
315         if( pxTCPHeader->ucTCPFlags != 0U )
316         {
317             ucIntermediateResult = uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + pxTCPWindow->ucOptionLength;
318             xSendLength = ( BaseType_t ) ucIntermediateResult;
319         }
320 
321         pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + pxTCPWindow->ucOptionLength ) << 2 );
322 
323         if( xTCPWindowLoggingLevel != 0 )
324         {
325             FreeRTOS_debug_printf( ( "TCP: send FIN+ACK (ack %u, cur/nxt %u/%u) ourSeqNr %u | Rx %u\n",
326                                      ( unsigned ) ( ulAckNr - pxTCPWindow->tx.ulFirstSequenceNumber ),
327                                      ( unsigned ) ( pxTCPWindow->tx.ulCurrentSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber ),
328                                      ( unsigned ) ( pxTCPWindow->ulNextTxSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber ),
329                                      ( unsigned ) ( pxTCPWindow->ulOurSequenceNumber - pxTCPWindow->tx.ulFirstSequenceNumber ),
330                                      ( unsigned ) ( pxTCPWindow->rx.ulCurrentSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ) ) );
331         }
332 
333         return xSendLength;
334     }
335     /*-----------------------------------------------------------*/
336 
337 
338 /**
339  * @brief prvHandleSynReceived(): called from prvTCPHandleState(). Called
340  *        from the states: eSYN_RECEIVED and eCONNECT_SYN. If the flags
341  *        received are correct, the socket will move to eESTABLISHED.
342  *
343  * @param[in] pxSocket: The socket handling the connection.
344  * @param[in] pxNetworkBuffer: The pointer to the network buffer carrying
345  *                             the packet.
346  * @param[in] ulReceiveLength: Length in bytes of the data received.
347  * @param[in] uxOptionsLength: Length of the TCP options in bytes.
348  *
349  * @return Length of the data to be sent.
350  */
prvHandleSynReceived(FreeRTOS_Socket_t * pxSocket,const NetworkBufferDescriptor_t * pxNetworkBuffer,uint32_t ulReceiveLength,UBaseType_t uxOptionsLength)351     static BaseType_t prvHandleSynReceived( FreeRTOS_Socket_t * pxSocket,
352                                             const NetworkBufferDescriptor_t * pxNetworkBuffer,
353                                             uint32_t ulReceiveLength,
354                                             UBaseType_t uxOptionsLength )
355     {
356         /* Map the ethernet buffer onto the ProtocolHeader_t struct for easy access to the fields. */
357 
358         /* MISRA Ref 11.3.1 [Misaligned access] */
359 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
360         /* coverity[misra_c_2012_rule_11_3_violation] */
361         ProtocolHeaders_t * pxProtocolHeaders = ( ( ProtocolHeaders_t * )
362                                                   &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
363         TCPHeader_t * pxTCPHeader = &pxProtocolHeaders->xTCPHeader;
364         TCPWindow_t * pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
365         uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;
366         uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber );
367         BaseType_t xSendLength = 0;
368         UBaseType_t uxIntermediateResult = 0U;
369 
370         /* Either expect a ACK or a SYN+ACK. */
371         uint8_t ucExpect = tcpTCP_FLAG_ACK;
372         const uint8_t ucFlagsMask = tcpTCP_FLAG_ACK | tcpTCP_FLAG_RST | tcpTCP_FLAG_SYN | tcpTCP_FLAG_FIN;
373 
374         if( pxSocket->u.xTCP.eTCPState == eCONNECT_SYN )
375         {
376             ucExpect |= tcpTCP_FLAG_SYN;
377         }
378 
379         if( ( ucTCPFlags & ucFlagsMask ) != ucExpect )
380         {
381             /* eSYN_RECEIVED: flags 0010 expected, not 0002. */
382             /* eSYN_RECEIVED: flags ACK  expected, not SYN. */
383             FreeRTOS_debug_printf( ( "%s: flags %04X expected, not %04X\n",
384                                      ( pxSocket->u.xTCP.eTCPState == ( uint8_t ) eSYN_RECEIVED ) ? "eSYN_RECEIVED" : "eCONNECT_SYN",
385                                      ucExpect, ucTCPFlags ) );
386 
387             /* In case pxSocket is not yet owned by the application, a closure
388              * of the socket will be scheduled for the next cycle. */
389             vTCPStateChange( pxSocket, eCLOSE_WAIT );
390 
391             /* Send RST with the expected sequence and ACK numbers,
392              * otherwise the packet will be ignored. */
393             pxTCPWindow->ulOurSequenceNumber = FreeRTOS_htonl( pxTCPHeader->ulAckNr );
394             pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber;
395 
396             pxTCPHeader->ucTCPFlags |= tcpTCP_FLAG_RST;
397 
398             uxIntermediateResult = uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength;
399             xSendLength = ( BaseType_t ) uxIntermediateResult;
400 
401             pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
402         }
403         else
404         {
405             pxTCPWindow->usPeerPortNumber = pxSocket->u.xTCP.usRemotePort;
406             pxTCPWindow->usOurPortNumber = pxSocket->usLocalPort;
407 
408             if( pxSocket->u.xTCP.eTCPState == eCONNECT_SYN )
409             {
410                 /* Map the Last packet onto the ProtocolHeader_t struct for easy access to the fields. */
411 
412                 /* MISRA Ref 11.3.1 [Misaligned access] */
413 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
414                 /* coverity[misra_c_2012_rule_11_3_violation] */
415                 ProtocolHeaders_t * pxLastHeaders = ( ( ProtocolHeaders_t * )
416                                                       &( pxSocket->u.xTCP.xPacket.u.ucLastPacket[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
417 
418                 /* Clear the SYN flag in lastPacket. */
419                 pxLastHeaders->xTCPHeader.ucTCPFlags = tcpTCP_FLAG_ACK;
420                 pxProtocolHeaders->xTCPHeader.ucTCPFlags = tcpTCP_FLAG_ACK;
421 
422                 /* This socket was the one connecting actively so now perform the
423                  * synchronisation. */
424                 vTCPWindowInit( &pxSocket->u.xTCP.xTCPWindow,
425                                 ulSequenceNumber, pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber, ( uint32_t ) pxSocket->u.xTCP.usMSS );
426                 pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + 1U;
427                 pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber + 1U;
428                 pxTCPWindow->tx.ulCurrentSequenceNumber++; /* because we send a TCP_SYN [ | TCP_ACK ]; */
429                 pxTCPWindow->ulNextTxSequenceNumber++;
430             }
431             else if( ulReceiveLength == 0U )
432             {
433                 pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber;
434             }
435             else
436             {
437                 /* Nothing. */
438             }
439 
440             /* The SYN+ACK has been confirmed, increase the next sequence number by
441              * 1. */
442             pxTCPWindow->ulOurSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1U;
443 
444             #if ( ipconfigUSE_TCP_WIN == 1 )
445                 {
446                     FreeRTOS_debug_printf( ( "TCP: %s %u => %xip:%u set ESTAB (scaling %u)\n",
447                                              ( pxSocket->u.xTCP.eTCPState == ( uint8_t ) eCONNECT_SYN ) ? "active" : "passive",
448                                              pxSocket->usLocalPort,
449                                              ( unsigned ) pxSocket->u.xTCP.ulRemoteIP,
450                                              pxSocket->u.xTCP.usRemotePort,
451                                              ( unsigned ) pxSocket->u.xTCP.bits.bWinScaling ) );
452                 }
453             #endif /* ipconfigUSE_TCP_WIN */
454 
455             if( ( pxSocket->u.xTCP.eTCPState == eCONNECT_SYN ) || ( ulReceiveLength != 0U ) )
456             {
457                 pxTCPHeader->ucTCPFlags = tcpTCP_FLAG_ACK;
458 
459                 uxIntermediateResult = uxIPHeaderSizeSocket( pxSocket ) + ( size_t ) ipSIZE_OF_TCP_HEADER + uxOptionsLength;
460                 xSendLength = ( BaseType_t ) uxIntermediateResult;
461                 pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
462             }
463 
464             #if ( ipconfigUSE_TCP_WIN != 0 )
465                 {
466                     if( pxSocket->u.xTCP.bits.bWinScaling == pdFALSE_UNSIGNED )
467                     {
468                         /* The other party did not send a scaling factor.
469                          * A shifting factor in this side must be canceled. */
470                         pxSocket->u.xTCP.ucMyWinScaleFactor = 0;
471                         pxSocket->u.xTCP.ucPeerWinScaleFactor = 0;
472                     }
473                 }
474             #endif /* ipconfigUSE_TCP_WIN */
475 
476             /* This was the third step of connecting: SYN, SYN+ACK, ACK so now the
477              * connection is established. */
478             vTCPStateChange( pxSocket, eESTABLISHED );
479         }
480 
481         return xSendLength;
482     }
483     /*-----------------------------------------------------------*/
484 
485 /**
486  * @brief prvHandleEstablished(): called from prvTCPHandleState()
487  *        Called if the status is eESTABLISHED. Data reception has been handled
488  *        earlier. Here the ACK's from peer will be checked, and if a FIN is received,
489  *        the code will check if it may be accepted, i.e. if all expected data has been
490  *        completely received.
491  *
492  * @param[in] pxSocket: The socket owning the connection.
493  * @param[in,out] ppxNetworkBuffer: Pointer to pointer to the network buffer.
494  * @param[in] ulReceiveLength: The length of the received packet.
495  * @param[in] uxOptionsLength: Length of TCP options.
496  *
497  * @return The send length of the packet to be sent.
498  */
prvHandleEstablished(FreeRTOS_Socket_t * pxSocket,NetworkBufferDescriptor_t ** ppxNetworkBuffer,uint32_t ulReceiveLength,UBaseType_t uxOptionsLength)499     static BaseType_t prvHandleEstablished( FreeRTOS_Socket_t * pxSocket,
500                                             NetworkBufferDescriptor_t ** ppxNetworkBuffer,
501                                             uint32_t ulReceiveLength,
502                                             UBaseType_t uxOptionsLength )
503     {
504         /* Map the buffer onto the ProtocolHeader_t struct for easy access to the fields. */
505 
506         /* MISRA Ref 11.3.1 [Misaligned access] */
507 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
508         /* coverity[misra_c_2012_rule_11_3_violation] */
509         ProtocolHeaders_t * pxProtocolHeaders = ( ( ProtocolHeaders_t * )
510                                                   &( ( *ppxNetworkBuffer )->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ) ] ) );
511         TCPHeader_t * pxTCPHeader = &pxProtocolHeaders->xTCPHeader;
512         TCPWindow_t * pxTCPWindow = &pxSocket->u.xTCP.xTCPWindow;
513         uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;
514         uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber ), ulCount, ulIntermediateResult = 0;
515         BaseType_t xSendLength = 0, xMayClose = pdFALSE, bRxComplete, bTxDone;
516         int32_t lDistance, lSendResult;
517         uint16_t usWindow;
518         UBaseType_t uxIntermediateResult = 0;
519 
520         /* Remember the window size the peer is advertising. */
521         usWindow = FreeRTOS_ntohs( pxTCPHeader->usWindow );
522         pxSocket->u.xTCP.ulWindowSize = ( uint32_t ) usWindow;
523         #if ( ipconfigUSE_TCP_WIN != 0 )
524             {
525                 pxSocket->u.xTCP.ulWindowSize =
526                     ( pxSocket->u.xTCP.ulWindowSize << pxSocket->u.xTCP.ucPeerWinScaleFactor );
527             }
528         #endif /* ipconfigUSE_TCP_WIN */
529 
530         if( ( ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_ACK ) == 0U )
531         {
532             /* RFC793: If ACK bit is not set at this state, the segment should
533              * be dropped
534              */
535         }
536         else
537         {
538             ulCount = ulTCPWindowTxAck( pxTCPWindow, FreeRTOS_ntohl( pxTCPHeader->ulAckNr ) );
539 
540             /* ulTCPWindowTxAck() returns the number of bytes which have been acked,
541              * starting at 'tx.ulCurrentSequenceNumber'.  Advance the tail pointer in
542              * txStream. */
543             if( ( pxSocket->u.xTCP.txStream != NULL ) && ( ulCount > 0U ) )
544             {
545                 /* Just advancing the tail index, 'ulCount' bytes have been
546                  * confirmed, and because there is new space in the txStream, the
547                  * user/owner should be woken up. */
548                 /* _HT_ : only in case the socket's waiting? */
549                 if( uxStreamBufferGet( pxSocket->u.xTCP.txStream, 0U, NULL, ( size_t ) ulCount, pdFALSE ) != 0U )
550                 {
551                     pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_SEND;
552 
553                     #if ipconfigSUPPORT_SELECT_FUNCTION == 1
554                         {
555                             if( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_WRITE ) ) != 0U )
556                             {
557                                 pxSocket->xEventBits |= ( ( EventBits_t ) eSELECT_WRITE ) << SOCKET_EVENT_BIT_COUNT;
558                             }
559                         }
560                     #endif
561 
562                     /* In case the socket owner has installed an OnSent handler,
563                      * call it now. */
564                     #if ( ipconfigUSE_CALLBACKS == 1 )
565                         {
566                             if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleSent ) )
567                             {
568                                 pxSocket->u.xTCP.pxHandleSent( ( Socket_t ) pxSocket, ulCount );
569                             }
570                         }
571                     #endif /* ipconfigUSE_CALLBACKS == 1  */
572                 }
573             }
574 
575             /* If this socket has a stream for transmission, add the data to the
576              * outgoing segment(s). */
577             if( pxSocket->u.xTCP.txStream != NULL )
578             {
579                 prvTCPAddTxData( pxSocket );
580             }
581 
582             pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber = pxTCPWindow->tx.ulCurrentSequenceNumber;
583 
584             if( ( pxSocket->u.xTCP.bits.bFinAccepted != pdFALSE_UNSIGNED ) || ( ( ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_FIN ) != 0U ) )
585             {
586                 /* Peer is requesting to stop, see if we're really finished. */
587                 xMayClose = pdTRUE;
588 
589                 /* Checks are only necessary if we haven't sent a FIN yet. */
590                 if( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED )
591                 {
592                     /* xTCPWindowTxDone returns true when all Tx queues are empty. */
593                     bRxComplete = xTCPWindowRxEmpty( pxTCPWindow );
594                     bTxDone = xTCPWindowTxDone( pxTCPWindow );
595 
596                     if( ( bRxComplete == 0 ) || ( bTxDone == 0 ) )
597                     {
598                         /* Refusing FIN: Rx incomplete 1 optlen 4 tx done 1. */
599                         FreeRTOS_debug_printf( ( "Refusing FIN[%u,%u]: RxCompl %d tx done %d\n",
600                                                  pxSocket->usLocalPort,
601                                                  pxSocket->u.xTCP.usRemotePort,
602                                                  ( int ) bRxComplete,
603                                                  ( int ) bTxDone ) );
604                         xMayClose = pdFALSE;
605                     }
606                     else
607                     {
608                         ulIntermediateResult = ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulCurrentSequenceNumber;
609                         lDistance = ( int32_t ) ulIntermediateResult;
610 
611                         if( lDistance > 1 )
612                         {
613                             FreeRTOS_debug_printf( ( "Refusing FIN: Rx not complete %d (cur %u high %u)\n",
614                                                      ( int ) lDistance,
615                                                      ( unsigned ) ( pxTCPWindow->rx.ulCurrentSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ),
616                                                      ( unsigned ) ( pxTCPWindow->rx.ulHighestSequenceNumber - pxTCPWindow->rx.ulFirstSequenceNumber ) ) );
617 
618                             xMayClose = pdFALSE;
619                         }
620                     }
621                 }
622 
623                 if( xTCPWindowLoggingLevel > 0 )
624                 {
625                     FreeRTOS_debug_printf( ( "TCP: FIN received, mayClose = %d (Rx %u Len %d, Tx %u)\n",
626                                              ( int ) xMayClose,
627                                              ( unsigned ) ( ulSequenceNumber - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber ),
628                                              ( unsigned ) ulReceiveLength,
629                                              ( unsigned ) ( pxTCPWindow->tx.ulCurrentSequenceNumber - pxSocket->u.xTCP.xTCPWindow.tx.ulFirstSequenceNumber ) ) );
630                 }
631 
632                 if( xMayClose != pdFALSE )
633                 {
634                     pxSocket->u.xTCP.bits.bFinAccepted = pdTRUE_UNSIGNED;
635                     xSendLength = prvTCPHandleFin( pxSocket, *ppxNetworkBuffer );
636                 }
637             }
638 
639             if( xMayClose == pdFALSE )
640             {
641                 pxTCPHeader->ucTCPFlags = tcpTCP_FLAG_ACK;
642 
643                 if( ulReceiveLength != 0U )
644                 {
645                     uxIntermediateResult = uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength;
646                     xSendLength = ( BaseType_t ) uxIntermediateResult;
647                     /* TCP-offset equals '( ( length / 4 ) << 4 )', resulting in a shift-left 2 */
648                     pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
649 
650                     if( pxSocket->u.xTCP.bits.bFinSent != pdFALSE_UNSIGNED )
651                     {
652                         pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFINSequenceNumber;
653                     }
654                 }
655 
656                 /* Now get data to be transmitted. */
657 
658                 /* _HT_ patch: since the MTU has be fixed at 1500 in stead of 1526, TCP
659                  * can not send-out both TCP options and also a full packet. Sending
660                  * options (SACK) is always more urgent than sending data, which can be
661                  * sent later. */
662                 if( uxOptionsLength == 0U )
663                 {
664                     /* prvTCPPrepareSend might allocate a bigger network buffer, if
665                      * necessary. */
666                     lSendResult = prvTCPPrepareSend( pxSocket, ppxNetworkBuffer, uxOptionsLength );
667 
668                     if( lSendResult > 0 )
669                     {
670                         xSendLength = ( BaseType_t ) lSendResult;
671                     }
672                 }
673             }
674         }
675 
676         return xSendLength;
677     }
678     /*-----------------------------------------------------------*/
679 
680 
681 /**
682  * @brief Check incoming packets for valid data and handle the state of the
683  *        TCP connection and respond according to the situation.
684  *
685  * @param[in] pxSocket: The socket whose connection state is being handled.
686  * @param[in] ppxNetworkBuffer: The network buffer descriptor holding the
687  *            packet received from the peer.
688  *
689  * @return If the data is correct and some packet was sent to the peer, then
690  *         the number of bytes sent is returned, or else a negative value is
691  *         returned indicating an error.
692  *
693  * @note prvTCPHandleState() is the most important function of this TCP stack
694  * We've tried to keep it (relatively short) by putting a lot of code in
695  * the static functions above:
696  *
697  *      prvCheckRxData()
698  *      prvStoreRxData()
699  *      prvSetOptions()
700  *      prvHandleSynReceived()
701  *      prvHandleEstablished()
702  *      prvSendData()
703  *
704  * As these functions are declared static, and they're called from one location
705  * only, most compilers will inline them, thus avoiding a call and return.
706  */
prvTCPHandleState(FreeRTOS_Socket_t * pxSocket,NetworkBufferDescriptor_t ** ppxNetworkBuffer)707     BaseType_t prvTCPHandleState( FreeRTOS_Socket_t * pxSocket,
708                                   NetworkBufferDescriptor_t ** ppxNetworkBuffer )
709     {
710         /* Map the buffer onto the ProtocolHeader_t struct for easy access to the fields. */
711 
712         /* MISRA Ref 11.3.1 [Misaligned access] */
713 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
714         /* coverity[misra_c_2012_rule_11_3_violation] */
715         ProtocolHeaders_t * pxProtocolHeaders = ( ( ProtocolHeaders_t * )
716                                                   &( ( *ppxNetworkBuffer )->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( *ppxNetworkBuffer ) ] ) );
717         TCPHeader_t * pxTCPHeader = &( pxProtocolHeaders->xTCPHeader );
718         BaseType_t xSendLength = 0;
719         uint32_t ulReceiveLength; /* Number of bytes contained in the TCP message. */
720         uint8_t * pucRecvData;
721         uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxTCPHeader->ulSequenceNumber );
722 
723         /* uxOptionsLength: the size of the options to be sent (always a multiple of
724          * 4 bytes)
725          * 1. in the SYN phase, we shall communicate the MSS
726          * 2. in case of a SACK, Selective ACK, ack a segment which comes in
727          * out-of-order. */
728         UBaseType_t uxOptionsLength = 0U;
729         uint8_t ucTCPFlags = pxTCPHeader->ucTCPFlags;
730         TCPWindow_t * pxTCPWindow = &( pxSocket->u.xTCP.xTCPWindow );
731         UBaseType_t uxIntermediateResult = 0;
732         uint32_t ulSum;
733 
734         /* First get the length and the position of the received data, if any.
735          * pucRecvData will point to the first byte of the TCP payload. */
736         ulReceiveLength = ( uint32_t ) prvCheckRxData( *ppxNetworkBuffer, &pucRecvData );
737 
738         if( pxSocket->u.xTCP.eTCPState >= eESTABLISHED )
739         {
740             if( pxTCPWindow->rx.ulCurrentSequenceNumber == ( ulSequenceNumber + 1U ) )
741             {
742                 /* This is most probably a keep-alive message from peer.  Setting
743                  * 'bWinChange' doesn't cause a window-size-change, the flag is used
744                  * here to force sending an immediate ACK. */
745                 pxSocket->u.xTCP.bits.bWinChange = pdTRUE_UNSIGNED;
746             }
747         }
748 
749         /* Keep track of the highest sequence number that might be expected within
750          * this connection. */
751         ulSum = ulSequenceNumber + ulReceiveLength - pxTCPWindow->rx.ulHighestSequenceNumber;
752 
753         if( ( ( int32_t ) ulSum ) > 0 )
754         {
755             pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + ulReceiveLength;
756         }
757 
758         /* Storing data may result in a fatal error if malloc() fails. */
759         if( prvStoreRxData( pxSocket, pucRecvData, *ppxNetworkBuffer, ulReceiveLength ) < 0 )
760         {
761             xSendLength = -1;
762         }
763         else
764         {
765             eIPTCPState_t eState;
766 
767             uxOptionsLength = prvSetOptions( pxSocket, *ppxNetworkBuffer );
768 
769             if( ( pxSocket->u.xTCP.eTCPState == eSYN_RECEIVED ) && ( ( ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_CTRL ) == ( uint8_t ) tcpTCP_FLAG_SYN ) )
770             {
771                 FreeRTOS_debug_printf( ( "eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK\n" ) );
772 
773                 /* In eSYN_RECEIVED a simple ACK is expected, but apparently the
774                  * 'SYN+ACK' didn't arrive.  Step back to the previous state in which
775                  * a first incoming SYN is handled.  The SYN was counted already so
776                  * decrease it first. */
777                 vTCPStateChange( pxSocket, eSYN_FIRST );
778             }
779 
780             if( ( ( ucTCPFlags & tcpTCP_FLAG_FIN ) != 0U ) && ( pxSocket->u.xTCP.bits.bFinRecv == pdFALSE_UNSIGNED ) )
781             {
782                 /* It's the first time a FIN has been received, remember its
783                  * sequence number. */
784                 pxTCPWindow->rx.ulFINSequenceNumber = ulSequenceNumber + ulReceiveLength;
785                 pxSocket->u.xTCP.bits.bFinRecv = pdTRUE_UNSIGNED;
786 
787                 /* Was peer the first one to send a FIN? */
788                 if( pxSocket->u.xTCP.bits.bFinSent == pdFALSE_UNSIGNED )
789                 {
790                     /* If so, don't send the-last-ACK. */
791                     pxSocket->u.xTCP.bits.bFinLast = pdTRUE_UNSIGNED;
792                 }
793             }
794 
795             eState = ( eIPTCPState_t ) pxSocket->u.xTCP.eTCPState;
796 
797             switch( eState )
798             {
799                 case eCLOSED: /* (server + client) no connection state at all. */
800 
801                     /* Nothing to do for a closed socket, except waiting for the
802                      * owner. */
803                     break;
804 
805                 case eTCP_LISTEN: /* (server) waiting for a connection request from
806                                    * any remote TCP and port. */
807 
808                     /* The listen state was handled in xProcessReceivedTCPPacket().
809                      * Should not come here. */
810                     break;
811 
812                 case eSYN_FIRST: /* (server) Just received a SYN request for a server
813                                   * socket. */
814 
815                     /* A new socket has been created, reply with a SYN+ACK.
816                      * Acknowledge with seq+1 because the SYN is seen as pseudo data
817                      * with len = 1. */
818                     uxOptionsLength = prvSetSynAckOptions( pxSocket, pxTCPHeader );
819                     pxTCPHeader->ucTCPFlags = ( uint8_t ) tcpTCP_FLAG_SYN | ( uint8_t ) tcpTCP_FLAG_ACK;
820 
821                     uxIntermediateResult = uxIPHeaderSizeSocket( pxSocket ) + ipSIZE_OF_TCP_HEADER + uxOptionsLength;
822                     xSendLength = ( BaseType_t ) uxIntermediateResult;
823 
824                     /* Set the TCP offset field:  ipSIZE_OF_TCP_HEADER equals 20 and
825                      * uxOptionsLength is a multiple of 4.  The complete expression is:
826                      * ucTCPOffset = ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) / 4 ) << 4 */
827                     pxTCPHeader->ucTCPOffset = ( uint8_t ) ( ( ipSIZE_OF_TCP_HEADER + uxOptionsLength ) << 2 );
828                     vTCPStateChange( pxSocket, eSYN_RECEIVED );
829 
830                     pxTCPWindow->rx.ulHighestSequenceNumber = ulSequenceNumber + 1U;
831                     pxTCPWindow->rx.ulCurrentSequenceNumber = ulSequenceNumber + 1U;
832                     pxTCPWindow->ulNextTxSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1U;
833                     pxTCPWindow->tx.ulCurrentSequenceNumber = pxTCPWindow->tx.ulFirstSequenceNumber + 1U; /* because we send a TCP_SYN. */
834                     break;
835 
836                 case eCONNECT_SYN:  /* (client) also called SYN_SENT: we've just send a
837                                      * SYN, expect a SYN+ACK and send a ACK now. */
838                 /* Fall through */
839                 case eSYN_RECEIVED: /* (server) we've had a SYN, replied with SYN+SCK
840                                      * expect a ACK and do nothing. */
841                     xSendLength = prvHandleSynReceived( pxSocket, *( ppxNetworkBuffer ), ulReceiveLength, uxOptionsLength );
842                     break;
843 
844                 case eESTABLISHED: /* (server + client) an open connection, data
845                                     * received can be delivered to the user. The normal
846                                     * state for the data transfer phase of the connection
847                                     * The closing states are also handled here with the
848                                     * use of some flags. */
849                     xSendLength = prvHandleEstablished( pxSocket, ppxNetworkBuffer, ulReceiveLength, uxOptionsLength );
850                     break;
851 
852                 case eLAST_ACK:   /* (server + client) waiting for an acknowledgement
853                                    * of the connection termination request previously
854                                    * sent to the remote TCP (which includes an
855                                    * acknowledgement of its connection termination
856                                    * request). */
857                 /* Fall through */
858                 case eFIN_WAIT_1: /* (server + client) waiting for a connection termination request from the remote TCP,
859                                    * or an acknowledgement of the connection termination request previously sent. */
860                 /* Fall through */
861                 case eFIN_WAIT_2: /* (server + client) waiting for a connection termination request from the remote TCP. */
862                     xSendLength = prvTCPHandleFin( pxSocket, *ppxNetworkBuffer );
863                     break;
864 
865                 case eCLOSE_WAIT: /* (server + client) waiting for a connection
866                                    * termination request from the local user.  Nothing to
867                                    * do, connection is closed, wait for owner to close
868                                    * this socket. */
869                     break;
870 
871                 case eCLOSING: /* (server + client) waiting for a connection
872                                 * termination request acknowledgement from the remote
873                                 * TCP. */
874                     break;
875 
876                 case eTIME_WAIT: /* (either server or client) waiting for enough time
877                                   * to pass to be sure the remote TCP received the
878                                   * acknowledgement of its connection termination
879                                   * request. [According to RFC 793 a connection can stay
880                                   * in TIME-WAIT for a maximum of four minutes known as
881                                   * a MSL (maximum segment lifetime).]  These states are
882                                   * implemented implicitly by settings flags like
883                                   * 'bFinSent', 'bFinRecv', and 'bFinAcked'. */
884                     break;
885 
886                 default:
887                     /* No more known states. */
888                     break;
889             }
890         }
891 
892         if( xSendLength > 0 )
893         {
894             xSendLength = prvSendData( pxSocket, ppxNetworkBuffer, ulReceiveLength, xSendLength );
895         }
896 
897         return xSendLength;
898     }
899     /*-----------------------------------------------------------*/
900 
901 /**
902  * @brief Handle 'listen' event on the given socket.
903  *
904  * @param[in] pxSocket: The socket on which the listen occurred.
905  * @param[in] pxNetworkBuffer: The network buffer carrying the packet.
906  *
907  * @return If a new socket/duplicate socket is created, then the pointer to
908  *         that socket is returned or else, a NULL pointer is returned.
909  */
prvHandleListen(FreeRTOS_Socket_t * pxSocket,NetworkBufferDescriptor_t * pxNetworkBuffer)910     FreeRTOS_Socket_t * prvHandleListen( FreeRTOS_Socket_t * pxSocket,
911                                          NetworkBufferDescriptor_t * pxNetworkBuffer )
912     {
913         /* Map the ethernet buffer onto a TCPPacket_t struct for easy access to the fields. */
914 
915         /* MISRA Ref 11.3.1 [Misaligned access] */
916 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
917         /* coverity[misra_c_2012_rule_11_3_violation] */
918         const TCPPacket_t * pxTCPPacket = ( ( const TCPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer );
919         FreeRTOS_Socket_t * pxReturn = NULL;
920         uint32_t ulInitialSequenceNumber;
921 
922         /* Silently discard a SYN packet which was not specifically sent for this node. */
923         if( pxTCPPacket->xIPHeader.ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
924         {
925             /* Assume that a new Initial Sequence Number will be required. Request
926              * it now in order to fail out if necessary. */
927             ulInitialSequenceNumber = ulApplicationGetNextSequenceNumber( *ipLOCAL_IP_ADDRESS_POINTER,
928                                                                           pxSocket->usLocalPort,
929                                                                           pxTCPPacket->xIPHeader.ulSourceIPAddress,
930                                                                           pxTCPPacket->xTCPHeader.usSourcePort );
931         }
932         else
933         {
934             /* Set the sequence number to 0 to avoid further processing. */
935             ulInitialSequenceNumber = 0U;
936         }
937 
938         /* A pure SYN (without ACK) has come in, create a new socket to answer
939          * it. */
940         if( ulInitialSequenceNumber != 0U )
941         {
942             if( pxSocket->u.xTCP.bits.bReuseSocket != pdFALSE_UNSIGNED )
943             {
944                 /* The flag bReuseSocket indicates that the same instance of the
945                  * listening socket should be used for the connection. */
946                 pxReturn = pxSocket;
947                 pxSocket->u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED;
948                 pxSocket->u.xTCP.pxPeerSocket = pxSocket;
949             }
950             else
951             {
952                 /* The socket does not have the bReuseSocket flag set meaning create a
953                  * new socket when a connection comes in. */
954                 pxReturn = NULL;
955 
956                 if( pxSocket->u.xTCP.usChildCount >= pxSocket->u.xTCP.usBacklog )
957                 {
958                     FreeRTOS_printf( ( "Check: Socket %u already has %u / %u child%s\n",
959                                        pxSocket->usLocalPort,
960                                        pxSocket->u.xTCP.usChildCount,
961                                        pxSocket->u.xTCP.usBacklog,
962                                        ( pxSocket->u.xTCP.usChildCount == 1U ) ? "" : "ren" ) );
963                     ( void ) prvTCPSendReset( pxNetworkBuffer );
964                 }
965                 else
966                 {
967                     FreeRTOS_Socket_t * pxNewSocket = ( FreeRTOS_Socket_t * )
968                                                       FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
969 
970                     /* MISRA Ref 11.4.1 [Socket error and integer to pointer conversion] */
971 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-114 */
972                     /* coverity[misra_c_2012_rule_11_4_violation] */
973                     if( ( pxNewSocket == NULL ) || ( pxNewSocket == FREERTOS_INVALID_SOCKET ) )
974                     {
975                         FreeRTOS_debug_printf( ( "TCP: Listen: new socket failed\n" ) );
976                         ( void ) prvTCPSendReset( pxNetworkBuffer );
977                     }
978                     else if( prvTCPSocketCopy( pxNewSocket, pxSocket ) != pdFALSE )
979                     {
980                         /* The socket will be connected immediately, no time for the
981                          * owner to setsockopt's, therefore copy properties of the server
982                          * socket to the new socket.  Only the binding might fail (due to
983                          * lack of resources). */
984                         pxReturn = pxNewSocket;
985                     }
986                     else
987                     {
988                         /* Copying failed somehow. */
989                     }
990                 }
991             }
992         }
993 
994         if( ( ulInitialSequenceNumber != 0U ) && ( pxReturn != NULL ) )
995         {
996             /* Map the byte stream onto the ProtocolHeaders_t for easy access to the fields. */
997 
998             /* MISRA Ref 11.3.1 [Misaligned access] */
999 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */
1000             /* coverity[misra_c_2012_rule_11_3_violation] */
1001             const ProtocolHeaders_t * pxProtocolHeaders = ( ( const ProtocolHeaders_t * )
1002                                                             &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) );
1003 
1004             pxReturn->u.xTCP.usRemotePort = FreeRTOS_htons( pxTCPPacket->xTCPHeader.usSourcePort );
1005             pxReturn->u.xTCP.ulRemoteIP = FreeRTOS_htonl( pxTCPPacket->xIPHeader.ulSourceIPAddress );
1006             pxReturn->u.xTCP.xTCPWindow.ulOurSequenceNumber = ulInitialSequenceNumber;
1007 
1008             /* Here is the SYN action. */
1009             pxReturn->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber = FreeRTOS_ntohl( pxProtocolHeaders->xTCPHeader.ulSequenceNumber );
1010             prvSocketSetMSS( pxReturn );
1011 
1012             prvTCPCreateWindow( pxReturn );
1013 
1014             vTCPStateChange( pxReturn, eSYN_FIRST );
1015 
1016             /* Make a copy of the header up to the TCP header.  It is needed later
1017              * on, whenever data must be sent to the peer. */
1018             ( void ) memcpy( ( void * ) pxReturn->u.xTCP.xPacket.u.ucLastPacket,
1019                              ( const void * ) pxNetworkBuffer->pucEthernetBuffer,
1020                              sizeof( pxReturn->u.xTCP.xPacket.u.ucLastPacket ) );
1021         }
1022 
1023         return pxReturn;
1024     }
1025     /*-----------------------------------------------------------*/
1026 
1027 
1028 /**
1029  * @brief Duplicates a socket after a listening socket receives a connection and bind
1030  *        the new socket to the same port as the listening socket.
1031  *        Also, let the new socket inherit all properties from the listening socket.
1032  *
1033  * @param[in] pxNewSocket: Pointer to the new socket.
1034  * @param[in] pxSocket: Pointer to the socket being duplicated.
1035  *
1036  * @return If all steps all successful, then pdTRUE is returned. Else, pdFALSE.
1037  */
prvTCPSocketCopy(FreeRTOS_Socket_t * pxNewSocket,FreeRTOS_Socket_t * pxSocket)1038     static BaseType_t prvTCPSocketCopy( FreeRTOS_Socket_t * pxNewSocket,
1039                                         FreeRTOS_Socket_t * pxSocket )
1040     {
1041         struct freertos_sockaddr xAddress;
1042         BaseType_t xResult;
1043 
1044         pxNewSocket->xReceiveBlockTime = pxSocket->xReceiveBlockTime;
1045         pxNewSocket->xSendBlockTime = pxSocket->xSendBlockTime;
1046         pxNewSocket->ucSocketOptions = pxSocket->ucSocketOptions;
1047         pxNewSocket->u.xTCP.uxRxStreamSize = pxSocket->u.xTCP.uxRxStreamSize;
1048         pxNewSocket->u.xTCP.uxTxStreamSize = pxSocket->u.xTCP.uxTxStreamSize;
1049         pxNewSocket->u.xTCP.uxLittleSpace = pxSocket->u.xTCP.uxLittleSpace;
1050         pxNewSocket->u.xTCP.uxEnoughSpace = pxSocket->u.xTCP.uxEnoughSpace;
1051         pxNewSocket->u.xTCP.uxRxWinSize = pxSocket->u.xTCP.uxRxWinSize;
1052         pxNewSocket->u.xTCP.uxTxWinSize = pxSocket->u.xTCP.uxTxWinSize;
1053 
1054         #if ( ipconfigSOCKET_HAS_USER_SEMAPHORE == 1 )
1055             {
1056                 pxNewSocket->pxUserSemaphore = pxSocket->pxUserSemaphore;
1057             }
1058         #endif /* ipconfigSOCKET_HAS_USER_SEMAPHORE */
1059 
1060         #if ( ipconfigUSE_CALLBACKS == 1 )
1061             {
1062                 /* In case call-backs are used, copy them from parent to child. */
1063                 pxNewSocket->u.xTCP.pxHandleConnected = pxSocket->u.xTCP.pxHandleConnected;
1064                 pxNewSocket->u.xTCP.pxHandleReceive = pxSocket->u.xTCP.pxHandleReceive;
1065                 pxNewSocket->u.xTCP.pxHandleSent = pxSocket->u.xTCP.pxHandleSent;
1066             }
1067         #endif /* ipconfigUSE_CALLBACKS */
1068 
1069         #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
1070             {
1071                 /* Child socket of listening sockets will inherit the Socket Set
1072                  * Otherwise the owner has no chance of including it into the set. */
1073                 if( pxSocket->pxSocketSet != NULL )
1074                 {
1075                     pxNewSocket->pxSocketSet = pxSocket->pxSocketSet;
1076                     pxNewSocket->xSelectBits = pxSocket->xSelectBits | ( ( EventBits_t ) eSELECT_READ ) | ( ( EventBits_t ) eSELECT_EXCEPT );
1077                 }
1078             }
1079         #endif /* ipconfigSUPPORT_SELECT_FUNCTION */
1080 
1081         /* And bind it to the same local port as its parent. */
1082         xAddress.sin_addr = *ipLOCAL_IP_ADDRESS_POINTER;
1083         xAddress.sin_port = FreeRTOS_htons( pxSocket->usLocalPort );
1084 
1085         #if ( ipconfigTCP_HANG_PROTECTION == 1 )
1086             {
1087                 /* Only when there is anti-hanging protection, a socket may become an
1088                  * orphan temporarily.  Once this socket is really connected, the owner of
1089                  * the server socket will be notified. */
1090 
1091                 /* When bPassQueued is true, the socket is an orphan until it gets
1092                  * connected. */
1093                 pxNewSocket->u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED;
1094                 pxNewSocket->u.xTCP.pxPeerSocket = pxSocket;
1095             }
1096         #else
1097             {
1098                 /* A reference to the new socket may be stored and the socket is marked
1099                  * as 'passable'. */
1100 
1101                 /* When bPassAccept is true, this socket may be returned in a call to
1102                  * accept(). */
1103                 pxNewSocket->u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED;
1104 
1105                 if( pxSocket->u.xTCP.pxPeerSocket == NULL )
1106                 {
1107                     pxSocket->u.xTCP.pxPeerSocket = pxNewSocket;
1108                 }
1109             }
1110         #endif /* if ( ipconfigTCP_HANG_PROTECTION == 1 ) */
1111 
1112         pxSocket->u.xTCP.usChildCount++;
1113 
1114         FreeRTOS_debug_printf( ( "Gain: Socket %u now has %u / %u child%s\n",
1115                                  pxSocket->usLocalPort,
1116                                  pxSocket->u.xTCP.usChildCount,
1117                                  pxSocket->u.xTCP.usBacklog,
1118                                  ( pxSocket->u.xTCP.usChildCount == 1U ) ? "" : "ren" ) );
1119 
1120         /* Now bind the child socket to the same port as the listening socket. */
1121         if( vSocketBind( pxNewSocket, &xAddress, sizeof( xAddress ), pdTRUE ) != 0 )
1122         {
1123             FreeRTOS_debug_printf( ( "TCP: Listen: new socket bind error\n" ) );
1124             ( void ) vSocketClose( pxNewSocket );
1125             xResult = pdFALSE;
1126         }
1127         else
1128         {
1129             xResult = pdTRUE;
1130         }
1131 
1132         return xResult;
1133     }
1134     /*-----------------------------------------------------------*/
1135 
1136     #if ( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) )
1137 
FreeRTOS_GetTCPStateName(UBaseType_t ulState)1138         const char * FreeRTOS_GetTCPStateName( UBaseType_t ulState )
1139         {
1140             static const char * const pcStateNames[] =
1141             {
1142                 "eCLOSED",
1143                 "eTCP_LISTEN",
1144                 "eCONNECT_SYN",
1145                 "eSYN_FIRST",
1146                 "eSYN_RECEIVED",
1147                 "eESTABLISHED",
1148                 "eFIN_WAIT_1",
1149                 "eFIN_WAIT_2",
1150                 "eCLOSE_WAIT",
1151                 "eCLOSING",
1152                 "eLAST_ACK",
1153                 "eTIME_WAIT",
1154                 "eUNKNOWN",
1155             };
1156             BaseType_t xIndex = ( BaseType_t ) ulState;
1157 
1158             if( ( xIndex < 0 ) || ( xIndex >= ARRAY_SIZE( pcStateNames ) ) )
1159             {
1160                 /* The last item is called 'eUNKNOWN' */
1161                 xIndex = ARRAY_SIZE( pcStateNames );
1162                 xIndex--;
1163             }
1164 
1165             return pcStateNames[ xIndex ];
1166         }
1167 
1168     #endif /* ( ( ipconfigHAS_DEBUG_PRINTF != 0 ) || ( ipconfigHAS_PRINTF != 0 ) ) */
1169     /*-----------------------------------------------------------*/
1170 
1171 #endif /* ipconfigUSE_TCP == 1 */
1172