From 28922925b7783a0cbca4d75f57eaf2bec79ae8b6 Mon Sep 17 00:00:00 2001
From: Yufeng Wang <yufengwang@google.com>
Date: Wed, 17 Jul 2024 00:01:49 -0700
Subject: [PATCH 01/14] Implement Commissioner Control cluster server

---
 .../fabric-bridge-app.matter                  |  66 +++++
 .../fabric-bridge-app.zap                     | 158 +++++++++++
 .../fabric-bridge-common/src/ZCLCallbacks.cpp |  11 +
 .../commissioner-control-server.cpp           | 251 ++++++++++++++++++
 .../commissioner-control-server.h             |  99 +++++++
 5 files changed, 585 insertions(+)
 create mode 100644 src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
 create mode 100644 src/app/clusters/commissioner-control-server/commissioner-control-server.h

diff --git a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter
index 7f3de425528f64..46bd51d578e6ee 100644
--- a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter
+++ b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.matter
@@ -1334,6 +1334,57 @@ cluster GroupKeyManagement = 63 {
   fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4;
 }
 
+/** Supports the ability for clients to request the commissioning of themselves or other nodes onto a fabric which the cluster server can commission onto. */
+provisional cluster CommissionerControl = 1873 {
+  revision 1;
+
+  bitmap SupportedDeviceCategoryBitmap : bitmap32 {
+    kFabricSynchronization = 0x1;
+  }
+
+  fabric_sensitive info event access(read: manage) CommissioningRequestResult = 0 {
+    int64u requestId = 0;
+    node_id clientNodeId = 1;
+    enum8 statusCode = 2;
+    fabric_idx fabricIndex = 254;
+  }
+
+  readonly attribute access(read: manage) SupportedDeviceCategoryBitmap supportedDeviceCategories = 0;
+  readonly attribute command_id generatedCommandList[] = 65528;
+  readonly attribute command_id acceptedCommandList[] = 65529;
+  readonly attribute event_id eventList[] = 65530;
+  readonly attribute attrib_id attributeList[] = 65531;
+  readonly attribute bitmap32 featureMap = 65532;
+  readonly attribute int16u clusterRevision = 65533;
+
+  request struct RequestCommissioningApprovalRequest {
+    int64u requestId = 0;
+    vendor_id vendorId = 1;
+    int16u productId = 2;
+    optional char_string<64> label = 3;
+  }
+
+  request struct CommissionNodeRequest {
+    int64u requestId = 0;
+    int16u responseTimeoutSeconds = 1;
+    optional octet_string ipAddress = 2;
+    optional int16u port = 3;
+  }
+
+  response struct ReverseOpenCommissioningWindow = 2 {
+    int16u commissioningTimeout = 0;
+    octet_string PAKEPasscodeVerifier = 1;
+    int16u discriminator = 2;
+    int32u iterations = 3;
+    octet_string<32> salt = 4;
+  }
+
+  /** This command is sent by a client to request approval for a future CommissionNode call. */
+  command access(invoke: manage) RequestCommissioningApproval(RequestCommissioningApprovalRequest): DefaultSuccess = 0;
+  /** This command is sent by a client to request that the server begins commissioning a previously approved request. */
+  command access(invoke: manage) CommissionNode(CommissionNodeRequest): ReverseOpenCommissioningWindow = 1;
+}
+
 endpoint 0 {
   device type ma_rootdevice = 22, version 1;
 
@@ -1647,6 +1698,21 @@ endpoint 0 {
     handle command KeySetReadAllIndices;
     handle command KeySetReadAllIndicesResponse;
   }
+
+  server cluster CommissionerControl {
+    emits event CommissioningRequestResult;
+    ram      attribute supportedDeviceCategories default = 0;
+    callback attribute generatedCommandList;
+    callback attribute acceptedCommandList;
+    callback attribute eventList;
+    callback attribute attributeList;
+    ram      attribute featureMap default = 0;
+    ram      attribute clusterRevision default = 1;
+
+    handle command RequestCommissioningApproval;
+    handle command CommissionNode;
+    handle command ReverseOpenCommissioningWindow;
+  }
 }
 endpoint 1 {
   device type ma_aggregator = 14, version 1;
diff --git a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.zap b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.zap
index cbf31a039b85ee..6345745cde4fce 100644
--- a/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.zap
+++ b/examples/fabric-bridge-app/fabric-bridge-common/fabric-bridge-app.zap
@@ -4003,6 +4003,164 @@
               "reportableChange": 0
             }
           ]
+        },
+        {
+          "name": "Commissioner Control",
+          "code": 1873,
+          "mfgCode": null,
+          "define": "COMMISSIONER_CONTROL_CLUSTER",
+          "side": "server",
+          "enabled": 1,
+          "apiMaturity": "provisional",
+          "commands": [
+            {
+              "name": "RequestCommissioningApproval",
+              "code": 0,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "CommissionNode",
+              "code": 1,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "ReverseOpenCommissioningWindow",
+              "code": 2,
+              "mfgCode": null,
+              "source": "server",
+              "isIncoming": 0,
+              "isEnabled": 1
+            }
+          ],
+          "attributes": [
+            {
+              "name": "SupportedDeviceCategories",
+              "code": 0,
+              "mfgCode": null,
+              "side": "server",
+              "type": "SupportedDeviceCategoryBitmap",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "0",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "GeneratedCommandList",
+              "code": 65528,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AcceptedCommandList",
+              "code": 65529,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EventList",
+              "code": 65530,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AttributeList",
+              "code": 65531,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "FeatureMap",
+              "code": 65532,
+              "mfgCode": null,
+              "side": "server",
+              "type": "bitmap32",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "0",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "ClusterRevision",
+              "code": 65533,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int16u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "1",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            }
+          ],
+          "events": [
+            {
+              "name": "CommissioningRequestResult",
+              "code": 0,
+              "mfgCode": null,
+              "side": "server",
+              "included": 1
+            }
+          ]
         }
       ]
     },
diff --git a/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp b/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp
index 7a9521fa7820a7..ca3adddbc642ef 100644
--- a/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp
+++ b/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp
@@ -20,6 +20,7 @@
 #include <app-common/zap-generated/cluster-objects.h>
 #include <app-common/zap-generated/ids/Attributes.h>
 #include <app-common/zap-generated/ids/Clusters.h>
+#include <app/clusters/commissioner-control-server/commissioner-control-server.h>
 #include <lib/support/ZclString.h>
 
 using namespace ::chip;
@@ -90,3 +91,13 @@ Protocols::InteractionModel::Status emberAfExternalAttributeWriteCallback(Endpoi
 
     return ret;
 }
