diff --git a/source/FreeRTOS_Sockets.c b/source/FreeRTOS_Sockets.c index 080ec3584..9fd643b3d 100644 --- a/source/FreeRTOS_Sockets.c +++ b/source/FreeRTOS_Sockets.c @@ -4372,11 +4372,11 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket ) * @return Head of the circular transmit buffer if all checks pass. Or else, NULL * is returned. */ - uint8_t * FreeRTOS_get_tx_head( ConstSocket_t xSocket, + uint8_t * FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t * pxLength ) { uint8_t * pucReturn = NULL; - const FreeRTOS_Socket_t * pxSocket = ( const FreeRTOS_Socket_t * ) xSocket; + FreeRTOS_Socket_t * pxSocket = ( FreeRTOS_Socket_t * ) xSocket; StreamBuffer_t * pxBuffer = NULL; *pxLength = 0; @@ -4387,6 +4387,13 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket ) { pxBuffer = pxSocket->u.xTCP.txStream; + if( ( pxBuffer == NULL ) && ( pxSocket->u.xTCP.bits.bMallocError != pdTRUE_UNSIGNED ) ) + { + /* Create the outgoing stream only when it is needed */ + ( void ) prvTCPCreateStream( pxSocket, pdFALSE ); + pxBuffer = pxSocket->u.xTCP.txStream; + } + if( pxBuffer != NULL ) { size_t uxSpace = uxStreamBufferGetSpace( pxBuffer ); @@ -5050,7 +5057,7 @@ void vSocketWakeUpUser( FreeRTOS_Socket_t * pxSocket ) if( pxBuffer == NULL ) { FreeRTOS_debug_printf( ( "prvTCPCreateStream: malloc failed\n" ) ); - pxSocket->u.xTCP.bits.bMallocError = pdTRUE; + pxSocket->u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED; vTCPStateChange( pxSocket, eCLOSE_WAIT ); } else diff --git a/source/include/FreeRTOS_Sockets.h b/source/include/FreeRTOS_Sockets.h index 5ce49529f..5296098c9 100644 --- a/source/include/FreeRTOS_Sockets.h +++ b/source/include/FreeRTOS_Sockets.h @@ -370,7 +370,7 @@ /* For advanced applications only: * Get a direct pointer to the circular transmit buffer. * '*pxLength' will contain the number of bytes that may be written. */ - uint8_t * FreeRTOS_get_tx_head( ConstSocket_t xSocket, + uint8_t * FreeRTOS_get_tx_head( Socket_t xSocket, BaseType_t * pxLength ); /* For the web server: borrow the circular Rx buffer for inspection 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 8a8763043..0b150204c 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 @@ -794,11 +794,48 @@ void test_FreeRTOS_get_tx_head_InvalidParams( void ) /* NULL socket. */ pucReturn = FreeRTOS_get_tx_head( NULL, &xLength ); TEST_ASSERT_EQUAL( NULL, pucReturn ); +} + +/** + * @brief Socket with stream not yet created is passed to the function. + */ +void test_FreeRTOS_get_tx_head_NoStream( void ) +{ + uint8_t * pucReturn; + FreeRTOS_Socket_t xSocket; + BaseType_t xLength; + uint8_t ucStream[ ipconfigTCP_MSS ]; + const size_t uxRemainingSize = 5; + + memset( &xSocket, 0, sizeof( xSocket ) ); + memset( ucStream, 0, ipconfigTCP_MSS ); /* NULL stream. */ xSocket.ucProtocol = FREERTOS_IPPROTO_TCP; + pvPortMalloc_ExpectAnyArgsAndReturn( ucStream ); + uxStreamBufferGetSpace_ExpectAndReturn( ( StreamBuffer_t * ) ucStream, uxRemainingSize ); pucReturn = FreeRTOS_get_tx_head( &xSocket, &xLength ); - TEST_ASSERT_EQUAL( NULL, pucReturn ); + TEST_ASSERT_EQUAL_PTR( &( ( ( StreamBuffer_t * ) ucStream )->ucArray[ 0 ] ), pucReturn ); + TEST_ASSERT_EQUAL( uxRemainingSize, xLength ); +} + +/** + * @brief Socket with stream not created but malloc failed previously. + */ +void test_FreeRTOS_get_tx_head_NoStreamMallocError( void ) +{ + uint8_t * pucReturn; + FreeRTOS_Socket_t xSocket; + BaseType_t xLength; + + memset( &xSocket, 0, sizeof( xSocket ) ); + + /* NULL stream. */ + xSocket.ucProtocol = FREERTOS_IPPROTO_TCP; + xSocket.u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED; + pucReturn = FreeRTOS_get_tx_head( &xSocket, &xLength ); + TEST_ASSERT_EQUAL_PTR( NULL, pucReturn ); + TEST_ASSERT_EQUAL( 0, xLength ); } /** diff --git a/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_privates_utest.c b/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_privates_utest.c index 3b73fb5f3..53ef4625a 100644 --- a/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_privates_utest.c +++ b/test/unit-test/FreeRTOS_Sockets/FreeRTOS_Sockets_privates_utest.c @@ -2296,14 +2296,14 @@ void test_prvTCPSendCheck_InvalidValues( void ) TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_EINVAL, lReturn ); /* No memory. */ - xSocket.u.xTCP.bits.bMallocError = pdTRUE; + xSocket.u.xTCP.bits.bMallocError = pdTRUE_UNSIGNED; xSocket.ucProtocol = FREERTOS_IPPROTO_TCP; listLIST_ITEM_CONTAINER_ExpectAnyArgsAndReturn( &xBoundTCPSocketsList ); lReturn = prvTCPSendCheck( &xSocket, uxDataLength ); TEST_ASSERT_EQUAL( -pdFREERTOS_ERRNO_ENOMEM, lReturn ); /* Invalid states. */ - xSocket.u.xTCP.bits.bMallocError = pdFALSE; + xSocket.u.xTCP.bits.bMallocError = pdFALSE_UNSIGNED; xSocket.ucProtocol = FREERTOS_IPPROTO_TCP; for( unsigned int i = 0; i < sizeof( array ) / sizeof( eIPTCPState_t ); i++ )