[dns] TxtEntry::AppendEntries() to append into a buffer (#7176)

This commit adds new flavor of `Dns::TxtEntry::AppendEntries()` to
encode and append TXT record entries in a data buffer (in addition to
existing one which appends to a `Message`). `Appender` class is used
in the underlying implementation . This commit also updates
`test_dns` unit test to validate newly added method.
This commit is contained in:
Abtin Keshavarzian
2021-11-22 21:41:28 -08:00
committed by Jonathan Hui
parent 7c284b1517
commit 56ca28882a
3 changed files with 80 additions and 28 deletions
+37 -12
View File
@@ -956,6 +956,13 @@ exit:
}
Error TxtEntry::AppendTo(Message &aMessage) const
{
Appender appender(aMessage);
return AppendTo(appender);
}
Error TxtEntry::AppendTo(Appender &aAppender) const
{
Error error = kErrorNone;
uint16_t keyLength;
@@ -964,7 +971,7 @@ Error TxtEntry::AppendTo(Message &aMessage) const
if (mKey == nullptr)
{
VerifyOrExit((mValue != nullptr) && (mValueLength != 0));
error = aMessage.AppendBytes(mValue, mValueLength);
error = aAppender.AppendBytes(mValue, mValueLength);
ExitNow();
}
@@ -975,8 +982,8 @@ Error TxtEntry::AppendTo(Message &aMessage) const
if (mValue == nullptr)
{
// Treat as a boolean attribute and encoded as "key" (with no `=`).
SuccessOrExit(error = aMessage.Append<uint8_t>(static_cast<uint8_t>(keyLength)));
error = aMessage.AppendBytes(mKey, keyLength);
SuccessOrExit(error = aAppender.Append<uint8_t>(static_cast<uint8_t>(keyLength)));
error = aAppender.AppendBytes(mKey, keyLength);
ExitNow();
}
@@ -984,10 +991,10 @@ Error TxtEntry::AppendTo(Message &aMessage) const
VerifyOrExit(mValueLength + keyLength + sizeof(char) <= kMaxKeyValueEncodedSize, error = kErrorInvalidArgs);
SuccessOrExit(error = aMessage.Append<uint8_t>(static_cast<uint8_t>(keyLength + mValueLength + sizeof(char))));
SuccessOrExit(error = aMessage.AppendBytes(mKey, keyLength));
SuccessOrExit(error = aMessage.Append(separator));
error = aMessage.AppendBytes(mValue, mValueLength);
SuccessOrExit(error = aAppender.Append<uint8_t>(static_cast<uint8_t>(keyLength + mValueLength + sizeof(char))));
SuccessOrExit(error = aAppender.AppendBytes(mKey, keyLength));
SuccessOrExit(error = aAppender.Append(separator));
error = aAppender.AppendBytes(mValue, mValueLength);
exit:
return error;
@@ -995,17 +1002,35 @@ exit:
Error TxtEntry::AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Message &aMessage)
{
Error error = kErrorNone;
uint16_t startOffset = aMessage.GetLength();
Appender appender(aMessage);
return AppendEntries(aEntries, aNumEntries, appender);
}
Error TxtEntry::AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, MutableData<kWithUint16Length> &aData)
{
Error error;
Appender appender(aData.GetBytes(), aData.GetLength());
SuccessOrExit(error = AppendEntries(aEntries, aNumEntries, appender));
appender.GetAsData(aData);
exit:
return error;
}
Error TxtEntry::AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Appender &aAppender)
{
Error error = kErrorNone;
for (uint8_t index = 0; index < aNumEntries; index++)
{
SuccessOrExit(error = aEntries[index].AppendTo(aMessage));
SuccessOrExit(error = aEntries[index].AppendTo(aAppender));
}
if (aMessage.GetLength() == startOffset)
if (aAppender.GetAppendedLength() == 0)
{
error = aMessage.Append<uint8_t>(0);
error = aAppender.Append<uint8_t>(0);
}
exit:
+18
View File
@@ -39,6 +39,7 @@
#include <openthread/dns.h>
#include <openthread/dns_client.h>
#include "common/appender.hpp"
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/encoding.hpp"
@@ -1161,7 +1162,24 @@ public:
*/
static Error AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Message &aMessage);
/**
* This static method appends an array of `TxtEntry` items to a `MutableData` buffer.
*
* @param[in] aEntries A pointer to array of `TxtEntry` items.
* @param[in] aNumEntries The number of entries in @p aEntries array.
* @param[in] aData The `MutableData` to append in.
*
* @retval kErrorNone Entries appended successfully .
* @retval kErrorInvalidArgs The `TxTEntry` info is not valid.
* @retval kErrorNoBufs Insufficient available buffers.
*
*/
static Error AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, MutableData<kWithUint16Length> &aData);
private:
Error AppendTo(Appender &aAppender) const;
static Error AppendEntries(const TxtEntry *aEntries, uint8_t aNumEntries, Appender &aAppender);
static constexpr uint8_t kMaxKeyValueEncodedSize = 255;
static constexpr char kKeyValueSeparator = '=';
static constexpr char kNullChar = '\0';
+25 -16
View File
@@ -1185,14 +1185,15 @@ void TestDnsTxtEntry(void)
{kEncodedTxt5, sizeof(kEncodedTxt5)}, {kEncodedTxt6, sizeof(kEncodedTxt6)},
{kEncodedTxt7, sizeof(kEncodedTxt7)}};
Instance * instance;
MessagePool * messagePool;
Message * message;
uint8_t txtData[kMaxTxtDataSize];
uint16_t txtDataLength;
uint8_t index;
Dns::TxtEntry txtEntry;
Dns::TxtEntry::Iterator iterator;
Instance * instance;
MessagePool * messagePool;
Message * message;
uint8_t txtData[kMaxTxtDataSize];
uint16_t txtDataLength;
uint8_t index;
Dns::TxtEntry txtEntry;
Dns::TxtEntry::Iterator iterator;
MutableData<kWithUint16Length> data;
printf("================================================================\n");
printf("TestDnsTxtEntry()\n");
@@ -1203,14 +1204,17 @@ void TestDnsTxtEntry(void)
messagePool = &instance->Get<MessagePool>();
VerifyOrQuit((message = messagePool->New(Message::kTypeIp6, 0)) != nullptr);
SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, OT_ARRAY_LENGTH(kTxtEntries), *message));
txtDataLength = message->GetLength();
data.Init(txtData, sizeof(txtData));
SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, OT_ARRAY_LENGTH(kTxtEntries), data));
VerifyOrQuit(data.GetBytes() == txtData);
txtDataLength = data.GetLength();
VerifyOrQuit(txtDataLength < kMaxTxtDataSize, "TXT data is too long");
SuccessOrQuit(message->Read(0, txtData, txtDataLength));
DumpBuffer("txt data", txtData, txtDataLength);
SuccessOrQuit(Dns::TxtEntry::AppendEntries(kTxtEntries, OT_ARRAY_LENGTH(kTxtEntries), *message));
VerifyOrQuit(txtDataLength == message->GetLength());
VerifyOrQuit(message->CompareBytes(0, txtData, txtDataLength));
index = 0;
for (const EncodedTxtData &encodedData : kEncodedTxtData)
{
@@ -1272,12 +1276,17 @@ void TestDnsTxtEntry(void)
// Verify appending empty txt data
SuccessOrQuit(message->SetLength(0));
SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, *message), "AppendEntries() failed with empty array");
txtDataLength = message->GetLength();
data.Init(txtData, sizeof(txtData));
SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, data), "AppendEntries() failed with empty array");
txtDataLength = data.GetLength();
VerifyOrQuit(txtDataLength == sizeof(uint8_t), "Data length is incorrect with empty array");
SuccessOrQuit(message->Read(0, txtData, txtDataLength));
VerifyOrQuit(txtData[0] == 0, "Data is invalid with empty array");
SuccessOrQuit(Dns::TxtEntry::AppendEntries(nullptr, 0, *message), "AppendEntries() failed with empty array");
VerifyOrQuit(message->GetLength() == txtDataLength);
VerifyOrQuit(message->CompareBytes(0, txtData, txtDataLength));
SuccessOrQuit(message->SetLength(0));
txtEntry.mKey = nullptr;
txtEntry.mValue = nullptr;