diff --git a/source/FreeRTOS_TCP_IP.c b/source/FreeRTOS_TCP_IP.c index 9d9156882e..e892cc569a 100644 --- a/source/FreeRTOS_TCP_IP.c +++ b/source/FreeRTOS_TCP_IP.c @@ -324,7 +324,8 @@ if( ( ( xPreviousState == eCONNECT_SYN ) || ( xPreviousState == eSYN_FIRST ) || ( xPreviousState == eSYN_RECEIVED ) ) && - ( eTCPState == eCLOSE_WAIT ) ) + ( ( eTCPState == eCLOSE_WAIT ) || + ( eTCPState == eCLOSED ) ) ) { /* A socket was in the connecting phase but something * went wrong and it should be closed. */ diff --git a/source/FreeRTOS_TCP_Transmission.c b/source/FreeRTOS_TCP_Transmission.c index 36eb39c5f0..67adc8bcf3 100644 --- a/source/FreeRTOS_TCP_Transmission.c +++ b/source/FreeRTOS_TCP_Transmission.c @@ -132,11 +132,11 @@ { /* The connection is in the SYN status. The packet will be repeated * to most 3 times. When there is no response, the socket get the - * status 'eCLOSE_WAIT'. */ + * status 'eCLOSED'. */ FreeRTOS_debug_printf( ( "Connect: giving up %xip:%u\n", ( unsigned ) pxSocket->u.xTCP.xRemoteIP.ulIP_IPv4, /* IP address of remote machine. */ pxSocket->u.xTCP.usRemotePort ) ); /* Port on remote machine. */ - vTCPStateChange( pxSocket, eCLOSE_WAIT ); + vTCPStateChange( pxSocket, eCLOSED ); } else if( prvTCPMakeSurePrepared( pxSocket ) == pdTRUE ) { diff --git a/test/unit-test/FreeRTOS_TCP_IP/FreeRTOS_TCP_IP_utest.c b/test/unit-test/FreeRTOS_TCP_IP/FreeRTOS_TCP_IP_utest.c index 7eee3348c6..69f19f94d6 100644 --- a/test/unit-test/FreeRTOS_TCP_IP/FreeRTOS_TCP_IP_utest.c +++ b/test/unit-test/FreeRTOS_TCP_IP/FreeRTOS_TCP_IP_utest.c @@ -802,29 +802,60 @@ void test_vTCPStateChange_ClosedWaitState_PrvStateSyn( void ) enum eTCP_STATE eTCPState; BaseType_t xTickCountAck = 0xAABBEEDD; BaseType_t xTickCountAlive = 0xAABBEFDD; - - memset( &xSocket, 0, sizeof( xSocket ) ); - eTCPState = eCLOSE_WAIT; - - xSocket.u.xTCP.eTCPState = eCONNECT_SYN; - - prvTCPSocketIsActive_ExpectAndReturn( xSocket.u.xTCP.eTCPState, pdTRUE ); - vTaskSuspendAll_Expect(); - xTaskResumeAll_ExpectAndReturn( 0 ); - xTaskGetTickCount_ExpectAndReturn( xTickCountAck ); - xTaskGetTickCount_ExpectAndReturn( xTickCountAlive ); - FreeRTOS_inet_ntop_ExpectAnyArgsAndReturn( NULL ); - - vSocketWakeUpUser_Expect( &xSocket ); - - vTCPStateChange( &xSocket, eTCPState ); - - TEST_ASSERT_EQUAL( eCLOSE_WAIT, xSocket.u.xTCP.eTCPState ); - TEST_ASSERT_EQUAL( xTickCountAck, xSocket.u.xTCP.xLastActTime ); - TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, xSocket.u.xTCP.bits.bWaitKeepAlive ); - TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, xSocket.u.xTCP.bits.bSendKeepAlive ); - TEST_ASSERT_EQUAL( 0, xSocket.u.xTCP.ucKeepRepCount ); - TEST_ASSERT_EQUAL( xTickCountAlive, xSocket.u.xTCP.xLastAliveTime ); + BaseType_t xRound; + + /* See Fix incorrect state transition #1302, see RFC 793. + * A changes in state transition: + * Before: eSYN_FIRST -> eCLOSE_WAIT + * After : eSYN_FIRST -> eCLOSED + * For example, a TCP client trying to connect to a remote + * device, reaching a time-out. + */ + for( xRound = 0; xRound < 3; xRound++ ) + { + memset( &xSocket, 0, sizeof( xSocket ) ); + /* The socket was in a SYN state, e.g. eSYN_FIRST. */ + xSocket.u.xTCP.eTCPState = eSYN_FIRST; + + switch( xRound ) + { + /* Check eSYN_FIRST to eCLOSED: */ + case 0: + eTCPState = eCLOSED; + break; + /* Check eSYN_FIRST to eCLOSE_WAIT: */ + case 1: + eTCPState = eCLOSE_WAIT; + break; + /* Check eSYN_FIRST to eSYN_RECEIVED: */ + case 2: + eTCPState = eSYN_RECEIVED; + break; + } + + if( xRound < 2 ) + { + prvTCPSocketIsActive_ExpectAndReturn( xSocket.u.xTCP.eTCPState, pdTRUE ); + vTaskSuspendAll_Expect(); + xTaskResumeAll_ExpectAndReturn( 0 ); + } + + xTaskGetTickCount_ExpectAndReturn( xTickCountAck ); + xTaskGetTickCount_ExpectAndReturn( xTickCountAlive ); + + FreeRTOS_inet_ntop_ExpectAnyArgsAndReturn( NULL ); + + vSocketWakeUpUser_Expect( &xSocket ); + + vTCPStateChange( &xSocket, eTCPState ); + + TEST_ASSERT_EQUAL( eTCPState, xSocket.u.xTCP.eTCPState ); + TEST_ASSERT_EQUAL( xTickCountAck, xSocket.u.xTCP.xLastActTime ); + TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, xSocket.u.xTCP.bits.bWaitKeepAlive ); + TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, xSocket.u.xTCP.bits.bSendKeepAlive ); + TEST_ASSERT_EQUAL( 0, xSocket.u.xTCP.ucKeepRepCount ); + TEST_ASSERT_EQUAL( xTickCountAlive, xSocket.u.xTCP.xLastAliveTime ); + } } /** @@ -2210,6 +2241,7 @@ void test_xProcessReceivedTCPPacket_ConnectSyn_State_Rst_Change_State( void ) uxIPHeaderSizePacket_ExpectAnyArgsAndReturn( ipSIZE_OF_IPv4_HEADER ); pxTCPSocketLookup_ExpectAnyArgsAndReturn( pxSocket ); prvTCPSocketIsActive_ExpectAnyArgsAndReturn( pdTRUE ); + prvTCPSocketIsActive_ExpectAnyArgsAndReturn( pdTRUE ); vTaskSuspendAll_Expect(); xTaskResumeAll_ExpectAndReturn( 0 ); xTaskGetTickCount_ExpectAndReturn( 1000 );