+
+void MatterCommissionerControlPluginServerInitCallback()
+{
+    ChipLogProgress(Zcl, "MatterCommissionerControlPluginServerInitCallback");
+
+    BitMask<CommissionerControl::SupportedDeviceCategoryBitmap> supportedDeviceCategories;
+    supportedDeviceCategories.SetField(CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1);
+    CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue(kRootEndpointId,
+                                                                                                 supportedDeviceCategories);
+}
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
new file mode 100644
index 00000000000000..d89c5729f9ada1
--- /dev/null
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -0,0 +1,251 @@
+/*
+ *
+ *    Copyright (c) 2024 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.
+ */
+#include "commissioner-control-server.h"
+
+#include <protocols/interaction_model/StatusCode.h>
+
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <app-common/zap-generated/cluster-enums.h>
+#include <app-common/zap-generated/cluster-objects.h>
+#include <app/AttributeAccessInterface.h>
+#include <app/AttributeAccessInterfaceRegistry.h>
+#include <app/CommandHandler.h>
+#include <app/EventLogging.h>
+#include <app/reporting/reporting.h>
+#include <platform/PlatformManager.h>
+
+#include <memory> // For std::shared_ptr
+
+using namespace chip;
+using namespace chip::app;
+
+using chip::Protocols::InteractionModel::Status;
+
+namespace {
+
+NodeId getNodeId(const app::CommandHandler * commandObj)
+{
+    if (nullptr == commandObj || nullptr == commandObj->GetExchangeContext())
+    {
+        ChipLogError(Zcl, "Cannot access ExchangeContext of Command Object for Node ID");
+        return kUndefinedNodeId;
+    }
+
+    if (!commandObj->GetExchangeContext()->HasSessionHandle())
+    {
+        ChipLogError(Zcl, "Cannot access session of Command Object for Node ID");
+        return kUndefinedNodeId;
+    }
+
+    auto descriptor = commandObj->GetExchangeContext()->GetSessionHandle()->GetSubjectDescriptor();
+    if (descriptor.authMode != Access::AuthMode::kCase)
+    {
+        ChipLogError(Zcl, "Cannot get Node ID from non-CASE session of Command Object");
+        return kUndefinedNodeId;
+    }
+
+    return descriptor.subject;
+}
+
+void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, const ConcreteCommandPath & path,
+                                               const Clusters::CommissionerControl::CommissioningWindowParams & params)
+{
+    Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::Type response;
+    response.commissioningTimeout = params.commissioningTimeout;
+    response.discriminator        = params.discriminator;
+    response.iterations           = params.iterations;
+    response.PAKEPasscodeVerifier = params.PAKEPasscodeVerifier;
+    response.salt                 = params.salt;
+
+    commandObj->AddResponse(path, response);
+}
+
+void RunDeferredCommissionNode(intptr_t commandArg)
+{
+    auto * info = reinterpret_cast<Clusters::CommissionerControl::CommissionNodeInfo *>(commandArg);
+
+    Clusters::CommissionerControl::Delegate * delegate =
+        Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();
+
+    if (delegate != nullptr)
+    {
+        CHIP_ERROR err = delegate->ReverseCommissionNode(info->params, info->ipAddress, info->port);
+        if (err != CHIP_NO_ERROR)
+        {
+            ChipLogError(Zcl, "ReverseCommissionNode error: %s", err.AsString());
+        }
+    }
+    else
+    {
+        ChipLogError(Zcl, "No delegate available for ReverseCommissionNode");
+    }
+
+    delete info;
+}
+
+} // namespace
+
+namespace chip {
+namespace app {
+namespace Clusters {
+namespace CommissionerControl {
+
+CommissionerControlServer CommissionerControlServer::instance;
+
+CommissionerControlServer & CommissionerControlServer::Instance()
+{
+    return instance;
+}
+
+CHIP_ERROR CommissionerControlServer::Init(Delegate & delegate)
+{
+    mDelegate = &delegate;
+    return CHIP_NO_ERROR;
+}
+
+Protocols::InteractionModel::Status CommissionerControlServer::GetSupportedDeviceCategoriesValue(
+    EndpointId endpoint, BitMask<SupportedDeviceCategoryBitmap> * supportedDeviceCategories) const
+{
+    Status status = Attributes::SupportedDeviceCategories::Get(endpoint, supportedDeviceCategories);
+    if (status != Status::Success)
+    {
+        ChipLogProgress(Zcl, "CommissionerControl: reading  supportedDeviceCategories, err:0x%x", to_underlying(status));
+    }
+    return status;
+}
+
+Protocols::InteractionModel::Status
+CommissionerControlServer::SetSupportedDeviceCategoriesValue(EndpointId endpoint,
+                                                             const BitMask<SupportedDeviceCategoryBitmap> supportedDeviceCategories)
+{
+    Status status = Status::Success;
+
+    if ((status = Attributes::SupportedDeviceCategories::Set(endpoint, supportedDeviceCategories)) != Status::Success)
+    {
+        ChipLogProgress(Zcl, "CommissionerControl: writing supportedDeviceCategories, err:0x%x", to_underlying(status));
+        return status;
+    }
+
+    return status;
+}
+
+CHIP_ERROR CommissionerControlServer::EmitCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result)
+{
+    EventNumber eventNumber;
+    CHIP_ERROR error = LogEvent(result, kRootEndpointId, eventNumber);
+    if (CHIP_NO_ERROR != error)
+    {
+        ChipLogError(Zcl, "CommissionerControl: Unable to emit CommissioningRequestResult event: %s", error.AsString());
+    }
+
+    return error;
+}
+
+} // namespace CommissionerControl
+} // namespace Clusters
+} // namespace app
+} // namespace chip
+
+bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
+    app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
+    const Clusters::CommissionerControl::Commands::RequestCommissioningApproval::DecodableType & commandData)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    Status status  = Status::Success;
+
+    ChipLogProgress(Zcl, "Received command to request commissioning approval");
+
+    auto sourceNodeId = getNodeId(commandObj);
+    auto fabricIndex  = commandObj->GetAccessingFabricIndex();
+    auto requestId    = commandData.requestId;
+    auto vendorId     = commandData.vendorId;
+    auto productId    = commandData.productId;
+    auto & label      = commandData.label;
+
+    // Create a CommissioningApprovalRequest struct and populate it with the command data
+    Clusters::CommissionerControl::CommissioningApprovalRequest request = { .requestId    = requestId,
+                                                                            .vendorId     = vendorId,
+                                                                            .productId    = productId,
+                                                                            .clientNodeId = sourceNodeId,
+                                                                            .fabricIndex  = fabricIndex,
+                                                                            .label        = label };
+
+    Clusters::CommissionerControl::Delegate * delegate =
+        Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();
+
+    VerifyOrExit(sourceNodeId != kUndefinedNodeId, err = CHIP_ERROR_WRONG_NODE_ID);
+    VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
+
+    // Handle commissioning approval request
+    err = delegate->HandleCommissioningApprovalRequest(request);
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %s", err.AsString());
+        status = Status::Failure;
+    }
+
+    commandObj->AddStatus(commandPath, status);
+    return true;
+}
+
+bool emberAfCommissionerControlClusterCommissionNodeCallback(
+    app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
+    const Clusters::CommissionerControl::Commands::CommissionNode::DecodableType & commandData)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    Status status  = Status::Success;
+
+    ChipLogProgress(Zcl, "Received command to commission node");
+
+    auto sourceNodeId = getNodeId(commandObj);
+    auto requestId    = commandData.requestId;
+
+    auto info       = std::make_unique<Clusters::CommissionerControl::CommissionNodeInfo>();
+    info->ipAddress = commandData.ipAddress;
+    info->port      = commandData.port;
+
+    Clusters::CommissionerControl::Delegate * delegate =
+        Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();
+
+    VerifyOrExit(sourceNodeId != kUndefinedNodeId, err = CHIP_ERROR_WRONG_NODE_ID);
+    VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
+
+    // Handle commissioning approval request
+    err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId, info->params);
+    VerifyOrExit(err == CHIP_NO_ERROR, err = CHIP_ERROR_INCORRECT_STATE);
+
+    // Add the response for the commissioning window
+    AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, info->params);
+
+    // Schedule the deferred reverse commission node task
+    DeviceLayer::PlatformMgr().ScheduleWork(RunDeferredCommissionNode, reinterpret_cast<intptr_t>(info.release()));
+
+    return true;
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(Zcl, "emberAfCommissionerControlClusterCommissionNodeCallback error: %s", err.AsString());
+        status = Status::Failure;
+    }
+
+    commandObj->AddStatus(commandPath, status);
+    return true;
+}
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
new file mode 100644
index 00000000000000..1e518b552e421f
--- /dev/null
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -0,0 +1,99 @@
+/*
+ *
+ *    Copyright (c) 2024 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.
+ */
+#pragma once
+
+#include <app-common/zap-generated/cluster-objects.h>
+
+namespace chip {
+namespace app {
+namespace Clusters {
+namespace CommissionerControl {
+
+struct CommissioningApprovalRequest
+{
+    uint64_t requestId;
+    VendorId vendorId;
+    uint16_t productId;
+    NodeId clientNodeId;
+    FabricIndex fabricIndex;
+    Optional<chip::CharSpan> label;
+};
+
+struct CommissioningWindowParams
+{
+    uint32_t iterations;
+    uint16_t commissioningTimeout;
+    uint16_t discriminator;
+    ByteSpan PAKEPasscodeVerifier;
+    ByteSpan salt;
+};
+
+struct CommissionNodeInfo
+{
+    CommissioningWindowParams params;
+    Optional<ByteSpan> ipAddress;
+    Optional<uint16_t> port;
+};
+
+class Delegate
+{
+public:
+    // Command Delegates
+    virtual CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) = 0;
+    virtual CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId,
+                                                     CommissioningWindowParams & outParams)             = 0;
+    virtual CHIP_ERROR ReverseCommissionNode(const CommissioningWindowParams & params, const Optional<ByteSpan> & ipAddress,
+                                             const Optional<uint16_t> & port)                           = 0;
+    virtual ~Delegate()                                                                                 = default;
+};
+
+class CommissionerControlServer
+{
+public:
+    static CommissionerControlServer & Instance();
+
+    CHIP_ERROR Init(Delegate & delegate);
+
+    Delegate * GetDelegate() { return mDelegate; }
+
+    Protocols::InteractionModel::Status
+    GetSupportedDeviceCategoriesValue(EndpointId endpoint,
+                                      BitMask<SupportedDeviceCategoryBitmap> * supportedDeviceCategories) const;
+
+    Protocols::InteractionModel::Status
+    SetSupportedDeviceCategoriesValue(EndpointId endpoint, const BitMask<SupportedDeviceCategoryBitmap> supportedDeviceCategories);
+
+    /**
+     * @brief
+     *   Called after the server return SUCCESS to a correctly formatted RequestCommissioningApproval command.
+     */
+    CHIP_ERROR EmitCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result);
+
+private:
+    CommissionerControlServer()  = default;
+    ~CommissionerControlServer() = default;
+
+    static CommissionerControlServer instance;
+
+    Delegate * mDelegate = nullptr;
+};
+
+} // namespace CommissionerControl
+} // namespace Clusters
+} // namespace app
+} // namespace chip

