|  | /* | 
|  | * | 
|  | *    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 <controller/CHIPDeviceController.h> | 
|  | #include <controller/CHIPDeviceControllerSystemState.h> | 
|  | #include <credentials/GroupDataProvider.h> | 
|  | #include <credentials/OperationalCertificateStore.h> | 
|  | #include <credentials/attestation_verifier/DeviceAttestationVerifier.h> | 
|  |  | 
|  | namespace chip { | 
|  |  | 
|  | namespace Controller { | 
|  |  | 
|  | struct SetupParams | 
|  | { | 
|  | 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 * operationalKeypair = nullptr; | 
|  |  | 
|  | /** | 
|  | * Controls whether or not the operationalKeypair should be owned by the | 
|  | * caller.  By default, this is false, but if the keypair cannot be | 
|  | * serialized, then setting this to true will allow the caller to manage | 
|  | * this keypair's lifecycle. | 
|  | */ | 
|  | bool hasExternallyOwnedOperationalKeypair = false; | 
|  |  | 
|  | /* The following certificates must be in x509 DER format */ | 
|  | ByteSpan controllerNOC; | 
|  | ByteSpan controllerICAC; | 
|  | ByteSpan controllerRCAC; | 
|  |  | 
|  | // | 
|  | // This must be set to a valid, operational VendorId value associated with | 
|  | // the controller/commissioner. | 
|  | // | 
|  | chip::VendorId controllerVendorId = VendorId::Unspecified; | 
|  |  | 
|  | // The Device Pairing Delegated used to initialize a Commissioner | 
|  | DevicePairingDelegate * pairingDelegate = nullptr; | 
|  |  | 
|  | /** | 
|  | * Controls whether we permit multiple DeviceController instances to exist | 
|  | * on the same logical fabric (identified by the tuple of the fabric's | 
|  | * root public key + fabric id). | 
|  | * | 
|  | * Each controller instance will be associated with its own FabricIndex. | 
|  | * This pivots the FabricTable to tracking identities instead of fabrics, | 
|  | * represented by FabricInfo instances that can have colliding logical fabrics. | 
|  | * | 
|  | */ | 
|  | bool permitMultiControllerFabrics = false; | 
|  |  | 
|  | // | 
|  | // Controls enabling server cluster interactions on a controller. This in turn | 
|  | // causes the following to get enabled: | 
|  | // | 
|  | //  - CASEServer to listen for unsolicited Sigma1 messages. | 
|  | //  - Advertisement of active controller operational identities. | 
|  | // | 
|  | bool enableServerInteractions = false; | 
|  |  | 
|  | Credentials::DeviceAttestationVerifier * deviceAttestationVerifier = nullptr; | 
|  | CommissioningDelegate * defaultCommissioner                        = nullptr; | 
|  | }; | 
|  |  | 
|  | // TODO everything other than the fabric storage, group data provider, OperationalKeystore | 
|  | // and OperationalCertificateStore here should be removed. We're blocked because of the | 
|  | // need to support !CHIP_DEVICE_LAYER | 
|  | struct FactoryInitParams | 
|  | { | 
|  | System::Layer * systemLayer                                        = nullptr; | 
|  | PersistentStorageDelegate * fabricIndependentStorage               = nullptr; | 
|  | Credentials::CertificateValidityPolicy * certificateValidityPolicy = nullptr; | 
|  | Credentials::GroupDataProvider * groupDataProvider                 = nullptr; | 
|  | Inet::EndPointManager<Inet::TCPEndPoint> * tcpEndPointManager      = nullptr; | 
|  | Inet::EndPointManager<Inet::UDPEndPoint> * udpEndPointManager      = nullptr; | 
|  | FabricTable * fabricTable                                          = nullptr; | 
|  | OperationalKeystore * operationalKeystore                          = nullptr; | 
|  | Credentials::OperationalCertificateStore * opCertStore             = nullptr; | 
|  | #if CONFIG_NETWORK_LAYER_BLE | 
|  | Ble::BleLayer * bleLayer = nullptr; | 
|  | #endif | 
|  |  | 
|  | // | 
|  | // Controls enabling server cluster interactions on a controller. This in turn | 
|  | // causes the following to get enabled: | 
|  | // | 
|  | //  - Advertisement of active controller operational identities. | 
|  | // | 
|  | bool enableServerInteractions = false; | 
|  |  | 
|  | /* 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); | 
|  |  | 
|  | // Shuts down matter and frees the system state. | 
|  | // | 
|  | // Must not be called while any controllers are alive. | 
|  | void Shutdown(); | 
|  |  | 
|  | 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; | 
|  |  | 
|  | // | 
|  | // Some clients do not prefer a complete shutdown of the stack being initiated if | 
|  | // all device controllers have ceased to exist. To avoid that, this method has been | 
|  | // created to permit retention of the underlying system state. | 
|  | // | 
|  | // NB: The system state will still be freed in Shutdown() regardless of this call. | 
|  | void RetainSystemState() { (void) mSystemState->Retain(); } | 
|  |  | 
|  | // | 
|  | // To initiate shutdown of the stack upon termination of all resident controllers in the | 
|  | // system, invoke this method to decrement the refcount on the system state and consequently, | 
|  | // shut-down the stack. | 
|  | // | 
|  | // This should only be invoked if a matching call to RetainSystemState() was called prior. | 
|  | // | 
|  | void ReleaseSystemState() { mSystemState->Release(); } | 
|  |  | 
|  | // | 
|  | // Retrieve a read-only pointer to the system state object that contains pointers to key stack | 
|  | // singletons. If the pointer is null, it indicates that the DeviceControllerFactory has yet to | 
|  | // be initialized properly, or has already been shut-down. | 
|  | // | 
|  | // This pointer ceases to be valid after a call to Shutdown has been made, or if all active | 
|  | // DeviceController instances have gone to 0. Consequently, care has to be taken to correctly | 
|  | // sequence the shutting down of active controllers with any entity that interacts with objects | 
|  | // present in the system state object. If de-coupling is desired, RetainSystemState and | 
|  | // ReleaseSystemState can be used to avoid this. | 
|  | // | 
|  | const DeviceControllerSystemState * GetSystemState() const { return mSystemState; } | 
|  |  | 
|  | class ControllerFabricDelegate final : public chip::FabricTable::Delegate | 
|  | { | 
|  | public: | 
|  | CHIP_ERROR Init(SessionResumptionStorage * sessionResumptionStorage, Credentials::GroupDataProvider * groupDataProvider) | 
|  | { | 
|  | VerifyOrReturnError(sessionResumptionStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT); | 
|  | VerifyOrReturnError(groupDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT); | 
|  |  | 
|  | mSessionResumptionStorage = sessionResumptionStorage; | 
|  | mGroupDataProvider        = groupDataProvider; | 
|  | return CHIP_NO_ERROR; | 
|  | }; | 
|  |  | 
|  | void OnFabricRemoved(const chip::FabricTable & fabricTable, FabricIndex fabricIndex) override | 
|  | { | 
|  | (void) fabricTable; | 
|  | if (mGroupDataProvider != nullptr) | 
|  | { | 
|  | mGroupDataProvider->RemoveFabric(fabricIndex); | 
|  | } | 
|  | ClearCASEResumptionStateOnFabricChange(fabricIndex); | 
|  | }; | 
|  |  | 
|  | void OnFabricUpdated(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override | 
|  | { | 
|  | (void) fabricTable; | 
|  | ClearCASEResumptionStateOnFabricChange(fabricIndex); | 
|  | } | 
|  |  | 
|  | private: | 
|  | void ClearCASEResumptionStateOnFabricChange(chip::FabricIndex fabricIndex) | 
|  | { | 
|  | VerifyOrReturn(mSessionResumptionStorage != nullptr); | 
|  | CHIP_ERROR err = mSessionResumptionStorage->DeleteAll(fabricIndex); | 
|  | if (err != CHIP_NO_ERROR) | 
|  | { | 
|  | ChipLogError(Controller, | 
|  | "Warning, failed to delete session resumption state for fabric index 0x%x: %" CHIP_ERROR_FORMAT, | 
|  | static_cast<unsigned>(fabricIndex), err.Format()); | 
|  | } | 
|  | } | 
|  |  | 
|  | Credentials::GroupDataProvider * mGroupDataProvider  = nullptr; | 
|  | SessionResumptionStorage * mSessionResumptionStorage = nullptr; | 
|  | }; | 
|  |  | 
|  | private: | 
|  | DeviceControllerFactory() {} | 
|  | void PopulateInitParams(ControllerInitParams & controllerParams, const SetupParams & params); | 
|  | CHIP_ERROR InitSystemState(FactoryInitParams params); | 
|  | CHIP_ERROR InitSystemState(); | 
|  |  | 
|  | uint16_t mListenPort; | 
|  | DeviceControllerSystemState * mSystemState              = nullptr; | 
|  | PersistentStorageDelegate * mFabricIndependentStorage   = nullptr; | 
|  | Crypto::OperationalKeystore * mOperationalKeystore      = nullptr; | 
|  | Credentials::OperationalCertificateStore * mOpCertStore = nullptr; | 
|  | bool mEnableServerInteractions                          = false; | 
|  | }; | 
|  |  | 
|  | } // namespace Controller | 
|  | } // namespace chip |