diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 547da903e..8ee10baf6 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -73,7 +73,7 @@ Error BorderAgent::GetId(Id &aId) if (Get().Read(mId) != kErrorNone) { - Random::NonCrypto::Fill(mId); + mId.GenerateRandom(); SuccessOrExit(error = Get().Save(mId)); } @@ -88,9 +88,15 @@ Error BorderAgent::SetId(const Id &aId) { Error error = kErrorNone; + if (mIdInitialized) + { + VerifyOrExit(aId != mId); + } + SuccessOrExit(error = Get().Save(aId)); mId = aId; mIdInitialized = true; + PostServiceTask(); exit: return error; diff --git a/src/core/meshcop/border_agent.hpp b/src/core/meshcop/border_agent.hpp index d95eb371d..2df3e7287 100644 --- a/src/core/meshcop/border_agent.hpp +++ b/src/core/meshcop/border_agent.hpp @@ -49,6 +49,7 @@ #include "common/non_copyable.hpp" #include "common/notifier.hpp" #include "common/owned_ptr.hpp" +#include "common/random.hpp" #include "common/tasklet.hpp" #include "meshcop/dataset.hpp" #include "meshcop/secure_transport.hpp" @@ -77,7 +78,6 @@ class BorderAgent : public InstanceLocator, private NonCopyable class CoapDtlsSession; public: - typedef otBorderAgentId Id; ///< Border Agent ID. typedef otBorderAgentCounters Counters; ///< Border Agent Counters. typedef otBorderAgentSessionInfo SessionInfo; ///< A session info. typedef otBorderAgentMeshCoPServiceChangedCallback ServiceChangedCallback; ///< Service changed callback. @@ -121,6 +121,21 @@ public: explicit BorderAgent(Instance &aInstance); #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE + /** + * Represents a Border Agent Identifier. + */ + struct Id : public otBorderAgentId, public Clearable, public Equatable + { + static constexpr uint16_t kLength = OT_BORDER_AGENT_ID_LENGTH; ///< The ID length (number of bytes). + + /** + * Generates a random ID. + */ + void GenerateRandom(void) { Random::NonCrypto::Fill(mId); } + }; + + static_assert(sizeof(Id) == Id::kLength, "sizeof(Id) is not valid"); + /** * Gets the randomly generated Border Agent ID. * @@ -142,7 +157,7 @@ public: * to set the ID only once after factory reset. If the ID has never been set by calling this * method, a random ID will be generated and returned when `GetId()` is called. * - * @param[out] aId specifies the Border Agent ID. + * @param[in] aId The Border Agent ID. * * @retval kErrorNone If successfully set the Border Agent ID. * @retval ... If failed to set the Border Agent ID. diff --git a/tests/nexus/test_border_agent.cpp b/tests/nexus/test_border_agent.cpp index 625e9e2ce..569bec65e 100644 --- a/tests/nexus/test_border_agent.cpp +++ b/tests/nexus/test_border_agent.cpp @@ -751,6 +751,7 @@ public: : mBorderAgent(aBorderAgent) , mIsRunning(false) , mUdpPort(0) + , mCallbackInvoked(false) { } @@ -761,6 +762,7 @@ public: mIsRunning = mBorderAgent.IsRunning(); mUdpPort = mBorderAgent.GetUdpPort(); SuccessOrQuit(mBorderAgent.PrepareServiceTxtData(mTxtData)); + mCallbackInvoked = true; } bool FindTxtEntry(const char *aKey, TxtEntry &aTxtEntry) @@ -785,6 +787,7 @@ public: BorderAgent::ServiceTxtData mTxtData; bool mIsRunning; uint16_t mUdpPort; + bool mCallbackInvoked; }; template bool CheckObjectSameAsTxtEntryData(const TxtEntry &aTxtEntry, const ObjectType &aObject) @@ -802,15 +805,19 @@ template <> bool CheckObjectSameAsTxtEntryData(const TxtEntry &aTxtEnt void TestBorderAgentTxtDataCallback(void) { - Core nexus; - Node &node0 = nexus.CreateNode(); + Core nexus; + Node &node0 = nexus.CreateNode(); + TxtDataTester txtDataTester(node0.Get()); + TxtEntry txtEntry; +#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE + BorderAgent::Id id; + BorderAgent::Id newId; +#endif Log("------------------------------------------------------------------------------------------------------"); Log("TestBorderAgentTxtDataCallback"); nexus.AdvanceTime(0); - TxtDataTester txtDataTester(node0.Get()); - TxtEntry txtEntry; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 1. Set MeshCoP service change callback. Will get initial values. @@ -819,9 +826,9 @@ void TestBorderAgentTxtDataCallback(void) 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)); - BorderAgent::Id id; VerifyOrQuit(node0.Get().GetId(id) == kErrorNone); VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, id)); #endif @@ -844,11 +851,13 @@ void TestBorderAgentTxtDataCallback(void) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // 2. Join Thread network and check updated values and states. + txtDataTester.mCallbackInvoked = 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().GetId(id) == kErrorNone); @@ -872,6 +881,33 @@ void TestBorderAgentTxtDataCallback(void) // 2.2 Check the Border Agent state VerifyOrQuit(txtDataTester.mIsRunning == true); VerifyOrQuit(txtDataTester.mUdpPort != 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; + SuccessOrQuit(node0.Get().SetId(newId)); + + nexus.AdvanceTime(1); + + VerifyOrQuit(txtDataTester.mCallbackInvoked); + VerifyOrQuit(txtDataTester.FindTxtEntry("id", txtEntry)); + VerifyOrQuit(CheckObjectSameAsTxtEntryData(txtEntry, newId)); + + // Validate that setting the ID to the same value as before is + // correctly detected and does not trigger the callback. + + txtDataTester.mCallbackInvoked = false; + SuccessOrQuit(node0.Get().SetId(newId)); + nexus.AdvanceTime(1); + VerifyOrQuit(!txtDataTester.mCallbackInvoked); + +#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE } } // namespace Nexus