Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
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 : /**
20 : * @file
21 : * This file contains an implementation of TLVBackingStore using PacketBuffers.
22 : */
23 :
24 : #pragma once
25 :
26 : #include <lib/core/TLV.h>
27 : #include <system/SystemPacketBuffer.h>
28 :
29 : #include <utility>
30 :
31 : namespace chip {
32 : namespace System {
33 :
34 : /**
35 : * An implementation of TLVBackingStore using PacketBuffers.
36 : */
37 : class TLVPacketBufferBackingStore : public chip::TLV::TLVBackingStore
38 : {
39 : public:
40 10247 : TLVPacketBufferBackingStore() : mHeadBuffer(nullptr), mCurrentBuffer(nullptr), mUseChainedBuffers(false) {}
41 : TLVPacketBufferBackingStore(chip::System::PacketBufferHandle && buffer, bool useChainedBuffers = false)
42 : {
43 : Init(std::move(buffer), useChainedBuffers);
44 : }
45 10247 : ~TLVPacketBufferBackingStore() override {}
46 :
47 : /**
48 : * Take ownership of a backing packet buffer.
49 : *
50 : * @param[in] buffer A handle to a packet buffer, to be used as backing store for a TLV class.
51 : * @param[in] useChainedBuffers
52 : * If true, advance to the next buffer in the chain once all data or space
53 : * in the current buffer has been consumed; a write will allocate new
54 : * packet buffers if necessary.
55 : *
56 : * @note This must take place before initializing a TLV class with this backing store.
57 : */
58 13797 : void Init(chip::System::PacketBufferHandle && buffer, bool useChainedBuffers = false)
59 : {
60 13797 : mHeadBuffer = std::move(buffer);
61 13797 : mCurrentBuffer = mHeadBuffer.Retain();
62 13797 : mUseChainedBuffers = useChainedBuffers;
63 13797 : }
64 : void Adopt(chip::System::PacketBufferHandle && buffer) { Init(std::move(buffer), mUseChainedBuffers); }
65 :
66 : /**
67 : * Release ownership of the backing packet buffer.
68 : *
69 : * @note TLV operations must no longer be performed on this store.
70 : */
71 13178 : CHECK_RETURN_VALUE chip::System::PacketBufferHandle Release()
72 : {
73 13178 : mCurrentBuffer = nullptr;
74 13178 : return std::move(mHeadBuffer);
75 : }
76 :
77 : // TLVBackingStore overrides:
78 : CHIP_ERROR OnInit(chip::TLV::TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override;
79 : CHIP_ERROR GetNextBuffer(chip::TLV::TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override;
80 : CHIP_ERROR OnInit(chip::TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override;
81 : CHIP_ERROR GetNewBuffer(chip::TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override;
82 : CHIP_ERROR FinalizeBuffer(chip::TLV::TLVWriter & writer, uint8_t * bufStart, uint32_t bufLen) override;
83 12801 : virtual bool GetNewBufferWillAlwaysFail() override
84 : {
85 : // For non-chained buffers, caller is given one chunk of contiguous memory. All calls to
86 : // GetNewBuffer will fail with CHIP_ERROR_NO_MEMORY.
87 12801 : return !mUseChainedBuffers;
88 : }
89 :
90 : protected:
91 : chip::System::PacketBufferHandle mHeadBuffer;
92 : chip::System::PacketBufferHandle mCurrentBuffer;
93 : bool mUseChainedBuffers;
94 : };
95 :
96 : class DLL_EXPORT PacketBufferTLVReader : public TLV::ContiguousBufferTLVReader
97 : {
98 : public:
99 : /**
100 : * Initializes a TLVReader object to read from a PacketBuffer.
101 : *
102 : * @param[in] buffer A handle to PacketBuffer, to be used as backing
103 : * store for a TLV class. If the buffer is chained,
104 : * only the head of the chain will be used.
105 : */
106 12991 : void Init(chip::System::PacketBufferHandle && buffer)
107 : {
108 12991 : mBuffer = std::move(buffer);
109 12991 : TLV::ContiguousBufferTLVReader::Init(mBuffer->Start(), mBuffer->DataLength());
110 12991 : }
111 :
112 : private:
113 : PacketBufferHandle mBuffer;
114 : };
115 :
116 : class DLL_EXPORT PacketBufferTLVWriter : public chip::TLV::TLVWriter
117 : {
118 : public:
119 : /**
120 : * Initializes a TLVWriter object to write to a PacketBuffer.
121 : *
122 : * @param[in] buffer A handle to PacketBuffer, to be used as backing store for a TLV class.
123 : * @param[in] useChainedBuffers
124 : * If true, advance to the next buffer in the chain once all space
125 : * in the current buffer has been consumed. Once all existing buffers
126 : * have been used, new PacketBuffers will be allocated as necessary.
127 : */
128 13797 : void Init(chip::System::PacketBufferHandle && buffer, bool useChainedBuffers = false)
129 : {
130 13797 : mBackingStore.Init(std::move(buffer), useChainedBuffers);
131 13797 : chip::TLV::TLVWriter::Init(mBackingStore);
132 13797 : }
133 : /**
134 : * Finish the writing of a TLV encoding and release ownership of the underlying PacketBuffer.
135 : *
136 : * @param[in,out] outBuffer The backing packet buffer.
137 : *
138 : * @retval #CHIP_NO_ERROR If the encoding was finalized successfully.
139 : * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN
140 : * If a container writer has been opened on the current writer and not
141 : * yet closed.
142 : * @retval #CHIP_ERROR_INVALID_ARGUMENT
143 : * If the apparent data length does not fit in uint16_t.
144 : *
145 : * @note No further TLV operations may be performed, unless or until this PacketBufferTLVWriter is re-initialized.
146 : */
147 13148 : CHIP_ERROR Finalize(chip::System::PacketBufferHandle * outBuffer)
148 : {
149 13148 : CHIP_ERROR err = Finalize();
150 13148 : *outBuffer = mBackingStore.Release();
151 13148 : return err;
152 : }
153 : /**
154 : * Free the underlying PacketBuffer.
155 : *
156 : * @note No further TLV operations may be performed, unless or until this PacketBufferTLVWriter is re-initialized.
157 : */
158 86 : void Reset() { static_cast<void>(mBackingStore.Release()); }
159 :
160 : private:
161 13148 : CHIP_ERROR Finalize() { return chip::TLV::TLVWriter::Finalize(); }
162 : TLVPacketBufferBackingStore mBackingStore;
163 : };
164 :
165 : } // namespace System
166 : } // namespace chip
|