From 801ddc6981cc72ea6fd386a5dd1e3c78a1da1468 Mon Sep 17 00:00:00 2001
From: Yufeng Wang <yufengwang@google.com>
Date: Wed, 17 Jul 2024 18:23:22 -0700
Subject: [PATCH 02/14] Update
 src/app/clusters/commissioner-control-server/commissioner-control-server.cpp

Co-authored-by: Terence Hampson <thampson@google.com>
---
 .../commissioner-control-server/commissioner-control-server.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index d89c5729f9ada1..20f66f3cbc6b1d 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -229,7 +229,7 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
     // Handle commissioning approval request
     err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId, info->params);
-    VerifyOrExit(err == CHIP_NO_ERROR, err = CHIP_ERROR_INCORRECT_STATE);
+    VerifyOrExit(err == CHIP_NO_ERROR);
 
     // Add the response for the commissioning window
     AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, info->params);

From c804c985ed72cd80f07dba7ea52b6943ca95516c Mon Sep 17 00:00:00 2001
From: Yufeng Wang <yufengwang@google.com>
Date: Wed, 17 Jul 2024 20:33:24 -0700
Subject: [PATCH 03/14] Address review comments

---
 .../commissioner-control-server.cpp           | 34 ++++---------------
 .../commissioner-control-server.h             |  2 +-
 2 files changed, 8 insertions(+), 28 deletions(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index 20f66f3cbc6b1d..0b25c7db7fcdbf 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -29,7 +29,7 @@
 #include <app/reporting/reporting.h>
 #include <platform/PlatformManager.h>
 
-#include <memory> // For std::shared_ptr
+#include <memory>
 
 using namespace chip;
 using namespace chip::app;
@@ -40,24 +40,8 @@ namespace {
 
 NodeId getNodeId(const app::CommandHandler * commandObj)
 {
-    if (nullptr == commandObj || nullptr == commandObj->GetExchangeContext())
-    {
-        ChipLogError(Zcl, "Cannot access ExchangeContext of Command Object for Node ID");
-        return kUndefinedNodeId;
-    }
-
-    if (!commandObj->GetExchangeContext()->HasSessionHandle())
-    {
-        ChipLogError(Zcl, "Cannot access session of Command Object for Node ID");
-        return kUndefinedNodeId;
-    }
-
-    auto descriptor = commandObj->GetExchangeContext()->GetSessionHandle()->GetSubjectDescriptor();
-    if (descriptor.authMode != Access::AuthMode::kCase)
-    {
-        ChipLogError(Zcl, "Cannot get Node ID from non-CASE session of Command Object");
-        return kUndefinedNodeId;
-    }
+    VerifyOrDie(commandObj);
+    auto descriptor = commandObj->GetSubjectDescriptor();
 
     return descriptor.subject;
 }
@@ -105,11 +89,11 @@ namespace app {
 namespace Clusters {
 namespace CommissionerControl {
 
-CommissionerControlServer CommissionerControlServer::instance;
+CommissionerControlServer CommissionerControlServer::mInstance;
 
 CommissionerControlServer & CommissionerControlServer::Instance()
 {
-    return instance;
+    return mInstance;
 }
 
 CHIP_ERROR CommissionerControlServer::Init(Delegate & delegate)
@@ -210,7 +194,6 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
     const Clusters::CommissionerControl::Commands::CommissionNode::DecodableType & commandData)
 {
     CHIP_ERROR err = CHIP_NO_ERROR;
-    Status status  = Status::Success;
 
     ChipLogProgress(Zcl, "Received command to commission node");
 
@@ -229,7 +212,7 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
     // Handle commissioning approval request
     err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId, info->params);
-    VerifyOrExit(err == CHIP_NO_ERROR);
+    SuccessOrExit(err == CHIP_NO_ERROR);
 
     // Add the response for the commissioning window
     AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, info->params);
@@ -237,15 +220,12 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
     // Schedule the deferred reverse commission node task
     DeviceLayer::PlatformMgr().ScheduleWork(RunDeferredCommissionNode, reinterpret_cast<intptr_t>(info.release()));
 
-    return true;
-
 exit:
     if (err != CHIP_NO_ERROR)
     {
         ChipLogError(Zcl, "emberAfCommissionerControlClusterCommissionNodeCallback error: %s", err.AsString());
-        status = Status::Failure;
+        commandObj->AddStatus(commandPath, Status::Failure);
     }
 
-    commandObj->AddStatus(commandPath, status);
     return true;
 }
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
index 1e518b552e421f..db9d596f5176a1 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -88,7 +88,7 @@ class CommissionerControlServer
     CommissionerControlServer()  = default;
     ~CommissionerControlServer() = default;
 
-    static CommissionerControlServer instance;
+    static CommissionerControlServer mInstance;
 
     Delegate * mDelegate = nullptr;
 };

From 6f17e1deaf38bf4c8d10e5dc9d6cab8283eddb07 Mon Sep 17 00:00:00 2001
From: Yufeng Wang <yufengwang@google.com>
Date: Thu, 18 Jul 2024 10:08:11 -0700
Subject: [PATCH 04/14] Update
 src/app/clusters/commissioner-control-server/commissioner-control-server.cpp

Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
---
 .../commissioner-control-server/commissioner-control-server.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index 0b25c7db7fcdbf..767ff1be2fc38a 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -128,7 +128,7 @@ CommissionerControlServer::SetSupportedDeviceCategoriesValue(EndpointId endpoint
     return status;
 }
 
-CHIP_ERROR CommissionerControlServer::EmitCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result)
+CHIP_ERROR CommissionerControlServer::GenerateCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result)
 {
     EventNumber eventNumber;
     CHIP_ERROR error = LogEvent(result, kRootEndpointId, eventNumber);

From 4f6c80dc9d8ac6243b02b6c0df133f8b980b35e0 Mon Sep 17 00:00:00 2001
From: Yufeng Wang <yufengwang@google.com>
Date: Thu, 18 Jul 2024 10:08:47 -0700
Subject: [PATCH 05/14] Update
 src/app/clusters/commissioner-control-server/commissioner-control-server.h

Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
---
 .../commissioner-control-server/commissioner-control-server.h   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
index db9d596f5176a1..b3f568ba5ce9ff 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -31,7 +31,7 @@ struct CommissioningApprovalRequest
     uint16_t productId;
     NodeId clientNodeId;
     FabricIndex fabricIndex;
-    Optional<chip::CharSpan> label;
+    Optional<CharSpan> label;
 };
 
 struct CommissioningWindowParams

