diff --git a/examples/chip-tool/commands/common/Commands.cpp b/examples/chip-tool/commands/common/Commands.cpp index 33c4aa5bed6211..2d4fb5b90649ef 100644 --- a/examples/chip-tool/commands/common/Commands.cpp +++ b/examples/chip-tool/commands/common/Commands.cpp @@ -27,6 +27,7 @@ #include #endif +#include #include #include #include @@ -35,6 +36,8 @@ #include #include +using DeviceControllerFactory = chip::Controller::DeviceControllerFactory; + void Commands::Register(const char * clusterName, commands_list commandsList) { for (auto & command : commandsList) @@ -46,7 +49,8 @@ void Commands::Register(const char * clusterName, commands_list commandsList) int Commands::Run(int argc, char ** argv) { CHIP_ERROR err = CHIP_NO_ERROR; - chip::Controller::CommissionerInitParams initParams; + chip::Controller::FactoryInitParams factoryInitParams; + chip::Controller::SetupParams commissionerParams; Command * command = nullptr; NodeId localId; NodeId remoteId; @@ -73,14 +77,14 @@ int Commands::Run(int argc, char ** argv) ChipLogProgress(Controller, "Read local id 0x" ChipLogFormatX64 ", remote id 0x" ChipLogFormatX64, ChipLogValueX64(localId), ChipLogValueX64(remoteId)); - initParams.storageDelegate = &mStorage; + factoryInitParams.storageDelegate = &mStorage; + factoryInitParams.listenPort = mStorage.GetListenPort(); err = mOpCredsIssuer.Initialize(mStorage); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Operational Cred Issuer: %s", chip::ErrorStr(err))); - initParams.operationalCredentialsDelegate = &mOpCredsIssuer; + commissionerParams.operationalCredentialsDelegate = &mOpCredsIssuer; - err = mController.SetUdpListenPort(mStorage.GetListenPort()); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Commissioner: %s", chip::ErrorStr(err))); chip::Credentials::SetDeviceAttestationCredentialsProvider(chip::Credentials::Examples::GetExampleDACProvider()); @@ -104,19 +108,22 @@ int Commands::Run(int argc, char ** argv) err = mOpCredsIssuer.GenerateNOCChainAfterValidation(localId, 0, ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan); SuccessOrExit(err); - initParams.ephemeralKeypair = &ephemeralKey; - initParams.controllerRCAC = rcacSpan; - initParams.controllerICAC = icacSpan; - initParams.controllerNOC = nocSpan; + commissionerParams.ephemeralKeypair = &ephemeralKey; + commissionerParams.controllerRCAC = rcacSpan; + commissionerParams.controllerICAC = icacSpan; + commissionerParams.controllerNOC = nocSpan; - err = mController.Init(initParams); + // init the factory, then setup the Controller + err = DeviceControllerFactory::GetInstance().Init(factoryInitParams); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Controller Factory failed to initialize")); + err = DeviceControllerFactory::GetInstance().SetupCommissioner(commissionerParams, mController); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Commissioner: %s", chip::ErrorStr(err))); } #if CONFIG_USE_SEPARATE_EVENTLOOP // ServiceEvents() calls StartEventLoopTask(), which is paired with the // StopEventLoopTask() below. - err = mController.ServiceEvents(); + err = DeviceControllerFactory::GetInstance().ServiceEvents(); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init failure! Run Loop: %s", chip::ErrorStr(err))); #endif // CONFIG_USE_SEPARATE_EVENTLOOP diff --git a/examples/ota-requestor-app/linux/ExampleSelfCommissioning.h b/examples/ota-requestor-app/linux/ExampleSelfCommissioning.h index bfd50286a952e7..99346b7813216c 100644 --- a/examples/ota-requestor-app/linux/ExampleSelfCommissioning.h +++ b/examples/ota-requestor-app/linux/ExampleSelfCommissioning.h @@ -18,7 +18,7 @@ #pragma once -#include +#include #include #include #include @@ -30,13 +30,14 @@ using chip::Controller::DeviceController; using chip::Controller::ExampleOperationalCredentialsIssuer; CHIP_ERROR DoExampleSelfCommissioning(DeviceController & controller, ExampleOperationalCredentialsIssuer * opCredsIssuer, - PersistentStorageDelegate * storage, chip::NodeId localNodeId) + PersistentStorageDelegate * storage, chip::NodeId localNodeId, uint16_t listenPort) { CHIP_ERROR err = CHIP_NO_ERROR; chip::Platform::ScopedMemoryBuffer noc; chip::Platform::ScopedMemoryBuffer icac; chip::Platform::ScopedMemoryBuffer rcac; - chip::Controller::ControllerInitParams initParams; + chip::Controller::FactoryInitParams initParams; + chip::Controller::SetupParams setupParams; VerifyOrExit(storage != nullptr && opCredsIssuer != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); @@ -61,15 +62,21 @@ CHIP_ERROR DoExampleSelfCommissioning(DeviceController & controller, ExampleOper err = opCredsIssuer->GenerateNOCChainAfterValidation(localNodeId, 0, ephemeralKey.Pubkey(), rcacSpan, icacSpan, nocSpan); SuccessOrExit(err); - initParams.ephemeralKeypair = &ephemeralKey; - initParams.controllerRCAC = rcacSpan; - initParams.controllerICAC = icacSpan; - initParams.controllerNOC = nocSpan; - initParams.operationalCredentialsDelegate = opCredsIssuer; + setupParams.ephemeralKeypair = &ephemeralKey; + setupParams.controllerRCAC = rcacSpan; + setupParams.controllerICAC = icacSpan; + setupParams.controllerNOC = nocSpan; + setupParams.operationalCredentialsDelegate = opCredsIssuer; initParams.storageDelegate = storage; + initParams.listenPort = listenPort; - err = controller.Init(initParams); + auto & factory = chip::Controller::DeviceControllerFactory::GetInstance(); + + err = factory.Init(initParams); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Controller Factory init failure! %s", chip::ErrorStr(err))); + + err = factory.SetupController(setupParams, controller); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Controller init failure! %s", chip::ErrorStr(err))); } diff --git a/examples/ota-requestor-app/linux/main.cpp b/examples/ota-requestor-app/linux/main.cpp index 331a48007097a0..98722b24bc8134 100644 --- a/examples/ota-requestor-app/linux/main.cpp +++ b/examples/ota-requestor-app/linux/main.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -229,17 +229,16 @@ int main(int argc, char * argv[]) chip::Logging::SetLogFilter(mStorage.GetLoggingLevel()); - err = mController.SetUdpListenPort(mStorage.GetListenPort()); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "failed to set UDP port: %s", chip::ErrorStr(err))); // Until #9518 is fixed, the only way to open a CASE session to another node is to commission it first using the // DeviceController API. Thus, the ota-requestor-app must do self commissioning and then read CASE credentials from persistent // storage to connect to the Provider node. See README.md for instructions. // NOTE: Controller is initialized in this call - err = DoExampleSelfCommissioning(mController, &mOpCredsIssuer, &mStorage, mStorage.GetLocalNodeId()); + err = DoExampleSelfCommissioning(mController, &mOpCredsIssuer, &mStorage, mStorage.GetLocalNodeId(), mStorage.GetListenPort()); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(SoftwareUpdate, "example self-commissioning failed: %s", chip::ErrorStr(err))); - err = mController.ServiceEvents(); + err = chip::Controller::DeviceControllerFactory::GetInstance().ServiceEvents(); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "ServiceEvents() failed: %s", chip::ErrorStr(err))); ChipLogProgress(SoftwareUpdate, "Attempting to connect to device 0x%" PRIX64, providerNodeId); diff --git a/examples/platform/linux/AppMain.cpp b/examples/platform/linux/AppMain.cpp index e3c7b3b0674ee3..87c7182ed71305 100644 --- a/examples/platform/linux/AppMain.cpp +++ b/examples/platform/linux/AppMain.cpp @@ -40,7 +40,7 @@ #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE #include -#include +#include #include #include #include @@ -212,16 +212,17 @@ CHIP_ERROR InitCommissioner() { NodeId localId = chip::kPlaceholderNodeId; - chip::Controller::CommissionerInitParams params; + chip::Controller::FactoryInitParams factoryParams; + chip::Controller::SetupParams params; - params.storageDelegate = &gServerStorage; - params.mDeviceAddressUpdateDelegate = nullptr; + factoryParams.storageDelegate = &gServerStorage; + // use a different listen port for the commissioner. + factoryParams.listenPort = LinuxDeviceOptions::GetInstance().securedCommissionerPort; + params.deviceAddressUpdateDelegate = nullptr; params.operationalCredentialsDelegate = &gOpCredsIssuer; ReturnErrorOnFailure(gOpCredsIssuer.Initialize(gServerStorage)); - // use a different listen port for the commissioner. - ReturnErrorOnFailure(gCommissioner.SetUdpListenPort(LinuxDeviceOptions::GetInstance().securedCommissionerPort)); // No need to explicitly set the UDC port since we will use default ReturnErrorOnFailure(gCommissioner.SetUdcListenPort(LinuxDeviceOptions::GetInstance().unsecuredCommissionerPort)); @@ -251,7 +252,9 @@ CHIP_ERROR InitCommissioner() params.controllerICAC = icacSpan; params.controllerNOC = nocSpan; - ReturnErrorOnFailure(gCommissioner.Init(params)); + auto & factory = chip::Controller::DeviceControllerFactory::GetInstance(); + ReturnErrorOnFailure(factory.Init(factoryParams)); + ReturnErrorOnFailure(factory.SetupCommissioner(params, gCommissioner)); return CHIP_NO_ERROR; } diff --git a/src/controller/BUILD.gn b/src/controller/BUILD.gn index 9abe48de30e61e..84604fac1c5044 100644 --- a/src/controller/BUILD.gn +++ b/src/controller/BUILD.gn @@ -34,6 +34,8 @@ static_library("controller") { "CHIPDevice.h", "CHIPDeviceController.cpp", "CHIPDeviceController.h", + "CHIPDeviceControllerFactory.cpp", + "CHIPDeviceControllerFactory.h", "DeviceAddressUpdateDelegate.h", "EmptyDataModelHandler.cpp", "ExampleOperationalCredentialsIssuer.cpp", diff --git a/src/controller/CHIPDevice.h b/src/controller/CHIPDevice.h index b9a256f959810a..d7eb54334293c1 100644 --- a/src/controller/CHIPDevice.h +++ b/src/controller/CHIPDevice.h @@ -165,15 +165,13 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta * still using them, it can lead to unknown behavior and crashes. * * @param[in] params Wrapper object for transport manager etc. - * @param[in] listenPort Port on which controller is listening (typically CHIP_PORT) * @param[in] fabric Local administrator that's initializing this device object */ - void Init(ControllerDeviceInitParams params, uint16_t listenPort, FabricIndex fabric) + void Init(ControllerDeviceInitParams params, FabricIndex fabric) { mSessionManager = params.sessionManager; mExchangeMgr = params.exchangeMgr; mInetLayer = params.inetLayer; - mListenPort = listenPort; mFabricIndex = fabric; mStorageDelegate = params.storageDelegate; mIDAllocator = params.idAllocator; @@ -196,15 +194,13 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta * is actually paired. * * @param[in] params Wrapper object for transport manager etc. - * @param[in] listenPort Port on which controller is listening (typically CHIP_PORT) * @param[in] deviceId Node ID of the device * @param[in] peerAddress The location of the peer. MUST be of type Transport::Type::kUdp * @param[in] fabric Local administrator that's initializing this device object */ - void Init(ControllerDeviceInitParams params, uint16_t listenPort, NodeId deviceId, const Transport::PeerAddress & peerAddress, - FabricIndex fabric) + void Init(ControllerDeviceInitParams params, NodeId deviceId, const Transport::PeerAddress & peerAddress, FabricIndex fabric) { - Init(params, mListenPort, fabric); + Init(params, fabric); mDeviceId = deviceId; mState = ConnectionState::Connecting; @@ -522,8 +518,6 @@ class DLL_EXPORT Device : public Messaging::ExchangeDelegate, public SessionEsta static void OnOpenPairingWindowSuccessResponse(void * context); static void OnOpenPairingWindowFailureResponse(void * context, uint8_t status); - uint16_t mListenPort; - FabricIndex mFabricIndex = Transport::kUndefinedFabricIndex; Transport::FabricTable * mFabricsTable = nullptr; diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 0b4952cd2e99fd..bb3cc97a332f75 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -109,8 +109,6 @@ constexpr uint32_t kSessionEstablishmentTimeout = 30 * kMillisecondsPerSecond; DeviceController::DeviceController() { mState = State::NotInitialized; - mSessionManager = nullptr; - mExchangeMgr = nullptr; mStorageDelegate = nullptr; mPairedDevicesInitialized = false; } @@ -118,95 +116,40 @@ DeviceController::DeviceController() CHIP_ERROR DeviceController::Init(ControllerInitParams params) { VerifyOrReturnError(mState == State::NotInitialized, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(params.systemState != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - if (params.systemLayer != nullptr && params.inetLayer != nullptr) - { - mSystemLayer = params.systemLayer; - mInetLayer = params.inetLayer; - mListenPort = params.listenPort; - } - else - { -#if CONFIG_DEVICE_LAYER - ReturnErrorOnFailure(DeviceLayer::PlatformMgr().InitChipStack()); - - mSystemLayer = &DeviceLayer::SystemLayer(); - mInetLayer = &DeviceLayer::InetLayer; -#endif // CONFIG_DEVICE_LAYER - } - - VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(mInetLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(params.systemState->SystemLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(params.systemState->InetLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); mStorageDelegate = params.storageDelegate; #if CONFIG_NETWORK_LAYER_BLE -#if CONFIG_DEVICE_LAYER - if (params.bleLayer == nullptr) - { - params.bleLayer = DeviceLayer::ConnectivityMgr().GetBleLayer(); - } -#endif // CONFIG_DEVICE_LAYER - mBleLayer = params.bleLayer; - VerifyOrReturnError(mBleLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); -#endif - - mTransportMgr = chip::Platform::New(); - mSessionManager = chip::Platform::New(); - mExchangeMgr = chip::Platform::New(); - mMessageCounterManager = chip::Platform::New(); - - ReturnErrorOnFailure(mTransportMgr->Init( - Transport::UdpListenParameters(mInetLayer).SetAddressType(Inet::kIPAddressType_IPv6).SetListenPort(mListenPort) -#if INET_CONFIG_ENABLE_IPV4 - , - Transport::UdpListenParameters(mInetLayer).SetAddressType(Inet::kIPAddressType_IPv4).SetListenPort(mListenPort) -#endif -#if CONFIG_NETWORK_LAYER_BLE - , - Transport::BleListenParameters(mBleLayer) + VerifyOrReturnError(params.systemState->BleLayer() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); #endif - )); - - ReturnErrorOnFailure(mFabrics.Init(mStorageDelegate)); - ReturnErrorOnFailure(mSessionManager->Init(mSystemLayer, mTransportMgr, &mFabrics, mMessageCounterManager)); + VerifyOrReturnError(params.systemState->TransportMgr() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - ReturnErrorOnFailure(mExchangeMgr->Init(mSessionManager)); - - ReturnErrorOnFailure(mMessageCounterManager->Init(mExchangeMgr)); - - ReturnErrorOnFailure(mExchangeMgr->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::TempZCL::Id, this)); - - if (params.imDelegate != nullptr) - { - mInteractionModelDelegate = params.imDelegate; - } - else - { - mDefaultIMDelegate = chip::Platform::New(); - mInteractionModelDelegate = mDefaultIMDelegate; - } - ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init(mExchangeMgr, mInteractionModelDelegate)); - - mExchangeMgr->SetDelegate(this); + // TODO Exchange Mgr needs to be able to track multiple delegates. Delegate API should be able to query for the right delegate + // to handle events. + ReturnErrorOnFailure( + params.systemState->ExchangeMgr()->RegisterUnsolicitedMessageHandlerForProtocol(Protocols::TempZCL::Id, this)); + params.systemState->ExchangeMgr()->SetDelegate(this); #if CHIP_DEVICE_CONFIG_ENABLE_MDNS ReturnErrorOnFailure(Mdns::Resolver::Instance().SetResolverDelegate(this)); - RegisterDeviceAddressUpdateDelegate(params.mDeviceAddressUpdateDelegate); - Mdns::Resolver::Instance().StartResolver(mInetLayer, kMdnsPort); + RegisterDeviceAddressUpdateDelegate(params.deviceAddressUpdateDelegate); + Mdns::Resolver::Instance().StartResolver(params.systemState->InetLayer(), kMdnsPort); #endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS - InitDataModelHandler(mExchangeMgr); + InitDataModelHandler(params.systemState->ExchangeMgr()); VerifyOrReturnError(params.operationalCredentialsDelegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT); mOperationalCredentialsDelegate = params.operationalCredentialsDelegate; ReturnErrorOnFailure(ProcessControllerNOCChain(params)); - mState = State::Initialized; - + mSystemState = params.systemState->Retain(); + mState = State::Initialized; ReleaseAllDevices(); - return CHIP_NO_ERROR; } @@ -244,7 +187,7 @@ CHIP_ERROR DeviceController::ProcessControllerNOCChain(const ControllerInitParam ReturnErrorOnFailure(newFabric.SetNOCCert(chipCertSpan)); newFabric.SetVendorId(params.controllerVendorId); - Transport::FabricInfo * fabric = mFabrics.FindFabricWithIndex(mFabricIndex); + Transport::FabricInfo * fabric = params.systemState->Fabrics()->FindFabricWithIndex(mFabricIndex); ReturnErrorCodeIf(fabric == nullptr, CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(fabric->SetFabricInfo(newFabric)); @@ -272,80 +215,17 @@ CHIP_ERROR DeviceController::Shutdown() mState = State::NotInitialized; - // Shut down the interaction model before we try shuttting down the exchange - // manager. - app::InteractionModelEngine::GetInstance()->Shutdown(); - #if CHIP_DEVICE_CONFIG_ENABLE_MDNS Mdns::Resolver::Instance().ShutdownResolver(); #endif // CHIP_DEVICE_CONFIG_ENABLE_MDNS - // TODO(#6668): Some exchange has leak, shutting down ExchangeManager will cause a assert fail. - // if (mExchangeMgr != nullptr) - // { - // mExchangeMgr->Shutdown(); - // } - if (mSessionManager != nullptr) - { - mSessionManager->Shutdown(); - } - mStorageDelegate = nullptr; ReleaseAllDevices(); -#if CONFIG_DEVICE_LAYER - // - // We can safely call PlatformMgr().Shutdown(), which like DeviceController::Shutdown(), - // expects to be called with external thread synchronization and will not try to acquire the - // stack lock. - // - // Actually stopping the event queue is a separable call that applications will have to sequence. - // Consumers are expected to call PlaformMgr().StopEventLoopTask() before calling - // DeviceController::Shutdown() in the CONFIG_DEVICE_LAYER configuration - // - ReturnErrorOnFailure(DeviceLayer::PlatformMgr().Shutdown()); -#else - ReturnErrorOnFailure(mInetLayer->Shutdown()); - ReturnErrorOnFailure(mSystemLayer->Shutdown()); - chip::Platform::Delete(mInetLayer); - chip::Platform::Delete(mSystemLayer); -#endif // CONFIG_DEVICE_LAYER - - mSystemLayer = nullptr; - mInetLayer = nullptr; - - if (mMessageCounterManager != nullptr) - { - chip::Platform::Delete(mMessageCounterManager); - mMessageCounterManager = nullptr; - } - - if (mExchangeMgr != nullptr) - { - chip::Platform::Delete(mExchangeMgr); - mExchangeMgr = nullptr; - } - - if (mSessionManager != nullptr) - { - chip::Platform::Delete(mSessionManager); - mSessionManager = nullptr; - } - - if (mTransportMgr != nullptr) - { - chip::Platform::Delete(mTransportMgr); - mTransportMgr = nullptr; - } - - if (mDefaultIMDelegate != nullptr) - { - chip::Platform::Delete(mDefaultIMDelegate); - mDefaultIMDelegate = nullptr; - } - - mFabrics.ReleaseFabricIndex(mFabricIndex); + mSystemState->Fabrics()->ReleaseFabricIndex(mFabricIndex); + mSystemState->Release(); + mSystemState = nullptr; #if CHIP_DEVICE_CONFIG_ENABLE_MDNS Mdns::Resolver::Instance().SetResolverDelegate(nullptr); @@ -355,17 +235,6 @@ CHIP_ERROR DeviceController::Shutdown() return CHIP_NO_ERROR; } -CHIP_ERROR DeviceController::SetUdpListenPort(uint16_t listenPort) -{ - if (mState == State::Initialized) - { - return CHIP_ERROR_INCORRECT_STATE; - } - - mListenPort = listenPort; - return CHIP_NO_ERROR; -} - CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -402,7 +271,7 @@ CHIP_ERROR DeviceController::GetDevice(NodeId deviceId, Device ** out_device) err = device->Deserialize(deviceInfo); VerifyOrExit(err == CHIP_NO_ERROR, ReleaseDevice(device)); - device->Init(GetControllerDeviceInitParams(), mListenPort, mFabricIndex); + device->Init(GetControllerDeviceInitParams(), mFabricIndex); } } @@ -475,17 +344,6 @@ void DeviceController::PersistDevice(Device * device) } } -CHIP_ERROR DeviceController::ServiceEvents() -{ - VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); - -#if CONFIG_DEVICE_LAYER - ReturnErrorOnFailure(DeviceLayer::PlatformMgr().StartEventLoopTask()); -#endif // CONFIG_DEVICE_LAYER - - return CHIP_NO_ERROR; -} - CHIP_ERROR DeviceController::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, System::PacketBufferHandle && msgBuf) { @@ -719,14 +577,14 @@ void DeviceController::OnNodeIdResolutionFailed(const chip::PeerId & peer, CHIP_ ControllerDeviceInitParams DeviceController::GetControllerDeviceInitParams() { return ControllerDeviceInitParams{ - .transportMgr = mTransportMgr, - .sessionManager = mSessionManager, - .exchangeMgr = mExchangeMgr, - .inetLayer = mInetLayer, + .transportMgr = mSystemState->TransportMgr(), + .sessionManager = mSystemState->SessionMgr(), + .exchangeMgr = mSystemState->ExchangeMgr(), + .inetLayer = mSystemState->InetLayer(), .storageDelegate = mStorageDelegate, .idAllocator = &mIDAllocator, - .fabricsTable = &mFabrics, - .imDelegate = mInteractionModelDelegate, + .fabricsTable = mSystemState->Fabrics(), + .imDelegate = mSystemState->IMDelegate(), }; } @@ -761,18 +619,18 @@ CHIP_ERROR DeviceCommissioner::Init(CommissionerInitParams params) #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable mUdcTransportMgr = chip::Platform::New(); - ReturnErrorOnFailure(mUdcTransportMgr->Init(Transport::UdpListenParameters(mInetLayer) + ReturnErrorOnFailure(mUdcTransportMgr->Init(Transport::UdpListenParameters(mSystemState->InetLayer()) .SetAddressType(Inet::kIPAddressType_IPv6) .SetListenPort((uint16_t)(mUdcListenPort)) #if INET_CONFIG_ENABLE_IPV4 , - Transport::UdpListenParameters(mInetLayer) + Transport::UdpListenParameters(mSystemState->InetLayer()) .SetAddressType(Inet::kIPAddressType_IPv4) .SetListenPort((uint16_t)(mUdcListenPort)) #endif // INET_CONFIG_ENABLE_IPV4 #if CONFIG_NETWORK_LAYER_BLE , - Transport::BleListenParameters(mBleLayer) + Transport::BleListenParameters(mSystemState->BleLayer()) #endif // CONFIG_NETWORK_LAYER_BLE )); @@ -825,7 +683,7 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam uint16_t keyID = 0; - Transport::FabricInfo * fabric = mFabrics.FindFabricWithIndex(mFabricIndex); + Transport::FabricInfo * fabric = mSystemState->Fabrics()->FindFabricWithIndex(mFabricIndex); VerifyOrExit(IsOperationalNodeId(remoteDeviceId), err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(mState == State::Initialized, err = CHIP_ERROR_INCORRECT_STATE); @@ -884,12 +742,12 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam mIsIPRendezvous = (params.GetPeerAddress().GetTransportType() != Transport::Type::kBle); - err = mPairingSession.MessageDispatch().Init(mSessionManager); + err = mPairingSession.MessageDispatch().Init(mSystemState->SessionMgr()); SuccessOrExit(err); - device->Init(GetControllerDeviceInitParams(), mListenPort, remoteDeviceId, peerAddress, fabric->GetFabricIndex()); + device->Init(GetControllerDeviceInitParams(), remoteDeviceId, peerAddress, fabric->GetFabricIndex()); - mSystemLayer->StartTimer(kSessionEstablishmentTimeout, OnSessionEstablishmentTimeoutCallback, this); + mSystemState->SystemLayer()->StartTimer(kSessionEstablishmentTimeout, OnSessionEstablishmentTimeoutCallback, this); if (params.GetPeerAddress().GetTransportType() != Transport::Type::kBle) { device->SetAddress(params.GetPeerAddress().GetIPAddress()); @@ -899,11 +757,11 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam { if (params.HasConnectionObject()) { - SuccessOrExit(err = mBleLayer->NewBleConnectionByObject(params.GetConnectionObject())); + SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByObject(params.GetConnectionObject())); } else if (params.HasDiscriminator()) { - SuccessOrExit(err = mBleLayer->NewBleConnectionByDiscriminator(params.GetDiscriminator())); + SuccessOrExit(err = mSystemState->BleLayer()->NewBleConnectionByDiscriminator(params.GetDiscriminator())); } else { @@ -911,10 +769,10 @@ CHIP_ERROR DeviceCommissioner::PairDevice(NodeId remoteDeviceId, RendezvousParam } } #endif - session = mSessionManager->CreateUnauthenticatedSession(params.GetPeerAddress()); + session = mSystemState->SessionMgr()->CreateUnauthenticatedSession(params.GetPeerAddress()); VerifyOrExit(session.HasValue(), CHIP_ERROR_NO_MEMORY); - exchangeCtxt = mExchangeMgr->NewContext(session.Value(), &mPairingSession); + exchangeCtxt = mSystemState->ExchangeMgr()->NewContext(session.Value(), &mPairingSession); VerifyOrExit(exchangeCtxt != nullptr, err = CHIP_ERROR_INTERNAL); err = mIDAllocator.Allocate(keyID); @@ -968,12 +826,12 @@ CHIP_ERROR DeviceCommissioner::PairTestDeviceWithoutSecurity(NodeId remoteDevice testSecurePairingSecret->ToSerializable(device->GetPairing()); - device->Init(GetControllerDeviceInitParams(), mListenPort, remoteDeviceId, peerAddress, mFabricIndex); + device->Init(GetControllerDeviceInitParams(), remoteDeviceId, peerAddress, mFabricIndex); device->Serialize(serialized); - err = mSessionManager->NewPairing(Optional::Value(peerAddress), device->GetDeviceId(), - testSecurePairingSecret, CryptoContext::SessionRole::kInitiator, mFabricIndex); + err = mSystemState->SessionMgr()->NewPairing(Optional::Value(peerAddress), device->GetDeviceId(), + testSecurePairingSecret, CryptoContext::SessionRole::kInitiator, mFabricIndex); if (err != CHIP_NO_ERROR) { ChipLogError(Controller, "Failed in setting up secure channel: err %s", ErrorStr(err)); @@ -1149,7 +1007,7 @@ void DeviceCommissioner::RendezvousCleanup(CHIP_ERROR status) void DeviceCommissioner::OnSessionEstablishmentError(CHIP_ERROR err) { - mSystemLayer->CancelTimer(OnSessionEstablishmentTimeoutCallback, this); + mSystemState->SystemLayer()->CancelTimer(OnSessionEstablishmentTimeoutCallback, this); if (mPairingDelegate != nullptr) { @@ -1168,9 +1026,9 @@ void DeviceCommissioner::OnSessionEstablished() // TODO: the session should know which peer we are trying to connect to when started mPairingSession.SetPeerNodeId(device->GetDeviceId()); - CHIP_ERROR err = mSessionManager->NewPairing(Optional::Value(mPairingSession.GetPeerAddress()), - mPairingSession.GetPeerNodeId(), &mPairingSession, - CryptoContext::SessionRole::kInitiator, mFabricIndex); + CHIP_ERROR err = mSystemState->SessionMgr()->NewPairing( + Optional::Value(mPairingSession.GetPeerAddress()), mPairingSession.GetPeerNodeId(), + &mPairingSession, CryptoContext::SessionRole::kInitiator, mFabricIndex); if (err != CHIP_NO_ERROR) { ChipLogError(Controller, "Failed in setting up secure channel: err %s", ErrorStr(err)); @@ -1337,7 +1195,7 @@ CHIP_ERROR DeviceCommissioner::ValidateAttestationInfo(const ByteSpan & attestat DeviceAttestationVerifier * dac_verifier = GetDeviceAttestationVerifier(); // Retrieve attestation challenge - ByteSpan attestationChallenge = mSessionManager + ByteSpan attestationChallenge = mSystemState->SessionMgr() ->GetSecureSession({ mPairingSession.GetPeerNodeId(), mPairingSession.GetLocalSessionId(), mPairingSession.GetPeerSessionId(), mFabricIndex }) ->GetCryptoContext() @@ -1674,7 +1532,7 @@ CHIP_ERROR DeviceCommissioner::OnOperationalCredentialsProvisioningCompletion(De #endif { mPairingSession.ToSerializable(device->GetPairing()); - mSystemLayer->CancelTimer(OnSessionEstablishmentTimeoutCallback, this); + mSystemState->SystemLayer()->CancelTimer(OnSessionEstablishmentTimeoutCallback, this); mPairedDevices.Insert(device->GetDeviceId()); mPairedDevicesUpdated = true; @@ -1721,7 +1579,7 @@ CHIP_ERROR DeviceCommissioner::CloseBleConnection() // It is fine since we can only commission one device at the same time. // We should be able to distinguish different BLE connections if we want // to commission multiple devices at the same time over BLE. - return mBleLayer->CloseAllBleConnections(); + return mSystemState->BleLayer()->CloseAllBleConnections(); } #endif @@ -2163,7 +2021,7 @@ void DeviceCommissioner::AdvanceCommissioningStage(CHIP_ERROR err) case CommissioningStage::kCleanup: ChipLogProgress(Controller, "Rendezvous cleanup"); mPairingSession.ToSerializable(device->GetPairing()); - mSystemLayer->CancelTimer(OnSessionEstablishmentTimeoutCallback, this); + mSystemState->SystemLayer()->CancelTimer(OnSessionEstablishmentTimeoutCallback, this); mPairedDevices.Insert(device->GetDeviceId()); mPairedDevicesUpdated = true; diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index f449e072f3af76..81d3adca983c4a 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -83,15 +84,9 @@ void BasicFailure(void * context, uint8_t status); struct ControllerInitParams { PersistentStorageDelegate * storageDelegate = nullptr; - System::Layer * systemLayer = nullptr; - Inet::InetLayer * inetLayer = nullptr; - -#if CONFIG_NETWORK_LAYER_BLE - Ble::BleLayer * bleLayer = nullptr; -#endif - DeviceControllerInteractionModelDelegate * imDelegate = nullptr; + DeviceControllerSystemState * systemState = nullptr; #if CHIP_DEVICE_CONFIG_ENABLE_MDNS - DeviceAddressUpdateDelegate * mDeviceAddressUpdateDelegate = nullptr; + DeviceAddressUpdateDelegate * deviceAddressUpdateDelegate = nullptr; #endif OperationalCredentialsDelegate * operationalCredentialsDelegate = nullptr; @@ -106,9 +101,7 @@ struct ControllerInitParams uint16_t controllerVendorId; - /* The port used for operational communication to listen for and send messages over UDP/TCP. - * The default value of `0` will pick any available port. */ - uint16_t listenPort = 0; + FabricId fabricId = kUndefinedFabricId; }; enum CommissioningStage : uint8_t @@ -248,22 +241,12 @@ class DLL_EXPORT DeviceController : public Messaging::ExchangeDelegate, void PersistDevice(Device * device); - CHIP_ERROR SetUdpListenPort(uint16_t listenPort); - virtual void ReleaseDevice(Device * device); #if CHIP_DEVICE_CONFIG_ENABLE_MDNS void RegisterDeviceAddressUpdateDelegate(DeviceAddressUpdateDelegate * delegate) { mDeviceAddressUpdateDelegate = delegate; } #endif - // ----- IO ----- - /** - * @brief - * Start the event loop task within the CHIP stack - * @return CHIP_ERROR The return status - */ - CHIP_ERROR ServiceEvents(); - /** * @brief Get the Compressed Fabric ID assigned to the device. */ @@ -274,7 +257,14 @@ class DLL_EXPORT DeviceController : public Messaging::ExchangeDelegate, */ uint64_t GetFabricId() const { return mFabricId; } - DeviceControllerInteractionModelDelegate * GetInteractionModelDelegate() { return mInteractionModelDelegate; } + DeviceControllerInteractionModelDelegate * GetInteractionModelDelegate() + { + if (mSystemState != nullptr) + { + return mSystemState->IMDelegate(); + } + return nullptr; + } protected: enum class State @@ -297,26 +287,15 @@ class DLL_EXPORT DeviceController : public Messaging::ExchangeDelegate, PeerId mLocalId = PeerId(); FabricId mFabricId = kUndefinedFabricId; - DeviceTransportMgr * mTransportMgr = nullptr; - SessionManager * mSessionManager = nullptr; - Messaging::ExchangeManager * mExchangeMgr = nullptr; - secure_channel::MessageCounterManager * mMessageCounterManager = nullptr; - PersistentStorageDelegate * mStorageDelegate = nullptr; - DeviceControllerInteractionModelDelegate * mDefaultIMDelegate = nullptr; + PersistentStorageDelegate * mStorageDelegate = nullptr; #if CHIP_DEVICE_CONFIG_ENABLE_MDNS DeviceAddressUpdateDelegate * mDeviceAddressUpdateDelegate = nullptr; // TODO(cecille): Make this configuarable. static constexpr int kMaxCommissionableNodes = 10; Mdns::DiscoveredNodeData mCommissionableNodes[kMaxCommissionableNodes]; #endif - Inet::InetLayer * mInetLayer = nullptr; -#if CONFIG_NETWORK_LAYER_BLE - Ble::BleLayer * mBleLayer = nullptr; -#endif - System::Layer * mSystemLayer = nullptr; - DeviceControllerInteractionModelDelegate * mInteractionModelDelegate = nullptr; + DeviceControllerSystemState * mSystemState = nullptr; - uint16_t mListenPort; uint16_t GetInactiveDeviceIndex(); uint16_t FindDeviceIndex(SessionHandle session); uint16_t FindDeviceIndex(NodeId id); @@ -329,7 +308,6 @@ class DLL_EXPORT DeviceController : public Messaging::ExchangeDelegate, void PersistNextKeyId(); FabricIndex mFabricIndex = Transport::kMinValidFabricIndex; - Transport::FabricTable mFabrics; OperationalCredentialsDelegate * mOperationalCredentialsDelegate; diff --git a/src/controller/CHIPDeviceControllerFactory.cpp b/src/controller/CHIPDeviceControllerFactory.cpp new file mode 100644 index 00000000000000..fa141799243532 --- /dev/null +++ b/src/controller/CHIPDeviceControllerFactory.cpp @@ -0,0 +1,284 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +/** + * @file + * Implementation of CHIP Device Controller Factory, a utility/manager class + * that vends Controller objects + */ + +#include + +#include + +#if CONFIG_DEVICE_LAYER +#include +#include +#endif + +using namespace chip::Inet; +using namespace chip::System; +using namespace chip::Credentials; + +namespace chip { +namespace Controller { + +CHIP_ERROR DeviceControllerFactory::Init(FactoryInitParams params) +{ + + // SystemState is only set the first time init is called, after that it is managed + // internally. If SystemState is set then init has already completed. + if (mSystemState != nullptr) + { + ChipLogError(Controller, "Device Controller Factory already initialized..."); + return CHIP_NO_ERROR; + } + + mListenPort = params.listenPort; + mStorageDelegate = params.storageDelegate; + + CHIP_ERROR err = InitSystemState(params); + + return err; +} + +CHIP_ERROR DeviceControllerFactory::InitSystemState() +{ + FactoryInitParams params; + if (mSystemState != nullptr) + { + params.systemLayer = mSystemState->SystemLayer(); + params.inetLayer = mSystemState->InetLayer(); +#if CONFIG_NETWORK_LAYER_BLE + params.bleLayer = mSystemState->BleLayer(); +#endif + } + + return InitSystemState(params); +} + +CHIP_ERROR DeviceControllerFactory::InitSystemState(FactoryInitParams params) +{ + if (mSystemState != nullptr && mSystemState->IsInitialized()) + { + return CHIP_NO_ERROR; + } + + if (mSystemState != nullptr) + { + mSystemState->Release(); + chip::Platform::Delete(mSystemState); + mSystemState = nullptr; + } + + DeviceControllerSystemStateParams stateParams; +#if CONFIG_DEVICE_LAYER + ReturnErrorOnFailure(DeviceLayer::PlatformMgr().InitChipStack()); + + stateParams.systemLayer = &DeviceLayer::SystemLayer(); + stateParams.inetLayer = &DeviceLayer::InetLayer; +#else + stateParams.systemLayer = params.systemLayer; + stateParams.inetLayer = params.inetLayer; + ChipLogError(Controller, "Warning: Device Controller Factory should be with a CHIP Device Layer..."); +#endif // CONFIG_DEVICE_LAYER + + VerifyOrReturnError(stateParams.systemLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(stateParams.inetLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + +#if CONFIG_NETWORK_LAYER_BLE +#if CONFIG_DEVICE_LAYER + stateParams.bleLayer = DeviceLayer::ConnectivityMgr().GetBleLayer(); +#else + stateParams.bleLayer = params.bleLayer; +#endif // CONFIG_DEVICE_LAYER + VerifyOrReturnError(stateParams.bleLayer != nullptr, CHIP_ERROR_INVALID_ARGUMENT); +#endif + + stateParams.transportMgr = chip::Platform::New(); + + ReturnErrorOnFailure(stateParams.transportMgr->Init( + Transport::UdpListenParameters(stateParams.inetLayer).SetAddressType(Inet::kIPAddressType_IPv6).SetListenPort(mListenPort) +#if INET_CONFIG_ENABLE_IPV4 + , + Transport::UdpListenParameters(stateParams.inetLayer).SetAddressType(Inet::kIPAddressType_IPv4).SetListenPort(mListenPort) +#endif +#if CONFIG_NETWORK_LAYER_BLE + , + Transport::BleListenParameters(stateParams.bleLayer) +#endif + )); + + if (params.imDelegate == nullptr) + { + params.imDelegate = chip::Platform::New(); + } + + stateParams.fabricTable = chip::Platform::New(); + stateParams.sessionMgr = chip::Platform::New(); + stateParams.exchangeMgr = chip::Platform::New(); + stateParams.messageCounterManager = chip::Platform::New(); + + ReturnErrorOnFailure(stateParams.fabricTable->Init(mStorageDelegate)); + ReturnErrorOnFailure(stateParams.sessionMgr->Init(stateParams.systemLayer, stateParams.transportMgr, stateParams.fabricTable, + stateParams.messageCounterManager)); + ReturnErrorOnFailure(stateParams.exchangeMgr->Init(stateParams.sessionMgr)); + ReturnErrorOnFailure(stateParams.messageCounterManager->Init(stateParams.exchangeMgr)); + + stateParams.imDelegate = params.imDelegate; + ReturnErrorOnFailure(chip::app::InteractionModelEngine::GetInstance()->Init(stateParams.exchangeMgr, stateParams.imDelegate)); + + // store the system state + mSystemState = chip::Platform::New(stateParams); + ChipLogDetail(Controller, "System State Initialized..."); + return CHIP_NO_ERROR; +} + +void DeviceControllerFactory::PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_MDNS + controllerParams.deviceAddressUpdateDelegate = params.deviceAddressUpdateDelegate; +#endif + controllerParams.operationalCredentialsDelegate = params.operationalCredentialsDelegate; + controllerParams.ephemeralKeypair = params.ephemeralKeypair; + controllerParams.controllerNOC = params.controllerNOC; + controllerParams.controllerICAC = params.controllerICAC; + controllerParams.controllerRCAC = params.controllerRCAC; + controllerParams.fabricId = params.fabricId; + + controllerParams.systemState = mSystemState; + controllerParams.storageDelegate = mStorageDelegate; + controllerParams.controllerVendorId = params.controllerVendorId; +} + +CHIP_ERROR DeviceControllerFactory::SetupController(SetupParams params, DeviceController & controller) +{ + VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(InitSystemState()); + + ControllerInitParams controllerParams; + PopulateInitParams(controllerParams, params); + + CHIP_ERROR err = controller.Init(controllerParams); + return err; +} + +CHIP_ERROR DeviceControllerFactory::SetupCommissioner(SetupParams params, DeviceCommissioner & commissioner) +{ + VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(InitSystemState()); + + CommissionerInitParams commissionerParams; + PopulateInitParams(commissionerParams, params); + commissionerParams.pairingDelegate = params.pairingDelegate; + + CHIP_ERROR err = commissioner.Init(commissionerParams); + return err; +} + +CHIP_ERROR DeviceControllerFactory::ServiceEvents() +{ + VerifyOrReturnError(mSystemState != nullptr, CHIP_ERROR_INCORRECT_STATE); + +#if CONFIG_DEVICE_LAYER + ReturnErrorOnFailure(DeviceLayer::PlatformMgr().StartEventLoopTask()); +#endif // CONFIG_DEVICE_LAYER + + return CHIP_NO_ERROR; +} + +DeviceControllerFactory::~DeviceControllerFactory() +{ + if (mSystemState != nullptr) + { + mSystemState->Release(); + chip::Platform::Delete(mSystemState); + mSystemState = nullptr; + } + mStorageDelegate = nullptr; +} + +CHIP_ERROR DeviceControllerSystemState::Shutdown() +{ + VerifyOrReturnError(mRefCount == 1, CHIP_ERROR_INCORRECT_STATE); + + ChipLogDetail(Controller, "Shutting down the System State, this will teardown the CHIP Stack"); + + // Shut down the interaction model + app::InteractionModelEngine::GetInstance()->Shutdown(); + +#if CONFIG_DEVICE_LAYER + // + // We can safely call PlatformMgr().Shutdown(), which like DeviceController::Shutdown(), + // expects to be called with external thread synchronization and will not try to acquire the + // stack lock. + // + // Actually stopping the event queue is a separable call that applications will have to sequence. + // Consumers are expected to call PlaformMgr().StopEventLoopTask() before calling + // DeviceController::Shutdown() in the CONFIG_DEVICE_LAYER configuration + // + ReturnErrorOnFailure(DeviceLayer::PlatformMgr().Shutdown()); +#endif + + // TODO(#6668): Some exchange has leak, shutting down ExchangeManager will cause a assert fail. + // if (mExchangeMgr != nullptr) + // { + // mExchangeMgr->Shutdown(); + // } + if (mSessionMgr != nullptr) + { + mSessionMgr->Shutdown(); + } + + mSystemLayer = nullptr; + mInetLayer = nullptr; + if (mTransportMgr != nullptr) + { + chip::Platform::Delete(mTransportMgr); + mTransportMgr = nullptr; + } + + if (mMessageCounterManager != nullptr) + { + chip::Platform::Delete(mMessageCounterManager); + mMessageCounterManager = nullptr; + } + + if (mExchangeMgr != nullptr) + { + chip::Platform::Delete(mExchangeMgr); + mExchangeMgr = nullptr; + } + + if (mSessionMgr != nullptr) + { + chip::Platform::Delete(mSessionMgr); + mSessionMgr = nullptr; + } + + if (mIMDelegate != nullptr) + { + chip::Platform::Delete(mIMDelegate); + mIMDelegate = nullptr; + } + + return CHIP_NO_ERROR; +} + +} // namespace Controller +} // namespace chip diff --git a/src/controller/CHIPDeviceControllerFactory.h b/src/controller/CHIPDeviceControllerFactory.h new file mode 100644 index 00000000000000..1808b66caf8813 --- /dev/null +++ b/src/controller/CHIPDeviceControllerFactory.h @@ -0,0 +1,117 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +/** + * @file + * DeviceControllerFactory is a singleton utility class that manages the + * runtime DeviceControllerSystemState and provides APIs to setup DeviceControllers + * and DeviceCommissioners. + * + * Together with the SystemState this class implicitly manages the lifecycle of the underlying + * CHIP stack. It lazily initializes the CHIPStack when setting up Controllers if the SystemState + * was previously shutdown. + */ + +#pragma once + +#include +#include + +namespace chip { + +namespace Controller { + +struct SetupParams +{ +#if CHIP_DEVICE_CONFIG_ENABLE_MDNS + DeviceAddressUpdateDelegate * deviceAddressUpdateDelegate = nullptr; +#endif + OperationalCredentialsDelegate * operationalCredentialsDelegate = nullptr; + + /* The following keypair must correspond to the public key used for generating + controllerNOC. It's used by controller to establish CASE sessions with devices */ + Crypto::P256Keypair * ephemeralKeypair = nullptr; + + /* The following certificates must be in x509 DER format */ + ByteSpan controllerNOC; + ByteSpan controllerICAC; + ByteSpan controllerRCAC; + + FabricId fabricId = kUndefinedFabricId; + + uint16_t controllerVendorId; + + // The Device Pairing Delegated used to initialize a Commissioner + DevicePairingDelegate * pairingDelegate = nullptr; +}; + +// TODO everything other than the storage delegate here should be removed. +// We're blocked because of the need to support !CHIP_DEVICE_LAYER +struct FactoryInitParams +{ + PersistentStorageDelegate * storageDelegate = nullptr; + System::Layer * systemLayer = nullptr; + Inet::InetLayer * inetLayer = nullptr; + DeviceControllerInteractionModelDelegate * imDelegate = nullptr; +#if CONFIG_NETWORK_LAYER_BLE + Ble::BleLayer * bleLayer = nullptr; +#endif + + /* The port used for operational communication to listen for and send messages over UDP/TCP. + * The default value of `0` will pick any available port. */ + uint16_t listenPort = 0; +}; + +class DeviceControllerFactory +{ +public: + static DeviceControllerFactory & GetInstance() + { + static DeviceControllerFactory instance; + return instance; + } + + CHIP_ERROR Init(FactoryInitParams params); + CHIP_ERROR SetupController(SetupParams params, DeviceController & controller); + CHIP_ERROR SetupCommissioner(SetupParams params, DeviceCommissioner & commissioner); + + // ----- IO ----- + /** + * @brief + * Start the event loop task within the CHIP stack + * @return CHIP_ERROR The return status + */ + CHIP_ERROR ServiceEvents(); + + ~DeviceControllerFactory(); + DeviceControllerFactory(DeviceControllerFactory const &) = delete; + void operator=(DeviceControllerFactory const &) = delete; + +private: + DeviceControllerFactory(){}; + void PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params); + CHIP_ERROR InitSystemState(FactoryInitParams params); + CHIP_ERROR InitSystemState(); + + uint16_t mListenPort; + PersistentStorageDelegate * mStorageDelegate = nullptr; + DeviceControllerSystemState * mSystemState = nullptr; +}; + +} // namespace Controller +} // namespace chip diff --git a/src/controller/CHIPDeviceControllerSystemState.h b/src/controller/CHIPDeviceControllerSystemState.h new file mode 100644 index 00000000000000..741b941aa53e26 --- /dev/null +++ b/src/controller/CHIPDeviceControllerSystemState.h @@ -0,0 +1,146 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +/** + * @file + * DeviceControllerSystemState is a representation of all the runtime state + * inside of CHIP that can be shared across Controllers and Commissioners. + * + * The System State assumes it's being owned by and managed by the DeviceControllerFactory. + * It will automatically shutdown the underlying CHIP Stack when its reference count + * decreases to "1". + * + */ + +#pragma once + +#include +#include +#include +#if CONFIG_DEVICE_LAYER +#include +#endif + +#if CONFIG_NETWORK_LAYER_BLE +#include +#endif + +namespace chip { + +namespace Controller { + +struct DeviceControllerSystemStateParams +{ + System::Layer * systemLayer = nullptr; + Inet::InetLayer * inetLayer = nullptr; +#if CONFIG_NETWORK_LAYER_BLE + Ble::BleLayer * bleLayer = nullptr; +#endif + DeviceTransportMgr * transportMgr = nullptr; + SessionManager * sessionMgr = nullptr; + Messaging::ExchangeManager * exchangeMgr = nullptr; + secure_channel::MessageCounterManager * messageCounterManager = nullptr; + Transport::FabricTable * fabricTable = nullptr; + DeviceControllerInteractionModelDelegate * imDelegate = nullptr; +}; + +// A representation of the internal state maintained by the DeviceControllerFactory +// and refcounted by Device Controllers. +// Expects that the creator of this object is the last one to release it. +class DeviceControllerSystemState +{ +public: + ~DeviceControllerSystemState(){}; + DeviceControllerSystemState(DeviceControllerSystemStateParams params) : + mSystemLayer(params.systemLayer), mInetLayer(params.inetLayer), mTransportMgr(params.transportMgr), + mSessionMgr(params.sessionMgr), mExchangeMgr(params.exchangeMgr), mMessageCounterManager(params.messageCounterManager), + mFabrics(params.fabricTable), mIMDelegate(params.imDelegate) + { +#if CONFIG_NETWORK_LAYER_BLE + mBleLayer = params.bleLayer; +#endif + }; + + DeviceControllerSystemState * Retain() + { + if (mRefCount == std::numeric_limits::max()) + { + abort(); + } + ++mRefCount; + return this; + }; + + void Release() + { + if (mRefCount == 0) + { + abort(); + } + + mRefCount--; + if (mRefCount == 1) + { + // Only the factory should have a ref now, shutdown and release the underlying objects + Shutdown(); + } + else if (mRefCount == 0) + { + this->~DeviceControllerSystemState(); + } + }; + bool IsInitialized() + { + return mSystemLayer != nullptr && mInetLayer != nullptr && mTransportMgr != nullptr && mSessionMgr != nullptr && + mExchangeMgr != nullptr && mMessageCounterManager != nullptr && mFabrics != nullptr; + }; + + System::Layer * SystemLayer() { return mSystemLayer; }; + Inet::InetLayer * InetLayer() { return mInetLayer; }; + DeviceTransportMgr * TransportMgr() { return mTransportMgr; }; + SessionManager * SessionMgr() { return mSessionMgr; }; + Messaging::ExchangeManager * ExchangeMgr() { return mExchangeMgr; } + secure_channel::MessageCounterManager * MessageCounterManager() { return mMessageCounterManager; }; + Transport::FabricTable * Fabrics() { return mFabrics; }; + DeviceControllerInteractionModelDelegate * IMDelegate() { return mIMDelegate; } +#if CONFIG_NETWORK_LAYER_BLE + Ble::BleLayer * BleLayer() { return mBleLayer; }; +#endif + +private: + DeviceControllerSystemState(){}; + + System::Layer * mSystemLayer = nullptr; + Inet::InetLayer * mInetLayer = nullptr; +#if CONFIG_NETWORK_LAYER_BLE + Ble::BleLayer * mBleLayer = nullptr; +#endif + DeviceTransportMgr * mTransportMgr = nullptr; + SessionManager * mSessionMgr = nullptr; + Messaging::ExchangeManager * mExchangeMgr = nullptr; + secure_channel::MessageCounterManager * mMessageCounterManager = nullptr; + Transport::FabricTable * mFabrics = nullptr; + DeviceControllerInteractionModelDelegate * mIMDelegate = nullptr; + + std::atomic mRefCount{ 1 }; + + CHIP_ERROR Shutdown(); +}; + +} // namespace Controller +} // namespace chip diff --git a/src/controller/java/AndroidDeviceControllerWrapper.cpp b/src/controller/java/AndroidDeviceControllerWrapper.cpp index 81e89ec5d31425..2c9ec3a0b3b41d 100644 --- a/src/controller/java/AndroidDeviceControllerWrapper.cpp +++ b/src/controller/java/AndroidDeviceControllerWrapper.cpp @@ -25,6 +25,7 @@ #include "JniReferences.h" #include +#include #include #include #include @@ -205,19 +206,20 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(Jav std::unique_ptr wrapper(new AndroidDeviceControllerWrapper(std::move(controller), stackLock)); wrapper->SetJavaObjectRef(vm, deviceControllerObj); - wrapper->Controller()->SetUdpListenPort(CHIP_PORT + 1); // Initialize device attestation verifier SetDeviceAttestationVerifier(Examples::GetExampleDACVerifier()); - chip::Controller::CommissionerInitParams initParams; + chip::Controller::FactoryInitParams initParams; + chip::Controller::SetupParams setupParams; - initParams.storageDelegate = wrapper.get(); - initParams.pairingDelegate = wrapper.get(); - initParams.operationalCredentialsDelegate = wrapper.get(); - initParams.systemLayer = systemLayer; - initParams.inetLayer = inetLayer; - initParams.bleLayer = GetJNIBleLayer(); + initParams.storageDelegate = wrapper.get(); + initParams.systemLayer = systemLayer; + initParams.inetLayer = inetLayer; + initParams.bleLayer = GetJNIBleLayer(); + initParams.listenPort = CHIP_PORT + 1; + setupParams.pairingDelegate = wrapper.get(); + setupParams.operationalCredentialsDelegate = wrapper.get(); wrapper->InitializeOperationalCredentialsIssuer(); @@ -252,13 +254,17 @@ AndroidDeviceControllerWrapper * AndroidDeviceControllerWrapper::AllocateNew(Jav return nullptr; } - initParams.ephemeralKeypair = &ephemeralKey; - initParams.controllerRCAC = rcacSpan; - initParams.controllerICAC = icacSpan; - initParams.controllerNOC = nocSpan; - - *errInfoOnFailure = wrapper->Controller()->Init(initParams); + setupParams.ephemeralKeypair = &ephemeralKey; + setupParams.controllerRCAC = rcacSpan; + setupParams.controllerICAC = icacSpan; + setupParams.controllerNOC = nocSpan; + *errInfoOnFailure = DeviceControllerFactory::GetInstance().Init(initParams); + if (*errInfoOnFailure != CHIP_NO_ERROR) + { + return nullptr; + } + *errInfoOnFailure = DeviceControllerFactory::GetInstance().SetupCommissioner(setupParams, *wrapper->Controller()); if (*errInfoOnFailure != CHIP_NO_ERROR) { return nullptr; diff --git a/src/controller/python/ChipDeviceController-ScriptBinding.cpp b/src/controller/python/ChipDeviceController-ScriptBinding.cpp index 69053b810e73cb..fc99cc88ac09a6 100644 --- a/src/controller/python/ChipDeviceController-ScriptBinding.cpp +++ b/src/controller/python/ChipDeviceController-ScriptBinding.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -205,19 +206,21 @@ ChipError::StorageType pychip_DeviceController_NewDeviceController(chip::Control nocSpan); VerifyOrReturnError(err == CHIP_NO_ERROR, err.AsInteger()); - CommissionerInitParams initParams; - initParams.storageDelegate = &sStorageDelegate; - initParams.mDeviceAddressUpdateDelegate = &sDeviceAddressUpdateDelegate; + FactoryInitParams factoryParams; + factoryParams.storageDelegate = &sStorageDelegate; + factoryParams.imDelegate = &PythonInteractionModelDelegate::Instance(); + + SetupParams initParams; + initParams.deviceAddressUpdateDelegate = &sDeviceAddressUpdateDelegate; initParams.pairingDelegate = &sPairingDelegate; initParams.operationalCredentialsDelegate = &sOperationalCredentialsIssuer; - initParams.imDelegate = &PythonInteractionModelDelegate::Instance(); initParams.ephemeralKeypair = &ephemeralKey; initParams.controllerRCAC = rcacSpan; initParams.controllerICAC = icacSpan; initParams.controllerNOC = nocSpan; - (*outDevCtrl)->SetUdpListenPort(0); - err = (*outDevCtrl)->Init(initParams); + ReturnErrorOnFailure(DeviceControllerFactory::GetInstance().Init(factoryParams).AsInteger()); + err = DeviceControllerFactory::GetInstance().SetupCommissioner(initParams, **outDevCtrl); VerifyOrReturnError(err == CHIP_NO_ERROR, err.AsInteger()); #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY chip::app::MdnsServer::Instance().StartServer(chip::Mdns::CommissioningMode::kDisabled); diff --git a/src/controller/python/chip/internal/CommissionerImpl.cpp b/src/controller/python/chip/internal/CommissionerImpl.cpp index 081abda21c00d5..ac71588061cc8a 100644 --- a/src/controller/python/chip/internal/CommissionerImpl.cpp +++ b/src/controller/python/chip/internal/CommissionerImpl.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -29,6 +30,8 @@ #include "ChipThreadWork.h" +using DeviceControllerFactory = chip::Controller::DeviceControllerFactory; + namespace { class ServerStorageDelegate : public chip::PersistentStorageDelegate @@ -97,12 +100,11 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N // System and Inet layers explicitly passed to indicate that the CHIP stack is // already assumed initialized - chip::Controller::CommissionerInitParams params; + chip::Controller::SetupParams commissionerParams; + chip::Controller::FactoryInitParams factoryParams; - params.storageDelegate = &gServerStorage; - params.systemLayer = &chip::DeviceLayer::SystemLayer(); - params.inetLayer = &chip::DeviceLayer::InetLayer; - params.pairingDelegate = &gPairingDelegate; + commissionerParams.pairingDelegate = &gPairingDelegate; + factoryParams.storageDelegate = &gServerStorage; chip::Platform::ScopedMemoryBuffer noc; chip::Platform::ScopedMemoryBuffer icac; @@ -134,13 +136,14 @@ extern "C" chip::Controller::DeviceCommissioner * pychip_internal_Commissioner_N icacSpan, nocSpan); SuccessOrExit(err); - params.operationalCredentialsDelegate = &gOperationalCredentialsIssuer; - params.ephemeralKeypair = &ephemeralKey; - params.controllerRCAC = rcacSpan; - params.controllerICAC = icacSpan; - params.controllerNOC = nocSpan; + commissionerParams.operationalCredentialsDelegate = &gOperationalCredentialsIssuer; + commissionerParams.ephemeralKeypair = &ephemeralKey; + commissionerParams.controllerRCAC = rcacSpan; + commissionerParams.controllerICAC = icacSpan; + commissionerParams.controllerNOC = nocSpan; - err = result->Init(params); + SuccessOrExit(DeviceControllerFactory::GetInstance().Init(factoryParams)); + err = DeviceControllerFactory::GetInstance().SetupCommissioner(commissionerParams, *result); } exit: ChipLogProgress(Controller, "Commissioner initialization status: %s", chip::ErrorStr(err)); diff --git a/src/controller/tests/TestDevice.cpp b/src/controller/tests/TestDevice.cpp index ff1156c8884c1b..8b9fdaca7101d6 100644 --- a/src/controller/tests/TestDevice.cpp +++ b/src/controller/tests/TestDevice.cpp @@ -91,7 +91,7 @@ void TestDevice_EstablishSessionDirectly(nlTestSuite * inSuite, void * inContext Inet::IPAddress mockAddr; Inet::IPAddress::FromString("127.0.0.1", mockAddr); PeerAddress addr = PeerAddress::UDP(mockAddr, CHIP_PORT); - device.Init(params, CHIP_PORT, mockNodeId, addr, mockFabricIndex); + device.Init(params, mockNodeId, addr, mockFabricIndex); device.OperationalCertProvisioned(); NL_TEST_ASSERT(inSuite, device.EstablishConnectivity(nullptr, nullptr) == CHIP_NO_ERROR); diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index b6ea262bb49e36..ab8b08a882a2dc 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -65,6 +66,7 @@ @interface CHIPDeviceController () @property (readonly) uint16_t listenPort; @end +// TODO Replace Shared Controller with a Controller Factory Singleton @implementation CHIPDeviceController + (CHIPDeviceController *)sharedController @@ -171,23 +173,21 @@ - (BOOL)startup:(_Nullable id)storageDelegate return; } + chip::Controller::FactoryInitParams params; + chip::Controller::SetupParams commissionerParams; + if (_listenPort) { - errorCode = _cppCommissioner->SetUdpListenPort(_listenPort); - if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCommissionerInit]) { - return; - } + params.listenPort = _listenPort; } // Initialize device attestation verifier chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::Examples::GetExampleDACVerifier()); - chip::Controller::CommissionerInitParams params; - params.storageDelegate = _persistentStorageDelegateBridge; - params.mDeviceAddressUpdateDelegate = _pairingDelegateBridge; - params.pairingDelegate = _pairingDelegateBridge; + commissionerParams.deviceAddressUpdateDelegate = _pairingDelegateBridge; + commissionerParams.pairingDelegate = _pairingDelegateBridge; - params.operationalCredentialsDelegate = _operationalCredentialsDelegate; + commissionerParams.operationalCredentialsDelegate = _operationalCredentialsDelegate; chip::Crypto::P256Keypair ephemeralKey; errorCode = ephemeralKey.Initialize(); @@ -209,13 +209,20 @@ - (BOOL)startup:(_Nullable id)storageDelegate return; } - params.ephemeralKeypair = &ephemeralKey; - params.controllerRCAC = rcac; - params.controllerICAC = icac; - params.controllerNOC = noc; - params.controllerVendorId = vendorId; + commissionerParams.ephemeralKeypair = &ephemeralKey; + commissionerParams.controllerRCAC = rcac; + commissionerParams.controllerICAC = icac; + commissionerParams.controllerNOC = noc; + commissionerParams.controllerVendorId = vendorId; + + // TODO Replace Shared Controller with a Controller Factory Singleton + auto & factory = chip::Controller::DeviceControllerFactory::GetInstance(); + errorCode = factory.Init(params); + if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCommissionerInit]) { + return; + } - errorCode = _cppCommissioner->Init(params); + errorCode = factory.SetupCommissioner(commissionerParams, *_cppCommissioner); if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCommissionerInit]) { return; } diff --git a/src/messaging/ExchangeMgr.h b/src/messaging/ExchangeMgr.h index eef0f1d446e8e4..67aadccb45a860 100644 --- a/src/messaging/ExchangeMgr.h +++ b/src/messaging/ExchangeMgr.h @@ -184,6 +184,8 @@ class DLL_EXPORT ExchangeManager : public SessionManagerDelegate */ void CloseAllContextsForDelegate(const ExchangeDelegate * delegate); + // TODO Store more than one delegate and add API to query delegates to check if incoming messages are for them. + // Do the same for the UMHs as well void SetDelegate(ExchangeMgrDelegate * delegate) { mDelegate = delegate; } SessionManager * GetSessionManager() const { return mSessionManager; }