Skip to content

Commit 4307513

Browse files
erjiaqingpull[bot]
authored andcommitted
[IM] Wildcard read and chunking (#11304)
* [IM] Support chunking in report engine * Address comments * Support wildcard path in read / subscribe interaction
1 parent e1508e1 commit 4307513

16 files changed

+603
-97
lines changed

src/app/ClusterInfo.h

+10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#pragma once
2020

21+
#include <app/ConcreteAttributePath.h>
2122
#include <app/util/basic-types.h>
2223
#include <assert.h>
2324
#include <lib/core/Optional.h>
@@ -57,6 +58,15 @@ struct ClusterInfo
5758
return true;
5859
}
5960

61+
bool IsAttributePathSupersetOf(const ConcreteAttributePath & other) const
62+
{
63+
VerifyOrReturnError(HasWildcardEndpointId() || mEndpointId == other.mEndpointId, false);
64+
VerifyOrReturnError(HasWildcardClusterId() || mClusterId == other.mClusterId, false);
65+
VerifyOrReturnError(HasWildcardAttributeId() || mAttributeId == other.mAttributeId, false);
66+
67+
return true;
68+
}
69+
6070
bool HasWildcard() const { return HasWildcardEndpointId() || HasWildcardClusterId() || HasWildcardAttributeId(); }
6171

