| /* |
| * |
| * Copyright (c) 2021 Project CHIP Authors |
| * Copyright (c) 2013-2017 Nest Labs, Inc. |
| * |
| * 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. |
| */ |
| |
| /** |
| * @file |
| * This file contains an implementation of TLVBackingStore using PacketBuffers. |
| */ |
| |
| #pragma once |
| |
| #include <lib/core/TLV.h> |
| #include <system/SystemPacketBuffer.h> |
| |
| #include <utility> |
| |
| namespace chip { |
| namespace System { |
| |
| /** |
| * An implementation of TLVBackingStore using PacketBuffers. |
| */ |
| class TLVPacketBufferBackingStore : public chip::TLV::TLVBackingStore |
| { |
| public: |
| TLVPacketBufferBackingStore() : mHeadBuffer(nullptr), mCurrentBuffer(nullptr), mUseChainedBuffers(false) {} |
| TLVPacketBufferBackingStore(chip::System::PacketBufferHandle && buffer, bool useChainedBuffers = false) |
| { |
| Init(std::move(buffer), useChainedBuffers); |
| } |
| ~TLVPacketBufferBackingStore() override {} |
| |
| /** |
| * Take ownership of a backing packet buffer. |
| * |
| * @param[in] buffer A handle to a packet buffer, to be used as backing store for a TLV class. |
| * @param[in] useChainedBuffers |
| * If true, advance to the next buffer in the chain once all data or space |
| * in the current buffer has been consumed; a write will allocate new |
| * packet buffers if necessary. |
| * |
| * @note This must take place before initializing a TLV class with this backing store. |
| */ |
| void Init(chip::System::PacketBufferHandle && buffer, bool useChainedBuffers = false) |
| { |
| mHeadBuffer = std::move(buffer); |
| mCurrentBuffer = mHeadBuffer.Retain(); |
| mUseChainedBuffers = useChainedBuffers; |
| } |
| void Adopt(chip::System::PacketBufferHandle && buffer) { Init(std::move(buffer), mUseChainedBuffers); } |
| |
| /** |
| * Release ownership of the backing packet buffer. |
| * |
| * @note TLV operations must no longer be performed on this store. |
| */ |
| CHECK_RETURN_VALUE chip::System::PacketBufferHandle Release() |
| { |
| mCurrentBuffer = nullptr; |
| return std::move(mHeadBuffer); |
| } |
| |
| // TLVBackingStore overrides: |
| CHIP_ERROR OnInit(chip::TLV::TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override; |
| CHIP_ERROR GetNextBuffer(chip::TLV::TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override; |
| CHIP_ERROR OnInit(chip::TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override; |
| CHIP_ERROR GetNewBuffer(chip::TLV::TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override; |
| CHIP_ERROR FinalizeBuffer(chip::TLV::TLVWriter & writer, uint8_t * bufStart, uint32_t bufLen) override; |
| virtual bool GetNewBufferWillAlwaysFail() override |
| { |
| // For non-chained buffers, caller is given one chunk of contiguous memory. All calls to |
| // GetNewBuffer will fail with CHIP_ERROR_NO_MEMORY. |
| return !mUseChainedBuffers; |
| } |
| |
| protected: |
| chip::System::PacketBufferHandle mHeadBuffer; |
| chip::System::PacketBufferHandle mCurrentBuffer; |
| bool mUseChainedBuffers; |
| }; |
| |
| class DLL_EXPORT PacketBufferTLVReader : public TLV::ContiguousBufferTLVReader |
| { |
| public: |
| /** |
| * Initializes a TLVReader object to read from a PacketBuffer. |
| * |
| * @param[in] buffer A handle to PacketBuffer, to be used as backing |
| * store for a TLV class. If the buffer is chained, |
| * only the head of the chain will be used. |
| */ |
| void Init(chip::System::PacketBufferHandle && buffer) |
| { |
| mBuffer = std::move(buffer); |
| TLV::ContiguousBufferTLVReader::Init(mBuffer->Start(), mBuffer->DataLength()); |
| } |
| |
| private: |
| PacketBufferHandle mBuffer; |
| }; |
| |
| class DLL_EXPORT PacketBufferTLVWriter : public chip::TLV::TLVWriter |
| { |
| public: |
| /** |
| * Initializes a TLVWriter object to write to a PacketBuffer. |
| * |
| * @param[in] buffer A handle to PacketBuffer, to be used as backing store for a TLV class. |
| * @param[in] useChainedBuffers |
| * If true, advance to the next buffer in the chain once all space |
| * in the current buffer has been consumed. Once all existing buffers |
| * have been used, new PacketBuffers will be allocated as necessary. |
| */ |
| void Init(chip::System::PacketBufferHandle && buffer, bool useChainedBuffers = false) |
| { |
| mBackingStore.Init(std::move(buffer), useChainedBuffers); |
| chip::TLV::TLVWriter::Init(mBackingStore); |
| } |
| /** |
| * Finish the writing of a TLV encoding and release ownership of the underlying PacketBuffer. |
| * |
| * @param[in,out] outBuffer The backing packet buffer. |
| * |
| * @retval #CHIP_NO_ERROR If the encoding was finalized successfully. |
| * @retval #CHIP_ERROR_TLV_CONTAINER_OPEN |
| * If a container writer has been opened on the current writer and not |
| * yet closed. |
| * @retval #CHIP_ERROR_INVALID_ARGUMENT |
| * If the apparent data length does not fit in uint16_t. |
| * |
| * @note No further TLV operations may be performed, unless or until this PacketBufferTLVWriter is re-initialized. |
| */ |
| CHIP_ERROR Finalize(chip::System::PacketBufferHandle * outBuffer) |
| { |
| CHIP_ERROR err = Finalize(); |
| *outBuffer = mBackingStore.Release(); |
| return err; |
| } |
| /** |
| * Free the underlying PacketBuffer. |
| * |
| * @note No further TLV operations may be performed, unless or until this PacketBufferTLVWriter is re-initialized. |
| */ |
| void Reset() { static_cast<void>(mBackingStore.Release()); } |
| |
| private: |
| CHIP_ERROR Finalize() { return chip::TLV::TLVWriter::Finalize(); } |
| TLVPacketBufferBackingStore mBackingStore; |
| }; |
| |
| } // namespace System |
| } // namespace chip |