| /* |
| * |
| * Copyright (c) 2021 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include "lib/core/TLV.h" |
| #include "system/SystemPacketBuffer.h" |
| #include "system/TLVPacketBufferBackingStore.h" |
| #include <app/AppConfig.h> |
| #include <app/AttributePathParams.h> |
| #include <app/ReadClient.h> |
| #include <vector> |
| |
| #if CHIP_CONFIG_ENABLE_READ_CLIENT |
| namespace chip { |
| namespace app { |
| |
| /* |
| * This is an adapter that intercepts calls that deliver data from the ReadClient, |
| * selectively buffers up list chunks in TLV and reconstitutes them into a singular, contiguous TLV array |
| * upon completion of delivery of all chunks. This is then delivered to a compliant ReadClient::Callback |
| * without any awareness on their part that chunking happened. |
| * |
| */ |
| class BufferedReadCallback : public ReadClient::Callback |
| { |
| public: |
| BufferedReadCallback(Callback & callback) : mCallback(callback) {} |
| |
| private: |
| /* |
| * Generates the reconsistuted TLV array from the stored individual list elements |
| */ |
| CHIP_ERROR GenerateListTLV(TLV::ScopedBufferTLVReader & reader); |
| |
| /* |
| * Dispatch any buffered list data if we need to. Buffered data will only be dispatched if: |
| * 1. The path provided in aPath is different from the buffered path being tracked internally AND the type of data |
| * in the buffer is list data |
| * |
| * OR |
| * |
| * 2. The path provided in aPath is similar to what is buffered but we've hit the end of the report. |
| * |
| */ |
| CHIP_ERROR DispatchBufferedData(const ConcreteAttributePath & aPath, const StatusIB & aStatus, bool aEndOfReport = false); |
| |
| /* |
| * Buffer up list data as they arrive. |
| */ |
| CHIP_ERROR BufferData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apReader); |
| |
| // |
| // 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 |
| { |
| mBufferedList.clear(); |
| return mCallback.OnError(aError); |
| } |
| |
| void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) override |
| { |
| return mCallback.OnEventData(aEventHeader, apData, apStatus); |
| } |
| |
| void OnDone(ReadClient * apReadClient) override { return mCallback.OnDone(apReadClient); } |
| void OnSubscriptionEstablished(SubscriptionId aSubscriptionId) override |
| { |
| mCallback.OnSubscriptionEstablished(aSubscriptionId); |
| } |
| |
| CHIP_ERROR OnResubscriptionNeeded(ReadClient * apReadClient, CHIP_ERROR aTerminationCause) override |
| { |
| return mCallback.OnResubscriptionNeeded(apReadClient, aTerminationCause); |
| } |
| |
| void OnDeallocatePaths(chip::app::ReadPrepareParams && aReadPrepareParams) override |
| { |
| return mCallback.OnDeallocatePaths(std::move(aReadPrepareParams)); |
| } |
| |
| virtual CHIP_ERROR OnUpdateDataVersionFilterList(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder, |
| const Span<AttributePathParams> & aAttributePaths, |
| bool & aEncodedDataVersionList) override |
| { |
| return mCallback.OnUpdateDataVersionFilterList(aDataVersionFilterIBsBuilder, aAttributePaths, aEncodedDataVersionList); |
| } |
| |
| virtual CHIP_ERROR GetHighestReceivedEventNumber(Optional<EventNumber> & aEventNumber) override |
| { |
| return mCallback.GetHighestReceivedEventNumber(aEventNumber); |
| } |
| |
| void OnUnsolicitedMessageFromPublisher(ReadClient * apReadClient) override |
| { |
| return mCallback.OnUnsolicitedMessageFromPublisher(apReadClient); |
| } |
| |
| void OnCASESessionEstablished(const SessionHandle & aSession, ReadPrepareParams & aSubscriptionParams) override |
| { |
| return mCallback.OnCASESessionEstablished(aSession, aSubscriptionParams); |
| } |
| |
| /* |
| * Given a reader positioned at a list element, allocate a packet buffer, copy the list item where |
| * the reader is positioned into that buffer and add it to our buffered list for tracking. |
| * |
| * This should be called in list index order starting from the lowest index that needs to be buffered. |
| * |
| */ |
| CHIP_ERROR BufferListItem(TLV::TLVReader & reader); |
| ConcreteDataAttributePath mBufferedPath; |
| std::vector<System::PacketBufferHandle> mBufferedList; |
| Callback & mCallback; |
| }; |
| |
| } // namespace app |
| } // namespace chip |
| #endif // CHIP_CONFIG_ENABLE_READ_CLIENT |