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 846 : BufferedReadCallback(Callback & callback, bool allowLargePayload = false) :
44 846 : mAllowLargePayload(allowLargePayload), mCallback(callback)
45 846 : {}
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 * apData);
69 :
70 : //
71 : // ReadClient::Callback
72 : //
73 : void OnReportBegin() override;
74 : void OnReportEnd() override;
75 17 : void NotifySubscriptionStillActive(const ReadClient & apReadClient) override
76 : {
77 17 : mCallback.NotifySubscriptionStillActive(apReadClient);
78 17 : }
79 : void OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus) override;
80 98 : void OnError(CHIP_ERROR aError) override
81 : {
82 98 : mBufferedList.clear();
83 98 : return mCallback.OnError(aError);
84 : }
85 :
86 1532 : void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) override
87 : {
88 1532 : return mCallback.OnEventData(aEventHeader, apData, apStatus);
89 : }
90 :
91 822 : void OnDone(ReadClient * apReadClient) override { return mCallback.OnDone(apReadClient); }
92 207 : void OnSubscriptionEstablished(SubscriptionId aSubscriptionId) override
93 : {
94 207 : mCallback.OnSubscriptionEstablished(aSubscriptionId);
95 207 : }
96 :
97 6 : CHIP_ERROR OnResubscriptionNeeded(ReadClient * apReadClient, CHIP_ERROR aTerminationCause) override
98 : {
99 6 : return mCallback.OnResubscriptionNeeded(apReadClient, aTerminationCause);
100 : }
101 :
102 208 : void OnDeallocatePaths(chip::app::ReadPrepareParams && aReadPrepareParams) override
103 : {
104 208 : return mCallback.OnDeallocatePaths(std::move(aReadPrepareParams));
105 : }
106 :
107 1253 : virtual CHIP_ERROR OnUpdateDataVersionFilterList(DataVersionFilterIBs::Builder & aDataVersionFilterIBsBuilder,
108 : const Span<AttributePathParams> & aAttributePaths,
109 : bool & aEncodedDataVersionList) override
110 : {
111 1253 : return mCallback.OnUpdateDataVersionFilterList(aDataVersionFilterIBsBuilder, aAttributePaths, aEncodedDataVersionList);
112 : }
113 :
114 4 : virtual CHIP_ERROR GetHighestReceivedEventNumber(Optional<EventNumber> & aEventNumber) override
115 : {
116 4 : return mCallback.GetHighestReceivedEventNumber(aEventNumber);
117 : }
118 :
119 9 : void OnUnsolicitedMessageFromPublisher(ReadClient * apReadClient) override
120 : {
121 9 : return mCallback.OnUnsolicitedMessageFromPublisher(apReadClient);
122 : }
123 :
124 0 : void OnCASESessionEstablished(const SessionHandle & aSession, ReadPrepareParams & aSubscriptionParams) override
125 : {
126 0 : return mCallback.OnCASESessionEstablished(aSession, aSubscriptionParams);
127 : }
128 :
129 : /*
130 : * Given a reader positioned at a list element, allocate a packet buffer, copy the list item where
131 : * the reader is positioned into that buffer and add it to our buffered list for tracking.
132 : *
133 : * This should be called in list index order starting from the lowest index that needs to be buffered.
134 : *
135 : */
136 : CHIP_ERROR BufferListItem(TLV::TLVReader & reader);
137 : ConcreteDataAttributePath mBufferedPath;
138 : std::vector<System::PacketBufferHandle> mBufferedList;
139 : bool mAllowLargePayload = false;
140 : Callback & mCallback;
141 : };
142 :
143 : } // namespace app
144 : } // namespace chip
145 : #endif // CHIP_CONFIG_ENABLE_READ_CLIENT
|