From b4513058bbc429f858a1a6f574e03608c8f62889 Mon Sep 17 00:00:00 2001
From: Yufeng Wang <yufengwang@google.com>
Date: Thu, 18 Jul 2024 12:07:34 -0700
Subject: [PATCH 06/14] Move MatterCommissionerControlPluginServerInitCallback
 from application to SDK

---
 .../fabric-bridge-common/src/ZCLCallbacks.cpp | 11 -------
 examples/fabric-bridge-app/linux/main.cpp     | 13 ++++++++
 .../commissioner-control-server.cpp           | 31 +++++++++++--------
 .../commissioner-control-server.h             |  2 +-
 4 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp b/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp
index ca3adddbc642ef..7a9521fa7820a7 100644
--- a/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp
+++ b/examples/fabric-bridge-app/fabric-bridge-common/src/ZCLCallbacks.cpp
@@ -20,7 +20,6 @@
 #include <app-common/zap-generated/cluster-objects.h>
 #include <app-common/zap-generated/ids/Attributes.h>
 #include <app-common/zap-generated/ids/Clusters.h>
-#include <app/clusters/commissioner-control-server/commissioner-control-server.h>
 #include <lib/support/ZclString.h>
 
 using namespace ::chip;
@@ -91,13 +90,3 @@ Protocols::InteractionModel::Status emberAfExternalAttributeWriteCallback(Endpoi
 
     return ret;
 }
-
-void MatterCommissionerControlPluginServerInitCallback()
-{
-    ChipLogProgress(Zcl, "MatterCommissionerControlPluginServerInitCallback");
-
-    BitMask<CommissionerControl::SupportedDeviceCategoryBitmap> supportedDeviceCategories;
-    supportedDeviceCategories.SetField(CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1);
-    CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue(kRootEndpointId,
-                                                                                                 supportedDeviceCategories);
-}
diff --git a/examples/fabric-bridge-app/linux/main.cpp b/examples/fabric-bridge-app/linux/main.cpp
index 0aa22b8445ee56..6312b3367aad38 100644
--- a/examples/fabric-bridge-app/linux/main.cpp
+++ b/examples/fabric-bridge-app/linux/main.cpp
@@ -23,6 +23,7 @@
 #include "DeviceManager.h"
 
 #include <app/AttributeAccessInterfaceRegistry.h>
+#include <app/clusters/commissioner-control-server/commissioner-control-server.h>
 
 #if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
 #include "RpcClient.h"
@@ -167,6 +168,18 @@ void ApplicationInit()
     pollingThread.detach();
 
     DeviceMgr().Init();
+
+    ChipLogProgress(Zcl, "Initialize SupportedDeviceCategories of Commissioner Control Cluster for this device.");
+
+    BitMask<CommissionerControl::SupportedDeviceCategoryBitmap> supportedDeviceCategories;
+    supportedDeviceCategories.SetField(CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1);
+    Protocols::InteractionModel::Status status =
+        CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue(kRootEndpointId,
+                                                                                                     supportedDeviceCategories);
+    if (status != Protocols::InteractionModel::Status::Success)
+    {
+        ChipLogError(NotSpecified, "Failed to set SupportedDeviceCategories: %d", static_cast<int>(status));
+    }
 }
 
 void ApplicationShutdown()
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index 767ff1be2fc38a..1f562d2fbcc5a2 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -38,14 +38,6 @@ using chip::Protocols::InteractionModel::Status;
 
 namespace {
 
-NodeId getNodeId(const app::CommandHandler * commandObj)
-{
-    VerifyOrDie(commandObj);
-    auto descriptor = commandObj->GetSubjectDescriptor();
-
-    return descriptor.subject;
-}
-
 void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, const ConcreteCommandPath & path,
                                                const Clusters::CommissionerControl::CommissioningWindowParams & params)
 {
@@ -128,7 +120,8 @@ CommissionerControlServer::SetSupportedDeviceCategoriesValue(EndpointId endpoint
     return status;
 }
 
-CHIP_ERROR CommissionerControlServer::GenerateCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result)
+CHIP_ERROR
+CommissionerControlServer::GenerateCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result)
 {
     EventNumber eventNumber;
     CHIP_ERROR error = LogEvent(result, kRootEndpointId, eventNumber);
@@ -154,12 +147,16 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
 
     ChipLogProgress(Zcl, "Received command to request commissioning approval");
 
-    auto sourceNodeId = getNodeId(commandObj);
+    auto descriptor   = commandObj->GetSubjectDescriptor();
+    auto sourceNodeId = descriptor.subject;
     auto fabricIndex  = commandObj->GetAccessingFabricIndex();
     auto requestId    = commandData.requestId;
     auto vendorId     = commandData.vendorId;
     auto productId    = commandData.productId;
-    auto & label      = commandData.label;
+
+    // The label assigned from commandData need to be stored in CommissionerControl::Delegate which ensure that the backing buffer
+    // of it has a valid lifespan during fabric sync setup process.
+    auto & label = commandData.label;
 
     // Create a CommissioningApprovalRequest struct and populate it with the command data
     Clusters::CommissionerControl::CommissioningApprovalRequest request = { .requestId    = requestId,
@@ -197,7 +194,8 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
     ChipLogProgress(Zcl, "Received command to commission node");
 
-    auto sourceNodeId = getNodeId(commandObj);
+    auto descriptor   = commandObj->GetSubjectDescriptor();
+    auto sourceNodeId = descriptor.subject;
     auto requestId    = commandData.requestId;
 
     auto info       = std::make_unique<Clusters::CommissionerControl::CommissionNodeInfo>();
@@ -210,7 +208,9 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
     VerifyOrExit(sourceNodeId != kUndefinedNodeId, err = CHIP_ERROR_WRONG_NODE_ID);
     VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
 
-    // Handle commissioning approval request
+    // Handle commissioning approval request, the ipAddress assigned from commandData need to be stored in
+    // CommissionerControl::Delegate which ensure that the backing buffer of ipAddress has a valid lifespan until the deferred task
+    // is executed.
     err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId, info->params);
     SuccessOrExit(err == CHIP_NO_ERROR);
 
@@ -229,3 +229,8 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
     return true;
 }
+
+void MatterCommissionerControlPluginServerInitCallback()
+{
+    ChipLogProgress(Zcl, "Initiating Commissioner Control cluster.");
+}
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
index b3f568ba5ce9ff..9ded85c533831e 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -82,7 +82,7 @@ class CommissionerControlServer
      * @brief
      *   Called after the server return SUCCESS to a correctly formatted RequestCommissioningApproval command.
      */
