mirror of
https://github.com/espressif/openthread.git
synced 2026-10-01 21:37:39 +00:00
[dns] add MatchesKey() to Dns::TxtEntry (#12579)
This commit adds `MatchesKey()` method to `Dns::TxtEntry` class to check if the entry's key matches a given key string using a case-insensitive string comparison. The new method properly handles the case where the entry's key is `nullptr` (which can happen when the key is longer than the recommended max length). It simplifies the TXT entry parsing logic in `BorderAgent` and `Trel::PeerDiscoverer`. The unit tests for `Dns::TxtEntry` are also updated to verify the new method.
This commit is contained in:
@@ -303,28 +303,21 @@ Error TxtData::Info::ParseFrom(const uint8_t *aTxtData, uint16_t aTxtDataLength)
|
|||||||
|
|
||||||
void TxtData::Info::ProcessTxtEntry(const Dns::TxtEntry &aEntry)
|
void TxtData::Info::ProcessTxtEntry(const Dns::TxtEntry &aEntry)
|
||||||
{
|
{
|
||||||
if (aEntry.mKey == nullptr)
|
if (aEntry.MatchesKey(Key::kRecordVersion))
|
||||||
{
|
|
||||||
// If the TXT data happens to have entries with key longer
|
|
||||||
// than `kMaxIterKeyLength`, `mKey` would be `nullptr` and full
|
|
||||||
// entry would be placed in `mValue`. We skip over such
|
|
||||||
// entries.
|
|
||||||
}
|
|
||||||
else if (StringMatch(aEntry.mKey, Key::kRecordVersion))
|
|
||||||
{
|
{
|
||||||
ReadStringValue(aEntry, mRecordVersion);
|
ReadStringValue(aEntry, mRecordVersion);
|
||||||
mHasRecordVersion = true;
|
mHasRecordVersion = true;
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kAgentId))
|
else if (aEntry.MatchesKey(Key::kAgentId))
|
||||||
{
|
{
|
||||||
mHasAgentId = ReadValue(aEntry, mAgentId);
|
mHasAgentId = ReadValue(aEntry, mAgentId);
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kThreadVersion))
|
else if (aEntry.MatchesKey(Key::kThreadVersion))
|
||||||
{
|
{
|
||||||
ReadStringValue(aEntry, mThreadVersion);
|
ReadStringValue(aEntry, mThreadVersion);
|
||||||
mHasThreadVersion = true;
|
mHasThreadVersion = true;
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kStateBitmap))
|
else if (aEntry.MatchesKey(Key::kStateBitmap))
|
||||||
{
|
{
|
||||||
uint32_t bitmap;
|
uint32_t bitmap;
|
||||||
|
|
||||||
@@ -334,16 +327,16 @@ void TxtData::Info::ProcessTxtEntry(const Dns::TxtEntry &aEntry)
|
|||||||
mHasStateBitmap = true;
|
mHasStateBitmap = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kNetworkName))
|
else if (aEntry.MatchesKey(Key::kNetworkName))
|
||||||
{
|
{
|
||||||
ReadStringValue(aEntry, mNetworkName.m8);
|
ReadStringValue(aEntry, mNetworkName.m8);
|
||||||
mHasNetworkName = true;
|
mHasNetworkName = true;
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kExtendedPanId))
|
else if (aEntry.MatchesKey(Key::kExtendedPanId))
|
||||||
{
|
{
|
||||||
mHasExtendedPanId = ReadValue(aEntry, mExtendedPanId);
|
mHasExtendedPanId = ReadValue(aEntry, mExtendedPanId);
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kActiveTimestamp))
|
else if (aEntry.MatchesKey(Key::kActiveTimestamp))
|
||||||
{
|
{
|
||||||
Timestamp timestamp;
|
Timestamp timestamp;
|
||||||
|
|
||||||
@@ -353,37 +346,37 @@ void TxtData::Info::ProcessTxtEntry(const Dns::TxtEntry &aEntry)
|
|||||||
mHasActiveTimestamp = true;
|
mHasActiveTimestamp = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kPartitionId))
|
else if (aEntry.MatchesKey(Key::kPartitionId))
|
||||||
{
|
{
|
||||||
mHasPartitionId = ReadBigEndianUintValue(aEntry, mPartitionId);
|
mHasPartitionId = ReadBigEndianUintValue(aEntry, mPartitionId);
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kDomainName))
|
else if (aEntry.MatchesKey(Key::kDomainName))
|
||||||
{
|
{
|
||||||
ReadStringValue(aEntry, mDomainName.m8);
|
ReadStringValue(aEntry, mDomainName.m8);
|
||||||
mHasDomainName = true;
|
mHasDomainName = true;
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kBbrSeqNum))
|
else if (aEntry.MatchesKey(Key::kBbrSeqNum))
|
||||||
{
|
{
|
||||||
mHasBbrSeqNum = ReadBigEndianUintValue(aEntry, mBbrSeqNum);
|
mHasBbrSeqNum = ReadBigEndianUintValue(aEntry, mBbrSeqNum);
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kBbrPort))
|
else if (aEntry.MatchesKey(Key::kBbrPort))
|
||||||
{
|
{
|
||||||
mHasBbrPort = ReadBigEndianUintValue(aEntry, mBbrPort);
|
mHasBbrPort = ReadBigEndianUintValue(aEntry, mBbrPort);
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kOmrPrefix))
|
else if (aEntry.MatchesKey(Key::kOmrPrefix))
|
||||||
{
|
{
|
||||||
mHasOmrPrefix = ReadOmrPrefix(aEntry, AsCoreType(&mOmrPrefix));
|
mHasOmrPrefix = ReadOmrPrefix(aEntry, AsCoreType(&mOmrPrefix));
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kExtAddress))
|
else if (aEntry.MatchesKey(Key::kExtAddress))
|
||||||
{
|
{
|
||||||
mHasExtAddress = ReadValue(aEntry, mExtAddress);
|
mHasExtAddress = ReadValue(aEntry, mExtAddress);
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kVendorName))
|
else if (aEntry.MatchesKey(Key::kVendorName))
|
||||||
{
|
{
|
||||||
ReadStringValue(aEntry, mVendorName);
|
ReadStringValue(aEntry, mVendorName);
|
||||||
mHasVendorName = true;
|
mHasVendorName = true;
|
||||||
}
|
}
|
||||||
else if (StringMatch(aEntry.mKey, Key::kModelName))
|
else if (aEntry.MatchesKey(Key::kModelName))
|
||||||
{
|
{
|
||||||
ReadStringValue(aEntry, mModelName);
|
ReadStringValue(aEntry, mModelName);
|
||||||
mHasModelName = true;
|
mHasModelName = true;
|
||||||
|
|||||||
@@ -1380,6 +1380,11 @@ exit:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TxtEntry::MatchesKey(const char *aKey) const
|
||||||
|
{
|
||||||
|
return (mKey != nullptr) && StringMatch(mKey, aKey, kStringCaseInsensitiveMatch);
|
||||||
|
}
|
||||||
|
|
||||||
Error TxtEntry::AppendTo(Message &aMessage) const
|
Error TxtEntry::AppendTo(Message &aMessage) const
|
||||||
{
|
{
|
||||||
Appender appender(aMessage);
|
Appender appender(aMessage);
|
||||||
|
|||||||
@@ -1223,6 +1223,16 @@ public:
|
|||||||
mValueLength = aValueLength;
|
mValueLength = aValueLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the entry's key (`mKey`) matches a given key string using a case-insensitive comparison.
|
||||||
|
*
|
||||||
|
* @param[in] aKey A pointer to a key string to compare with.
|
||||||
|
*
|
||||||
|
* @retval TRUE The entry's key matches the given @p aKey.
|
||||||
|
* @retval FALSE The entry's key does not match or `mKey` is `nullptr`.
|
||||||
|
*/
|
||||||
|
bool MatchesKey(const char *aKey) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes and appends the `TxtEntry` to a message.
|
* Encodes and appends the `TxtEntry` to a message.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -750,23 +750,14 @@ Error PeerDiscoverer::TxtData::Decode(Info &aInfo)
|
|||||||
|
|
||||||
while ((error = iterator.GetNextEntry(entry)) == kErrorNone)
|
while ((error = iterator.GetNextEntry(entry)) == kErrorNone)
|
||||||
{
|
{
|
||||||
// If the TXT data happens to have entries with key longer
|
if (entry.MatchesKey(kExtAddressKey))
|
||||||
// than `kMaxIterKeyLength`, `mKey` would be `nullptr` and full
|
|
||||||
// entry would be placed in `mValue`. We skip over such
|
|
||||||
// entries.
|
|
||||||
if (entry.mKey == nullptr)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringMatch(entry.mKey, kExtAddressKey))
|
|
||||||
{
|
{
|
||||||
VerifyOrExit(!parsedExtAddress, error = kErrorParse);
|
VerifyOrExit(!parsedExtAddress, error = kErrorParse);
|
||||||
VerifyOrExit(entry.mValueLength >= sizeof(Mac::ExtAddress), error = kErrorParse);
|
VerifyOrExit(entry.mValueLength >= sizeof(Mac::ExtAddress), error = kErrorParse);
|
||||||
aInfo.mExtAddress.Set(entry.mValue);
|
aInfo.mExtAddress.Set(entry.mValue);
|
||||||
parsedExtAddress = true;
|
parsedExtAddress = true;
|
||||||
}
|
}
|
||||||
else if (StringMatch(entry.mKey, kExtPanIdKey))
|
else if (entry.MatchesKey(kExtPanIdKey))
|
||||||
{
|
{
|
||||||
VerifyOrExit(!parsedExtPanId, error = kErrorParse);
|
VerifyOrExit(!parsedExtPanId, error = kErrorParse);
|
||||||
VerifyOrExit(entry.mValueLength >= sizeof(MeshCoP::ExtendedPanId), error = kErrorParse);
|
VerifyOrExit(entry.mValueLength >= sizeof(MeshCoP::ExtendedPanId), error = kErrorParse);
|
||||||
|
|||||||
+12
-4
@@ -34,6 +34,7 @@
|
|||||||
#include "test_util.hpp"
|
#include "test_util.hpp"
|
||||||
|
|
||||||
#include "common/array.hpp"
|
#include "common/array.hpp"
|
||||||
|
#include "common/string.hpp"
|
||||||
#include "instance/instance.hpp"
|
#include "instance/instance.hpp"
|
||||||
#include "net/dns_types.hpp"
|
#include "net/dns_types.hpp"
|
||||||
|
|
||||||
@@ -1632,10 +1633,8 @@ void TestHeaderAndResourceRecords(void)
|
|||||||
|
|
||||||
void TestDnsTxtEntry(void)
|
void TestDnsTxtEntry(void)
|
||||||
{
|
{
|
||||||
enum
|
static constexpr uint16_t kMaxTxtDataSize = 255;
|
||||||
{
|
static constexpr uint16_t kMaxKeyStringSize = Dns::TxtEntry::kMaxIterKeyLength;
|
||||||
kMaxTxtDataSize = 255,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EncodedTxtData
|
struct EncodedTxtData
|
||||||
{
|
{
|
||||||
@@ -1718,6 +1717,7 @@ void TestDnsTxtEntry(void)
|
|||||||
Dns::TxtEntry txtEntry;
|
Dns::TxtEntry txtEntry;
|
||||||
Dns::TxtEntry::Iterator iterator;
|
Dns::TxtEntry::Iterator iterator;
|
||||||
MutableData<kWithUint16Length> data;
|
MutableData<kWithUint16Length> data;
|
||||||
|
char keyString[kMaxKeyStringSize];
|
||||||
|
|
||||||
printf("================================================================\n");
|
printf("================================================================\n");
|
||||||
printf("TestDnsTxtEntry()\n");
|
printf("TestDnsTxtEntry()\n");
|
||||||
@@ -1772,6 +1772,14 @@ void TestDnsTxtEntry(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
VerifyOrQuit(strcmp(txtEntry.mKey, expectedTxtEntry.mKey) == 0);
|
VerifyOrQuit(strcmp(txtEntry.mKey, expectedTxtEntry.mKey) == 0);
|
||||||
|
|
||||||
|
SuccessOrQuit(StringCopy(keyString, expectedTxtEntry.mKey));
|
||||||
|
VerifyOrQuit(txtEntry.MatchesKey(keyString));
|
||||||
|
StringConvertToLowercase(keyString);
|
||||||
|
VerifyOrQuit(txtEntry.MatchesKey(keyString));
|
||||||
|
StringConvertToUppercase(keyString);
|
||||||
|
VerifyOrQuit(txtEntry.MatchesKey(keyString));
|
||||||
|
|
||||||
VerifyOrQuit(txtEntry.mValueLength == expectedTxtEntry.mValueLength);
|
VerifyOrQuit(txtEntry.mValueLength == expectedTxtEntry.mValueLength);
|
||||||
|
|
||||||
if (txtEntry.mValueLength != 0)
|
if (txtEntry.mValueLength != 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user