Skip to content

Commit

Permalink
Implement a Vector-based TLVBackingStore (project-chip#32508)
Browse files Browse the repository at this point in the history
* Implement a Vector-based TLVBackingStore for converting from stream-based input to TLV format

* :Address comments

* Fix for esp32 qemu build
  • Loading branch information
yufengwangca authored Mar 15, 2024
1 parent a0b2fe2 commit 08df52c
Show file tree
Hide file tree
Showing 7 changed files with 375 additions and 0 deletions.
2 changes: 2 additions & 0 deletions scripts/tools/check_includes_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@
'src/app/PendingResponseTrackerImpl.h': {'unordered_set'},

# Not intended for embedded clients
'src/lib/core/TLVVectorWriter.cpp': {'vector'},
'src/lib/core/TLVVectorWriter.h': {'vector'},
'src/lib/support/jsontlv/JsonToTlv.cpp': {'sstream', 'string', 'vector'},
'src/lib/support/jsontlv/JsonToTlv.h': {'string'},
'src/lib/support/jsontlv/TlvToJson.h': {'string'},
Expand Down
14 changes: 14 additions & 0 deletions src/lib/core/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,17 @@ static_library("core") {
"${chip_root}/src/system",
]
}

static_library("vectortlv") {
output_name = "libVectorTlv"
output_dir = "${root_out_dir}/lib"

sources = [
"TLVVectorWriter.cpp",
"TLVVectorWriter.h",
]

cflags = [ "-Wconversion" ]

public_deps = [ ":core" ]
}
93 changes: 93 additions & 0 deletions src/lib/core/TLVVectorWriter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
*
* 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.
*/

#include <lib/core/TLVVectorWriter.h>

#include <cstdint>
#include <vector>

#include <lib/core/CHIPError.h>
#include <lib/core/TLVCommon.h>

namespace chip {
namespace TLV {

namespace {

constexpr uint32_t kIpv6MtuSize = 1280;

} // namespace

TlvVectorWriter::TlvVectorWriter(std::vector<uint8_t> & buffer) : mVectorBuffer(buffer)
{
Init(mVectorBuffer);
}

TlvVectorWriter::~TlvVectorWriter() = default;

TlvVectorWriter::TlvVectorBuffer::TlvVectorBuffer(std::vector<uint8_t> & buffer) : mFinalBuffer(buffer) {}

TlvVectorWriter::TlvVectorBuffer::~TlvVectorBuffer() {}

CHIP_ERROR TlvVectorWriter::TlvVectorBuffer::OnInit(TLVWriter & /*writer*/, uint8_t *& bufStart, uint32_t & bufLen)
{
VerifyOrReturnError(mFinalBuffer.empty(), CHIP_ERROR_INCORRECT_STATE);

ResizeWriteBuffer(bufStart, bufLen);

return CHIP_NO_ERROR;
}

CHIP_ERROR TlvVectorWriter::TlvVectorBuffer::GetNewBuffer(TLVWriter & /*writer*/, uint8_t *& bufStart, uint32_t & bufLen)
{
VerifyOrReturnError(!mFinalBuffer.empty(), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mWritingBuffer.data() == bufStart, CHIP_ERROR_INCORRECT_STATE);

ResizeWriteBuffer(bufStart, bufLen);

return CHIP_NO_ERROR;
}

CHIP_ERROR TlvVectorWriter::TlvVectorBuffer::FinalizeBuffer(TLVWriter & /*writer*/, uint8_t * bufStart, uint32_t bufLen)
{
VerifyOrReturnError(mWritingBuffer.data() == bufStart, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(bufLen <= mWritingBuffer.size(), CHIP_ERROR_BUFFER_TOO_SMALL);

mWritingBuffer.resize(bufLen);

mFinalBuffer.insert(mFinalBuffer.end(), mWritingBuffer.begin(), mWritingBuffer.end());
mWritingBuffer.resize(0);

mFinalBuffer.shrink_to_fit();

return CHIP_NO_ERROR;
}

void TlvVectorWriter::TlvVectorBuffer::ResizeWriteBuffer(uint8_t *& bufStart, uint32_t & bufLen)
{
VerifyOrReturn(mWritingBuffer.empty());

mWritingBuffer.resize(kIpv6MtuSize);
bufStart = mWritingBuffer.data();

auto size = mWritingBuffer.size();
VerifyOrReturn(size <= std::numeric_limits<uint32_t>::max());
bufLen = static_cast<uint32_t>(size);
}

} // namespace TLV
} // namespace chip
83 changes: 83 additions & 0 deletions src/lib/core/TLVVectorWriter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
*
* 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.
*/
#pragma once

#include <cstdint>
#include <vector>

#include <lib/core/CHIPError.h>
#include <lib/core/TLVBackingStore.h>
#include <lib/core/TLVCommon.h>

namespace chip {
namespace TLV {

// Implementation of TLVWriter that writes to a std::vector, automatically
// resizing the vector as needed when writing.
// Users of TlvVectorWriter may call any public API of TLVWriter, except for the
// Init functions.
// This class is not thread-safe, it must be constructed, used, and destroyed on
// a single thread.
class TlvVectorWriter : public TLVWriter
{
public:
// All data will be written to and read from the provided buffer, which must
// outlive this object.
TlvVectorWriter(std::vector<uint8_t> & buffer);
TlvVectorWriter(const TlvVectorWriter &) = delete;
TlvVectorWriter & operator=(const TlvVectorWriter &) = delete;
~TlvVectorWriter();

private:
class TlvVectorBuffer : public TLVBackingStore
{
public:
TlvVectorBuffer(std::vector<uint8_t> & buffer);
TlvVectorBuffer(const TlvVectorBuffer &) = delete;
TlvVectorBuffer & operator=(const TlvVectorBuffer &) = delete;
~TlvVectorBuffer() override;

// TLVBackingStore implementation:
CHIP_ERROR OnInit(TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
CHIP_ERROR GetNextBuffer(TLVReader & reader, const uint8_t *& bufStart, uint32_t & bufLen) override
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
CHIP_ERROR OnInit(TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override;
CHIP_ERROR GetNewBuffer(TLVWriter & writer, uint8_t *& bufStart, uint32_t & bufLen) override;
CHIP_ERROR FinalizeBuffer(TLVWriter & writer, uint8_t * bufStart, uint32_t bufLen) override;

private:
void ResizeWriteBuffer(uint8_t *& bufStart, uint32_t & bufLen);

// mWritingBuffer is the mutable buffer exposed via the TLVBackingStore
// interface. When FinalizeBuffer is called the contents of mWritingBuffer
// are appended to mFinalBuffer and mWritingBuffer is cleared. This allows
// for reading all written data from a single, contiguous buffer
// (mFinalBuffer).
std::vector<uint8_t> mWritingBuffer;
std::vector<uint8_t> & mFinalBuffer;
};

TlvVectorBuffer mVectorBuffer;
};

} // namespace TLV
} // namespace chip
2 changes: 2 additions & 0 deletions src/lib/core/tests/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ chip_test_suite_using_nltest("tests") {
"TestOptional.cpp",
"TestReferenceCounted.cpp",
"TestTLV.cpp",
"TestTLVVectorWriter.cpp",
]

cflags = [ "-Wconversion" ]

public_deps = [
"${chip_root}/src/lib/core",
"${chip_root}/src/lib/core:vectortlv",
"${chip_root}/src/lib/support:test_utils",
"${chip_root}/src/lib/support:testing_nlunit",
"${chip_root}/src/platform",
Expand Down
Loading

0 comments on commit 08df52c

Please sign in to comment.