-    CHIP_ERROR EmitCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result);
+    CHIP_ERROR GenerateCommissioningRequestResultEvent(const Events::CommissioningRequestResult::Type & result);
 
 private:
     CommissionerControlServer()  = default;

From d96cfbcd66e368f7ae18b6fb311658d043df3841 Mon Sep 17 00:00:00 2001
From: Yufeng Wang <yufengwang@google.com>
Date: Thu, 18 Jul 2024 14:27:22 -0700
Subject: [PATCH 07/14] Return kUndefinedNodeId if get the NodeID from a group
 or PASE session.

---
 examples/fabric-bridge-app/linux/main.cpp     | 13 ---
 .../commissioner-control-server.cpp           | 53 ++++++++---
 .../commissioner-control-server.h             | 91 ++++++++++++++++++-
 3 files changed, 125 insertions(+), 32 deletions(-)

diff --git a/examples/fabric-bridge-app/linux/main.cpp b/examples/fabric-bridge-app/linux/main.cpp
index 6312b3367aad38..0aa22b8445ee56 100644
--- a/examples/fabric-bridge-app/linux/main.cpp
+++ b/examples/fabric-bridge-app/linux/main.cpp
@@ -23,7 +23,6 @@
 #include "DeviceManager.h"
 
 #include <app/AttributeAccessInterfaceRegistry.h>
-#include <app/clusters/commissioner-control-server/commissioner-control-server.h>
 
 #if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
 #include "RpcClient.h"
@@ -168,18 +167,6 @@ void ApplicationInit()
     pollingThread.detach();
 
     DeviceMgr().Init();
-
-    ChipLogProgress(Zcl, "Initialize SupportedDeviceCategories of Commissioner Control Cluster for this device.");
-
-    BitMask<CommissionerControl::SupportedDeviceCategoryBitmap> supportedDeviceCategories;
-    supportedDeviceCategories.SetField(CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1);
-    Protocols::InteractionModel::Status status =
-        CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue(kRootEndpointId,
-                                                                                                     supportedDeviceCategories);
-    if (status != Protocols::InteractionModel::Status::Success)
-    {
-        ChipLogError(NotSpecified, "Failed to set SupportedDeviceCategories: %d", static_cast<int>(status));
-    }
 }
 
 void ApplicationShutdown()
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index 1f562d2fbcc5a2..d9be46efcc9aa5 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -38,6 +38,32 @@ using chip::Protocols::InteractionModel::Status;
 
 namespace {
 
+NodeId getNodeId(const app::CommandHandler * commandObj)
+{
+    if (nullptr == commandObj || nullptr == commandObj->GetExchangeContext())
+    {
+        ChipLogError(Zcl, "Cannot access ExchangeContext of Command Object for Node ID");
+        return kUndefinedNodeId;
+    }
+
+    if (!commandObj->GetExchangeContext()->HasSessionHandle())
+    {
+        ChipLogError(Zcl, "Cannot access session of Command Object for Node ID");
+        return kUndefinedNodeId;
+    }
+
+    auto descriptor = commandObj->GetExchangeContext()->GetSessionHandle()->GetSubjectDescriptor();
+
+    // Return kUndefinedNodeId if get the NodeID from a group or PASE session.
+    if (descriptor.authMode != Access::AuthMode::kCase)
+    {
+        ChipLogError(Zcl, "Cannot get Node ID from non-CASE session of Command Object");
+        return kUndefinedNodeId;
+    }
+
+    return descriptor.subject;
+}
+
 void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, const ConcreteCommandPath & path,
                                                const Clusters::CommissionerControl::CommissioningWindowParams & params)
 {
@@ -147,8 +173,7 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
 
     ChipLogProgress(Zcl, "Received command to request commissioning approval");
 
-    auto descriptor   = commandObj->GetSubjectDescriptor();
-    auto sourceNodeId = descriptor.subject;
+    auto sourceNodeId = getNodeId(commandObj);
     auto fabricIndex  = commandObj->GetAccessingFabricIndex();
     auto requestId    = commandData.requestId;
     auto vendorId     = commandData.vendorId;
@@ -194,13 +219,10 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
     ChipLogProgress(Zcl, "Received command to commission node");
 
-    auto descriptor   = commandObj->GetSubjectDescriptor();
-    auto sourceNodeId = descriptor.subject;
+    auto sourceNodeId = getNodeId(commandObj);
     auto requestId    = commandData.requestId;
 
-    auto info       = std::make_unique<Clusters::CommissionerControl::CommissionNodeInfo>();
-    info->ipAddress = commandData.ipAddress;
-    info->port      = commandData.port;
+    auto commissionNodeInfo = std::make_unique<Clusters::CommissionerControl::CommissionNodeInfo>();
 
     Clusters::CommissionerControl::Delegate * delegate =
         Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();
@@ -208,17 +230,20 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
     VerifyOrExit(sourceNodeId != kUndefinedNodeId, err = CHIP_ERROR_WRONG_NODE_ID);
     VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
 
-    // Handle commissioning approval request, the ipAddress assigned from commandData need to be stored in
-    // CommissionerControl::Delegate which ensure that the backing buffer of ipAddress has a valid lifespan until the deferred task
-    // is executed.
-    err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId, info->params);
+    // Set IP address and port in the CommissionNodeInfo struct
+    commissionNodeInfo->port = commandData.port;
+    err                      = commissionNodeInfo->SetIPAddress(commandData.ipAddress);
+    SuccessOrExit(err == CHIP_NO_ERROR);
+
+    // Validate the commission node command.
+    err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId);
     SuccessOrExit(err == CHIP_NO_ERROR);
 
-    // Add the response for the commissioning window
-    AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, info->params);
+    // Add the response for the commissioning window.
+    AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, commissionNodeInfo->params);
 
     // Schedule the deferred reverse commission node task
