Skip to content

Commit

Permalink
T txt record (#9790)
Browse files Browse the repository at this point in the history
* Consolidate TXT record stats.

It makes sense to centralize these, especially since c++14 supports
extended constexpr functions so we can calculate these from a
table. This also sets the table to centralize the generation of
the TXT records so we don't have the hardcoded values in multiple
places.

* Add T txt records to minimal and platform.

* Use define directly.

I'm not sure quite why I wrote it weird in the first place.
  • Loading branch information
cecille authored and pull[bot] committed Oct 1, 2021
1 parent d491361 commit 1438250
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 117 deletions.
7 changes: 5 additions & 2 deletions src/app/server/Mdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ CHIP_ERROR MdnsServer::AdvertiseOperational()
.SetPort(GetSecuredPort())
.SetMRPRetryIntervals(Optional<uint32_t>(CHIP_CONFIG_MRP_DEFAULT_INITIAL_RETRY_INTERVAL),
Optional<uint32_t>(CHIP_CONFIG_MRP_DEFAULT_ACTIVE_RETRY_INTERVAL))
.SetTcpSupported(Optional<bool>(INET_CONFIG_ENABLE_TCP_ENDPOINT))
.EnableIpV4(true);

auto & mdnsAdvertiser = chip::Mdns::ServiceAdvertiser::Instance();
Expand Down Expand Up @@ -335,8 +336,10 @@ CHIP_ERROR MdnsServer::Advertise(bool commissionableNode, chip::Mdns::Commission
advertiseParameters.SetRotatingId(chip::Optional<const char *>::Value(rotatingDeviceIdHexBuffer));
#endif

advertiseParameters.SetMRPRetryIntervals(Optional<uint32_t>(CHIP_CONFIG_MRP_DEFAULT_INITIAL_RETRY_INTERVAL),
Optional<uint32_t>(CHIP_CONFIG_MRP_DEFAULT_ACTIVE_RETRY_INTERVAL));
advertiseParameters
.SetMRPRetryIntervals(Optional<uint32_t>(CHIP_CONFIG_MRP_DEFAULT_INITIAL_RETRY_INTERVAL),
Optional<uint32_t>(CHIP_CONFIG_MRP_DEFAULT_ACTIVE_RETRY_INTERVAL))
.SetTcpSupported(Optional<bool>(INET_CONFIG_ENABLE_TCP_ENDPOINT));

if (mode != chip::Mdns::CommissioningMode::kEnabledEnhanced)
{
Expand Down
54 changes: 19 additions & 35 deletions src/lib/mdns/Advertiser.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <lib/core/CHIPError.h>
#include <lib/core/Optional.h>
#include <lib/core/PeerId.h>
#include <lib/mdns/TxtFields.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/SafeString.h>
#include <lib/support/Span.h>
Expand All @@ -35,22 +36,6 @@ static constexpr uint16_t kMdnsPort = 5353;
// Need 8 bytes to fit a thread mac.
static constexpr size_t kMaxMacSize = 8;

// Operational node TXT entries
static constexpr size_t kTxtRetryIntervalIdleMaxLength = 7; // [CRI] 0-3600000
static constexpr size_t kTxtRetryIntervalActiveMaxLength = 7; // [CRA] 0-3600000
static constexpr size_t kMaxRetryInterval = 3600000;

// Commissionable/commissioner node TXT entries
static constexpr size_t kKeyDiscriminatorMaxLength = 5;
static constexpr size_t kKeyVendorProductMaxLength = 11;
static constexpr size_t kKeyAdditionalCommissioningMaxLength = 1;
static constexpr size_t kKeyCommissioningModeMaxLength = 1;
static constexpr size_t kKeyDeviceTypeMaxLength = 5;
static constexpr size_t kKeyDeviceNameMaxLength = 32;
static constexpr size_t kKeyRotatingIdMaxLength = 100;
static constexpr size_t kKeyPairingInstructionMaxLength = 128;
static constexpr size_t kKeyPairingHintMaxLength = 10;

// Commissionable/commissioner node subtypes
static constexpr size_t kSubTypeShortDiscriminatorMaxLength = 4; // _S<dd>
static constexpr size_t kSubTypeLongDiscriminatorMaxLength = 6; // _L<dddd>
Expand Down Expand Up @@ -82,11 +67,11 @@ template <class Derived>
class BaseAdvertisingParams
{
public:
static constexpr uint8_t kCommonTxtMaxNumber = 2;
static constexpr size_t kCommonTxtMaxKeySize = MaxStringLength("CRI", "CRA"); // possible keys
static constexpr size_t kCommonTxtMaxValueSize = std::max({ kTxtRetryIntervalIdleMaxLength, kTxtRetryIntervalActiveMaxLength });
static constexpr size_t kCommonTxtTotalKeySize = TotalStringLength("CRI", "CRA"); // possible keys
static constexpr size_t kCommonTxtTotalValueSize = kTxtRetryIntervalIdleMaxLength + kTxtRetryIntervalActiveMaxLength;
static constexpr uint8_t kCommonTxtMaxNumber = KeyCount(TxtKeyUse::kCommon);
static constexpr size_t kCommonTxtMaxKeySize = MaxKeyLen(TxtKeyUse::kCommon);
static constexpr size_t kCommonTxtMaxValueSize = MaxValueLen(TxtKeyUse::kCommon);
static constexpr size_t kCommonTxtTotalKeySize = TotalKeyLen(TxtKeyUse::kCommon);
static constexpr size_t kCommonTxtTotalValueSize = TotalValueLen(TxtKeyUse::kCommon);

Derived & SetPort(uint16_t port)
{
Expand Down Expand Up @@ -121,6 +106,12 @@ class BaseAdvertisingParams
intervalIdle = mMrpRetryIntervalIdle;
intervalActive = mMrpRetryIntervalActive;
}
Derived & SetTcpSupported(Optional<bool> tcpSupported)
{
mTcpSupported = tcpSupported;
return *reinterpret_cast<Derived *>(this);
}
Optional<bool> GetTcpSupported() const { return mTcpSupported; }

private:
uint16_t mPort = CHIP_PORT;
Expand All @@ -129,7 +120,8 @@ class BaseAdvertisingParams
size_t mMacLength = 0;
Optional<uint32_t> mMrpRetryIntervalIdle;
Optional<uint32_t> mMrpRetryIntervalActive;
}; // namespace Mdns
Optional<bool> mTcpSupported;
};

/// Defines parameters required for advertising a CHIP node
/// over mDNS as an 'operationally ready' node.
Expand Down Expand Up @@ -157,19 +149,11 @@ class OperationalAdvertisingParameters : public BaseAdvertisingParams<Operationa
class CommissionAdvertisingParameters : public BaseAdvertisingParams<CommissionAdvertisingParameters>
{
public:
static constexpr uint8_t kTxtMaxNumber = kCommonTxtMaxNumber + 9;
static constexpr uint8_t kTxtMaxKeySize =
std::max(kCommonTxtMaxKeySize, MaxStringLength("D", "VP", "CM", "AP", "DT", "DN", "RI", "PI", "PH")); // possible keys
static constexpr uint8_t kTxtMaxValueSize =
std::max({ kKeyDiscriminatorMaxLength, kKeyVendorProductMaxLength, kKeyAdditionalCommissioningMaxLength,
kKeyCommissioningModeMaxLength, kKeyDeviceTypeMaxLength, kKeyDeviceNameMaxLength, kKeyRotatingIdMaxLength,
kKeyPairingInstructionMaxLength, kKeyPairingHintMaxLength, kCommonTxtMaxValueSize });
static constexpr size_t kTxtTotalKeySize =
kCommonTxtTotalKeySize + TotalStringLength("D", "VP", "CM", "AP", "DT", "DN", "RI", "PI", "PH"); // possible keys
static constexpr size_t kTxtTotalValueSize = kCommonTxtTotalValueSize + kKeyDiscriminatorMaxLength +
kKeyVendorProductMaxLength + kKeyAdditionalCommissioningMaxLength + kKeyCommissioningModeMaxLength +
kKeyDeviceTypeMaxLength + kKeyDeviceNameMaxLength + kKeyRotatingIdMaxLength + kKeyPairingInstructionMaxLength +
kKeyPairingHintMaxLength;
static constexpr uint8_t kTxtMaxNumber = kCommonTxtMaxNumber + KeyCount(TxtKeyUse::kCommission);
static constexpr uint8_t kTxtMaxKeySize = std::max(kCommonTxtMaxKeySize, MaxKeyLen(TxtKeyUse::kCommission));
static constexpr uint8_t kTxtMaxValueSize = std::max(kCommonTxtMaxValueSize, MaxValueLen(TxtKeyUse::kCommission));
static constexpr size_t kTxtTotalKeySize = kCommonTxtTotalKeySize + TotalKeyLen(TxtKeyUse::kCommission);
static constexpr size_t kTxtTotalValueSize = kCommonTxtTotalValueSize + TotalValueLen(TxtKeyUse::kCommission);

CommissionAdvertisingParameters & SetShortDiscriminator(uint8_t discriminator)
{
Expand Down
16 changes: 13 additions & 3 deletions src/lib/mdns/Advertiser_ImplMinimalMdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,11 @@ class AdvertiserMinMdns : public ServiceAdvertiser,

struct CommonTxtEntryStorage
{
// CRA and CRI are both 3 chars + '=' = 4 + 1 for nullchar
char mrpRetryIntervalIdleBuf[kTxtRetryIntervalIdleMaxLength + 4 + 1];
char mrpRetryIntervalActiveBuf[kTxtRetryIntervalActiveMaxLength + 4 + 1];
// +2 for all to account for '=' and terminating nullchar
char mrpRetryIntervalIdleBuf[KeySize(TxtFieldKey::kMrpRetryIntervalIdle) + ValSize(TxtFieldKey::kMrpRetryIntervalIdle) + 2];
char mrpRetryIntervalActiveBuf[KeySize(TxtFieldKey::kMrpRetryIntervalActive) +
ValSize(TxtFieldKey::kMrpRetryIntervalActive) + 2];
char tcpSupportedBuf[KeySize(TxtFieldKey::kTcpSupport) + ValSize(TxtFieldKey::kTcpSupport) + 2];
};
template <class Derived>
CHIP_ERROR AddCommonTxtEntries(const BaseAdvertisingParams<Derived> & params, CommonTxtEntryStorage & storage,
Expand Down Expand Up @@ -203,6 +205,14 @@ class AdvertiserMinMdns : public ServiceAdvertiser,
CHIP_ERROR_INVALID_STRING_LENGTH);
txtFields[numTxtFields++] = storage.mrpRetryIntervalActiveBuf;
}
if (params.GetTcpSupported().HasValue())
{
size_t writtenCharactersNumber =
snprintf(storage.tcpSupportedBuf, sizeof(storage.tcpSupportedBuf), "T=%d", params.GetTcpSupported().Value());
VerifyOrReturnError((writtenCharactersNumber > 0) && (writtenCharactersNumber < sizeof(storage.tcpSupportedBuf)),
CHIP_ERROR_INVALID_STRING_LENGTH);
txtFields[numTxtFields++] = storage.tcpSupportedBuf;
}
return CHIP_NO_ERROR;
}

Expand Down
24 changes: 18 additions & 6 deletions src/lib/mdns/Discovery_ImplPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,10 @@ CHIP_ERROR DiscoveryImplPlatform::GetCommissionableInstanceName(char * instanceN
return CHIP_NO_ERROR;
}

template <class Derived, size_t N_idle, size_t N_active>
template <class Derived, size_t N_idle, size_t N_active, size_t N_tcp>
CHIP_ERROR AddCommonTxtElements(const BaseAdvertisingParams<Derived> & params, char (&mrpRetryIdleStorage)[N_idle],
char (&mrpRetryActiveStorage)[N_active], TextEntry txtEntryStorage[], size_t & txtEntryIdx)
char (&mrpRetryActiveStorage)[N_active], char (&tcpSupportedStorage)[N_tcp],
TextEntry txtEntryStorage[], size_t & txtEntryIdx)
{
Optional<uint32_t> mrpRetryIntervalIdle, mrpRetryIntervalActive;
params.GetMRPRetryIntervals(mrpRetryIntervalIdle, mrpRetryIntervalActive);
Expand Down Expand Up @@ -178,6 +179,15 @@ CHIP_ERROR AddCommonTxtElements(const BaseAdvertisingParams<Derived> & params, c
CHIP_ERROR_INVALID_STRING_LENGTH);
txtEntryStorage[txtEntryIdx++] = { "CRA", Uint8::from_const_char(mrpRetryActiveStorage), strlen(mrpRetryActiveStorage) };
}
if (params.GetTcpSupported().HasValue())
{
size_t writtenCharactersNumber =
snprintf(tcpSupportedStorage, sizeof(tcpSupportedStorage), "%d", params.GetTcpSupported().Value());
VerifyOrReturnError((writtenCharactersNumber > 0) && (writtenCharactersNumber <= kKeyTcpSupportMaxLength),
CHIP_ERROR_INVALID_STRING_LENGTH);
txtEntryStorage[txtEntryIdx++] = { "T", reinterpret_cast<const uint8_t *>(tcpSupportedStorage),
strlen(tcpSupportedStorage) };
}
return CHIP_NO_ERROR;
}

