Matter SDK Coverage Report
Current view: top level - controller - CommissioningWindowOpener.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 26.1 % 211 55
Test Date: 2025-01-17 19:00:11 Functions: 11.8 % 17 2

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2022 Project CHIP Authors
       3              :  *    All rights reserved.
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : #include <app-common/zap-generated/cluster-objects.h>
      19              : #include <controller/CommissioningWindowOpener.h>
      20              : #include <lib/core/CHIPSafeCasts.h>
      21              : #include <lib/support/CHIPMem.h>
      22              : #include <protocols/secure_channel/PASESession.h>
      23              : #include <setup_payload/ManualSetupPayloadGenerator.h>
      24              : #include <setup_payload/QRCodeSetupPayloadGenerator.h>
      25              : 
      26              : using namespace chip::app::Clusters;
      27              : using namespace chip::System::Clock;
      28              : using namespace chip::Crypto;
      29              : 
      30              : namespace {
      31              : // TODO: What should the timed invoke timeout here be?
      32              : constexpr uint16_t kTimedInvokeTimeoutMs = 10000;
      33              : } // anonymous namespace
      34              : 
      35              : namespace chip {
      36              : namespace Controller {
      37              : 
      38            0 : CHIP_ERROR CommissioningWindowOpener::OpenBasicCommissioningWindow(NodeId deviceId, Seconds16 timeout,
      39              :                                                                    Callback::Callback<OnOpenBasicCommissioningWindow> * callback)
      40              : {
      41            0 :     VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
      42            0 :     mSetupPayload = SetupPayload();
      43              : 
      44              :     // Basic commissioning does not use the setup payload.
      45              : 
      46            0 :     mCommissioningWindowOption           = CommissioningWindowOption::kOriginalSetupCode;
      47            0 :     mBasicCommissioningWindowCallback    = callback;
      48            0 :     mCommissioningWindowCallback         = nullptr;
      49            0 :     mCommissioningWindowVerifierCallback = nullptr;
      50            0 :     mNodeId                              = deviceId;
      51            0 :     mCommissioningWindowTimeout          = timeout;
      52              : 
      53            0 :     mNextStep = Step::kOpenCommissioningWindow;
      54            0 :     return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
      55              : }
      56              : 
      57            0 : CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(NodeId deviceId, Seconds16 timeout, uint32_t iteration,
      58              :                                                               uint16_t discriminator, Optional<uint32_t> setupPIN,
      59              :                                                               Optional<ByteSpan> salt,
      60              :                                                               Callback::Callback<OnOpenCommissioningWindow> * callback,
      61              :                                                               SetupPayload & payload, bool readVIDPIDAttributes)
      62              : {
      63            0 :     return OpenCommissioningWindow(CommissioningWindowPasscodeParams()
      64            0 :                                        .SetNodeId(deviceId)
      65            0 :                                        .SetTimeout(timeout)
      66            0 :                                        .SetIteration(iteration)
      67            0 :                                        .SetDiscriminator(discriminator)
      68            0 :                                        .SetSetupPIN(setupPIN)
      69            0 :                                        .SetSalt(salt)
      70            0 :                                        .SetReadVIDPIDAttributes(readVIDPIDAttributes)
      71            0 :                                        .SetCallback(callback),
      72            0 :                                    payload);
      73              : }
      74              : 
      75            4 : CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowPasscodeParams & params,
      76              :                                                               SetupPayload & payload)
      77              : {
      78            4 :     VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
      79            4 :     VerifyOrReturnError(params.HasNodeId(), CHIP_ERROR_INVALID_ARGUMENT);
      80            4 :     VerifyOrReturnError(params.HasDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT);
      81            4 :     VerifyOrReturnError(kSpake2p_Min_PBKDF_Iterations <= params.GetIteration() &&
      82              :                             params.GetIteration() <= kSpake2p_Max_PBKDF_Iterations,
      83              :                         CHIP_ERROR_INVALID_ARGUMENT);
      84            3 :     VerifyOrReturnError(!params.HasSalt() ||
      85              :                             (params.GetSalt().size() >= kSpake2p_Min_PBKDF_Salt_Length &&
      86              :                              params.GetSalt().size() <= kSpake2p_Max_PBKDF_Salt_Length),
      87              :                         CHIP_ERROR_INVALID_ARGUMENT);
      88              : 
      89            3 :     mSetupPayload = SetupPayload();
      90              : 
      91            3 :     if (params.HasSetupPIN())
      92              :     {
      93            2 :         VerifyOrReturnError(SetupPayload::IsValidSetupPIN(params.GetSetupPIN()), CHIP_ERROR_INVALID_ARGUMENT);
      94            2 :         mCommissioningWindowOption = CommissioningWindowOption::kTokenWithProvidedPIN;
      95            2 :         mSetupPayload.setUpPINCode = params.GetSetupPIN();
      96              :     }
      97              :     else
      98              :     {
      99            1 :         mCommissioningWindowOption = CommissioningWindowOption::kTokenWithRandomPIN;
     100              :     }
     101              : 
     102            3 :     mSetupPayload.version = 0;
     103            3 :     mDiscriminator.SetLongValue(params.GetDiscriminator());
     104            3 :     mSetupPayload.discriminator = mDiscriminator;
     105            3 :     mSetupPayload.rendezvousInformation.SetValue(RendezvousInformationFlag::kOnNetwork);
     106              : 
     107            3 :     if (params.HasSalt())
     108              :     {
     109            2 :         memcpy(mPBKDFSaltBuffer, params.GetSalt().data(), params.GetSalt().size());
     110            2 :         mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer, params.GetSalt().size());
     111              :     }
     112              :     else
     113              :     {
     114            1 :         ReturnErrorOnFailure(DRBG_get_bytes(mPBKDFSaltBuffer, sizeof(mPBKDFSaltBuffer)));
     115            1 :         mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer);
     116              :     }
     117            3 :     mPBKDFIterations = params.GetIteration();
     118              : 
     119            3 :     bool randomSetupPIN = !params.HasSetupPIN();
     120            3 :     ReturnErrorOnFailure(
     121              :         PASESession::GeneratePASEVerifier(mVerifier, mPBKDFIterations, mPBKDFSalt, randomSetupPIN, mSetupPayload.setUpPINCode));
     122              : 
     123            3 :     payload                              = mSetupPayload;
     124            3 :     mCommissioningWindowCallback         = params.GetCallback();
     125            3 :     mBasicCommissioningWindowCallback    = nullptr;
     126            3 :     mCommissioningWindowVerifierCallback = nullptr;
     127            3 :     mNodeId                              = params.GetNodeId();
     128            3 :     mCommissioningWindowTimeout          = params.GetTimeout();
     129            3 :     mTargetEndpointId                    = params.GetEndpointId();
     130              : 
     131            3 :     if (params.GetReadVIDPIDAttributes())
     132              :     {
     133            1 :         mNextStep = Step::kReadVID;
     134              :     }
     135              :     else
     136              :     {
     137            2 :         mNextStep = Step::kOpenCommissioningWindow;
     138              :     }
     139              : 
     140            3 :     return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
     141              : }
     142              : 
     143            4 : CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindow(const CommissioningWindowVerifierParams & params)
     144              : {
     145            4 :     VerifyOrReturnError(mNextStep == Step::kAcceptCommissioningStart, CHIP_ERROR_INCORRECT_STATE);
     146            4 :     VerifyOrReturnError(params.HasNodeId(), CHIP_ERROR_INVALID_ARGUMENT);
     147            4 :     VerifyOrReturnError(params.HasDiscriminator(), CHIP_ERROR_INVALID_ARGUMENT);
     148            4 :     VerifyOrReturnError(kSpake2p_Min_PBKDF_Iterations <= params.GetIteration() &&
     149              :                             params.GetIteration() <= kSpake2p_Max_PBKDF_Iterations,
     150              :                         CHIP_ERROR_INVALID_ARGUMENT);
     151            3 :     VerifyOrReturnError(params.GetSalt().size() >= kSpake2p_Min_PBKDF_Salt_Length &&
     152              :                             params.GetSalt().size() <= kSpake2p_Max_PBKDF_Salt_Length,
     153              :                         CHIP_ERROR_INVALID_ARGUMENT);
     154            2 :     memcpy(mPBKDFSaltBuffer, params.GetSalt().data(), params.GetSalt().size());
     155            2 :     mPBKDFSalt = ByteSpan(mPBKDFSaltBuffer, params.GetSalt().size());
     156              : 
     157            2 :     ReturnErrorOnFailure(mVerifier.Deserialize(params.GetVerifier()));
     158            1 :     mCommissioningWindowVerifierCallback = params.GetCallback();
     159            1 :     mBasicCommissioningWindowCallback    = nullptr;
     160            1 :     mCommissioningWindowCallback         = nullptr;
     161            1 :     mNodeId                              = params.GetNodeId();
     162            1 :     mCommissioningWindowTimeout          = params.GetTimeout();
     163            1 :     mPBKDFIterations                     = params.GetIteration();
     164            1 :     mCommissioningWindowOption           = CommissioningWindowOption::kTokenWithProvidedPIN;
     165            1 :     mDiscriminator.SetLongValue(params.GetDiscriminator());
     166            1 :     mTargetEndpointId = params.GetEndpointId();
     167              : 
     168            1 :     mNextStep = Step::kOpenCommissioningWindow;
     169              : 
     170            1 :     return mController->GetConnectedDevice(mNodeId, &mDeviceConnected, &mDeviceConnectionFailure);
     171              : }
     172              : 
     173            0 : CHIP_ERROR CommissioningWindowOpener::OpenCommissioningWindowInternal(Messaging::ExchangeManager & exchangeMgr,
     174              :                                                                       const SessionHandle & sessionHandle)
     175              : {
     176            0 :     ChipLogProgress(Controller, "OpenCommissioningWindow for device ID 0x" ChipLogFormatX64, ChipLogValueX64(mNodeId));
     177              : 
     178            0 :     ClusterBase cluster(exchangeMgr, sessionHandle, mTargetEndpointId);
     179              : 
     180            0 :     if (mCommissioningWindowOption != CommissioningWindowOption::kOriginalSetupCode)
     181              :     {
     182              :         Spake2pVerifierSerialized serializedVerifier;
     183            0 :         MutableByteSpan serializedVerifierSpan(serializedVerifier);
     184            0 :         ReturnErrorOnFailure(mVerifier.Serialize(serializedVerifierSpan));
     185              : 
     186            0 :         AdministratorCommissioning::Commands::OpenCommissioningWindow::Type request;
     187            0 :         request.commissioningTimeout = mCommissioningWindowTimeout.count();
     188            0 :         request.PAKEPasscodeVerifier = serializedVerifierSpan;
     189            0 :         request.discriminator        = mDiscriminator.GetLongValue();
     190            0 :         request.iterations           = mPBKDFIterations;
     191            0 :         request.salt                 = mPBKDFSalt;
     192              : 
     193            0 :         ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
     194              :                                                    OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
     195              :     }
     196              :     else
     197              :     {
     198            0 :         AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type request;
     199            0 :         request.commissioningTimeout = mCommissioningWindowTimeout.count();
     200            0 :         ReturnErrorOnFailure(cluster.InvokeCommand(request, this, OnOpenCommissioningWindowSuccess,
     201              :                                                    OnOpenCommissioningWindowFailure, MakeOptional(kTimedInvokeTimeoutMs)));
     202              :     }
     203              : 
     204            0 :     return CHIP_NO_ERROR;
     205            0 : }
     206              : 
     207            0 : void CommissioningWindowOpener::OnPIDReadResponse(void * context, uint16_t value)
     208              : {
     209            0 :     ChipLogProgress(Controller, "Received PID for the device. Value %d", value);
     210            0 :     auto * self                   = static_cast<CommissioningWindowOpener *>(context);
     211            0 :     self->mSetupPayload.productID = value;
     212              : 
     213            0 :     self->mNextStep = Step::kOpenCommissioningWindow;
     214              : 
     215            0 :     CHIP_ERROR err = self->mController->GetConnectedDevice(self->mNodeId, &self->mDeviceConnected, &self->mDeviceConnectionFailure);
     216            0 :     if (err != CHIP_NO_ERROR)
     217              :     {
     218            0 :         OnOpenCommissioningWindowFailure(context, err);
     219              :     }
     220            0 : }
     221              : 
     222            0 : void CommissioningWindowOpener::OnVIDReadResponse(void * context, VendorId value)
     223              : {
     224            0 :     ChipLogProgress(Controller, "Received VID for the device. Value %d", to_underlying(value));
     225              : 
     226            0 :     auto * self = static_cast<CommissioningWindowOpener *>(context);
     227              : 
     228            0 :     self->mSetupPayload.vendorID = value;
     229              : 
     230            0 :     self->mNextStep = Step::kReadPID;
     231            0 :     CHIP_ERROR err = self->mController->GetConnectedDevice(self->mNodeId, &self->mDeviceConnected, &self->mDeviceConnectionFailure);
     232            0 :     if (err != CHIP_NO_ERROR)
     233              :     {
     234            0 :         OnOpenCommissioningWindowFailure(context, err);
     235              :     }
     236            0 : }
     237              : 
     238            0 : void CommissioningWindowOpener::OnVIDPIDReadFailureResponse(void * context, CHIP_ERROR error)
     239              : {
     240            0 :     ChipLogProgress(Controller, "Failed to read VID/PID for the device. error %" CHIP_ERROR_FORMAT, error.Format());
     241            0 :     OnOpenCommissioningWindowFailure(context, error);
     242            0 : }
     243              : 
     244            0 : void CommissioningWindowOpener::OnOpenCommissioningWindowSuccess(void * context, const chip::app::DataModel::NullObjectType &)
     245              : {
     246            0 :     ChipLogProgress(Controller, "Successfully opened pairing window on the device");
     247            0 :     auto * self     = static_cast<CommissioningWindowOpener *>(context);
     248            0 :     self->mNextStep = Step::kAcceptCommissioningStart;
     249            0 :     if (self->mCommissioningWindowCallback != nullptr)
     250              :     {
     251              :         char payloadBuffer[QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
     252              : 
     253            0 :         MutableCharSpan manualCode(payloadBuffer);
     254            0 :         CHIP_ERROR err = ManualSetupPayloadGenerator(self->mSetupPayload).payloadDecimalStringRepresentation(manualCode);
     255            0 :         if (err == CHIP_NO_ERROR)
     256              :         {
     257            0 :             ChipLogProgress(Controller, "Manual pairing code: [%s]", payloadBuffer);
     258              :         }
     259              :         else
     260              :         {
     261            0 :             ChipLogError(Controller, "Unable to generate manual code for setup payload: %" CHIP_ERROR_FORMAT, err.Format());
     262              :         }
     263              : 
     264            0 :         MutableCharSpan QRCode(payloadBuffer);
     265            0 :         err = QRCodeBasicSetupPayloadGenerator(self->mSetupPayload).payloadBase38Representation(QRCode);
     266            0 :         if (err == CHIP_NO_ERROR)
     267              :         {
     268            0 :             ChipLogProgress(Controller, "SetupQRCode: [%s]", payloadBuffer);
     269              :         }
     270              :         else
     271              :         {
     272            0 :             ChipLogError(Controller, "Unable to generate QR code for setup payload: %" CHIP_ERROR_FORMAT, err.Format());
     273              :         }
     274              : 
     275            0 :         self->mCommissioningWindowCallback->mCall(self->mCommissioningWindowCallback->mContext, self->mNodeId, CHIP_NO_ERROR,
     276            0 :                                                   self->mSetupPayload);
     277              :         // Don't touch `self` anymore; it might have been destroyed by the callee.
     278              :     }
     279            0 :     else if (self->mCommissioningWindowVerifierCallback != nullptr)
     280              :     {
     281            0 :         self->mCommissioningWindowVerifierCallback->mCall(self->mCommissioningWindowVerifierCallback->mContext, self->mNodeId,
     282              :                                                           CHIP_NO_ERROR);
     283              :         // Don't touch `self` anymore; it might have been destroyed by the callee.
     284              :     }
     285            0 :     else if (self->mBasicCommissioningWindowCallback != nullptr)
     286              :     {
     287            0 :         self->mBasicCommissioningWindowCallback->mCall(self->mBasicCommissioningWindowCallback->mContext, self->mNodeId,
     288              :                                                        CHIP_NO_ERROR);
     289              :         // Don't touch `self` anymore; it might have been destroyed by the callee.
     290              :     }
     291            0 : }
     292              : 
     293            0 : void CommissioningWindowOpener::OnOpenCommissioningWindowFailure(void * context, CHIP_ERROR error)
     294              : {
     295            0 :     ChipLogError(Controller, "Failed to open pairing window on the device. Status %" CHIP_ERROR_FORMAT, error.Format());
     296            0 :     auto * self     = static_cast<CommissioningWindowOpener *>(context);
     297            0 :     self->mNextStep = Step::kAcceptCommissioningStart;
     298            0 :     if (self->mCommissioningWindowCallback != nullptr)
     299              :     {
     300            0 :         self->mCommissioningWindowCallback->mCall(self->mCommissioningWindowCallback->mContext, self->mNodeId, error,
     301            0 :                                                   SetupPayload());
     302              :     }
     303            0 :     else if (self->mCommissioningWindowVerifierCallback != nullptr)
     304              :     {
     305            0 :         self->mCommissioningWindowVerifierCallback->mCall(self->mCommissioningWindowVerifierCallback->mContext, self->mNodeId,
     306              :                                                           error);
     307              :     }
     308            0 :     else if (self->mBasicCommissioningWindowCallback != nullptr)
     309              :     {
     310            0 :         self->mBasicCommissioningWindowCallback->mCall(self->mBasicCommissioningWindowCallback->mContext, self->mNodeId, error);
     311              :     }
     312            0 : }
     313              : 
     314            0 : void CommissioningWindowOpener::OnDeviceConnectedCallback(void * context, Messaging::ExchangeManager & exchangeMgr,
     315              :                                                           const SessionHandle & sessionHandle)
     316              : {
     317            0 :     auto * self = static_cast<CommissioningWindowOpener *>(context);
     318              : 
     319              : #if CHIP_ERROR_LOGGING
     320            0 :     const char * messageIfError = nullptr;
     321              : #endif // CHIP_ERROR_LOGGING
     322            0 :     CHIP_ERROR err = CHIP_NO_ERROR;
     323              : 
     324            0 :     switch (self->mNextStep)
     325              :     {
     326            0 :     case Step::kReadVID: {
     327            0 :         ClusterBase cluster(exchangeMgr, sessionHandle, kRootEndpointId);
     328            0 :         err = cluster.ReadAttribute<BasicInformation::Attributes::VendorID::TypeInfo>(context, OnVIDReadResponse,
     329              :                                                                                       OnVIDPIDReadFailureResponse);
     330              : #if CHIP_ERROR_LOGGING
     331            0 :         messageIfError = "Could not read VID for opening commissioning window";
     332              : #endif // CHIP_ERROR_LOGGING
     333            0 :         break;
     334            0 :     }
     335            0 :     case Step::kReadPID: {
     336            0 :         ClusterBase cluster(exchangeMgr, sessionHandle, kRootEndpointId);
     337            0 :         err = cluster.ReadAttribute<BasicInformation::Attributes::ProductID::TypeInfo>(context, OnPIDReadResponse,
     338              :                                                                                        OnVIDPIDReadFailureResponse);
     339              : #if CHIP_ERROR_LOGGING
     340            0 :         messageIfError = "Could not read PID for opening commissioning window";
     341              : #endif // CHIP_ERROR_LOGGING
     342            0 :         break;
     343            0 :     }
     344            0 :     case Step::kOpenCommissioningWindow: {
     345            0 :         err = self->OpenCommissioningWindowInternal(exchangeMgr, sessionHandle);
     346              : #if CHIP_ERROR_LOGGING
     347            0 :         messageIfError = "Could not connect to open commissioning window";
     348              : #endif // CHIP_ERROR_LOGGING
     349            0 :         break;
     350              :     }
     351            0 :     case Step::kAcceptCommissioningStart: {
     352            0 :         err = CHIP_ERROR_INCORRECT_STATE;
     353              : #if CHIP_ERROR_LOGGING
     354            0 :         messageIfError = "Just got a connected device; how can we be done?";
     355              : #endif // CHIP_ERROR_LOGGING
     356            0 :         break;
     357              :     }
     358              :     }
     359              : 
     360            0 :     if (err != CHIP_NO_ERROR)
     361              :     {
     362            0 :         ChipLogError(Controller, "%s: %" CHIP_ERROR_FORMAT, messageIfError, err.Format());
     363            0 :         OnOpenCommissioningWindowFailure(context, err);
     364              :     }
     365            0 : }
     366              : 
     367            0 : void CommissioningWindowOpener::OnDeviceConnectionFailureCallback(void * context, const ScopedNodeId & peerId, CHIP_ERROR error)
     368              : {
     369            0 :     OnOpenCommissioningWindowFailure(context, error);
     370            0 : }
     371              : 
     372            0 : AutoCommissioningWindowOpener::AutoCommissioningWindowOpener(DeviceController * controller) :
     373            0 :     CommissioningWindowOpener(controller), mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this),
     374            0 :     mOnOpenBasicCommissioningWindowCallback(OnOpenBasicCommissioningWindowResponse, this)
     375            0 : {}
     376              : 
     377            0 : CHIP_ERROR AutoCommissioningWindowOpener::OpenBasicCommissioningWindow(DeviceController * controller, NodeId deviceId,
     378              :                                                                        Seconds16 timeout)
     379              : {
     380              :     // Not using Platform::New because we want to keep our constructor private.
     381            0 :     auto * opener = new (std::nothrow) AutoCommissioningWindowOpener(controller);
     382            0 :     if (opener == nullptr)
     383              :     {
     384            0 :         return CHIP_ERROR_NO_MEMORY;
     385              :     }
     386              : 
     387            0 :     CHIP_ERROR err = opener->CommissioningWindowOpener::OpenBasicCommissioningWindow(
     388              :         deviceId, timeout, &opener->mOnOpenBasicCommissioningWindowCallback);
     389            0 :     if (err != CHIP_NO_ERROR)
     390              :     {
     391            0 :         delete opener;
     392              :     }
     393              :     // Else will clean up when the callback is called.
     394            0 :     return err;
     395              : }
     396              : 
     397            0 : CHIP_ERROR AutoCommissioningWindowOpener::OpenCommissioningWindow(DeviceController * controller, NodeId deviceId, Seconds16 timeout,
     398              :                                                                   uint32_t iteration, uint16_t discriminator,
     399              :                                                                   Optional<uint32_t> setupPIN, Optional<ByteSpan> salt,
     400              :                                                                   SetupPayload & payload, bool readVIDPIDAttributes)
     401              : {
     402              :     // Not using Platform::New because we want to keep our constructor private.
     403            0 :     auto * opener = new (std::nothrow) AutoCommissioningWindowOpener(controller);
     404            0 :     if (opener == nullptr)
     405              :     {
     406            0 :         return CHIP_ERROR_NO_MEMORY;
     407              :     }
     408              : 
     409            0 :     CHIP_ERROR err = opener->CommissioningWindowOpener::OpenCommissioningWindow(
     410              :         deviceId, timeout, iteration, discriminator, setupPIN, salt, &opener->mOnOpenCommissioningWindowCallback, payload,
     411              :         readVIDPIDAttributes);
     412            0 :     if (err != CHIP_NO_ERROR)
     413              :     {
     414            0 :         delete opener;
     415              :     }
     416              :     // Else will clean up when the callback is called.
     417            0 :     return err;
     418              : }
     419              : 
     420            0 : void AutoCommissioningWindowOpener::OnOpenCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status,
     421              :                                                                       chip::SetupPayload payload)
     422              : {
     423            0 :     auto * self = static_cast<AutoCommissioningWindowOpener *>(context);
     424            0 :     delete self;
     425            0 : }
     426            0 : void AutoCommissioningWindowOpener::OnOpenBasicCommissioningWindowResponse(void * context, NodeId deviceId, CHIP_ERROR status)
     427              : {
     428            0 :     auto * self = static_cast<AutoCommissioningWindowOpener *>(context);
     429            0 :     delete self;
     430            0 : }
     431              : 
     432              : } // namespace Controller
     433              : } // namespace chip
        

Generated by: LCOV version 2.0-1