[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:
Abtin Keshavarzian
2023-02-02 11:01:24 -08:00
committed by GitHub
parent e5530a7e5f
commit 88b3367402
4 changed files with 268 additions and 99 deletions
+102 -32
View File
@@ -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);
}