6272
/**

src/app/ReadClient.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ CHIP_ERROR ReadClient::OnMessageReceived(Messaging::ExchangeContext * apExchange
261261
}
262262

263263
exit:
264-
if (!IsSubscriptionType() || err != CHIP_NO_ERROR)
264+
if ((!IsSubscriptionType() && !mPendingMoreChunks) || err != CHIP_NO_ERROR)
265265
{
266266
ShutdownInternal(err);
267267
}
@@ -300,7 +300,6 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload)
300300
bool isEventReportsPresent = false;
301301
bool isAttributeReportIBsPresent = false;
302302
bool suppressResponse = false;
303-
bool moreChunkedMessages = false;
304303
uint64_t subscriptionId = 0;
305304
EventReports::Parser EventReports;
306305
AttributeReportIBs::Parser attributeReportIBs;
@@ -349,10 +348,11 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload)
349348
}
350349
SuccessOrExit(err);
351350

352-
err = report.GetMoreChunkedMessages(&moreChunkedMessages);
351+
err = report.GetMoreChunkedMessages(&mPendingMoreChunks);
353352
if (CHIP_END_OF_TLV == err)
354353
{
355-
err = CHIP_NO_ERROR;
354+
mPendingMoreChunks = false;
355+
err = CHIP_NO_ERROR;
356356
}
357357
SuccessOrExit(err);
358358

@@ -378,7 +378,7 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload)
378378
err = CHIP_NO_ERROR;
379379
}
380380
SuccessOrExit(err);
381-
if (isAttributeReportIBsPresent && nullptr != mpCallback && !moreChunkedMessages)
381+
if (isAttributeReportIBsPresent && nullptr != mpCallback)
382382
{
383383
TLV::TLVReader attributeReportIBsReader;
384384
attributeReportIBs.GetReader(&attributeReportIBsReader);
@@ -407,9 +407,9 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload)
407407

408408
StatusResponse::SendStatusResponse(err == CHIP_NO_ERROR ? Protocols::InteractionModel::Status::Success
409409
: Protocols::InteractionModel::Status::InvalidSubscription,
410-
mpExchangeCtx, IsAwaitingSubscribeResponse());
410+
mpExchangeCtx, IsAwaitingSubscribeResponse() || mPendingMoreChunks);
411411

412-
if (!mInitialReport)
412+
if (!mInitialReport && !mPendingMoreChunks)
413413
{
414414
mpExchangeCtx = nullptr;
415415
}

src/app/ReadClient.h

+1
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ class ReadClient : public Messaging::ExchangeDelegate
265265
Callback * mpCallback = nullptr;
266266
ClientState mState = ClientState::Uninitialized;
267267
bool mInitialReport = true;
268+
bool mPendingMoreChunks = false;
268269
uint16_t mMinIntervalFloorSeconds = 0;
269270
uint16_t mMaxIntervalCeilingSeconds = 0;
270271
uint64_t mSubscriptionId = 0;

src/app/ReadHandler.cpp

+32-6
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ CHIP_ERROR ReadHandler::Init(Messaging::ExchangeManager * apExchangeMgr, Interac
5454
mHoldReport = false;
5555
mDirty = false;
5656
mActiveSubscription = false;
57+
mIsChunkedReport = false;
5758
mInteractionType = aInteractionType;
5859
mInitiatorNodeId = apExchangeContext->GetSessionHandle().GetPeerNodeId();
5960
mFabricIndex = apExchangeContext->GetSessionHandle().GetFabricIndex();
@@ -107,6 +108,7 @@ void ReadHandler::Shutdown(ShutdownOptions aOptions)
107108
mHoldReport = false;
108109
mDirty = false;
109110
mActiveSubscription = false;
111+
mIsChunkedReport = false;
110112
mInitiatorNodeId = kUndefinedNodeId;
111113
}
112114

@@ -140,7 +142,18 @@ CHIP_ERROR ReadHandler::OnStatusResponse(Messaging::ExchangeContext * apExchange
140142
switch (mState)
141143
{
142144
case HandlerState::AwaitingReportResponse:
143-
if (IsSubscriptionType())
145+
if (IsChunkedReport())
146+
{
147+
InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm();
148+
MoveToState(HandlerState::GeneratingReports);
149+
if (mpExchangeCtx)
150+
{
151+
mpExchangeCtx->WillSendMessage();
152+
}
153+
// Trigger ReportingEngine run for sending next chunk of data.
154+
SuccessOrExit(err = InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun());
155+
}
156+
else if (IsSubscriptionType())
144157
{
145158
InteractionModelEngine::GetInstance()->GetReportingEngine().OnReportConfirm();
146159
if (IsInitialReport())
@@ -176,10 +189,10 @@ CHIP_ERROR ReadHandler::OnStatusResponse(Messaging::ExchangeContext * apExchange
176189
return err;
177190
}
178191

179-
CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload)
192+
CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload, bool aMoreChunks)
180193
{
181194
VerifyOrReturnLogError(IsReportable(), CHIP_ERROR_INCORRECT_STATE);
182-
if (IsInitialReport())
195+
if (IsInitialReport() || IsChunkedReport())
183196
{
184197
mSessionHandle.SetValue(mpExchangeCtx->GetSessionHandle());
185198
}
@@ -190,6 +203,7 @@ CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload)
190203
mpExchangeCtx->SetResponseTimeout(kImMessageTimeout);
191204
}
192205
VerifyOrReturnLogError(mpExchangeCtx != nullptr, CHIP_ERROR_INCORRECT_STATE);
206+
mIsChunkedReport = aMoreChunks;
193207
MoveToState(HandlerState::AwaitingReportResponse);
194208
CHIP_ERROR err = mpExchangeCtx->SendMessage(Protocols::InteractionModel::MsgType::ReportData, std::move(aPayload),
195209
Messaging::SendFlags(Messaging::SendMessageFlags::kExpectResponse));
@@ -200,7 +214,10 @@ CHIP_ERROR ReadHandler::SendReportData(System::PacketBufferHandle && aPayload)
200214
err = RefreshSubscribeSyncTimer();
201215
}
202216
}
203-
ClearDirty();
217+
if (!aMoreChunks)
218+
{
219+
ClearDirty();
220+
}
204221
return err;
205222
}
206223

@@ -319,20 +336,28 @@ CHIP_ERROR ReadHandler::ProcessAttributePathList(AttributePathIBs::Parser & aAtt
319336
AttributePathIB::Parser path;
320337
err = path.Init(reader);
321338
SuccessOrExit(err);
322-
// TODO: Support wildcard paths here
323339
// TODO: MEIs (ClusterId and AttributeId) have a invalid pattern instead of a single invalid value, need to add separate
324340
// functions for checking if we have received valid values.
341+
// TODO: Wildcard cluster id with non-global attributes or wildcard attribute paths should be rejected.
325342
err = path.GetEndpoint(&(clusterInfo.mEndpointId));
326343
if (err == CHIP_NO_ERROR)
327344
{
328345
VerifyOrExit(!clusterInfo.HasWildcardEndpointId(), err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH);
329346
}
347+
else if (err == CHIP_END_OF_TLV)
348+
{
349+
err = CHIP_NO_ERROR;
350+
}
330351
SuccessOrExit(err);
331352
err = path.GetCluster(&(clusterInfo.mClusterId));
332353
if (err == CHIP_NO_ERROR)
333354
{
334355
VerifyOrExit(!clusterInfo.HasWildcardClusterId(), err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH);
335356
}
357+
else if (err == CHIP_END_OF_TLV)
358+
{
359+
err = CHIP_NO_ERROR;
360+
}
336361

337362
SuccessOrExit(err);
338363
err = path.GetAttribute(&(clusterInfo.mAttributeId));
@@ -364,7 +389,8 @@ CHIP_ERROR ReadHandler::ProcessAttributePathList(AttributePathIBs::Parser & aAtt
364389
// if we have exhausted this container
365390
if (CHIP_END_OF_TLV == err)
366391
{
367-
err = CHIP_NO_ERROR;
392+
mAttributePathExpandIterator = AttributePathExpandIterator(mpAttributeClusterInfoList);
393+
err = CHIP_NO_ERROR;
368394
}
369395

370396
exit:

src/app/ReadHandler.h

+18-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#pragma once
2626

27+
#include <app/AttributePathExpandIterator.h>
2728
#include <app/ClusterInfo.h>
2829
#include <app/EventManagement.h>
2930
#include <app/InteractionModelDelegate.h>
@@ -97,12 +98,13 @@ class ReadHandler : public Messaging::ExchangeDelegate
9798
* Send ReportData to initiator
9899
*
99100
* @param[in] aPayload A payload that has read request data
101+
* @param[in] aMoreChunks A flags indicating there will be more chunks expected to be sent for this read request
100102
*
101103
* @retval #Others If fails to send report data
102104
* @retval #CHIP_NO_ERROR On success.
103105
*
104106
*/
105-
CHIP_ERROR SendReportData(System::PacketBufferHandle && aPayload);
107+
CHIP_ERROR SendReportData(System::PacketBufferHandle && aPayload, bool mMoreChunks);
106108