Expand All @@ -196,6 +206,7 @@ CHIP_ERROR DiscoveryImplPlatform::Advertise(const CommissionAdvertisingParameter
char pairingInstrBuf[kKeyPairingInstructionMaxLength + 1];
char mrpRetryIntervalIdleBuf[kTxtRetryIntervalIdleMaxLength + 1];
char mrpRetryIntervalActiveBuf[kTxtRetryIntervalActiveMaxLength + 1];
char tcpSupportedBuf[kKeyTcpSupportMaxLength + 1];
// size of textEntries array should be count of Bufs above
TextEntry textEntries[CommissionAdvertisingParameters::kTxtMaxNumber];
size_t textEntrySize = 0;
Expand Down Expand Up @@ -261,8 +272,8 @@ CHIP_ERROR DiscoveryImplPlatform::Advertise(const CommissionAdvertisingParameter
textEntries[textEntrySize++] = { "DN", reinterpret_cast<const uint8_t *>(deviceNameBuf),
strnlen(deviceNameBuf, sizeof(deviceNameBuf)) };
}
AddCommonTxtElements<CommissionAdvertisingParameters>(params, mrpRetryIntervalIdleBuf, mrpRetryIntervalActiveBuf, textEntries,
textEntrySize);
AddCommonTxtElements<CommissionAdvertisingParameters>(params, mrpRetryIntervalIdleBuf, mrpRetryIntervalActiveBuf,
tcpSupportedBuf, textEntries, textEntrySize);

// Following fields are for nodes and not for commissioners
if (params.GetCommissionAdvertiseMode() == CommssionAdvertiseMode::kCommissionableNode)
Expand Down Expand Up @@ -391,11 +402,12 @@ CHIP_ERROR DiscoveryImplPlatform::Advertise(const OperationalAdvertisingParamete

char mrpRetryIntervalIdleBuf[kTxtRetryIntervalIdleMaxLength + 1];
char mrpRetryIntervalActiveBuf[kTxtRetryIntervalActiveMaxLength + 1];
char tcpSupportedBuf[kKeyTcpSupportMaxLength + 1];
TextEntry txtEntries[OperationalAdvertisingParameters::kTxtMaxNumber];
size_t textEntrySize = 0;

ReturnLogErrorOnFailure(
AddCommonTxtElements(params, mrpRetryIntervalIdleBuf, mrpRetryIntervalActiveBuf, txtEntries, textEntrySize));
ReturnLogErrorOnFailure(AddCommonTxtElements(params, mrpRetryIntervalIdleBuf, mrpRetryIntervalActiveBuf, tcpSupportedBuf,
txtEntries, textEntrySize));

if (MakeServiceSubtype(compressedFabricIdSub, sizeof(compressedFabricIdSub),
DiscoveryFilter(DiscoveryFilterType::kCompressedFabricId, params.GetPeerId().GetCompressedFabricId())) ==
Expand Down
82 changes: 21 additions & 61 deletions src/lib/mdns/TxtFields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,95 +183,55 @@ uint32_t GetRetryInterval(const ByteSpan & value)

TxtFieldKey GetTxtFieldKey(const ByteSpan & key)
{
if (IsKey(key, "D"))
for (auto & info : txtFieldInfo)
{
return TxtFieldKey::kLongDiscriminator;
}
else if (IsKey(key, "VP"))
{
return TxtFieldKey::kVendorProduct;
}
else if (IsKey(key, "CM"))
{
return TxtFieldKey::kCommissioningMode;
}
else if (IsKey(key, "DT"))
{
return TxtFieldKey::kDeviceType;
}
else if (IsKey(key, "DN"))
{
return TxtFieldKey::kDeviceName;
}
else if (IsKey(key, "RI"))
{
return TxtFieldKey::kRotatingDeviceId;
}
else if (IsKey(key, "PI"))
{
return TxtFieldKey::kPairingInstruction;
}
else if (IsKey(key, "PH"))
{
return TxtFieldKey::kPairingHint;
}
else if (IsKey(key, "CRI"))
{
return TxtFieldKey::kMrpRetryIntervalIdle;
}
else if (IsKey(key, "CRA"))
{
return TxtFieldKey::kMrpRetryIntervalActive;
}
else if (IsKey(key, "T"))
{
return TxtFieldKey::kTcpSupport;
}
else
{
return TxtFieldKey::kUnknown;
if (IsKey(key, info.keyStr))
{
return info.key;
}
}
return TxtFieldKey::kUnknown;
}

} // namespace Internal

void FillNodeDataFromTxt(const ByteSpan & key, const ByteSpan & val, DiscoveredNodeData & nodeData)
{
Internal::TxtFieldKey keyType = Internal::GetTxtFieldKey(key);
TxtFieldKey keyType = Internal::GetTxtFieldKey(key);
switch (keyType)
{
case Internal::TxtFieldKey::kLongDiscriminator:
case TxtFieldKey::kLongDiscriminator:
nodeData.longDiscriminator = Internal::GetLongDiscriminator(val);
break;
case Internal::TxtFieldKey::kVendorProduct:
case TxtFieldKey::kVendorProduct:
nodeData.vendorId = Internal::GetVendor(val);
nodeData.productId = Internal::GetProduct(val);
break;
case Internal::TxtFieldKey::kCommissioningMode:
case TxtFieldKey::kCommissioningMode:
nodeData.commissioningMode = Internal::GetCommissioningMode(val);
break;
case Internal::TxtFieldKey::kDeviceType:
case TxtFieldKey::kDeviceType:
nodeData.deviceType = Internal::GetDeviceType(val);
break;
case Internal::TxtFieldKey::kDeviceName:
case TxtFieldKey::kDeviceName:
Internal::GetDeviceName(val, nodeData.deviceName);
break;
case Internal::TxtFieldKey::kRotatingDeviceId:
case TxtFieldKey::kRotatingDeviceId:
Internal::GetRotatingDeviceId(val, nodeData.rotatingId, &nodeData.rotatingIdLen);
break;
case Internal::TxtFieldKey::kPairingInstruction:
case TxtFieldKey::kPairingInstruction:
Internal::GetPairingInstruction(val, nodeData.pairingInstruction);
break;
case Internal::TxtFieldKey::kPairingHint:
case TxtFieldKey::kPairingHint:
nodeData.pairingHint = Internal::GetPairingHint(val);
break;
case Internal::TxtFieldKey::kMrpRetryIntervalIdle:
case TxtFieldKey::kMrpRetryIntervalIdle:
nodeData.mrpRetryIntervalIdle = Internal::GetRetryInterval(val);
break;
case Internal::TxtFieldKey::kMrpRetryIntervalActive:
case TxtFieldKey::kMrpRetryIntervalActive:
nodeData.mrpRetryIntervalActive = Internal::GetRetryInterval(val);
break;
case Internal::TxtFieldKey::kTcpSupport:
case TxtFieldKey::kTcpSupport:
nodeData.supportsTcp = Internal::MakeBoolFromAsciiDecimal(val);
break;
default:
Expand All @@ -283,13 +243,13 @@ void FillNodeDataFromTxt(const ByteSpan & key, const ByteSpan & value, ResolvedN
{
switch (Internal::GetTxtFieldKey(key))
{
case Internal::TxtFieldKey::kMrpRetryIntervalIdle:
case TxtFieldKey::kMrpRetryIntervalIdle:
nodeData.mMrpRetryIntervalIdle = Internal::GetRetryInterval(value);
break;
case Internal::TxtFieldKey::kMrpRetryIntervalActive:
case TxtFieldKey::kMrpRetryIntervalActive:
nodeData.mMrpRetryIntervalActive = Internal::GetRetryInterval(value);
break;
case Internal::TxtFieldKey::kTcpSupport:
case TxtFieldKey::kTcpSupport:
nodeData.mSupportsTcp = Internal::MakeBoolFromAsciiDecimal(value);
break;
default:
Expand Down
Loading

0 comments on commit 1438250

Please sign in to comment.