diff --git a/source/FreeRTOS_Sockets.c b/source/FreeRTOS_Sockets.c index 6568e8fc02..d143d16463 100644 --- a/source/FreeRTOS_Sockets.c +++ b/source/FreeRTOS_Sockets.c @@ -3891,6 +3891,12 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket ) if( pxParentSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) { pxClientSocket = pxParentSocket->u.xTCP.pxPeerSocket; + + if( pxClientSocket != NULL ) + { + FreeRTOS_printf( ( "prvAcceptWaitClient: client %p parent %p\n", + ( void * ) pxClientSocket, ( void * ) pxParentSocket ) ); + } } else { @@ -3899,11 +3905,14 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket ) if( pxClientSocket != NULL ) { - pxParentSocket->u.xTCP.pxPeerSocket = NULL; - /* Is it still not taken ? */ if( pxClientSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) { + if( pxParentSocket->u.xTCP.pxPeerSocket != NULL ) + { + pxParentSocket->u.xTCP.pxPeerSocket = NULL; + } + pxClientSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED; } else diff --git a/source/FreeRTOS_TCP_IP.c b/source/FreeRTOS_TCP_IP.c index cfba8d04fb..de9e14dff2 100644 --- a/source/FreeRTOS_TCP_IP.c +++ b/source/FreeRTOS_TCP_IP.c @@ -274,6 +274,36 @@ } /*-----------------------------------------------------------*/ + static BaseType_t vTCPRemoveTCPChild( const FreeRTOS_Socket_t * pxChildSocket ) + { + BaseType_t xReturn = pdFALSE; + const ListItem_t * pxEnd = ( ( const ListItem_t * ) &( xBoundTCPSocketsList.xListEnd ) ); + + /* MISRA Ref 11.3.1 [Misaligned access] */ + /* More details at: https://github.com/FreeRTOS/FreeRTOS-Plus-TCP/blob/main/MISRA.md#rule-113 */ + /* coverity[misra_c_2012_rule_11_3_violation] */ + const ListItem_t * pxIterator = ( const ListItem_t * ) listGET_HEAD_ENTRY( &xBoundTCPSocketsList ); + + while( pxIterator != pxEnd ) + { + FreeRTOS_Socket_t * pxSocket; + pxSocket = ( ( FreeRTOS_Socket_t * ) listGET_LIST_ITEM_OWNER( pxIterator ) ); + pxIterator = ( ListItem_t * ) listGET_NEXT( pxIterator ); + + if( ( pxSocket != pxChildSocket ) && ( pxSocket->usLocalPort == pxChildSocket->usLocalPort ) ) + { + if( pxSocket->u.xTCP.pxPeerSocket == pxChildSocket ) /**< for server socket: child, for child socket: parent */ + { + pxSocket->u.xTCP.pxPeerSocket = NULL; + xReturn = pdTRUE; + break; + } + } + } + + return xReturn; + } + /** * @brief Changing to a new state. Centralised here to do specific actions such as * resetting the alive timer, calling the user's OnConnect handler to notify @@ -440,8 +470,33 @@ if( ( eTCPState == eCLOSED ) || ( eTCPState == eCLOSE_WAIT ) ) { + BaseType_t xMustClear = pdFALSE; + BaseType_t xHasCleared = pdFALSE; + + if( ( xParent == pxSocket ) && ( pxSocket->u.xTCP.pxPeerSocket != NULL ) ) + { + xParent = pxSocket->u.xTCP.pxPeerSocket; + } + + if( ( xParent->u.xTCP.pxPeerSocket != NULL ) && + ( xParent->u.xTCP.pxPeerSocket == pxSocket ) ) + { + xMustClear = pdTRUE; + ( void ) xMustClear; + } + /* Socket goes to status eCLOSED because of a RST. * When nobody owns the socket yet, delete it. */ + FreeRTOS_printf( ( "vTCPStateChange: Closing (Queued %d, Accept %d Reuse %d)\n", + pxSocket->u.xTCP.bits.bPassQueued, + pxSocket->u.xTCP.bits.bPassAccept, + pxSocket->u.xTCP.bits.bReuseSocket ) ); + FreeRTOS_printf( ( "vTCPStateChange: me %p parent %p peer %p clear %d\n", + ( void * ) pxSocket, + ( void * ) xParent, + xParent ? ( void * ) xParent->u.xTCP.pxPeerSocket : NULL, + ( int ) xMustClear ) ); + vTaskSuspendAll(); { if( ( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED ) || @@ -449,25 +504,19 @@ { if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) { + xHasCleared = vTCPRemoveTCPChild( pxSocket ); + ( void ) xHasCleared; + pxSocket->u.xTCP.bits.bPassQueued = pdFALSE_UNSIGNED; pxSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED; - } - - ( void ) xTaskResumeAll(); - - FreeRTOS_printf( ( "vTCPStateChange: Closing socket\n" ) ); - - if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) - { configASSERT( xIsCallingFromIPTask() != pdFALSE ); vSocketCloseNextTime( pxSocket ); } } - else - { - ( void ) xTaskResumeAll(); - } } + ( void ) xTaskResumeAll(); + FreeRTOS_printf( ( "vTCPStateChange: xHasCleared = %d\n", + ( int ) xHasCleared ) ); } if( ( eTCPState == eCLOSE_WAIT ) && ( pxSocket->u.xTCP.bits.bReuseSocket == pdTRUE_UNSIGNED ) ) diff --git a/source/FreeRTOS_TCP_State_Handling.c b/source/FreeRTOS_TCP_State_Handling.c index af569bf54b..f8e7de41c5 100644 --- a/source/FreeRTOS_TCP_State_Handling.c +++ b/source/FreeRTOS_TCP_State_Handling.c @@ -1021,11 +1021,19 @@ pxSocket->u.xTCP.usChildCount++; - FreeRTOS_debug_printf( ( "Gain: Socket %u now has %u / %u child%s\n", + if( pxSocket->u.xTCP.pxPeerSocket == NULL ) + { + pxSocket->u.xTCP.pxPeerSocket = pxNewSocket; + } + + FreeRTOS_debug_printf( ( "Gain: Socket %u now has %u / %u child%s me: %p parent: %p peer: %p\n", pxSocket->usLocalPort, pxSocket->u.xTCP.usChildCount, pxSocket->u.xTCP.usBacklog, - ( pxSocket->u.xTCP.usChildCount == 1U ) ? "" : "ren" ) ); + ( pxSocket->u.xTCP.usChildCount == 1U ) ? "" : "ren", + ( void * ) pxNewSocket, + ( void * ) pxSocket, + pxSocket ? ( void * ) pxSocket->u.xTCP.pxPeerSocket : NULL ) ); /* Now bind the child socket to the same port as the listening socket. */ if( vSocketBind( pxNewSocket, &xAddress, sizeof( xAddress ), pdTRUE ) != 0 ) diff --git a/test/cbmc/proofs/TCP/prvTCPHandleState/Makefile.json b/test/cbmc/proofs/TCP/prvTCPHandleState/Makefile.json index a192cca2df..c82fbddc3a 100644 --- a/test/cbmc/proofs/TCP/prvTCPHandleState/Makefile.json +++ b/test/cbmc/proofs/TCP/prvTCPHandleState/Makefile.json @@ -39,6 +39,7 @@ "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto", "$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto", "$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_State_Handling.goto", "$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_Reception.goto", diff --git a/test/cbmc/proofs/TCP/prvTCPHandleState/TCPHandleState_harness.c b/test/cbmc/proofs/TCP/prvTCPHandleState/TCPHandleState_harness.c index 199d032716..1f5f99ea68 100644 --- a/test/cbmc/proofs/TCP/prvTCPHandleState/TCPHandleState_harness.c +++ b/test/cbmc/proofs/TCP/prvTCPHandleState/TCPHandleState_harness.c @@ -91,6 +91,9 @@ void harness() FreeRTOS_Socket_t xSck; xSocketToListen = &xSck; + /* Call to init the socket list. */ + vListInitialise( &xBoundTCPSocketsList ); + if( ensure_memory_is_valid( pxNetworkBuffer, bufferSize ) ) { /* Allocates min. buffer size required for the proof */ diff --git a/test/cbmc/proofs/TCP/prvTCPPrepareSend/Makefile.json b/test/cbmc/proofs/TCP/prvTCPPrepareSend/Makefile.json index 97cbf2b02d..df1df0a680 100644 --- a/test/cbmc/proofs/TCP/prvTCPPrepareSend/Makefile.json +++ b/test/cbmc/proofs/TCP/prvTCPPrepareSend/Makefile.json @@ -31,15 +31,21 @@ "CBMCFLAGS": [ "--unwind 1", + "--unwindset __CPROVER_file_local_FreeRTOS_TCP_IP_c_vTCPRemoveTCPChild.0:1", "--nondet-static" ], "OBJS": [ "$(ENTRY)_harness.goto", + "$(FREERTOS_PLUS_TCP)/test/FreeRTOS-Kernel/list.goto", "$(FREERTOS_PLUS_TCP)/source/FreeRTOS_IP.goto", "$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_IP.goto", "$(FREERTOS_PLUS_TCP)/source/FreeRTOS_TCP_Transmission.goto" ], + "OPT": + [ + "--export-file-local-symbols" + ], "DEF": [ "FREERTOS_TCP_ENABLE_VERIFICATION" diff --git a/test/cbmc/proofs/TCP/prvTCPPrepareSend/TCPPrepareSend_harness.c b/test/cbmc/proofs/TCP/prvTCPPrepareSend/TCPPrepareSend_harness.c index 06e6e7d9ab..d889e16382 100644 --- a/test/cbmc/proofs/TCP/prvTCPPrepareSend/TCPPrepareSend_harness.c +++ b/test/cbmc/proofs/TCP/prvTCPPrepareSend/TCPPrepareSend_harness.c @@ -94,6 +94,9 @@ void harness() UBaseType_t uxOptionsLength; + /* Call to init the socket list. */ + vListInitialise( &xBoundTCPSocketsList ); + if( pxSocket ) { publicTCPPrepareSend( pxSocket, &pxNetworkBuffer, uxOptionsLength ); diff --git a/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_TCP_API_utest.c b/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_TCP_API_utest.c index 10933c2af4..5880a45430 100644 --- a/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_TCP_API_utest.c +++ b/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_TCP_API_utest.c @@ -128,6 +128,34 @@ void test_FreeRTOS_accept_ClientSocketTaken( void ) pxReturn = FreeRTOS_accept( &xServerSocket, &xAddress, &xAddressLength ); TEST_ASSERT_EQUAL( NULL, pxReturn ); +} + +/** + * @brief Client socket is already taken. + */ +void test_FreeRTOS_accept_PeerSocketNullWithReuseSocket( void ) +{ + FreeRTOS_Socket_t xServerSocket, * pxReturn, xPeerSocket; + struct freertos_sockaddr xAddress; + socklen_t xAddressLength; + + memset( &xServerSocket, 0, sizeof( xServerSocket ) ); + memset( &xPeerSocket, 0, sizeof( xPeerSocket ) ); + + /* Invalid Protocol */ + listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( &xBoundTCPSocketsList ); + xServerSocket.ucProtocol = FREERTOS_IPPROTO_TCP; + xServerSocket.u.xTCP.eTCPState = eTCP_LISTEN; + + xServerSocket.u.xTCP.pxPeerSocket = NULL; + xServerSocket.u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED; + xServerSocket.u.xTCP.bits.bReuseSocket = pdTRUE_UNSIGNED; + + vTaskSuspendAll_Expect(); + xTaskResumeAll_ExpectAndReturn( pdFALSE ); + + pxReturn = FreeRTOS_accept( &xServerSocket, &xAddress, &xAddressLength ); + TEST_ASSERT_EQUAL( &xServerSocket, pxReturn ); TEST_ASSERT_EQUAL( NULL, xServerSocket.u.xTCP.pxPeerSocket ); } 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 55d4c112b1..94a972213b 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 @@ -34,15 +34,14 @@ #include #include -/*#include "mock_task.h" */ -#include "mock_TCP_IP_list_macros.h" +#include "mock_task.h" +#include "mock_list.h" /* This must come after list.h is included (in this case, indirectly * by mock_list.h). */ +#include "mock_TCP_IP_list_macros.h" #include "mock_queue.h" -#include "mock_task.h" #include "mock_event_groups.h" -#include "mock_list.h" #include "mock_FreeRTOS_IP.h" #include "mock_FreeRTOS_IP_Utils.h" @@ -55,7 +54,6 @@ #include "mock_FreeRTOS_UDP_IP.h" #include "mock_FreeRTOS_TCP_Transmission.h" #include "mock_FreeRTOS_TCP_Reception.h" -#include "mock_TCP_IP_list_macros.h" #include "catch_assert.h" @@ -82,6 +80,11 @@ uint8_t ucEthernetBuffer[ ipconfigNETWORK_MTU ] = 0xc3, 0x17 }; +static void test_Helper_ListInitialise( List_t * const pxList ); + +static void test_Helper_ListInsertEnd( List_t * const pxList, + ListItem_t * const pxNewListItem ); + /* ============================== Test Cases ============================== */ /** @@ -692,6 +695,103 @@ void test_vTCPStateChange_ClosedState( void ) TEST_ASSERT_EQUAL( xTickCountAlive, xSocket.u.xTCP.xLastAliveTime ); } +/** + * @brief Test functionality when the state to be reached and the + * current state equal to closed state, with child socket. + */ +void test_vTCPStateChange_ClosedState_ChildSocket( void ) +{ + FreeRTOS_Socket_t xSocket = { 0 }; + FreeRTOS_Socket_t xChildSocket = { 0 }; + enum eTCP_STATE eTCPState; + BaseType_t xTickCountAck = 0xAABBEEDD; + BaseType_t xTickCountAlive = 0xAABBEFDD; + + memset( &xSocket, 0, sizeof( xSocket ) ); + eTCPState = eCLOSED; + xSocket.u.xTCP.pxPeerSocket = &xChildSocket; + xChildSocket.u.xTCP.pxPeerSocket = &xSocket; + + vTaskSuspendAll_Expect(); + xTaskResumeAll_ExpectAndReturn( 0 ); + xTaskGetTickCount_ExpectAndReturn( xTickCountAck ); + xTaskGetTickCount_ExpectAndReturn( xTickCountAlive ); + FreeRTOS_inet_ntop_ExpectAnyArgsAndReturn( NULL ); + + vSocketWakeUpUser_Expect( &xChildSocket ); + + vTCPStateChange( &xSocket, eTCPState ); + + TEST_ASSERT_EQUAL( eCLOSED, 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 ); +} + +/** + * @brief Test functionality when the state to be reached and the + * current state equal to closed state, with child socket. + */ +void test_vTCPStateChange_EstablishedState_ChildSocket2( void ) +{ + FreeRTOS_Socket_t xSocket = { 0 }; + FreeRTOS_Socket_t xSocketParent2 = { 0 }; + FreeRTOS_Socket_t xChildSocket = { 0 }; + enum eTCP_STATE eTCPState; + BaseType_t xTickCountAck = 0xAABBEEDD; + BaseType_t xTickCountAlive = 0xAABBEFDD; + + memset( &xSocket, 0, sizeof( xSocket ) ); + eTCPState = eCLOSED; + xSocket.u.xTCP.pxPeerSocket = &xChildSocket; + xSocket.u.xTCP.eTCPState = eESTABLISHED; + xChildSocket.u.xTCP.pxPeerSocket = &xSocketParent2; + xSocket.u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED; + xSocket.u.xTCP.bits.bReuseSocket = pdFALSE_UNSIGNED; + + prvTCPSocketIsActive_ExpectAndReturn( xSocket.u.xTCP.eTCPState, pdTRUE ); + vTaskSuspendAll_Expect(); + + ListItem_t xLocalListItem; + FreeRTOS_Socket_t xSocket2; + + memset( &xSocket2, 0, sizeof( xSocket ) ); + + pxSocket = &xSocket; + List_t * pSocketList = &xBoundTCPSocketsList; + ListItem_t NewEntry; + + pxSocket->xBoundSocketListItem.xItemValue = 40000; + pxSocket->xBoundSocketListItem.pvOwner = pxSocket; + pxSocket->ucProtocol = FREERTOS_IPPROTO_UDP; + pxSocket->u.xTCP.bits.bPassAccept = pdTRUE; + + test_Helper_ListInitialise( pSocketList ); + test_Helper_ListInsertEnd( &xBoundTCPSocketsList, &( pxSocket->xBoundSocketListItem ) ); + + xIsCallingFromIPTask_ExpectAndReturn( pdTRUE ); + + vSocketClose_ExpectAnyArgsAndReturn( NULL ); + + xTaskResumeAll_ExpectAndReturn( 0 ); + xTaskGetTickCount_ExpectAndReturn( xTickCountAck ); + xTaskGetTickCount_ExpectAndReturn( xTickCountAlive ); + FreeRTOS_inet_ntop_ExpectAnyArgsAndReturn( NULL ); + + vSocketWakeUpUser_Expect( &xChildSocket ); + + vTCPStateChange( &xSocket, eTCPState ); + + TEST_ASSERT_EQUAL( eCLOSED, 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 ); +} + /** * @brief Test functionality when the state to be reached is closed wait * and current state is equal to connect syn. @@ -956,9 +1056,29 @@ void test_vTCPStateChange_ClosedWaitState_CallingFromIPTask( void ) xSocket.u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED; vTaskSuspendAll_Expect(); - xTaskResumeAll_ExpectAndReturn( 0 ); + ListItem_t xLocalListItem; + FreeRTOS_Socket_t xSocket2; + + memset( &xSocket2, 0, sizeof( xSocket ) ); + + pxSocket = &xSocket; + List_t * pSocketList = &xBoundTCPSocketsList; + ListItem_t NewEntry; + + pxSocket->xBoundSocketListItem.xItemValue = 40000; + pxSocket->xBoundSocketListItem.pvOwner = pxSocket; + pxSocket->ucProtocol = FREERTOS_IPPROTO_UDP; + pxSocket->u.xTCP.bits.bPassAccept = pdTRUE; + + test_Helper_ListInitialise( pSocketList ); + test_Helper_ListInsertEnd( &xBoundTCPSocketsList, &( pxSocket->xBoundSocketListItem ) ); + + xIsCallingFromIPTask_ExpectAndReturn( pdTRUE ); + vSocketClose_ExpectAnyArgsAndReturn( NULL ); + xTaskResumeAll_ExpectAndReturn( 0 ); + xTaskGetTickCount_ExpectAndReturn( xTickCountAck ); xTaskGetTickCount_ExpectAndReturn( xTickCountAlive ); FreeRTOS_inet_ntop_ExpectAnyArgsAndReturn( NULL ); @@ -993,9 +1113,26 @@ void test_vTCPStateChange_ClosedWaitState_NotCallingFromIPTask( void ) xSocket.u.xTCP.bits.bPassQueued = pdTRUE_UNSIGNED; vTaskSuspendAll_Expect(); - xTaskResumeAll_ExpectAndReturn( 0 ); + ListItem_t xLocalListItem; + FreeRTOS_Socket_t xSocket2; + + memset( &xSocket2, 0, sizeof( xSocket ) ); + + pxSocket = &xSocket; + List_t * pSocketList = &xBoundTCPSocketsList; + ListItem_t NewEntry; + + pxSocket->xBoundSocketListItem.xItemValue = 40000; + pxSocket->xBoundSocketListItem.pvOwner = pxSocket; + pxSocket->ucProtocol = FREERTOS_IPPROTO_UDP; + pxSocket->u.xTCP.bits.bPassAccept = pdTRUE; + + test_Helper_ListInitialise( pSocketList ); + test_Helper_ListInsertEnd( &xBoundTCPSocketsList, &( pxSocket->xBoundSocketListItem ) ); + xIsCallingFromIPTask_ExpectAndReturn( pdFALSE ); + catch_assert( vTCPStateChange( &xSocket, eTCPState ) ); } @@ -1017,9 +1154,27 @@ void test_vTCPStateChange_ClosedWaitState_CallingFromIPTask1( void ) xSocket.u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED; vTaskSuspendAll_Expect(); - xTaskResumeAll_ExpectAndReturn( 0 ); + ListItem_t xLocalListItem; + FreeRTOS_Socket_t xSocket2; + + memset( &xSocket2, 0, sizeof( xSocket ) ); + + pxSocket = &xSocket; + List_t * pSocketList = &xBoundTCPSocketsList; + ListItem_t NewEntry; + + pxSocket->xBoundSocketListItem.xItemValue = 40000; + pxSocket->xBoundSocketListItem.pvOwner = pxSocket; + pxSocket->ucProtocol = FREERTOS_IPPROTO_UDP; + pxSocket->u.xTCP.bits.bPassAccept = pdTRUE; + + test_Helper_ListInitialise( pSocketList ); + test_Helper_ListInsertEnd( &xBoundTCPSocketsList, &( pxSocket->xBoundSocketListItem ) ); + xIsCallingFromIPTask_ExpectAndReturn( pdTRUE ); + xTaskResumeAll_ExpectAndReturn( 0 ); + xTaskGetTickCount_ExpectAndReturn( xTickCountAck ); xTaskGetTickCount_ExpectAndReturn( xTickCountAlive ); FreeRTOS_inet_ntop_ExpectAnyArgsAndReturn( NULL ); @@ -1052,7 +1207,23 @@ void test_vTCPStateChange_ClosedWaitState_NotCallingFromIPTask1( void ) xSocket.u.xTCP.bits.bPassAccept = pdTRUE_UNSIGNED; vTaskSuspendAll_Expect(); - xTaskResumeAll_ExpectAndReturn( 0 ); + ListItem_t xLocalListItem; + FreeRTOS_Socket_t xSocket2; + + memset( &xSocket2, 0, sizeof( xSocket ) ); + + pxSocket = &xSocket; + List_t * pSocketList = &xBoundTCPSocketsList; + ListItem_t NewEntry; + + pxSocket->xBoundSocketListItem.xItemValue = 40000; + pxSocket->xBoundSocketListItem.pvOwner = pxSocket; + pxSocket->ucProtocol = FREERTOS_IPPROTO_UDP; + pxSocket->u.xTCP.bits.bPassAccept = pdTRUE; + + test_Helper_ListInitialise( pSocketList ); + test_Helper_ListInsertEnd( &xBoundTCPSocketsList, &( pxSocket->xBoundSocketListItem ) ); + xIsCallingFromIPTask_ExpectAndReturn( pdFALSE ); catch_assert( vTCPStateChange( &xSocket, eTCPState ) ); @@ -1438,7 +1609,6 @@ void test_vTCPStateChange_ClosedToEstablishedState_SelectWrite_QueuedBitSet_Pare TEST_ASSERT_EQUAL( 100, xSocket.u.xTCP.usTimeout ); TEST_ASSERT_EQUAL( eSOCKET_ACCEPT, xParentSock.xEventBits ); TEST_ASSERT_EQUAL( &xSocket, xParentSock.u.xTCP.pxPeerSocket ); - TEST_ASSERT_EQUAL( NULL, xSocket.u.xTCP.pxPeerSocket ); TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, xSocket.u.xTCP.bits.bPassQueued ); TEST_ASSERT_EQUAL( pdTRUE_UNSIGNED, xSocket.u.xTCP.bits.bPassAccept ); } @@ -1491,7 +1661,6 @@ void test_vTCPStateChange_ClosedToEstablishedState_QueuedBitSet_ParentNonNULL_Ha TEST_ASSERT_EQUAL( 100, xSocket.u.xTCP.usTimeout ); TEST_ASSERT_EQUAL( eSOCKET_ACCEPT, xParentSock.xEventBits ); TEST_ASSERT_EQUAL( &xSocket, xParentSock.u.xTCP.pxPeerSocket ); - TEST_ASSERT_EQUAL( NULL, xSocket.u.xTCP.pxPeerSocket ); TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, xSocket.u.xTCP.bits.bPassQueued ); TEST_ASSERT_EQUAL( pdTRUE_UNSIGNED, xSocket.u.xTCP.bits.bPassAccept ); } @@ -1546,7 +1715,6 @@ void test_vTCPStateChange_ClosedToEstablishedState_QueuedBitSet_ParentNonNULL_Ha TEST_ASSERT_EQUAL( 100, xSocket.u.xTCP.usTimeout ); TEST_ASSERT_EQUAL( eSOCKET_ACCEPT, xParentSock.xEventBits ); TEST_ASSERT_EQUAL( &xSocket, xParentSock.u.xTCP.pxPeerSocket ); - TEST_ASSERT_EQUAL( NULL, xSocket.u.xTCP.pxPeerSocket ); TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, xSocket.u.xTCP.bits.bPassQueued ); TEST_ASSERT_EQUAL( pdTRUE_UNSIGNED, xSocket.u.xTCP.bits.bPassAccept ); } @@ -1597,7 +1765,6 @@ void test_vTCPStateChange_ClosedToEstablishedState_SelectRead_QueuedBitSet_Paren TEST_ASSERT_EQUAL( 0, xSocket.u.xTCP.ucKeepRepCount ); TEST_ASSERT_EQUAL( xTickCountAlive, xSocket.u.xTCP.xLastAliveTime ); TEST_ASSERT_EQUAL( 100, xSocket.u.xTCP.usTimeout ); - TEST_ASSERT_EQUAL( NULL, xSocket.u.xTCP.pxPeerSocket ); TEST_ASSERT_EQUAL( pdFALSE_UNSIGNED, xSocket.u.xTCP.bits.bPassQueued ); TEST_ASSERT_EQUAL( pdTRUE_UNSIGNED, xSocket.u.xTCP.bits.bPassAccept ); TEST_ASSERT_EQUAL( eSOCKET_ACCEPT | ( eSELECT_READ << SOCKET_EVENT_BIT_COUNT ), xSocket.xEventBits ); @@ -2444,3 +2611,102 @@ void test_xTCPCheckNewClient_Found( void ) TEST_ASSERT_EQUAL( pdTRUE, Return ); TEST_ASSERT_EQUAL_PTR( pxSocket, pxSocket->u.xTCP.pxPeerSocket ); } + +/** + * @brief This function validates the case when the child socket is found in + * the bounded socket list. + */ +void test_vTCPRemoveTCPChild_ChildSocketFound( void ) +{ + BaseType_t Return = pdFALSE; + + ListItem_t xLocalListItem; + FreeRTOS_Socket_t xChildSocket; + + memset( &xChildSocket, 0, sizeof( xSocket ) ); + + pxSocket = &xSocket; + List_t * pSocketList = &xBoundTCPSocketsList; + ListItem_t NewEntry; + + pxSocket->xBoundSocketListItem.xItemValue = 40000; + pxSocket->xBoundSocketListItem.pvOwner = pxSocket; + pxSocket->ucProtocol = FREERTOS_IPPROTO_UDP; + pxSocket->u.xTCP.bits.bPassAccept = pdTRUE; + pxSocket->u.xTCP.pxPeerSocket = &xChildSocket; + + xChildSocket.usLocalPort = FreeRTOS_ntohs( 40000 ); + + test_Helper_ListInitialise( pSocketList ); + test_Helper_ListInsertEnd( &xBoundTCPSocketsList, &( pxSocket->xBoundSocketListItem ) ); + + pxSocket->usLocalPort = FreeRTOS_ntohs( 40000 ); + Return = vTCPRemoveTCPChild( &xChildSocket ); + TEST_ASSERT_EQUAL( pdTRUE, Return ); +} + +/** + * @brief This function validates the case when the child socket is found in + * the bounded socket list but non matching port number. + */ +void test_vTCPRemoveTCPChild_ChildSocketFound_DifferentPortNumber( void ) +{ + BaseType_t Return = pdFALSE; + + ListItem_t xLocalListItem; + FreeRTOS_Socket_t xChildSocket; + + memset( &xChildSocket, 0, sizeof( xSocket ) ); + + pxSocket = &xSocket; + List_t * pSocketList = &xBoundTCPSocketsList; + ListItem_t NewEntry; + + pxSocket->xBoundSocketListItem.xItemValue = 40000; + pxSocket->xBoundSocketListItem.pvOwner = pxSocket; + pxSocket->ucProtocol = FREERTOS_IPPROTO_UDP; + pxSocket->u.xTCP.bits.bPassAccept = pdTRUE; + pxSocket->u.xTCP.pxPeerSocket = &xChildSocket; + + xChildSocket.usLocalPort = FreeRTOS_ntohs( 80000 ); + + test_Helper_ListInitialise( pSocketList ); + test_Helper_ListInsertEnd( &xBoundTCPSocketsList, &( pxSocket->xBoundSocketListItem ) ); + + pxSocket->usLocalPort = FreeRTOS_ntohs( 40000 ); + Return = vTCPRemoveTCPChild( &xChildSocket ); + TEST_ASSERT_EQUAL( pdFALSE, Return ); +} + +/** + * @brief This function validates the case when no child socket is found in + * the bounded socket list but matching port number is present. + */ +void test_vTCPRemoveTCPChild_NoChildSocketFound_MatchingPortNumber( void ) +{ + BaseType_t Return = pdFALSE; + + ListItem_t xLocalListItem; + FreeRTOS_Socket_t xChildSocket; + + memset( &xChildSocket, 0, sizeof( xSocket ) ); + + pxSocket = &xSocket; + List_t * pSocketList = &xBoundTCPSocketsList; + ListItem_t NewEntry; + + pxSocket->xBoundSocketListItem.xItemValue = 40000; + pxSocket->xBoundSocketListItem.pvOwner = pxSocket; + pxSocket->ucProtocol = FREERTOS_IPPROTO_UDP; + pxSocket->u.xTCP.bits.bPassAccept = pdTRUE; + pxSocket->u.xTCP.pxPeerSocket = NULL; + + xChildSocket.usLocalPort = FreeRTOS_ntohs( 40000 ); + + test_Helper_ListInitialise( pSocketList ); + test_Helper_ListInsertEnd( &xBoundTCPSocketsList, &( pxSocket->xBoundSocketListItem ) ); + + pxSocket->usLocalPort = FreeRTOS_ntohs( 40000 ); + Return = vTCPRemoveTCPChild( &xChildSocket ); + TEST_ASSERT_EQUAL( pdFALSE, Return ); +} diff --git a/test/unit-test/FreeRTOS_TCP_IP/TCP_IP_list_macros.h b/test/unit-test/FreeRTOS_TCP_IP/TCP_IP_list_macros.h index 97fb8f8eb4..0ed60a2064 100644 --- a/test/unit-test/FreeRTOS_TCP_IP/TCP_IP_list_macros.h +++ b/test/unit-test/FreeRTOS_TCP_IP/TCP_IP_list_macros.h @@ -29,9 +29,13 @@ #define LIST_MACRO_H #include +#include #include #include +#undef listGET_HEAD_ENTRY +ListItem_t * listGET_HEAD_ENTRY( List_t * pxList ); + #undef listSET_LIST_ITEM_OWNER void listSET_LIST_ITEM_OWNER( ListItem_t * pxListItem, void * owner ); diff --git a/test/unit-test/FreeRTOS_TCP_State_Handling/FreeRTOS_TCP_State_Handling_utest.c b/test/unit-test/FreeRTOS_TCP_State_Handling/FreeRTOS_TCP_State_Handling_utest.c index 41cd1a78ce..b65fb12698 100644 --- a/test/unit-test/FreeRTOS_TCP_State_Handling/FreeRTOS_TCP_State_Handling_utest.c +++ b/test/unit-test/FreeRTOS_TCP_State_Handling/FreeRTOS_TCP_State_Handling_utest.c @@ -1800,6 +1800,7 @@ void test_prvTCPSocketCopy_BindError( void ) pxSocket->u.xTCP.uxTxWinSize = 0x123456; pxSocket->pxSocketSet = ( struct xSOCKET_SET * ) 0x1111111; pxSocket->xSelectBits = eSELECT_READ; + pxSocket->u.xTCP.pxPeerSocket = &MockReturnSocket; FreeRTOS_GetLocalAddress_ExpectAndReturn( pxSocket, NULL, pdTRUE ); FreeRTOS_GetLocalAddress_IgnoreArg_pxAddress(); @@ -1811,6 +1812,7 @@ void test_prvTCPSocketCopy_BindError( void ) TEST_ASSERT_NOT_EQUAL( pxSocket->usLocalPort, MockReturnSocket.usLocalPort ); TEST_ASSERT_EQUAL( pxSocket->u.xTCP.uxTxWinSize, MockReturnSocket.u.xTCP.uxTxWinSize ); TEST_ASSERT_EQUAL( ( pxSocket->xSelectBits | eSELECT_READ | eSELECT_EXCEPT ), MockReturnSocket.xSelectBits ); + TEST_ASSERT_EQUAL( pxSocket->u.xTCP.pxPeerSocket, &MockReturnSocket ); } /**