Skip to content

Commit 98dbd41

Browse files
committed
Address review comments
1 parent a6e081a commit 98dbd41

File tree

5 files changed

+110
-53
lines changed

5 files changed

+110
-53
lines changed

examples/fabric-admin/commands/common/CHIPCommand.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ CHIP_ERROR CHIPCommand::MaybeSetUpStack()
182182
mCredIssuerCmds->SetCredentialIssuerOption(CredentialIssuerCommands::CredentialIssuerOptions::kAllowTestCdSigningKey,
183183
allowTestCdSigningKey);
184184

185-
ReturnLogErrorOnFailure(PairingManager::Instance().Init(&CurrentCommissioner()));
185+
PairingManager::Instance().Init(&CurrentCommissioner());
186186

187187
return CHIP_NO_ERROR;
188188
}

examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ CHIP_ERROR FabricSyncDeviceCommand::RunCommand(EndpointId remoteId)
344344
return CHIP_NO_ERROR;
345345
}
346346

347-
PairingManager::Instance().RegisterOpenCommissioningWindowDelegate(this);
347+
PairingManager::Instance().SetOpenCommissioningWindowDelegate(this);
348348

349349
DeviceMgr().OpenRemoteDeviceCommissioningWindow(remoteId);
350350

examples/fabric-admin/device_manager/DeviceManager.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ void DeviceManager::OpenRemoteDeviceCommissioningWindow(EndpointId remoteEndpoin
134134
// Open the commissioning window of a device from another fabric via its fabric bridge.
135135
// This method constructs and sends a command to open the commissioning window for a device
136136
// that is part of a different fabric, accessed through a fabric bridge.
137-
StringBuilder<kMaxCommandSize> commandBuilder;
138137

139138
// Use random discriminator to have less chance of collision.
140139
uint16_t discriminator =

examples/fabric-admin/device_manager/PairingManager.cpp

+64-41
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,35 @@
2424

2525
using namespace ::chip;
2626

27-
Platform::UniquePtr<chip::Controller::CommissioningWindowOpener> PairingManager::mWindowOpener;
28-
2927
PairingManager::PairingManager() :
3028
mOnOpenCommissioningWindowCallback(OnOpenCommissioningWindowResponse, this),
3129
mOnOpenCommissioningWindowVerifierCallback(OnOpenCommissioningWindowVerifierResponse, this)
3230
{}
3331

34-
CHIP_ERROR PairingManager::Init(chip::Controller::DeviceCommissioner * commissioner)
32+
void PairingManager::Init(Controller::DeviceCommissioner * commissioner)
3533
{
34+
VerifyOrDie(mCommissioner == nullptr);
3635
mCommissioner = commissioner;
37-
return CHIP_NO_ERROR;
3836
}
3937

4038
CHIP_ERROR PairingManager::OpenCommissioningWindow(NodeId nodeId, EndpointId endpointId, uint16_t commissioningTimeout,
4139
uint32_t iterations, uint16_t discriminator, const ByteSpan & salt,
4240
const ByteSpan & verifier)
4341
{
44-
VerifyOrReturnError(mCommissioner != nullptr, CHIP_ERROR_INCORRECT_STATE);
42+
if (mCommissioner == nullptr)
43+
{
44+
ChipLogError(NotSpecified, "Commissioner is null, cannot open commissioning window");
45+
return CHIP_ERROR_INCORRECT_STATE;
46+
}
47+
48+
// Check if a window is already open
49+
if (mWindowOpener != nullptr)
50+
{
51+
ChipLogError(NotSpecified, "A commissioning window is already open");
52+
return CHIP_ERROR_INCORRECT_STATE;
53+
}
4554

46-
auto * params = new CommissioningWindowParams();
55+
auto params = Platform::MakeUnique<CommissioningWindowParams>();
4756
params->nodeId = nodeId;
4857
params->endpointId = endpointId;
4958
params->commissioningWindowTimeout = commissioningTimeout;
@@ -52,96 +61,110 @@ CHIP_ERROR PairingManager::OpenCommissioningWindow(NodeId nodeId, EndpointId end
5261

5362
if (!salt.empty())
5463
{
64+
if (salt.size() > Crypto::kSpake2p_Max_PBKDF_Salt_Length)
65+
{
66+
ChipLogError(NotSpecified, "Salt size exceeds buffer capacity");
67+
return CHIP_ERROR_BUFFER_TOO_SMALL;
68+
}
69+
5570
memcpy(params->saltBuffer, salt.data(), salt.size());
5671
params->salt = ByteSpan(params->saltBuffer, salt.size());
5772
}
5873

5974
if (!verifier.empty())
6075
{
76+
if (verifier.size() > Crypto::kSpake2p_VerifierSerialized_Length)
77+
{
78+
ChipLogError(NotSpecified, "Verifier size exceeds buffer capacity");
79+
return CHIP_ERROR_BUFFER_TOO_SMALL;
80+
}
81+
6182
memcpy(params->verifierBuffer, verifier.data(), verifier.size());
6283
params->verifier = ByteSpan(params->verifierBuffer, verifier.size());
6384
}
6485

6586
// Schedule work on the Matter thread
66-
chip::DeviceLayer::PlatformMgr().ScheduleWork(OnOpenCommissioningWindow, reinterpret_cast<intptr_t>(params));
67-
68-
return CHIP_NO_ERROR;
87+
return DeviceLayer::PlatformMgr().ScheduleWork(OnOpenCommissioningWindow, reinterpret_cast<intptr_t>(params.release()));
6988
}
7089

7190
void PairingManager::OnOpenCommissioningWindow(intptr_t context)
7291
{
73-
auto * params = reinterpret_cast<CommissioningWindowParams *>(context);
92+
Platform::UniquePtr<CommissioningWindowParams> params(reinterpret_cast<CommissioningWindowParams *>(context));
7493
PairingManager & self = PairingManager::Instance();
7594

7695
if (self.mCommissioner == nullptr)
7796
{
78-
ChipLogError(AppServer, "Commissioner is null, cannot open commissioning window");
97+
ChipLogError(NotSpecified, "Commissioner is null, cannot open commissioning window");
7998
return;
8099
}
81100

82-
mWindowOpener = Platform::MakeUnique<Controller::CommissioningWindowOpener>(self.mCommissioner);
101+
self.mWindowOpener = Platform::MakeUnique<Controller::CommissioningWindowOpener>(self.mCommissioner);
83102

84103
if (!params->verifier.empty())
85104
{
86105
if (params->salt.empty())
87106
{
88-
ChipLogError(AppServer, "Salt is required when verifier is set");
107+
ChipLogError(NotSpecified, "Salt is required when verifier is set");
108+
self.mWindowOpener.reset();
89109
return;
90110
}
91111

92-
CHIP_ERROR err = mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams()
93-
.SetNodeId(params->nodeId)
94-
.SetEndpointId(params->endpointId)
95-
.SetTimeout(params->commissioningWindowTimeout)
96-
.SetIteration(params->iteration)
97-
.SetDiscriminator(params->discriminator)
98-
.SetVerifier(params->verifier)
99-
.SetSalt(params->salt)
100-
.SetCallback(&self.mOnOpenCommissioningWindowVerifierCallback));
112+
CHIP_ERROR err =
113+
self.mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowVerifierParams()
114+
.SetNodeId(params->nodeId)
115+
.SetEndpointId(params->endpointId)
116+
.SetTimeout(params->commissioningWindowTimeout)
117+
.SetIteration(params->iteration)
118+
.SetDiscriminator(params->discriminator)
119+
.SetVerifier(params->verifier)
120+
.SetSalt(params->salt)
121+
.SetCallback(&self.mOnOpenCommissioningWindowVerifierCallback));
101122
if (err != CHIP_NO_ERROR)
102123
{
103-
ChipLogError(AppServer, "Failed to open commissioning window with verifier: %s", ErrorStr(err));
124+
ChipLogError(NotSpecified, "Failed to open commissioning window with verifier: %s", ErrorStr(err));
125+
self.mWindowOpener.reset();
104126
}
105127
}
106128
else
107129
{
108130
SetupPayload ignored;
109-
CHIP_ERROR err = mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams()
110-
.SetNodeId(params->nodeId)
111-
.SetEndpointId(params->endpointId)
112-
.SetTimeout(params->commissioningWindowTimeout)
113-
.SetIteration(params->iteration)
114-
.SetDiscriminator(params->discriminator)
115-
.SetSetupPIN(NullOptional)
116-
.SetSalt(NullOptional)
117-
.SetCallback(&self.mOnOpenCommissioningWindowCallback),
118-
ignored);
131+
CHIP_ERROR err = self.mWindowOpener->OpenCommissioningWindow(Controller::CommissioningWindowPasscodeParams()
132+
.SetNodeId(params->nodeId)
133+
.SetEndpointId(params->endpointId)
134+
.SetTimeout(params->commissioningWindowTimeout)
135+
.SetIteration(params->iteration)
136+
.SetDiscriminator(params->discriminator)
137+
.SetSetupPIN(NullOptional)
138+
.SetSalt(NullOptional)
139+
.SetCallback(&self.mOnOpenCommissioningWindowCallback),
140+
ignored);
119141
if (err != CHIP_NO_ERROR)
120142
{
121-
ChipLogError(AppServer, "Failed to open commissioning window with passcode: %s", ErrorStr(err));
143+
ChipLogError(NotSpecified, "Failed to open commissioning window with passcode: %s", ErrorStr(err));
144+
self.mWindowOpener.reset();
122145
}
123146
}
124-
125-
// Clean up params
126-
delete params;
127147
}
128148

