From 56ca28882aa2c51cb9fcc579ef87347c6387b25a Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 16 Nov 2021 10:24:23 -0800 Subject: [PATCH] [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. --- src/core/net/dns_types.cpp | 49 ++++++++++++++++++++++++++++---------- src/core/net/dns_types.hpp | 18 ++++++++++++++ tests/unit/test_dns.cpp | 41 ++++++++++++++++++------------- 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/core/net/dns_types.cpp b/src/core/net/dns_types.cpp index 6ae316710..46e316b2f 100644 --- a/src/core/net/dns_types.cpp +++ b/src/core/net/dns_types.cpp @@ -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(static_cast(keyLength))); - error = aMessage.AppendBytes(mKey, keyLength); + SuccessOrExit(error = aAppender.Append(static_cast(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(static_cast(keyLength + mValueLength + sizeof(char)))); - SuccessOrExit(error = aMessage.AppendBytes(mKey, keyLength)); - SuccessOrExit(error = aMessage.Append(separator)); - error = aMessage.AppendBytes(mValue, mValueLength); + SuccessOrExit(error = aAppender.Append(static_cast(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 &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(0); + error = aAppender.Append(0); } exit: diff --git a/src/core/net/dns_types.hpp b/src/core/net/dns_types.hpp index 1bdf0d800..907055811 100644 --- a/src/core/net/dns_types.hpp +++ b/src/core/net/dns_types.hpp @@ -39,6 +39,7 @@ #include #include +#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 &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'; diff --git a/tests/unit/test_dns.cpp b/tests/unit/test_dns.cpp index 36da5fa19..61b4f3927 100644 --- a/tests/unit/test_dns.cpp +++ b/tests/unit/test_dns.cpp @@ -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 data; printf("================================================================\n"); printf("TestDnsTxtEntry()\n"); @@ -1203,14 +1204,17 @@ void TestDnsTxtEntry(void) messagePool = &instance->Get(); 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;