Skip to content

Commit

Permalink
[Fabric-Bridge] Add state machine to CommissionerControlDelegate to g…
Browse files Browse the repository at this point in the history
…uard various unexpected commands (#35186)

* Add state machine to CommissionerControlDelegate to guard various unexpected commands

* Restyled by whitespace

* Restyled by clang-format

* Do not reset state when commissionNode fail to allow retry

---------

Co-authored-by: Restyled.io <[email protected]>
  • Loading branch information
2 people authored and pull[bot] committed Nov 9, 2024
1 parent b7d19a8 commit 1530542
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 9 deletions.
67 changes: 58 additions & 9 deletions examples/fabric-bridge-app/linux/CommissionerControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,33 @@ namespace app {
namespace Clusters {
namespace CommissionerControl {

void CommissionerControlDelegate::ResetDelegateState()
{
// Reset the step to the initial state
mNextStep = Step::kIdle;

// Reset identifiers and product information
mRequestId = 0;
mClientNodeId = kUndefinedNodeId;
mVendorId = VendorId::Unspecified;
mProductId = 0;

// Clear the label buffer and optional label
memset(mLabelBuffer, 0, sizeof(mLabelBuffer));
mLabel.ClearValue();

// Reset PBKDF salt and PAKE passcode verifier buffers
mPBKDFSalt = ByteSpan();
memset(mPBKDFSaltBuffer, 0, sizeof(mPBKDFSaltBuffer));

mPAKEPasscodeVerifier = ByteSpan();
memset(mPAKEPasscodeVerifierBuffer, 0, sizeof(mPAKEPasscodeVerifierBuffer));
}

CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const CommissioningApprovalRequest & request)
{
VerifyOrReturnError(mNextStep == Step::kIdle, CHIP_ERROR_INCORRECT_STATE);

CommissionerControl::Events::CommissioningRequestResult::Type result;
result.requestId = request.requestId;
result.clientNodeId = request.clientNodeId;
Expand Down Expand Up @@ -86,19 +111,34 @@ CHIP_ERROR CommissionerControlDelegate::HandleCommissioningApprovalRequest(const
mLabel.ClearValue();
}

return CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(result);
CHIP_ERROR err = CommissionerControlServer::Instance().GenerateCommissioningRequestResultEvent(result);

if (err == CHIP_NO_ERROR)
{
mNextStep = Step::kWaitCommissionNodeRequest;
}
else
{
ResetDelegateState();
}

return err;
}

CHIP_ERROR CommissionerControlDelegate::ValidateCommissionNodeCommand(NodeId clientNodeId, uint64_t requestId)
{
CHIP_ERROR err = CHIP_NO_ERROR;

VerifyOrReturnError(mNextStep == Step::kWaitCommissionNodeRequest, CHIP_ERROR_INCORRECT_STATE);

// Verify if the CommissionNode command is sent from the same NodeId as the RequestCommissioningApproval.
VerifyOrExit(mClientNodeId == clientNodeId, err = CHIP_ERROR_WRONG_NODE_ID);

// Verify if the provided RequestId matches the value provided to the RequestCommissioningApproval.
VerifyOrExit(mRequestId == requestId, err = CHIP_ERROR_INCORRECT_STATE);

mNextStep = Step::kStartCommissionNode;

exit:
return err;
}
Expand Down Expand Up @@ -129,20 +169,29 @@ CHIP_ERROR CommissionerControlDelegate::GetCommissioningWindowParams(Commissioni
CHIP_ERROR CommissionerControlDelegate::HandleCommissionNode(const CommissioningWindowParams & params,
const Optional<ByteSpan> & ipAddress, const Optional<uint16_t> & port)
{
CHIP_ERROR err = CHIP_NO_ERROR;

ChipLogProgress(NotSpecified, "CommissionerControlDelegate::HandleCommissionNode");

VerifyOrReturnError(mNextStep == Step::kStartCommissionNode, CHIP_ERROR_INCORRECT_STATE);

#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
return CommissionNode(Controller::CommissioningWindowPasscodeParams()
.SetSetupPIN(kSetupPinCode)
.SetTimeout(params.commissioningTimeout)
.SetDiscriminator(params.discriminator)
.SetIteration(params.iterations)
.SetSalt(params.salt),
mVendorId, mProductId);
err = CommissionNode(Controller::CommissioningWindowPasscodeParams()
.SetSetupPIN(kSetupPinCode)
.SetTimeout(params.commissioningTimeout)
.SetDiscriminator(params.discriminator)
.SetIteration(params.iterations)
.SetSalt(params.salt),
mVendorId, mProductId);
#else
ChipLogProgress(NotSpecified, "Failed to reverse commission bridge: PW_RPC_FABRIC_BRIDGE_SERVICE not defined");
return CHIP_ERROR_NOT_IMPLEMENTED;
err = CHIP_ERROR_NOT_IMPLEMENTED;
#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE

// Reset the delegate's state to prepare for a new commissioning sequence.
ResetDelegateState();

return err;
}

} // namespace CommissionerControl
Expand Down
13 changes: 13 additions & 0 deletions examples/fabric-bridge-app/linux/include/CommissionerControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,21 @@ class CommissionerControlDelegate : public Delegate
~CommissionerControlDelegate() = default;

private:
enum class Step : uint8_t
{
// Ready to start reverse commissioning.
kIdle,
// Wait for the commission node command.
kWaitCommissionNodeRequest,
// Need to commission node.
kStartCommissionNode,
};

void ResetDelegateState();

static constexpr size_t kLabelBufferSize = 64;

Step mNextStep = Step::kIdle;
uint64_t mRequestId = 0;
NodeId mClientNodeId = kUndefinedNodeId;
VendorId mVendorId = VendorId::Unspecified;
Expand Down

0 comments on commit 1530542

Please sign in to comment.