Skip to content

Commit 46a1a38

Browse files
Add the ability to read extra attributes during commissioning (project-chip#36867)
* Add support for ExtraReadPaths to CommissioningParameters * CHIP_CONFIG_ENABLE_READ_CLIENT strikes again * Check for alloc failure * Address further review comments
1 parent 2ecbcc2 commit 46a1a38

7 files changed

+77
-12
lines changed

src/app/AttributePathParams.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,27 @@ struct AttributePathParams
3030
{
3131
AttributePathParams() = default;
3232

33-
explicit AttributePathParams(EndpointId aEndpointId) :
33+
constexpr explicit AttributePathParams(EndpointId aEndpointId) :
3434
AttributePathParams(aEndpointId, kInvalidClusterId, kInvalidAttributeId, kInvalidListIndex)
3535
{}
3636

3737
//
3838
// TODO: (Issue #10596) Need to ensure that we do not encode the NodeId over the wire
3939
// if it is either not 'set', or is set to a value that matches accessing fabric
4040
// on which the interaction is undertaken.
41-
AttributePathParams(EndpointId aEndpointId, ClusterId aClusterId) :
41+
constexpr AttributePathParams(EndpointId aEndpointId, ClusterId aClusterId) :
4242
AttributePathParams(aEndpointId, aClusterId, kInvalidAttributeId, kInvalidListIndex)
4343
{}
4444

45-
AttributePathParams(EndpointId aEndpointId, ClusterId aClusterId, AttributeId aAttributeId) :
45+
constexpr AttributePathParams(EndpointId aEndpointId, ClusterId aClusterId, AttributeId aAttributeId) :
4646
AttributePathParams(aEndpointId, aClusterId, aAttributeId, kInvalidListIndex)
4747
{}
4848

49-
AttributePathParams(ClusterId aClusterId, AttributeId aAttributeId) :
49+
constexpr AttributePathParams(ClusterId aClusterId, AttributeId aAttributeId) :
5050
AttributePathParams(kInvalidEndpointId, aClusterId, aAttributeId, kInvalidListIndex)
5151
{}
5252

53-
AttributePathParams(EndpointId aEndpointId, ClusterId aClusterId, AttributeId aAttributeId, ListIndex aListIndex) :
53+
constexpr AttributePathParams(EndpointId aEndpointId, ClusterId aClusterId, AttributeId aAttributeId, ListIndex aListIndex) :
5454
mClusterId(aClusterId), mAttributeId(aAttributeId), mEndpointId(aEndpointId), mListIndex(aListIndex)
5555
{}
5656

src/controller/AutoCommissioner.cpp

+29-2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@
1818

1919
#include <controller/AutoCommissioner.h>
2020

21-
#include <cstring>
22-
2321
#include <app/InteractionModelTimeout.h>
2422
#include <controller/CHIPDeviceController.h>
2523
#include <credentials/CHIPCert.h>
2624
#include <lib/support/SafeInt.h>
2725

26+
#include <cstring>
27+
#include <type_traits>
28+
2829
namespace chip {
2930
namespace Controller {
3031

@@ -225,6 +226,32 @@ CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParam
225226
mParams.SetICDClientType(params.GetICDClientType().Value());
226227
}
227228

229+
auto extraReadPaths = params.GetExtraReadPaths();
230+
if (extraReadPaths.size() > 0)
231+
{
232+
using ReadPath = std::remove_pointer_t<decltype(extraReadPaths.data())>;
233+
static_assert(std::is_trivially_copyable_v<ReadPath>, "can't use memmove / memcpy, not trivially copyable");
234+
235+
if (mExtraReadPaths.AllocatedSize() == extraReadPaths.size())
236+
{
237+
memmove(mExtraReadPaths.Get(), extraReadPaths.data(), extraReadPaths.size() * sizeof(ReadPath));
238+
}
239+
else
240+
{
241+
// We can't reallocate mExtraReadPaths yet as this would free the old buffer,
242+
// and the caller might be passing a sub-span of the old paths.
243+
decltype(mExtraReadPaths) oldReadPaths(std::move(mExtraReadPaths));
244+
VerifyOrReturnError(mExtraReadPaths.Alloc(extraReadPaths.size()), CHIP_ERROR_NO_MEMORY);
245+
memcpy(mExtraReadPaths.Get(), extraReadPaths.data(), extraReadPaths.size() * sizeof(ReadPath));
246+
}
247+
248+
mParams.SetExtraReadPaths(mExtraReadPaths.Span());
249+
}
250+
else
251+
{
252+
mExtraReadPaths.Free();
253+
}
254+
228255
return CHIP_NO_ERROR;
229256
}
230257

src/controller/AutoCommissioner.h

+11-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@
1616
* limitations under the License.
1717
*/
1818
#pragma once
19+
20+
#include <app/AttributePathParams.h>
1921
#include <controller/CommissioneeDeviceProxy.h>
2022
#include <controller/CommissioningDelegate.h>
2123
#include <credentials/DeviceAttestationConstructor.h>
2224
#include <crypto/CHIPCryptoPAL.h>
25+
#include <lib/support/ScopedBuffer.h>
2326
#include <protocols/secure_channel/RendezvousParameters.h>
2427

2528
namespace chip {
@@ -116,7 +119,9 @@ class AutoCommissioner : public CommissioningDelegate
116119
CommissioneeDeviceProxy * mCommissioneeDeviceProxy = nullptr;
117120
OperationalCredentialsDelegate * mOperationalCredentialsDelegate = nullptr;
118121
OperationalDeviceProxy mOperationalDeviceProxy;
119-
// Memory space for the commisisoning parameters that come in as ByteSpans - the caller is not guaranteed to retain this memory
122+
123+
// BEGIN memory space for commissioning parameters that are Spans or similar pointers:
124+
// The caller is not guaranteed to retain the memory these parameters point to.
120125
uint8_t mSsid[CommissioningParameters::kMaxSsidLen];
121126
uint8_t mCredentials[CommissioningParameters::kMaxCredentialsLen];
122127
uint8_t mThreadOperationalDataset[CommissioningParameters::kMaxThreadDatasetLen];
@@ -136,6 +141,11 @@ class AutoCommissioner : public CommissioningDelegate
136141
static constexpr size_t kMaxDefaultNtpSize = 128;
137142
char mDefaultNtp[kMaxDefaultNtpSize];
138143

144+
uint8_t mICDSymmetricKey[Crypto::kAES_CCM128_Key_Length];
145+
Platform::ScopedMemoryBufferWithSize<app::AttributePathParams> mExtraReadPaths;
146+
147+
// END memory space for commisisoning parameters
148+
139149
bool mNeedsNetworkSetup = false;
140150
ReadCommissioningInfo mDeviceCommissioningInfo;
141151
bool mNeedsDST = false;
@@ -155,8 +165,6 @@ class AutoCommissioner : public CommissioningDelegate
155165
uint8_t mAttestationElements[Credentials::kMaxRspLen];
156166
uint16_t mAttestationSignatureLen = 0;
157167
uint8_t mAttestationSignature[Crypto::kMax_ECDSA_Signature_Length];
158-
159-
uint8_t mICDSymmetricKey[Crypto::kAES_CCM128_Key_Length];
160168
};
161169
} // namespace Controller
162170
} // namespace chip

