Skip to content

Commit

Permalink
[Fabric-Sync]: Convert ember-driven functions to interface functions (p…
Browse files Browse the repository at this point in the history
…roject-chip#36659)

* [Fabric-Sync]: Convert ember-driven functions to interface functions

* Address review comments
  • Loading branch information
yufengwangca authored Dec 3, 2024
1 parent 0495a4e commit e0fc29a
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const
mLabel.ClearValue();
}

CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result);
CHIP_ERROR err = mCommissionerControlServer.GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result);

if (err == CHIP_NO_ERROR)
{
Expand Down Expand Up @@ -228,7 +228,7 @@ CHIP_ERROR CommissionerControlInit()
return CHIP_ERROR_NO_MEMORY;
}

err = Clusters::CommissionerControl::CommissionerControlServer::Instance().Init(*sCommissionerControlDelegate);
err = sCommissionerControlDelegate->GetCommissionerControlServer().Init();
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Initialization failed on Commissioner Control Delegate.");
Expand All @@ -242,7 +242,7 @@ CHIP_ERROR CommissionerControlInit()
supportedDeviceCategories.SetField(Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1);

Protocols::InteractionModel::Status status =
Clusters::CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue(
sCommissionerControlDelegate->GetCommissionerControlServer().SetSupportedDeviceCategoriesValue(
Clusters::CommissionerControl::kAggregatorEndpointId, supportedDeviceCategories);

if (status != Protocols::InteractionModel::Status::Success)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ inline constexpr EndpointId kAggregatorEndpointId = 1;
class CommissionerControlDelegate : public Delegate
{
public:
CommissionerControlDelegate() : mCommissionerControlServer(this, kAggregatorEndpointId, CommissionerControl::Id) {}

CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override;
// TODO(#35627) clientNodeId should move towards ScopedNodeId.
CHIP_ERROR ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId) override;
Expand All @@ -39,6 +41,8 @@ class CommissionerControlDelegate : public Delegate

~CommissionerControlDelegate() = default;

CommissionerControlServer & GetCommissionerControlServer() { return mCommissionerControlServer; }

private:
enum class Step : uint8_t
{
Expand Down Expand Up @@ -82,6 +86,8 @@ class CommissionerControlDelegate : public Delegate
ByteSpan mPBKDFSalt;
Crypto::Spake2pVerifierSerialized mPAKEPasscodeVerifierBuffer;
ByteSpan mPAKEPasscodeVerifier;

CommissionerControlServer mCommissionerControlServer;
};

} // namespace CommissionerControl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ inline constexpr EndpointId kAggregatorEndpointId = 1;
class CommissionerControlDelegate : public Delegate
{
public:
CommissionerControlDelegate(bridge::FabricAdminDelegate * fabricAdmin) : mFabricAdmin(fabricAdmin) {}
CommissionerControlDelegate(bridge::FabricAdminDelegate * fabricAdmin) :
mFabricAdmin(fabricAdmin), mCommissionerControlServer(this, kAggregatorEndpointId, CommissionerControl::Id)
{}

CHIP_ERROR HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request) override;
// TODO(#35627) clientNodeId should move towards ScopedNodeId.
Expand All @@ -42,6 +44,8 @@ class CommissionerControlDelegate : public Delegate

~CommissionerControlDelegate() = default;

CommissionerControlServer & GetCommissionerControlServer() { return mCommissionerControlServer; }

private:
enum class Step : uint8_t
{
Expand Down Expand Up @@ -87,6 +91,7 @@ class CommissionerControlDelegate : public Delegate
ByteSpan mPAKEPasscodeVerifier;

bridge::FabricAdminDelegate * mFabricAdmin;
CommissionerControlServer mCommissionerControlServer;
};

} // namespace CommissionerControl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const
mLabel.ClearValue();
}

CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result);
CHIP_ERROR err = mCommissionerControlServer.GenerateCommissioningRequestResultEvent(kAggregatorEndpointId, result);

if (err == CHIP_NO_ERROR)
{
Expand Down Expand Up @@ -227,7 +227,7 @@ CHIP_ERROR CommissionerControlInit(bridge::FabricAdminDelegate * fabricAdmin)
return CHIP_ERROR_NO_MEMORY;
}

err = Clusters::CommissionerControl::CommissionerControlServer::Instance().Init(*sCommissionerControlDelegate);
err = sCommissionerControlDelegate->GetCommissionerControlServer().Init();
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Initialization failed on Commissioner Control Delegate.");
Expand All @@ -241,7 +241,7 @@ CHIP_ERROR CommissionerControlInit(bridge::FabricAdminDelegate * fabricAdmin)
supportedDeviceCategories.SetField(Clusters::CommissionerControl::SupportedDeviceCategoryBitmap::kFabricSynchronization, 1);