-    DeviceLayer::PlatformMgr().ScheduleWork(RunDeferredCommissionNode, reinterpret_cast<intptr_t>(info.release()));
+    DeviceLayer::PlatformMgr().ScheduleWork(RunDeferredCommissionNode, reinterpret_cast<intptr_t>(commissionNodeInfo.release()));
 
 exit:
     if (err != CHIP_NO_ERROR)
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
index 9ded85c533831e..35b413d5810f91 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -24,6 +24,9 @@ namespace app {
 namespace Clusters {
 namespace CommissionerControl {
 
+// Set to 64 bytes, which is more than enough for storing an IPv6 address in either binary or text form.
+static constexpr size_t kIpAddressBufferSize = 64;
+
 struct CommissioningApprovalRequest
 {
     uint64_t requestId;
@@ -48,18 +51,96 @@ struct CommissionNodeInfo
     CommissioningWindowParams params;
     Optional<ByteSpan> ipAddress;
     Optional<uint16_t> port;
+    uint8_t ipAddressBuffer[kIpAddressBufferSize];
+
+    CHIP_ERROR SetIPAddress(const Optional<ByteSpan> & address)
+    {
+        if (!address.HasValue())
+        {
+            ipAddress.ClearValue();
+            return CHIP_NO_ERROR;
+        }
+
+        const ByteSpan & addressSpan = address.Value();
+        size_t addressLength         = addressSpan.size();
+
+        if (addressLength > kIpAddressBufferSize)
+        {
+            return CHIP_ERROR_BUFFER_TOO_SMALL;
+        }
+
+        if (addressLength == 0)
+        {
+            ipAddress.ClearValue();
+            return CHIP_NO_ERROR;
+        }
+
+        memcpy(ipAddressBuffer, addressSpan.data(), addressLength);
+        ipAddress.SetValue(ByteSpan(ipAddressBuffer, addressLength));
+        return CHIP_NO_ERROR;
+    }
 };
 
 class Delegate
 {
 public:
-    // Command Delegates
+    /**
+     * @brief Handle a commissioning approval request.
+     *
+     * This command is sent by a client to request approval for a future CommissionNode call.
+     * The server SHALL always return SUCCESS to a correctly formatted RequestCommissioningApproval
+     * command, and then send a CommissioningRequestResult event once the result is ready.
+     *
+     * @param request The commissioning approval request to handle.
+     * @return CHIP_ERROR indicating the success or failure of the operation.
+     */
     virtual CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) = 0;
-    virtual CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId,
-                                                     CommissioningWindowParams & outParams)             = 0;
+
+    /**
+     * @brief Validate a commission node command.
+     *
+     * This command is sent by a client to request that the server begins commissioning a previously
+     * approved request.
+     *
+     * The server SHALL return FAILURE if the CommissionNode command is not sent from the same
+     * NodeId as the RequestCommissioningApproval or if the provided RequestId to CommissionNode
+     * does not match the value provided to RequestCommissioningApproval.
+     *
+     * The validation SHALL fail if the client Node ID is kUndefinedNodeId, such as getting the NodeID from
+     * a group or PASE session.
+     *
+     * @param clientNodeId The NodeId of the client.
+     * @param requestId The request ID to validate.
+     * @return CHIP_ERROR indicating the success or failure of the operation.
+     */
+    virtual CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) = 0;
+
+    /**
+     * @brief Get the parameters for the commissioning window.
+     *
+     * This method is called to retrieve the parameters needed for the commissioning window.
+     *
+     * @param[out] outParams The parameters for the commissioning window.
+     * @return CHIP_ERROR indicating the success or failure of the operation.
+     */
+    virtual CHIP_ERROR GetCommissioningWindowParams(CommissioningWindowParams & outParams) = 0;
+
+    /**
+     * @brief Reverse the commission node process.
+     *
+     * When received within the timeout specified by CommissionNode, the client SHALL open a
+     * commissioning window on the node which the client called RequestCommissioningApproval to
+     * have commissioned.
+     *
+     * @param params The parameters for the commissioning window.
+     * @param ipAddress Optional IP address for the commissioning window.
+     * @param port Optional port for the commissioning window.
+     * @return CHIP_ERROR indicating the success or failure of the operation.
+     */
     virtual CHIP_ERROR ReverseCommissionNode(const CommissioningWindowParams & params, const Optional<ByteSpan> & ipAddress,
-                                             const Optional<uint16_t> & port)                           = 0;
-    virtual ~Delegate()                                                                                 = default;
+                                             const Optional<uint16_t> & port) = 0;
+
+    virtual ~Delegate() = default;
 };
 
 class CommissionerControlServer

From bff49d6746a21f85be925a523661d629ff75daed Mon Sep 17 00:00:00 2001
From: Yufeng Wang <yufengwang@google.com>
Date: Thu, 25 Jul 2024 02:44:46 +0200
Subject: [PATCH 08/14] Add case requirement to CommissionerControlCluster

---
 .../commissioner-control-server.cpp           | 20 +++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index d9be46efcc9aa5..e56a98a05aebdb 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -174,6 +174,15 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
     ChipLogProgress(Zcl, "Received command to request commissioning approval");
 
     auto sourceNodeId = getNodeId(commandObj);
+
+    // Check if the command is executed via a CASE session
+    if (sourceNodeId == kUndefinedNodeId)
+    {
+        ChipLogError(Zcl, "Command not executed via CASE session, failing with UNSUPPORTED_ACCESS");
+        commandObj->AddStatus(commandPath, Status::UnsupportedAccess);
+        return true;
+    }
+
     auto fabricIndex  = commandObj->GetAccessingFabricIndex();
     auto requestId    = commandData.requestId;
     auto vendorId     = commandData.vendorId;
@@ -194,7 +203,6 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
     Clusters::CommissionerControl::Delegate * delegate =
         Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();
 
-    VerifyOrExit(sourceNodeId != kUndefinedNodeId, err = CHIP_ERROR_WRONG_NODE_ID);
     VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
 
     // Handle commissioning approval request
@@ -220,6 +228,15 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
     ChipLogProgress(Zcl, "Received command to commission node");
 
     auto sourceNodeId = getNodeId(commandObj);
+
+    // Check if the command is executed via a CASE session
+    if (sourceNodeId == kUndefinedNodeId)
+    {
+        ChipLogError(Zcl, "Command not executed via CASE session, failing with UNSUPPORTED_ACCESS");
+        commandObj->AddStatus(commandPath, Status::UnsupportedAccess);
+        return true;
+    }
+
     auto requestId    = commandData.requestId;
 
     auto commissionNodeInfo = std::make_unique<Clusters::CommissionerControl::CommissionNodeInfo>();
@@ -227,7 +244,6 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
     Clusters::CommissionerControl::Delegate * delegate =
         Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();
 
-    VerifyOrExit(sourceNodeId != kUndefinedNodeId, err = CHIP_ERROR_WRONG_NODE_ID);
     VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
 
     // Set IP address and port in the CommissionNodeInfo struct

From b0cbeb12099c30c082b35f3671607aa23b9f620f Mon Sep 17 00:00:00 2001
From: "Restyled.io" <commits@restyled.io>
Date: Thu, 25 Jul 2024 00:45:37 +0000
Subject: [PATCH 09/14] Restyled by clang-format

---
 .../commissioner-control-server.cpp                    | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index e56a98a05aebdb..ba40913d166a64 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -183,10 +183,10 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
         return true;
     }
 
-    auto fabricIndex  = commandObj->GetAccessingFabricIndex();
-    auto requestId    = commandData.requestId;
-    auto vendorId     = commandData.vendorId;
-    auto productId    = commandData.productId;
+    auto fabricIndex = commandObj->GetAccessingFabricIndex();
+    auto requestId   = commandData.requestId;
+    auto vendorId    = commandData.vendorId;
+    auto productId   = commandData.productId;
 
     // The label assigned from commandData need to be stored in CommissionerControl::Delegate which ensure that the backing buffer
     // of it has a valid lifespan during fabric sync setup process.
@@ -237,7 +237,7 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
         return true;
     }
 
-    auto requestId    = commandData.requestId;
+    auto requestId = commandData.requestId;
 
     auto commissionNodeInfo = std::make_unique<Clusters::CommissionerControl::CommissionNodeInfo>();
 

From e06ce4a19e8dcf62382d5a4b1512a76bef57fde1 Mon Sep 17 00:00:00 2001
From: Terence Hampson <thampson@google.com>
Date: Thu, 25 Jul 2024 22:19:27 +0000
Subject: [PATCH 10/14] Address PR comments

