diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index e0a0fa744e4cc3..1a39ce8071a05c 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -428,12 +428,20 @@ void CASESession::Clear() mTCPConnCbCtxt.connClosedCb = nullptr; mTCPConnCbCtxt.connReceivedCb = nullptr; - if (mPeerConnState && mPeerConnState->mConnectionState != Transport::TCPState::kConnected) + if (mPeerConnState) { - // Abort the connection if the CASESession is being destroyed and the - // connection is in the middle of being set up. - mSessionManager->TCPDisconnect(mPeerConnState, /* shouldAbort = */ true); - mPeerConnState = nullptr; + // Set the app state callback object in the Connection state to null + // to prevent any dangling pointer to memory(mTCPConnCbCtxt) owned + // by the CASESession object, that is now getting cleared. + mPeerConnState->mAppState = nullptr; + + if (mPeerConnState->mConnectionState != Transport::TCPState::kConnected) + { + // Abort the connection if the CASESession is being destroyed and the + // connection is in the middle of being set up. + mSessionManager->TCPDisconnect(mPeerConnState, /* shouldAbort = */ true); + mPeerConnState = nullptr; + } } #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT } diff --git a/src/transport/raw/ActiveTCPConnectionState.h b/src/transport/raw/ActiveTCPConnectionState.h index 0f53d4479e9300..2176048cc25364 100644 --- a/src/transport/raw/ActiveTCPConnectionState.h +++ b/src/transport/raw/ActiveTCPConnectionState.h @@ -62,7 +62,10 @@ struct ActiveTCPConnectionState void Free() { - mEndPoint->Free(); + if (mEndPoint) + { + mEndPoint->Free(); + } mPeerAddr = PeerAddress::Uninitialized(); mEndPoint = nullptr; mReceived = nullptr; diff --git a/src/transport/raw/TCP.cpp b/src/transport/raw/TCP.cpp index b73540d7956f29..70d9ed3fdd440e 100644 --- a/src/transport/raw/TCP.cpp +++ b/src/transport/raw/TCP.cpp @@ -55,14 +55,8 @@ constexpr int kListenBacklogSize = 2; TCPBase::~TCPBase() { - if (mListenSocket != nullptr) - { - // endpoint is only non null if it is initialized and listening - mListenSocket->Free(); - mListenSocket = nullptr; - } - - CloseActiveConnections(); + // Call Close to free the listening socket and close all active connections. + Close(); } void TCPBase::CloseActiveConnections() @@ -125,6 +119,9 @@ void TCPBase::Close() mListenSocket->Free(); mListenSocket = nullptr; } + + CloseActiveConnections(); + mState = TCPState::kNotReady; } diff --git a/src/transport/raw/tests/TestTCP.cpp b/src/transport/raw/tests/TestTCP.cpp index 80531491f288a0..78381559a8a364 100644 --- a/src/transport/raw/tests/TestTCP.cpp +++ b/src/transport/raw/tests/TestTCP.cpp @@ -609,6 +609,29 @@ TEST_F(TestTCP, HandleConnCloseCalledTest6) HandleConnCloseTest(addr); } +TEST_F(TestTCP, CheckTCPEndpointAfterCloseTest) +{ + TCPImpl tcp; + + IPAddress addr; + IPAddress::FromString("::1", addr); + + MockTransportMgrDelegate gMockTransportMgrDelegate(mIOContext); + gMockTransportMgrDelegate.InitializeMessageTest(tcp, addr); + gMockTransportMgrDelegate.ConnectTest(tcp, addr); + + Transport::PeerAddress lPeerAddress = Transport::PeerAddress::TCP(addr, gChipTCPPort); + void * state = TestAccess::FindActiveConnection(tcp, lPeerAddress); + ASSERT_NE(state, nullptr); + TCPEndPoint * lEndPoint = TestAccess::GetEndpoint(state); + ASSERT_NE(lEndPoint, nullptr); + + // Call Close and check the TCPEndpoint + tcp.Close(); + lEndPoint = TestAccess::GetEndpoint(state); + ASSERT_EQ(lEndPoint, nullptr); +} + TEST_F(TestTCP, CheckProcessReceivedBuffer) { TCPImpl tcp;