src/controller/CHIPDeviceController.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -2329,6 +2329,12 @@ void DeviceCommissioner::ContinueReadingCommissioningInfo(const CommissioningPar
23292329
Clusters::IcdManagement::Attributes::ActiveModeDuration::Id));
23302330
VerifyOrReturn(builder.AddAttributePath(kRootEndpointId, Clusters::IcdManagement::Id,
23312331
Clusters::IcdManagement::Attributes::ActiveModeThreshold::Id));
2332+
2333+
// Extra paths requested via CommissioningParameters
2334+
for (auto const & path : params.GetExtraReadPaths())
2335+
{
2336+
VerifyOrReturn(builder.AddAttributePath(path));
2337+
}
23322338
}();
23332339

23342340
VerifyOrDie(builder.size() > 0); // our logic is broken if there is nothing to read
@@ -2363,6 +2369,7 @@ void DeviceCommissioner::FinishReadingCommissioningInfo()
23632369
// up returning an error (e.g. because some mandatory information was missing).
23642370
CHIP_ERROR err = CHIP_NO_ERROR;
23652371
ReadCommissioningInfo info;
2372+
info.attributes = mAttributeCache.get();
23662373
AccumulateErrors(err, ParseGeneralCommissioningInfo(info));
23672374
AccumulateErrors(err, ParseBasicInformation(info));
23682375
AccumulateErrors(err, ParseNetworkCommissioningInfo(info));