129-
void PairingManager::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err, chip::SetupPayload payload)
149+
void PairingManager::OnOpenCommissioningWindowResponse(void * context, NodeId remoteId, CHIP_ERROR err, SetupPayload payload)
130150
{
151+
VerifyOrDie(context != nullptr);
131152
PairingManager * self = static_cast<PairingManager *>(context);
132153
if (self->mCommissioningWindowDelegate)
133154
{
134155
self->mCommissioningWindowDelegate->OnCommissioningWindowOpened(remoteId, err, payload);
135-
self->UnregisterOpenCommissioningWindowDelegate();
156+
self->SetOpenCommissioningWindowDelegate(nullptr);
136157
}
137158

138159
OnOpenCommissioningWindowVerifierResponse(context, remoteId, err);
139160
}
140161

141162
void PairingManager::OnOpenCommissioningWindowVerifierResponse(void * context, NodeId remoteId, CHIP_ERROR err)
142163
{
164+
VerifyOrDie(context != nullptr);
165+
PairingManager * self = static_cast<PairingManager *>(context);
143166
LogErrorOnFailure(err);
144167

145-
PairingManager * self = reinterpret_cast<PairingManager *>(context);
146-
VerifyOrReturn(self != nullptr, ChipLogError(NotSpecified, "OnOpenCommissioningWindowCommand: context is null"));
168+
// Reset the window opener once the window operation is complete
169+
self->mWindowOpener.reset();
147170
}