Protocols::InteractionModel::Status status =
Clusters::CommissionerControl::CommissionerControlServer::Instance().SetSupportedDeviceCategoriesValue(
sCommissionerControlDelegate->GetCommissionerControlServer().SetSupportedDeviceCategoriesValue(
Clusters::CommissionerControl::kAggregatorEndpointId, supportedDeviceCategories);

if (status != Protocols::InteractionModel::Status::Success)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
#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/CommandHandlerInterfaceRegistry.h>
#include <app/EventLogging.h>
#include <app/reporting/reporting.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/PlatformManager.h>

#include <memory>
Expand All @@ -38,9 +38,9 @@ using chip::Protocols::InteractionModel::Status;

namespace {

NodeId GetNodeId(const CommandHandler * commandObj)
NodeId GetNodeId(const CommandHandler & commandHandler)
{
auto descriptor = commandObj->GetSubjectDescriptor();
auto descriptor = commandHandler.GetSubjectDescriptor();

if (descriptor.authMode != Access::AuthMode::kCase)
{
Expand All @@ -49,7 +49,7 @@ NodeId GetNodeId(const CommandHandler * commandObj)
return descriptor.subject;
}

void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, const ConcreteCommandPath & path,
void AddReverseOpenCommissioningWindowResponse(CommandHandler & commandHandler, const ConcreteCommandPath & path,
const Clusters::CommissionerControl::CommissioningWindowParams & params)
{
Clusters::CommissionerControl::Commands::ReverseOpenCommissioningWindow::Type response;
Expand All @@ -59,30 +59,7 @@ void AddReverseOpenCommissioningWindowResponse(CommandHandler * commandObj, cons
response.PAKEPasscodeVerifier = params.PAKEPasscodeVerifier;
response.salt = params.salt;

commandObj->AddResponse(path, response);
}

void RunDeferredCommissionNode(intptr_t commandArg)
{
auto * params = reinterpret_cast<Clusters::CommissionerControl::CommissioningWindowParams *>(commandArg);

Clusters::CommissionerControl::Delegate * delegate =
Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();

if (delegate != nullptr)
{
CHIP_ERROR err = delegate->HandleCommissionNode(*params);
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format());
}
}
else
{
ChipLogError(Zcl, "No delegate available for HandleCommissionNode");
}

delete params;
commandHandler.AddResponse(path, response);
}

} // namespace
Expand All @@ -92,16 +69,20 @@ namespace app {
namespace Clusters {
namespace CommissionerControl {

CommissionerControlServer CommissionerControlServer::sInstance;
CommissionerControlServer::CommissionerControlServer(Delegate * delegate, EndpointId endpointId, ClusterId clusterId) :
CommandHandlerInterface(MakeOptional(endpointId), clusterId)
{
mDelegate = delegate;
}

CommissionerControlServer & CommissionerControlServer::Instance()
CommissionerControlServer::~CommissionerControlServer()
{
return sInstance;
CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this);
}

CHIP_ERROR CommissionerControlServer::Init(Delegate & delegate)
CHIP_ERROR CommissionerControlServer::Init()
{
mDelegate = &delegate;
ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this));
return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -146,38 +127,53 @@ CommissionerControlServer::GenerateCommissioningRequestResultEvent(EndpointId en
return error;
}

} // namespace CommissionerControl
} // namespace Clusters
} // namespace app
} // namespace chip
void CommissionerControlServer::InvokeCommand(HandlerContext & handlerContext)
{
ChipLogDetail(Zcl, "CommissionerControl: InvokeCommand");
switch (handlerContext.mRequestPath.mCommandId)
{
case Commands::RequestCommissioningApproval::Id:
ChipLogDetail(Zcl, "CommissionerControl: Entering RequestCommissioningApproval");

bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Clusters::CommissionerControl::Commands::RequestCommissioningApproval::DecodableType & commandData)
CommandHandlerInterface::HandleCommand<Commands::RequestCommissioningApproval::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & req) { HandleRequestCommissioningApproval(ctx, req); });
break;

case Commands::CommissionNode::Id:
ChipLogDetail(Zcl, "CommissionerControl: Entering CommissionNode");

CommandHandlerInterface::HandleCommand<Commands::CommissionNode::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & req) { HandleCommissionNode(ctx, req); });
break;
}
}

void CommissionerControlServer::HandleRequestCommissioningApproval(
HandlerContext & ctx, const Commands::RequestCommissioningApproval::DecodableType & req)
{
CHIP_ERROR err = CHIP_NO_ERROR;
Status status = Status::Success;

ChipLogProgress(Zcl, "Received command to request commissioning approval");

auto sourceNodeId = GetNodeId(commandObj);
auto sourceNodeId = GetNodeId(ctx.mCommandHandler);

// Check if the command is executed via a CASE session
if (sourceNodeId == kUndefinedNodeId)
{
ChipLogError(Zcl, "Commissioning approval request not executed via CASE session, failing with UNSUPPORTED_ACCESS");
commandObj->AddStatus(commandPath, Status::UnsupportedAccess);
return true;
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedAccess);
return;
}

auto fabricIndex = commandObj->GetAccessingFabricIndex();
auto requestId = commandData.requestID;
auto vendorId = commandData.vendorID;
auto productId = commandData.productID;
auto fabricIndex = ctx.mCommandHandler.GetAccessingFabricIndex();
auto requestId = req.requestID;
auto vendorId = req.vendorID;
auto productId = req.productID;

