Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #pragma once
20 :
21 : #include "lib/core/TLV.h"
22 : #include "system/SystemPacketBuffer.h"
23 : #include "system/TLVPacketBufferBackingStore.h"
24 : #include <app/AppConfig.h>
25 : #include <app/AttributePathParams.h>
26 : #include <app/ReadClient.h>
27 : #include <vector>
28 :
29 : #if CHIP_CONFIG_ENABLE_READ_CLIENT
30 : namespace chip {
31 : namespace app {
32 :
33 : /*
34 : * This is an adapter that intercepts calls that deliver data from the ReadClient,
35 : * selectively buffers up list chunks in TLV and reconstitutes them into a singular, contiguous TLV array
36 : * upon completion of delivery of all chunks. This is then delivered to a compliant ReadClient::Callback
37 : * without any awareness on their part that chunking happened.
38 : *
39 : */
40 : class BufferedReadCallback : public ReadClient::Callback
41 : {
42 : public:
43 836 : BufferedReadCallback(Callback & callback, bool allowLargePayload = false) :
44 836 : mAllowLargePayload(allowLargePayload), mCallback(callback)
45 836 : {}
46 :
47 : private:
48 : /*
49 : * Generates the reconsistuted TLV array from the stored individual list elements
50 : */
51 : CHIP_ERROR GenerateListTLV(TLV::ScopedBufferTLVReader & reader);
52 :
53 : /*
54 : * Dispatch any buffered list data if we need to. Buffered data will only be dispatched if:
55 : * 1. The path provided in aPath is different from the buffered path being tracked internally AND the type of data
56 : * in the buffer is list data
57 : *
58 : * OR
59 : *
60 : * 2. The path provided in aPath is similar to what is buffered but we've hit the end of the report.
61 : *
62 : */
63 : CHIP_ERROR DispatchBufferedData(const ConcreteAttributePath & aPath, const StatusIB & aStatus, bool aEndOfReport = false);
64 :
65 : /*
66 : * Buffer up list data as they arrive.
67 : */
68 : CHIP_ERROR BufferData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apReader);
69 :
70 : //
71 : // ReadClient::Callback
72 : //
73 : void OnReportBegin() override;
74 : void OnReportEnd() override;
75 : void OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus) override;
76 98 : void OnError(CHIP_ERROR aError) override
77 : {
78 98 : mBufferedList.clear();
79 98 : return mCallback.OnError(aError);
80 : }
81 :
82 1532 : void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) override
83 : {
84 1532 : return mCallback.OnEventData(aEventHeader, apData, apStatus);
85 : }
86 :
87 822 : void OnDone(ReadClient * apReadClient) override { return mCallback.OnDone(apReadClient); }
88 207 : void OnSubscriptionEstablished(SubscriptionId aSubscriptionId) override
89 : {
90 207 : mCallback.OnSubscriptionEstablished(aSubscriptionId);
91 207 : }
92 :
93 6 : CHIP_ERROR OnResubscriptionNeeded(ReadClient * apReadClient, CHIP_ERROR aTerminationCause) override
94 : {
95 6 : return mCallback.OnResubscriptionNeeded(apReadClient, aTerminationCause);
96 : }
97 :
98 208 : void OnDeallocatePaths(chip::app::ReadPrepareParams && aReadPrepareParams) override
99 : {
100 208 : return mCallback.OnDeallocatePaths(std::move(aReadPrepareParams));
101 : }
102 :
103 1253 : virtual CHIP_ERROR OnUpdateDataVersionFilterList(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder,
104 : const Span<AttributePathParams> & aAttributePaths,
105 : bool & aEncodedDataVersionList) override
106 : {
107 1253 : return mCallback.OnUpdateDataVersionFilterList(aDataVersionFilterIBsBuilder, aAttributePaths, aEncodedDataVersionList);
108 : }
109 :
110 4 : virtual CHIP_ERROR GetHighestReceivedEventNumber(Optional<EventNumber> & aEventNumber) override
111 : {
112 4 : return mCallback.GetHighestReceivedEventNumber(aEventNumber);
113 : }
114 :
115 9 : void OnUnsolicitedMessageFromPublisher(ReadClient * apReadClient) override
116 : {
117 9 : return mCallback.OnUnsolicitedMessageFromPublisher(apReadClient);
118 : }
119 :
120 0 : void OnCASESessionEstablished(const SessionHandle & aSession, ReadPrepareParams & aSubscriptionParams) override
121 : {
122 0 : return mCallback.OnCASESessionEstablished(aSession, aSubscriptionParams);
123 : }
124 :
125 : /*
126 : * Given a reader positioned at a list element, allocate a packet buffer, copy the list item where
127 : * the reader is positioned into that buffer and add it to our buffered list for tracking.
128 : *
129 : * This should be called in list index order starting from the lowest index that needs to be buffered.
130 : *
131 : */
132 : CHIP_ERROR BufferListItem(TLV::TLVReader & reader);
133 : ConcreteDataAttributePath mBufferedPath;
134 : std::vector<System::PacketBufferHandle> mBufferedList;
135 : bool mAllowLargePayload = false;
136 : Callback & mCallback;
137 : };
138 :
139 : } // namespace app
140 : } // namespace chip
141 : #endif // CHIP_CONFIG_ENABLE_READ_CLIENT
|