mirror of
https://github.com/espressif/openthread.git
synced 2026-09-07 09:40:12 +00:00
[core] adding FrameBuilder for constructing frames (#7935)
This commit adds a new class `FrameBuilder` which helps with construction of frames in a given buffer. It provides helper methods to append different items to the frame, e.g., bytes from a buffer or `Message`, a `uint8`, `uint16` or `uint32` value assuming big or little endian encoding, or a given object. It also provides methods to overwrite previously appended content in the frame at a given offset. This class is used in `Lowpan` (replacing `BufferWriter`) which helps simplify the code. This commit also updates `Appender` to use the `FrameBuilder` and adds a new unit test for `FrameBuidler`.
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2022, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include "test_platform.h"
|
||||
#include "test_util.hpp"
|
||||
|
||||
#include "common/frame_builder.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
void TestFrameBuilder(void)
|
||||
{
|
||||
const uint8_t kData1[] = {0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
const uint8_t kData2[] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa};
|
||||
|
||||
static constexpr uint16_t kMaxBufferSize = sizeof(kData1) * 2 + sizeof(kData2);
|
||||
|
||||
Instance * instance;
|
||||
Message * message;
|
||||
uint16_t offset;
|
||||
uint8_t buffer[kMaxBufferSize];
|
||||
uint8_t zeroBuffer[kMaxBufferSize];
|
||||
FrameBuilder frameBuilder;
|
||||
|
||||
printf("TestFrameBuilder\n");
|
||||
|
||||
instance = static_cast<Instance *>(testInitInstance());
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
|
||||
message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
|
||||
VerifyOrQuit(message != nullptr);
|
||||
|
||||
SuccessOrQuit(message->Append(kData1));
|
||||
SuccessOrQuit(message->Append(kData2));
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
memset(zeroBuffer, 0, sizeof(zeroBuffer));
|
||||
|
||||
frameBuilder.Init(buffer, sizeof(buffer));
|
||||
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(frameBuilder.GetLength() == 0);
|
||||
VerifyOrQuit(frameBuilder.GetMaxLength() == sizeof(buffer));
|
||||
VerifyOrQuit(memcmp(buffer, zeroBuffer, sizeof(buffer)) == 0);
|
||||
VerifyOrQuit(frameBuilder.CanAppend(sizeof(buffer)));
|
||||
VerifyOrQuit(!frameBuilder.CanAppend(sizeof(buffer) + 1));
|
||||
|
||||
SuccessOrQuit(frameBuilder.Append(kData1));
|
||||
VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData1));
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
|
||||
VerifyOrQuit(memcmp(buffer + sizeof(kData1), zeroBuffer, sizeof(buffer) - sizeof(kData1)) == 0);
|
||||
|
||||
SuccessOrQuit(frameBuilder.AppendUint8(0x01));
|
||||
SuccessOrQuit(frameBuilder.AppendBigEndianUint16(0x0203));
|
||||
SuccessOrQuit(frameBuilder.AppendLittleEndianUint16(0x0504));
|
||||
VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData1) * 2);
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
|
||||
VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData1, sizeof(kData1)) == 0);
|
||||
|
||||
SuccessOrQuit(frameBuilder.AppendBigEndianUint32(0x01020304));
|
||||
SuccessOrQuit(frameBuilder.AppendUint8(0x05));
|
||||
VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData1) * 3);
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
|
||||
VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData1, sizeof(kData1)) == 0);
|
||||
VerifyOrQuit(memcmp(buffer + 2 * sizeof(kData1), kData1, sizeof(kData1)) == 0);
|
||||
|
||||
frameBuilder.Init(buffer, sizeof(buffer));
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(frameBuilder.GetLength() == 0);
|
||||
VerifyOrQuit(frameBuilder.GetMaxLength() == sizeof(buffer));
|
||||
|
||||
offset = sizeof(kData1);
|
||||
SuccessOrQuit(frameBuilder.AppendBytesFromMessage(*message, offset, sizeof(kData2)));
|
||||
VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData2));
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(memcmp(buffer, kData2, sizeof(kData2)) == 0);
|
||||
|
||||
frameBuilder.Init(buffer, sizeof(buffer));
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(frameBuilder.GetLength() == 0);
|
||||
VerifyOrQuit(frameBuilder.GetMaxLength() == sizeof(buffer));
|
||||
|
||||
SuccessOrQuit(frameBuilder.AppendLittleEndianUint32(0x04030201));
|
||||
SuccessOrQuit(frameBuilder.AppendUint8(0x05));
|
||||
VerifyOrQuit(frameBuilder.GetLength() == sizeof(kData1));
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
|
||||
|
||||
SuccessOrQuit(frameBuilder.AppendBytes(zeroBuffer, sizeof(kData2)));
|
||||
SuccessOrQuit(frameBuilder.Append(kData1));
|
||||
VerifyOrQuit(frameBuilder.GetLength() == sizeof(buffer));
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
|
||||
VerifyOrQuit(memcmp(buffer + sizeof(kData1), zeroBuffer, sizeof(kData2)) == 0);
|
||||
VerifyOrQuit(memcmp(buffer + sizeof(kData1) + sizeof(kData2), kData1, sizeof(kData1)) == 0);
|
||||
|
||||
VerifyOrQuit(!frameBuilder.CanAppend(1));
|
||||
VerifyOrQuit(frameBuilder.AppendUint8(0x00) == kErrorNoBufs);
|
||||
|
||||
offset = sizeof(kData1);
|
||||
frameBuilder.Write(offset, kData2);
|
||||
VerifyOrQuit(frameBuilder.GetLength() == sizeof(buffer));
|
||||
VerifyOrQuit(frameBuilder.GetBytes() == buffer);
|
||||
VerifyOrQuit(memcmp(buffer, kData1, sizeof(kData1)) == 0);
|
||||
VerifyOrQuit(memcmp(buffer + sizeof(kData1), kData2, sizeof(kData2)) == 0);
|
||||
VerifyOrQuit(memcmp(buffer + sizeof(kData1) + sizeof(kData2), kData1, sizeof(kData1)) == 0);
|
||||
|
||||
message->Free();
|
||||
testFreeInstance(instance);
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ot::TestFrameBuilder();
|
||||
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user