---
 .../commissioner-control-server.cpp           | 49 +++++++------------
 .../commissioner-control-server.h             | 42 ++++++----------
 2 files changed, 33 insertions(+), 58 deletions(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index ba40913d166a64..99a98ff4e718fb 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -38,29 +38,14 @@ using chip::Protocols::InteractionModel::Status;
 
 namespace {
 
-NodeId getNodeId(const app::CommandHandler * commandObj)
+NodeId GetNodeId(const CommandHandler * commandObj)
 {
-    if (nullptr == commandObj || nullptr == commandObj->GetExchangeContext())
-    {
-        ChipLogError(Zcl, "Cannot access ExchangeContext of Command Object for Node ID");
-        return kUndefinedNodeId;
-    }
+    auto descriptor = commandObj->GetSubjectDescriptor();
 
-    if (!commandObj->GetExchangeContext()->HasSessionHandle())
-    {
-        ChipLogError(Zcl, "Cannot access session of Command Object for Node ID");
-        return kUndefinedNodeId;
-    }
-
-    auto descriptor = commandObj->GetExchangeContext()->GetSessionHandle()->GetSubjectDescriptor();
-
-    // Return kUndefinedNodeId if get the NodeID from a group or PASE session.
     if (descriptor.authMode != Access::AuthMode::kCase)
     {
-        ChipLogError(Zcl, "Cannot get Node ID from non-CASE session of Command Object");
         return kUndefinedNodeId;
     }
-
     return descriptor.subject;
 }
 
@@ -86,10 +71,10 @@ void RunDeferredCommissionNode(intptr_t commandArg)
 
     if (delegate != nullptr)
     {
-        CHIP_ERROR err = delegate->ReverseCommissionNode(info->params, info->ipAddress, info->port);
+        CHIP_ERROR err = delegate->ReverseCommissionNode(info->params, info->GetIPAddress(), info->port);
         if (err != CHIP_NO_ERROR)
         {
-            ChipLogError(Zcl, "ReverseCommissionNode error: %s", err.AsString());
+            ChipLogError(Zcl, "ReverseCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format());
         }
     }
     else
@@ -107,11 +92,11 @@ namespace app {
 namespace Clusters {
 namespace CommissionerControl {
 
-CommissionerControlServer CommissionerControlServer::mInstance;
+CommissionerControlServer CommissionerControlServer::sInstance;
 
 CommissionerControlServer & CommissionerControlServer::Instance()
 {
-    return mInstance;
+    return sInstance;
 }
 
 CHIP_ERROR CommissionerControlServer::Init(Delegate & delegate)
@@ -120,7 +105,7 @@ CHIP_ERROR CommissionerControlServer::Init(Delegate & delegate)
     return CHIP_NO_ERROR;
 }
 
-Protocols::InteractionModel::Status CommissionerControlServer::GetSupportedDeviceCategoriesValue(
+Status CommissionerControlServer::GetSupportedDeviceCategoriesValue(
     EndpointId endpoint, BitMask<SupportedDeviceCategoryBitmap> * supportedDeviceCategories) const
 {
     Status status = Attributes::SupportedDeviceCategories::Get(endpoint, supportedDeviceCategories);
@@ -131,7 +116,7 @@ Protocols::InteractionModel::Status CommissionerControlServer::GetSupportedDevic
     return status;
 }
 
-Protocols::InteractionModel::Status
+Status
 CommissionerControlServer::SetSupportedDeviceCategoriesValue(EndpointId endpoint,
                                                              const BitMask<SupportedDeviceCategoryBitmap> supportedDeviceCategories)
 {
@@ -173,12 +158,12 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
 
     ChipLogProgress(Zcl, "Received command to request commissioning approval");
 
-    auto sourceNodeId = getNodeId(commandObj);
+    auto sourceNodeId = GetNodeId(commandObj);
 
     // Check if the command is executed via a CASE session
     if (sourceNodeId == kUndefinedNodeId)
     {
-        ChipLogError(Zcl, "Command not executed via CASE session, failing with UNSUPPORTED_ACCESS");
+        ChipLogError(Zcl, "Commissioning approval request not executed via CASE session, failing with UNSUPPORTED_ACCESS");
         commandObj->AddStatus(commandPath, Status::UnsupportedAccess);
         return true;
     }
@@ -211,8 +196,8 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
 exit:
     if (err != CHIP_NO_ERROR)
     {
-        ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %s", err.AsString());
-        status = Status::Failure;
+        ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %" CHIP_ERROR_FORMAT, err.Format());
+        status = StatusIB(err).mStatus;
     }
 
     commandObj->AddStatus(commandPath, status);
@@ -227,12 +212,12 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
     ChipLogProgress(Zcl, "Received command to commission node");
 
-    auto sourceNodeId = getNodeId(commandObj);
+    auto sourceNodeId = GetNodeId(commandObj);
 
     // Check if the command is executed via a CASE session
     if (sourceNodeId == kUndefinedNodeId)
     {
-        ChipLogError(Zcl, "Command not executed via CASE session, failing with UNSUPPORTED_ACCESS");
+        ChipLogError(Zcl, "Commission node request not executed via CASE session, failing with UNSUPPORTED_ACCESS");
         commandObj->AddStatus(commandPath, Status::UnsupportedAccess);
         return true;
     }
@@ -264,8 +249,8 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 exit:
     if (err != CHIP_NO_ERROR)
     {
-        ChipLogError(Zcl, "emberAfCommissionerControlClusterCommissionNodeCallback error: %s", err.AsString());
-        commandObj->AddStatus(commandPath, Status::Failure);
+        ChipLogError(Zcl, "emberAfCommissionerControlClusterCommissionNodeCallback error: %" CHIP_ERROR_FORMAT, err.Format());
+        commandObj->AddStatus(commandPath, StatusIB(err).mStatus);
     }
 
     return true;
@@ -273,5 +258,5 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
 void MatterCommissionerControlPluginServerInitCallback()
 {
-    ChipLogProgress(Zcl, "Initiating Commissioner Control cluster.");
+    ChipLogProgress(Zcl, "Initializing Commissioner Control cluster.");
 }
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
index 35b413d5810f91..1edc55d90110ca 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -24,8 +24,8 @@ namespace app {
 namespace Clusters {
 namespace CommissionerControl {
 
-// Set to 64 bytes, which is more than enough for storing an IPv6 address in either binary or text form.
-static constexpr size_t kIpAddressBufferSize = 64;
+// Spec indicates that IP Address is either 4 or 16 bytes.
+static constexpr size_t kIpAddressBufferSize = 16;
 
 struct CommissioningApprovalRequest
 {
@@ -48,10 +48,10 @@ struct CommissioningWindowParams
 
 struct CommissionNodeInfo
 {
-    CommissioningWindowParams params;
-    Optional<ByteSpan> ipAddress;
-    Optional<uint16_t> port;
-    uint8_t ipAddressBuffer[kIpAddressBufferSize];
+    const Optional<ByteSpan> GetIPAddress()
+    {
+        return ipAddress;
+    }
 
     CHIP_ERROR SetIPAddress(const Optional<ByteSpan> & address)
     {
@@ -63,22 +63,22 @@ struct CommissionNodeInfo
 
         const ByteSpan & addressSpan = address.Value();
         size_t addressLength         = addressSpan.size();
-
-        if (addressLength > kIpAddressBufferSize)
-        {
-            return CHIP_ERROR_BUFFER_TOO_SMALL;
-        }
-
-        if (addressLength == 0)
+        if (addressLength != 4 && addressLength != 16)
         {
-            ipAddress.ClearValue();
-            return CHIP_NO_ERROR;
+            return CHIP_ERROR_INVALID_ARGUMENT;
         }
 
         memcpy(ipAddressBuffer, addressSpan.data(), addressLength);
         ipAddress.SetValue(ByteSpan(ipAddressBuffer, addressLength));
         return CHIP_NO_ERROR;
     }
+
+    CommissioningWindowParams params;
+    Optional<uint16_t> port;
+
+protected:
+    Optional<ByteSpan> ipAddress;
+    uint8_t ipAddressBuffer[kIpAddressBufferSize];
 };
 
 class Delegate
@@ -115,16 +115,6 @@ class Delegate
      */
     virtual CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) = 0;
 
-    /**
-     * @brief Get the parameters for the commissioning window.
-     *
-     * This method is called to retrieve the parameters needed for the commissioning window.
-     *
-     * @param[out] outParams The parameters for the commissioning window.
-     * @return CHIP_ERROR indicating the success or failure of the operation.
-     */
-    virtual CHIP_ERROR GetCommissioningWindowParams(CommissioningWindowParams & outParams) = 0;
-
     /**
      * @brief Reverse the commission node process.
      *
@@ -169,7 +159,7 @@ class CommissionerControlServer
     CommissionerControlServer()  = default;
     ~CommissionerControlServer() = default;
 
-    static CommissionerControlServer mInstance;
+    static CommissionerControlServer sInstance;
 
     Delegate * mDelegate = nullptr;
 };

From d56a7f756c643c420e8e91e9a4e0bc20e5d535ab Mon Sep 17 00:00:00 2001
From: Terence Hampson <thampson@google.com>
Date: Thu, 25 Jul 2024 22:30:01 +0000
Subject: [PATCH 11/14] Few more fixes

---
 .../commissioner-control-server.cpp              |  6 +++---
 .../commissioner-control-server.h                | 16 ++++++++++------
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index 99a98ff4e718fb..1fba69e8962432 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -71,7 +71,7 @@ void RunDeferredCommissionNode(intptr_t commandArg)
 
     if (delegate != nullptr)
     {
-        CHIP_ERROR err = delegate->ReverseCommissionNode(info->params, info->GetIPAddress(), info->port);
+        CHIP_ERROR err = delegate->ReverseCommissionNode(info->params, info->ipAddress.GetIPAddress(), info->port);
         if (err != CHIP_NO_ERROR)
         {
             ChipLogError(Zcl, "ReverseCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format());
@@ -138,7 +138,7 @@ CommissionerControlServer::GenerateCommissioningRequestResultEvent(const Events:
     CHIP_ERROR error = LogEvent(result, kRootEndpointId, eventNumber);
     if (CHIP_NO_ERROR != error)
     {
-        ChipLogError(Zcl, "CommissionerControl: Unable to emit CommissioningRequestResult event: %s", error.AsString());
+        ChipLogError(Zcl, "CommissionerControl: Unable to emit CommissioningRequestResult event: %" CHIP_ERROR_FORMAT, error.Format());
     }
 
     return error;
@@ -233,7 +233,7 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
     // Set IP address and port in the CommissionNodeInfo struct
     commissionNodeInfo->port = commandData.port;
-    err                      = commissionNodeInfo->SetIPAddress(commandData.ipAddress);
+    err                      = commissionNodeInfo->ipAddress.SetIPAddress(commandData.ipAddress);
     SuccessOrExit(err == CHIP_NO_ERROR);
 
     // Validate the commission node command.
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
index 1edc55d90110ca..c5ae15b0b64cc3 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -46,8 +46,8 @@ struct CommissioningWindowParams
     ByteSpan salt;
 };
 
-struct CommissionNodeInfo
-{
+class ProtectedIPAddress {
+public:
     const Optional<ByteSpan> GetIPAddress()
     {
         return ipAddress;
@@ -73,14 +73,18 @@ struct CommissionNodeInfo
         return CHIP_NO_ERROR;
     }
 
-    CommissioningWindowParams params;
-    Optional<uint16_t> port;
-
-protected:
+private:
     Optional<ByteSpan> ipAddress;
     uint8_t ipAddressBuffer[kIpAddressBufferSize];
 };
 
+struct CommissionNodeInfo
+{
+    CommissioningWindowParams params;
+    ProtectedIPAddress ipAddress;
+    Optional<uint16_t> port;
+};
+
 class Delegate
 {
 public:

From 53b1e8a47feabf9976a5b82bf9bc35e57fa5840a Mon Sep 17 00:00:00 2001
From: "Restyled.io" <commits@restyled.io>
Date: Thu, 25 Jul 2024 22:30:23 +0000
Subject: [PATCH 12/14] Restyled by clang-format

---
 .../commissioner-control-server.cpp                       | 6 ++++--
 .../commissioner-control-server.h                         | 8 +++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index 1fba69e8962432..937996187ce3ec 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -138,7 +138,8 @@ CommissionerControlServer::GenerateCommissioningRequestResultEvent(const Events:
     CHIP_ERROR error = LogEvent(result, kRootEndpointId, eventNumber);
     if (CHIP_NO_ERROR != error)
     {
-        ChipLogError(Zcl, "CommissionerControl: Unable to emit CommissioningRequestResult event: %" CHIP_ERROR_FORMAT, error.Format());
+        ChipLogError(Zcl, "CommissionerControl: Unable to emit CommissioningRequestResult event: %" CHIP_ERROR_FORMAT,
+                     error.Format());
     }
 
     return error;
@@ -196,7 +197,8 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
 exit:
     if (err != CHIP_NO_ERROR)
     {
-        ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %" CHIP_ERROR_FORMAT, err.Format());
+        ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %" CHIP_ERROR_FORMAT,
+                     err.Format());
         status = StatusIB(err).mStatus;
     }
 
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
index c5ae15b0b64cc3..3a8d5e051ea9af 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -46,12 +46,10 @@ struct CommissioningWindowParams
     ByteSpan salt;
 };
 
-class ProtectedIPAddress {
+class ProtectedIPAddress
+{
 public:
-    const Optional<ByteSpan> GetIPAddress()
-    {
-        return ipAddress;
-    }
+    const Optional<ByteSpan> GetIPAddress() { return ipAddress; }
 
     CHIP_ERROR SetIPAddress(const Optional<ByteSpan> & address)
     {

From 165f4dc524e494ce96184375dc02c679dc427f39 Mon Sep 17 00:00:00 2001
From: Terence Hampson <thampson@google.com>
Date: Fri, 26 Jul 2024 01:26:53 +0000
Subject: [PATCH 13/14] Add GetCommissioningWindowParams back in

---
 .../commissioner-control-server.cpp                    |  4 ++++
 .../commissioner-control-server.h                      | 10 ++++++++++
 2 files changed, 14 insertions(+)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index 937996187ce3ec..69b9384ff76718 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -242,6 +242,10 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
     err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId);
     SuccessOrExit(err == CHIP_NO_ERROR);
 
+    // Populate the parameters for the commissioning window
+    err = delegate->GetCommissioningWindowParams(commissionNodeInfo->params);
+    SuccessOrExit(err == CHIP_NO_ERROR);    
+
     // Add the response for the commissioning window.
     AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, commissionNodeInfo->params);
 
diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.h b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
index 3a8d5e051ea9af..5e2422f5ebe018 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.h
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.h
@@ -117,6 +117,16 @@ class Delegate
      */
     virtual CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) = 0;
 
+    /**
+     * @brief Get the parameters for the commissioning window.
+     *
+     * This method is called to retrieve the parameters needed for the commissioning window.
+     *
+     * @param[out] outParams The parameters for the commissioning window.
+     * @return CHIP_ERROR indicating the success or failure of the operation.
+     */
+    virtual CHIP_ERROR GetCommissioningWindowParams(CommissioningWindowParams & outParams) = 0;
+
     /**
      * @brief Reverse the commission node process.
      *

From 73c331edbdc84a1eade0d26151da7dbad855a6a4 Mon Sep 17 00:00:00 2001
From: "Restyled.io" <commits@restyled.io>
Date: Fri, 26 Jul 2024 01:27:22 +0000
Subject: [PATCH 14/14] Restyled by whitespace

---
 .../commissioner-control-server/commissioner-control-server.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
index 69b9384ff76718..98616f9e0e281b 100644
--- a/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
+++ b/src/app/clusters/commissioner-control-server/commissioner-control-server.cpp
@@ -244,7 +244,7 @@ bool emberAfCommissionerControlClusterCommissionNodeCallback(
 
     // Populate the parameters for the commissioning window
     err = delegate->GetCommissioningWindowParams(commissionNodeInfo->params);
-    SuccessOrExit(err == CHIP_NO_ERROR);    
+    SuccessOrExit(err == CHIP_NO_ERROR);
 
     // Add the response for the commissioning window.
     AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, commissionNodeInfo->params);