src/controller/CHIPDeviceController.h

+1
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ class DLL_EXPORT DeviceCommissioner : public DeviceController,
816816

817817
Optional<CommissioningParameters> GetCommissioningParameters()
818818
{
819+
// TODO: Return a non-optional const & to avoid a copy, mDefaultCommissioner is never null
819820
return mDefaultCommissioner == nullptr ? NullOptional : MakeOptional(mDefaultCommissioner->GetCommissioningParameters());
820821
}
821822

src/controller/CommissioningDelegate.h

+20
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818

1919
#pragma once
2020
#include <app-common/zap-generated/cluster-objects.h>
21+
#include <app/AttributePathParams.h>
22+
#include <app/ClusterStateCache.h>
2123
#include <app/OperationalSessionSetup.h>
2224
#include <controller/CommissioneeDeviceProxy.h>
2325
#include <credentials/attestation_verifier/DeviceAttestationDelegate.h>
2426
#include <credentials/attestation_verifier/DeviceAttestationVerifier.h>
2527
#include <crypto/CHIPCryptoPAL.h>
28+
#include <lib/support/Span.h>
2629
#include <lib/support/Variant.h>
2730
#include <matter/tracing/build_config.h>
2831
#include <system/SystemClock.h>
@@ -591,6 +594,18 @@ class CommissioningParameters
591594
}
592595
void ClearICDStayActiveDurationMsec() { mICDStayActiveDurationMsec.ClearValue(); }
593596

597+
Span<const app::AttributePathParams> GetExtraReadPaths() const { return mExtraReadPaths; }
598+
599+
// Additional attribute paths to read as part of the kReadCommissioningInfo stage.
600+
// These values read from the device will be available in ReadCommissioningInfo.attributes.
601+
// Clients should avoid requesting paths that are already read internally by the commissioner
602+
// as no consolidation of internally read and extra paths provided here will be performed.
603+
CommissioningParameters & SetExtraReadPaths(Span<const app::AttributePathParams> paths)
604+
{
605+
mExtraReadPaths = paths;
606+
return *this;
607+
}
608+
594609
// Clear all members that depend on some sort of external buffer. Can be
595610
// used to make sure that we are not holding any dangling pointers.
596611
void ClearExternalBufferDependentValues()
@@ -613,6 +628,7 @@ class CommissioningParameters
613628
mDSTOffsets.ClearValue();
614629
mDefaultNTP.ClearValue();
615630
mICDSymmetricKey.ClearValue();
631+
mExtraReadPaths = decltype(mExtraReadPaths)();
616632
}
617633

618634
private:
@@ -662,6 +678,7 @@ class CommissioningParameters
662678
Optional<uint32_t> mICDStayActiveDurationMsec;
663679
ICDRegistrationStrategy mICDRegistrationStrategy = ICDRegistrationStrategy::kIgnore;
664680
bool mCheckForMatchingFabric = false;
681+
Span<const app::AttributePathParams> mExtraReadPaths;
665682
};
666683

667684
struct RequestedCertificate
@@ -762,6 +779,9 @@ struct ICDManagementClusterInfo
762779

763780
struct ReadCommissioningInfo
764781
{
782+
#if CHIP_CONFIG_ENABLE_READ_CLIENT
783+
app::ClusterStateCache const * attributes = nullptr;
784+
#endif
765785
NetworkClusters network;
766786
BasicClusterInfo basic;
767787
GeneralCommissioningInfo general;

src/lib/support/ScopedBuffer.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
#include <lib/support/CHIPMem.h>
2828
#include <lib/support/CodeUtils.h>
29+
#include <lib/support/Span.h>
2930

3031
#include <type_traits>
3132
#include <utility>
@@ -218,11 +219,12 @@ class ScopedMemoryBufferWithSize : public ScopedMemoryBuffer<T>
218219
return *this;
219220
}
220221

221-
~ScopedMemoryBufferWithSize() { mCount = 0; }
222-
223222
// return the size as count of elements
224223
inline size_t AllocatedSize() const { return mCount; }
225224

225+
chip::Span<T> Span() { return chip::Span<T>(this->Get(), AllocatedSize()); }
226+
chip::Span<const T> Span() const { return chip::Span<T>(this->Get(), AllocatedSize()); }
227+
226228
void Free()
227229
{
228230
mCount = 0;

0 commit comments

Comments
 (0)