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