// The label assigned from commandData need to be stored in CommissionerControl::Delegate which ensure that the backing buffer
// The label assigned from req 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;
auto & label = req.label;

// Create a CommissioningApprovalRequest struct and populate it with the command data
Clusters::CommissionerControl::CommissioningApprovalRequest request = { .requestId = requestId,
Expand All @@ -187,86 +183,93 @@ bool emberAfCommissionerControlClusterRequestCommissioningApprovalCallback(
.fabricIndex = fabricIndex,
.label = label };

Clusters::CommissionerControl::Delegate * delegate =
Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();

VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);

// Handle commissioning approval request
err = delegate->HandleCommissioningApprovalRequest(request);
err = mDelegate->HandleCommissioningApprovalRequest(request);

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "emberAfCommissionerControlClusterRequestCommissioningApprovalCallback error: %" CHIP_ERROR_FORMAT,
err.Format());
ChipLogError(Zcl, "HandleRequestCommissioningApproval error: %" CHIP_ERROR_FORMAT, err.Format());
status = StatusIB(err).mStatus;
}

commandObj->AddStatus(commandPath, status);
return true;
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
}

bool emberAfCommissionerControlClusterCommissionNodeCallback(
app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
const Clusters::CommissionerControl::Commands::CommissionNode::DecodableType & commandData)
void CommissionerControlServer::HandleCommissionNode(HandlerContext & ctx, const Commands::CommissionNode::DecodableType & req)
{
CHIP_ERROR err = CHIP_NO_ERROR;

ChipLogProgress(Zcl, "Received command to commission node");

auto sourceNodeId = GetNodeId(commandObj);
auto sourceNodeId = GetNodeId(ctx.mCommandHandler);

// Constraint on responseTimeoutSeconds is [30; 120] seconds
if ((commandData.responseTimeoutSeconds < 30) || (commandData.responseTimeoutSeconds > 120))
if ((req.responseTimeoutSeconds < 30) || (req.responseTimeoutSeconds > 120))
{
ChipLogError(Zcl, "Invalid responseTimeoutSeconds for CommissionNode.");
commandObj->AddStatus(commandPath, Status::ConstraintError);
return true;
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError);
return;
}

// Check if the command is executed via a CASE session
if (sourceNodeId == kUndefinedNodeId)
{
ChipLogError(Zcl, "Commission node request not executed via CASE session, failing with UNSUPPORTED_ACCESS");
commandObj->AddStatus(commandPath, Status::UnsupportedAccess);
return true;
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedAccess);
return;
}

auto requestId = commandData.requestID;

auto requestId = req.requestID;
auto delegate = mDelegate;
auto commissioningWindowParams = std::make_unique<Clusters::CommissionerControl::CommissioningWindowParams>();

Clusters::CommissionerControl::Delegate * delegate =
Clusters::CommissionerControl::CommissionerControlServer::Instance().GetDelegate();

VerifyOrExit(delegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mDelegate != nullptr, err = CHIP_ERROR_INCORRECT_STATE);

// Validate the commission node command.
err = delegate->ValidateCommissionNodeCommand(sourceNodeId, requestId);
err = mDelegate->ValidateCommissionNodeCommand(sourceNodeId, requestId);
SuccessOrExit(err);

// Populate the parameters for the commissioning window
err = delegate->GetCommissioningWindowParams(*commissioningWindowParams);
err = mDelegate->GetCommissioningWindowParams(*commissioningWindowParams);
SuccessOrExit(err);

// Add the response for the commissioning window.
AddReverseOpenCommissioningWindowResponse(commandObj, commandPath, *commissioningWindowParams);
AddReverseOpenCommissioningWindowResponse(ctx.mCommandHandler, ctx.mRequestPath, *commissioningWindowParams);

// Schedule the deferred reverse commission node task
DeviceLayer::PlatformMgr().ScheduleWork(RunDeferredCommissionNode,
reinterpret_cast<intptr_t>(commissioningWindowParams.release()));
DeviceLayer::SystemLayer().ScheduleLambda([delegate, params = commissioningWindowParams.release()]() {
if (delegate != nullptr)
{
CHIP_ERROR error = delegate->HandleCommissionNode(*params);
if (error != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, error.Format());
}
}
else
{
ChipLogError(Zcl, "No delegate available for HandleCommissionNode");
}

delete params;
});

exit:
if (err != CHIP_NO_ERROR)
{
ChipLogError(Zcl, "emberAfCommissionerControlClusterCommissionNodeCallback error: %" CHIP_ERROR_FORMAT, err.Format());
commandObj->AddStatus(commandPath, StatusIB(err).mStatus);
ChipLogError(Zcl, "HandleCommissionNode error: %" CHIP_ERROR_FORMAT, err.Format());
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, StatusIB(err).mStatus);
}

return true;
}

} // namespace CommissionerControl
} // namespace Clusters
} // namespace app
} // namespace chip

void MatterCommissionerControlPluginServerInitCallback()
{
ChipLogProgress(Zcl, "Initializing Commissioner Control cluster.");
Expand Down
Loading

0 comments on commit e0fc29a

Please sign in to comment.