[netdata] add TlvIterator and FindSubTlv<TlvType>() (#6621)

This commit contains the following changes:

- It adds `TlvIterator` to help iterate over TLVs of a given type
  in a given sequence of TLVs or sub-TLVs of another TLV.
- It adds helper method `PrefixTlv::FindSubTlv<TlvType>()` to
  search within the sub-TLVs for a specific one.
- It moves the `static` helper methods which find a TLV (with a
  given type) to `NetworkDataTlv` (from `NetworkData`).
This commit is contained in:
Abtin Keshavarzian
2021-05-17 22:20:40 -07:00
committed by GitHub
parent 3e19ce1f1f
commit 6792eb76af
12 changed files with 526 additions and 445 deletions
+1
View File
@@ -320,6 +320,7 @@ LOCAL_SRC_FILES := \
src/core/thread/network_data_local.cpp \
src/core/thread/network_data_notifier.cpp \
src/core/thread/network_data_service.cpp \
src/core/thread/network_data_tlvs.cpp \
src/core/thread/network_data_types.cpp \
src/core/thread/network_diagnostic.cpp \
src/core/thread/panid_query_server.cpp \
+1
View File
@@ -589,6 +589,7 @@ openthread_core_files = [
"thread/network_data_notifier.hpp",
"thread/network_data_service.cpp",
"thread/network_data_service.hpp",
"thread/network_data_tlvs.cpp",
"thread/network_data_tlvs.hpp",
"thread/network_data_types.cpp",
"thread/network_data_types.hpp",
+1
View File
@@ -193,6 +193,7 @@ set(COMMON_SOURCES
thread/network_data_local.cpp
thread/network_data_notifier.cpp
thread/network_data_service.cpp
thread/network_data_tlvs.cpp
thread/network_data_types.cpp
thread/network_diagnostic.cpp
thread/panid_query_server.cpp
+1
View File
@@ -270,6 +270,7 @@ SOURCES_COMMON = \
thread/network_data_local.cpp \
thread/network_data_notifier.cpp \
thread/network_data_service.cpp \
thread/network_data_tlvs.cpp \
thread/network_data_types.cpp \
thread/network_diagnostic.cpp \
thread/panid_query_server.cpp \
+9 -100
View File
@@ -54,52 +54,6 @@ NetworkData::NetworkData(Instance &aInstance, Type aType)
mLength = 0;
}
void NetworkData::Clear(void)
{
mLength = 0;
}
const NetworkDataTlv *NetworkData::FindTlv(const NetworkDataTlv *aStart,
const NetworkDataTlv *aEnd,
NetworkDataTlv::Type aType)
{
const NetworkDataTlv *tlv;
for (tlv = aStart; (tlv + 1 <= aEnd) && (tlv->GetNext() <= aEnd); tlv = tlv->GetNext())
{
if (tlv->GetType() == aType)
{
ExitNow();
}
}
tlv = nullptr;
exit:
return tlv;
}
const NetworkDataTlv *NetworkData::FindTlv(const NetworkDataTlv *aStart,
const NetworkDataTlv *aEnd,
NetworkDataTlv::Type aType,
bool aStable)
{
const NetworkDataTlv *tlv;
for (tlv = aStart; (tlv + 1 <= aEnd) && (tlv->GetNext() <= aEnd); tlv = tlv->GetNext())
{
if ((tlv->GetType() == aType) && (tlv->IsStable() == aStable))
{
ExitNow();
}
}
tlv = nullptr;
exit:
return tlv;
}
Error NetworkData::GetNetworkData(bool aStable, uint8_t *aData, uint8_t &aDataLength) const
{
Error error = kErrorNone;
@@ -503,7 +457,7 @@ void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, Pref
case NetworkDataTlv::kTypeBorderRouter:
{
BorderRouterTlv *borderRouter = static_cast<BorderRouterTlv *>(cur);
ContextTlv * context = FindContext(aPrefix);
ContextTlv * context = aPrefix.FindSubTlv<ContextTlv>();
// Replace p_border_router_16
for (BorderRouterEntry *entry = borderRouter->GetFirstEntry(); entry <= borderRouter->GetLastEntry();
@@ -587,31 +541,6 @@ void NetworkData::RemoveTemporaryData(uint8_t *aData, uint8_t &aDataLength, Serv
}
}
const BorderRouterTlv *NetworkData::FindBorderRouter(const PrefixTlv &aPrefix)
{
return FindTlv<BorderRouterTlv>(aPrefix.GetSubTlvs(), aPrefix.GetNext());
}
const BorderRouterTlv *NetworkData::FindBorderRouter(const PrefixTlv &aPrefix, bool aStable)
{
return FindTlv<BorderRouterTlv>(aPrefix.GetSubTlvs(), aPrefix.GetNext(), aStable);
}
const HasRouteTlv *NetworkData::FindHasRoute(const PrefixTlv &aPrefix)
{
return FindTlv<HasRouteTlv>(aPrefix.GetSubTlvs(), aPrefix.GetNext());
}
const HasRouteTlv *NetworkData::FindHasRoute(const PrefixTlv &aPrefix, bool aStable)
{
return FindTlv<HasRouteTlv>(aPrefix.GetSubTlvs(), aPrefix.GetNext(), aStable);
}
const ContextTlv *NetworkData::FindContext(const PrefixTlv &aPrefix)
{
return FindTlv<ContextTlv>(aPrefix.GetSubTlvs(), aPrefix.GetNext());
}
const PrefixTlv *NetworkData::FindPrefix(const uint8_t *aPrefix, uint8_t aPrefixLength) const
{
return FindPrefix(aPrefix, aPrefixLength, mTlvs, mLength);
@@ -622,27 +551,17 @@ const PrefixTlv *NetworkData::FindPrefix(const uint8_t *aPrefix,
const uint8_t *aTlvs,
uint8_t aTlvsLength)
{
const NetworkDataTlv *start = reinterpret_cast<const NetworkDataTlv *>(aTlvs);
const NetworkDataTlv *end = reinterpret_cast<const NetworkDataTlv *>(aTlvs + aTlvsLength);
const PrefixTlv * prefixTlv;
TlvIterator tlvIterator(aTlvs, aTlvsLength);
const PrefixTlv *prefixTlv;
while (start < end)
while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
{
prefixTlv = FindTlv<PrefixTlv>(start, end);
VerifyOrExit(prefixTlv != nullptr);
if (prefixTlv->IsEqual(aPrefix, aPrefixLength))
{
ExitNow();
break;
}
start = prefixTlv->GetNext();
}
prefixTlv = nullptr;
exit:
return prefixTlv;
}
@@ -670,30 +589,20 @@ const ServiceTlv *NetworkData::FindService(uint32_t aEnterpriseNumber,
const uint8_t *aTlvs,
uint8_t aTlvsLength)
{
const NetworkDataTlv *start = reinterpret_cast<const NetworkDataTlv *>(aTlvs);
const NetworkDataTlv *end = reinterpret_cast<const NetworkDataTlv *>(aTlvs + aTlvsLength);
const ServiceTlv * serviceTlv;
TlvIterator tlvIterator(aTlvs, aTlvsLength);
const ServiceTlv *serviceTlv;
while (start < end)
while ((serviceTlv = tlvIterator.Iterate<ServiceTlv>()) != nullptr)
{
serviceTlv = FindTlv<ServiceTlv>(start, end);
VerifyOrExit(serviceTlv != nullptr);
if ((serviceTlv->GetEnterpriseNumber() == aEnterpriseNumber) &&
(serviceTlv->GetServiceDataLength() >= aServiceDataLength) &&
(!aExactServiceDataMatch || (serviceTlv->GetServiceDataLength() == aServiceDataLength)) &&
(memcmp(serviceTlv->GetServiceData(), aServiceData, aServiceDataLength) == 0))
{
ExitNow();
break;
}
start = serviceTlv->GetNext();
}
serviceTlv = nullptr;
exit:
return serviceTlv;
}
+1 -253
View File
@@ -139,7 +139,7 @@ public:
* This method clears the network data.
*
*/
void Clear(void);
void Clear(void) { mLength = 0; }
/**
* This method provides a full or stable copy of the Thread Network Data.
@@ -340,125 +340,6 @@ protected:
*/
const NetworkDataTlv *GetTlvsEnd(void) const { return reinterpret_cast<const NetworkDataTlv *>(mTlvs + mLength); }
/**
* This method returns a pointer to the Border Router TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
*
* @returns A pointer to the Border Router TLV if one is found or nullptr if no Border Router TLV exists.
*
*/
static BorderRouterTlv *FindBorderRouter(PrefixTlv &aPrefix)
{
return const_cast<BorderRouterTlv *>(FindBorderRouter(const_cast<const PrefixTlv &>(aPrefix)));
}
/**
* This method returns a pointer to the Border Router TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
*
* @returns A pointer to the Border Router TLV if one is found or nullptr if no Border Router TLV exists.
*
*/
static const BorderRouterTlv *FindBorderRouter(const PrefixTlv &aPrefix);
/**
* This method returns a pointer to the stable or non-stable Border Router TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable..
*
* @returns A pointer to the Border Router TLV if one is found or nullptr if no Border Router TLV exists.
*
*/
static BorderRouterTlv *FindBorderRouter(PrefixTlv &aPrefix, bool aStable)
{
return const_cast<BorderRouterTlv *>(FindBorderRouter(const_cast<const PrefixTlv &>(aPrefix), aStable));
}
/**
* This method returns a pointer to the stable or non-stable Border Router TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable..
*
* @returns A pointer to the Border Router TLV if one is found or nullptr if no Border Router TLV exists.
*
*/
static const BorderRouterTlv *FindBorderRouter(const PrefixTlv &aPrefix, bool aStable);
/**
* This method returns a pointer to the Has Route TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
*
* @returns A pointer to the Has Route TLV if one is found or nullptr if no Has Route TLV exists.
*
*/
static HasRouteTlv *FindHasRoute(PrefixTlv &aPrefix)
{
return const_cast<HasRouteTlv *>(FindHasRoute(const_cast<const PrefixTlv &>(aPrefix)));
}
/**
* This method returns a pointer to the Has Route TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
*
* @returns A pointer to the Has Route TLV if one is found or nullptr if no Has Route TLV exists.
*
*/
static const HasRouteTlv *FindHasRoute(const PrefixTlv &aPrefix);
/**
* This method returns a pointer to the stable or non-stable Has Route TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the Has Route TLV if one is found or nullptr if no Has Route TLV exists.
*
*/
static HasRouteTlv *FindHasRoute(PrefixTlv &aPrefix, bool aStable)
{
return const_cast<HasRouteTlv *>(FindHasRoute(const_cast<const PrefixTlv &>(aPrefix), aStable));
}
/**
* This method returns a pointer to the stable or non-stable Has Route TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the Has Route TLV if one is found or nullptr if no Has Route TLV exists.
*
*/
static const HasRouteTlv *FindHasRoute(const PrefixTlv &aPrefix, bool aStable);
/**
* This method returns a pointer to the Context TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
*
* @returns A pointer to the Context TLV if one is found or nullptr if no Context TLV exists.
*
*/
static ContextTlv *FindContext(PrefixTlv &aPrefix)
{
return const_cast<ContextTlv *>(FindContext(const_cast<const PrefixTlv &>(aPrefix)));
}
/**
* This method returns a pointer to the Context TLV within a given Prefix TLV.
*
* @param[in] aPrefix A reference to the Prefix TLV.
*
* @returns A pointer to the Context TLV if one is found or nullptr if no Context TLV exists.
*
*/
static const ContextTlv *FindContext(const PrefixTlv &aPrefix);
/**
* This method returns a pointer to a Prefix TLV.
*
@@ -710,139 +591,6 @@ protected:
*/
Error SendServerDataNotification(uint16_t aRloc16, Coap::ResponseHandler aHandler, void *aContext);
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
static NetworkDataTlv *FindTlv(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, NetworkDataTlv::Type aType)
{
return const_cast<NetworkDataTlv *>(
FindTlv(const_cast<const NetworkDataTlv *>(aStart), const_cast<const NetworkDataTlv *>(aEnd), aType));
}
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
static const NetworkDataTlv *FindTlv(const NetworkDataTlv *aStart,
const NetworkDataTlv *aEnd,
NetworkDataTlv::Type aType);
/**
* This static template method searches in a given sequence of TLVs to find the first TLV with a give template
* `TlvType`.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename TlvType> static TlvType *FindTlv(NetworkDataTlv *aStart, NetworkDataTlv *aEnd)
{
return static_cast<TlvType *>(FindTlv(aStart, aEnd, static_cast<NetworkDataTlv::Type>(TlvType::kType)));
}
/**
* This static template method searches in a given sequence of TLVs to find the first TLV with a give template
* `TlvType`.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename TlvType> static const TlvType *FindTlv(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
{
return static_cast<const TlvType *>(FindTlv(aStart, aEnd, static_cast<NetworkDataTlv::Type>(TlvType::kType)));
}
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type and stable
* flag.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param [in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
static NetworkDataTlv *FindTlv(NetworkDataTlv * aStart,
NetworkDataTlv * aEnd,
NetworkDataTlv::Type aType,
bool aStable)
{
return const_cast<NetworkDataTlv *>(FindTlv(const_cast<const NetworkDataTlv *>(aStart),
const_cast<const NetworkDataTlv *>(aEnd), aType, aStable));
}
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type and stable
* flag.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param [in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
static const NetworkDataTlv *FindTlv(const NetworkDataTlv *aStart,
const NetworkDataTlv *aEnd,
NetworkDataTlv::Type aType,
bool aStable);
/**
* This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type and
* stable flag.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param [in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename TlvType> static TlvType *FindTlv(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, bool aStable)
{
return static_cast<TlvType *>(
FindTlv(aStart, aEnd, static_cast<NetworkDataTlv::Type>(TlvType::kType), aStable));
}
/**
* This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type and
* stable flag.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param [in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename TlvType>
static const TlvType *FindTlv(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, bool aStable)
{
return static_cast<const TlvType *>(
FindTlv(aStart, aEnd, static_cast<NetworkDataTlv::Type>(TlvType::kType), aStable));
}
uint8_t mTlvs[kMaxSize]; ///< The Network Data buffer.
uint8_t mLength; ///< The number of valid bytes in @var mTlvs.
+15 -18
View File
@@ -96,17 +96,16 @@ exit:
const PrefixTlv *LeaderBase::FindNextMatchingPrefix(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const
{
const PrefixTlv *prefixTlv;
TlvIterator tlvIterator((aPrevTlv == nullptr) ? GetTlvsStart() : aPrevTlv->GetNext(), GetTlvsEnd());
for (const NetworkDataTlv *start = (aPrevTlv == nullptr) ? GetTlvsStart() : aPrevTlv->GetNext();
(prefixTlv = FindTlv<PrefixTlv>(start, GetTlvsEnd())) != nullptr; start = prefixTlv->GetNext())
while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
{
if (aAddress.MatchesPrefix(prefixTlv->GetPrefix(), prefixTlv->GetPrefixLength()))
{
ExitNow();
break;
}
}
exit:
return prefixTlv;
}
@@ -126,7 +125,7 @@ Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aCon
while ((prefix = FindNextMatchingPrefix(aAddress, prefix)) != nullptr)
{
contextTlv = FindContext(*prefix);
contextTlv = prefix->FindSubTlv<ContextTlv>();
if (contextTlv == nullptr)
{
@@ -147,6 +146,7 @@ Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aCon
Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) const
{
Error error = kErrorNotFound;
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
const PrefixTlv *prefix;
if (aContextId == Mle::kMeshLocalPrefixContextId)
@@ -157,10 +157,9 @@ Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) cons
ExitNow(error = kErrorNone);
}
for (const NetworkDataTlv *start = GetTlvsStart(); (prefix = FindTlv<PrefixTlv>(start, GetTlvsEnd())) != nullptr;
start = prefix->GetNext())
while ((prefix = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
{
const ContextTlv *contextTlv = FindContext(*prefix);
const ContextTlv *contextTlv = prefix->FindSubTlv<ContextTlv>();
if ((contextTlv == nullptr) || (contextTlv->GetContextId() != aContextId))
{
@@ -189,7 +188,7 @@ bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress) const
// check both stable and temporary Border Router TLVs
for (int i = 0; i < 2; i++)
{
const BorderRouterTlv *borderRouter = FindBorderRouter(*prefix, /* aStable */ (i == 0));
const BorderRouterTlv *borderRouter = prefix->FindSubTlv<BorderRouterTlv>(/* aStable */ (i == 0));
if (borderRouter == nullptr)
{
@@ -247,15 +246,16 @@ Error LeaderBase::ExternalRouteLookup(uint8_t aDomainId,
uint16_t * aRloc16) const
{
Error error = kErrorNoRoute;
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
const PrefixTlv * prefixTlv;
const HasRouteEntry *bestRouteEntry = nullptr;
uint8_t bestMatchLength = 0;
for (const NetworkDataTlv *start = GetTlvsStart(); (prefixTlv = FindTlv<PrefixTlv>(start, GetTlvsEnd())) != nullptr;
start = prefixTlv->GetNext())
while ((prefixTlv = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
{
const HasRouteTlv *hasRoute;
uint8_t prefixLength = prefixTlv->GetPrefixLength();
TlvIterator subTlvIterator(*prefixTlv);
if (prefixTlv->GetDomainId() != aDomainId)
{
@@ -272,9 +272,7 @@ Error LeaderBase::ExternalRouteLookup(uint8_t aDomainId,
continue;
}
for (const NetworkDataTlv *subStart = prefixTlv->GetSubTlvs();
(hasRoute = FindTlv<HasRouteTlv>(subStart, prefixTlv->GetNext())) != nullptr;
subStart = hasRoute->GetNext())
while ((hasRoute = subTlvIterator.Iterate<HasRouteTlv>()) != nullptr)
{
for (const HasRouteEntry *entry = hasRoute->GetFirstEntry(); entry <= hasRoute->GetLastEntry();
entry = entry->GetNext())
@@ -314,12 +312,11 @@ Error LeaderBase::ExternalRouteLookup(uint8_t aDomainId,
Error LeaderBase::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const
{
Error error = kErrorNoRoute;
TlvIterator subTlvIterator(aPrefix);
const BorderRouterTlv * borderRouter;
const BorderRouterEntry *route = nullptr;
for (const NetworkDataTlv *start = aPrefix.GetSubTlvs();
(borderRouter = FindTlv<BorderRouterTlv>(start, aPrefix.GetNext())) != nullptr;
start = borderRouter->GetNext())
while ((borderRouter = subTlvIterator.Iterate<BorderRouterTlv>()) != nullptr)
{
for (const BorderRouterEntry *entry = borderRouter->GetFirstEntry(); entry <= borderRouter->GetLastEntry();
entry = entry->GetNext())
@@ -421,7 +418,7 @@ exit:
const CommissioningDataTlv *LeaderBase::GetCommissioningData(void) const
{
return FindTlv<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
return NetworkDataTlv::Find<CommissioningDataTlv>(GetTlvsStart(), GetTlvsEnd());
}
const MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType) const
+29 -32
View File
@@ -575,7 +575,7 @@ bool Leader::ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const
// Check whether `aPrefix` has a Has Route sub-TLV with stable
// flag `aStable` containing a matching entry to `aEntry`.
return (aPrefix == nullptr) ? false : ContainsMatchingEntry(FindHasRoute(*aPrefix, aStable), aEntry);
return (aPrefix == nullptr) ? false : ContainsMatchingEntry(aPrefix->FindSubTlv<HasRouteTlv>(aStable), aEntry);
}
bool Leader::ContainsMatchingEntry(const HasRouteTlv *aHasRoute, const HasRouteEntry &aEntry)
@@ -604,7 +604,7 @@ bool Leader::ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const
// Check whether `aPrefix` has a Border Router sub-TLV with stable
// flag `aStable` containing a matching entry to `aEntry`.
return (aPrefix == nullptr) ? false : ContainsMatchingEntry(FindBorderRouter(*aPrefix, aStable), aEntry);
return (aPrefix == nullptr) ? false : ContainsMatchingEntry(aPrefix->FindSubTlv<BorderRouterTlv>(aStable), aEntry);
}
bool Leader::ContainsMatchingEntry(const BorderRouterTlv *aBorderRouter, const BorderRouterEntry &aEntry)
@@ -634,22 +634,23 @@ bool Leader::ContainsMatchingServer(const ServiceTlv *aService, const ServerTlv
// Check whether the `aService` has a matching Server sub-TLV
// same as `aServer`.
bool contains = false;
const ServerTlv *server;
bool contains = false;
VerifyOrExit(aService != nullptr);
for (const NetworkDataTlv *start = aService->GetSubTlvs();
(server = FindTlv<ServerTlv>(start, aService->GetNext(), aServer.IsStable())) != nullptr;
start = server->GetNext())
if (aService != nullptr)
{
if (*server == aServer)
const ServerTlv *server;
TlvIterator subTlvIterator(*aService);
while ((server = subTlvIterator.Iterate<ServerTlv>(aServer.IsStable())) != nullptr)
{
ExitNow(contains = true);
if (*server == aServer)
{
contains = true;
break;
}
}
}
exit:
return contains;
}
@@ -804,7 +805,7 @@ Error Leader::AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags
aService.GetServiceDataLength());
}
server = FindTlv<ServerTlv>(aService.GetSubTlvs(), aService.GetNext());
server = NetworkDataTlv::Find<ServerTlv>(aService.GetSubTlvs(), aService.GetNext());
OT_ASSERT(server != nullptr);
SuccessOrExit(error = AddServer(*server, *dstService, aChangedFlags));
@@ -827,7 +828,7 @@ exit:
Error Leader::AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags)
{
Error error = kErrorNone;
HasRouteTlv * dstHasRoute = FindHasRoute(aDstPrefix, aHasRoute.IsStable());
HasRouteTlv * dstHasRoute = aDstPrefix.FindSubTlv<HasRouteTlv>(aHasRoute.IsStable());
const HasRouteEntry *entry = aHasRoute.GetFirstEntry();
if (dstHasRoute == nullptr)
@@ -864,8 +865,8 @@ exit:
Error Leader::AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags)
{
Error error = kErrorNone;
BorderRouterTlv * dstBorderRouter = FindBorderRouter(aDstPrefix, aBorderRouter.IsStable());
ContextTlv * dstContext = FindContext(aDstPrefix);
BorderRouterTlv * dstBorderRouter = aDstPrefix.FindSubTlv<BorderRouterTlv>(aBorderRouter.IsStable());
ContextTlv * dstContext = aDstPrefix.FindSubTlv<ContextTlv>();
uint8_t contextId = 0;
const BorderRouterEntry *entry = aBorderRouter.GetFirstEntry();
@@ -976,20 +977,17 @@ Error Leader::AllocateServiceId(uint8_t &aServiceId) const
const ServiceTlv *Leader::FindServiceById(uint8_t aServiceId) const
{
const NetworkDataTlv *start = GetTlvsStart();
const ServiceTlv * service;
const ServiceTlv *service;
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
while ((service = FindTlv<ServiceTlv>(start, GetTlvsEnd())) != nullptr)
while ((service = tlvIterator.Iterate<ServiceTlv>()) != nullptr)
{
if (service->GetServiceId() == aServiceId)
{
ExitNow();
break;
}
start = service->GetNext();
}
exit:
return service;
}
@@ -1154,7 +1152,7 @@ void Leader::RemoveRlocInPrefix(PrefixTlv & aPrefix,
cur = cur->GetNext();
}
if ((context = FindContext(aPrefix)) != nullptr)
if ((context = aPrefix.FindSubTlv<ContextTlv>()) != nullptr)
{
if (aPrefix.GetSubTlvsLength() == sizeof(ContextTlv))
{
@@ -1181,7 +1179,7 @@ void Leader::RemoveRlocInService(ServiceTlv & aService,
NetworkDataTlv *start = aService.GetSubTlvs();
ServerTlv * server;
while ((server = FindTlv<ServerTlv>(start, aService.GetNext())) != nullptr)
while ((server = NetworkDataTlv::Find<ServerTlv>(start, aService.GetNext())) != nullptr)
{
if (RlocMatch(server->GetServer16(), aRloc16, aMatchMode) && !ContainsMatchingServer(aExcludeService, *server))
{
@@ -1260,7 +1258,7 @@ void Leader::RemoveContext(uint8_t aContextId)
NetworkDataTlv *start = GetTlvsStart();
PrefixTlv * prefix;
while ((prefix = FindTlv<PrefixTlv>(start, GetTlvsEnd())) != nullptr)
while ((prefix = NetworkDataTlv::Find<PrefixTlv>(start, GetTlvsEnd())) != nullptr)
{
RemoveContext(*prefix, aContextId);
@@ -1279,7 +1277,7 @@ void Leader::RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId)
NetworkDataTlv *start = aPrefix.GetSubTlvs();
ContextTlv * context;
while ((context = FindTlv<ContextTlv>(start, aPrefix.GetNext())) != nullptr)
while ((context = NetworkDataTlv::Find<ContextTlv>(start, aPrefix.GetNext())) != nullptr)
{
if (context->GetContextId() == aContextId)
{
@@ -1295,13 +1293,12 @@ void Leader::RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId)
void Leader::UpdateContextsAfterReset(void)
{
NetworkDataTlv *start;
PrefixTlv * prefix;
const PrefixTlv *prefix;
TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd());
for (start = GetTlvsStart(); (prefix = FindTlv<PrefixTlv>(start, GetTlvsEnd())) != nullptr;
start = prefix->GetNext())
while ((prefix = tlvIterator.Iterate<PrefixTlv>()) != nullptr)
{
ContextTlv *context = FindContext(*prefix);
const ContextTlv *context = prefix->FindSubTlv<ContextTlv>();
if (context == nullptr)
{
+1 -1
View File
@@ -143,7 +143,7 @@ Error Local::RemovePrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubT
PrefixTlv *tlv;
VerifyOrExit((tlv = FindPrefix(aPrefix)) != nullptr, error = kErrorNotFound);
VerifyOrExit(FindTlv(tlv->GetSubTlvs(), tlv->GetNext(), aSubTlvType) != nullptr, error = kErrorNotFound);
VerifyOrExit(tlv->FindSubTlv(aSubTlvType) != nullptr, error = kErrorNotFound);
RemoveTlv(tlv);
exit:
+1 -1
View File
@@ -255,7 +255,7 @@ Error Manager::IterateToNextServer(Iterator &aIterator) const
VerifyOrExit(aIterator.mServiceTlv != nullptr);
aIterator.mServerSubTlv = NetworkData::FindTlv<ServerTlv>(
aIterator.mServerSubTlv = NetworkDataTlv::Find<ServerTlv>(
/* aStart */ (aIterator.mServerSubTlv != nullptr) ? aIterator.mServerSubTlv->GetNext()
: aIterator.mServiceTlv->GetSubTlvs(),
/* aEnd */ aIterator.mServiceTlv->GetNext());
+120
View File
@@ -0,0 +1,120 @@
/*
* Copyright (c) 2016-21, 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 methods for generating and processing Thread Network Data TLVs.
*/
#include "network_data_tlvs.hpp"
namespace ot {
namespace NetworkData {
//---------------------------------------------------------------------------------------------------------------------
// NetworkDataTlv
const NetworkDataTlv *NetworkDataTlv::Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, Type aType)
{
const NetworkDataTlv *tlv;
for (tlv = aStart; (tlv + 1 <= aEnd) && (tlv->GetNext() <= aEnd); tlv = tlv->GetNext())
{
if (tlv->GetType() == aType)
{
ExitNow();
}
}
tlv = nullptr;
exit:
return tlv;
}
const NetworkDataTlv *NetworkDataTlv::Find(const NetworkDataTlv *aStart,
const NetworkDataTlv *aEnd,
Type aType,
bool aStable)
{
const NetworkDataTlv *tlv;
for (tlv = aStart; (tlv + 1 <= aEnd) && (tlv->GetNext() <= aEnd); tlv = tlv->GetNext())
{
if ((tlv->GetType() == aType) && (tlv->IsStable() == aStable))
{
ExitNow();
}
}
tlv = nullptr;
exit:
return tlv;
}
//---------------------------------------------------------------------------------------------------------------------
// PrefixTlv
const NetworkDataTlv *PrefixTlv::FindSubTlv(Type aType) const
{
return Find(GetSubTlvs(), GetNext(), aType);
}
const NetworkDataTlv *PrefixTlv::FindSubTlv(Type aType, bool aStable) const
{
return Find(GetSubTlvs(), GetNext(), aType, aStable);
}
//---------------------------------------------------------------------------------------------------------------------
// TlvIterator
const NetworkDataTlv *TlvIterator::Iterate(NetworkDataTlv::Type aType)
{
const NetworkDataTlv *tlv = NetworkDataTlv::Find(mStart, mEnd, aType);
VerifyOrExit(tlv != nullptr);
mStart = tlv->GetNext();
exit:
return tlv;
}
const NetworkDataTlv *TlvIterator::Iterate(NetworkDataTlv::Type aType, bool aStable)
{
const NetworkDataTlv *tlv = NetworkDataTlv::Find(mStart, mEnd, aType, aStable);
VerifyOrExit(tlv != nullptr);
mStart = tlv->GetNext();
exit:
return tlv;
}
} // namespace NetworkData
} // namespace ot
+346 -40
View File
@@ -68,21 +68,11 @@ OT_TOOL_PACKED_BEGIN
class NetworkDataTlv
{
public:
/**
* This method initializes TLV.
*
*/
void Init(void)
{
mType = 0;
mLength = 0;
}
/**
* Thread Network Data Type values.
*
*/
enum Type
enum Type : uint8_t
{
kTypeHasRoute = 0, ///< Has Route TLV
kTypePrefix = 1, ///< Prefix TLV
@@ -93,6 +83,16 @@ public:
kTypeServer = 6, ///< Server TLV
};
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
mType = 0;
mLength = 0;
}
/**
* This method returns the Type value.
*
@@ -209,6 +209,138 @@ public:
*/
void SetStable(void) { mType |= kStableMask; }
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given type.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType)
{
return const_cast<NetworkDataTlv *>(
Find(const_cast<const NetworkDataTlv *>(aStart), const_cast<const NetworkDataTlv *>(aEnd), aType));
}
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given type.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
static const NetworkDataTlv *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, Type aType);
/**
* This template static method searches in a given sequence of TLVs to find the first TLV with a given type.
*
* @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd)
{
return static_cast<TlvType *>(Find(aStart, aEnd, TlvType::kType));
}
/**
* This template static method searches in a given sequence of TLVs to find the first TLV with a given type.
*
* @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename TlvType> static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
{
return static_cast<const TlvType *>(Find(aStart, aEnd, TlvType::kType));
}
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and stable
* flag.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
static NetworkDataTlv *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, Type aType, bool aStable)
{
return const_cast<NetworkDataTlv *>(
Find(const_cast<const NetworkDataTlv *>(aStart), const_cast<const NetworkDataTlv *>(aEnd), aType, aStable));
}
/**
* This static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and stable
* flag.
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aType The TLV type to find.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
static const NetworkDataTlv *Find(const NetworkDataTlv *aStart,
const NetworkDataTlv *aEnd,
Type aType,
bool aStable);
/**
* This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and
* stable flag.
*
* @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename TlvType> static TlvType *Find(NetworkDataTlv *aStart, NetworkDataTlv *aEnd, bool aStable)
{
return static_cast<TlvType *>(Find(aStart, aEnd, TlvType::kType, aStable));
}
/**
* This template static method searches in a given sequence of TLVs to find the first TLV with a given TLV type and
* stable flag.
*
* @tparam TlvType The TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @param[in] aStart A pointer to the start of the sequence of TLVs to search within.
* @param[in] aEnd A pointer to the end of the sequence of TLVs.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename TlvType>
static const TlvType *Find(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd, bool aStable)
{
return static_cast<const TlvType *>(Find(aStart, aEnd, TlvType::kType, aStable));
}
private:
enum
{
@@ -324,10 +456,7 @@ OT_TOOL_PACKED_BEGIN
class HasRouteTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeHasRoute, ///< The TLV Type.
};
static constexpr Type kType = kTypeHasRoute; ///< The TLV Type.
/**
* This method initializes the TLV.
@@ -426,10 +555,7 @@ OT_TOOL_PACKED_BEGIN
class PrefixTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypePrefix, ///< The TLV Type.
};
static constexpr Type kType = kTypePrefix; ///< The TLV Type.
/**
* This method initializes the TLV.
@@ -533,7 +659,7 @@ public:
* @param[in] aPrefixLength The prefix length pointed to by @p aPrefix (in bits).
*
* @retval TRUE The TLV's Prefix is equal to @p aPrefix.
* @retval FALSE The TLV's Prefix is not euqal @p aPrefix.
* @retval FALSE The TLV's Prefix is not equal @p aPrefix.
*
*/
bool IsEqual(const uint8_t *aPrefix, uint8_t aPrefixLength) const
@@ -587,6 +713,110 @@ public:
SetLength(sizeof(*this) - sizeof(NetworkDataTlv) + Ip6::Prefix::SizeForLength(mPrefixLength) + aLength);
}
/**
* This template method searches in the sub-TLVs to find the first one matching a given TLV type.
*
* @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename SubTlvType> SubTlvType *FindSubTlv(void)
{
return static_cast<SubTlvType *>(FindSubTlv(SubTlvType::kType));
}
/**
* This template method searches in the sub-TLVs to find the first one matching a given TLV Type.
*
* @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename SubTlvType> const SubTlvType *FindSubTlv(void) const
{
return static_cast<const SubTlvType *>(FindSubTlv(SubTlvType::kType));
}
/**
* This template method searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
*
* @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename SubTlvType> SubTlvType *FindSubTlv(bool aStable)
{
return static_cast<SubTlvType *>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
}
/**
* This template method searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
*
* @tparam SubTlvType The sub-TLV type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
template <typename SubTlvType> const SubTlvType *FindSubTlv(bool aStable) const
{
return static_cast<const SubTlvType *>(FindSubTlv(static_cast<Type>(SubTlvType::kType), aStable));
}
/**
* This method searches in the sub-TLVs to find the first one matching a given TLV type.
*
* @param[in] aType The sub-TLV type to search for.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
NetworkDataTlv *FindSubTlv(Type aType)
{
return const_cast<NetworkDataTlv *>(const_cast<const PrefixTlv *>(this)->FindSubTlv(aType));
}
/**
* This method searches in the sub-TLVs to find the first one matching a given TLV type.
*
* @param[in] aType The sub-TLV type to search for.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
const NetworkDataTlv *FindSubTlv(Type aType) const;
/**
* This method searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
*
* @param[in] aType The sub-TLV type to search for.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
NetworkDataTlv *FindSubTlv(Type aType, bool aStable)
{
return const_cast<NetworkDataTlv *>(const_cast<const PrefixTlv *>(this)->FindSubTlv(aType, aStable));
}
/**
* This method searches in the sub-TLVs to find the first one matching a given TLV type and stable flag.
*
* @param[in] aType The sub-TLV type to search for.
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the TLV if found, or nullptr if not found.
*
*/
const NetworkDataTlv *FindSubTlv(Type aType, bool aStable) const;
/**
* This static method calculates the total size (number of bytes) of a Prefix TLV with a given Prefix Length value.
*
@@ -789,10 +1019,7 @@ OT_TOOL_PACKED_BEGIN
class BorderRouterTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeBorderRouter, ///< The TLV Type.
};
static constexpr Type kType = kTypeBorderRouter; ///< The TLV Type.
/**
* This method initializes the TLV.
@@ -894,10 +1121,7 @@ OT_TOOL_PACKED_BEGIN
class ContextTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeContext, ///< The TLV Type.
};
static constexpr Type kType = kTypeContext; ///< The TLV Type.
/**
* This method initializes the Context TLV.
@@ -971,10 +1195,7 @@ OT_TOOL_PACKED_BEGIN
class CommissioningDataTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeCommissioningData, ///< The TLV Type.
};
static constexpr Type kType = kTypeCommissioningData; ///< The TLV Type.
/**
* This method initializes the TLV.
@@ -996,10 +1217,7 @@ OT_TOOL_PACKED_BEGIN
class ServiceTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeService, ///< The TLV Type.
};
static constexpr Type kType = kTypeService; ///< The TLV Type.
enum : uint32_t
{
@@ -1205,10 +1423,7 @@ OT_TOOL_PACKED_BEGIN
class ServerTlv : public NetworkDataTlv
{
public:
enum
{
kType = kTypeServer, ///< The TLV Type.
};
static constexpr Type kType = kTypeServer; ///< The TLV Type.
/**
* This method initializes the Server TLV.
@@ -1298,6 +1513,97 @@ private:
uint16_t mServer16;
} OT_TOOL_PACKED_END;
/**
* This class represents a Network Data TLV iterator.
*
*/
class TlvIterator
{
public:
/**
* This constructor initializes the `TlvIterator` to iterate over a given sequence of TLVs.
*
* @param[in] aStart A pointer to the start of the TLV sequence.
* @param[in] aEnd A pointer to the end of the TLV sequence.
*
*/
TlvIterator(const NetworkDataTlv *aStart, const NetworkDataTlv *aEnd)
: mStart(aStart)
, mEnd(aEnd)
{
}
/**
* This constructor initializes the `TlvIterator` to iterate over TLVs from a given buffer.
*
* @param[in] aBuffer A pointer to a buffer containing the TLVs.
* @param[in] aLength The length (number of bytes) of @p aBuffer.
*
*/
TlvIterator(const uint8_t *aBuffer, uint8_t aLength)
: TlvIterator(reinterpret_cast<const NetworkDataTlv *>(aBuffer),
reinterpret_cast<const NetworkDataTlv *>(aBuffer + aLength))
{
}
/**
* This constructor initializes the `TlvIterator` to iterate over sub-TLVs of a given Prefix TLV.
*
* @param[in] aPrefixTlv A Prefix TLV to iterate over its sub-TLVs.
*
*/
explicit TlvIterator(const PrefixTlv &aPrefixTlv)
: TlvIterator(aPrefixTlv.GetSubTlvs(), aPrefixTlv.GetNext())
{
}
/**
* This constructor initializes the `TlvIterator` to iterate over sub-TLVs of a given Service TLV.
*
* @param[in] aServiceTlv A Service TLV to iterate over its sub-TLVs.
*
*/
explicit TlvIterator(const ServiceTlv &aServiceTlv)
: TlvIterator(aServiceTlv.GetSubTlvs(), aServiceTlv.GetNext())
{
}
/**
* This template method iterates to the next TLV with a given type.
*
* @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @returns A pointer to the next TLV, or nullptr if it can not be found.
*
*/
template <typename TlvType> const TlvType *Iterate(void)
{
return static_cast<const TlvType *>(Iterate(TlvType::kType));
}
/**
* This template method iterates to the next TLV with a given type and stable flag.
*
* @tparam TlvType The TLV Type to search for (MUST be a sub-class of `NetworkDataTlv`).
*
* @param[in] aStable TRUE to find a stable TLV, FALSE to find a TLV not marked as stable.
*
* @returns A pointer to the next TLV, or nullptr if it can not be found.
*
*/
template <typename TlvType> const TlvType *Iterate(bool aStable)
{
return static_cast<const TlvType *>(Iterate(TlvType::kType, aStable));
}
private:
const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType);
const NetworkDataTlv *Iterate(NetworkDataTlv::Type aType, bool aStable);
const NetworkDataTlv *mStart;
const NetworkDataTlv *mEnd;
};
/**
* @}
*