Skip to content

Commit

Permalink
Call OnReportBegin before ReadClient calls OnEventData, and report at…
Browse files Browse the repository at this point in the history
…tribute/event in OnError in Darwin framework callback

Issue 18783 - Sort out interaction of OnReportBegin/OnReportEnd with subscriptions in the Darwin framework

Update src/darwin/Framework/CHIP/CHIPDevice.mm

Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
  • Loading branch information
jtung-apple and bzbarsky-apple committed Jun 15, 2022
1 parent a99bed0 commit c9e89af
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 20 deletions.
7 changes: 6 additions & 1 deletion src/app/BufferedReadCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ class BufferedReadCallback : public ReadClient::Callback
void OnReportBegin() override;
void OnReportEnd() override;
void OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus) override;
void OnError(CHIP_ERROR aError) override { return mCallback.OnError(aError); }
void OnError(CHIP_ERROR aError) override
{
mBufferedList.clear();
return mCallback.OnError(aError);
}

void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) override
{
return mCallback.OnEventData(aEventHeader, apData, apStatus);
Expand Down
30 changes: 17 additions & 13 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ ReadClient::ReadClient(InteractionModelEngine * apImEngine, Messaging::ExchangeM

void ReadClient::ClearActiveSubscriptionState()
{
mIsInitialReport = true;
mIsReporting = false;
mIsPrimingReports = true;
mPendingMoreChunks = false;
mMinIntervalFloorSeconds = 0;
Expand Down Expand Up @@ -558,24 +558,15 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload)
else if (err == CHIP_NO_ERROR)
{
TLV::TLVReader attributeReportIBsReader;
mSawAttributeReportsInCurrentReport = true;
attributeReportIBs.GetReader(&attributeReportIBsReader);

if (mIsInitialReport)
{
mpCallback.OnReportBegin();
mIsInitialReport = false;
}

err = ProcessAttributeReportIBs(attributeReportIBsReader);
}
SuccessOrExit(err);

if (mSawAttributeReportsInCurrentReport && !mPendingMoreChunks)
if (mIsReporting && !mPendingMoreChunks)
{
mpCallback.OnReportEnd();
mIsInitialReport = true;
mSawAttributeReportsInCurrentReport = false;
mIsReporting = false;
}

SuccessOrExit(err = report.ExitContainer());
Expand All @@ -597,7 +588,7 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle && aPayload)
{
bool noResponseExpected = IsSubscriptionActive() && !mPendingMoreChunks;
err = StatusResponse::Send(err == CHIP_NO_ERROR ? Protocols::InteractionModel::Status::Success
: Protocols::InteractionModel::Status::InvalidSubscription,
: Protocols::InteractionModel::Status::InvalidSubscription,
mpExchangeCtx, !noResponseExpected);

if (noResponseExpected || (err != CHIP_NO_ERROR))
Expand Down Expand Up @@ -633,6 +624,15 @@ CHIP_ERROR ReadClient::ProcessAttributePath(AttributePathIB::Parser & aAttribute
return CHIP_NO_ERROR;
}

void ReadClient::NoteReportingData()
{
if (!mIsReporting)
{
mpCallback.OnReportBegin();
mIsReporting = true;
}
}

CHIP_ERROR ReadClient::ProcessAttributeReportIBs(TLV::TLVReader & aAttributeReportIBsReader)
{
CHIP_ERROR err = CHIP_NO_ERROR;
Expand All @@ -657,6 +657,7 @@ CHIP_ERROR ReadClient::ProcessAttributeReportIBs(TLV::TLVReader & aAttributeRepo
ReturnErrorOnFailure(ProcessAttributePath(path, attributePath));
ReturnErrorOnFailure(status.GetErrorStatus(&errorStatus));
ReturnErrorOnFailure(errorStatus.DecodeStatusIB(statusIB));
NoteReportingData();
mpCallback.OnAttributeData(attributePath, nullptr, statusIB);
}
else if (CHIP_END_OF_TLV == err)
Expand All @@ -681,6 +682,7 @@ CHIP_ERROR ReadClient::ProcessAttributeReportIBs(TLV::TLVReader & aAttributeRepo
attributePath.mListOp = ConcreteDataAttributePath::ListOperation::ReplaceAll;
}

NoteReportingData();
mpCallback.OnAttributeData(attributePath, &dataReader, statusIB);
}
}
Expand Down Expand Up @@ -722,6 +724,7 @@ CHIP_ERROR ReadClient::ProcessEventReportIBs(TLV::TLVReader & aEventReportIBsRea
mReadPrepareParams.mEventNumber.SetValue(header.mEventNumber + 1);
}

NoteReportingData();
mpCallback.OnEventData(header, &dataReader, nullptr);
}
else if (err == CHIP_END_OF_TLV)
Expand All @@ -735,6 +738,7 @@ CHIP_ERROR ReadClient::ProcessEventReportIBs(TLV::TLVReader & aEventReportIBsRea
ReturnErrorOnFailure(status.GetErrorStatus(&statusIBParser));
ReturnErrorOnFailure(statusIBParser.DecodeStatusIB(statusIB));

NoteReportingData();
mpCallback.OnEventData(header, nullptr, &statusIB);
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/app/ReadClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,18 @@ class ReadClient : public Messaging::ExchangeDelegate
virtual ~Callback() = default;

/**
* Used to signal the commencement of processing of the first attribute report received in a given exchange.
* Used to signal the commencement of processing of the first attribute or event report received in a given exchange.
*
* This object MUST continue to exist after this call is completed. The application shall wait until it
* receives an OnDone call to destroy the object.
*
* Once OnReportBegin has been called, either OnReportEnd or OnError will be called before OnDone.
*
*/
virtual void OnReportBegin() {}

/**
* Used to signal the completion of processing of the last attribute report in a given exchange.
* Used to signal the completion of processing of the last attribute or event report in a given exchange.
*
* This object MUST continue to exist after this call is completed. The application shall wait until it
* receives an OnDone call to destroy the object.
Expand Down Expand Up @@ -395,6 +397,8 @@ class ReadClient : public Messaging::ExchangeDelegate
CHIP_ERROR SendSubscribeRequestImpl(const ReadPrepareParams & aSubscribePrepareParams);
void UpdateDataVersionFilters(const ConcreteDataAttributePath & aPath);
static void OnResubscribeTimerCallback(System::Layer * apSystemLayer, void * apAppState);
// Called to ensure OnReportBegin is called before calling OnEventData or OnAttributeData
void NoteReportingData();

/*
* Called internally to signal the completion of all work on this object, gracefully close the
Expand All @@ -414,6 +418,7 @@ class ReadClient : public Messaging::ExchangeDelegate
Messaging::ExchangeContext * mpExchangeCtx = nullptr;
Callback & mpCallback;
ClientState mState = ClientState::Idle;
bool mIsReporting = false;
bool mIsInitialReport = true;
bool mIsPrimingReports = true;
bool mPendingMoreChunks = false;
Expand All @@ -424,7 +429,6 @@ class ReadClient : public Messaging::ExchangeDelegate
FabricIndex mFabricIndex = kUndefinedFabricIndex;
InteractionType mInteractionType = InteractionType::Read;
Timestamp mEventTimestamp;
bool mSawAttributeReportsInCurrentReport = false;

ReadClient * mpNext = nullptr;
InteractionModelEngine * mpImEngine = nullptr;
Expand Down
14 changes: 11 additions & 3 deletions src/darwin/Framework/CHIP/CHIPDevice.mm
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ - (instancetype)initWithDevice:(chip::DeviceProxy *)device

void OnSubscriptionEstablished(SubscriptionId aSubscriptionId) override;

void ReportData();
void ReportError(CHIP_ERROR err);
void ReportError(const StatusIB & status);
void ReportError(NSError * _Nullable err);
Expand Down Expand Up @@ -1393,7 +1394,8 @@ - (instancetype)initWithPath:(const ConcreteEventPath &)path
mEventReports = [NSMutableArray new];
}

void SubscriptionCallback::OnReportEnd()
// Reports attribute and event data if any exists
void SubscriptionCallback::ReportData()
{
__block NSArray * attributeReports = mAttributeReports;
mAttributeReports = nil;
Expand All @@ -1409,9 +1411,10 @@ - (instancetype)initWithPath:(const ConcreteEventPath &)path
mEventReportCallback(eventReports);
});
}
// Else we have a pending error already.
}

void SubscriptionCallback::OnReportEnd() { ReportData(); }

void SubscriptionCallback::OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus)
{
id _Nullable value = nil;
Expand Down Expand Up @@ -1485,7 +1488,12 @@ - (instancetype)initWithPath:(const ConcreteEventPath &)path
[mAttributeReports addObject:[[CHIPAttributeReport alloc] initWithPath:aPath value:value error:error]];
}

void SubscriptionCallback::OnError(CHIP_ERROR aError) { ReportError([CHIPError errorForCHIPErrorCode:aError]); }
void SubscriptionCallback::OnError(CHIP_ERROR aError)
{
// If OnError is called after OnReportBegin, we should report the collected data
ReportData();
ReportError([CHIPError errorForCHIPErrorCode:aError]);
}

void SubscriptionCallback::OnDone(ReadClient *)
{
Expand Down

0 comments on commit c9e89af

Please sign in to comment.