107109
bool IsFree() const { return mState == HandlerState::Uninitialized; }
108110
bool IsReportable() const { return mState == HandlerState::GeneratingReports && !mHoldReport; }
@@ -126,11 +128,19 @@ class ReadHandler : public Messaging::ExchangeDelegate
126128

127129
bool IsReadType() { return mInteractionType == InteractionType::Read; }
128130
bool IsSubscriptionType() { return mInteractionType == InteractionType::Subscribe; }
131+
bool IsChunkedReport() { return mIsChunkedReport; }
129132
bool IsInitialReport() { return mInitialReport; }
130133
bool IsActiveSubscription() const { return mActiveSubscription; }
131134
CHIP_ERROR OnSubscribeRequest(Messaging::ExchangeContext * apExchangeContext, System::PacketBufferHandle && aPayload);
132135
void GetSubscriptionId(uint64_t & aSubscriptionId) { aSubscriptionId = mSubscriptionId; }
133-
void SetDirty() { mDirty = true; }
136+
AttributePathExpandIterator * GetAttributePathExpandIterator() { return &mAttributePathExpandIterator; }
137+
void SetDirty()
138+
{
139+
mDirty = true;
140+
// If the contents of the global dirty set have changed, we need to reset the iterator since the paths
141+
// we've sent up till now are no longer valid and need to be invalidated.
142+
mAttributePathExpandIterator = AttributePathExpandIterator(mpAttributeClusterInfoList);
143+
}
134144
void ClearDirty() { mDirty = false; }
135145
bool IsDirty() { return mDirty; }
136146
NodeId GetInitiatorNodeId() const { return mInitiatorNodeId; }
@@ -192,8 +202,12 @@ class ReadHandler : public Messaging::ExchangeDelegate
192202
bool mHoldReport = false;
193203
bool mDirty = false;
194204
bool mActiveSubscription = false;
195-
NodeId mInitiatorNodeId = kUndefinedNodeId;
196-
FabricIndex mFabricIndex = 0;
205+
// The flag indicating we are in the middle of a series of chunked report messages, this flag will be cleared during sending
206+
// last chunked message.
207+
bool mIsChunkedReport = false;
208+
NodeId mInitiatorNodeId = kUndefinedNodeId;
209+
FabricIndex mFabricIndex = 0;
210+
AttributePathExpandIterator mAttributePathExpandIterator = AttributePathExpandIterator(nullptr);
197211
};
198212
} // namespace app
199213
} // namespace chip

0 commit comments

Comments
 (0)