[border-agent] introduce TxtData class (#12005)

This commit introduces a new `MeshCoP::BorderAgent::TxtData` class to
encapsulate the logic for preparing the Border Agent's MeshCoP
service TXT data.

The TXT data generation logic is moved from the `BorderAgent::Manager`
into the new `TxtData` class. This refactoring improves modularity
and maintainability and prepares for the future addition of a MeshCoP
TXT data parser.
This commit is contained in:
Abtin Keshavarzian
2025-10-10 12:59:33 -07:00
committed by GitHub
parent 5180438303
commit 6f0993065e
10 changed files with 376 additions and 196 deletions
+2
View File
@@ -528,6 +528,8 @@ openthread_core_files = [
"meshcop/border_agent.hpp",
"meshcop/border_agent_tracker.cpp",
"meshcop/border_agent_tracker.hpp",
"meshcop/border_agent_txt_data.cpp",
"meshcop/border_agent_txt_data.hpp",
"meshcop/commissioner.cpp",
"meshcop/commissioner.hpp",
"meshcop/dataset.cpp",
+1
View File
@@ -159,6 +159,7 @@ set(COMMON_SOURCES
meshcop/announce_begin_client.cpp
meshcop/border_agent.cpp
meshcop/border_agent_tracker.cpp
meshcop/border_agent_txt_data.cpp
meshcop/commissioner.cpp
meshcop/dataset.cpp
meshcop/dataset_manager.cpp
+1 -1
View File
@@ -111,7 +111,7 @@ void otBorderAgentSetMeshCoPServiceChangedCallback(otInstance
otError otBorderAgentGetMeshCoPServiceTxtData(otInstance *aInstance, otBorderAgentMeshCoPServiceTxtData *aTxtData)
{
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent::Manager>().PrepareServiceTxtData(*aTxtData);
return AsCoreType(aInstance).Get<MeshCoP::BorderAgent::TxtData>().Prepare(*aTxtData);
}
const otBorderAgentCounters *otBorderAgentGetCounters(otInstance *aInstance)
+1
View File
@@ -173,6 +173,7 @@ Instance::Instance(void)
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
, mBorderAgentManager(*this)
, mBorderAgentTxtData(*this)
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
, mBorderAgentEphemeralKeyManager(*this)
+3
View File
@@ -87,6 +87,7 @@
#include "mac/wakeup_tx_scheduler.hpp"
#include "meshcop/border_agent.hpp"
#include "meshcop/border_agent_tracker.hpp"
#include "meshcop/border_agent_txt_data.hpp"
#include "meshcop/commissioner.hpp"
#include "meshcop/dataset_manager.hpp"
#include "meshcop/dataset_updater.hpp"
@@ -590,6 +591,7 @@ private:
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
MeshCoP::BorderAgent::Manager mBorderAgentManager;
MeshCoP::BorderAgent::TxtData mBorderAgentTxtData;
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
@@ -1034,6 +1036,7 @@ template <> inline MeshCoP::DatasetUpdater &Instance::Get(void) { return mDatase
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
template <> inline MeshCoP::BorderAgent::Manager &Instance::Get(void) { return mBorderAgentManager; }
template <> inline MeshCoP::BorderAgent::TxtData &Instance::Get(void) { return mBorderAgentTxtData; }
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE && OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
+2 -132
View File
@@ -36,6 +36,7 @@
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
#include "instance/instance.hpp"
#include "meshcop/border_agent_txt_data.hpp"
namespace ot {
namespace MeshCoP {
@@ -46,7 +47,6 @@ RegisterLogModule("BorderAgent");
//----------------------------------------------------------------------------------------------------------------------
// `Manager`
const char Manager::kTxtDataRecordVersion[] = "1";
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
const char Manager::kServiceType[] = "_meshcop._udp";
const char Manager::kDefaultBaseServiceName[] = OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_BASE_NAME;
@@ -476,7 +476,7 @@ void Manager::RegisterService(void)
txtDataBuffer = reinterpret_cast<uint8_t *>(Heap::CAlloc(txtDataBufferSize, sizeof(uint8_t)));
OT_ASSERT(txtDataBuffer != nullptr);
SuccessOrAssert(PrepareServiceTxtData(txtDataBuffer, txtDataBufferSize, txtDataLength));
SuccessOrAssert(Get<TxtData>().Prepare(txtDataBuffer, txtDataBufferSize, txtDataLength));
if (mVendorTxtData.GetLength() != 0)
{
@@ -518,136 +518,6 @@ exit:
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
Error Manager::PrepareServiceTxtData(ServiceTxtData &aTxtData)
{
return PrepareServiceTxtData(aTxtData.mData, sizeof(aTxtData.mData), aTxtData.mLength);
}
Error Manager::PrepareServiceTxtData(uint8_t *aBuffer, uint16_t aBufferSize, uint16_t &aLength)
{
Error error = kErrorNone;
Dns::TxtDataEncoder encoder(aBuffer, aBufferSize);
MeshCoP::Dataset::Info datasetInfo;
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
{
Id id;
GetId(id);
SuccessOrExit(error = encoder.AppendEntry("id", id));
}
#endif
SuccessOrExit(error = encoder.AppendStringEntry("rv", kTxtDataRecordVersion));
SuccessOrExit(error = encoder.AppendBigEndianUintEntry("sb", DetermineStateBitmap()));
SuccessOrExit(error = encoder.AppendStringEntry("tv", kThreadVersionString));
SuccessOrExit(error = encoder.AppendEntry("xa", Get<Mac::Mac>().GetExtAddress()));
if (Get<MeshCoP::ActiveDatasetManager>().IsComplete() &&
(Get<MeshCoP::ActiveDatasetManager>().Read(datasetInfo) == kErrorNone))
{
if (datasetInfo.IsPresent<Dataset::kExtendedPanId>())
{
SuccessOrExit(error = encoder.AppendEntry("xp", datasetInfo.Get<Dataset::kExtendedPanId>()));
}
if (datasetInfo.IsPresent<Dataset::kNetworkName>())
{
SuccessOrExit(error = encoder.AppendNameEntry("nn", datasetInfo.Get<Dataset::kNetworkName>().GetAsData()));
}
}
if (Get<Mle::Mle>().IsAttached())
{
SuccessOrExit(error = encoder.AppendBigEndianUintEntry("pt", Get<Mle::Mle>().GetLeaderData().GetPartitionId()));
if (Get<MeshCoP::ActiveDatasetManager>().GetTimestamp().IsValid())
{
SuccessOrExit(error = encoder.AppendEntry("at", Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()));
}
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
if (Get<Mle::Mle>().IsAttached() && Get<BackboneRouter::Local>().IsEnabled())
{
BackboneRouter::Config bbrConfig;
Get<BackboneRouter::Local>().GetConfig(bbrConfig);
SuccessOrExit(error = encoder.AppendEntry("sq", bbrConfig.mSequenceNumber));
SuccessOrExit(error = encoder.AppendBigEndianUintEntry("bb", BackboneRouter::kBackboneUdpPort));
}
SuccessOrExit(error =
encoder.AppendNameEntry("dn", Get<MeshCoP::NetworkNameManager>().GetDomainName().GetAsData()));
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
{
Ip6::Prefix prefix;
BorderRouter::RoutePreference preference;
if (Get<BorderRouter::RoutingManager>().GetFavoredOmrPrefix(prefix, preference) == kErrorNone &&
prefix.GetLength() > 0)
{
uint8_t omrData[Ip6::NetworkPrefix::kSize + 1];
omrData[0] = prefix.GetLength();
memcpy(omrData + 1, prefix.GetBytes(), prefix.GetBytesSize());
SuccessOrExit(error = encoder.AppendEntry("omr", omrData));
}
}
#endif
aLength = encoder.GetLength();
exit:
return error;
}
uint32_t Manager::DetermineStateBitmap(void) const
{
uint32_t bitmap = 0;
bitmap |= (IsRunning() ? StateBitmap::kConnectionModePskc : StateBitmap::kConnectionModeDisabled);
bitmap |= StateBitmap::kAvailabilityHigh;
switch (Get<Mle::Mle>().GetRole())
{
case Mle::DeviceRole::kRoleDisabled:
bitmap |= (StateBitmap::kThreadIfStatusNotInitialized | StateBitmap::kThreadRoleDisabledOrDetached);
break;
case Mle::DeviceRole::kRoleDetached:
bitmap |= (StateBitmap::kThreadIfStatusInitialized | StateBitmap::kThreadRoleDisabledOrDetached);
break;
case Mle::DeviceRole::kRoleChild:
bitmap |= (StateBitmap::kThreadIfStatusActive | StateBitmap::kThreadRoleChild);
break;
case Mle::DeviceRole::kRoleRouter:
bitmap |= (StateBitmap::kThreadIfStatusActive | StateBitmap::kThreadRoleRouter);
break;
case Mle::DeviceRole::kRoleLeader:
bitmap |= (StateBitmap::kThreadIfStatusActive | StateBitmap::kThreadRoleLeader);
break;
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
if (Get<Mle::Mle>().IsAttached())
{
bitmap |= (Get<BackboneRouter::Local>().IsEnabled() ? StateBitmap::kFlagBbrIsActive : 0);
bitmap |= (Get<BackboneRouter::Local>().IsPrimary() ? StateBitmap::kFlagBbrIsPrimary : 0);
}
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
if (Get<EphemeralKeyManager>().GetState() != EphemeralKeyManager::kStateDisabled)
{
bitmap |= StateBitmap::kFlagEpskcSupported;
}
#endif
return bitmap;
}
//----------------------------------------------------------------------------------------------------------------------
// Manager::SessionIterator
-60
View File
@@ -120,7 +120,6 @@ public:
typedef otBorderAgentCounters Counters; ///< Border Agent Counters.
typedef otBorderAgentSessionInfo SessionInfo; ///< A session info.
typedef otBorderAgentMeshCoPServiceChangedCallback ServiceChangedCallback; ///< Service changed callback.
typedef otBorderAgentMeshCoPServiceTxtData ServiceTxtData; ///< Service TXT data.
/**
* Represents an iterator for secure sessions.
@@ -239,16 +238,6 @@ public:
*/
void SetServiceChangedCallback(ServiceChangedCallback aCallback, void *aContext);
/**
* Prepares the MeshCoP service TXT data.
*
* @param[out] aTxtData A reference to a MeshCoP Service TXT data struct to get the data.
*
* @retval kErrorNone If successfully retrieved the Border Agent MeshCoP Service TXT data.
* @retval kErrorNoBufs If the buffer in @p aTxtData doesn't have enough size.
*/
Error PrepareServiceTxtData(ServiceTxtData &aTxtData);
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
/**
* Sets the base name to construct the service instance name used when advertising the mDNS `_meshcop._udp` service
@@ -368,51 +357,6 @@ private:
uint64_t mAllocationTime;
};
struct StateBitmap
{
// --- State Bitmap ConnectionMode ---
static constexpr uint8_t kOffsetConnectionMode = 0;
static constexpr uint32_t kMaskConnectionMode = 7 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeDisabled = 0 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModePskc = 1 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModePskd = 2 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeVendor = 3 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeX509 = 4 << kOffsetConnectionMode;
// --- State Bitmap ThreadIfStatus ---
static constexpr uint8_t kOffsetThreadIfStatus = 3;
static constexpr uint32_t kMaskThreadIfStatus = 3 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusNotInitialized = 0 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusInitialized = 1 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusActive = 2 << kOffsetThreadIfStatus;
// --- State Bitmap Availability ---
static constexpr uint8_t kOffsetAvailability = 5;
static constexpr uint32_t kMaskAvailability = 3 << kOffsetAvailability;
static constexpr uint32_t kAvailabilityInfrequent = 0 << kOffsetAvailability;
static constexpr uint32_t kAvailabilityHigh = 1 << kOffsetAvailability;
// --- State Bitmap BbrIsActive ---
static constexpr uint8_t kOffsetBbrIsActive = 7;
static constexpr uint32_t kFlagBbrIsActive = 1 << kOffsetBbrIsActive;
// --- State Bitmap BbrIsPrimary ---
static constexpr uint8_t kOffsetBbrIsPrimary = 8;
static constexpr uint32_t kFlagBbrIsPrimary = 1 << kOffsetBbrIsPrimary;
// --- State Bitmap ThreadRole ---
static constexpr uint8_t kOffsetThreadRole = 9;
static constexpr uint32_t kMaskThreadRole = 3 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleDisabledOrDetached = 0 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleChild = 1 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleRouter = 2 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleLeader = 3 << kOffsetThreadRole;
// --- State Bitmap EpskcSupported ---
static constexpr uint8_t kOffsetEpskcSupported = 11;
static constexpr uint32_t kFlagEpskcSupported = 1 << kOffsetEpskcSupported;
};
void UpdateState(void);
void Start(void);
void Stop(void);
@@ -432,9 +376,6 @@ private:
static Coap::Message::Code CoapCodeFromError(Error aError);
Error PrepareServiceTxtData(uint8_t *aBuffer, uint16_t aBufferSize, uint16_t &aLength);
uint32_t DetermineStateBitmap(void) const;
void PostServiceTask(void);
void HandleServiceTask(void);
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
@@ -453,7 +394,6 @@ private:
using ServiceTask = TaskletIn<Manager, &Manager::HandleServiceTask>;
static const char kTxtDataRecordVersion[];
#if OPENTHREAD_CONFIG_BORDER_AGENT_MESHCOP_SERVICE_ENABLE
static const char kServiceType[];
static const char kDefaultBaseServiceName[];
+204
View File
@@ -0,0 +1,204 @@
/*
* Copyright (c) 2025, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file implements generation of Border Agent TXT data.
*/
#include "border_agent_txt_data.hpp"
#include "instance/instance.hpp"
namespace ot {
namespace MeshCoP {
namespace BorderAgent {
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
const char TxtData::kRecordVersion[] = "1";
const char TxtData::Key::kRecordVersion[] = "rv";
const char TxtData::Key::kAgentId[] = "id";
const char TxtData::Key::kThreadVersion[] = "tv";
const char TxtData::Key::kStateBitmap[] = "sb";
const char TxtData::Key::kNetworkName[] = "nn";
const char TxtData::Key::kExtendedPanId[] = "xp";
const char TxtData::Key::kActiveTimestamp[] = "at";
const char TxtData::Key::kPartitionId[] = "pt";
const char TxtData::Key::kDomainName[] = "dn";
const char TxtData::Key::kBbrSeqNum[] = "sq";
const char TxtData::Key::kBbrPort[] = "bb";
const char TxtData::Key::kOmrPrefix[] = "omr";
const char TxtData::Key::kExtAddress[] = "xa";
TxtData::TxtData(Instance &aInstance)
: InstanceLocator(aInstance)
{
}
Error TxtData::Prepare(uint8_t *aBuffer, uint16_t aBufferSize, uint16_t &aLength)
{
Error error = kErrorNone;
Dns::TxtDataEncoder encoder(aBuffer, aBufferSize);
MeshCoP::Dataset::Info datasetInfo;
VerifyOrExit(aBuffer != nullptr, error = kErrorNoBufs);
#if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
{
Id id;
Get<Manager>().GetId(id);
SuccessOrExit(error = encoder.AppendEntry(Key::kAgentId, id));
}
#endif
SuccessOrExit(error = encoder.AppendStringEntry(Key::kRecordVersion, kRecordVersion));
SuccessOrExit(error = encoder.AppendBigEndianUintEntry(Key::kStateBitmap, StateBitmap::Determine(GetInstance())));
SuccessOrExit(error = encoder.AppendStringEntry(Key::kThreadVersion, kThreadVersionString));
SuccessOrExit(error = encoder.AppendEntry(Key::kExtAddress, Get<Mac::Mac>().GetExtAddress()));
if (Get<MeshCoP::ActiveDatasetManager>().IsComplete() &&
(Get<MeshCoP::ActiveDatasetManager>().Read(datasetInfo) == kErrorNone))
{
if (datasetInfo.IsPresent<Dataset::kExtendedPanId>())
{
SuccessOrExit(error = encoder.AppendEntry(Key::kExtendedPanId, datasetInfo.Get<Dataset::kExtendedPanId>()));
}
if (datasetInfo.IsPresent<Dataset::kNetworkName>())
{
SuccessOrExit(error = encoder.AppendNameEntry(Key::kNetworkName,
datasetInfo.Get<Dataset::kNetworkName>().GetAsData()));
}
}
if (Get<Mle::Mle>().IsAttached())
{
SuccessOrExit(error = encoder.AppendBigEndianUintEntry(Key::kPartitionId,
Get<Mle::Mle>().GetLeaderData().GetPartitionId()));
if (Get<MeshCoP::ActiveDatasetManager>().GetTimestamp().IsValid())
{
SuccessOrExit(error = encoder.AppendEntry(Key::kActiveTimestamp,
Get<MeshCoP::ActiveDatasetManager>().GetTimestamp()));
}
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
if (Get<Mle::Mle>().IsAttached() && Get<BackboneRouter::Local>().IsEnabled())
{
BackboneRouter::Config bbrConfig;
Get<BackboneRouter::Local>().GetConfig(bbrConfig);
SuccessOrExit(error = encoder.AppendEntry(Key::kBbrSeqNum, bbrConfig.mSequenceNumber));
SuccessOrExit(error = encoder.AppendBigEndianUintEntry(Key::kBbrPort, BackboneRouter::kBackboneUdpPort));
}
SuccessOrExit(error = encoder.AppendNameEntry(Key::kDomainName,
Get<MeshCoP::NetworkNameManager>().GetDomainName().GetAsData()));
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
{
Ip6::Prefix prefix;
BorderRouter::RoutePreference preference;
if (Get<BorderRouter::RoutingManager>().GetFavoredOmrPrefix(prefix, preference) == kErrorNone &&
prefix.GetLength() > 0)
{
uint8_t omrData[Ip6::NetworkPrefix::kSize + 1];
omrData[0] = prefix.GetLength();
memcpy(omrData + 1, prefix.GetBytes(), prefix.GetBytesSize());
SuccessOrExit(error = encoder.AppendEntry(Key::kOmrPrefix, omrData));
}
}
#endif
aLength = encoder.GetLength();
exit:
return error;
}
Error TxtData::Prepare(ServiceTxtData &aTxtData)
{
return Prepare(aTxtData.mData, sizeof(aTxtData.mData), aTxtData.mLength);
}
uint32_t TxtData::StateBitmap::Determine(Instance &aInstance)
{
uint32_t bitmap = 0;
bitmap |= (aInstance.Get<Manager>().IsRunning() ? kConnectionModePskc : kConnectionModeDisabled);
bitmap |= kAvailabilityHigh;
switch (aInstance.Get<Mle::Mle>().GetRole())
{
case Mle::DeviceRole::kRoleDisabled:
bitmap |= (kThreadIfStatusNotInitialized | kThreadRoleDisabledOrDetached);
break;
case Mle::DeviceRole::kRoleDetached:
bitmap |= (kThreadIfStatusInitialized | kThreadRoleDisabledOrDetached);
break;
case Mle::DeviceRole::kRoleChild:
bitmap |= (kThreadIfStatusActive | kThreadRoleChild);
break;
case Mle::DeviceRole::kRoleRouter:
bitmap |= (kThreadIfStatusActive | kThreadRoleRouter);
break;
case Mle::DeviceRole::kRoleLeader:
bitmap |= (kThreadIfStatusActive | kThreadRoleLeader);
break;
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
if (aInstance.Get<Mle::Mle>().IsAttached())
{
bitmap |= (aInstance.Get<BackboneRouter::Local>().IsEnabled() ? kFlagBbrIsActive : 0);
bitmap |= (aInstance.Get<BackboneRouter::Local>().IsPrimary() ? kFlagBbrIsPrimary : 0);
}
#endif
#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
if (aInstance.Get<EphemeralKeyManager>().GetState() != EphemeralKeyManager::kStateDisabled)
{
bitmap |= kFlagEpskcSupported;
}
#endif
return bitmap;
}
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
} // namespace BorderAgent
} // namespace MeshCoP
} // namespace ot
+158
View File
@@ -0,0 +1,158 @@
/*
* Copyright (c) 2025, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for Border Agent MeshCoP service TXT data.
*/
#ifndef BORDER_AGENT_TXT_DATA_HPP_
#define BORDER_AGENT_TXT_DATA_HPP_
#include "openthread-core-config.h"
#include <openthread/border_agent.h>
#include "common/error.hpp"
#include "common/locator.hpp"
namespace ot {
namespace MeshCoP {
namespace BorderAgent {
#if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
class TxtData : public InstanceLocator
{
public:
typedef otBorderAgentMeshCoPServiceTxtData ServiceTxtData; ///< Service TXT Data.
/**
* Initializes the `TxtData` object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*/
TxtData(Instance &aInstance);
/**
* Prepares the MeshCoP service TXT data.
*
* @param[out] aBuffer A pointer to a buffer to store the TXT data.
* @param[in] aBufferSize The size of @p aBuffer.
* @param[out] aLength On exit, the length of the prepared TXT data.
*
* @retval kErrorNone Successfully prepared the TXT data.
* @retval kErrorNoBufs The @p aBufferSize is too small.
*/
Error Prepare(uint8_t *aBuffer, uint16_t aBufferSize, uint16_t &aLength);
/**
* Prepares the MeshCoP service TXT data.
*
* @param[out] aTxtData A reference to a MeshCoP Service TXT data struct to get the data.
*
* @retval kErrorNone Successfully prepared the TXT data.
* @retval kErrorNoBufs The buffer in @p aTxtData is too small.
*/
Error Prepare(ServiceTxtData &aTxtData);
private:
static const char kRecordVersion[];
struct Key
{
static const char kRecordVersion[];
static const char kAgentId[];
static const char kThreadVersion[];
static const char kStateBitmap[];
static const char kNetworkName[];
static const char kExtendedPanId[];
static const char kActiveTimestamp[];
static const char kPartitionId[];
static const char kDomainName[];
static const char kBbrSeqNum[];
static const char kBbrPort[];
static const char kOmrPrefix[];
static const char kExtAddress[];
};
struct StateBitmap
{
static uint32_t Determine(Instance &aInstance);
// --- State Bitmap ConnectionMode ---
static constexpr uint8_t kOffsetConnectionMode = 0;
static constexpr uint32_t kMaskConnectionMode = 7 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeDisabled = 0 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModePskc = 1 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModePskd = 2 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeVendor = 3 << kOffsetConnectionMode;
static constexpr uint32_t kConnectionModeX509 = 4 << kOffsetConnectionMode;
// --- State Bitmap ThreadIfStatus ---
static constexpr uint8_t kOffsetThreadIfStatus = 3;
static constexpr uint32_t kMaskThreadIfStatus = 3 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusNotInitialized = 0 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusInitialized = 1 << kOffsetThreadIfStatus;
static constexpr uint32_t kThreadIfStatusActive = 2 << kOffsetThreadIfStatus;
// --- State Bitmap Availability ---
static constexpr uint8_t kOffsetAvailability = 5;
static constexpr uint32_t kMaskAvailability = 3 << kOffsetAvailability;
static constexpr uint32_t kAvailabilityInfrequent = 0 << kOffsetAvailability;
static constexpr uint32_t kAvailabilityHigh = 1 << kOffsetAvailability;
// --- State Bitmap BbrIsActive ---
static constexpr uint8_t kOffsetBbrIsActive = 7;
static constexpr uint32_t kFlagBbrIsActive = 1 << kOffsetBbrIsActive;
// --- State Bitmap BbrIsPrimary ---
static constexpr uint8_t kOffsetBbrIsPrimary = 8;
static constexpr uint32_t kFlagBbrIsPrimary = 1 << kOffsetBbrIsPrimary;
// --- State Bitmap ThreadRole ---
static constexpr uint8_t kOffsetThreadRole = 9;
static constexpr uint32_t kMaskThreadRole = 3 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleDisabledOrDetached = 0 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleChild = 1 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleRouter = 2 << kOffsetThreadRole;
static constexpr uint32_t kThreadRoleLeader = 3 << kOffsetThreadRole;
// --- State Bitmap EpskcSupported ---
static constexpr uint8_t kOffsetEpskcSupported = 11;
static constexpr uint32_t kFlagEpskcSupported = 1 << kOffsetEpskcSupported;
};
};
#endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
} // namespace BorderAgent
} // namespace MeshCoP
} // namespace ot
#endif // BORDER_AGENT_TXT_DATA_HPP_
+4 -3
View File
@@ -38,6 +38,7 @@ namespace Nexus {
using ActiveDatasetManager = MeshCoP::ActiveDatasetManager;
using Manager = MeshCoP::BorderAgent::Manager;
using BaTxtData = MeshCoP::BorderAgent::TxtData;
using EphemeralKeyManager = MeshCoP::BorderAgent::EphemeralKeyManager;
using EpskcEvent = HistoryTracker::EpskcEvent;
using Iterator = HistoryTracker::Iterator;
@@ -1323,10 +1324,10 @@ void HandleServiceChanged(void *aContext) // Callback used in `TestBorderAgentTx
void ReadAndValidateMeshCoPTxtData(Node &aNode)
{
Manager::ServiceTxtData serviceTxtData;
TxtData txtData;
BaTxtData::ServiceTxtData serviceTxtData;
TxtData txtData;
SuccessOrQuit(aNode.Get<Manager>().PrepareServiceTxtData(serviceTxtData));
SuccessOrQuit(aNode.Get<BaTxtData>().Prepare(serviceTxtData));
txtData.Init(serviceTxtData.mData, serviceTxtData.mLength);
ValidateMeshCoPTxtData(txtData, aNode);