Skip to content

Commit

Permalink
[mdns] update 'TxtEntry' to handle boolean attribute
Browse files Browse the repository at this point in the history
This commit updates `TxtEntry` along with `EncodeTxtData()` and
`DecodeTxtData()` to support boolean attributes which are encode as
`key` without `=`.

It also updates `AdvertisingProxy::MakeTxtList()` to use the
`DecodeTxtData()`.
  • Loading branch information
abtink committed Sep 2, 2023
1 parent 869d62c commit c505101
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 38 deletions.
7 changes: 4 additions & 3 deletions src/border_agent/border_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,10 +343,11 @@ void AppendVendorTxtEntries(const std::map<std::string, std::vector<uint8_t>> &a

for (auto &addedEntry : aTxtList)
{
if (addedEntry.mName == key)
if (addedEntry.mKey == key)
{
addedEntry.mValue = value;
found = true;
addedEntry.mValue = value;
addedEntry.mIsBooleanAttribute = false;
found = true;
break;
}
}
Expand Down
41 changes: 26 additions & 15 deletions src/mdns/mdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,25 @@ otbrError Publisher::EncodeTxtData(const TxtList &aTxtList, std::vector<uint8_t>
{
otbrError error = OTBR_ERROR_NONE;

for (const auto &txtEntry : aTxtList)
for (const TxtEntry &txtEntry : aTxtList)
{
const auto &name = txtEntry.mName;
const auto &value = txtEntry.mValue;
const size_t entryLength = name.length() + 1 + value.size();
size_t entryLength = txtEntry.mKey.length();

if (!txtEntry.mIsBooleanAttribute)
{
entryLength += txtEntry.mValue.size() + sizeof(uint8_t); // for `=` char.
}

VerifyOrExit(entryLength <= kMaxTextEntrySize, error = OTBR_ERROR_INVALID_ARGS);

aTxtData.push_back(static_cast<uint8_t>(entryLength));
aTxtData.insert(aTxtData.end(), name.begin(), name.end());
aTxtData.push_back('=');
aTxtData.insert(aTxtData.end(), value.begin(), value.end());
aTxtData.insert(aTxtData.end(), txtEntry.mKey.begin(), txtEntry.mKey.end());

if (!txtEntry.mIsBooleanAttribute)
{
aTxtData.push_back('=');
aTxtData.insert(aTxtData.end(), txtEntry.mValue.begin(), txtEntry.mValue.end());
}
}

exit:
Expand All @@ -127,24 +134,28 @@ otbrError Publisher::DecodeTxtData(Publisher::TxtList &aTxtList, const uint8_t *
uint16_t keyStart = r + 1;
uint16_t entryEnd = keyStart + entrySize;
uint16_t keyEnd = keyStart;
uint16_t valStart;

VerifyOrExit(entryEnd <= aTxtLength, error = OTBR_ERROR_PARSE);

while (keyEnd < entryEnd && aTxtData[keyEnd] != '=')
{
keyEnd++;
}

valStart = keyEnd;
if (valStart < entryEnd && aTxtData[valStart] == '=')
if (keyEnd == entryEnd)
{
valStart++;
// No `=`, treat as a boolean attribute.
aTxtList.emplace_back(reinterpret_cast<const char *>(&aTxtData[keyStart]), keyEnd - keyStart);
}
else
{
uint16_t valStart = keyEnd + 1; // To skip over `=`

aTxtList.emplace_back(reinterpret_cast<const char *>(&aTxtData[keyStart]), keyEnd - keyStart,
&aTxtData[valStart], entryEnd - valStart);
aTxtList.emplace_back(reinterpret_cast<const char *>(&aTxtData[keyStart]), keyEnd - keyStart,
&aTxtData[valStart], entryEnd - valStart);
}

r += entrySize + 1;
VerifyOrExit(r <= aTxtLength, error = OTBR_ERROR_PARSE);
}

exit:
Expand Down Expand Up @@ -260,7 +271,7 @@ Publisher::SubTypeList Publisher::SortSubTypeList(SubTypeList aSubTypeList)
Publisher::TxtList Publisher::SortTxtList(TxtList aTxtList)
{
std::sort(aTxtList.begin(), aTxtList.end(),
[](const TxtEntry &aLhs, const TxtEntry &aRhs) { return aLhs.mName < aRhs.mName; });
[](const TxtEntry &aLhs, const TxtEntry &aRhs) { return aLhs.mKey < aRhs.mKey; });
return aTxtList;
}

Expand Down
37 changes: 27 additions & 10 deletions src/mdns/mdns.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,31 +70,48 @@ class Publisher : private NonCopyable
{
public:
/**
* This structure represents a name/value pair of the TXT record.
* This structure represents a key/value pair of the TXT record.
*
*/
struct TxtEntry
{
std::string mName; ///< The name of the TXT entry.
std::vector<uint8_t> mValue; ///< The value of the TXT entry.
std::string mKey; ///< The key of the TXT entry.
std::vector<uint8_t> mValue; ///< The value of the TXT entry. Can be empty.
bool mIsBooleanAttribute; ///< This entry is boolean attribute (encoded as `key` without `=`).

TxtEntry(const char *aName, const char *aValue)
: TxtEntry(aName, reinterpret_cast<const uint8_t *>(aValue), strlen(aValue))
TxtEntry(const char *aKey, const char *aValue)
: TxtEntry(aKey, reinterpret_cast<const uint8_t *>(aValue), strlen(aValue))
{
}

TxtEntry(const char *aName, const uint8_t *aValue, size_t aValueLength)
: TxtEntry(aName, strlen(aName), aValue, aValueLength)
TxtEntry(const char *aKey, const uint8_t *aValue, size_t aValueLength)
: TxtEntry(aKey, strlen(aKey), aValue, aValueLength)
{
}

TxtEntry(const char *aName, size_t aNameLength, const uint8_t *aValue, size_t aValueLength)
: mName(aName, aNameLength)
TxtEntry(const char *aKey, size_t aKeyLength, const uint8_t *aValue, size_t aValueLength)
: mKey(aKey, aKeyLength)
, mValue(aValue, aValue + aValueLength)
, mIsBooleanAttribute(false)
{
}

bool operator==(const TxtEntry &aOther) const { return mName == aOther.mName && mValue == aOther.mValue; }
TxtEntry(const char *aKey)
: TxtEntry(aKey, strlen(aKey))
{
}

TxtEntry(const char *aKey, size_t aKeyLength)
: mKey(aKey, aKeyLength)
, mIsBooleanAttribute(true)
{
}

bool operator==(const TxtEntry &aOther) const
{
return (mKey == aOther.mKey) && (mValue == aOther.mValue) &&
(mIsBooleanAttribute == aOther.mIsBooleanAttribute);
}
};

typedef std::vector<TxtEntry> TxtList;
Expand Down
10 changes: 1 addition & 9 deletions src/sdp_proxy/advertising_proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,18 +342,10 @@ Mdns::Publisher::TxtList AdvertisingProxy::MakeTxtList(const otSrpServerService
{
const uint8_t *txtData;
uint16_t txtDataLength = 0;
otDnsTxtEntryIterator iterator;
otDnsTxtEntry txtEntry;
Mdns::Publisher::TxtList txtList;

txtData = otSrpServerServiceGetTxtData(aSrpService, &txtDataLength);

otDnsInitTxtEntryIterator(&iterator, txtData, txtDataLength);

while (otDnsGetNextTxtEntry(&iterator, &txtEntry) == OT_ERROR_NONE)
{
txtList.emplace_back(txtEntry.mKey, txtEntry.mValue, txtEntry.mValueLength);
}
Mdns::Publisher::DecodeTxtData(txtList, txtData, txtDataLength);

return txtList;
}
Expand Down
7 changes: 6 additions & 1 deletion src/trel_dnssd/trel_dnssd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,12 @@ void TrelDnssd::Peer::ReadExtAddrFromTxtData(void)

for (const auto &txtEntry : txtEntries)
{
if (StringUtils::EqualCaseInsensitive(txtEntry.mName, kTxtRecordExtAddressKey))
if (txtEntry.mIsBooleanAttribute)
{
continue;
}

if (StringUtils::EqualCaseInsensitive(txtEntry.mKey, kTxtRecordExtAddressKey))
{
VerifyOrExit(txtEntry.mValue.size() == sizeof(mExtAddr));

Expand Down

0 comments on commit c505101

Please sign in to comment.