From e86207c4c8c39f7c86fa031bb742cce25073d20b Mon Sep 17 00:00:00 2001 From: Hein Tibosch Date: Wed, 8 Feb 2023 12:11:39 +0800 Subject: [PATCH] Make sure that a TCP socket is closed only once --- source/FreeRTOS_TCP_IP.c | 33 ++++++++++++++++++++-------- source/include/FreeRTOS_IP_Private.h | 20 +++++++++++++---- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/source/FreeRTOS_TCP_IP.c b/source/FreeRTOS_TCP_IP.c index 7db7737267..995173573d 100644 --- a/source/FreeRTOS_TCP_IP.c +++ b/source/FreeRTOS_TCP_IP.c @@ -445,27 +445,42 @@ } } + /* Fill in the new state. */ + pxSocket->u.xTCP.eTCPState = eTCPState; + if( ( eTCPState == eCLOSED ) || ( eTCPState == eCLOSE_WAIT ) ) { /* Socket goes to status eCLOSED because of a RST. * When nobody owns the socket yet, delete it. */ - if( ( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED ) || - ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) ) + vTaskSuspendAll(); { - FreeRTOS_debug_printf( ( "vTCPStateChange: Closing socket\n" ) ); + if( ( pxSocket->u.xTCP.bits.bPassQueued != pdFALSE_UNSIGNED ) || + ( pxSocket->u.xTCP.bits.bPassAccept != pdFALSE_UNSIGNED ) ) + { + if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) + { + pxSocket->u.xTCP.bits.bPassQueued = pdFALSE_UNSIGNED; + pxSocket->u.xTCP.bits.bPassAccept = pdFALSE_UNSIGNED; + } - if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) + xTaskResumeAll(); + + FreeRTOS_printf( ( "vTCPStateChange: Closing socket\n" ) ); + + if( pxSocket->u.xTCP.bits.bReuseSocket == pdFALSE_UNSIGNED ) + { + configASSERT( xIsCallingFromIPTask() != pdFALSE ); + vSocketCloseNextTime( pxSocket ); + } + } + else { - configASSERT( xIsCallingFromIPTask() != pdFALSE ); - vSocketCloseNextTime( pxSocket ); + xTaskResumeAll(); } } } - /* Fill in the new state. */ - pxSocket->u.xTCP.eTCPState = eTCPState; - if( ( eTCPState == eCLOSE_WAIT ) && ( pxSocket->u.xTCP.bits.bReuseSocket == pdTRUE_UNSIGNED ) ) { switch( xPreviousState ) diff --git a/source/include/FreeRTOS_IP_Private.h b/source/include/FreeRTOS_IP_Private.h index 411cf9cb1b..542c28b247 100644 --- a/source/include/FreeRTOS_IP_Private.h +++ b/source/include/FreeRTOS_IP_Private.h @@ -508,6 +508,20 @@ BaseType_t xIPIsNetworkTaskReady( void ); */ TickType_t xTCPTimerCheck( BaseType_t xWillSleep ); +/** + * About the TCP flags 'bPassQueued' and 'bPassAccept': + * + * When a new TCP connection request is received on a listening socket, the bPassQueued and + * bPassAccept members of the newly created socket are updated as follows: + * + * 1. bPassQueued is set to indicate that the 3-way TCP handshake is in progress. + * 2. When the 3-way TCP handshake is complete, bPassQueued is cleared. At the same time, + * bPassAccept is set to indicate that the socket is ready to be picked up by the task + * that called FreeRTOS_accept(). + * 3. When the socket is picked up by the task that called FreeRTOS_accept, the bPassAccept + * is cleared. + */ + /** * Every TCP socket has a buffer space just big enough to store * the last TCP header received. @@ -544,10 +558,8 @@ BaseType_t xIPIsNetworkTaskReady( void ); /* Most compilers do like bit-flags */ uint32_t bMssChange : 1, /**< This socket has seen a change in MSS */ - bPassAccept : 1, /**< when true, this socket may be returned in a call to accept() */ - bPassQueued : 1, /**< when true, this socket is an orphan until it gets connected - * Why an orphan? Because it may not be returned in a accept() call until it - * gets the state eESTABLISHED */ + bPassAccept : 1, /**< See comment here above. */ + bPassQueued : 1, /**< See comment here above. */ bReuseSocket : 1, /**< When a listening socket gets a connection, do not create a new instance but keep on using it */ bCloseAfterSend : 1, /**< As soon as the last byte has been transmitted, finalise the connection * Useful in e.g. FTP connections, where the last data bytes are sent along with the FIN flag */