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 15568 : 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 15568 : ~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 19033 : void Init(chip::System::PacketBufferHandle && buffer, bool useChainedBuffers = false) 59 : { 60 19033 : mHeadBuffer = std::move(buffer); 61 19033 : mCurrentBuffer = mHeadBuffer.Retain(); 62 19033 : mUseChainedBuffers = useChainedBuffers; 63 19033 : } 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 17919 : CHECK_RETURN_VALUE chip::System::PacketBufferHandle Release() 72 : { 73 17919 : mCurrentBuffer = nullptr; 74 17919 : 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 12366 : 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 12366 : 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 12765 : void Init(chip::System::PacketBufferHandle && buffer) 107 : { 108 12765 : mBuffer = std::move(buffer); 109 12765 : TLV::ContiguousBufferTLVReader::Init(mBuffer->Start(), mBuffer->DataLength()); 110 12765 : } 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 18990 : void Init(chip::System::PacketBufferHandle && buffer, bool useChainedBuffers = false) 129 : { 130 18990 : mBackingStore.Init(std::move(buffer), useChainedBuffers); 131 18990 : chip::TLV::TLVWriter::Init(mBackingStore); 132 18990 : } 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 17835 : CHIP_ERROR Finalize(chip::System::PacketBufferHandle * outBuffer) 148 : { 149 17835 : CHIP_ERROR err = Finalize(); 150 17835 : *outBuffer = mBackingStore.Release(); 151 17835 : 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 81 : void Reset() { static_cast<void>(mBackingStore.Release()); } 159 : 160 : private: 161 17835 : CHIP_ERROR Finalize() { return chip::TLV::TLVWriter::Finalize(); } 162 : TLVPacketBufferBackingStore mBackingStore; 163 : }; 164 : 165 : } // namespace System 166 : } // namespace chip