mirror of
https://github.com/espressif/openthread.git
synced 2026-08-01 08:37:47 +00:00
[message] add WriteBytesFromMessage() and Remove/InsertHeader() (#8708)
This commit updates `Message` class adding new methods. A new method `WriteBytesFromMessage()` is added which writes bytes read from another or potentially the same message to the message at a given offset. This method replaces the `CopyTo()` and unlike `CopyTo()` it can be used to copy bytes within the same message in either forward or backward directions. This commit adds `RemoveHeader()` which removes header bytes from the message at a given offset and length. It shrinks the message and copies existing header bytes before the removed segment forward to replace the removed bytes. This commit also adds `InsertHeader()` method which grows the message to make space for new header bytes at a given offset. The existing header bytes are copied backward to make room for the new header bytes. Unit test `test_message` is updated to validated all the newly added methods.
This commit is contained in:
+102
-32
@@ -134,63 +134,90 @@ void TestMessage(void)
|
||||
|
||||
VerifyOrQuit(message->GetLength() == kMaxSize);
|
||||
|
||||
// Test `Message::CopyTo()` behavior.
|
||||
// Test `WriteBytesFromMessage()` behavior copying between different
|
||||
// messages.
|
||||
|
||||
VerifyOrQuit((message2 = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
|
||||
SuccessOrQuit(message2->SetLength(kMaxSize));
|
||||
|
||||
for (uint16_t srcOffset = 0; srcOffset < kMaxSize; srcOffset += kOffsetStep)
|
||||
for (uint16_t readOffset = 0; readOffset < kMaxSize; readOffset += kOffsetStep)
|
||||
{
|
||||
for (uint16_t dstOffset = 0; dstOffset < kMaxSize; dstOffset += kOffsetStep)
|
||||
for (uint16_t writeOffset = 0; writeOffset < kMaxSize; writeOffset += kOffsetStep)
|
||||
{
|
||||
for (uint16_t length = 0; length <= kMaxSize - dstOffset; length += kLengthStep)
|
||||
for (uint16_t length = 0; length <= kMaxSize - Max(writeOffset, readOffset); length += kLengthStep)
|
||||
{
|
||||
uint16_t bytesCopied;
|
||||
|
||||
message2->WriteBytes(0, zeroBuffer, kMaxSize);
|
||||
|
||||
bytesCopied = message->CopyTo(srcOffset, dstOffset, length, *message2);
|
||||
|
||||
if (srcOffset + length <= kMaxSize)
|
||||
{
|
||||
VerifyOrQuit(bytesCopied == length, "CopyTo() failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(bytesCopied == kMaxSize - srcOffset, "CopyTo() failed");
|
||||
}
|
||||
message2->WriteBytesFromMessage(writeOffset, *message, readOffset, length);
|
||||
|
||||
SuccessOrQuit(message2->Read(0, readBuffer, kMaxSize));
|
||||
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], zeroBuffer, dstOffset) == 0, "read before length");
|
||||
VerifyOrQuit(memcmp(&readBuffer[dstOffset], &writeBuffer[srcOffset], bytesCopied) == 0);
|
||||
VerifyOrQuit(
|
||||
memcmp(&readBuffer[dstOffset + bytesCopied], zeroBuffer, kMaxSize - bytesCopied - dstOffset) == 0,
|
||||
"read after length");
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], zeroBuffer, writeOffset) == 0);
|
||||
VerifyOrQuit(memcmp(&readBuffer[writeOffset], &writeBuffer[readOffset], length) == 0);
|
||||
VerifyOrQuit(memcmp(&readBuffer[writeOffset + length], zeroBuffer, kMaxSize - length - writeOffset) ==
|
||||
0);
|
||||
|
||||
VerifyOrQuit(message->CompareBytes(srcOffset, *message2, dstOffset, bytesCopied));
|
||||
VerifyOrQuit(message2->CompareBytes(dstOffset, *message, srcOffset, bytesCopied));
|
||||
VerifyOrQuit(message->CompareBytes(readOffset, *message2, writeOffset, length));
|
||||
VerifyOrQuit(message2->CompareBytes(writeOffset, *message, readOffset, length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify `CopyTo()` with same source and destination message and a backward copy.
|
||||
// Verify `WriteBytesFromMessage()` behavior copying backwards within
|
||||
// same message.
|
||||
|
||||
for (uint16_t srcOffset = 0; srcOffset < kMaxSize; srcOffset++)
|
||||
for (uint16_t readOffset = 0; readOffset < kMaxSize; readOffset++)
|
||||
{
|
||||
uint16_t bytesCopied;
|
||||
uint16_t length = kMaxSize - readOffset;
|
||||
|
||||
message->WriteBytes(0, writeBuffer, kMaxSize);
|
||||
|
||||
bytesCopied = message->CopyTo(srcOffset, 0, kMaxSize, *message);
|
||||
VerifyOrQuit(bytesCopied == kMaxSize - srcOffset, "CopyTo() failed");
|
||||
message->WriteBytesFromMessage(0, *message, readOffset, length);
|
||||
|
||||
SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
|
||||
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[srcOffset], bytesCopied) == 0,
|
||||
"CopyTo() changed before srcOffset");
|
||||
VerifyOrQuit(memcmp(&readBuffer[bytesCopied], &writeBuffer[bytesCopied], kMaxSize - bytesCopied) == 0,
|
||||
"CopyTo() write error");
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[readOffset], length) == 0);
|
||||
VerifyOrQuit(memcmp(&readBuffer[length], &writeBuffer[length], kMaxSize - length) == 0);
|
||||
}
|
||||
|
||||
// Verify `WriteBytesFromMessage()` behavior copying forward within
|
||||
// same message.
|
||||
|
||||
for (uint16_t writeOffset = 0; writeOffset < kMaxSize; writeOffset++)
|
||||
{
|
||||
uint16_t length = kMaxSize - writeOffset;
|
||||
|
||||
message->WriteBytes(0, writeBuffer, kMaxSize);
|
||||
|
||||
message->WriteBytesFromMessage(writeOffset, *message, 0, length);
|
||||
|
||||
SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
|
||||
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[0], writeOffset) == 0);
|
||||
VerifyOrQuit(memcmp(&readBuffer[writeOffset], &writeBuffer[0], length) == 0);
|
||||
}
|
||||
|
||||
// Test `WriteBytesFromMessage()` behavior copying within same
|
||||
// message at different read and write offsets and lengths.
|
||||
|
||||
for (uint16_t readOffset = 0; readOffset < kMaxSize; readOffset += kOffsetStep)
|
||||
{
|
||||
for (uint16_t writeOffset = 0; writeOffset < kMaxSize; writeOffset += kOffsetStep)
|
||||
{
|
||||
for (uint16_t length = 0; length <= kMaxSize - Max(writeOffset, readOffset); length += kLengthStep)
|
||||
{
|
||||
message->WriteBytes(0, writeBuffer, kMaxSize);
|
||||
|
||||
message->WriteBytesFromMessage(writeOffset, *message, readOffset, length);
|
||||
|
||||
SuccessOrQuit(message->Read(0, readBuffer, kMaxSize));
|
||||
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], writeBuffer, writeOffset) == 0);
|
||||
VerifyOrQuit(memcmp(&readBuffer[writeOffset], &writeBuffer[readOffset], length) == 0);
|
||||
VerifyOrQuit(memcmp(&readBuffer[writeOffset + length], &writeBuffer[writeOffset + length],
|
||||
kMaxSize - length - writeOffset) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify `AppendBytesFromMessage()` with two different messages as source and destination.
|
||||
@@ -236,6 +263,49 @@ void TestMessage(void)
|
||||
message->Free();
|
||||
message2->Free();
|
||||
|
||||
// Verify `RemoveHeader()`
|
||||
|
||||
for (uint16_t offset = 0; offset < kMaxSize; offset += kOffsetStep)
|
||||
{
|
||||
for (uint16_t length = 0; length <= kMaxSize - offset; length += kLengthStep)
|
||||
{
|
||||
VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
|
||||
SuccessOrQuit(message->AppendBytes(writeBuffer, kMaxSize));
|
||||
|
||||
message->RemoveHeader(offset, length);
|
||||
|
||||
VerifyOrQuit(message->GetLength() == kMaxSize - length);
|
||||
|
||||
SuccessOrQuit(message->Read(0, readBuffer, kMaxSize - length));
|
||||
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[0], offset) == 0);
|
||||
VerifyOrQuit(memcmp(&readBuffer[offset], &writeBuffer[offset + length], kMaxSize - length - offset) == 0);
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
// Verify `InsertHeader()`
|
||||
|
||||
for (uint16_t offset = 0; offset < kMaxSize; offset += kOffsetStep)
|
||||
{
|
||||
for (uint16_t length = 0; length <= kMaxSize; length += kLengthStep)
|
||||
{
|
||||
VerifyOrQuit((message = messagePool->Allocate(Message::kTypeIp6)) != nullptr);
|
||||
SuccessOrQuit(message->AppendBytes(writeBuffer, kMaxSize));
|
||||
|
||||
SuccessOrQuit(message->InsertHeader(offset, length));
|
||||
|
||||
VerifyOrQuit(message->GetLength() == kMaxSize + length);
|
||||
|
||||
SuccessOrQuit(message->Read(0, readBuffer, offset));
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[0], offset) == 0);
|
||||
|
||||
SuccessOrQuit(message->Read(offset + length, readBuffer, kMaxSize - offset));
|
||||
VerifyOrQuit(memcmp(&readBuffer[0], &writeBuffer[offset], kMaxSize - offset) == 0);
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
testFreeInstance(instance);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user