mirror of
https://github.com/espressif/openthread.git
synced 2026-09-14 21:20:11 +00:00
[border-agent] new API to set vendor-specific extra TXT data (#11487)
This commit introduces a new API to allow setting vendor-specific extra TXT data to be included when the Border Agent advertises its mDNS `_meshcop._udp` service. The provided vendor TXT data is appended as given to the TXT data generated by the Border Agent and included in the `_meshcop._udp` mDNS service advertisement. This vendor TXT data can be set at any time, regardless of the Border Agent's state. Any change from a previously set value will trigger an update of the registered mDNS service to advertise the new TXT data. This commit also updates `test_border_agent` by generalizing and simplifying the validation of the Border Agent's `_meshcop._udp` service TXT data. The tests are also expanded to validate the complete registered service TXT data, including the newly added support for vendor-specific extra TXT data.
This commit is contained in:
+294
-146
@@ -756,36 +756,107 @@ void TestBorderAgentEphemeralKey(void)
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
class TxtDataTester
|
||||
struct TxtData
|
||||
{
|
||||
public:
|
||||
TxtDataTester(BorderAgent &aBorderAgent)
|
||||
: mBorderAgent(aBorderAgent)
|
||||
, mIsRunning(false)
|
||||
, mUdpPort(0)
|
||||
, mCallbackInvoked(false)
|
||||
void Init(const uint8_t *aData, uint16_t aLength) { mData = aData, mLength = aLength; }
|
||||
|
||||
void ValidateFormat(void)
|
||||
{
|
||||
TxtEntry::Iterator iter;
|
||||
TxtEntry txtEntry;
|
||||
|
||||
iter.Init(mData, mLength);
|
||||
|
||||
while (true)
|
||||
{
|
||||
Error error = iter.GetNextEntry(txtEntry);
|
||||
|
||||
if (error == kErrorNotFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
SuccessOrQuit(error);
|
||||
VerifyOrQuit(txtEntry.mKey != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleServiceChanged(void *aContext) { static_cast<TxtDataTester *>(aContext)->HandleServiceChanged(); }
|
||||
|
||||
void HandleServiceChanged(void)
|
||||
void LogAllTxtEntries(void)
|
||||
{
|
||||
mIsRunning = mBorderAgent.IsRunning();
|
||||
mUdpPort = mBorderAgent.GetUdpPort();
|
||||
SuccessOrQuit(mBorderAgent.PrepareServiceTxtData(mTxtData));
|
||||
mCallbackInvoked = true;
|
||||
static constexpr uint16_t kValueStringSize = 256;
|
||||
|
||||
char valueString[kValueStringSize];
|
||||
TxtEntry::Iterator iter;
|
||||
TxtEntry txtEntry;
|
||||
|
||||
Log("TXT data - length %u", mLength);
|
||||
|
||||
iter.Init(mData, mLength);
|
||||
|
||||
while (true)
|
||||
{
|
||||
Error error = iter.GetNextEntry(txtEntry);
|
||||
StringWriter writer(valueString, sizeof(valueString));
|
||||
|
||||
if (error == kErrorNotFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
SuccessOrQuit(error);
|
||||
VerifyOrQuit(txtEntry.mKey != nullptr);
|
||||
|
||||
writer.AppendHexBytes(txtEntry.mValue, txtEntry.mValueLength);
|
||||
Log(" %s -> [%s] (len:%u)", txtEntry.mKey, valueString, txtEntry.mValueLength);
|
||||
}
|
||||
}
|
||||
|
||||
bool FindTxtEntry(const char *aKey, TxtEntry &aTxtEntry)
|
||||
bool ContainsKey(const char *aKey) const
|
||||
{
|
||||
TxtEntry txtEntry;
|
||||
|
||||
return FindTxtEntry(aKey, txtEntry);
|
||||
}
|
||||
|
||||
void ValidateKey(const char *aKey, const void *aValue, uint16_t aValueLength) const
|
||||
{
|
||||
TxtEntry txtEntry;
|
||||
|
||||
VerifyOrQuit(FindTxtEntry(aKey, txtEntry));
|
||||
VerifyOrQuit(txtEntry.mValueLength == aValueLength);
|
||||
VerifyOrQuit(memcmp(txtEntry.mValue, aValue, aValueLength) == 0);
|
||||
}
|
||||
|
||||
template <typename ObjectType> void ValidateKey(const char *aKey, const ObjectType &aObject) const
|
||||
{
|
||||
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
|
||||
|
||||
ValidateKey(aKey, &aObject, sizeof(aObject));
|
||||
}
|
||||
|
||||
void ValidateKey(const char *aKey, const char *aString) const { ValidateKey(aKey, aString, strlen(aString)); }
|
||||
|
||||
uint32_t ReadUint32Key(const char *aKey) const
|
||||
{
|
||||
TxtEntry txtEntry;
|
||||
|
||||
VerifyOrQuit(FindTxtEntry(aKey, txtEntry));
|
||||
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
|
||||
return BigEndian::ReadUint32(txtEntry.mValue);
|
||||
}
|
||||
|
||||
bool FindTxtEntry(const char *aKey, TxtEntry &aTxtEntry) const
|
||||
{
|
||||
bool found = false;
|
||||
TxtEntry::Iterator iter;
|
||||
|
||||
iter.Init(mTxtData.mData, mTxtData.mLength);
|
||||
iter.Init(mData, mLength);
|
||||
|
||||
while (iter.GetNextEntry(aTxtEntry) == kErrorNone)
|
||||
{
|
||||
if (strcmp(aTxtEntry.mKey, aKey) == 0)
|
||||
VerifyOrQuit(aTxtEntry.mKey != nullptr);
|
||||
|
||||
if (StringMatch(aTxtEntry.mKey, aKey))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
@@ -795,27 +866,11 @@ public:
|
||||
return found;
|
||||
}
|
||||
|
||||
BorderAgent &mBorderAgent;
|
||||
BorderAgent::ServiceTxtData mTxtData;
|
||||
bool mIsRunning;
|
||||
uint16_t mUdpPort;
|
||||
bool mCallbackInvoked;
|
||||
const uint8_t *mData;
|
||||
uint16_t mLength;
|
||||
};
|
||||
|
||||
template <typename ObjectType> bool CheckObjectSameAsTxtEntryData(const TxtEntry &aTxtEntry, const ObjectType &aObject)
|
||||
{
|
||||
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
|
||||
|
||||
return aTxtEntry.mValueLength == sizeof(ObjectType) && memcmp(aTxtEntry.mValue, &aObject, sizeof(ObjectType)) == 0;
|
||||
}
|
||||
|
||||
template <> bool CheckObjectSameAsTxtEntryData<NameData>(const TxtEntry &aTxtEntry, const NameData &aNameData)
|
||||
{
|
||||
return aTxtEntry.mValueLength == aNameData.GetLength() &&
|
||||
memcmp(aTxtEntry.mValue, aNameData.GetBuffer(), aNameData.GetLength()) == 0;
|
||||
}
|
||||
|
||||
void TestBorderAgentTxtDataCallback(void)
|
||||
void ValidateMeshCoPTxtData(TxtData &aTxtData, Node &aNode)
|
||||
{
|
||||
// State bitmap masks and field values
|
||||
static constexpr uint32_t kMaskConnectionMode = 7 << 0;
|
||||
@@ -832,15 +887,100 @@ void TestBorderAgentTxtDataCallback(void)
|
||||
static constexpr uint32_t kThreadRoleLeader = 3 << 9;
|
||||
static constexpr uint32_t kFlagEpskcSupported = 1 << 11;
|
||||
|
||||
Core nexus;
|
||||
Node &node0 = nexus.CreateNode();
|
||||
TxtDataTester txtDataTester(node0.Get<BorderAgent>());
|
||||
TxtEntry txtEntry;
|
||||
uint32_t stateBitmap;
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
|
||||
BorderAgent::Id id;
|
||||
uint32_t stateBitmap;
|
||||
uint32_t threadIfStatus;
|
||||
uint32_t threadRole;
|
||||
|
||||
aTxtData.ValidateFormat();
|
||||
aTxtData.LogAllTxtEntries();
|
||||
|
||||
SuccessOrQuit(aNode.Get<BorderAgent>().GetId(id));
|
||||
aTxtData.ValidateKey("id", id);
|
||||
aTxtData.ValidateKey("nn", aNode.Get<NetworkNameManager>().GetNetworkName().GetAsCString());
|
||||
aTxtData.ValidateKey("xp", aNode.Get<ExtendedPanIdManager>().GetExtPanId());
|
||||
aTxtData.ValidateKey("tv", kThreadVersionString);
|
||||
aTxtData.ValidateKey("xa", aNode.Get<Mac::Mac>().GetExtAddress());
|
||||
|
||||
if (aNode.Get<Mle::Mle>().IsAttached())
|
||||
{
|
||||
aTxtData.ValidateKey("pt", BigEndian::HostSwap32(aNode.Get<Mle::Mle>().GetLeaderData().GetPartitionId()));
|
||||
aTxtData.ValidateKey("at", aNode.Get<ActiveDatasetManager>().GetTimestamp());
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(!aTxtData.ContainsKey("pt"));
|
||||
VerifyOrQuit(!aTxtData.ContainsKey("at"));
|
||||
}
|
||||
|
||||
stateBitmap = aTxtData.ReadUint32Key("sb");
|
||||
|
||||
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == aNode.Get<BorderAgent>().IsRunning() ? kConnectionModePskc
|
||||
: kConnectionModeDisabled);
|
||||
switch (aNode.Get<Mle::Mle>().GetRole())
|
||||
{
|
||||
case Mle::DeviceRole::kRoleDisabled:
|
||||
threadIfStatus = kThreadIfStatusNotInitialized;
|
||||
threadRole = kThreadRoleDisabledOrDetached;
|
||||
break;
|
||||
case Mle::DeviceRole::kRoleDetached:
|
||||
threadIfStatus = kThreadIfStatusInitialized;
|
||||
threadRole = kThreadRoleDisabledOrDetached;
|
||||
break;
|
||||
case Mle::DeviceRole::kRoleChild:
|
||||
threadIfStatus = kThreadIfStatusActive;
|
||||
threadRole = kThreadRoleChild;
|
||||
break;
|
||||
case Mle::DeviceRole::kRoleRouter:
|
||||
threadIfStatus = kThreadIfStatusActive;
|
||||
threadRole = kThreadRoleRouter;
|
||||
break;
|
||||
case Mle::DeviceRole::kRoleLeader:
|
||||
threadIfStatus = kThreadIfStatusActive;
|
||||
threadRole = kThreadRoleLeader;
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == threadIfStatus);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadRole) == threadRole);
|
||||
|
||||
if (aNode.Get<BorderAgent>().Get<EphemeralKeyManager>().GetState() !=
|
||||
BorderAgent::EphemeralKeyManager::kStateDisabled)
|
||||
{
|
||||
VerifyOrQuit(stateBitmap & kFlagEpskcSupported);
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrQuit(!(stateBitmap & kFlagEpskcSupported));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void HandleServiceChanged(void *aContext) // Callback used in `TestBorderAgentTxtDataCallback().`
|
||||
{
|
||||
// `aContext` is a boolean `callbackInvoked`
|
||||
VerifyOrQuit(aContext != nullptr);
|
||||
*static_cast<bool *>(aContext) = true;
|
||||
}
|
||||
|
||||
void ReadAndValidateMeshCoPTxtData(Node &aNode)
|
||||
{
|
||||
BorderAgent::ServiceTxtData serviceTxtData;
|
||||
TxtData txtData;
|
||||
|
||||
SuccessOrQuit(aNode.Get<BorderAgent>().PrepareServiceTxtData(serviceTxtData));
|
||||
txtData.Init(serviceTxtData.mData, serviceTxtData.mLength);
|
||||
|
||||
ValidateMeshCoPTxtData(txtData, aNode);
|
||||
}
|
||||
|
||||
void TestBorderAgentTxtDataCallback(void)
|
||||
{
|
||||
Core nexus;
|
||||
Node &node0 = nexus.CreateNode();
|
||||
bool callbackInvoked = false;
|
||||
BorderAgent::Id newId;
|
||||
#endif
|
||||
|
||||
Log("------------------------------------------------------------------------------------------------------");
|
||||
Log("TestBorderAgentTxtDataCallback");
|
||||
@@ -848,152 +988,88 @@ void TestBorderAgentTxtDataCallback(void)
|
||||
nexus.AdvanceTime(0);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// 1. Set MeshCoP service change callback. Will get initial values.
|
||||
// Set MeshCoP service change callback. Will get initial values.
|
||||
Log("Set MeshCoP service change callback and check initial values");
|
||||
node0.Get<BorderAgent>().SetServiceChangedCallback(TxtDataTester::HandleServiceChanged, &txtDataTester);
|
||||
node0.Get<BorderAgent>().SetServiceChangedCallback(HandleServiceChanged, &callbackInvoked);
|
||||
nexus.AdvanceTime(1);
|
||||
|
||||
// 1.1 Check the initial TXT entries
|
||||
VerifyOrQuit(txtDataTester.mCallbackInvoked);
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("id", txtEntry));
|
||||
VerifyOrQuit(node0.Get<BorderAgent>().GetId(id) == kErrorNone);
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, id));
|
||||
#endif
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("nn", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<NetworkNameManager>().GetNetworkName().GetAsData()));
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("xp", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<ExtendedPanIdManager>().GetExtPanId()));
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("tv", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, NameData(kThreadVersionString, strlen(kThreadVersionString))));
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("xa", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<Mac::Mac>().GetExtAddress()));
|
||||
// Check the initial TXT entries
|
||||
ReadAndValidateMeshCoPTxtData(node0);
|
||||
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
|
||||
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
|
||||
stateBitmap = BigEndian::ReadUint32(txtEntry.mValue);
|
||||
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == kConnectionModeDisabled);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == kThreadIfStatusNotInitialized);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadRole) == kThreadRoleDisabledOrDetached);
|
||||
VerifyOrQuit(stateBitmap & kFlagEpskcSupported);
|
||||
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("pt", txtEntry) == false);
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("at", txtEntry) == false);
|
||||
|
||||
// 1.2 Check the Border Agent state
|
||||
VerifyOrQuit(txtDataTester.mIsRunning == false);
|
||||
VerifyOrQuit(txtDataTester.mUdpPort == 0);
|
||||
// Check the Border Agent state
|
||||
VerifyOrQuit(!node0.Get<BorderAgent>().IsRunning());
|
||||
VerifyOrQuit(node0.Get<BorderAgent>().GetUdpPort() == 0);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// 2. Join Thread network and check updated values and states.
|
||||
txtDataTester.mCallbackInvoked = false;
|
||||
// Join Thread network and check updated values and states.
|
||||
callbackInvoked = false;
|
||||
Log("Join Thread network and check updated Txt data and states");
|
||||
node0.Form();
|
||||
nexus.AdvanceTime(50 * Time::kOneSecondInMsec);
|
||||
|
||||
// 2.1 Check the initial TXT entries
|
||||
VerifyOrQuit(txtDataTester.mCallbackInvoked);
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("id", txtEntry));
|
||||
VerifyOrQuit(node0.Get<BorderAgent>().GetId(id) == kErrorNone);
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, id));
|
||||
#endif
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("nn", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<NetworkNameManager>().GetNetworkName().GetAsData()));
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("xp", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<ExtendedPanIdManager>().GetExtPanId()));
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("tv", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, NameData(kThreadVersionString, strlen(kThreadVersionString))));
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("xa", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<Mac::Mac>().GetExtAddress()));
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("pt", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(
|
||||
txtEntry, BigEndian::HostSwap32(node0.Get<Mle::Mle>().GetLeaderData().GetPartitionId())));
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("at", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, node0.Get<ActiveDatasetManager>().GetTimestamp()));
|
||||
VerifyOrQuit(callbackInvoked);
|
||||
ReadAndValidateMeshCoPTxtData(node0);
|
||||
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
|
||||
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
|
||||
stateBitmap = BigEndian::ReadUint32(txtEntry.mValue);
|
||||
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == kConnectionModePskc);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == kThreadIfStatusActive);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadRole) == kThreadRoleLeader);
|
||||
VerifyOrQuit(stateBitmap & kFlagEpskcSupported);
|
||||
|
||||
// 2.2 Check the Border Agent state
|
||||
VerifyOrQuit(txtDataTester.mIsRunning == true);
|
||||
VerifyOrQuit(txtDataTester.mUdpPort != 0);
|
||||
VerifyOrQuit(node0.Get<BorderAgent>().IsRunning());
|
||||
VerifyOrQuit(node0.Get<BorderAgent>().GetUdpPort() != 0);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
|
||||
Log("Change the Border Agent ID and validate that TXT data changed and callback is invoked");
|
||||
|
||||
newId.GenerateRandom();
|
||||
VerifyOrQuit(newId != id);
|
||||
|
||||
txtDataTester.mCallbackInvoked = false;
|
||||
callbackInvoked = false;
|
||||
SuccessOrQuit(node0.Get<BorderAgent>().SetId(newId));
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
|
||||
VerifyOrQuit(txtDataTester.mCallbackInvoked);
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("id", txtEntry));
|
||||
VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, newId));
|
||||
ReadAndValidateMeshCoPTxtData(node0);
|
||||
|
||||
// Validate that setting the ID to the same value as before is
|
||||
// correctly detected and does not trigger the callback.
|
||||
|
||||
txtDataTester.mCallbackInvoked = false;
|
||||
callbackInvoked = false;
|
||||
SuccessOrQuit(node0.Get<BorderAgent>().SetId(newId));
|
||||
nexus.AdvanceTime(1);
|
||||
VerifyOrQuit(!txtDataTester.mCallbackInvoked);
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
|
||||
VerifyOrQuit(!callbackInvoked);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Disable EphemeralKeyManager and validate that TXT data state bitmap indicates this");
|
||||
|
||||
txtDataTester.mCallbackInvoked = false;
|
||||
callbackInvoked = false;
|
||||
node0.Get<EphemeralKeyManager>().SetEnabled(false);
|
||||
VerifyOrQuit(node0.Get<EphemeralKeyManager>().GetState() == EphemeralKeyManager::kStateDisabled);
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
VerifyOrQuit(txtDataTester.mCallbackInvoked);
|
||||
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
|
||||
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
|
||||
stateBitmap = BigEndian::ReadUint32(txtEntry.mValue);
|
||||
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == kConnectionModePskc);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == kThreadIfStatusActive);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadRole) == kThreadRoleLeader);
|
||||
VerifyOrQuit(!(stateBitmap & kFlagEpskcSupported));
|
||||
VerifyOrQuit(callbackInvoked);
|
||||
ReadAndValidateMeshCoPTxtData(node0);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Disable the MLE operation and validate the TXT data state bitmap");
|
||||
|
||||
txtDataTester.mCallbackInvoked = false;
|
||||
callbackInvoked = false;
|
||||
SuccessOrQuit(node0.Get<Mle::Mle>().Disable());
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
VerifyOrQuit(txtDataTester.mCallbackInvoked);
|
||||
|
||||
VerifyOrQuit(txtDataTester.FindTxtEntry("sb", txtEntry));
|
||||
VerifyOrQuit(txtEntry.mValueLength == sizeof(uint32_t));
|
||||
stateBitmap = BigEndian::ReadUint32(txtEntry.mValue);
|
||||
VerifyOrQuit((stateBitmap & kMaskConnectionMode) == kConnectionModeDisabled);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadIfStatus) == kThreadIfStatusNotInitialized);
|
||||
VerifyOrQuit((stateBitmap & kMaskThreadRole) == kThreadRoleDisabledOrDetached);
|
||||
VerifyOrQuit(!(stateBitmap & kFlagEpskcSupported));
|
||||
VerifyOrQuit(callbackInvoked);
|
||||
ReadAndValidateMeshCoPTxtData(node0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void ValidateRegisteredServiceData(Dns::Multicast::Core::Service &aService, Node &aNode)
|
||||
{
|
||||
TxtData txtData;
|
||||
|
||||
txtData.Init(aService.mTxtData, aService.mTxtDataLength);
|
||||
ValidateMeshCoPTxtData(txtData, aNode);
|
||||
}
|
||||
|
||||
void TestBorderAgentServiceRegisteration(void)
|
||||
{
|
||||
static const char kDefaultServiceBaseName[] = OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME;
|
||||
|
||||
static const char kEphemeralKey[] = "nexus1234";
|
||||
static const char kDefaultServiceBaseName[] = OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME;
|
||||
static const char kEphemeralKey[] = "nexus1234";
|
||||
static const uint8_t kVendorTxtData[] = {8, 'v', 'n', '=', 'n', 'e', 'x', 'u', 's'};
|
||||
|
||||
static constexpr uint32_t kUdpPort = 49155;
|
||||
static constexpr uint32_t kInfraIfIndex = 1;
|
||||
@@ -1003,6 +1079,7 @@ void TestBorderAgentServiceRegisteration(void)
|
||||
Dns::Multicast::Core::Iterator *iterator;
|
||||
Dns::Multicast::Core::Service service;
|
||||
Dns::Multicast::Core::EntryState entryState;
|
||||
uint16_t txtDataLengthWithNoVendorData;
|
||||
|
||||
Log("------------------------------------------------------------------------------------------------------");
|
||||
Log("TestBorderAgentServiceRegisteration");
|
||||
@@ -1044,10 +1121,10 @@ void TestBorderAgentServiceRegisteration(void)
|
||||
VerifyOrQuit(StringStartsWith(service.mHostName, "ot"));
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent>().GetUdpPort());
|
||||
VerifyOrQuit(service.mSubTypeLabelsLength == 0);
|
||||
VerifyOrQuit(service.mTxtDataLength > 1);
|
||||
VerifyOrQuit(service.mTtl > 0);
|
||||
VerifyOrQuit(service.mInfraIfIndex == kInfraIfIndex);
|
||||
VerifyOrQuit(entryState == OT_MDNS_ENTRY_STATE_REGISTERED);
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
|
||||
// Check that there is no more registered mDNS service
|
||||
VerifyOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState) == kErrorNotFound);
|
||||
@@ -1093,8 +1170,8 @@ void TestBorderAgentServiceRegisteration(void)
|
||||
|
||||
if (StringMatch(service.mServiceType, "_meshcop._udp"))
|
||||
{
|
||||
VerifyOrQuit(service.mTxtDataLength > 1);
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent>().GetUdpPort());
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
}
|
||||
else if (StringMatch(service.mServiceType, "_meshcop-e._udp"))
|
||||
{
|
||||
@@ -1132,11 +1209,11 @@ void TestBorderAgentServiceRegisteration(void)
|
||||
VerifyOrQuit(StringStartsWith(service.mServiceInstance, kDefaultServiceBaseName));
|
||||
VerifyOrQuit(StringStartsWith(service.mHostName, "ot"));
|
||||
VerifyOrQuit(service.mSubTypeLabelsLength == 0);
|
||||
VerifyOrQuit(service.mTxtDataLength > 1);
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent>().GetUdpPort());
|
||||
VerifyOrQuit(service.mTtl > 0);
|
||||
VerifyOrQuit(service.mInfraIfIndex == kInfraIfIndex);
|
||||
VerifyOrQuit(entryState == OT_MDNS_ENTRY_STATE_REGISTERED);
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
|
||||
// Check that there is no more registered mDNS service
|
||||
VerifyOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState) == kErrorNotFound);
|
||||
@@ -1164,11 +1241,11 @@ void TestBorderAgentServiceRegisteration(void)
|
||||
VerifyOrQuit(StringStartsWith(service.mServiceInstance, "OpenThreadAgent"));
|
||||
VerifyOrQuit(StringStartsWith(service.mHostName, "ot"));
|
||||
VerifyOrQuit(service.mSubTypeLabelsLength == 0);
|
||||
VerifyOrQuit(service.mTxtDataLength > 1);
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent>().GetUdpPort());
|
||||
VerifyOrQuit(service.mTtl > 0);
|
||||
VerifyOrQuit(service.mInfraIfIndex == kInfraIfIndex);
|
||||
VerifyOrQuit(entryState == OT_MDNS_ENTRY_STATE_REGISTERED);
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
|
||||
// Check that there is no more registered mDNS service
|
||||
VerifyOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState) == kErrorNotFound);
|
||||
@@ -1212,11 +1289,82 @@ void TestBorderAgentServiceRegisteration(void)
|
||||
VerifyOrQuit(StringStartsWith(service.mServiceInstance, "OpenThreadAgent"));
|
||||
VerifyOrQuit(StringStartsWith(service.mHostName, "ot"));
|
||||
VerifyOrQuit(service.mSubTypeLabelsLength == 0);
|
||||
VerifyOrQuit(service.mTxtDataLength > 1);
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent>().GetUdpPort());
|
||||
VerifyOrQuit(service.mTtl > 0);
|
||||
VerifyOrQuit(service.mInfraIfIndex == kInfraIfIndex);
|
||||
VerifyOrQuit(entryState == OT_MDNS_ENTRY_STATE_REGISTERED);
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
txtDataLengthWithNoVendorData = service.mTxtDataLength;
|
||||
|
||||
// Check that there is no more registered mDNS service
|
||||
VerifyOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState) == kErrorNotFound);
|
||||
|
||||
node0.Get<Dns::Multicast::Core>().FreeIterator(*iterator);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Set vendor TXT data and validate that it is included in the registered mDNS service");
|
||||
|
||||
node0.Get<BorderAgent>().SetVendorTxtData(kVendorTxtData, sizeof(kVendorTxtData));
|
||||
nexus.AdvanceTime(5 * Time::kOneSecondInMsec);
|
||||
|
||||
iterator = node0.Get<Dns::Multicast::Core>().AllocateIterator();
|
||||
VerifyOrQuit(iterator != nullptr);
|
||||
|
||||
SuccessOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState));
|
||||
Log(" HostName: %s", service.mHostName);
|
||||
Log(" ServiceInstance: %s", service.mServiceInstance);
|
||||
Log(" ServiceType: %s", service.mServiceType);
|
||||
Log(" Port: %u", service.mPort);
|
||||
Log(" TTL: %lu", ToUlong(service.mTtl));
|
||||
|
||||
VerifyOrQuit(StringMatch(service.mServiceType, "_meshcop._udp"));
|
||||
VerifyOrQuit(StringStartsWith(service.mServiceInstance, "OpenThreadAgent"));
|
||||
VerifyOrQuit(StringStartsWith(service.mHostName, "ot"));
|
||||
VerifyOrQuit(service.mSubTypeLabelsLength == 0);
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent>().GetUdpPort());
|
||||
VerifyOrQuit(service.mTtl > 0);
|
||||
VerifyOrQuit(service.mInfraIfIndex == kInfraIfIndex);
|
||||
VerifyOrQuit(entryState == OT_MDNS_ENTRY_STATE_REGISTERED);
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
|
||||
// Check that vendor TXT data is included at the end of
|
||||
// the registered service TXT data.
|
||||
VerifyOrQuit(service.mTxtDataLength > txtDataLengthWithNoVendorData);
|
||||
VerifyOrQuit(service.mTxtDataLength > sizeof(kVendorTxtData));
|
||||
VerifyOrQuit(!memcmp(&service.mTxtData[service.mTxtDataLength - sizeof(kVendorTxtData)], kVendorTxtData,
|
||||
sizeof(kVendorTxtData)));
|
||||
|
||||
// Check that there is no more registered mDNS service
|
||||
VerifyOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState) == kErrorNotFound);
|
||||
|
||||
node0.Get<Dns::Multicast::Core>().FreeIterator(*iterator);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Clear vendor TXT data and validate that the registered mDNS service is updated accordingly");
|
||||
|
||||
node0.Get<BorderAgent>().SetVendorTxtData(nullptr, 0);
|
||||
nexus.AdvanceTime(5 * Time::kOneSecondInMsec);
|
||||
|
||||
iterator = node0.Get<Dns::Multicast::Core>().AllocateIterator();
|
||||
VerifyOrQuit(iterator != nullptr);
|
||||
|
||||
SuccessOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState));
|
||||
Log(" HostName: %s", service.mHostName);
|
||||
Log(" ServiceInstance: %s", service.mServiceInstance);
|
||||
Log(" ServiceType: %s", service.mServiceType);
|
||||
Log(" Port: %u", service.mPort);
|
||||
Log(" TTL: %lu", ToUlong(service.mTtl));
|
||||
|
||||
VerifyOrQuit(StringMatch(service.mServiceType, "_meshcop._udp"));
|
||||
VerifyOrQuit(StringStartsWith(service.mServiceInstance, "OpenThreadAgent"));
|
||||
VerifyOrQuit(StringStartsWith(service.mHostName, "ot"));
|
||||
VerifyOrQuit(service.mSubTypeLabelsLength == 0);
|
||||
VerifyOrQuit(service.mPort == node0.Get<MeshCoP::BorderAgent>().GetUdpPort());
|
||||
VerifyOrQuit(service.mTtl > 0);
|
||||
VerifyOrQuit(service.mInfraIfIndex == kInfraIfIndex);
|
||||
VerifyOrQuit(entryState == OT_MDNS_ENTRY_STATE_REGISTERED);
|
||||
ValidateRegisteredServiceData(service, node0);
|
||||
VerifyOrQuit(service.mTxtDataLength == txtDataLengthWithNoVendorData);
|
||||
|
||||
// Check that there is no more registered mDNS service
|
||||
VerifyOrQuit(node0.Get<Dns::Multicast::Core>().GetNextService(*iterator, service, entryState) == kErrorNotFound);
|
||||
|
||||
Reference in New Issue
Block a user