From 5dd2f932a93021417109a227718538ac8879c01c Mon Sep 17 00:00:00 2001 From: Kevin Schoedel Date: Thu, 25 Nov 2021 10:53:18 -0500 Subject: [PATCH] Inet: Split InetLayer class #### Problem This is a step toward #7715 _Virtualize System and Inet interfaces_ for mockability, building on recent virtualization of Inet endpoints and changes to object allocation pools. The `InetLayer` class acts as a factory for `UDPEndPoint` and `TCPEndPoint`. Merely making its methods virtual would result in an unacceptable code size increase for applications that do not use TCP on platforms that offer it, since the vtable would introduce a dependency that normal linking doesn't remove. #### Change overview - Split the `EndPoint` factory/iteration code into its own class, `EndPointManager`. `InetLayer` remains as a stub wrapper for the pair of Managers. - Move the code for TCP idle timeout from `InetLayer` to `TCPEndPoint`. - Move `IPPacketInfo` from `InetLayer.h` to its own files. **NOTE** that applications that use CHIP TCP must now explicitly initialize it via `InetLayer::InitTCP()`. #### Testing CI; no changes to external functionality. Tests revised where necessary to initialize TCP. --- src/credentials/FabricTable.cpp | 1 + src/credentials/tests/TestFabricTable.cpp | 1 - src/include/platform/CHIPDeviceEvent.h | 2 +- src/include/platform/CHIPDeviceLayer.h | 2 + .../internal/GenericPlatformManagerImpl.cpp | 2 +- src/inet/BUILD.gn | 2 + src/inet/EndPointBasis.h | 37 +- src/inet/IPAddress-StringFuncts.cpp | 2 +- src/inet/IPPacketInfo.cpp | 34 ++ src/inet/IPPacketInfo.h | 50 +++ src/inet/InetInterface.cpp | 5 +- src/inet/InetLayer.cpp | 315 ++---------------- src/inet/InetLayer.h | 225 +++++++------ src/inet/TCPEndPoint.cpp | 133 +++++--- src/inet/TCPEndPoint.h | 85 ++--- src/inet/UDPEndPoint.cpp | 19 +- src/inet/UDPEndPoint.h | 67 ++-- src/inet/tests/TestInetCommon.h | 2 + src/inet/tests/TestInetCommonPosix.cpp | 9 +- src/inet/tests/TestInetEndPoint.cpp | 25 +- src/inet/tests/TestInetLayer.cpp | 12 +- src/inet/tests/TestInetLayerCommon.cpp | 1 + src/lib/dnssd/Resolver_ImplMinimalMdns.cpp | 1 + src/lib/dnssd/minimal_mdns/Server.cpp | 4 +- .../dnssd/minimal_mdns/responders/Responder.h | 2 +- src/lib/support/ObjectLifeCycle.h | 21 +- src/messaging/tests/echo/common.cpp | 4 + src/platform/Darwin/CHIPDevicePlatformEvent.h | 1 + src/platform/Globals.cpp | 16 + src/platform/Linux/CHIPDevicePlatformEvent.h | 1 + src/system/SystemLayerImplLibevent.cpp | 3 +- src/system/SystemLayerImplLwIP.cpp | 4 +- src/system/SystemLayerImplSelect.cpp | 3 +- src/system/tests/TestSystemTimer.cpp | 6 +- src/transport/raw/TCP.cpp | 5 +- src/transport/raw/TCP.h | 6 +- src/transport/raw/UDP.cpp | 2 +- src/transport/raw/UDP.h | 7 +- 38 files changed, 486 insertions(+), 631 deletions(-) create mode 100644 src/inet/IPPacketInfo.cpp create mode 100644 src/inet/IPPacketInfo.h diff --git a/src/credentials/FabricTable.cpp b/src/credentials/FabricTable.cpp index 8b9c77a0c7ac20..ae19040827457a 100644 --- a/src/credentials/FabricTable.cpp +++ b/src/credentials/FabricTable.cpp @@ -22,6 +22,7 @@ #include "FabricTable.h" #include +#include #include #include #include diff --git a/src/credentials/tests/TestFabricTable.cpp b/src/credentials/tests/TestFabricTable.cpp index 2972171475007e..b2902edf54523e 100644 --- a/src/credentials/tests/TestFabricTable.cpp +++ b/src/credentials/tests/TestFabricTable.cpp @@ -33,7 +33,6 @@ #include using namespace chip; -using namespace Transport; static const uint8_t sTestRootCert[] = { 0x15, 0x30, 0x01, 0x08, 0x59, 0xea, 0xa6, 0x32, 0x94, 0x7f, 0x54, 0x1c, 0x24, 0x02, 0x01, 0x37, 0x03, 0x27, 0x14, 0x01, 0x00, diff --git a/src/include/platform/CHIPDeviceEvent.h b/src/include/platform/CHIPDeviceEvent.h index 0b28974210b72b..6bf1d304e8f247 100644 --- a/src/include/platform/CHIPDeviceEvent.h +++ b/src/include/platform/CHIPDeviceEvent.h @@ -313,7 +313,7 @@ typedef void (*AsyncWorkFunct)(intptr_t arg); #endif // defined(CHIP_DEVICE_LAYER_TARGET) #include -#include +#include #include #include #include diff --git a/src/include/platform/CHIPDeviceLayer.h b/src/include/platform/CHIPDeviceLayer.h index a03bbbcac48edc..fd61b902588e69 100644 --- a/src/include/platform/CHIPDeviceLayer.h +++ b/src/include/platform/CHIPDeviceLayer.h @@ -47,6 +47,8 @@ void SetSystemLayerForTesting(System::LayerImpl * layer); // These functions are defined in src/platform/Globals.cpp chip::Inet::InetLayer & InetLayer(); +chip::Inet::EndPointManager * UDPEndPointManager(); +chip::Inet::EndPointManager * TCPEndPointManager(); chip::System::Layer & SystemLayer(); #if CHIP_SYSTEM_CONFIG_USE_SOCKETS diff --git a/src/include/platform/internal/GenericPlatformManagerImpl.cpp b/src/include/platform/internal/GenericPlatformManagerImpl.cpp index 158780f37c0c19..bb6f1f5407eff7 100644 --- a/src/include/platform/internal/GenericPlatformManagerImpl.cpp +++ b/src/include/platform/internal/GenericPlatformManagerImpl.cpp @@ -81,7 +81,7 @@ CHIP_ERROR GenericPlatformManagerImpl::_InitChipStack() SuccessOrExit(err); // Initialize the CHIP Inet layer. - err = InetLayer().Init(SystemLayer(), nullptr); + err = InetLayer().Init(SystemLayer(), UDPEndPointManager()); if (err != CHIP_NO_ERROR) { ChipLogError(DeviceLayer, "InetLayer initialization failed: %s", ErrorStr(err)); diff --git a/src/inet/BUILD.gn b/src/inet/BUILD.gn index 30c60673916893..44f33bbe834643 100644 --- a/src/inet/BUILD.gn +++ b/src/inet/BUILD.gn @@ -72,6 +72,8 @@ static_library("inet") { "IPAddress-StringFuncts.cpp", "IPAddress.cpp", "IPAddress.h", + "IPPacketInfo.cpp", + "IPPacketInfo.h", "IPPrefix.cpp", "IPPrefix.h", "Inet.h", diff --git a/src/inet/EndPointBasis.h b/src/inet/EndPointBasis.h index 0bee2f192770d9..bf9b60cd2f42b4 100644 --- a/src/inet/EndPointBasis.h +++ b/src/inet/EndPointBasis.h @@ -25,30 +25,55 @@ #pragma once #include +#include #include namespace chip { + +namespace System { +class Layer; +} // namespace System + namespace Inet { -class InetLayer; +template +class EndPointManager; + +template +class EndPointDeletor; /** * Basis of internet transport endpoint classes. */ -class DLL_EXPORT EndPointBase +template +class DLL_EXPORT EndPointBasis : public ReferenceCounted> { public: - EndPointBase(InetLayer & aInetLayer, void * aAppState = nullptr) : mAppState(aAppState), mInetLayer(aInetLayer) {} + using EndPoint = EndPointType; + + EndPointBasis(EndPointManager & endPointManager) : mAppState(nullptr), mEndPointManager(endPointManager) {} /** - * Returns a reference to the Inet layer object that owns this basis object. + * Returns a reference to the endpoint fatory that owns this basis object. */ - InetLayer & Layer() const { return mInetLayer; } + EndPointManager & GetEndPointManager() const { return mEndPointManager; } + + /** + * Returns a reference to the System::Layer associated with this object. + */ + chip::System::Layer & GetSystemLayer() const { return mEndPointManager.SystemLayer(); } void * mAppState; private: - InetLayer & mInetLayer; /**< InetLayer object that owns this object. */ + EndPointManager & mEndPointManager; /**< Factory that owns this object. */ +}; + +template +class EndPointDeletor +{ +public: + static void Release(EndPointType * obj) { obj->GetEndPointManager().DeleteEndPoint(obj); } }; } // namespace Inet diff --git a/src/inet/IPAddress-StringFuncts.cpp b/src/inet/IPAddress-StringFuncts.cpp index 86aeafe5ba7104..3db3f53fc31f2c 100644 --- a/src/inet/IPAddress-StringFuncts.cpp +++ b/src/inet/IPAddress-StringFuncts.cpp @@ -30,7 +30,7 @@ #include #include -#include +#include #include #if !CHIP_SYSTEM_CONFIG_USE_LWIP diff --git a/src/inet/IPPacketInfo.cpp b/src/inet/IPPacketInfo.cpp new file mode 100644 index 00000000000000..edd2fd1213f566 --- /dev/null +++ b/src/inet/IPPacketInfo.cpp @@ -0,0 +1,34 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IPPacketInfo.h" + +namespace chip { +namespace Inet { + +void IPPacketInfo::Clear() +{ + SrcAddress = IPAddress::Any; + DestAddress = IPAddress::Any; + Interface = InterfaceId::Null(); + SrcPort = 0; + DestPort = 0; +} + +} // namespace Inet +} // namespace chip diff --git a/src/inet/IPPacketInfo.h b/src/inet/IPPacketInfo.h new file mode 100644 index 00000000000000..666edd53759f09 --- /dev/null +++ b/src/inet/IPPacketInfo.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2020-2021 Project CHIP Authors + * Copyright (c) 2013-2017 Nest Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace Inet { + +/** + * Information about an incoming/outgoing message/connection. + * + * @warning + * Do not alter the contents of this class without first reading and understanding + * the code/comments in UDPEndPoint::GetPacketInfo(). + */ +class IPPacketInfo +{ +public: + IPAddress SrcAddress; /**< The source IPAddress in the packet. */ + IPAddress DestAddress; /**< The destination IPAddress in the packet. */ + InterfaceId Interface; /**< The interface identifier for the connection. */ + uint16_t SrcPort; /**< The source port in the packet. */ + uint16_t DestPort; /**< The destination port in the packet. */ + + /** + * Reset the members of the IPPacketInfo object. + */ + void Clear(); +}; + +} // namespace Inet +} // namespace chip diff --git a/src/inet/InetInterface.cpp b/src/inet/InetInterface.cpp index ed6ce664cb6a8b..a049c0a432840e 100644 --- a/src/inet/InetInterface.cpp +++ b/src/inet/InetInterface.cpp @@ -27,10 +27,9 @@ #define __STDC_LIMIT_MACROS #endif -#include "InetInterface.h" - -#include "InetLayer.h" +#include +#include #include #include #include diff --git a/src/inet/InetLayer.cpp b/src/inet/InetLayer.cpp index 8b006a0f83f7b3..06024c7f582359 100644 --- a/src/inet/InetLayer.cpp +++ b/src/inet/InetLayer.cpp @@ -17,332 +17,65 @@ */ /** - * @file - * This file defines classes for abstracting access to and - * interactions with a platform- and system-specific Internet - * Protocol stack which, as of this implementation, may be either - * BSD/POSIX Sockets or LwIP. - * - * Major abstractions provided are: - * - * * Timers - * * Domain Name System (DNS) resolution - * * TCP network transport - * * UDP network transport - * * Raw network transport - * - * For BSD/POSIX Sockets (CHIP_SYSTEM_CONFIG_USE_SOCKETS), event readiness - * notification is handled via file descriptors, using a System::Layer API. - * - * For LwIP (CHIP_SYSTEM_CONFIG_USE_LWIP), event readiness notification is handled - * via events / messages and platform- and system-specific hooks for the event - * / message system. - * + * Provides access to UDP (and optionally TCP) EndPointManager. */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif -#include "InetLayer.h" - -#include "InetFaultInjection.h" - -#include +#include +#include #include #include - -#include -#include -#include -#include -#include - -#if CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#else // !CHIP_SYSTEM_CONFIG_USE_LWIP -#include -#include -#include -#ifdef __ANDROID__ -#include -#elif CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS -#include -#endif -#endif // CHIP_SYSTEM_CONFIG_USE_LWIP - -#if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF -#include -#endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF +#include namespace chip { namespace Inet { -/** - * This is the InetLayer default constructor. - * - * It performs some basic data member initialization; however, since - * InetLayer follows an explicit initializer design pattern, the InetLayer::Init - * method must be called successfully prior to using the object. - * - */ -InetLayer::InetLayer() {} - -/** - * This is the InetLayer explicit initializer. This must be called - * and complete successfully before the InetLayer may be used. - * - * The caller may provide an optional context argument which will be - * passed back via any platform-specific hook functions. For - * LwIP-based adaptations, this will typically be a pointer to the - * event queue associated with the InetLayer instance. - * - * @param[in] aSystemLayer A required instance of the chip System Layer - * already successfully initialized. - * - * @param[in] aContext An optional context argument which will be passed - * back to the caller via any platform-specific hook - * functions. - * - * @retval #CHIP_ERROR_INCORRECT_STATE If the InetLayer is in an - * incorrect state. - * @retval #CHIP_ERROR_NO_MEMORY If the InetLayer runs out - * of resource for this - * request for a new timer. - * @retval other Platform-specific errors indicating the reason for - * initialization failure. - * @retval #CHIP_NO_ERROR On success. - * - */ -CHIP_ERROR InetLayer::Init(chip::System::Layer & aSystemLayer, void * aContext) +CHIP_ERROR InetLayer::Init(System::Layer & aSystemLayer, EndPointManager * udpEndPointManager) { Inet::RegisterLayerErrorFormatter(); VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE); - - // Platform-specific initialization may elect to set this data - // member. Ensure it is set to a sane default value before - // invoking platform-specific initialization. - - mPlatformData = nullptr; + VerifyOrReturnError(udpEndPointManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); mSystemLayer = &aSystemLayer; - mContext = aContext; + ReturnErrorOnFailure(udpEndPointManager->Init(aSystemLayer)); + mUDPEndPointManager = udpEndPointManager; mLayerState.SetInitialized(); - return CHIP_NO_ERROR; } -/** - * This is the InetLayer explicit deinitializer and should be called - * prior to disposing of an instantiated InetLayer instance. - * - * @return #CHIP_NO_ERROR on success; otherwise, a specific error indicating - * the reason for shutdown failure. - * - */ CHIP_ERROR InetLayer::Shutdown() { VerifyOrReturnError(mLayerState.SetShuttingDown(), CHIP_ERROR_INCORRECT_STATE); - - CHIP_ERROR err = CHIP_NO_ERROR; - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - // Abort all TCP endpoints owned by this instance. - TCPEndPointImpl::sPool.ForEachActiveObject([&](TCPEndPoint * lEndPoint) { - if ((lEndPoint != nullptr) && &lEndPoint->Layer() == this) - { - lEndPoint->Abort(); - } - return true; - }); -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - // Close all UDP endpoints owned by this instance. - UDPEndPointImpl::sPool.ForEachActiveObject([&](UDPEndPoint * lEndPoint) { - if ((lEndPoint != nullptr) && &lEndPoint->Layer() == this) - { - lEndPoint->Close(); - } - return true; - }); -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - - mLayerState.SetShutdown(); - mLayerState.Reset(); // Return to uninitialized state to permit re-initialization. - return err; -} - -/** - * This returns any client-specific platform data assigned to the - * instance, if it has been previously set. - * - * @return Client-specific platform data, if is has been previously set; - * otherwise, NULL. - * - */ -void * InetLayer::GetPlatformData() -{ - return mPlatformData; -} - -/** - * This sets the specified client-specific platform data to the - * instance for later retrieval by the client platform. - * - * @param[in] aPlatformData The client-specific platform data to set. - * - */ -void InetLayer::SetPlatformData(void * aPlatformData) -{ - mPlatformData = aPlatformData; -} - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 -bool InetLayer::IsIdleTimerRunning() -{ - bool timerRunning = false; - - // See if there are any TCP connections with the idle timer check in use. - TCPEndPointImpl::sPool.ForEachActiveObject([&](TCPEndPoint * lEndPoint) { - if ((lEndPoint != nullptr) && (lEndPoint->mIdleTimeout != 0)) - { - timerRunning = true; - return false; - } - return true; - }); - - return timerRunning; + VerifyOrReturnError(mTCPEndPointManager == nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(mUDPEndPointManager->Shutdown()); + mLayerState.ResetFromShuttingDown(); // Return to uninitialized state to permit re-initialization. + return CHIP_NO_ERROR; } -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 -#if INET_CONFIG_ENABLE_TCP_ENDPOINT -/** - * Creates a new TCPEndPoint object. - * - * @note - * This function gets a free TCPEndPoint object from a pre-allocated pool - * and also calls the explicit initializer on the new object. - * - * @param[in,out] retEndPoint A pointer to a pointer of the TCPEndPoint object that is - * a return parameter upon completion of the object creation. - * *retEndPoint is NULL if creation fails. - * - * @retval #CHIP_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. - * @retval #CHIP_ERROR_ENDPOINT_POOL_FULL If the InetLayer TCPEndPoint pool is full and no new - * endpoints can be created. - * @retval #CHIP_NO_ERROR On success. - * - */ -CHIP_ERROR InetLayer::NewTCPEndPoint(TCPEndPoint ** retEndPoint) +CHIP_ERROR InetLayer::InitTCP(EndPointManager * tcpEndPointManager) { - assertChipStackLockedByCurrentThread(); - - *retEndPoint = nullptr; - VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE); - - *retEndPoint = TCPEndPointImpl::sPool.CreateObject(*this); - if (*retEndPoint == nullptr) - { - ChipLogError(Inet, "%s endpoint pool FULL", "TCP"); - return CHIP_ERROR_ENDPOINT_POOL_FULL; - } - - SYSTEM_STATS_INCREMENT(chip::System::Stats::kInetLayer_NumTCPEps); - +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + VerifyOrReturnError(tcpEndPointManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorOnFailure(tcpEndPointManager->Init(*mSystemLayer)); +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT + mTCPEndPointManager = tcpEndPointManager; return CHIP_NO_ERROR; } -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT -#if INET_CONFIG_ENABLE_UDP_ENDPOINT -/** - * Creates a new UDPEndPoint object. - * - * @note - * This function gets a free UDPEndPoint object from a pre-allocated pool - * and also calls the explicit initializer on the new object. - * - * @param[in,out] retEndPoint A pointer to a pointer of the UDPEndPoint object that is - * a return parameter upon completion of the object creation. - * *retEndPoint is NULL if creation fails. - * - * @retval #CHIP_ERROR_INCORRECT_STATE If the InetLayer object is not initialized. - * @retval #CHIP_ERROR_ENDPOINT_POOL_FULL If the InetLayer UDPEndPoint pool is full and no new - * endpoints can be created. - * @retval #CHIP_NO_ERROR On success. - * - */ -CHIP_ERROR InetLayer::NewUDPEndPoint(UDPEndPoint ** retEndPoint) +CHIP_ERROR InetLayer::ShutdownTCP() { - assertChipStackLockedByCurrentThread(); - - *retEndPoint = nullptr; - VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE); - - *retEndPoint = UDPEndPointImpl::sPool.CreateObject(*this); - if (*retEndPoint == nullptr) +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + if (mTCPEndPointManager != nullptr) { - ChipLogError(Inet, "%s endpoint pool FULL", "UDP"); - return CHIP_ERROR_ENDPOINT_POOL_FULL; + ReturnErrorOnFailure(mTCPEndPointManager->Shutdown()); + mTCPEndPointManager = nullptr; } - - SYSTEM_STATS_INCREMENT(chip::System::Stats::kInetLayer_NumUDPEps); - +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT return CHIP_NO_ERROR; } -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 -void InetLayer::HandleTCPInactivityTimer(chip::System::Layer * aSystemLayer, void * aAppState) -{ - InetLayer & lInetLayer = *reinterpret_cast(aAppState); - bool lTimerRequired = lInetLayer.IsIdleTimerRunning(); - - TCPEndPointImpl::sPool.ForEachActiveObject([&](TCPEndPoint * lEndPoint) { - if (&lEndPoint->Layer() != &lInetLayer) - return true; - if (!lEndPoint->IsConnected()) - return true; - if (lEndPoint->mIdleTimeout == 0) - return true; - - if (lEndPoint->mRemainingIdleTime == 0) - { - lEndPoint->DoClose(INET_ERROR_IDLE_TIMEOUT, false); - } - else - { - --lEndPoint->mRemainingIdleTime; - } - - return true; - }); - - if (lTimerRequired) - { - aSystemLayer->StartTimer(System::Clock::Milliseconds32(INET_TCP_IDLE_CHECK_INTERVAL), HandleTCPInactivityTimer, - &lInetLayer); - } -} -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 - -/** - * Reset the members of the IPPacketInfo object. - * - */ -void IPPacketInfo::Clear() -{ - SrcAddress = IPAddress::Any; - DestAddress = IPAddress::Any; - Interface = InterfaceId::Null(); - SrcPort = 0; - DestPort = 0; -} } // namespace Inet } // namespace chip diff --git a/src/inet/InetLayer.h b/src/inet/InetLayer.h index 9ebbff3f136f58..8200ec060e8f21 100644 --- a/src/inet/InetLayer.h +++ b/src/inet/InetLayer.h @@ -17,150 +17,157 @@ */ /** - * @file - * This file defines classes for abstracting access to and - * interactions with a platform- and system-specific Internet - * Protocol stack which, as of this implementation, may be either - * BSD/POSIX Sockets, LwIP or Network.framework. - * - * Major abstractions provided are: - * - * * Timers - * * Domain Name System (DNS) resolution - * * TCP network transport - * * UDP network transport - * * Raw network transport - * - * For BSD/POSIX Sockets, event readiness notification is handled - * via file descriptors and a traditional poll / select - * implementation on the platform adaptation. - * - * For LwIP, event readiness notification is handled via events / - * messages and platform- and system-specific hooks for the event - * / message system. - * + * Provides access to UDP (and optionally TCP) EndPointManager. */ #pragma once -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS -#endif - -#include - -#include -#include -#include -#include -#include -#include - -#if INET_CONFIG_ENABLE_TCP_ENDPOINT -#include -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT -#include -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT - +#include +#include #include #include -#include -#include - #include namespace chip { namespace Inet { -class InetLayer; - /** - * @class InetLayer - * - * @brief - * This provides access to Internet services, including timers, - * Domain Name System (DNS) resolution, TCP network transport, UDP - * network transport, and raw network transport, for a single - * thread. - * - * For BSD/POSIX Sockets, event readiness notification is handled - * via file descriptors and a traditional poll / select - * implementation on the platform adaptation. - * - * For LwIP, event readiness notification is handle via events / - * messages and platform- and system-specific hooks for the event / - * message system. + * Template providing traits for EndPoint types used by EndPointManager. * + * Instances must define: + * static constexpr const char * Name; + * static constexpr int SystemStatsKey; */ -class DLL_EXPORT InetLayer -{ -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - friend class TCPEndPoint; -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT - -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - friend class UDPEndPoint; -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT +template +struct EndPointProperties; +/** + * Manage creating, deletion, and iteration of Inet::EndPoint types. + */ +template +class EndPointManager +{ public: - InetLayer(); + using EndPoint = EndPointType; + using EndPointVisitor = bool (*)(EndPoint *); - CHIP_ERROR Init(chip::System::Layer & aSystemLayer, void * aContext); + EndPointManager() {} + virtual ~EndPointManager() {} - // Must be called before System::Layer::Shutdown(), since this holds a pointer to that. - CHIP_ERROR Shutdown(); + CHIP_ERROR Init(System::Layer & systemLayer) + { + mSystemLayer = &systemLayer; + return CHIP_NO_ERROR; + } - chip::System::Layer * SystemLayer() const { return mSystemLayer; } + CHIP_ERROR Shutdown() { return CHIP_NO_ERROR; } - // End Points + System::Layer & SystemLayer() const { return *mSystemLayer; } -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - CHIP_ERROR NewTCPEndPoint(TCPEndPoint ** retEndPoint); -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT + CHIP_ERROR NewEndPoint(EndPoint ** retEndPoint) + { + assertChipStackLockedByCurrentThread(); -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - CHIP_ERROR NewUDPEndPoint(UDPEndPoint ** retEndPoint); -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT + *retEndPoint = CreateEndPoint(); + if (*retEndPoint == nullptr) + { + ChipLogError(Inet, "%s endpoint pool FULL", EndPointProperties::Name); + return CHIP_ERROR_ENDPOINT_POOL_FULL; + } - void * GetPlatformData(); - void SetPlatformData(void * aPlatformData); + // TODO: Use the Impl's underlying ObjectPool statistics + SYSTEM_STATS_INCREMENT(EndPointProperties::SystemStatsKey); + return CHIP_NO_ERROR; + } -#if INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 - static void HandleTCPInactivityTimer(chip::System::Layer * aSystemLayer, void * aAppState); -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0 + virtual EndPoint * CreateEndPoint() = 0; + virtual void DeleteEndPoint(EndPoint * endPoint) = 0; + virtual bool ForEachEndPoint(const EndPointVisitor visitor) = 0; private: - ObjectLifeCycle mLayerState; - void * mContext; - void * mPlatformData; - chip::System::Layer * mSystemLayer; + System::Layer * mSystemLayer; +}; - bool IsIdleTimerRunning(); +template +class EndPointManagerImplPool : public EndPointManager +{ +public: + using Manager = EndPointManager; + using EndPoint = typename EndPointImpl::EndPoint; + + EndPointManagerImplPool() = default; + ~EndPointManagerImplPool() { VerifyOrDie(sEndPointPool.Allocated() == 0); } + + EndPoint * CreateEndPoint() override { return sEndPointPool.CreateObject(*this); } + void DeleteEndPoint(EndPoint * endPoint) override { sEndPointPool.ReleaseObject(static_cast(endPoint)); } + bool ForEachEndPoint(const typename Manager::EndPointVisitor visitor) override + { + return sEndPointPool.ForEachActiveObject([&](EndPoint * endPoint) -> bool { return visitor(endPoint); }); + } + +private: + ObjectPool sEndPointPool; }; +class TCPEndPoint; +class UDPEndPoint; + /** - * @class IPPacketInfo - * - * @brief - * Information about an incoming/outgoing message/connection. - * - * @warning - * Do not alter the contents of this class without first reading and understanding - * the code/comments in UDPEndPoint::GetPacketInfo(). + * Provides access to UDP (and optionally TCP) EndPointManager. */ -class IPPacketInfo +class InetLayer { public: - IPAddress SrcAddress; /**< The source IPAddress in the packet. */ - IPAddress DestAddress; /**< The destination IPAddress in the packet. */ - InterfaceId Interface; /**< The interface identifier for the connection. */ - uint16_t SrcPort; /**< The source port in the packet. */ - uint16_t DestPort; /**< The destination port in the packet. */ + InetLayer() = default; + ~InetLayer() { mLayerState.Destroy(); } + + /** + * This is the InetLayer explicit initializer. This must be called + * and complete successfully before the InetLayer may be used. + * + * The caller may provide an optional context argument which will be + * passed back via any platform-specific hook functions. For + * LwIP-based adaptations, this will typically be a pointer to the + * event queue associated with the InetLayer instance. + * + * @param[in] aSystemLayer A required instance of the chip System Layer already successfully initialized. + * @param[in] udpEndPointManager A required instance of an implementation of EndPointManager. + * This function will initialize the EndPointManager. + * + * @retval #CHIP_ERROR_INCORRECT_STATE If the InetLayer is in an incorrect state. + * @retval #CHIP_NO_ERROR On success. + * + */ + CHIP_ERROR Init(System::Layer & aSystemLayer, EndPointManager * udpEndPointManager); + + /** + * This is the InetLayer explicit deinitializer and should be called + * prior to disposing of an instantiated InetLayer instance. + * + * Must be called before System::Layer::Shutdown(), since this holds a pointer to that. + * + * @return #CHIP_NO_ERROR on success; otherwise, a specific error indicating + * the reason for shutdown failure. + * + */ + CHIP_ERROR Shutdown(); + + EndPointManager * GetUDPEndPointManager() const { return mUDPEndPointManager; } - void Clear(); + // Initialize the TCP EndPointManager. Must be called after Init() if the appication uses TCP. + CHIP_ERROR InitTCP(EndPointManager * tcpEndPointManager); + // Shut down the TCP EndPointManager. Must be called before Shutdown() if the appication uses TCP. + CHIP_ERROR ShutdownTCP(); + EndPointManager * GetTCPEndPointManager() const { return mTCPEndPointManager; } + + chip::System::Layer * SystemLayer() const { return mSystemLayer; } + +private: + ObjectLifeCycle mLayerState; + System::Layer * mSystemLayer; + EndPointManager * mTCPEndPointManager; + EndPointManager * mUDPEndPointManager; }; } // namespace Inet diff --git a/src/inet/TCPEndPoint.cpp b/src/inet/TCPEndPoint.cpp index 56fe46609648a0..1eb693ef833b4d 100644 --- a/src/inet/TCPEndPoint.cpp +++ b/src/inet/TCPEndPoint.cpp @@ -32,10 +32,9 @@ #define __STDC_LIMIT_MACROS #endif -#include "TCPEndPoint.h" +#include #include -#include #include #include @@ -89,8 +88,6 @@ namespace Inet { #if CHIP_SYSTEM_CONFIG_USE_LWIP -BitMapObjectPool TCPEndPointImplLwIP::sPool; - namespace { /* @@ -954,8 +951,7 @@ err_t TCPEndPointImplLwIP::LwIPHandleConnectComplete(void * arg, struct tcp_pcb if (arg != NULL) { - TCPEndPointImplLwIP * ep = static_cast(arg); - System::Layer * lSystemLayer = ep->Layer().SystemLayer(); + TCPEndPointImplLwIP * ep = static_cast(arg); if (lwipErr == ERR_OK) { @@ -966,7 +962,7 @@ err_t TCPEndPointImplLwIP::LwIPHandleConnectComplete(void * arg, struct tcp_pcb // Post callback to HandleConnectComplete. ep->Retain(); - CHIP_ERROR err = lSystemLayer->ScheduleLambda([ep, conErr = System::MapErrorLwIP(lwipErr)] { + CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, conErr = System::MapErrorLwIP(lwipErr)] { ep->HandleConnectComplete(conErr); ep->Release(); }); @@ -993,7 +989,7 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p { TCPEndPointImplLwIP * listenEP = static_cast(arg); TCPEndPointImplLwIP * conEP = NULL; - System::Layer * lSystemLayer = listenEP->Layer().SystemLayer(); + System::Layer & lSystemLayer = listenEP->GetSystemLayer(); // Tell LwIP we've accepted the connection so it can decrement the listen PCB's pending_accepts counter. tcp_accepted(listenEP->mTCP); @@ -1007,10 +1003,8 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p // if (err == CHIP_NO_ERROR) { - InetLayer & lInetLayer = listenEP->Layer(); - TCPEndPoint * connectEndPoint = nullptr; - err = lInetLayer.NewTCPEndPoint(&connectEndPoint); + err = listenEP->GetEndPointManager().NewEndPoint(&connectEndPoint); conEP = static_cast(connectEndPoint); } @@ -1042,7 +1036,7 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p // Post a callback to the HandleConnectionReceived() function, passing it the new end point. listenEP->Retain(); conEP->Retain(); - err = lSystemLayer->ScheduleLambda([listenEP, conEP] { + err = lSystemLayer.ScheduleLambda([listenEP, conEP] { listenEP->HandleIncomingConnection(conEP); conEP->Release(); listenEP->Release(); @@ -1053,7 +1047,7 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p listenEP->Release(); err = CHIP_ERROR_CONNECTION_ABORTED; conEP->Release(); // for the Retain() above - conEP->Release(); // for the Retain() in NewTCPEndPoint() + conEP->Release(); // for the implied Retain() on construction } } @@ -1061,7 +1055,7 @@ err_t TCPEndPointImplLwIP::LwIPHandleIncomingConnection(void * arg, struct tcp_p else { listenEP->Retain(); - err = lSystemLayer->ScheduleLambda([listenEP, err] { + err = lSystemLayer.ScheduleLambda([listenEP, err] { listenEP->HandleError(err); listenEP->Release(); }); @@ -1091,12 +1085,11 @@ err_t TCPEndPointImplLwIP::LwIPHandleDataReceived(void * arg, struct tcp_pcb * t if (arg != NULL) { - TCPEndPointImplLwIP * ep = static_cast(arg); - System::Layer * lSystemLayer = ep->Layer().SystemLayer(); + TCPEndPointImplLwIP * ep = static_cast(arg); // Post callback to HandleDataReceived. ep->Retain(); - CHIP_ERROR err = lSystemLayer->ScheduleLambda([ep, p] { + CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, p] { ep->HandleDataReceived(System::PacketBufferHandle::Adopt(p)); ep->Release(); }); @@ -1127,12 +1120,11 @@ err_t TCPEndPointImplLwIP::LwIPHandleDataSent(void * arg, struct tcp_pcb * tpcb, if (arg != NULL) { - TCPEndPointImplLwIP * ep = static_cast(arg); - System::Layer * lSystemLayer = ep->Layer().SystemLayer(); + TCPEndPointImplLwIP * ep = static_cast(arg); // Post callback to HandleDataReceived. ep->Retain(); - CHIP_ERROR err = lSystemLayer->ScheduleLambda([ep, len] { + CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, len] { ep->HandleDataSent(len); ep->Release(); }); @@ -1156,7 +1148,7 @@ void TCPEndPointImplLwIP::LwIPHandleError(void * arg, err_t lwipErr) if (arg != NULL) { TCPEndPointImplLwIP * ep = static_cast(arg); - System::LayerLwIP * lSystemLayer = static_cast(ep->Layer().SystemLayer()); + System::LayerLwIP & lSystemLayer = static_cast(ep->GetSystemLayer()); // At this point LwIP has already freed the PCB. Since the thread that owns the TCPEndPoint may // try to use the PCB before it receives the TCPError event posted below, we set the PCB to NULL @@ -1168,7 +1160,7 @@ void TCPEndPointImplLwIP::LwIPHandleError(void * arg, err_t lwipErr) // Post callback to HandleError. ep->Retain(); - CHIP_ERROR err = lSystemLayer->ScheduleLambda([ep, conErr = System::MapErrorLwIP(lwipErr)] { + CHIP_ERROR err = lSystemLayer.ScheduleLambda([ep, conErr = System::MapErrorLwIP(lwipErr)] { ep->HandleError(conErr); ep->Release(); }); @@ -1181,8 +1173,6 @@ void TCPEndPointImplLwIP::LwIPHandleError(void * arg, err_t lwipErr) #if CHIP_SYSTEM_CONFIG_USE_SOCKETS -BitMapObjectPool TCPEndPointImplSockets::sPool; - CHIP_ERROR TCPEndPointImplSockets::BindImpl(IPAddressType addrType, const IPAddress & addr, uint16_t port, bool reuseAddr) { CHIP_ERROR res = GetSocket(addrType); @@ -1249,7 +1239,7 @@ CHIP_ERROR TCPEndPointImplSockets::BindImpl(IPAddressType addrType, const IPAddr } #if CHIP_SYSTEM_CONFIG_USE_DISPATCH - dispatch_queue_t dispatchQueue = static_cast(Layer().SystemLayer())->GetDispatchQueue(); + dispatch_queue_t dispatchQueue = static_cast(GetSystemLayer()).GetDispatchQueue(); if (dispatchQueue != nullptr) { unsigned long fd = static_cast(mSocket); @@ -1287,11 +1277,11 @@ CHIP_ERROR TCPEndPointImplSockets::ListenImpl(uint16_t backlog) fcntl(mSocket, F_SETFL, flags | O_NONBLOCK); // Wait for ability to read on this endpoint. - CHIP_ERROR res = static_cast(Layer().SystemLayer()) - ->SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this)); + CHIP_ERROR res = static_cast(GetSystemLayer()) + .SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this)); if (res == CHIP_NO_ERROR) { - res = static_cast(Layer().SystemLayer())->RequestCallbackOnPendingRead(mWatch); + res = static_cast(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch); } return res; @@ -1398,8 +1388,8 @@ CHIP_ERROR TCPEndPointImplSockets::ConnectImpl(const IPAddress & addr, uint16_t return res; } - ReturnErrorOnFailure(static_cast(Layer().SystemLayer()) - ->SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this))); + ReturnErrorOnFailure(static_cast(GetSystemLayer()) + .SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this))); // Once Connecting or Connected, bump the reference count. The corresponding Release() will happen in DoClose(). Retain(); @@ -1408,7 +1398,7 @@ CHIP_ERROR TCPEndPointImplSockets::ConnectImpl(const IPAddress & addr, uint16_t { mState = State::kConnected; // Wait for ability to read on this endpoint. - ReturnErrorOnFailure(static_cast(Layer().SystemLayer())->RequestCallbackOnPendingRead(mWatch)); + ReturnErrorOnFailure(static_cast(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch)); if (OnConnectComplete != nullptr) { OnConnectComplete(this, CHIP_NO_ERROR); @@ -1418,7 +1408,7 @@ CHIP_ERROR TCPEndPointImplSockets::ConnectImpl(const IPAddress & addr, uint16_t { mState = State::kConnecting; // Wait for ability to write on this endpoint. - ReturnErrorOnFailure(static_cast(Layer().SystemLayer())->RequestCallbackOnPendingWrite(mWatch)); + ReturnErrorOnFailure(static_cast(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch)); } return CHIP_NO_ERROR; @@ -1512,7 +1502,7 @@ CHIP_ERROR TCPEndPointImplSockets::SendQueuedImpl(bool queueWasEmpty) if (queueWasEmpty) { // Wait for ability to write on this endpoint. - return static_cast(Layer().SystemLayer())->RequestCallbackOnPendingWrite(mWatch); + return static_cast(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch); } return CHIP_NO_ERROR; } @@ -1659,7 +1649,7 @@ CHIP_ERROR TCPEndPointImplSockets::DriveSendingImpl() if (mSendQueue.IsNull()) { // Do not wait for ability to write on this endpoint. - err = static_cast(Layer().SystemLayer())->ClearCallbackOnPendingWrite(mWatch); + err = static_cast(GetSystemLayer()).ClearCallbackOnPendingWrite(mWatch); if (err != CHIP_NO_ERROR) { break; @@ -1729,10 +1719,10 @@ CHIP_ERROR TCPEndPointImplSockets::DriveSendingImpl() void TCPEndPointImplSockets::HandleConnectCompleteImpl() { // Wait for ability to read or write on this endpoint. - CHIP_ERROR err = static_cast(Layer().SystemLayer())->RequestCallbackOnPendingRead(mWatch); + CHIP_ERROR err = static_cast(GetSystemLayer()).RequestCallbackOnPendingRead(mWatch); if (err == CHIP_NO_ERROR) { - err = static_cast(Layer().SystemLayer())->RequestCallbackOnPendingWrite(mWatch); + err = static_cast(GetSystemLayer()).RequestCallbackOnPendingWrite(mWatch); } if (err != CHIP_NO_ERROR) { @@ -1765,7 +1755,7 @@ void TCPEndPointImplSockets::DoCloseImpl(CHIP_ERROR err, State oldState) } } - static_cast(Layer().SystemLayer())->StopWatchingSocket(&mWatch); + static_cast(GetSystemLayer()).StopWatchingSocket(&mWatch); close(mSocket); mSocket = kInvalidSocketFd; } @@ -1930,7 +1920,7 @@ CHIP_ERROR TCPEndPointImplSockets::GetSocket(IPAddressType addrType) { return CHIP_ERROR_POSIX(errno); } - ReturnErrorOnFailure(static_cast(Layer().SystemLayer())->StartWatchingSocket(mSocket, &mWatch)); + ReturnErrorOnFailure(static_cast(GetSystemLayer()).StartWatchingSocket(mSocket, &mWatch)); mAddrType = addrType; // If creating an IPv6 socket, tell the kernel that it will be IPv6 only. This makes it @@ -2138,7 +2128,7 @@ void TCPEndPointImplSockets::ReceiveData() mState = State::kClosing; } // Do not wait for ability to read on this endpoint. - (void) static_cast(Layer().SystemLayer())->ClearCallbackOnPendingRead(mWatch); + (void) static_cast(GetSystemLayer()).ClearCallbackOnPendingRead(mWatch); // Call the app's OnPeerClose. if (OnPeerClose != nullptr) { @@ -2231,10 +2221,8 @@ void TCPEndPointImplSockets::HandleIncomingConnection() // Attempt to allocate an end point object. if (err == CHIP_NO_ERROR) { - InetLayer & lInetLayer = Layer(); - TCPEndPoint * connectEndPoint = nullptr; - err = lInetLayer.NewTCPEndPoint(&connectEndPoint); + err = GetEndPointManager().NewEndPoint(&connectEndPoint); conEP = static_cast(connectEndPoint); } @@ -2243,7 +2231,7 @@ void TCPEndPointImplSockets::HandleIncomingConnection() { // Put the new end point into the Connected state. conEP->mSocket = conSocket; - err = static_cast(Layer().SystemLayer())->StartWatchingSocket(conSocket, &conEP->mWatch); + err = static_cast(GetSystemLayer()).StartWatchingSocket(conSocket, &conEP->mWatch); if (err == CHIP_NO_ERROR) { conEP->mState = State::kConnected; @@ -2255,11 +2243,11 @@ void TCPEndPointImplSockets::HandleIncomingConnection() conEP->Retain(); // Wait for ability to read on this endpoint. - auto conEPLayer = static_cast(conEP->Layer().SystemLayer()); - err = conEPLayer->SetCallback(conEP->mWatch, HandlePendingIO, reinterpret_cast(conEP)); + auto & conEPLayer = static_cast(conEP->GetSystemLayer()); + err = conEPLayer.SetCallback(conEP->mWatch, HandlePendingIO, reinterpret_cast(conEP)); if (err == CHIP_NO_ERROR) { - err = conEPLayer->RequestCallbackOnPendingRead(conEP->mWatch); + err = conEPLayer.RequestCallbackOnPendingRead(conEP->mWatch); } if (err == CHIP_NO_ERROR) { @@ -2513,8 +2501,7 @@ void TCPEndPoint::Free() void TCPEndPoint::SetIdleTimeout(uint32_t timeoutMS) { uint32_t newIdleTimeout = (timeoutMS + (INET_TCP_IDLE_CHECK_INTERVAL - 1)) / INET_TCP_IDLE_CHECK_INTERVAL; - InetLayer & lInetLayer = Layer(); - bool isIdleTimerRunning = lInetLayer.IsIdleTimerRunning(); + bool isIdleTimerRunning = IsIdleTimerRunning(GetEndPointManager()); if (newIdleTimeout > UINT16_MAX) { @@ -2524,10 +2511,48 @@ void TCPEndPoint::SetIdleTimeout(uint32_t timeoutMS) if (!isIdleTimerRunning && mIdleTimeout) { - Layer().SystemLayer()->StartTimer(System::Clock::Milliseconds32(INET_TCP_IDLE_CHECK_INTERVAL), - InetLayer::HandleTCPInactivityTimer, &lInetLayer); + GetSystemLayer().StartTimer(System::Clock::Milliseconds32(INET_TCP_IDLE_CHECK_INTERVAL), HandleIdleTimer, + &GetEndPointManager()); } } + +// static +void TCPEndPoint::HandleIdleTimer(chip::System::Layer * aSystemLayer, void * aAppState) +{ + auto & endPointManager = *reinterpret_cast *>(aAppState); + bool lTimerRequired = IsIdleTimerRunning(endPointManager); + + endPointManager.ForEachEndPoint([](TCPEndPoint * lEndPoint) -> bool { + if (!lEndPoint->IsConnected()) + return true; + if (lEndPoint->mIdleTimeout == 0) + return true; + + if (lEndPoint->mRemainingIdleTime == 0) + { + lEndPoint->DoClose(INET_ERROR_IDLE_TIMEOUT, false); + } + else + { + --lEndPoint->mRemainingIdleTime; + } + + return true; + }); + + if (lTimerRequired) + { + aSystemLayer->StartTimer(System::Clock::Milliseconds32(INET_TCP_IDLE_CHECK_INTERVAL), HandleIdleTimer, &endPointManager); + } +} + +// static +bool TCPEndPoint::IsIdleTimerRunning(EndPointManager & endPointManager) +{ + // See if there are any TCP connections with the idle timer check in use. + return !endPointManager.ForEachEndPoint([](TCPEndPoint * lEndPoint) { return (lEndPoint->mIdleTimeout == 0); }); +} + #endif // INET_TCP_IDLE_CHECK_INTERVAL > 0 CHIP_ERROR TCPEndPoint::SetUserTimeout(uint32_t userTimeoutMillis) @@ -2553,13 +2578,13 @@ void TCPEndPoint::StartConnectTimerIfSet() { if (mConnectTimeoutMsecs > 0) { - Layer().SystemLayer()->StartTimer(System::Clock::Milliseconds32(mConnectTimeoutMsecs), TCPConnectTimeoutHandler, this); + GetSystemLayer().StartTimer(System::Clock::Milliseconds32(mConnectTimeoutMsecs), TCPConnectTimeoutHandler, this); } } void TCPEndPoint::StopConnectTimer() { - Layer().SystemLayer()->CancelTimer(TCPConnectTimeoutHandler, this); + GetSystemLayer().CancelTimer(TCPConnectTimeoutHandler, this); } void TCPEndPoint::TCPConnectTimeoutHandler(chip::System::Layer * aSystemLayer, void * aAppState) @@ -2721,7 +2746,7 @@ CHIP_ERROR TCPEndPoint::DoClose(CHIP_ERROR err, bool suppressCallback) void TCPEndPoint::ScheduleNextTCPUserTimeoutPoll(uint32_t aTimeOut) { - Layer().SystemLayer()->StartTimer(System::Clock::Milliseconds32(aTimeOut), TCPUserTimeoutHandler, this); + GetSystemLayer().StartTimer(System::Clock::Milliseconds32(aTimeOut), TCPUserTimeoutHandler, this); } #if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS @@ -2763,7 +2788,7 @@ void TCPEndPoint::StartTCPUserTimeoutTimer() void TCPEndPoint::StopTCPUserTimeoutTimer() { - Layer().SystemLayer()->CancelTimer(TCPUserTimeoutHandler, this); + GetSystemLayer().CancelTimer(TCPUserTimeoutHandler, this); mUserTimeoutTimerRunning = false; } diff --git a/src/inet/TCPEndPoint.h b/src/inet/TCPEndPoint.h index a15b6cf7f7c1d5..31ee56f1521009 100644 --- a/src/inet/TCPEndPoint.h +++ b/src/inet/TCPEndPoint.h @@ -30,8 +30,7 @@ #include #include #include -#include -#include +#include #include #include @@ -56,16 +55,8 @@ class TCPTest; namespace Inet { -class InetLayer; class TCPTest; -class TCPEndPoint; -class TCPEndPointDeletor -{ -public: - static void Release(TCPEndPoint * obj); -}; - /** * @brief Objects of this class represent TCP transport endpoints. * @@ -74,28 +65,9 @@ class TCPEndPointDeletor * endpoints (SOCK_STREAM sockets on Linux and BSD-derived systems) or LwIP * TCP protocol control blocks, as the system is configured accordingly. */ -class DLL_EXPORT TCPEndPoint : public EndPointBase, public ReferenceCounted +class DLL_EXPORT TCPEndPoint : public EndPointBasis { public: - TCPEndPoint(InetLayer & inetLayer, void * appState = nullptr) : - EndPointBase(inetLayer, appState), OnConnectComplete(nullptr), OnDataReceived(nullptr), OnDataSent(nullptr), - OnConnectionClosed(nullptr), OnPeerClose(nullptr), OnConnectionReceived(nullptr), OnAcceptError(nullptr), - mState(State::kReady), mReceiveEnabled(true), mConnectTimeoutMsecs(0) // Initialize to zero for using system defaults. -#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - , - mUserTimeoutMillis(INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC), mUserTimeoutTimerRunning(false) -#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS - , - mIsTCPSendIdle(true), mTCPSendQueuePollPeriodMillis(INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC), - mTCPSendQueueRemainingPollCount( - MaxTCPSendQueuePolls(INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC, INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC)), - OnTCPSendIdleChanged(nullptr) -#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS -#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT - {} - - virtual ~TCPEndPoint() = default; - /** * @brief Bind the endpoint to an interface IP address. * @@ -600,10 +572,28 @@ class DLL_EXPORT TCPEndPoint : public EndPointBase, public ReferenceCounted & endPointManager) : + EndPointBasis(endPointManager), OnConnectComplete(nullptr), OnDataReceived(nullptr), OnDataSent(nullptr), + OnConnectionClosed(nullptr), OnPeerClose(nullptr), OnConnectionReceived(nullptr), OnAcceptError(nullptr), + mState(State::kReady), mReceiveEnabled(true), mConnectTimeoutMsecs(0) // Initialize to zero for using system defaults. +#if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT + , + mUserTimeoutMillis(INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC), mUserTimeoutTimerRunning(false) +#if INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS + , + mIsTCPSendIdle(true), mTCPSendQueuePollPeriodMillis(INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC), + mTCPSendQueueRemainingPollCount( + MaxTCPSendQueuePolls(INET_CONFIG_DEFAULT_TCP_USER_TIMEOUT_MSEC, INET_CONFIG_TCP_SEND_QUEUE_POLL_INTERVAL_MSEC)), + OnTCPSendIdleChanged(nullptr) +#endif // INET_CONFIG_ENABLE_TCP_SEND_IDLE_CALLBACKS +#endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT + {} + + virtual ~TCPEndPoint() = default; + /** * Basic dynamic state of the underlying endpoint. * @@ -630,6 +620,8 @@ class DLL_EXPORT TCPEndPoint : public EndPointBase, public ReferenceCounted 0 + static void HandleIdleTimer(System::Layer * aSystemLayer, void * aAppState); + static bool IsIdleTimerRunning(EndPointManager & endPointManager); uint16_t mIdleTimeout; // in units of INET_TCP_IDLE_CHECK_INTERVAL; zero means no timeout uint16_t mRemainingIdleTime; // in units of INET_TCP_IDLE_CHECK_INTERVAL #endif // INET_TCP_IDLE_CHECK_INTERVAL > 0 @@ -693,7 +685,6 @@ class DLL_EXPORT TCPEndPoint : public EndPointBase, public ReferenceCountedDelete(); -} - #if CHIP_SYSTEM_CONFIG_USE_LWIP class TCPEndPointImplLwIP : public TCPEndPoint, public EndPointStateLwIP { public: - TCPEndPointImplLwIP(InetLayer & inetLayer, void * appState = nullptr) : TCPEndPoint(inetLayer, appState), mUnackedLength(0) {} + TCPEndPointImplLwIP(EndPointManager & endPointManager) : TCPEndPoint(endPointManager), mUnackedLength(0) {} // TCPEndPoint overrides. CHIP_ERROR GetPeerInfo(IPAddress * retAddr, uint16_t * retPort) const override; @@ -733,11 +719,6 @@ class TCPEndPointImplLwIP : public TCPEndPoint, public EndPointStateLwIP #endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT private: - friend class InetLayer; - friend class BitMapObjectPool; - static BitMapObjectPool sPool; - void Delete() override { sPool.ReleaseObject(this); } - // TCPEndPoint overrides. CHIP_ERROR BindImpl(IPAddressType addrType, const IPAddress & addr, uint16_t port, bool reuseAddr) override; CHIP_ERROR ListenImpl(uint16_t backlog) override; @@ -787,8 +768,8 @@ using TCPEndPointImpl = TCPEndPointImplLwIP; class TCPEndPointImplSockets : public TCPEndPoint, public EndPointStateSockets { public: - TCPEndPointImplSockets(InetLayer & inetLayer, void * appState = nullptr) : - TCPEndPoint(inetLayer, appState) + TCPEndPointImplSockets(EndPointManager & endPointManager) : + TCPEndPoint(endPointManager) #if INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT , mBytesWrittenSinceLastProbe(0), mLastTCPKernelSendQueueLen(0) @@ -808,11 +789,6 @@ class TCPEndPointImplSockets : public TCPEndPoint, public EndPointStateSockets #endif // INET_CONFIG_OVERRIDE_SYSTEM_TCP_USER_TIMEOUT private: - friend class InetLayer; - friend class BitMapObjectPool; - static BitMapObjectPool sPool; - void Delete() override { sPool.ReleaseObject(this); } - // TCPEndPoint overrides. CHIP_ERROR BindImpl(IPAddressType addrType, const IPAddress & addr, uint16_t port, bool reuseAddr) override; CHIP_ERROR ListenImpl(uint16_t backlog) override; @@ -851,5 +827,14 @@ using TCPEndPointImpl = TCPEndPointImplSockets; #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS +using TCPEndPointManagerImpl = EndPointManagerImplPool; + +template <> +struct EndPointProperties +{ + static constexpr const char * Name = "TCP"; + static constexpr int SystemStatsKey = System::Stats::kInetLayer_NumTCPEps; +}; + } // namespace Inet } // namespace chip diff --git a/src/inet/UDPEndPoint.cpp b/src/inet/UDPEndPoint.cpp index b1d3c8416c5dcf..27d94189f2647e 100644 --- a/src/inet/UDPEndPoint.cpp +++ b/src/inet/UDPEndPoint.cpp @@ -30,8 +30,8 @@ #define __APPLE_USE_RFC_3542 #include +#include #include -#include #include #include #include @@ -147,8 +147,6 @@ CHIP_ERROR CheckMulticastGroupArgs(InterfaceId aInterfaceId, const IPAddress & a #if CHIP_SYSTEM_CONFIG_USE_LWIP -BitMapObjectPool UDPEndPointImplLwIP::sPool; - CHIP_ERROR UDPEndPointImplLwIP::BindImpl(IPAddressType addressType, const IPAddress & address, uint16_t port, InterfaceId interfaceId) { @@ -539,7 +537,6 @@ void UDPEndPointImplLwIP::LwIPReceiveUDPMessage(void * arg, struct udp_pcb * pcb #endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5 { UDPEndPointImplLwIP * ep = static_cast(arg); - System::Layer * lSystemLayer = ep->Layer().SystemLayer(); IPPacketInfo * pktInfo = nullptr; System::PacketBufferHandle buf = System::PacketBufferHandle::Adopt(p); if (buf->HasChainedBuffer()) @@ -588,7 +585,7 @@ void UDPEndPointImplLwIP::LwIPReceiveUDPMessage(void * arg, struct udp_pcb * pcb } ep->Retain(); - CHIP_ERROR err = lSystemLayer->ScheduleLambda([ep, p = System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(buf)] { + CHIP_ERROR err = ep->GetSystemLayer().ScheduleLambda([ep, p = System::LwIPPacketBufferView::UnsafeGetLwIPpbuf(buf)] { ep->HandleDataReceived(System::PacketBufferHandle::Adopt(p)); ep->Release(); }); @@ -703,8 +700,6 @@ IPPacketInfo * UDPEndPointImplLwIP::GetPacketInfo(const System::PacketBufferHand #if CHIP_SYSTEM_CONFIG_USE_SOCKETS -BitMapObjectPool UDPEndPointImplSockets::sPool; - namespace { CHIP_ERROR IPv6Bind(int socket, const IPAddress & address, uint16_t port, InterfaceId interface) @@ -833,7 +828,7 @@ CHIP_ERROR UDPEndPointImplSockets::BindImpl(IPAddressType addressType, const IPA } #if CHIP_SYSTEM_CONFIG_USE_DISPATCH - dispatch_queue_t dispatchQueue = static_cast(Layer().SystemLayer())->GetDispatchQueue(); + dispatch_queue_t dispatchQueue = static_cast(&GetSystemLayer())->GetDispatchQueue(); if (dispatchQueue != nullptr) { unsigned long fd = static_cast(mSocket); @@ -905,7 +900,7 @@ uint16_t UDPEndPointImplSockets::GetBoundPort() const CHIP_ERROR UDPEndPointImplSockets::ListenImpl() { // Wait for ability to read on this endpoint. - auto * layer = static_cast(Layer().SystemLayer()); + auto * layer = static_cast(&GetSystemLayer()); ReturnErrorOnFailure(layer->SetCallback(mWatch, HandlePendingIO, reinterpret_cast(this))); return layer->RequestCallbackOnPendingRead(mWatch); } @@ -1054,7 +1049,7 @@ void UDPEndPointImplSockets::CloseImpl() { if (mSocket != kInvalidSocketFd) { - static_cast(Layer().SystemLayer())->StopWatchingSocket(&mWatch); + static_cast(&GetSystemLayer())->StopWatchingSocket(&mWatch); close(mSocket); mSocket = kInvalidSocketFd; } @@ -1104,7 +1099,7 @@ CHIP_ERROR UDPEndPointImplSockets::GetSocket(IPAddressType addressType) { return CHIP_ERROR_POSIX(errno); } - ReturnErrorOnFailure(static_cast(Layer().SystemLayer())->StartWatchingSocket(mSocket, &mWatch)); + ReturnErrorOnFailure(static_cast(&GetSystemLayer())->StartWatchingSocket(mSocket, &mWatch)); mAddrType = addressType; @@ -1449,8 +1444,6 @@ CHIP_ERROR UDPEndPointImplSockets::IPv6JoinLeaveMulticastGroupImpl(InterfaceId a #if CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK -BitMapObjectPool UDPEndPointImplNetworkFramework::sPool; - CHIP_ERROR UDPEndPointImplNetworkFramework::BindImpl(IPAddressType addressType, const IPAddress & address, uint16_t port, InterfaceId intfId) { diff --git a/src/inet/UDPEndPoint.h b/src/inet/UDPEndPoint.h index 97da7807b52a97..71ef054da488c2 100644 --- a/src/inet/UDPEndPoint.h +++ b/src/inet/UDPEndPoint.h @@ -30,8 +30,9 @@ #include #include +#include #include -#include +#include #include #include @@ -52,16 +53,6 @@ namespace chip { namespace Inet { -class InetLayer; -class IPPacketInfo; - -class UDPEndPoint; -class UDPEndPointDeletor -{ -public: - static void Release(UDPEndPoint * obj); -}; - /** * @brief Objects of this class represent UDP transport endpoints. * @@ -70,20 +61,14 @@ class UDPEndPointDeletor * endpoints (SOCK_DGRAM sockets on Linux and BSD-derived systems) or LwIP * UDP protocol control blocks, as the system is configured accordingly. */ -class DLL_EXPORT UDPEndPoint : public EndPointBase, public ReferenceCounted +class DLL_EXPORT UDPEndPoint : public EndPointBasis { public: - UDPEndPoint(InetLayer & inetLayer, void * appState = nullptr) : - EndPointBase(inetLayer, appState), mState(State::kReady), OnMessageReceived(nullptr), OnReceiveError(nullptr) - {} - UDPEndPoint(const UDPEndPoint &) = delete; UDPEndPoint(UDPEndPoint &&) = delete; UDPEndPoint & operator=(const UDPEndPoint &) = delete; UDPEndPoint & operator=(UDPEndPoint &&) = delete; - virtual ~UDPEndPoint() = default; - /** * Type of message text reception event handling function. * @@ -274,6 +259,12 @@ class DLL_EXPORT UDPEndPoint : public EndPointBase, public ReferenceCounted & endPointManager) : + EndPointBasis(endPointManager), mState(State::kReady), OnMessageReceived(nullptr), OnReceiveError(nullptr) + {} + + virtual ~UDPEndPoint() = default; + /** * Basic dynamic state of the underlying endpoint. * @@ -296,9 +287,6 @@ class DLL_EXPORT UDPEndPoint : public EndPointBase, public ReferenceCountedDelete(); -} - #if CHIP_SYSTEM_CONFIG_USE_LWIP class UDPEndPointImplLwIP : public UDPEndPoint, public EndPointStateLwIP { public: - UDPEndPointImplLwIP(InetLayer & inetLayer, void * appState = nullptr) : UDPEndPoint(inetLayer, appState) {} + UDPEndPointImplLwIP(EndPointManager & endPointManager) : UDPEndPoint(endPointManager) {} // UDPEndPoint overrides. CHIP_ERROR SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) override; @@ -333,11 +316,6 @@ class UDPEndPointImplLwIP : public UDPEndPoint, public EndPointStateLwIP void Free() override; private: - friend class InetLayer; - friend class BitMapObjectPool; - static BitMapObjectPool sPool; - void Delete() override { sPool.ReleaseObject(this); } - // UDPEndPoint overrides. #if INET_CONFIG_ENABLE_IPV4 CHIP_ERROR IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join) override; @@ -392,8 +370,8 @@ using UDPEndPointImpl = UDPEndPointImplLwIP; class UDPEndPointImplSockets : public UDPEndPoint, public EndPointStateSockets { public: - UDPEndPointImplSockets(InetLayer & inetLayer, void * appState = nullptr) : - UDPEndPoint(inetLayer, appState), mBoundIntfId(InterfaceId::Null()) + UDPEndPointImplSockets(EndPointManager & endPointManager) : + UDPEndPoint(endPointManager), mBoundIntfId(InterfaceId::Null()) {} // UDPEndPoint overrides. @@ -403,11 +381,6 @@ class UDPEndPointImplSockets : public UDPEndPoint, public EndPointStateSockets void Free() override; private: - friend class InetLayer; - friend class BitMapObjectPool; - static BitMapObjectPool sPool; - void Delete() override { sPool.ReleaseObject(this); } - // UDPEndPoint overrides. #if INET_CONFIG_ENABLE_IPV4 CHIP_ERROR IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join) override; @@ -451,7 +424,7 @@ using UDPEndPointImpl = UDPEndPointImplSockets; class UDPEndPointImplNetworkFramework : public UDPEndPoint, public EndPointStateNetworkFramework { public: - UDPEndPointImplNetworkFramework(InetLayer & inetLayer, void * appState = nullptr) : UDPEndPoint(inetLayer, appState) {} + UDPEndPointImplNetworkFramework(EndPointManager & endPointManager) : UDPEndPoint(endPointManager) {} // UDPEndPoint overrides. CHIP_ERROR SetMulticastLoopback(IPVersion aIPVersion, bool aLoopback) override; @@ -460,11 +433,6 @@ class UDPEndPointImplNetworkFramework : public UDPEndPoint, public EndPointState void Free() override; private: - friend class InetLayer; - friend class BitMapObjectPool; - static BitMapObjectPool sPool; - void Delete() override { sPool.ReleaseObject(this); } - // UDPEndPoint overrides. #if INET_CONFIG_ENABLE_IPV4 CHIP_ERROR IPv4JoinLeaveMulticastGroupImpl(InterfaceId aInterfaceId, const IPAddress & aAddress, bool join) override; @@ -500,5 +468,14 @@ using UDPEndPointImpl = UDPEndPointImplNetworkFramework; #endif // CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK +using UDPEndPointManagerImpl = EndPointManagerImplPool; + +template <> +struct EndPointProperties +{ + static constexpr const char * Name = "UDP"; + static constexpr int SystemStatsKey = System::Stats::kInetLayer_NumUDPEps; +}; + } // namespace Inet } // namespace chip diff --git a/src/inet/tests/TestInetCommon.h b/src/inet/tests/TestInetCommon.h index 271cad28b8c0b9..e920fdb73de5e0 100644 --- a/src/inet/tests/TestInetCommon.h +++ b/src/inet/tests/TestInetCommon.h @@ -40,6 +40,8 @@ #include #include +#include +#include #include #include diff --git a/src/inet/tests/TestInetCommonPosix.cpp b/src/inet/tests/TestInetCommonPosix.cpp index 27b1555e1149df..fa32cd780e31e5 100644 --- a/src/inet/tests/TestInetCommonPosix.cpp +++ b/src/inet/tests/TestInetCommonPosix.cpp @@ -81,6 +81,8 @@ using namespace chip::Inet; System::LayerImpl gSystemLayer; Inet::InetLayer gInet; +Inet::UDPEndPointManagerImpl gUDP; +Inet::TCPEndPointManagerImpl gTCP; #if CHIP_SYSTEM_CONFIG_USE_LWIP static sys_mbox_t * sLwIPEventQueue = NULL; @@ -220,8 +222,6 @@ static void PrintNetworkState() void InitNetwork() { - void * lContext = nullptr; - #if CHIP_SYSTEM_CONFIG_USE_LWIP // If an tap device name hasn't been specified, derive one from the IPv6 interface id. @@ -417,11 +417,11 @@ void InitNetwork() PrintNetworkState(); AcquireLwIP(); - lContext = sLwIPEventQueue; #endif // CHIP_SYSTEM_CONFIG_USE_LWIP - gInet.Init(gSystemLayer, lContext); + gInet.Init(gSystemLayer, &gUDP); + gInet.InitTCP(&gTCP); } void ServiceEvents(uint32_t aSleepTimeMilliseconds) @@ -504,6 +504,7 @@ static void OnLwIPInitComplete(void * arg) void ShutdownNetwork() { + gInet.ShutdownTCP(); gInet.Shutdown(); #if CHIP_SYSTEM_CONFIG_USE_LWIP ReleaseLwIP(); diff --git a/src/inet/tests/TestInetEndPoint.cpp b/src/inet/tests/TestInetEndPoint.cpp index b3248d7f488db2..4af7590d883253 100644 --- a/src/inet/tests/TestInetEndPoint.cpp +++ b/src/inet/tests/TestInetEndPoint.cpp @@ -35,6 +35,7 @@ #include +#include #include #include @@ -81,12 +82,6 @@ void HandleTimer(Layer * aLayer, void * aAppState) // Test before init network, Inet is not initialized static void TestInetPre(nlTestSuite * inSuite, void * inContext) { -#if INET_CONFIG_ENABLE_UDP_ENDPOINT - UDPEndPoint * testUDPEP = nullptr; -#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT -#if INET_CONFIG_ENABLE_TCP_ENDPOINT - TCPEndPoint * testTCPEP = nullptr; -#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT CHIP_ERROR err = CHIP_NO_ERROR; // Deinit system layer and network @@ -97,13 +92,13 @@ static void TestInetPre(nlTestSuite * inSuite, void * inContext) } #if INET_CONFIG_ENABLE_UDP_ENDPOINT - err = gInet.NewUDPEndPoint(&testUDPEP); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE); + EndPointManager * udpEndPointManager = gInet.GetUDPEndPointManager(); + NL_TEST_ASSERT(inSuite, udpEndPointManager == nullptr); #endif // INET_CONFIG_ENABLE_UDP_ENDPOINT #if INET_CONFIG_ENABLE_TCP_ENDPOINT - err = gInet.NewTCPEndPoint(&testTCPEP); - NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE); + EndPointManager * tcpEndPointManager = gInet.GetTCPEndPointManager(); + NL_TEST_ASSERT(inSuite, tcpEndPointManager == nullptr); #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT err = gSystemLayer.StartTimer(10_ms32, HandleTimer, nullptr); @@ -226,10 +221,10 @@ static void TestInetEndPointInternal(nlTestSuite * inSuite, void * inContext) PacketBufferHandle buf = PacketBufferHandle::New(PacketBuffer::kMaxSize); // init all the EndPoints - err = gInet.NewUDPEndPoint(&testUDPEP); + err = gInet.GetUDPEndPointManager()->NewEndPoint(&testUDPEP); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = gInet.NewTCPEndPoint(&testTCPEP1); + err = gInet.GetTCPEndPointManager()->NewEndPoint(&testTCPEP1); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); err = InterfaceId::Null().GetLinkLocalAddr(&addr); @@ -266,7 +261,7 @@ static void TestInetEndPointInternal(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE); testUDPEP->Free(); - err = gInet.NewUDPEndPoint(&testUDPEP); + err = gInet.GetUDPEndPointManager()->NewEndPoint(&testUDPEP); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); #if INET_CONFIG_ENABLE_IPV4 err = testUDPEP->Bind(IPAddressType::kIPv4, addr_v4, 3000, intId); @@ -326,12 +321,12 @@ static void TestInetEndPointLimit(nlTestSuite * inSuite, void * inContext) // TODO: err is not validated EXCEPT the last call for (int i = 0; i < INET_CONFIG_NUM_UDP_ENDPOINTS + 1; i++) - err = gInet.NewUDPEndPoint(&testUDPEP[i]); + err = gInet.GetUDPEndPointManager()->NewEndPoint(&testUDPEP[i]); NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_ENDPOINT_POOL_FULL); // TODO: err is not validated EXCEPT the last call for (int i = 0; i < INET_CONFIG_NUM_TCP_ENDPOINTS + 1; i++) - err = gInet.NewTCPEndPoint(&testTCPEP[i]); + err = gInet.GetTCPEndPointManager()->NewEndPoint(&testTCPEP[i]); NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_ENDPOINT_POOL_FULL); // Verify same aComplete and aAppState args do not exhaust timer pool diff --git a/src/inet/tests/TestInetLayer.cpp b/src/inet/tests/TestInetLayer.cpp index c57a2ee11f8e5a..9b295e70f9de38 100644 --- a/src/inet/tests/TestInetLayer.cpp +++ b/src/inet/tests/TestInetLayer.cpp @@ -692,8 +692,8 @@ static CHIP_ERROR PrepareTransportForSend() { if (sTCPIPEndPoint == nullptr) { - lStatus = gInet.NewTCPEndPoint(&sTCPIPEndPoint); - INET_FAIL_ERROR(lStatus, "InetLayer::NewTCPEndPoint failed"); + lStatus = gInet.GetTCPEndPointManager()->NewEndPoint(&sTCPIPEndPoint); + INET_FAIL_ERROR(lStatus, "InetLayer::GetTCPEndPointManager()->NewEndPoint failed"); sTCPIPEndPoint->OnConnectComplete = HandleTCPConnectionComplete; sTCPIPEndPoint->OnConnectionClosed = HandleTCPConnectionClosed; @@ -820,8 +820,8 @@ static void StartTest() if (gOptFlags & kOptFlagUseUDPIP) { - lStatus = gInet.NewUDPEndPoint(&sUDPIPEndPoint); - INET_FAIL_ERROR(lStatus, "InetLayer::NewUDPEndPoint failed"); + lStatus = gInet.GetUDPEndPointManager()->NewEndPoint(&sUDPIPEndPoint); + INET_FAIL_ERROR(lStatus, "InetLayer::GetUDPEndPointManager()->NewEndPoint failed"); if (gInterfaceId.IsPresent()) { @@ -845,8 +845,8 @@ static void StartTest() const uint16_t lConnectionBacklogMax = 1; const bool lReuseAddress = true; - lStatus = gInet.NewTCPEndPoint(&sTCPIPListenEndPoint); - INET_FAIL_ERROR(lStatus, "InetLayer::NewTCPEndPoint failed"); + lStatus = gInet.GetTCPEndPointManager()->NewEndPoint(&sTCPIPListenEndPoint); + INET_FAIL_ERROR(lStatus, "InetLayer::GetTCPEndPointManager()->NewEndPoint failed"); sTCPIPListenEndPoint->OnConnectionReceived = HandleTCPConnectionReceived; sTCPIPListenEndPoint->OnAcceptError = HandleTCPAcceptError; diff --git a/src/inet/tests/TestInetLayerCommon.cpp b/src/inet/tests/TestInetLayerCommon.cpp index a81916dfc60829..516f57a839a5ab 100644 --- a/src/inet/tests/TestInetLayerCommon.cpp +++ b/src/inet/tests/TestInetLayerCommon.cpp @@ -33,6 +33,7 @@ #include +#include #include #include diff --git a/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp b/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp index 739894d3a55e5f..011f8739ea4ccd 100644 --- a/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp +++ b/src/lib/dnssd/Resolver_ImplMinimalMdns.cpp @@ -20,6 +20,7 @@ #include +#include #include #include #include diff --git a/src/lib/dnssd/minimal_mdns/Server.cpp b/src/lib/dnssd/minimal_mdns/Server.cpp index 9bfb9d15c0ebb3..792c677582a2fc 100644 --- a/src/lib/dnssd/minimal_mdns/Server.cpp +++ b/src/lib/dnssd/minimal_mdns/Server.cpp @@ -242,7 +242,7 @@ CHIP_ERROR ServerBase::Listen(chip::Inet::InetLayer * inetLayer, ListenIterator info->addressType = addressType; info->interfaceId = interfaceId; - ReturnErrorOnFailure(inetLayer->NewUDPEndPoint(&info->listen_udp)); + ReturnErrorOnFailure(inetLayer->GetUDPEndPointManager()->NewEndPoint(&info->listen_udp)); ReturnErrorOnFailure(info->listen_udp->Bind(addressType, chip::Inet::IPAddress::Any, port, interfaceId)); @@ -269,7 +269,7 @@ CHIP_ERROR ServerBase::Listen(chip::Inet::InetLayer * inetLayer, ListenIterator // - helps in not having conflicts on port 5353, will receive unicast replies directly // - has a *DRAWBACK* of unicast queries being considered LEGACY by mdns since they do // not originate from 5353 and the answers will include a query section. - ReturnErrorOnFailure(inetLayer->NewUDPEndPoint(&info->unicast_query_udp)); + ReturnErrorOnFailure(inetLayer->GetUDPEndPointManager()->NewEndPoint(&info->unicast_query_udp)); ReturnErrorOnFailure(info->unicast_query_udp->Bind(addressType, chip::Inet::IPAddress::Any, 0, interfaceId)); ReturnErrorOnFailure(info->unicast_query_udp->Listen(OnUdpPacketReceived, nullptr /*OnReceiveError*/, this)); #endif diff --git a/src/lib/dnssd/minimal_mdns/responders/Responder.h b/src/lib/dnssd/minimal_mdns/responders/Responder.h index d62c53e6bf4796..04c7ca1537dfdb 100644 --- a/src/lib/dnssd/minimal_mdns/responders/Responder.h +++ b/src/lib/dnssd/minimal_mdns/responders/Responder.h @@ -20,7 +20,7 @@ #include #include -#include +#include namespace mdns { namespace Minimal { diff --git a/src/lib/support/ObjectLifeCycle.h b/src/lib/support/ObjectLifeCycle.h index b2a8f2ff85558b..a9f5f370e8dd92 100644 --- a/src/lib/support/ObjectLifeCycle.h +++ b/src/lib/support/ObjectLifeCycle.h @@ -70,11 +70,15 @@ class ObjectLifeCycle * Typical use is `VerifyOrReturnError(state.SetInitializing(), CHIP_ERROR_INCORRECT_STATE)`; these functions return `bool` * rather than a `CHIP_ERROR` so that error source tracking will record the call point rather than this function itself. */ - bool SetInitializing() { return Transition(); } - bool SetInitialized() { return Transition(); } - bool SetShuttingDown() { return Transition(); } - bool SetShutdown() { return Transition(); } - bool Reset() { return Transition(); } + bool SetInitializing() { return Transition(State::Uninitialized, State::Initializing); } + bool SetInitialized() { return Transition(State::Initializing, State::Initialized); } + bool SetShuttingDown() { return Transition(State::Initialized, State::ShuttingDown); } + bool SetShutdown() { return Transition(State::ShuttingDown, State::Shutdown); } + bool Reset() { return Transition(State::Shutdown, State::Uninitialized); } + + // Skip steps when a class's shutdown code has nothing useful to do in between. + bool ResetFromShuttingDown() { return Transition(State::ShuttingDown, State::Uninitialized); } + bool ResetFromInitialized() { return Transition(State::Initialized, State::Uninitialized); } /** * Transition from Uninitialized or Shutdown to Destroyed. @@ -98,12 +102,11 @@ class ObjectLifeCycle State GetState() const { return mState; } private: - template - bool Transition() + bool Transition(State from, State to) { - if (mState == FROM) + if (mState == from) { - mState = TO; + mState = to; return true; } return false; diff --git a/src/messaging/tests/echo/common.cpp b/src/messaging/tests/echo/common.cpp index 89e12db1c83f9b..75b73baad40ce7 100644 --- a/src/messaging/tests/echo/common.cpp +++ b/src/messaging/tests/echo/common.cpp @@ -48,6 +48,10 @@ void InitializeChip(void) err = chip::DeviceLayer::PlatformMgr().InitChipStack(); SuccessOrExit(err); + // Initialize TCP. + err = chip::DeviceLayer::InetLayer().InitTCP(chip::DeviceLayer::TCPEndPointManager()); + SuccessOrExit(err); + exit: if (err != CHIP_NO_ERROR) { diff --git a/src/platform/Darwin/CHIPDevicePlatformEvent.h b/src/platform/Darwin/CHIPDevicePlatformEvent.h index 1e2e407c6d9863..5692efb6f68b51 100644 --- a/src/platform/Darwin/CHIPDevicePlatformEvent.h +++ b/src/platform/Darwin/CHIPDevicePlatformEvent.h @@ -24,6 +24,7 @@ #pragma once #include +#include namespace chip { namespace DeviceLayer { diff --git a/src/platform/Globals.cpp b/src/platform/Globals.cpp index 0b6e806b3e253e..eaed4f1fbaa20c 100644 --- a/src/platform/Globals.cpp +++ b/src/platform/Globals.cpp @@ -31,6 +31,22 @@ chip::Inet::InetLayer & InetLayer() return gInetLayer; } +chip::Inet::EndPointManager * UDPEndPointManager() +{ + static chip::Inet::UDPEndPointManagerImpl gUDPEndPointManager; + return &gUDPEndPointManager; +} + +chip::Inet::EndPointManager * TCPEndPointManager() +{ +#if INET_CONFIG_ENABLE_TCP_ENDPOINT + static chip::Inet::TCPEndPointManagerImpl gTCPEndPointManager; + return &gTCPEndPointManager; +#else // INET_CONFIG_ENABLE_TCP_ENDPOINT + return nullptr; +#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT +} + chip::System::LayerImpl * gMockedSystemLayer = nullptr; void SetSystemLayerForTesting(System::LayerImpl * layer) diff --git a/src/platform/Linux/CHIPDevicePlatformEvent.h b/src/platform/Linux/CHIPDevicePlatformEvent.h index 6daae6ac9ee1ce..009f39148aef92 100644 --- a/src/platform/Linux/CHIPDevicePlatformEvent.h +++ b/src/platform/Linux/CHIPDevicePlatformEvent.h @@ -24,6 +24,7 @@ #pragma once #include +#include namespace chip { namespace DeviceLayer { diff --git a/src/system/SystemLayerImplLibevent.cpp b/src/system/SystemLayerImplLibevent.cpp index d6ccd0cf2cb298..dc9f03184e160f 100644 --- a/src/system/SystemLayerImplLibevent.cpp +++ b/src/system/SystemLayerImplLibevent.cpp @@ -133,8 +133,7 @@ CHIP_ERROR LayerImplLibevent::Shutdown() mEventBase = nullptr; mSystemLayer = nullptr; - mLayerState.SetShutdown(); - mLayerState.Reset(); // Return to uninitialized state to permit re-initialization. + mLayerState.ResetFromShuttingDown(); // Return to uninitialized state to permit re-initialization. return CHIP_NO_ERROR; } diff --git a/src/system/SystemLayerImplLwIP.cpp b/src/system/SystemLayerImplLwIP.cpp index c1171f66f9026c..5957328cbb7a76 100644 --- a/src/system/SystemLayerImplLwIP.cpp +++ b/src/system/SystemLayerImplLwIP.cpp @@ -46,9 +46,7 @@ CHIP_ERROR LayerImplLwIP::Init() CHIP_ERROR LayerImplLwIP::Shutdown() { - VerifyOrReturnError(mLayerState.SetShuttingDown(), CHIP_ERROR_INCORRECT_STATE); - mLayerState.SetShutdown(); - mLayerState.Reset(); // Return to uninitialized state to permit re-initialization. + VerifyOrReturnError(mLayerState.ResetFromInitialized(), CHIP_ERROR_INCORRECT_STATE); return CHIP_NO_ERROR; } diff --git a/src/system/SystemLayerImplSelect.cpp b/src/system/SystemLayerImplSelect.cpp index a96077a33e3593..63b67cbdc5b30c 100644 --- a/src/system/SystemLayerImplSelect.cpp +++ b/src/system/SystemLayerImplSelect.cpp @@ -85,8 +85,7 @@ CHIP_ERROR LayerImplSelect::Shutdown() } mWakeEvent.Close(*this); - mLayerState.SetShutdown(); - mLayerState.Reset(); // Return to uninitialized state to permit re-initialization. + mLayerState.ResetFromShuttingDown(); // Return to uninitialized state to permit re-initialization. return CHIP_NO_ERROR; } diff --git a/src/system/tests/TestSystemTimer.cpp b/src/system/tests/TestSystemTimer.cpp index 6a4d0618eedc12..9b902f246ee0b6 100644 --- a/src/system/tests/TestSystemTimer.cpp +++ b/src/system/tests/TestSystemTimer.cpp @@ -107,13 +107,13 @@ void TimerFailed(void * aState) sOverflowTestDone = true; } -void HandleTimerFailed(Layer * inetLayer, void * aState) +void HandleTimerFailed(Layer * systemLayer, void * aState) { - (void) inetLayer; + (void) systemLayer; TimerFailed(aState); } -void HandleTimer10Success(Layer * inetLayer, void * aState) +void HandleTimer10Success(Layer * systemLayer, void * aState) { TestContext & lContext = *static_cast(aState); NL_TEST_ASSERT(lContext.mTestSuite, true); diff --git a/src/transport/raw/TCP.cpp b/src/transport/raw/TCP.cpp index 98a1b45865cd20..07d6290c7a0fe5 100644 --- a/src/transport/raw/TCP.cpp +++ b/src/transport/raw/TCP.cpp @@ -85,7 +85,8 @@ CHIP_ERROR TCPBase::Init(TcpListenParameters & params) VerifyOrExit(mState == State::kNotReady, err = CHIP_ERROR_INCORRECT_STATE); #if INET_CONFIG_ENABLE_TCP_ENDPOINT - err = params.GetInetLayer()->NewTCPEndPoint(&mListenSocket); + VerifyOrDieWithMsg(params.GetEndPointManager() != nullptr, Inet, "TCP not initialized"); + err = params.GetEndPointManager()->NewEndPoint(&mListenSocket); #else err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; #endif @@ -248,7 +249,7 @@ CHIP_ERROR TCPBase::SendAfterConnect(const PeerAddress & addr, System::PacketBuf VerifyOrExit(mUsedEndPointCount < mActiveConnectionsSize, err = CHIP_ERROR_NO_MEMORY); #if INET_CONFIG_ENABLE_TCP_ENDPOINT - err = mListenSocket->Layer().NewTCPEndPoint(&endPoint); + err = mListenSocket->GetEndPointManager().NewEndPoint(&endPoint); #else err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; #endif diff --git a/src/transport/raw/TCP.h b/src/transport/raw/TCP.h index 75b526c65ffe73..0a0cb2bfbf4418 100644 --- a/src/transport/raw/TCP.h +++ b/src/transport/raw/TCP.h @@ -42,11 +42,11 @@ namespace Transport { class TcpListenParameters { public: - explicit TcpListenParameters(Inet::InetLayer * layer) : mLayer(layer) {} + explicit TcpListenParameters(Inet::InetLayer * inetLayer) : mEndPointManager(inetLayer->GetTCPEndPointManager()) {} TcpListenParameters(const TcpListenParameters &) = default; TcpListenParameters(TcpListenParameters &&) = default; - Inet::InetLayer * GetInetLayer() { return mLayer; } + Inet::EndPointManager * GetEndPointManager() { return mEndPointManager; } Inet::IPAddressType GetAddressType() const { return mAddressType; } TcpListenParameters & SetAddressType(Inet::IPAddressType type) @@ -73,7 +73,7 @@ class TcpListenParameters } private: - Inet::InetLayer * mLayer = nullptr; ///< Associated inet layer + Inet::EndPointManager * mEndPointManager; ///< Associated endpoint factory Inet::IPAddressType mAddressType = Inet::IPAddressType::kIPv6; ///< type of listening socket uint16_t mListenPort = CHIP_PORT; ///< TCP listen port Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null(); ///< Interface to listen on diff --git a/src/transport/raw/UDP.cpp b/src/transport/raw/UDP.cpp index 5915418e9dc42a..af06e9c6b4ed92 100644 --- a/src/transport/raw/UDP.cpp +++ b/src/transport/raw/UDP.cpp @@ -46,7 +46,7 @@ CHIP_ERROR UDP::Init(UdpListenParameters & params) Close(); } - err = params.GetInetLayer()->NewUDPEndPoint(&mUDPEndPoint); + err = params.GetEndPointManager()->NewEndPoint(&mUDPEndPoint); SuccessOrExit(err); ChipLogDetail(Inet, "UDP::Init bind&listen port=%d", params.GetListenPort()); diff --git a/src/transport/raw/UDP.h b/src/transport/raw/UDP.h index 5cc04166b29d9a..c4951e80e40ec3 100644 --- a/src/transport/raw/UDP.h +++ b/src/transport/raw/UDP.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -40,11 +41,11 @@ namespace Transport { class UdpListenParameters { public: - explicit UdpListenParameters(Inet::InetLayer * layer) : mLayer(layer) {} + explicit UdpListenParameters(Inet::InetLayer * inetLayer) : mEndPointManager(inetLayer->GetUDPEndPointManager()) {} UdpListenParameters(const UdpListenParameters &) = default; UdpListenParameters(UdpListenParameters &&) = default; - Inet::InetLayer * GetInetLayer() { return mLayer; } + Inet::EndPointManager * GetEndPointManager() { return mEndPointManager; } Inet::IPAddressType GetAddressType() const { return mAddressType; } UdpListenParameters & SetAddressType(Inet::IPAddressType type) @@ -71,7 +72,7 @@ class UdpListenParameters } private: - Inet::InetLayer * mLayer = nullptr; ///< Associated inet layer + Inet::EndPointManager * mEndPointManager; ///< Associated endpoint factory Inet::IPAddressType mAddressType = Inet::IPAddressType::kIPv6; ///< type of listening socket uint16_t mListenPort = CHIP_PORT; ///< UDP listen port Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null(); ///< Interface to listen on