From 29d7e69f23a66e28b4c5d0c648f07ca581f4fc50 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 21 Apr 2020 10:42:33 -0700 Subject: [PATCH] [dataset] add GetTlv(), and SetTlv() for simple TLVs (#4856) This commit adds helper method `MeshCoP::Tlv::FindTlv()` to search within a given sequence of TLVs for a specific TLV type. This is used to simplify `Dataset::GetTlv()` and provide a template version `GetTlv()`. This commit also adds new flavors of `SetTlv()` for simple TLVs, i.e, TLVs with a single value which is either an `uint16_t` or `uint32_t` value or can be treated a data blob. --- src/core/meshcop/dataset.cpp | 148 ++++++----------- src/core/meshcop/dataset.hpp | 61 ++++++- src/core/meshcop/dataset_local.cpp | 2 +- src/core/meshcop/dataset_manager.cpp | 8 +- src/core/meshcop/dataset_manager_ftd.cpp | 78 +++------ src/core/meshcop/joiner_router.cpp | 8 +- src/core/meshcop/meshcop_tlvs.cpp | 25 +++ src/core/meshcop/meshcop_tlvs.hpp | 198 ++++++++++++++++++++++- src/core/thread/network_data_leader.cpp | 13 +- 9 files changed, 366 insertions(+), 175 deletions(-) diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index 49ef09525..90f49ab7e 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -37,6 +37,7 @@ #include #include "common/code_utils.hpp" +#include "common/encoding.hpp" #include "common/instance.hpp" #include "common/locator-getters.hpp" #include "common/logging.hpp" @@ -47,6 +48,9 @@ namespace ot { namespace MeshCoP { +using ot::Encoding::BigEndian::HostSwap16; +using ot::Encoding::BigEndian::HostSwap32; + Dataset::Dataset(Type aType) : mUpdateTime(0) , mLength(0) @@ -75,44 +79,9 @@ exit: return rval; } -Tlv *Dataset::GetTlv(Tlv::Type aType) -{ - Tlv *cur = reinterpret_cast(mTlvs); - Tlv *end = reinterpret_cast(mTlvs + mLength); - Tlv *rval = NULL; - - while (cur < end) - { - if (cur->GetType() == aType) - { - ExitNow(rval = cur); - } - - cur = cur->GetNext(); - } - -exit: - return rval; -} - const Tlv *Dataset::GetTlv(Tlv::Type aType) const { - const Tlv *cur = reinterpret_cast(mTlvs); - const Tlv *end = reinterpret_cast(mTlvs + mLength); - const Tlv *rval = NULL; - - while (cur < end) - { - if (cur->GetType() == aType) - { - ExitNow(rval = cur); - } - - cur = cur->GetNext(); - } - -exit: - return rval; + return Tlv::FindTlv(mTlvs, mLength, aType); } void Dataset::ConvertTo(otOperationalDataset &aDataset) const @@ -230,10 +199,8 @@ void Dataset::ConvertTo(otOperationalDataset &aDataset) const } default: - { break; } - } cur = cur->GetNext(); } @@ -259,7 +226,7 @@ otError Dataset::SetFrom(const otOperationalDataset &aDataset) if (aDataset.mComponents.mIsActiveTimestampPresent) { - MeshCoP::ActiveTimestampTlv tlv; + ActiveTimestampTlv tlv; tlv.Init(); tlv.SetSeconds(aDataset.mActiveTimestamp); tlv.SetTicks(0); @@ -268,7 +235,7 @@ otError Dataset::SetFrom(const otOperationalDataset &aDataset) if (aDataset.mComponents.mIsPendingTimestampPresent) { - MeshCoP::PendingTimestampTlv tlv; + PendingTimestampTlv tlv; tlv.Init(); tlv.SetSeconds(aDataset.mPendingTimestamp); tlv.SetTicks(0); @@ -277,15 +244,12 @@ otError Dataset::SetFrom(const otOperationalDataset &aDataset) if (aDataset.mComponents.mIsDelayPresent) { - MeshCoP::DelayTimerTlv tlv; - tlv.Init(); - tlv.SetDelayTimer(aDataset.mDelay); - SetTlv(tlv); + SetUint32Tlv(Tlv::kDelayTimer, aDataset.mDelay); } if (aDataset.mComponents.mIsChannelPresent) { - MeshCoP::ChannelTlv tlv; + ChannelTlv tlv; tlv.Init(); tlv.SetChannel(aDataset.mChannel); SetTlv(tlv); @@ -293,7 +257,7 @@ otError Dataset::SetFrom(const otOperationalDataset &aDataset) if (aDataset.mComponents.mIsChannelMaskPresent) { - MeshCoP::ChannelMaskTlv tlv; + ChannelMaskTlv tlv; tlv.Init(); tlv.SetChannelMask(aDataset.mChannelMask); SetTlv(tlv); @@ -301,55 +265,39 @@ otError Dataset::SetFrom(const otOperationalDataset &aDataset) if (aDataset.mComponents.mIsExtendedPanIdPresent) { - MeshCoP::ExtendedPanIdTlv tlv; - tlv.Init(); - tlv.SetExtendedPanId(static_cast(aDataset.mExtendedPanId)); - SetTlv(tlv); + SetTlv(Tlv::kExtendedPanId, &aDataset.mExtendedPanId, sizeof(Mac::ExtendedPanId)); } if (aDataset.mComponents.mIsMeshLocalPrefixPresent) { - MeshCoP::MeshLocalPrefixTlv tlv; - tlv.Init(); - tlv.SetMeshLocalPrefix(static_cast(aDataset.mMeshLocalPrefix)); - SetTlv(tlv); + SetTlv(Tlv::kMeshLocalPrefix, &aDataset.mMeshLocalPrefix, sizeof(Mle::MeshLocalPrefix)); } if (aDataset.mComponents.mIsMasterKeyPresent) { - MeshCoP::NetworkMasterKeyTlv tlv; - tlv.Init(); - tlv.SetNetworkMasterKey(static_cast(aDataset.mMasterKey)); - SetTlv(tlv); + SetTlv(Tlv::kNetworkMasterKey, &aDataset.mMasterKey, sizeof(MasterKey)); } if (aDataset.mComponents.mIsNetworkNamePresent) { - MeshCoP::NetworkNameTlv tlv; - tlv.Init(); - tlv.SetNetworkName(static_cast(aDataset.mNetworkName).GetAsData()); - SetTlv(tlv); + Mac::NameData nameData = static_cast(aDataset.mNetworkName).GetAsData(); + + SetTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength()); } if (aDataset.mComponents.mIsPanIdPresent) { - MeshCoP::PanIdTlv tlv; - tlv.Init(); - tlv.SetPanId(aDataset.mPanId); - SetTlv(tlv); + SetUint16Tlv(Tlv::kPanId, aDataset.mPanId); } if (aDataset.mComponents.mIsPskcPresent) { - MeshCoP::PskcTlv tlv; - tlv.Init(); - tlv.SetPskc(static_cast(aDataset.mPskc)); - SetTlv(tlv); + SetTlv(Tlv::kPskc, &aDataset.mPskc, sizeof(Pskc)); } if (aDataset.mComponents.mIsSecurityPolicyPresent) { - MeshCoP::SecurityPolicyTlv tlv; + SecurityPolicyTlv tlv; tlv.Init(); tlv.SetRotationTime(aDataset.mSecurityPolicy.mRotationTime); tlv.SetFlags(aDataset.mSecurityPolicy.mFlags); @@ -367,13 +315,13 @@ const Timestamp *Dataset::GetTimestamp(void) const if (mType == kActive) { - const ActiveTimestampTlv *tlv = static_cast(GetTlv(Tlv::kActiveTimestamp)); + const ActiveTimestampTlv *tlv = GetTlv(); VerifyOrExit(tlv != NULL, OT_NOOP); timestamp = static_cast(tlv); } else { - const PendingTimestampTlv *tlv = static_cast(GetTlv(Tlv::kPendingTimestamp)); + const PendingTimestampTlv *tlv = GetTlv(); VerifyOrExit(tlv != NULL, OT_NOOP); timestamp = static_cast(tlv); } @@ -384,44 +332,35 @@ exit: void Dataset::SetTimestamp(const Timestamp &aTimestamp) { - if (mType == kActive) - { - ActiveTimestampTlv activeTimestamp; - activeTimestamp.Init(); - *static_cast(&activeTimestamp) = aTimestamp; - SetTlv(activeTimestamp); - } - else - { - PendingTimestampTlv pendingTimestamp; - pendingTimestamp.Init(); - *static_cast(&pendingTimestamp) = aTimestamp; - SetTlv(pendingTimestamp); - } + SetTlv((mType == kActive) ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp, &aTimestamp, sizeof(Timestamp)); } -otError Dataset::SetTlv(const Tlv &aTlv) +otError Dataset::SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength) { otError error = OT_ERROR_NONE; uint16_t bytesAvailable = sizeof(mTlvs) - mLength; - Tlv * old = GetTlv(aTlv.GetType()); + Tlv * old = GetTlv(aType); + Tlv tlv; if (old != NULL) { bytesAvailable += sizeof(Tlv) + old->GetLength(); } - VerifyOrExit(sizeof(Tlv) + aTlv.GetLength() <= bytesAvailable, error = OT_ERROR_NO_BUFS); + VerifyOrExit(sizeof(Tlv) + aLength <= bytesAvailable, error = OT_ERROR_NO_BUFS); - // remove old TLV if (old != NULL) { Remove(reinterpret_cast(old), sizeof(Tlv) + old->GetLength()); } - // add new TLV - memcpy(mTlvs + mLength, &aTlv, sizeof(Tlv) + aTlv.GetLength()); - mLength += sizeof(Tlv) + aTlv.GetLength(); + tlv.SetType(aType); + tlv.SetLength(aLength); + memcpy(mTlvs + mLength, &tlv, sizeof(Tlv)); + mLength += sizeof(Tlv); + + memcpy(mTlvs + mLength, aValue, aLength); + mLength += aLength; mUpdateTime = TimerMilli::GetNow(); @@ -429,6 +368,25 @@ exit: return error; } +otError Dataset::SetTlv(const Tlv &aTlv) +{ + return SetTlv(aTlv.GetType(), aTlv.GetValue(), aTlv.GetLength()); +} + +otError Dataset::SetUint16Tlv(Tlv::Type aType, uint16_t aValue) +{ + uint16_t value16 = HostSwap16(aValue); + + return SetTlv(aType, &value16, sizeof(uint16_t)); +} + +otError Dataset::SetUint32Tlv(Tlv::Type aType, uint32_t aValue) +{ + uint32_t value32 = HostSwap32(aValue); + + return SetTlv(aType, &value32, sizeof(uint32_t)); +} + otError Dataset::Set(const Message &aMessage, uint16_t aOffset, uint8_t aLength) { otError error = OT_ERROR_NONE; @@ -600,10 +558,8 @@ otError Dataset::ApplyConfiguration(Instance &aInstance, bool *aIsMasterKeyUpdat } default: - { break; } - } cur = cur->GetNext(); } diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp index 375094159..46f488734 100644 --- a/src/core/meshcop/dataset.hpp +++ b/src/core/meshcop/dataset.hpp @@ -103,7 +103,7 @@ public: * @returns A pointer to the TLV or NULL if none is found. * */ - Tlv *GetTlv(Tlv::Type aType); + Tlv *GetTlv(Tlv::Type aType) { return const_cast(const_cast(this)->GetTlv(aType)); } /** * This method returns a pointer to the TLV with a given type. @@ -115,6 +115,28 @@ public: */ const Tlv *GetTlv(Tlv::Type aType) const; + /** + * This template method returns a pointer to the TLV with a given template type `TlvType` + * + * @returns A pointer to the TLV or NULL if none is found. + * + */ + template TlvType *GetTlv(void) + { + return static_cast(GetTlv(static_cast(TlvType::kType))); + } + + /** + * This template method returns a pointer to the TLV with a given template type `TlvType` + * + * @returns A pointer to the TLV or NULL if none is found. + * + */ + template const TlvType *GetTlv(void) const + { + return static_cast(GetTlv(static_cast(TlvType::kType))); + } + /** * This method returns a pointer to the byte representation of the Dataset. * @@ -190,6 +212,43 @@ public: */ otError SetTlv(const Tlv &aTlv); + /** + * This method sets a TLV with a given TLV Type and Value. + * + * @param[in] aType The TLV Type. + * @param[in] aValue A pointer to TLV Value. + * @param[in] aLength The TLV Length in bytes (length of @p aValue). + * + * @retval OT_ERROR_NONE Successfully set the TLV. + * @retval OT_ERROR_NO_BUFS Could not set the TLV due to insufficient buffer space. + * + */ + otError SetTlv(Tlv::Type aType, const void *aValue, uint8_t aLength); + + /** + * This method sets a TLV with a given TLV Type and a `uint16_t` Value. + * + * @param[in] aType The TLV Type. + * @param[in] aValue The TLV value (as `uint16_t`). + * + * @retval OT_ERROR_NONE Successfully set the TLV. + * @retval OT_ERROR_NO_BUFS Could not set the TLV due to insufficient buffer space. + * + */ + otError SetUint16Tlv(Tlv::Type aType, uint16_t aValue); + + /** + * This method sets a TLV with a given TLV Type and a `uint32_t` Value. + * + * @param[in] aType The TLV Type. + * @param[in] aValue The TLV value (as `uint32_t`). + * + * @retval OT_ERROR_NONE Successfully set the TLV. + * @retval OT_ERROR_NO_BUFS Could not set the TLV due to insufficient buffer space. + * + */ + otError SetUint32Tlv(Tlv::Type aType, uint32_t aValue); + /** * This method sets the Dataset using TLVs stored in a message buffer. * diff --git a/src/core/meshcop/dataset_local.cpp b/src/core/meshcop/dataset_local.cpp index e33ca1d88..86537d25a 100644 --- a/src/core/meshcop/dataset_local.cpp +++ b/src/core/meshcop/dataset_local.cpp @@ -105,7 +105,7 @@ otError DatasetLocal::Read(Dataset &aDataset) const } else { - delayTimer = static_cast(aDataset.GetTlv(Tlv::kDelayTimer)); + delayTimer = aDataset.GetTlv(); VerifyOrExit(delayTimer, OT_NOOP); elapsed = TimerMilli::GetNow() - mUpdateTime; diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index 21cd3b886..6ca0d4ba0 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -218,7 +218,7 @@ otError DatasetManager::GetChannelMask(Mac::ChannelMask &aChannelMask) const SuccessOrExit(error = mLocal.Read(dataset)); - channelMaskTlv = static_cast(dataset.GetTlv(MeshCoP::Tlv::kChannelMask)); + channelMaskTlv = dataset.GetTlv(); VerifyOrExit(channelMaskTlv != NULL, error = OT_ERROR_NOT_FOUND); VerifyOrExit((mask = channelMaskTlv->GetChannelMask()) != 0, OT_NOOP); @@ -241,7 +241,7 @@ void DatasetManager::HandleTimer(void) Dataset dataset(Dataset::kPending); Get().Read(dataset); - const ActiveTimestampTlv *tlv = static_cast(dataset.GetTlv(Tlv::kActiveTimestamp)); + const ActiveTimestampTlv *tlv = dataset.GetTlv(); const Timestamp * pendingActiveTimestamp = static_cast(tlv); if (pendingActiveTimestamp != NULL && mLocal.Compare(pendingActiveTimestamp) == 0) @@ -790,7 +790,7 @@ void PendingDataset::StartDelayTimer(void) mDelayTimer.Stop(); - if ((delayTimer = static_cast(dataset.GetTlv(Tlv::kDelayTimer))) != NULL) + if ((delayTimer = dataset.GetTlv()) != NULL) { uint32_t delay = delayTimer->GetDelayTimer(); @@ -819,7 +819,7 @@ void PendingDataset::HandleDelayTimer(void) // if the Delay Timer value is larger than what our Timer implementation can handle, we have to compute // the remainder and wait some more. - if ((delayTimer = static_cast(dataset.GetTlv(Tlv::kDelayTimer))) != NULL) + if ((delayTimer = dataset.GetTlv()) != NULL) { uint32_t elapsed = mDelayTimer.GetFireTime() - dataset.GetUpdateTime(); uint32_t delay = delayTimer->GetDelayTimer(); diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index ea6a9795c..e0c9e18f3 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -366,8 +366,7 @@ otError ActiveDataset::GenerateLocal(void) mLocal.Read(dataset); - // Active Timestamp - if (dataset.GetTlv(Tlv::kActiveTimestamp) == NULL) + if (dataset.GetTlv() == NULL) { ActiveTimestampTlv activeTimestampTlv; activeTimestampTlv.Init(); @@ -376,8 +375,7 @@ otError ActiveDataset::GenerateLocal(void) dataset.SetTlv(activeTimestampTlv); } - // Channel - if (dataset.GetTlv(Tlv::kChannel) == NULL) + if (dataset.GetTlv() == NULL) { ChannelTlv tlv; tlv.Init(); @@ -385,8 +383,7 @@ otError ActiveDataset::GenerateLocal(void) dataset.SetTlv(tlv); } - // channelMask - if (dataset.GetTlv(Tlv::kChannelMask) == NULL) + if (dataset.GetTlv() == NULL) { ChannelMaskTlv tlv; tlv.Init(); @@ -394,62 +391,39 @@ otError ActiveDataset::GenerateLocal(void) dataset.SetTlv(tlv); } - // Extended PAN ID - if (dataset.GetTlv(Tlv::kExtendedPanId) == NULL) + if (dataset.GetTlv() == NULL) { - ExtendedPanIdTlv tlv; - tlv.Init(); - tlv.SetExtendedPanId(Get().GetExtendedPanId()); - dataset.SetTlv(tlv); + dataset.SetTlv(Tlv::kExtendedPanId, &Get().GetExtendedPanId(), sizeof(Mac::ExtendedPanId)); } - // Mesh-Local Prefix - if (dataset.GetTlv(Tlv::kMeshLocalPrefix) == NULL) + if (dataset.GetTlv() == NULL) { - MeshLocalPrefixTlv tlv; - tlv.Init(); - tlv.SetMeshLocalPrefix(Get().GetMeshLocalPrefix()); - dataset.SetTlv(tlv); + dataset.SetTlv(Tlv::kMeshLocalPrefix, &Get().GetMeshLocalPrefix(), + sizeof(Mle::MeshLocalPrefix)); } - // Master Key - if (dataset.GetTlv(Tlv::kNetworkMasterKey) == NULL) + if (dataset.GetTlv() == NULL) { - NetworkMasterKeyTlv tlv; - tlv.Init(); - tlv.SetNetworkMasterKey(Get().GetMasterKey()); - dataset.SetTlv(tlv); + dataset.SetTlv(Tlv::kNetworkMasterKey, &Get().GetMasterKey(), sizeof(MasterKey)); } - // Network Name - if (dataset.GetTlv(Tlv::kNetworkName) == NULL) + if (dataset.GetTlv() == NULL) { - NetworkNameTlv tlv; - tlv.Init(); - tlv.SetNetworkName(Get().GetNetworkName().GetAsData()); - dataset.SetTlv(tlv); + Mac::NameData nameData = Get().GetNetworkName().GetAsData(); + + dataset.SetTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength()); } - // Pan ID - if (dataset.GetTlv(Tlv::kPanId) == NULL) + if (dataset.GetTlv() == NULL) { - PanIdTlv tlv; - tlv.Init(); - tlv.SetPanId(Get().GetPanId()); - dataset.SetTlv(tlv); + dataset.SetUint16Tlv(Tlv::kPanId, Get().GetPanId()); } - // PSKc - if (dataset.GetTlv(Tlv::kPskc) == NULL) + if (dataset.GetTlv() == NULL) { - PskcTlv tlv; - - tlv.Init(); - if (Get().IsPskcSet()) { - // use configured PSKc - tlv.SetPskc(Get().GetPskc()); + dataset.SetTlv(Tlv::kPskc, &Get().GetPskc(), sizeof(Pskc)); } else { @@ -457,14 +431,11 @@ otError ActiveDataset::GenerateLocal(void) Pskc pskc; SuccessOrExit(error = pskc.GenerateRandom()); - tlv.SetPskc(pskc); + dataset.SetTlv(Tlv::kPskc, &pskc, sizeof(Pskc)); } - - dataset.SetTlv(tlv); } - // Security Policy - if (dataset.GetTlv(Tlv::kSecurityPolicy) == NULL) + if (dataset.GetTlv() == NULL) { SecurityPolicyTlv tlv; tlv.Init(); @@ -536,9 +507,8 @@ exit: void PendingDataset::ApplyActiveDataset(const Timestamp &aTimestamp, Coap::Message &aMessage) { - uint16_t offset = aMessage.GetOffset(); - Dataset dataset(mLocal.GetType()); - DelayTimerTlv delayTimer; + uint16_t offset = aMessage.GetOffset(); + Dataset dataset(mLocal.GetType()); VerifyOrExit(Get().IsAttached(), OT_NOOP); @@ -558,9 +528,7 @@ void PendingDataset::ApplyActiveDataset(const Timestamp &aTimestamp, Coap::Messa } // add delay timer tlv - delayTimer.Init(); - delayTimer.SetDelayTimer(Get().GetDelayTimerMinimal()); - dataset.SetTlv(delayTimer); + dataset.SetUint32Tlv(Tlv::kDelayTimer, Get().GetDelayTimerMinimal()); // add pending timestamp tlv dataset.SetTimestamp(aTimestamp); diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index 0fbc37653..2b62d2fa1 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -370,7 +370,7 @@ Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void) Get().Read(dataset); - if ((tlv = dataset.GetTlv(Tlv::kActiveTimestamp)) != NULL) + if ((tlv = dataset.GetTlv()) != NULL) { SuccessOrExit(error = tlv->AppendTo(*message)); } @@ -381,7 +381,7 @@ Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void) SuccessOrExit(error = activeTimestamp.AppendTo(*message)); } - if ((tlv = dataset.GetTlv(Tlv::kChannelMask)) != NULL) + if ((tlv = dataset.GetTlv()) != NULL) { SuccessOrExit(error = tlv->AppendTo(*message)); } @@ -392,7 +392,7 @@ Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void) SuccessOrExit(error = channelMask.AppendTo(*message)); } - if ((tlv = dataset.GetTlv(Tlv::kPskc)) != NULL) + if ((tlv = dataset.GetTlv()) != NULL) { SuccessOrExit(error = tlv->AppendTo(*message)); } @@ -403,7 +403,7 @@ Coap::Message *JoinerRouter::PrepareJoinerEntrustMessage(void) SuccessOrExit(error = pskc.AppendTo(*message)); } - if ((tlv = dataset.GetTlv(Tlv::kSecurityPolicy)) != NULL) + if ((tlv = dataset.GetTlv()) != NULL) { SuccessOrExit(error = tlv->AppendTo(*message)); } diff --git a/src/core/meshcop/meshcop_tlvs.cpp b/src/core/meshcop/meshcop_tlvs.cpp index 174c47abb..9d91b09cd 100644 --- a/src/core/meshcop/meshcop_tlvs.cpp +++ b/src/core/meshcop/meshcop_tlvs.cpp @@ -83,6 +83,31 @@ bool Tlv::IsValid(const Tlv &aTlv) return rval; } +const Tlv *Tlv::FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength, Type aType) +{ + const Tlv *tlv; + const Tlv *end = reinterpret_cast(aTlvsStart + aTlvsLength); + + for (tlv = reinterpret_cast(aTlvsStart); tlv < end; tlv = tlv->GetNext()) + { + VerifyOrExit((tlv + 1) <= end, tlv = NULL); + VerifyOrExit(!tlv->IsExtended() || + (reinterpret_cast(tlv) + 1 <= reinterpret_cast(end)), + tlv = NULL); + VerifyOrExit(tlv->GetNext() <= end, tlv = NULL); + + if (tlv->GetType() == aType) + { + ExitNow(); + } + } + + tlv = NULL; + +exit: + return tlv; +} + Mac::NameData NetworkNameTlv::GetNetworkName(void) const { uint8_t len = GetLength(); diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp index 9f689afe1..221544b07 100644 --- a/src/core/meshcop/meshcop_tlvs.hpp +++ b/src/core/meshcop/meshcop_tlvs.hpp @@ -190,6 +190,63 @@ public: */ static bool IsValid(const Tlv &aTlv); + /** + * This static method searches in a given sequence of TLVs to find the first TLV with a given template Type. + * + * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within. + * @param[in] aTlvsLength The length (number of bytes) in TLV sequence. + * @param[in] aType The TLV Type to search for. + * + * @returns A pointer to the TLV if found, or NULL if not found. + * + */ + static Tlv *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength, Type aType) + { + return const_cast(FindTlv(const_cast(aTlvsStart), aTlvsLength, aType)); + } + + /** + * This static method searches in a given sequence of TLVs to find the first TLV with a given template Type. + * + * @param[in] aTlvsStart A pointer to the start of the sequence of TLVs to search within. + * @param[in] aTlvsLength The length (number of bytes) in TLV sequence. + * @param[in] aType The TLV Type to search for. + * + * @returns A pointer to the TLV if found, or NULL if not found. + * + */ + static const Tlv *FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength, 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] aTlvsStart A pointer to the start of the sequence of TLVs to search within. + * @param[in] aTlvsLength The length (number of bytes) in TLV sequence. + * + * @returns A pointer to the TLV if found, or NULL if not found. + * + */ + template static TlvType *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength) + { + return static_cast(FindTlv(aTlvsStart, aTlvsLength, static_cast(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] aTlvsStart A pointer to the start of the sequence of TLVs to search within. + * @param[in] aTlvsLength The length (number of bytes) in TLV sequence. + * + * @returns A pointer to the TLV if found, or NULL if not found. + * + */ + template static const TlvType *FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength) + { + return static_cast(FindTlv(aTlvsStart, aTlvsLength, static_cast(TlvType::kType))); + } + } OT_TOOL_PACKED_END; /** @@ -225,6 +282,11 @@ OT_TOOL_PACKED_BEGIN class ChannelTlv : public Tlv { public: + enum + { + kType = kChannel, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -290,6 +352,11 @@ OT_TOOL_PACKED_BEGIN class PanIdTlv : public Tlv { public: + enum + { + kType = kPanId, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -337,6 +404,11 @@ OT_TOOL_PACKED_BEGIN class ExtendedPanIdTlv : public Tlv { public: + enum + { + kType = kExtendedPanId, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -384,6 +456,11 @@ OT_TOOL_PACKED_BEGIN class NetworkNameTlv : public Tlv { public: + enum + { + kType = kNetworkName, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -431,6 +508,11 @@ OT_TOOL_PACKED_BEGIN class PskcTlv : public Tlv { public: + enum + { + kType = kPskc, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -478,6 +560,11 @@ OT_TOOL_PACKED_BEGIN class NetworkMasterKeyTlv : public Tlv { public: + enum + { + kType = kNetworkMasterKey, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -525,6 +612,11 @@ OT_TOOL_PACKED_BEGIN class NetworkKeySequenceTlv : public Tlv { public: + enum + { + kType = kNetworkKeySequence, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -572,6 +664,11 @@ OT_TOOL_PACKED_BEGIN class MeshLocalPrefixTlv : public Tlv { public: + enum + { + kType = kMeshLocalPrefix, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -627,6 +724,11 @@ OT_TOOL_PACKED_BEGIN class SteeringDataTlv : public Tlv { public: + enum + { + kType = kSteeringData, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -760,6 +862,11 @@ OT_TOOL_PACKED_BEGIN class BorderAgentLocatorTlv : public Tlv { public: + enum + { + kType = kBorderAgentLocator, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -809,7 +916,8 @@ class CommissionerIdTlv : public Tlv public: enum { - kMaxLength = 64, ///< maximum length (bytes) + kType = kCommissionerId, ///< The TLV Type. + kMaxLength = 64, ///< maximum length (bytes) }; /** @@ -866,6 +974,11 @@ OT_TOOL_PACKED_BEGIN class CommissionerSessionIdTlv : public Tlv { public: + enum + { + kType = kCommissionerSessionId, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -913,6 +1026,11 @@ OT_TOOL_PACKED_BEGIN class SecurityPolicyTlv : public Tlv { public: + enum + { + kType = kSecurityPolicy, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -986,6 +1104,11 @@ OT_TOOL_PACKED_BEGIN class ActiveTimestampTlv : public Tlv, public Timestamp { public: + enum + { + kType = kActiveTimestamp, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1015,6 +1138,11 @@ OT_TOOL_PACKED_BEGIN class StateTlv : public Tlv { public: + enum + { + kType = kState, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1073,6 +1201,11 @@ OT_TOOL_PACKED_BEGIN class JoinerUdpPortTlv : public Tlv { public: + enum + { + kType = kJoinerUdpPort, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1120,6 +1253,11 @@ OT_TOOL_PACKED_BEGIN class PendingTimestampTlv : public Tlv, public Timestamp { public: + enum + { + kType = kPendingTimestamp, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1149,6 +1287,11 @@ OT_TOOL_PACKED_BEGIN class DelayTimerTlv : public Tlv { public: + enum + { + kType = kDelayTimer, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1374,6 +1517,11 @@ OT_TOOL_PACKED_BEGIN class ChannelMaskBaseTlv : public Tlv { public: + enum + { + kType = kChannelMask, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1472,6 +1620,11 @@ OT_TOOL_PACKED_BEGIN class EnergyListTlv : public Tlv { public: + enum + { + kType = kEnergyList, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1502,7 +1655,8 @@ class ProvisioningUrlTlv : public Tlv public: enum { - kMaxLength = OT_PROVISIONING_URL_MAX_SIZE, // Maximum number of chars in the Provisioning URL string. + kType = kProvisioningUrl, ///< The TLV Type. + kMaxLength = OT_PROVISIONING_URL_MAX_SIZE, ///< Maximum number of chars in the Provisioning URL string. }; /** @@ -1564,6 +1718,11 @@ OT_TOOL_PACKED_BEGIN class VendorNameTlv : public Tlv { public: + enum + { + kType = kVendorName, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1628,6 +1787,11 @@ OT_TOOL_PACKED_BEGIN class VendorModelTlv : public Tlv { public: + enum + { + kType = kVendorModel, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1692,6 +1856,11 @@ OT_TOOL_PACKED_BEGIN class VendorSwVersionTlv : public Tlv { public: + enum + { + kType = kVendorSwVersion, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1756,6 +1925,11 @@ OT_TOOL_PACKED_BEGIN class VendorDataTlv : public Tlv { public: + enum + { + kType = kVendorData, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -1820,6 +1994,11 @@ OT_TOOL_PACKED_BEGIN class VendorStackVersionTlv : public Tlv { public: + enum + { + kType = kVendorStackVersion, ///< The TLV Type. + }; + /** * Default constructor. * @@ -1981,6 +2160,11 @@ OT_TOOL_PACKED_BEGIN class UdpEncapsulationTlv : public ExtendedTlv { public: + enum + { + kType = MeshCoP::Tlv::kUdpEncapsulation, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -2061,6 +2245,11 @@ OT_TOOL_PACKED_BEGIN class DiscoveryRequestTlv : public Tlv { public: + enum + { + kType = kDiscoveryRequest, ///< The TLV Type. + }; + /** * This method initializes the TLV. * @@ -2148,6 +2337,11 @@ OT_TOOL_PACKED_BEGIN class DiscoveryResponseTlv : public Tlv { public: + enum + { + kType = kDiscoveryResponse, ///< The TLV Type. + }; + /** * This method initializes the TLV. * diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index 63e8dbb56..777471bf5 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -485,22 +485,11 @@ const MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aT { const MeshCoP::Tlv * rval = NULL; const NetworkDataTlv *commissioningDataTlv; - const MeshCoP::Tlv * cur; - const MeshCoP::Tlv * end; commissioningDataTlv = GetCommissioningData(); VerifyOrExit(commissioningDataTlv != NULL, OT_NOOP); - cur = reinterpret_cast(commissioningDataTlv->GetValue()); - end = reinterpret_cast(commissioningDataTlv->GetValue() + commissioningDataTlv->GetLength()); - - for (; cur < end; cur = cur->GetNext()) - { - if (cur->GetType() == aType) - { - ExitNow(rval = cur); - } - } + rval = MeshCoP::Tlv::FindTlv(commissioningDataTlv->GetValue(), commissioningDataTlv->GetLength(), aType); exit: return rval;