| /* | 
 |  * | 
 |  *    Copyright (c) 2020-2022 Project CHIP Authors | 
 |  *    Copyright (c) 2013-2017 Nest Labs, Inc. | 
 |  *    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 | 
 |  *      Declaration of CHIP Device Controller, a common class | 
 |  *      that implements connecting and messaging and will later | 
 |  *      be expanded to support discovery, pairing and | 
 |  *      provisioning of CHIP  devices. | 
 |  * | 
 |  */ | 
 |  | 
 | #pragma once | 
 |  | 
 | #include <app/CASEClientPool.h> | 
 | #include <app/CASESessionManager.h> | 
 | #include <app/ClusterStateCache.h> | 
 | #include <app/OperationalSessionSetup.h> | 
 | #include <app/OperationalSessionSetupPool.h> | 
 | #include <controller/AbstractDnssdDiscoveryController.h> | 
 | #include <controller/AutoCommissioner.h> | 
 | #include <controller/CHIPCluster.h> | 
 | #include <controller/CHIPDeviceControllerSystemState.h> | 
 | #include <controller/CommissioneeDeviceProxy.h> | 
 | #include <controller/CommissioningDelegate.h> | 
 | #include <controller/DevicePairingDelegate.h> | 
 | #include <controller/OperationalCredentialsDelegate.h> | 
 | #include <controller/SetUpCodePairer.h> | 
 | #include <credentials/FabricTable.h> | 
 | #include <credentials/attestation_verifier/DeviceAttestationDelegate.h> | 
 | #include <credentials/attestation_verifier/DeviceAttestationVerifier.h> | 
 | #include <inet/InetInterface.h> | 
 | #include <lib/core/CHIPConfig.h> | 
 | #include <lib/core/CHIPCore.h> | 
 | #include <lib/core/CHIPPersistentStorageDelegate.h> | 
 | #include <lib/core/DataModelTypes.h> | 
 | #include <lib/core/TLV.h> | 
 | #include <lib/support/DLLUtil.h> | 
 | #include <lib/support/Pool.h> | 
 | #include <lib/support/SafeInt.h> | 
 | #include <lib/support/SerializableIntegerSet.h> | 
 | #include <lib/support/Span.h> | 
 | #include <lib/support/ThreadOperationalDataset.h> | 
 | #include <messaging/ExchangeMgr.h> | 
 | #include <protocols/secure_channel/MessageCounterManager.h> | 
 | #include <protocols/secure_channel/RendezvousParameters.h> | 
 | #include <protocols/user_directed_commissioning/UserDirectedCommissioning.h> | 
 | #include <system/SystemClock.h> | 
 | #include <transport/SessionManager.h> | 
 | #include <transport/TransportMgr.h> | 
 | #include <transport/raw/UDP.h> | 
 |  | 
 | #if CONFIG_DEVICE_LAYER | 
 | #include <platform/CHIPDeviceLayer.h> | 
 | #endif | 
 |  | 
 | #if CONFIG_NETWORK_LAYER_BLE | 
 | #include <ble/BleLayer.h> | 
 | #endif | 
 | #include <controller/DeviceDiscoveryDelegate.h> | 
 |  | 
 | namespace chip { | 
 |  | 
 | namespace Controller { | 
 |  | 
 | using namespace chip::Protocols::UserDirectedCommissioning; | 
 |  | 
 | constexpr uint16_t kNumMaxActiveDevices = CHIP_CONFIG_CONTROLLER_MAX_ACTIVE_DEVICES; | 
 |  | 
 | // Raw functions for cluster callbacks | 
 | void OnBasicFailure(void * context, CHIP_ERROR err); | 
 |  | 
 | struct ControllerInitParams | 
 | { | 
 |     DeviceControllerSystemState * systemState                       = nullptr; | 
 |     DeviceDiscoveryDelegate * deviceDiscoveryDelegate               = nullptr; | 
 |     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; | 
 |  | 
 |     /** | 
 |      * 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: | 
 |     // | 
 |     //  - Advertisement of active controller operational identities. | 
 |     // | 
 |     bool enableServerInteractions = false; | 
 |  | 
 |     /** | 
 |      * Controls whether shutdown of the controller removes the corresponding | 
 |      * entry from the fabric table.  For now the removal is just from the | 
 |      * in-memory table, not from storage, which means that after controller | 
 |      * shutdown the storage and the in-memory fabric table will be out of sync. | 
 |      * This is acceptable for implementations that don't actually store any of | 
 |      * the fabric table information, but if someone wants a true removal at some | 
 |      * point another option will need to be added here. | 
 |      */ | 
 |     bool removeFromFabricTableOnShutdown = true; | 
 |  | 
 |     chip::VendorId controllerVendorId; | 
 | }; | 
 |  | 
 | struct CommissionerInitParams : public ControllerInitParams | 
 | { | 
 |     DevicePairingDelegate * pairingDelegate     = nullptr; | 
 |     CommissioningDelegate * defaultCommissioner = nullptr; | 
 |     // Device attestation verifier instance for the commissioning. | 
 |     // If null, the globally set attestation verifier (e.g. from GetDeviceAttestationVerifier() | 
 |     // singleton) will be used. | 
 |     Credentials::DeviceAttestationVerifier * deviceAttestationVerifier = nullptr; | 
 | }; | 
 |  | 
 | /** | 
 |  * @brief | 
 |  *   Controller applications can use this class to communicate with already paired CHIP devices. The | 
 |  *   application is required to provide access to the persistent storage, where the paired device information | 
 |  *   is stored. This object of this class can be initialized with the data from the storage (List of devices, | 
 |  *   and device pairing information for individual devices). Alternatively, this class can retrieve the | 
 |  *   relevant information when the application tries to communicate with the device | 
 |  */ | 
 | class DLL_EXPORT DeviceController : public AbstractDnssdDiscoveryController | 
 | { | 
 | public: | 
 |     DeviceController(); | 
 |     ~DeviceController() override {} | 
 |  | 
 |     CHIP_ERROR Init(ControllerInitParams params); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *  Tears down the entirety of the stack, including destructing key objects in the system. | 
 |      *  This expects to be called with external thread synchronization, and will not internally | 
 |      *  grab the CHIP stack lock. | 
 |      * | 
 |      *  This will also not stop the CHIP event queue / thread (if one exists).  Consumers are expected to | 
 |      *  ensure this happened before calling this method. | 
 |      */ | 
 |     virtual void Shutdown(); | 
 |  | 
 |     SessionManager * SessionMgr() | 
 |     { | 
 |         if (mSystemState) | 
 |         { | 
 |             return mSystemState->SessionMgr(); | 
 |         } | 
 |  | 
 |         return nullptr; | 
 |     } | 
 |  | 
 |     CHIP_ERROR GetPeerAddressAndPort(NodeId peerId, Inet::IPAddress & addr, uint16_t & port); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Looks up the PeerAddress for an established CASE session. | 
 |      * | 
 |      * @param[in] nodeId the NodeId of the target. | 
 |      * @param[out] addr the PeerAddress to be filled on success | 
 |      * | 
 |      * @return CHIP_ERROR CHIP_ERROR_NOT_CONNECTED if no CASE session exists for the device | 
 |      */ | 
 |     CHIP_ERROR GetPeerAddress(NodeId nodeId, Transport::PeerAddress & addr); | 
 |  | 
 |     ScopedNodeId GetPeerScopedId(NodeId nodeId) { return ScopedNodeId(nodeId, GetFabricIndex()); } | 
 |  | 
 |     /** | 
 |      * This function finds the device corresponding to deviceId, and establishes | 
 |      * a CASE session with it. | 
 |      * | 
 |      * Once the CASE session is successfully established the `onConnectedDevice` | 
 |      * callback is called. This can happen before GetConnectedDevice returns if | 
 |      * there is an existing CASE session. | 
 |      * | 
 |      * If a CASE sessions fails to be established, the `onError` callback will | 
 |      * be called.  This can also happen before GetConnectedDevice returns. | 
 |      * | 
 |      * An error return from this function means that neither callback has been | 
 |      * called yet, and neither callback will be called in the future. | 
 |      */ | 
 |     CHIP_ERROR GetConnectedDevice(NodeId peerNodeId, Callback::Callback<OnDeviceConnected> * onConnection, | 
 |                                   chip::Callback::Callback<OnDeviceConnectionFailure> * onFailure) | 
 |     { | 
 |         VerifyOrReturnError(mState == State::Initialized, CHIP_ERROR_INCORRECT_STATE); | 
 |         mSystemState->CASESessionMgr()->FindOrEstablishSession(ScopedNodeId(peerNodeId, GetFabricIndex()), onConnection, onFailure); | 
 |         return CHIP_NO_ERROR; | 
 |     } | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Compute a PASE verifier and passcode ID for the desired setup pincode. | 
 |      * | 
 |      *   This can be used to open a commissioning window on the device for | 
 |      *   additional administrator commissioning. | 
 |      * | 
 |      * @param[in] iterations      The number of iterations to use when generating the verifier | 
 |      * @param[in] setupPincode    The desired PIN code to use | 
 |      * @param[in] salt            The 16-byte salt for verifier computation | 
 |      * @param[out] outVerifier    The Spake2pVerifier to be populated on success | 
 |      * | 
 |      * @return CHIP_ERROR         CHIP_NO_ERROR on success, or corresponding error | 
 |      */ | 
 |     CHIP_ERROR ComputePASEVerifier(uint32_t iterations, uint32_t setupPincode, const ByteSpan & salt, | 
 |                                    Spake2pVerifier & outVerifier); | 
 |  | 
 |     void RegisterDeviceDiscoveryDelegate(DeviceDiscoveryDelegate * delegate) { mDeviceDiscoveryDelegate = delegate; } | 
 |  | 
 |     /** | 
 |      * @brief Get the Compressed Fabric ID assigned to the device. | 
 |      */ | 
 |     uint64_t GetCompressedFabricId() const | 
 |     { | 
 |         const auto * fabricInfo = GetFabricInfo(); | 
 |         return (fabricInfo != nullptr) ? static_cast<uint64_t>(fabricInfo->GetCompressedFabricId()) : kUndefinedCompressedFabricId; | 
 |     } | 
 |  | 
 |     /** | 
 |      * @brief Get the Compressed Fabric Id as a big-endian 64 bit octet string. | 
 |      * | 
 |      * Output span is resized to 8 bytes on success if it was larger. | 
 |      * | 
 |      * @param outBytes span to contain the compressed fabric ID, must be at least 8 bytes long | 
 |      * @return CHIP_ERROR_BUFFER_TOO_SMALL if `outBytes` is too small, CHIP_ERROR_INVALID_FABRIC_INDEX | 
 |      *         if the controller is somehow not associated with a fabric (internal error!) or | 
 |      *         CHIP_NO_ERROR on success. | 
 |      */ | 
 |     CHIP_ERROR GetCompressedFabricIdBytes(MutableByteSpan & outBytes) const; | 
 |  | 
 |     /** | 
 |      * @brief Get the raw Fabric ID assigned to the device. | 
 |      */ | 
 |     uint64_t GetFabricId() const | 
 |     { | 
 |         const auto * fabricInfo = GetFabricInfo(); | 
 |         return (fabricInfo != nullptr) ? static_cast<uint64_t>(fabricInfo->GetFabricId()) : kUndefinedFabricId; | 
 |     } | 
 |  | 
 |     /** | 
 |      * @brief Get the Node ID of this instance. | 
 |      */ | 
 |     NodeId GetNodeId() const | 
 |     { | 
 |         const auto * fabricInfo = GetFabricInfo(); | 
 |         return (fabricInfo != nullptr) ? static_cast<uint64_t>(fabricInfo->GetNodeId()) : kUndefinedNodeId; | 
 |     } | 
 |  | 
 |     /** | 
 |      * @brief Get the root public key for the fabric | 
 |      * | 
 |      * @param outRootPublicKey reference to public key object that gets updated on success. | 
 |      * | 
 |      * @return CHIP_NO_ERROR on success, CHIP_ERROR_INCORRECT_STATE if fabric table is unset, or another internal error | 
 |      *         on storage access failure. | 
 |      */ | 
 |     CHIP_ERROR GetRootPublicKey(Crypto::P256PublicKey & outRootPublicKey) const; | 
 |  | 
 |     FabricIndex GetFabricIndex() const { return mFabricIndex; } | 
 |  | 
 |     const FabricTable * GetFabricTable() const | 
 |     { | 
 |         if (mSystemState == nullptr) | 
 |         { | 
 |             return nullptr; | 
 |         } | 
 |         return mSystemState->Fabrics(); | 
 |     } | 
 |  | 
 |     OperationalCredentialsDelegate * GetOperationalCredentialsDelegate() { return mOperationalCredentialsDelegate; } | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Reconfigures a new set of operational credentials to be used with this | 
 |      *   controller given ControllerInitParams state. | 
 |      * | 
 |      * WARNING: This is a low-level method that should only be called directly | 
 |      *          if you know exactly how this will interact with controller state, | 
 |      *          since there are several integrations that do this call for you. | 
 |      *          It can be used for fine-grained dependency injection of a controller's | 
 |      *          NOC and operational keypair. | 
 |      */ | 
 |     CHIP_ERROR InitControllerNOCChain(const ControllerInitParams & params); | 
 |  | 
 | protected: | 
 |     enum class State | 
 |     { | 
 |         NotInitialized, | 
 |         Initialized | 
 |     }; | 
 |  | 
 |     // This is not public to avoid users of DeviceController relying on "innards" access to | 
 |     // the raw fabric table. Everything needed should be available with getters on DeviceController. | 
 |     const FabricInfo * GetFabricInfo() const | 
 |     { | 
 |         VerifyOrReturnError((mState == State::Initialized) && (mFabricIndex != kUndefinedFabricIndex), nullptr); | 
 |         VerifyOrReturnError(GetFabricTable() != nullptr, nullptr); | 
 |  | 
 |         return GetFabricTable()->FindFabricWithIndex(mFabricIndex); | 
 |     } | 
 |  | 
 |     State mState; | 
 |  | 
 |     FabricIndex mFabricIndex = kUndefinedFabricIndex; | 
 |  | 
 |     bool mRemoveFromFabricTableOnShutdown = true; | 
 |  | 
 |     // TODO(cecille): Make this configuarable. | 
 |     static constexpr int kMaxCommissionableNodes = 10; | 
 |     Dnssd::DiscoveredNodeData mCommissionableNodes[kMaxCommissionableNodes]; | 
 |     DeviceControllerSystemState * mSystemState = nullptr; | 
 |  | 
 |     ControllerDeviceInitParams GetControllerDeviceInitParams(); | 
 |  | 
 |     OperationalCredentialsDelegate * mOperationalCredentialsDelegate; | 
 |  | 
 |     chip::VendorId mVendorId; | 
 |  | 
 |     DiscoveredNodeList GetDiscoveredNodes() override { return DiscoveredNodeList(mCommissionableNodes); } | 
 | }; | 
 |  | 
 | #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY | 
 | using UdcTransportMgr = TransportMgr<Transport::UDP /* IPv6 */ | 
 | #if INET_CONFIG_ENABLE_IPV4 | 
 |                                      , | 
 |                                      Transport::UDP /* IPv4 */ | 
 | #endif | 
 |                                      >; | 
 | #endif | 
 |  | 
 | /** | 
 |  * @brief Callback prototype for ExtendArmFailSafe command. | 
 |  */ | 
 | typedef void (*OnExtendFailsafeSuccess)( | 
 |     void * context, const app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data); | 
 | typedef void (*OnExtendFailsafeFailure)(void * context, CHIP_ERROR error); | 
 |  | 
 | /** | 
 |  * @brief | 
 |  *   The commissioner applications can use this class to pair new/unpaired CHIP devices. The application is | 
 |  *   required to provide write access to the persistent storage, where the paired device information | 
 |  *   will be stored. | 
 |  */ | 
 | class DLL_EXPORT DeviceCommissioner : public DeviceController, | 
 | #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable | 
 |                                       public Protocols::UserDirectedCommissioning::InstanceNameResolver, | 
 | #endif | 
 |                                       public SessionEstablishmentDelegate, | 
 |                                       public app::ClusterStateCache::Callback | 
 | { | 
 | public: | 
 |     DeviceCommissioner(); | 
 |     ~DeviceCommissioner() override {} | 
 |  | 
 | #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable | 
 |     /** | 
 |      * Set port for User Directed Commissioning | 
 |      */ | 
 |     CHIP_ERROR SetUdcListenPort(uint16_t listenPort); | 
 | #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY | 
 |  | 
 |     /** | 
 |      * Commissioner-specific initialization, includes parameters such as the pairing delegate. | 
 |      */ | 
 |     CHIP_ERROR Init(CommissionerInitParams params); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *  Tears down the entirety of the stack, including destructing key objects in the system. | 
 |      *  This is not a thread-safe API, and should be called with external synchronization. | 
 |      * | 
 |      *  Please see implementation for more details. | 
 |      */ | 
 |     void Shutdown() override; | 
 |  | 
 |     // ----- Connection Management ----- | 
 |     /** | 
 |      * @brief | 
 |      *   Pair a CHIP device with the provided code. The code can be either a QRCode | 
 |      *   or a Manual Setup Code. | 
 |      *   Use registered DevicePairingDelegate object to receive notifications on | 
 |      *   pairing status updates. | 
 |      * | 
 |      *   Note: Pairing process requires that the caller has registered PersistentStorageDelegate | 
 |      *         in the Init() call. | 
 |      * | 
 |      * @param[in] remoteDeviceId        The remote device Id. | 
 |      * @param[in] setUpCode             The setup code for connecting to the device | 
 |      * @param[in] discoveryType         The network discovery type, defaults to DiscoveryType::kAll. | 
 |      */ | 
 |     CHIP_ERROR PairDevice(NodeId remoteDeviceId, const char * setUpCode, DiscoveryType discoveryType = DiscoveryType::kAll); | 
 |     CHIP_ERROR PairDevice(NodeId remoteDeviceId, const char * setUpCode, const CommissioningParameters & CommissioningParameters, | 
 |                           DiscoveryType discoveryType = DiscoveryType::kAll); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Pair a CHIP device with the provided Rendezvous connection parameters. | 
 |      *   Use registered DevicePairingDelegate object to receive notifications on | 
 |      *   pairing status updates. | 
 |      * | 
 |      *   Note: Pairing process requires that the caller has registered PersistentStorageDelegate | 
 |      *         in the Init() call. | 
 |      * | 
 |      * @param[in] remoteDeviceId        The remote device Id. | 
 |      * @param[in] rendezvousParams      The Rendezvous connection parameters | 
 |      */ | 
 |     CHIP_ERROR PairDevice(NodeId remoteDeviceId, RendezvousParameters & rendezvousParams); | 
 |  | 
 |     /** | 
 |      * @overload | 
 |      * @param[in] remoteDeviceId        The remote device Id. | 
 |      * @param[in] rendezvousParams      The Rendezvous connection parameters | 
 |      * @param[in] commissioningParams    The commissioning parameters (uses default if not supplied) | 
 |      */ | 
 |     CHIP_ERROR PairDevice(NodeId remoteDeviceId, RendezvousParameters & rendezvousParams, | 
 |                           CommissioningParameters & commissioningParams); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Start establishing a PASE connection with a node for the purposes of commissioning. | 
 |      *   Commissioners that wish to use the auto-commissioning functions should use the | 
 |      *   supplied "PairDevice" functions above to automatically establish a connection then | 
 |      *   perform commissioning. This function is intended to be use by commissioners that | 
 |      *   are not using the supplied auto-commissioner. | 
 |      * | 
 |      *   This function is non-blocking. PASE is established once the DevicePairingDelegate | 
 |      *   receives the OnPairingComplete call. | 
 |      * | 
 |      *   PASE connections can only be established with nodes that have their commissioning | 
 |      *   window open. The PASE connection will fail if this window is not open and the | 
 |      *   OnPairingComplete will be called with an error. | 
 |      * | 
 |      * @param[in] remoteDeviceId        The remote device Id. | 
 |      * @param[in] params                The Rendezvous connection parameters | 
 |      */ | 
 |     CHIP_ERROR EstablishPASEConnection(NodeId remoteDeviceId, RendezvousParameters & params); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Start establishing a PASE connection with a node for the purposes of commissioning. | 
 |      *   Commissioners that wish to use the auto-commissioning functions should use the | 
 |      *   supplied "PairDevice" functions above to automatically establish a connection then | 
 |      *   perform commissioning. This function is intended to be used by commissioners that | 
 |      *   are not using the supplied auto-commissioner. | 
 |      * | 
 |      *   This function is non-blocking. PASE is established once the DevicePairingDelegate | 
 |      *   receives the OnPairingComplete call. | 
 |      * | 
 |      *   PASE connections can only be established with nodes that have their commissioning | 
 |      *   window open. The PASE connection will fail if this window is not open and in that case | 
 |      *   OnPairingComplete will be called with an error. | 
 |      * | 
 |      * @param[in] remoteDeviceId        The remote device Id. | 
 |      * @param[in] setUpCode             The setup code for connecting to the device | 
 |      * @param[in] discoveryType         The network discovery type, defaults to DiscoveryType::kAll. | 
 |      */ | 
 |     CHIP_ERROR EstablishPASEConnection(NodeId remoteDeviceId, const char * setUpCode, | 
 |                                        DiscoveryType discoveryType = DiscoveryType::kAll); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Start the auto-commissioning process on a node after establishing a PASE connection. | 
 |      *   This function is intended to be used in conjunction with the EstablishPASEConnection | 
 |      *   function. It can be called either before or after the DevicePairingDelegate receives | 
 |      *   the OnPairingComplete call. Commissioners that want to perform simple auto-commissioning | 
 |      *   should use the supplied "PairDevice" functions above, which will establish the PASE | 
 |      *   connection and commission automatically. | 
 |      * | 
 |      * @param[in] remoteDeviceId        The remote device Id. | 
 |      * @param[in] params                The commissioning parameters | 
 |      */ | 
 |     CHIP_ERROR Commission(NodeId remoteDeviceId, CommissioningParameters & params); | 
 |     CHIP_ERROR Commission(NodeId remoteDeviceId); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   This function instructs the commissioner to proceed to the next stage of commissioning after | 
 |      *   attestation is reported to an installed attestation delegate. | 
 |      * | 
 |      * @param[in] device                The device being commissioned. | 
 |      * @param[in] attestationResult     The attestation result to use instead of whatever the device | 
 |      *                                  attestation verifier came up with. May be a success or an error result. | 
 |      */ | 
 |     CHIP_ERROR | 
 |     ContinueCommissioningAfterDeviceAttestation(DeviceProxy * device, Credentials::AttestationVerificationResult attestationResult); | 
 |  | 
 |     CHIP_ERROR GetDeviceBeingCommissioned(NodeId deviceId, CommissioneeDeviceProxy ** device); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   This function stops a pairing process that's in progress. It does not delete the pairing of a previously | 
 |      *   paired device. | 
 |      * | 
 |      * @param[in] remoteDeviceId        The remote device Id. | 
 |      * | 
 |      * @return CHIP_ERROR               CHIP_NO_ERROR on success, or corresponding error | 
 |      */ | 
 |     CHIP_ERROR StopPairing(NodeId remoteDeviceId); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Remove pairing for a paired device. If the device is currently being paired, it'll stop the pairing process. | 
 |      * | 
 |      * @param[in] remoteDeviceId        The remote device Id. | 
 |      * | 
 |      * @return CHIP_ERROR               CHIP_NO_ERROR on success, or corresponding error | 
 |      */ | 
 |     CHIP_ERROR UnpairDevice(NodeId remoteDeviceId); | 
 |  | 
 |     //////////// SessionEstablishmentDelegate Implementation /////////////// | 
 |     void OnSessionEstablishmentError(CHIP_ERROR error) override; | 
 |     void OnSessionEstablished(const SessionHandle & session) override; | 
 |  | 
 |     void RendezvousCleanup(CHIP_ERROR status); | 
 |  | 
 |     void PerformCommissioningStep(DeviceProxy * device, CommissioningStage step, CommissioningParameters & params, | 
 |                                   CommissioningDelegate * delegate, EndpointId endpoint, Optional<System::Clock::Timeout> timeout); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   This function validates the Attestation Information sent by the device. | 
 |      * | 
 |      * @param[in] info Structure contatining all the required information for validating the device attestation. | 
 |      */ | 
 |     CHIP_ERROR ValidateAttestationInfo(const Credentials::DeviceAttestationVerifier::AttestationInfo & info); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      * Sends CommissioningStepComplete report to the commissioning delegate. Function will fill in current step. | 
 |      * @params[in] err      error from the current step | 
 |      * @params[in] report   report to send. Current step will be filled in automatically | 
 |      */ | 
 |     void | 
 |     CommissioningStageComplete(CHIP_ERROR err, | 
 |                                CommissioningDelegate::CommissioningReport report = CommissioningDelegate::CommissioningReport()); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   This function is called by the DevicePairingDelegate to indicate that network credentials have been set | 
 |      * on the CommissioningParameters of the CommissioningDelegate using CommissioningDelegate.SetCommissioningParameters(). | 
 |      * As a result, commissioning can advance to the next stage. | 
 |      * | 
 |      * The DevicePairingDelegate may call this method from the OnScanNetworksSuccess and OnScanNetworksFailure callbacks, | 
 |      * or it may call this method after obtaining network credentials using asyncronous methods (prompting user, cloud API call, | 
 |      * etc). | 
 |      * | 
 |      * If an error happens in the subsequent network commissioning step (either NetworkConfig or ConnectNetwork commands) | 
 |      * then the DevicePairingDelegate will receive the error in completionStatus.networkCommissioningStatus and the | 
 |      * commissioning stage will return to kNeedsNetworkCreds so that the DevicePairingDelegate can re-attempt with new | 
 |      * network information. The DevicePairingDelegate can exit the commissioning process by calling StopPairing. | 
 |      * | 
 |      * @return CHIP_ERROR   The return status. Returns CHIP_ERROR_INCORRECT_STATE if not in the correct state (kNeedsNetworkCreds). | 
 |      */ | 
 |     CHIP_ERROR NetworkCredentialsReady(); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *  This function returns the current CommissioningStage for this commissioner. | 
 |      */ | 
 |     CommissioningStage GetCommissioningStage() { return mCommissioningStage; } | 
 |  | 
 | #if CONFIG_NETWORK_LAYER_BLE | 
 | #if CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE | 
 |     /** | 
 |      * @brief | 
 |      *   Prior to commissioning, the Controller should make sure the BleLayer transport | 
 |      *   is set to the Commissioner transport and not the Server transport. | 
 |      */ | 
 |     void ConnectBleTransportToSelf(); | 
 | #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Once we have finished all commissioning work, the Controller should close the BLE | 
 |      *   connection to the device and establish CASE session / another PASE session to the device | 
 |      *   if needed. | 
 |      */ | 
 |     void CloseBleConnection(); | 
 | #endif | 
 |     /** | 
 |      * @brief | 
 |      *   Discover all devices advertising as commissionable. | 
 |      *   Should be called on main loop thread. | 
 |      * * @param[in] filter  Browse filter - controller will look for only the specified subtype. | 
 |      * @return CHIP_ERROR   The return status | 
 |      */ | 
 |     CHIP_ERROR DiscoverCommissionableNodes(Dnssd::DiscoveryFilter filter); | 
 |  | 
 |     /** | 
 |      * Stop commissionable discovery triggered by a previous | 
 |      * DiscoverCommissionableNodes call. | 
 |      */ | 
 |     CHIP_ERROR StopCommissionableDiscovery(); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Returns information about discovered devices. | 
 |      *   Should be called on main loop thread. | 
 |      * @return const DiscoveredNodeData* info about the selected device. May be nullptr if no information has been returned yet. | 
 |      */ | 
 |     const Dnssd::DiscoveredNodeData * GetDiscoveredDevice(int idx); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Returns the max number of commissionable nodes this commissioner can track mdns information for. | 
 |      * @return int  The max number of commissionable nodes supported | 
 |      */ | 
 |     int GetMaxCommissionableNodesSupported() { return kMaxCommissionableNodes; } | 
 |  | 
 | #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable | 
 |     /** | 
 |      * @brief | 
 |      *   Called when a UDC message is received specifying the given instanceName | 
 |      * This method indicates that UDC Server needs the Commissionable Node corresponding to | 
 |      * the given instance name to be found. UDC Server will wait for OnCommissionableNodeFound. | 
 |      * | 
 |      * @param instanceName DNS-SD instance name for the client requesting commissioning | 
 |      * | 
 |      */ | 
 |     void FindCommissionableNode(char * instanceName) override; | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Return the UDC Server instance | 
 |      * | 
 |      */ | 
 |     UserDirectedCommissioningServer * GetUserDirectedCommissioningServer() { return mUdcServer; } | 
 | #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   Overrides method from AbstractDnssdDiscoveryController | 
 |      * | 
 |      * @param nodeData DNS-SD node information | 
 |      * | 
 |      */ | 
 |     void OnNodeDiscovered(const chip::Dnssd::DiscoveredNodeData & nodeData) override; | 
 |  | 
 |     void RegisterPairingDelegate(DevicePairingDelegate * pairingDelegate) { mPairingDelegate = pairingDelegate; } | 
 |     DevicePairingDelegate * GetPairingDelegate() const { return mPairingDelegate; } | 
 |  | 
 |     // ClusterStateCache::Callback impl | 
 |     void OnDone(app::ReadClient *) override; | 
 |  | 
 |     // Issue an NOC chain using the associated OperationalCredentialsDelegate. The NOC chain will | 
 |     // be provided in X509 DER format. | 
 |     // NOTE: This is only valid assuming that `mOperationalCredentialsDelegate` is what is desired | 
 |     // to issue the NOC chain. | 
 |     CHIP_ERROR IssueNOCChain(const ByteSpan & NOCSRElements, NodeId nodeId, | 
 |                              chip::Callback::Callback<OnNOCChainGeneration> * callback); | 
 |  | 
 |     void SetDeviceAttestationVerifier(Credentials::DeviceAttestationVerifier * deviceAttestationVerifier) | 
 |     { | 
 |         mDeviceAttestationVerifier = deviceAttestationVerifier; | 
 |     } | 
 |  | 
 |     Optional<CommissioningParameters> GetCommissioningParameters() | 
 |     { | 
 |         return mDefaultCommissioner == nullptr ? NullOptional : MakeOptional(mDefaultCommissioner->GetCommissioningParameters()); | 
 |     } | 
 |  | 
 |     // Reset the arm failsafe timer during commissioning.  If this returns | 
 |     // false, that means that the timer was already set for a longer time period | 
 |     // than the new time we are trying to set.  In this case, neither | 
 |     // onSuccess nor onFailure will be called. | 
 |     bool ExtendArmFailSafe(DeviceProxy * proxy, CommissioningStage step, uint16_t armFailSafeTimeout, | 
 |                            Optional<System::Clock::Timeout> commandTimeout, OnExtendFailsafeSuccess onSuccess, | 
 |                            OnExtendFailsafeFailure onFailure); | 
 |  | 
 | private: | 
 |     DevicePairingDelegate * mPairingDelegate; | 
 |  | 
 |     DeviceProxy * mDeviceBeingCommissioned               = nullptr; | 
 |     CommissioneeDeviceProxy * mDeviceInPASEEstablishment = nullptr; | 
 |  | 
 |     CommissioningStage mCommissioningStage = CommissioningStage::kSecurePairing; | 
 |     bool mRunCommissioningAfterConnection  = false; | 
 |  | 
 |     ObjectPool<CommissioneeDeviceProxy, kNumMaxActiveDevices> mCommissioneeDevicePool; | 
 |  | 
 | #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY // make this commissioner discoverable | 
 |     UserDirectedCommissioningServer * mUdcServer = nullptr; | 
 |     // mUdcTransportMgr is for insecure communication (ex. user directed commissioning) | 
 |     UdcTransportMgr * mUdcTransportMgr = nullptr; | 
 |     uint16_t mUdcListenPort            = CHIP_UDC_PORT; | 
 | #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY | 
 |  | 
 | #if CONFIG_NETWORK_LAYER_BLE | 
 |     static void OnDiscoveredDeviceOverBleSuccess(void * appState, BLE_CONNECTION_OBJECT connObj); | 
 |     static void OnDiscoveredDeviceOverBleError(void * appState, CHIP_ERROR err); | 
 |     RendezvousParameters mRendezvousParametersForDeviceDiscoveredOverBle; | 
 | #endif | 
 |  | 
 |     CHIP_ERROR LoadKeyId(PersistentStorageDelegate * delegate, uint16_t & out); | 
 |  | 
 |     /* This function sends a Device Attestation Certificate chain request to the device. | 
 |        The function does not hold a reference to the device object. | 
 |      */ | 
 |     CHIP_ERROR SendCertificateChainRequestCommand(DeviceProxy * device, Credentials::CertificateType certificateType, | 
 |                                                   Optional<System::Clock::Timeout> timeout); | 
 |     /* This function sends an Attestation request to the device. | 
 |        The function does not hold a reference to the device object. | 
 |      */ | 
 |     CHIP_ERROR SendAttestationRequestCommand(DeviceProxy * device, const ByteSpan & attestationNonce, | 
 |                                              Optional<System::Clock::Timeout> timeout); | 
 |     /* This function sends an CSR request to the device. | 
 |        The function does not hold a reference to the device object. | 
 |      */ | 
 |     CHIP_ERROR SendOperationalCertificateSigningRequestCommand(DeviceProxy * device, const ByteSpan & csrNonce, | 
 |                                                                Optional<System::Clock::Timeout> timeout); | 
 |     /* This function sends the operational credentials to the device. | 
 |        The function does not hold a reference to the device object. | 
 |      */ | 
 |     CHIP_ERROR SendOperationalCertificate(DeviceProxy * device, const ByteSpan & nocCertBuf, const Optional<ByteSpan> & icaCertBuf, | 
 |                                           IdentityProtectionKeySpan ipk, NodeId adminSubject, | 
 |                                           Optional<System::Clock::Timeout> timeout); | 
 |     /* This function sends the trusted root certificate to the device. | 
 |        The function does not hold a reference to the device object. | 
 |      */ | 
 |     CHIP_ERROR SendTrustedRootCertificate(DeviceProxy * device, const ByteSpan & rcac, Optional<System::Clock::Timeout> timeout); | 
 |  | 
 |     /* This function is called by the commissioner code when the device completes | 
 |        the operational credential provisioning process. | 
 |        The function does not hold a reference to the device object. | 
 |        */ | 
 |     CHIP_ERROR OnOperationalCredentialsProvisioningCompletion(DeviceProxy * device); | 
 |  | 
 |     /* Callback when the previously sent CSR request results in failure */ | 
 |     static void OnCSRFailureResponse(void * context, CHIP_ERROR error); | 
 |  | 
 |     void ExtendArmFailSafeForDeviceAttestation(const Credentials::DeviceAttestationVerifier::AttestationInfo & info, | 
 |                                                Credentials::AttestationVerificationResult result); | 
 |     static void OnCertificateChainFailureResponse(void * context, CHIP_ERROR error); | 
 |     static void OnCertificateChainResponse( | 
 |         void * context, const app::Clusters::OperationalCredentials::Commands::CertificateChainResponse::DecodableType & response); | 
 |  | 
 |     static void OnAttestationFailureResponse(void * context, CHIP_ERROR error); | 
 |     static void | 
 |     OnAttestationResponse(void * context, | 
 |                           const app::Clusters::OperationalCredentials::Commands::AttestationResponse::DecodableType & data); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   This function is called by the IM layer when the commissioner receives the CSR from the device. | 
 |      *   (Reference: Specifications section 11.18.5.6. NOCSR Elements) | 
 |      * | 
 |      * @param[in] context               The context provided while registering the callback. | 
 |      * @param[in] data                  The response struct containing the following fields: | 
 |      *                                    NOCSRElements: CSR elements as per specifications section 11.22.5.6. NOCSR Elements. | 
 |      *                                    AttestationSignature: Cryptographic signature generated for the fields in the response | 
 |      * message. | 
 |      */ | 
 |     static void OnOperationalCertificateSigningRequest( | 
 |         void * context, const app::Clusters::OperationalCredentials::Commands::CSRResponse::DecodableType & data); | 
 |  | 
 |     /* Callback when adding operational certs to device results in failure */ | 
 |     static void OnAddNOCFailureResponse(void * context, CHIP_ERROR errro); | 
 |     /* Callback when the device confirms that it has added the operational certificates */ | 
 |     static void | 
 |     OnOperationalCertificateAddResponse(void * context, | 
 |                                         const app::Clusters::OperationalCredentials::Commands::NOCResponse::DecodableType & data); | 
 |  | 
 |     /* Callback when the device confirms that it has added the root certificate */ | 
 |     static void OnRootCertSuccessResponse(void * context, const chip::app::DataModel::NullObjectType &); | 
 |     /* Callback called when adding root cert to device results in failure */ | 
 |     static void OnRootCertFailureResponse(void * context, CHIP_ERROR error); | 
 |  | 
 |     static void OnDeviceConnectedFn(void * context, Messaging::ExchangeManager & exchangeMgr, const SessionHandle & sessionHandle); | 
 |     static void OnDeviceConnectionFailureFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error); | 
 | #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES | 
 |     static void OnDeviceConnectionRetryFn(void * context, const ScopedNodeId & peerId, CHIP_ERROR error, | 
 |                                           System::Clock::Seconds16 retryTimeout); | 
 | #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES | 
 |  | 
 |     static void OnDeviceAttestationInformationVerification(void * context, | 
 |                                                            const Credentials::DeviceAttestationVerifier::AttestationInfo & info, | 
 |                                                            Credentials::AttestationVerificationResult result); | 
 |  | 
 |     static void OnDeviceNOCChainGeneration(void * context, CHIP_ERROR status, const ByteSpan & noc, const ByteSpan & icac, | 
 |                                            const ByteSpan & rcac, Optional<IdentityProtectionKeySpan> ipk, | 
 |                                            Optional<NodeId> adminSubject); | 
 |     static void OnArmFailSafe(void * context, | 
 |                               const chip::app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data); | 
 |     static void OnSetRegulatoryConfigResponse( | 
 |         void * context, | 
 |         const chip::app::Clusters::GeneralCommissioning::Commands::SetRegulatoryConfigResponse::DecodableType & data); | 
 |     static void | 
 |     OnScanNetworksResponse(void * context, | 
 |                            const app::Clusters::NetworkCommissioning::Commands::ScanNetworksResponse::DecodableType & data); | 
 |     static void OnScanNetworksFailure(void * context, CHIP_ERROR err); | 
 |     static void | 
 |     OnNetworkConfigResponse(void * context, | 
 |                             const app::Clusters::NetworkCommissioning::Commands::NetworkConfigResponse::DecodableType & data); | 
 |     static void OnConnectNetworkResponse( | 
 |         void * context, const chip::app::Clusters::NetworkCommissioning::Commands::ConnectNetworkResponse::DecodableType & data); | 
 |     static void OnCommissioningCompleteResponse( | 
 |         void * context, | 
 |         const chip::app::Clusters::GeneralCommissioning::Commands::CommissioningCompleteResponse::DecodableType & data); | 
 |     static void OnDisarmFailsafe(void * context, | 
 |                                  const app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data); | 
 |     static void OnDisarmFailsafeFailure(void * context, CHIP_ERROR error); | 
 |     void DisarmDone(); | 
 |     static void OnArmFailSafeExtendedForDeviceAttestation( | 
 |         void * context, const chip::app::Clusters::GeneralCommissioning::Commands::ArmFailSafeResponse::DecodableType & data); | 
 |     static void OnFailedToExtendedArmFailSafeDeviceAttestation(void * context, CHIP_ERROR error); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   This function processes the CSR sent by the device. | 
 |      *   (Reference: Specifications section 11.18.5.6. NOCSR Elements) | 
 |      * | 
 |      * @param[in] proxy           device proxy | 
 |      * @param[in] NOCSRElements   CSR elements as per specifications section 11.22.5.6. NOCSR Elements. | 
 |      * @param[in] AttestationSignature       Cryptographic signature generated for all the above fields. | 
 |      * @param[in] dac               device attestation certificate | 
 |      * @param[in] pai               Product Attestation Intermediate certificate | 
 |      * @param[in] csrNonce          certificate signing request nonce | 
 |      */ | 
 |     CHIP_ERROR ProcessCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements, const ByteSpan & AttestationSignature, | 
 |                           const ByteSpan & dac, const ByteSpan & pai, const ByteSpan & csrNonce); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   This function validates the CSR information from the device. | 
 |      *   (Reference: Specifications section 11.18.5.6. NOCSR Elements) | 
 |      * | 
 |      * @param[in] proxy           device proxy | 
 |      * @param[in] NOCSRElements   CSR elements as per specifications section 11.22.5.6. NOCSR Elements. | 
 |      * @param[in] AttestationSignature       Cryptographic signature generated for all the above fields. | 
 |      * @param[in] dac               device attestation certificate | 
 |      * @param[in] csrNonce          certificate signing request nonce | 
 |      */ | 
 |     CHIP_ERROR ValidateCSR(DeviceProxy * proxy, const ByteSpan & NOCSRElements, const ByteSpan & AttestationSignature, | 
 |                            const ByteSpan & dac, const ByteSpan & csrNonce); | 
 |  | 
 |     /** | 
 |      * @brief | 
 |      *   This function processes the DAC or PAI certificate sent by the device. | 
 |      */ | 
 |     CHIP_ERROR ProcessCertificateChain(const ByteSpan & certificate); | 
 |  | 
 |     void HandleAttestationResult(CHIP_ERROR err); | 
 |  | 
 |     CommissioneeDeviceProxy * FindCommissioneeDevice(NodeId id); | 
 |     CommissioneeDeviceProxy * FindCommissioneeDevice(const Transport::PeerAddress & peerAddress); | 
 |     void ReleaseCommissioneeDevice(CommissioneeDeviceProxy * device); | 
 |  | 
 |     template <typename RequestObjectT> | 
 |     CHIP_ERROR SendCommand(DeviceProxy * device, const RequestObjectT & request, | 
 |                            CommandResponseSuccessCallback<typename RequestObjectT::ResponseType> successCb, | 
 |                            CommandResponseFailureCallback failureCb, Optional<System::Clock::Timeout> timeout) | 
 |     { | 
 |         return SendCommand(device, request, successCb, failureCb, 0, timeout); | 
 |     } | 
 |  | 
 |     template <typename RequestObjectT> | 
 |     CHIP_ERROR SendCommand(DeviceProxy * device, const RequestObjectT & request, | 
 |                            CommandResponseSuccessCallback<typename RequestObjectT::ResponseType> successCb, | 
 |                            CommandResponseFailureCallback failureCb, EndpointId endpoint, Optional<System::Clock::Timeout> timeout) | 
 |     { | 
 |         ClusterBase cluster(*device->GetExchangeManager(), device->GetSecureSession().Value(), endpoint); | 
 |         cluster.SetCommandTimeout(timeout); | 
 |  | 
 |         return cluster.InvokeCommand(request, this, successCb, failureCb); | 
 |     } | 
 |  | 
 |     static CHIP_ERROR | 
 |     ConvertFromOperationalCertStatus(chip::app::Clusters::OperationalCredentials::NodeOperationalCertStatusEnum err); | 
 |  | 
 |     // Sends commissioning complete callbacks to the delegate depending on the status. Sends | 
 |     // OnCommissioningComplete and either OnCommissioningSuccess or OnCommissioningFailure depending on the given completion status. | 
 |     void SendCommissioningCompleteCallbacks(NodeId nodeId, const CompletionStatus & completionStatus); | 
 |  | 
 |     // Cleans up and resets failsafe as appropriate depending on the error and the failed stage. | 
 |     // For success, sends completion report with the CommissioningDelegate and sends callbacks to the PairingDelegate | 
 |     // For failures after AddNOC succeeds, sends completion report with the CommissioningDelegate and sends callbacks to the | 
 |     // PairingDelegate. In this case, it does not disarm the failsafe or close the pase connection. For failures up through AddNOC, | 
 |     // sends a command to immediately expire the failsafe, then sends completion report with the CommissioningDelegate and callbacks | 
 |     // to the PairingDelegate upon arm failsafe command completion. | 
 |     void CleanupCommissioning(DeviceProxy * proxy, NodeId nodeId, const CompletionStatus & completionStatus); | 
 |  | 
 |     // Extend the fail-safe before trying to do network-enable (since after that | 
 |     // point, for non-concurrent-commissioning devices, we may not have a way to | 
 |     // extend it). | 
 |     void ExtendFailsafeBeforeNetworkEnable(DeviceProxy * device, CommissioningParameters & params, CommissioningStage step); | 
 |  | 
 |     chip::Callback::Callback<OnDeviceConnected> mOnDeviceConnectedCallback; | 
 |     chip::Callback::Callback<OnDeviceConnectionFailure> mOnDeviceConnectionFailureCallback; | 
 | #if CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES | 
 |     chip::Callback::Callback<OnDeviceConnectionRetry> mOnDeviceConnectionRetryCallback; | 
 | #endif // CHIP_DEVICE_CONFIG_ENABLE_AUTOMATIC_CASE_RETRIES | 
 |  | 
 |     chip::Callback::Callback<Credentials::DeviceAttestationVerifier::OnAttestationInformationVerification> | 
 |         mDeviceAttestationInformationVerificationCallback; | 
 |  | 
 |     chip::Callback::Callback<OnNOCChainGeneration> mDeviceNOCChainCallback; | 
 |     SetUpCodePairer mSetUpCodePairer; | 
 |     AutoCommissioner mAutoCommissioner; | 
 |     CommissioningDelegate * mDefaultCommissioner = | 
 |         nullptr; // Commissioning delegate to call when PairDevice / Commission functions are used | 
 |     CommissioningDelegate * mCommissioningDelegate = | 
 |         nullptr; // Commissioning delegate that issued the PerformCommissioningStep command | 
 |     CompletionStatus commissioningCompletionStatus; | 
 |  | 
 |     Platform::UniquePtr<app::ClusterStateCache> mAttributeCache; | 
 |     Platform::UniquePtr<app::ReadClient> mReadClient; | 
 |     Credentials::AttestationVerificationResult mAttestationResult; | 
 |     Platform::UniquePtr<Credentials::DeviceAttestationVerifier::AttestationDeviceInfo> mAttestationDeviceInfo; | 
 |     Credentials::DeviceAttestationVerifier * mDeviceAttestationVerifier = nullptr; | 
 | }; | 
 |  | 
 | } // namespace Controller | 
 | } // namespace chip |