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_IP.c 30 * @brief Module which handles the TCP connections for FreeRTOS+TCP. 31 * It depends on FreeRTOS_TCP_WIN.c, which handles the TCP windowing 32 * schemes. 33 * 34 * Endianness: in this module all ports and IP addresses are stored in 35 * host byte-order, except fields in the IP-packets 36 */ 37 38 /* Standard includes. */ 39 #include <stdint.h> 40 #include <stdio.h> 41 42 /* FreeRTOS includes. */ 43 #include "FreeRTOS.h" 44 #include "task.h" 45 #include "queue.h" 46 #include "semphr.h" 47 48 /* FreeRTOS+TCP includes. */ 49 #include "FreeRTOS_IP.h" 50 #include "FreeRTOS_Sockets.h" 51 #include "FreeRTOS_IP_Private.h" 52 #include "FreeRTOS_UDP_IP.h" 53 #include "FreeRTOS_DHCP.h" 54 #include "NetworkInterface.h" 55 #include "NetworkBufferManagement.h" 56 #include "FreeRTOS_ARP.h" 57 58 #include "FreeRTOS_TCP_Reception.h" 59 #include "FreeRTOS_TCP_Transmission.h" 60 #include "FreeRTOS_TCP_State_Handling.h" 61 #include "FreeRTOS_TCP_Utils.h" 62 63 64 /* Just make sure the contents doesn't get compiled if TCP is not enabled. */ 65 #if ipconfigUSE_TCP == 1 66 67 68 69 /** @brief When closing a socket an event is posted to the Network Event Queue. 70 * If the queue is full, then the event is not posted and the socket 71 * can be orphaned. To prevent this, the below variable is used to keep 72 * track of any socket which needs to be closed. This variable can be 73 * accessed by the IP task only. Thus, preventing any race condition. 74 */ 75 /* MISRA Ref 8.9.1 [File scoped variables] */ 76 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */ 77 /* coverity[misra_c_2012_rule_8_9_violation] */ 78 static FreeRTOS_Socket_t * xSocketToClose = NULL; 79 80 /** @brief When a connection is coming in on a reusable socket, and the 81 * SYN phase times out, the socket must be put back into eTCP_LISTEN 82 * mode, so it can accept a new connection again. 83 * This variable can be accessed by the IP task only. Thus, preventing any 84 * race condition. 85 */ 86 /* MISRA Ref 8.9.1 [File scoped variables] */ 87 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-89 */ 88 /* coverity[misra_c_2012_rule_8_9_violation] */ 89 static FreeRTOS_Socket_t * xSocketToListen = NULL; 90 91 /* 92 * For anti-hang protection and TCP keep-alive messages. Called in two places: 93 * after receiving a packet and after a state change. The socket's alive timer 94 * may be reset. 95 */ 96 static void prvTCPTouchSocket( FreeRTOS_Socket_t * pxSocket ); 97 98 99 /* 100 * Calculate when this socket needs to be checked to do (re-)transmissions. 101 */ 102 static TickType_t prvTCPNextTimeout( FreeRTOS_Socket_t * pxSocket ); 103 104 105 #if ( ipconfigHAS_DEBUG_PRINTF != 0 ) 106 107 /* 108 * For logging and debugging: make a string showing the TCP flags. 109 */ 110 const char * prvTCPFlagMeaning( UBaseType_t xFlags ); 111 #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */ 112 113 114 /*-----------------------------------------------------------*/ 115 116 117 /** @brief Close the socket another time. 118 * 119 * @param[in] pxSocket: The socket to be checked. 120 */ 121 /* coverity[single_use] */ vSocketCloseNextTime(FreeRTOS_Socket_t * pxSocket)122 void vSocketCloseNextTime( FreeRTOS_Socket_t * pxSocket ) 123 { 124 if( ( xSocketToClose != NULL ) && ( xSocketToClose != pxSocket ) ) 125 { 126 ( void ) vSocketClose( xSocketToClose ); 127 } 128 129 xSocketToClose = pxSocket; 130 } 131 /*-----------------------------------------------------------*/ 132 133 /** @brief Postpone a call to FreeRTOS_listen() to avoid recursive calls. 134 * 135 * @param[in] pxSocket: The socket to be checked. 136 */ 137 /* coverity[single_use] */ vSocketListenNextTime(FreeRTOS_Socket_t * pxSocket)138 void vSocketListenNextTime( FreeRTOS_Socket_t * pxSocket ) 139 { 140 if( ( xSocketToListen != NULL ) && ( xSocketToListen != pxSocket ) ) 141 { 142 ( void ) FreeRTOS_listen( ( Socket_t ) xSocketToListen, xSocketToListen->u.xTCP.usBacklog ); 143 } 144 145 xSocketToListen = pxSocket; 146 } 147 /*-----------------------------------------------------------*/ 148 149 /** 150 * @brief As soon as a TCP socket timer expires, this function will be called 151 * (from xTCPTimerCheck). It can send a delayed ACK or new data. 152 * 153 * @param[in] pxSocket: socket to be checked. 154 * 155 * @return 0 on success, a negative error code on failure. A negative value will be 156 * returned in case the hang-protection has put the socket in a wait-close state. 157 * 158 * @note Sequence of calling (normally) : 159 * IP-Task: 160 * xTCPTimerCheck() // Check all sockets ( declared in FreeRTOS_Sockets.c ) 161 * xTCPSocketCheck() // Either send a delayed ACK or call prvTCPSendPacket() 162 * prvTCPSendPacket() // Either send a SYN or call prvTCPSendRepeated ( regular messages ) 163 * prvTCPSendRepeated() // Send at most 8 messages on a row 164 * prvTCPReturnPacket() // Prepare for returning 165 * xNetworkInterfaceOutput() // Sends data to the NIC ( declared in portable/NetworkInterface/xxx ) 166 */ xTCPSocketCheck(FreeRTOS_Socket_t * pxSocket)167 BaseType_t xTCPSocketCheck( FreeRTOS_Socket_t * pxSocket ) 168 { 169 BaseType_t xResult = 0; 170 BaseType_t xReady = pdFALSE; 171 172 if( ( pxSocket->u.xTCP.eTCPState >= eESTABLISHED ) && ( pxSocket->u.xTCP.txStream != NULL ) ) 173 { 174 /* The API FreeRTOS_send() might have added data to the TX stream. Add 175 * this data to the windowing system so it can be transmitted. */ 176 prvTCPAddTxData( pxSocket ); 177 } 178 179 #if ( ipconfigUSE_TCP_WIN == 1 ) 180 { 181 if( pxSocket->u.xTCP.pxAckMessage != NULL ) 182 { 183 /* The first task of this regular socket check is to send-out delayed 184 * ACK's. */ 185 if( pxSocket->u.xTCP.bits.bUserShutdown == pdFALSE_UNSIGNED ) 186 { 187 /* Earlier data was received but not yet acknowledged. This 188 * function is called when the TCP timer for the socket expires, the 189 * ACK may be sent now. */ 190 if( pxSocket->u.xTCP.eTCPState != eCLOSED ) 191 { 192 if( ( xTCPWindowLoggingLevel > 1 ) && ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) ) 193 { 194 FreeRTOS_debug_printf( ( "Send[%u->%u] del ACK %u SEQ %u (len %u)\n", 195 pxSocket->usLocalPort, 196 pxSocket->u.xTCP.usRemotePort, 197 ( unsigned ) ( pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber - pxSocket->u.xTCP.xTCPWindow.rx.ulFirstSequenceNumber ), 198 ( unsigned ) ( pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber - pxSocket->u.xTCP.xTCPWindow.tx.ulFirstSequenceNumber ), 199 ( unsigned ) ( ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER ) ) ); 200 } 201 202 prvTCPReturnPacket( pxSocket, pxSocket->u.xTCP.pxAckMessage, ipSIZE_OF_IPv4_HEADER + ipSIZE_OF_TCP_HEADER, ipconfigZERO_COPY_TX_DRIVER ); 203 204 #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) 205 { 206 /* The ownership has been passed to the SEND routine, 207 * clear the pointer to it. */ 208 pxSocket->u.xTCP.pxAckMessage = NULL; 209 } 210 #endif /* ipconfigZERO_COPY_TX_DRIVER */ 211 } 212 213 if( prvTCPNextTimeout( pxSocket ) > 1U ) 214 { 215 /* Tell the code below that this function is ready. */ 216 xReady = pdTRUE; 217 } 218 } 219 else 220 { 221 /* The user wants to perform an active shutdown(), skip sending 222 * the delayed ACK. The function prvTCPSendPacket() will send the 223 * FIN along with the ACK's. */ 224 } 225 226 if( pxSocket->u.xTCP.pxAckMessage != NULL ) 227 { 228 vReleaseNetworkBufferAndDescriptor( pxSocket->u.xTCP.pxAckMessage ); 229 pxSocket->u.xTCP.pxAckMessage = NULL; 230 } 231 } 232 } 233 #endif /* ipconfigUSE_TCP_WIN */ 234 235 if( xReady == pdFALSE ) 236 { 237 /* The second task of this regular socket check is sending out data. */ 238 if( ( pxSocket->u.xTCP.eTCPState >= eESTABLISHED ) || 239 ( pxSocket->u.xTCP.eTCPState == eCONNECT_SYN ) ) 240 { 241 ( void ) prvTCPSendPacket( pxSocket ); 242 } 243 244 /* Set the time-out for the next wakeup for this socket. */ 245 ( void ) prvTCPNextTimeout( pxSocket ); 246 247 #if ( ipconfigTCP_HANG_PROTECTION == 1 ) 248 { 249 /* In all (non-connected) states in which keep-alive messages can not be sent 250 * the anti-hang protocol will close sockets that are 'hanging'. */ 251 xResult = prvTCPStatusAgeCheck( pxSocket ); 252 } 253 #endif 254 } 255 256 return xResult; 257 } 258 /*-----------------------------------------------------------*/ 259 260 /** 261 * @brief 'Touch' the socket to keep it alive/updated. 262 * 263 * @param[in] pxSocket: The socket to be updated. 264 * 265 * @note This is used for anti-hanging protection and TCP keep-alive messages. 266 * Called in two places: after receiving a packet and after a state change. 267 * The socket's alive timer may be reset. 268 */ prvTCPTouchSocket(FreeRTOS_Socket_t * pxSocket)269 static void prvTCPTouchSocket( FreeRTOS_Socket_t * pxSocket ) 270 { 271 #if ( ipconfigTCP_HANG_PROTECTION == 1 ) 272 { 273 pxSocket->u.xTCP.xLastActTime = xTaskGetTickCount(); 274 } 275 #endif 276 277 #if ( ipconfigTCP_KEEP_ALIVE == 1 ) 278 { 279 pxSocket->u.xTCP.bits.bWaitKeepAlive = pdFALSE_UNSIGNED; 280 pxSocket->u.xTCP.bits.bSendKeepAlive = pdFALSE_UNSIGNED; 281 pxSocket->u.xTCP.ucKeepRepCount = 0U; 282 pxSocket->u.xTCP.xLastAliveTime = xTaskGetTickCount(); 283 } 284 #endif 285 286 ( void ) pxSocket; 287 } 288 /*-----------------------------------------------------------*/ 289 290 /** 291 * @brief Changing to a new state. Centralised here to do specific actions such as 292 * resetting the alive timer, calling the user's OnConnect handler to notify 293 * that a socket has got (dis)connected, and setting bit to unblock a call to 294 * FreeRTOS_select(). 295 * 296 * @param[in] pxSocket: The socket whose state we are trying to change. 297 * @param[in] eTCPState: The state to which we want to change to. 298 */ vTCPStateChange(FreeRTOS_Socket_t * pxSocket,enum eTCP_STATE eTCPState)299 void vTCPStateChange( FreeRTOS_Socket_t * pxSocket, 300 enum eTCP_STATE eTCPState ) 301 { 302 FreeRTOS_Socket_t * xParent = pxSocket; 303 BaseType_t bBefore = tcpNOW_CONNECTED( ( BaseType_t ) pxSocket->u.xTCP.eTCPState ); /* Was it connected ? */ 304 BaseType_t bAfter = tcpNOW_CONNECTED( ( BaseType_t ) eTCPState ); /* Is it connected now ? */ 305 306 BaseType_t xPreviousState = ( BaseType_t ) pxSocket->u.xTCP.eTCPState; 307 308 #if ( ipconfigUSE_CALLBACKS == 1 ) 309 FreeRTOS_Socket_t * xConnected = NULL; 310 #endif 311 312 if( ( ( xPreviousState == eCONNECT_SYN ) || 313 ( xPreviousState == eSYN_FIRST ) || 314 ( xPreviousState == eSYN_RECEIVED ) ) && 315 ( eTCPState == eCLOSE_WAIT ) ) 316 { 317 /* A socket was in the connecting phase but something 318 * went wrong and it should be closed. */ 319 FreeRTOS_debug_printf( ( "Move from %s to %s\n", 320 FreeRTOS_GetTCPStateName( xPreviousState ), 321 FreeRTOS_GetTCPStateName( eTCPState ) ) ); 322 323 /* Set the flag to show that it was connected before and that the 324 * status has changed now. This will cause the control flow to go 325 * in the below if condition.*/ 326 bBefore = pdTRUE; 327 } 328 329 /* Has the connected status changed? */ 330 if( bBefore != bAfter ) 331 { 332 /* if bPassQueued is true, this socket is an orphan until it gets connected. */ 333 if( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED ) 334 { 335 /* Find it's parent if the reuse bit is not set. */ 336 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) 337 { 338 xParent = pxSocket->u.xTCP.pxPeerSocket; 339 configASSERT( xParent != NULL ); 340 } 341 } 342 343 /* Is the socket connected now ? */ 344 if( bAfter != pdFALSE ) 345 { 346 /* if bPassQueued is true, this socket is an orphan until it gets connected. */ 347 if( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED ) 348 { 349 if( xParent != NULL ) 350 { 351 /* The child socket has got connected. See if the parent 352 * ( the listening socket ) should be signalled, or if a 353 * call-back must be made, in which case 'xConnected' will 354 * be set to the parent socket. */ 355 356 if( xParent->u.xTCP.pxPeerSocket == NULL ) 357 { 358 xParent->u.xTCP.pxPeerSocket = pxSocket; 359 } 360 361 xParent->xEventBits |= ( EventBits_t ) eSOCKET_ACCEPT; 362 363 #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) 364 { 365 /* Library support FreeRTOS_select(). Receiving a new 366 * connection is being translated as a READ event. */ 367 if( ( xParent->xSelectBits & ( ( EventBits_t ) eSELECT_READ ) ) != 0U ) 368 { 369 xParent->xEventBits |= ( ( EventBits_t ) eSELECT_READ ) << SOCKET_EVENT_BIT_COUNT; 370 } 371 } 372 #endif 373 374 #if ( ipconfigUSE_CALLBACKS == 1 ) 375 { 376 if( ( ipconfigIS_VALID_PROG_ADDRESS( xParent->u.xTCP.pxHandleConnected ) ) && 377 ( xParent->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) ) 378 { 379 /* The listening socket does not become connected itself, in stead 380 * a child socket is created. 381 * Postpone a call the OnConnect event until the end of this function. */ 382 xConnected = xParent; 383 } 384 } 385 #endif 386 } 387 388 /* Don't need to access the parent socket anymore, so the 389 * reference 'pxPeerSocket' may be cleared. */ 390 pxSocket->u.xTCP.pxPeerSocket = NULL; 391 pxSocket->u.xTCP.bits.bPassQueued = pdFALSE_UNSIGNED; 392 393 /* When true, this socket may be returned in a call to accept(). */ 394 pxSocket->u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED; 395 } 396 else 397 { 398 /* An active connect() has succeeded. In this case there is no 399 * ( listening ) parent socket. Signal the now connected socket. */ 400 401 pxSocket->xEventBits |= ( EventBits_t ) eSOCKET_CONNECT; 402 403 #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) 404 { 405 if( ( pxSocket->xSelectBits & ( ( EventBits_t ) eSELECT_WRITE ) ) != 0U ) 406 { 407 pxSocket->xEventBits |= ( ( EventBits_t ) eSELECT_WRITE ) << SOCKET_EVENT_BIT_COUNT; 408 } 409 } 410 #endif 411 } 412 } 413 else /* bAfter == pdFALSE, connection is closed. */ 414 { 415 /* Notify/wake-up the socket-owner by setting the event bits. */ 416 xParent->xEventBits |= ( EventBits_t ) eSOCKET_CLOSED; 417 418 #if ( ipconfigSUPPORT_SELECT_FUNCTION == 1 ) 419 { 420 if( ( xParent->xSelectBits & ( EventBits_t ) eSELECT_EXCEPT ) != 0U ) 421 { 422 xParent->xEventBits |= ( ( EventBits_t ) eSELECT_EXCEPT ) << SOCKET_EVENT_BIT_COUNT; 423 } 424 } 425 #endif 426 } 427 428 #if ( ipconfigUSE_CALLBACKS == 1 ) 429 { 430 if( ( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleConnected ) ) && ( xConnected == NULL ) ) 431 { 432 /* The 'connected' state has changed, call the user handler. */ 433 xConnected = pxSocket; 434 } 435 } 436 #endif /* ipconfigUSE_CALLBACKS */ 437 438 if( prvTCPSocketIsActive( pxSocket->u.xTCP.eTCPState ) == 0 ) 439 { 440 /* Now the socket isn't in an active state anymore so it 441 * won't need further attention of the IP-task. 442 * Setting time-out to zero means that the socket won't get checked during 443 * timer events. */ 444 pxSocket->u.xTCP.usTimeout = 0U; 445 } 446 } 447 448 if( ( eTCPState == eCLOSED ) || 449 ( eTCPState == eCLOSE_WAIT ) ) 450 { 451 /* Socket goes to status eCLOSED because of a RST. 452 * When nobody owns the socket yet, delete it. */ 453 if( ( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED ) || 454 ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) ) 455 { 456 FreeRTOS_debug_printf( ( "vTCPStateChange: Closing socket\n" ) ); 457 458 if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) 459 { 460 configASSERT( xIsCallingFromIPTask() != pdFALSE ); 461 vSocketCloseNextTime( pxSocket ); 462 } 463 } 464 } 465 466 /* Fill in the new state. */ 467 pxSocket->u.xTCP.eTCPState = eTCPState; 468 469 if( ( eTCPState == eCLOSE_WAIT ) && ( pxSocket->u.xTCP.bits.bReuseSocket == pdTRUE_UNSIGNED ) ) 470 { 471 switch( xPreviousState ) 472 { 473 case eSYN_FIRST: /* 3 (server) Just created, must ACK the SYN request */ 474 case eSYN_RECEIVED: /* 4 (server) waiting for a confirming connection request */ 475 FreeRTOS_debug_printf( ( "Restoring a reuse socket port %u\n", pxSocket->usLocalPort ) ); 476 477 /* Go back into listening mode. Set the TCP status to 'eCLOSED', 478 * otherwise FreeRTOS_listen() will refuse the action. */ 479 pxSocket->u.xTCP.eTCPState = eCLOSED; 480 481 /* vSocketListenNextTime() makes sure that FreeRTOS_listen() will be called 482 * before the IP-task handles any new message. */ 483 vSocketListenNextTime( pxSocket ); 484 break; 485 486 default: 487 /* Nothing to do. */ 488 break; 489 } 490 } 491 492 /* Touch the alive timers because moving to another state. */ 493 prvTCPTouchSocket( pxSocket ); 494 495 #if ( ipconfigHAS_DEBUG_PRINTF == 1 ) 496 { 497 if( ( xTCPWindowLoggingLevel >= 0 ) && ( ipconfigTCP_MAY_LOG_PORT( pxSocket->usLocalPort ) ) ) 498 { 499 FreeRTOS_debug_printf( ( "Socket %u -> %xip:%u State %s->%s\n", 500 pxSocket->usLocalPort, 501 ( unsigned ) pxSocket->u.xTCP.ulRemoteIP, 502 pxSocket->u.xTCP.usRemotePort, 503 FreeRTOS_GetTCPStateName( ( UBaseType_t ) xPreviousState ), 504 FreeRTOS_GetTCPStateName( ( UBaseType_t ) eTCPState ) ) ); 505 } 506 } 507 #endif /* ipconfigHAS_DEBUG_PRINTF */ 508 509 #if ( ipconfigUSE_CALLBACKS == 1 ) 510 { 511 if( xConnected != NULL ) 512 { 513 /* The 'connected' state has changed, call the OnConnect handler of the parent. */ 514 xConnected->u.xTCP.pxHandleConnected( ( Socket_t ) xConnected, bAfter ); 515 } 516 } 517 #endif 518 519 if( xParent != NULL ) 520 { 521 vSocketWakeUpUser( xParent ); 522 } 523 } 524 /*-----------------------------------------------------------*/ 525 526 527 /** 528 * @brief Calculate after how much time this socket needs to be checked again. 529 * 530 * @param[in] pxSocket: The socket to be checked. 531 * 532 * @return The number of clock ticks before the timer expires. 533 */ prvTCPNextTimeout(FreeRTOS_Socket_t * pxSocket)534 static TickType_t prvTCPNextTimeout( FreeRTOS_Socket_t * pxSocket ) 535 { 536 TickType_t ulDelayMs = ( TickType_t ) tcpMAXIMUM_TCP_WAKEUP_TIME_MS; 537 538 if( pxSocket->u.xTCP.eTCPState == eCONNECT_SYN ) 539 { 540 /* The socket is actively connecting to a peer. */ 541 if( pxSocket->u.xTCP.bits.bConnPrepared != pdFALSE_UNSIGNED ) 542 { 543 /* Ethernet address has been found, use progressive timeout for 544 * active connect(). */ 545 if( pxSocket->u.xTCP.ucRepCount < 3U ) 546 { 547 ulDelayMs = ( ( ( uint32_t ) 3000U ) << ( pxSocket->u.xTCP.ucRepCount - 1U ) ); 548 } 549 else 550 { 551 ulDelayMs = 11000U; 552 } 553 } 554 else 555 { 556 /* Still in the ARP phase: check every half second. */ 557 ulDelayMs = 500U; 558 } 559 560 FreeRTOS_debug_printf( ( "Connect[%xip:%u]: next timeout %u: %u ms\n", 561 ( unsigned ) pxSocket->u.xTCP.ulRemoteIP, pxSocket->u.xTCP.usRemotePort, 562 pxSocket->u.xTCP.ucRepCount, ( unsigned ) ulDelayMs ) ); 563 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ipMS_TO_MIN_TICKS( ulDelayMs ); 564 } 565 else if( pxSocket->u.xTCP.usTimeout == 0U ) 566 { 567 /* Let the sliding window mechanism decide what time-out is appropriate. */ 568 BaseType_t xResult = xTCPWindowTxHasData( &pxSocket->u.xTCP.xTCPWindow, pxSocket->u.xTCP.ulWindowSize, &ulDelayMs ); 569 570 if( ulDelayMs == 0U ) 571 { 572 if( xResult != ( BaseType_t ) 0 ) 573 { 574 ulDelayMs = 1U; 575 } 576 else 577 { 578 ulDelayMs = tcpMAXIMUM_TCP_WAKEUP_TIME_MS; 579 } 580 } 581 else 582 { 583 /* ulDelayMs contains the time to wait before a re-transmission. */ 584 } 585 586 pxSocket->u.xTCP.usTimeout = ( uint16_t ) ipMS_TO_MIN_TICKS( ulDelayMs ); /* LCOV_EXCL_BR_LINE ulDelayMs will not be smaller than 1 */ 587 } 588 else 589 { 590 /* field '.usTimeout' has already been set (by the 591 * keep-alive/delayed-ACK mechanism). */ 592 } 593 594 /* Return the number of clock ticks before the timer expires. */ 595 return ( TickType_t ) pxSocket->u.xTCP.usTimeout; 596 } 597 /*-----------------------------------------------------------*/ 598 599 /** 600 * @brief Process the received TCP packet. 601 * 602 * @param[in] pxDescriptor: The descriptor in which the TCP packet is held. 603 * 604 * @return If the processing of the packet was successful, then pdPASS is returned 605 * or else pdFAIL. 606 * 607 * @note FreeRTOS_TCP_IP has only 2 public functions, this is the second one: 608 * xProcessReceivedTCPPacket() 609 * prvTCPHandleState() 610 * prvTCPPrepareSend() 611 * prvTCPReturnPacket() 612 * xNetworkInterfaceOutput() // Sends data to the NIC 613 * prvTCPSendRepeated() 614 * prvTCPReturnPacket() // Prepare for returning 615 * xNetworkInterfaceOutput() // Sends data to the NIC 616 */ xProcessReceivedTCPPacket(NetworkBufferDescriptor_t * pxDescriptor)617 BaseType_t xProcessReceivedTCPPacket( NetworkBufferDescriptor_t * pxDescriptor ) 618 { 619 /* Function might modify the parameter. */ 620 NetworkBufferDescriptor_t * pxNetworkBuffer = pxDescriptor; 621 622 configASSERT( pxNetworkBuffer != NULL ); 623 configASSERT( pxNetworkBuffer->pucEthernetBuffer != NULL ); 624 625 /* Map the buffer onto a ProtocolHeaders_t struct for easy access to the fields. */ 626 627 /* MISRA Ref 11.3.1 [Misaligned access] */ 628 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ 629 /* coverity[misra_c_2012_rule_11_3_violation] */ 630 const ProtocolHeaders_t * pxProtocolHeaders = ( ( const ProtocolHeaders_t * ) 631 &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) ] ) ); 632 FreeRTOS_Socket_t * pxSocket; 633 uint16_t ucTCPFlags = pxProtocolHeaders->xTCPHeader.ucTCPFlags; 634 uint32_t ulLocalIP; 635 uint16_t usLocalPort = FreeRTOS_htons( pxProtocolHeaders->xTCPHeader.usDestinationPort ); 636 uint16_t usRemotePort = FreeRTOS_htons( pxProtocolHeaders->xTCPHeader.usSourcePort ); 637 uint32_t ulRemoteIP; 638 uint32_t ulSequenceNumber = FreeRTOS_ntohl( pxProtocolHeaders->xTCPHeader.ulSequenceNumber ); 639 uint32_t ulAckNumber = FreeRTOS_ntohl( pxProtocolHeaders->xTCPHeader.ulAckNr ); 640 BaseType_t xResult = pdPASS; 641 642 const IPHeader_t * pxIPHeader; 643 644 /* Check for a minimum packet size. */ 645 if( pxNetworkBuffer->xDataLength < ( ipSIZE_OF_ETH_HEADER + xIPHeaderSize( pxNetworkBuffer ) + ipSIZE_OF_TCP_HEADER ) ) 646 { 647 xResult = pdFAIL; 648 } 649 else 650 { 651 /* Map the ethernet buffer onto the IPHeader_t struct for easy access to the fields. */ 652 653 /* MISRA Ref 11.3.1 [Misaligned access] */ 654 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ 655 /* coverity[misra_c_2012_rule_11_3_violation] */ 656 pxIPHeader = ( ( const IPHeader_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipSIZE_OF_ETH_HEADER ] ) ); 657 ulLocalIP = FreeRTOS_htonl( pxIPHeader->ulDestinationIPAddress ); 658 ulRemoteIP = FreeRTOS_htonl( pxIPHeader->ulSourceIPAddress ); 659 660 /* Find the destination socket, and if not found: return a socket listening to 661 * the destination PORT. */ 662 pxSocket = ( FreeRTOS_Socket_t * ) pxTCPSocketLookup( ulLocalIP, usLocalPort, ulRemoteIP, usRemotePort ); 663 664 if( ( pxSocket == NULL ) || ( prvTCPSocketIsActive( pxSocket->u.xTCP.eTCPState ) == pdFALSE ) ) 665 { 666 /* A TCP messages is received but either there is no socket with the 667 * given port number or the there is a socket, but it is in one of these 668 * non-active states: eCLOSED, eCLOSE_WAIT, eFIN_WAIT_2, eCLOSING, or 669 * eTIME_WAIT. */ 670 671 FreeRTOS_debug_printf( ( "TCP: No active socket on port %d (%xip:%d)\n", usLocalPort, ( unsigned ) ulRemoteIP, usRemotePort ) ); 672 673 /* Send a RST to all packets that can not be handled. As a result 674 * the other party will get a ECONN error. There are two exceptions: 675 * 1) A packet that already has the RST flag set. 676 * 2) A packet that only has the ACK flag set. 677 * A packet with only the ACK flag set might be the last ACK in 678 * a three-way hand-shake that closes a connection. */ 679 if( ( ( ucTCPFlags & tcpTCP_FLAG_CTRL ) != tcpTCP_FLAG_ACK ) && 680 ( ( ucTCPFlags & tcpTCP_FLAG_RST ) == 0U ) ) 681 { 682 ( void ) prvTCPSendReset( pxNetworkBuffer ); 683 } 684 685 /* The packet can't be handled. */ 686 xResult = pdFAIL; 687 } 688 else 689 { 690 pxSocket->u.xTCP.ucRepCount = 0U; 691 692 if( pxSocket->u.xTCP.eTCPState == eTCP_LISTEN ) 693 { 694 /* The matching socket is in a listening state. Test if the peer 695 * has set the SYN flag. */ 696 if( ( ucTCPFlags & tcpTCP_FLAG_CTRL ) != tcpTCP_FLAG_SYN ) 697 { 698 /* What happens: maybe after a reboot, a client doesn't know the 699 * connection had gone. Send a RST in order to get a new connect 700 * request. */ 701 #if ( ipconfigHAS_DEBUG_PRINTF == 1 ) 702 { 703 FreeRTOS_debug_printf( ( "TCP: Server can't handle flags: %s from %xip:%u to port %u\n", 704 prvTCPFlagMeaning( ( UBaseType_t ) ucTCPFlags ), ( unsigned ) ulRemoteIP, usRemotePort, usLocalPort ) ); 705 } 706 #endif /* ipconfigHAS_DEBUG_PRINTF */ 707 708 if( ( ucTCPFlags & tcpTCP_FLAG_RST ) == 0U ) 709 { 710 ( void ) prvTCPSendReset( pxNetworkBuffer ); 711 } 712 713 xResult = pdFAIL; 714 } 715 else 716 { 717 /* prvHandleListen() will either return a newly created socket 718 * (if bReuseSocket is false), otherwise it returns the current 719 * socket which will later get connected. */ 720 pxSocket = prvHandleListen( pxSocket, pxNetworkBuffer ); 721 722 if( pxSocket == NULL ) 723 { 724 xResult = pdFAIL; 725 } 726 } 727 } /* if( pxSocket->u.xTCP.eTCPState == eTCP_LISTEN ). */ 728 else 729 { 730 /* This is not a socket in listening mode. Check for the RST 731 * flag. */ 732 if( ( ucTCPFlags & tcpTCP_FLAG_RST ) != 0U ) 733 { 734 FreeRTOS_debug_printf( ( "TCP: RST received from %xip:%u for %u\n", ( unsigned ) ulRemoteIP, usRemotePort, usLocalPort ) ); 735 736 /* Implement https://tools.ietf.org/html/rfc5961#section-3.2. */ 737 if( pxSocket->u.xTCP.eTCPState == eCONNECT_SYN ) 738 { 739 /* Per the above RFC, "In the SYN-SENT state ... the RST is 740 * acceptable if the ACK field acknowledges the SYN." */ 741 if( ulAckNumber == ( pxSocket->u.xTCP.xTCPWindow.ulOurSequenceNumber + 1U ) ) 742 { 743 vTCPStateChange( pxSocket, eCLOSED ); 744 } 745 } 746 else 747 { 748 /* Check whether the packet matches the next expected sequence number. */ 749 if( ulSequenceNumber == pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber ) 750 { 751 vTCPStateChange( pxSocket, eCLOSED ); 752 } 753 /* Otherwise, check whether the packet is within the receive window. */ 754 else if( ( xSequenceGreaterThan( ulSequenceNumber, pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber ) != pdFALSE ) && 755 ( xSequenceLessThan( ulSequenceNumber, pxSocket->u.xTCP.xTCPWindow.rx.ulCurrentSequenceNumber + 756 pxSocket->u.xTCP.xTCPWindow.xSize.ulRxWindowLength ) != pdFALSE ) ) 757 { 758 /* Send a challenge ACK. */ 759 ( void ) prvTCPSendChallengeAck( pxNetworkBuffer ); 760 } 761 else 762 { 763 /* Nothing. */ 764 } 765 } 766 767 /* Otherwise, do nothing. In any case, the packet cannot be handled. */ 768 xResult = pdFAIL; 769 } 770 /* Check whether there is a pure SYN amongst the TCP flags while the connection is established. */ 771 else if( ( ( ucTCPFlags & tcpTCP_FLAG_CTRL ) == tcpTCP_FLAG_SYN ) && ( pxSocket->u.xTCP.eTCPState >= eESTABLISHED ) ) 772 { 773 /* SYN flag while this socket is already connected. */ 774 FreeRTOS_debug_printf( ( "TCP: SYN unexpected from %xip:%u\n", ( unsigned ) ulRemoteIP, usRemotePort ) ); 775 776 /* The packet cannot be handled. */ 777 xResult = pdFAIL; 778 } 779 else 780 { 781 /* Update the copy of the TCP header only (skipping eth and IP 782 * headers). It might be used later on, whenever data must be sent 783 * to the peer. */ 784 const size_t uxOffset = ipSIZE_OF_ETH_HEADER + uxIPHeaderSizeSocket( pxSocket ); 785 ( void ) memcpy( ( void * ) ( &( pxSocket->u.xTCP.xPacket.u.ucLastPacket[ uxOffset ] ) ), 786 ( const void * ) ( &( pxNetworkBuffer->pucEthernetBuffer[ uxOffset ] ) ), 787 ipSIZE_OF_TCP_HEADER ); 788 /* Clear flags that are set by the peer, and set the ACK flag. */ 789 pxSocket->u.xTCP.xPacket.u.ucLastPacket[ uxOffset + ipTCP_FLAGS_OFFSET ] = tcpTCP_FLAG_ACK; 790 } 791 } 792 } 793 794 if( xResult != pdFAIL ) 795 { 796 uint16_t usWindow; 797 798 /* pxSocket is not NULL when xResult != pdFAIL. */ 799 configASSERT( pxSocket != NULL ); /* LCOV_EXCL_LINE ,this branch will not be hit*/ 800 801 /* Touch the alive timers because we received a message for this 802 * socket. */ 803 prvTCPTouchSocket( pxSocket ); 804 805 /* Parse the TCP option(s), if present. */ 806 807 /* _HT_ : if we're in the SYN phase, and peer does not send a MSS option, 808 * then we MUST assume an MSS size of 536 bytes for backward compatibility. */ 809 810 /* When there are no TCP options, the TCP offset equals 20 bytes, which is stored as 811 * the number 5 (words) in the higher nibble of the TCP-offset byte. */ 812 if( ( pxProtocolHeaders->xTCPHeader.ucTCPOffset & tcpTCP_OFFSET_LENGTH_BITS ) > tcpTCP_OFFSET_STANDARD_LENGTH ) 813 { 814 xResult = prvCheckOptions( pxSocket, pxNetworkBuffer ); 815 } 816 817 if( xResult != pdFAIL ) 818 { 819 usWindow = FreeRTOS_ntohs( pxProtocolHeaders->xTCPHeader.usWindow ); 820 pxSocket->u.xTCP.ulWindowSize = ( uint32_t ) usWindow; 821 #if ( ipconfigUSE_TCP_WIN == 1 ) 822 { 823 /* rfc1323 : The Window field in a SYN (i.e., a <SYN> or <SYN,ACK>) 824 * segment itself is never scaled. */ 825 if( ( ucTCPFlags & ( uint8_t ) tcpTCP_FLAG_SYN ) == 0U ) 826 { 827 pxSocket->u.xTCP.ulWindowSize = 828 ( pxSocket->u.xTCP.ulWindowSize << pxSocket->u.xTCP.ucPeerWinScaleFactor ); 829 } 830 } 831 #endif /* ipconfigUSE_TCP_WIN */ 832 833 /* In prvTCPHandleState() the incoming messages will be handled 834 * depending on the current state of the connection. */ 835 if( prvTCPHandleState( pxSocket, &pxNetworkBuffer ) > 0 ) 836 { 837 /* prvTCPHandleState() has sent a message, see if there are more to 838 * be transmitted. */ 839 #if ( ipconfigUSE_TCP_WIN == 1 ) 840 { 841 ( void ) prvTCPSendRepeated( pxSocket, &pxNetworkBuffer ); 842 } 843 #endif /* ipconfigUSE_TCP_WIN */ 844 } 845 846 if( pxNetworkBuffer != NULL ) 847 { 848 /* We must check if the buffer is unequal to NULL, because the 849 * socket might keep a reference to it in case a delayed ACK must be 850 * sent. */ 851 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); 852 #ifndef _lint 853 /* Clear pointers that are freed. */ 854 pxNetworkBuffer = NULL; 855 #endif 856 } 857 858 /* And finally, calculate when this socket wants to be woken up. */ 859 ( void ) prvTCPNextTimeout( pxSocket ); 860 } 861 } 862 } 863 864 /* pdPASS being returned means the buffer has been consumed. */ 865 return xResult; 866 } 867 /*-----------------------------------------------------------*/ 868 869 870 /** 871 * @brief In the API accept(), the user asks is there is a new client? As API's can 872 * not walk through the xBoundTCPSocketsList the IP-task will do this. 873 * 874 * @param[in] pxSocket: The socket for which the bound socket list will be iterated. 875 * 876 * @return if there is a new client, then pdTRUE is returned or else, pdFALSE. 877 */ xTCPCheckNewClient(FreeRTOS_Socket_t * pxSocket)878 BaseType_t xTCPCheckNewClient( FreeRTOS_Socket_t * pxSocket ) 879 { 880 TickType_t uxLocalPort = ( TickType_t ) FreeRTOS_htons( pxSocket->usLocalPort ); 881 const ListItem_t * pxIterator; 882 FreeRTOS_Socket_t * pxFound; 883 BaseType_t xResult = pdFALSE; 884 885 /* MISRA Ref 11.3.1 [Misaligned access] */ 886 /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ 887 /* coverity[misra_c_2012_rule_11_3_violation] */ 888 const ListItem_t * pxEndTCP = ( ( const ListItem_t * ) &( xBoundTCPSocketsList.xListEnd ) ); 889 890 /* Here xBoundTCPSocketsList can be accessed safely IP-task is the only one 891 * who has access. */ 892 for( pxIterator = ( const ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList ); 893 pxIterator != pxEndTCP; 894 pxIterator = ( const ListItem_t * ) listGET_NEXT( pxIterator ) ) 895 { 896 if( listGET_LIST_ITEM_VALUE( pxIterator ) == ( configLIST_VOLATILE TickType_t ) uxLocalPort ) 897 { 898 pxFound = ( ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator ) ); 899 900 if( ( pxFound->ucProtocol == ( uint8_t ) FREERTOS_IPPROTO_TCP ) && ( pxFound->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) ) 901 { 902 pxSocket->u.xTCP.pxPeerSocket = pxFound; 903 FreeRTOS_debug_printf( ( "xTCPCheckNewClient[0]: client on port %u\n", pxSocket->usLocalPort ) ); 904 xResult = pdTRUE; 905 break; 906 } 907 } 908 } 909 910 return xResult; 911 } 912 /*-----------------------------------------------------------*/ 913 914 915 #endif /* ipconfigUSE_TCP == 1 */ 916 917 /* Provide access to private members for testing. */ 918 #ifdef FREERTOS_ENABLE_UNIT_TESTS 919 #include "freertos_tcp_test_access_tcp_define.h" 920 #endif 921 922 /* Provide access to private members for verification. */ 923 #ifdef FREERTOS_TCP_ENABLE_VERIFICATION 924 #include "aws_freertos_tcp_verification_access_tcp_define.h" 925 #endif 926