examples/fabric-admin/device_manager/PairingManager.h

+44-9
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,26 @@ class CommissioningWindowDelegate
2929
virtual ~CommissioningWindowDelegate() = default;
3030
};
3131

32+
/**
33+
* The PairingManager class is responsible for managing the commissioning and pairing process
34+
* of Matter devices. PairingManager is designed to be used as a singleton, meaning that there
35+
* should only be one instance of it running at any given time.
36+
*
37+
* Usage:
38+
*
39+
* 1. The class should be initialized when the system starts up, typically by invoking the static
40+
* instance method to get the singleton.
41+
* 2. To open a commissioning window, the appropriate method should be called on the PairingManager instance.
42+
* 3. The PairingManager will handle the lifecycle of the CommissioningWindowOpener and ensure that
43+
* resources are cleaned up appropriately when pairing is complete or the process is aborted.
44+
*
45+
* Example:
46+
*
47+
* @code
48+
* PairingManager& manager = PairingManager::Instance();
49+
* manager.OpenCommissioningWindow();
50+
* @endcode
51+
*/
3252
class PairingManager
3353
{
3454
public:
@@ -38,19 +58,28 @@ class PairingManager
3858
return instance;
3959
}
4060

41-
CHIP_ERROR Init(chip::Controller::DeviceCommissioner * commissioner);
61+
void Init(chip::Controller::DeviceCommissioner * commissioner);
4262

63+
/**
64+
* Opens a commissioning window on the specified node and endpoint.
65+
* Only one commissioning window can be active at a time. If a commissioning
66+
* window is already open, this function will return an error.
67+
*
68+
* @param nodeId The target node ID for commissioning.
69+
* @param endpointId The target endpoint ID for commissioning.
70+
* @param commissioningTimeout Timeout for the commissioning window in seconds.
71+
* @param iterations Iterations for PBKDF calculations.
72+
* @param discriminator Discriminator for commissioning.
73+
* @param salt Optional salt for verifier-based commissioning.
74+
* @param verifier Optional verifier for enhanced commissioning security.
75+
*
76+
* @return CHIP_ERROR_INCORRECT_STATE if a commissioning window is already open.
77+
*/
4378
CHIP_ERROR OpenCommissioningWindow(chip::NodeId nodeId, chip::EndpointId endpointId, uint16_t commissioningTimeout,
4479
uint32_t iterations, uint16_t discriminator, const chip::ByteSpan & salt,
4580
const chip::ByteSpan & verifier);
4681

47-
void RegisterOpenCommissioningWindowDelegate(CommissioningWindowDelegate * delegate)
48-
{
49-
ChipLogProgress(NotSpecified, "yujuan: PairingManager::RegisterOpenCommissioningWindowDelegate");
50-
mCommissioningWindowDelegate = delegate;
51-
}
52-
53-
void UnregisterOpenCommissioningWindowDelegate() { mCommissioningWindowDelegate = nullptr; }
82+
void SetOpenCommissioningWindowDelegate(CommissioningWindowDelegate * delegate) { mCommissioningWindowDelegate = delegate; }
5483

5584
private:
5685
PairingManager();
@@ -76,7 +105,13 @@ class PairingManager
76105

77106
CommissioningWindowDelegate * mCommissioningWindowDelegate = nullptr;
78107

79-
static chip::Platform::UniquePtr<chip::Controller::CommissioningWindowOpener> mWindowOpener;
108+
/**
109+
* Holds the unique_ptr to the current CommissioningWindowOpener.
110+
* Only one commissioning window opener can be active at a time.
111+
* The pointer is reset when the commissioning window is closed or when an error occurs.
112+
*/
113+
chip::Platform::UniquePtr<chip::Controller::CommissioningWindowOpener> mWindowOpener;
114+
80115
static void OnOpenCommissioningWindow(intptr_t context);
81116
static void OnOpenCommissioningWindowResponse(void * context, chip::NodeId deviceId, CHIP_ERROR status,
82117
chip::SetupPayload payload);

0 commit comments

Comments
 (0)