diff --git a/src/core/common/tlvs.cpp b/src/core/common/tlvs.cpp index a5ed15b45..2620b24e8 100644 --- a/src/core/common/tlvs.cpp +++ b/src/core/common/tlvs.cpp @@ -271,7 +271,7 @@ template Error Tlv::FindUintTlv(const Message &aMessage, uint8_t aType, template Error Tlv::FindUintTlv(const Message &aMessage, uint8_t aType, uint16_t &aValue); template Error Tlv::FindUintTlv(const Message &aMessage, uint8_t aType, uint32_t &aValue); -Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength) +Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint16_t aLength) { Error error; uint16_t offset; @@ -322,4 +322,32 @@ exit: return error; } +const Tlv *Tlv::FindTlv(const void *aTlvsStart, uint16_t aTlvsLength, uint8_t aType) +{ + const Tlv *tlv; + const Tlv *end = reinterpret_cast(reinterpret_cast(aTlvsStart) + aTlvsLength); + + for (tlv = reinterpret_cast(aTlvsStart); tlv < end; tlv = tlv->GetNext()) + { + VerifyOrExit((tlv + 1) <= end, tlv = nullptr); + + if (tlv->IsExtended()) + { + VerifyOrExit((As(tlv) + 1) <= As(end), tlv = nullptr); + } + + VerifyOrExit(tlv->GetNext() <= end, tlv = nullptr); + + if (tlv->GetType() == aType) + { + ExitNow(); + } + } + + tlv = nullptr; + +exit: + return tlv; +} + } // namespace ot diff --git a/src/core/common/tlvs.hpp b/src/core/common/tlvs.hpp index 79bd5bd62..9af6f4d40 100644 --- a/src/core/common/tlvs.hpp +++ b/src/core/common/tlvs.hpp @@ -39,6 +39,7 @@ #include #include +#include "common/const_cast.hpp" #include "common/encoding.hpp" #include "common/error.hpp" #include "common/type_traits.hpp" @@ -174,6 +175,9 @@ public: */ Error AppendTo(Message &aMessage) const; + //------------------------------------------------------------------------------------------------------------------ + // Static methods for reading/finding/appending TLVs in a `Message`. + /** * Reads a TLV's value in a message at a given offset expecting a minimum length for the value. * @@ -538,6 +542,68 @@ public: return AppendStringTlv(aMessage, StringTlvType::kType, StringTlvType::kMaxStringLength, aValue); } + //------------------------------------------------------------------------------------------------------------------ + // Static methods for finding TLVs within a sequence of TLVs. + + /** + * Searches in a given sequence of TLVs to find the first TLV of a given 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 the TLV sequence. + * @param[in] aType The TLV type to search for. + * + * @returns A pointer to the TLV within the TLV sequence if found, or `nullptr` if not found. + * + */ + static const Tlv *FindTlv(const void *aTlvsStart, uint16_t aTlvsLength, uint8_t aType); + + /** + * Searches in a given sequence of TLVs to find the first TLV of a given 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 the TLV sequence. + * @param[in] aType The TLV type to search for. + * + * @returns A pointer to the TLV within the TLV sequence if found, or `nullptr` if not found. + * + */ + static Tlv *FindTlv(void *aTlvsStart, uint16_t aTlvsLength, uint8_t aType) + { + return AsNonConst(FindTlv(AsConst(aTlvsStart), aTlvsLength, aType)); + } + + /** + * Searches in a given sequence of TLVs to find the first TLV with a give template `TlvType`. + * + * @tparam kTlvType The TLV 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. + * + * @returns A pointer to the TLV if found, or `nullptr` if not found. + * + */ + template static TlvType *Find(void *aTlvsStart, uint16_t aTlvsLength) + { + return static_cast(FindTlv(aTlvsStart, aTlvsLength, TlvType::kType)); + } + + /** + * Searches in a given sequence of TLVs to find the first TLV with a give template `TlvType`. + * + * @tparam kTlvType The TLV 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. + * + * @returns A pointer to the TLV if found, or `nullptr` if not found. + * + */ + template static const TlvType *Find(const void *aTlvsStart, uint16_t aTlvsLength) + { + return static_cast(FindTlv(aTlvsStart, aTlvsLength, TlvType::kType)); + } + protected: static const uint8_t kExtendedLength = 255; // Extended Length value. @@ -554,7 +620,7 @@ private: uint16_t mSize; }; - static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint8_t aLength); + static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint16_t aLength); static Error AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint8_t aLength); static Error ReadStringTlv(const Message &aMessage, uint16_t aOffset, uint8_t aMaxStringLength, char *aValue); static Error FindStringTlv(const Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, char *aValue); diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index 60aa0dae0..974b23e8a 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -179,7 +179,7 @@ exit: return rval; } -const Tlv *Dataset::GetTlv(Tlv::Type aType) const { return Tlv::FindTlv(mTlvs, mLength, aType); } +const Tlv *Dataset::GetTlv(Tlv::Type aType) const { return As(Tlv::FindTlv(mTlvs, mLength, aType)); } void Dataset::ConvertTo(Info &aDatasetInfo) const { diff --git a/src/core/meshcop/meshcop_tlvs.cpp b/src/core/meshcop/meshcop_tlvs.cpp index 0e643ac03..4bf5abc08 100644 --- a/src/core/meshcop/meshcop_tlvs.cpp +++ b/src/core/meshcop/meshcop_tlvs.cpp @@ -91,31 +91,6 @@ 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 = nullptr); - VerifyOrExit(!tlv->IsExtended() || - (reinterpret_cast(tlv) + 1 <= reinterpret_cast(end)), - tlv = nullptr); - VerifyOrExit(tlv->GetNext() <= end, tlv = nullptr); - - if (tlv->GetType() == aType) - { - ExitNow(); - } - } - - tlv = nullptr; - -exit: - return tlv; -} - 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 3eca8dc35..d675fbb1c 100644 --- a/src/core/meshcop/meshcop_tlvs.hpp +++ b/src/core/meshcop/meshcop_tlvs.hpp @@ -163,43 +163,6 @@ public: */ const Tlv *GetNext(void) const { return As(ot::Tlv::GetNext()); } - /** - * Reads the requested TLV out of @p aMessage. - * - * @param[in] aMessage A reference to the message. - * @param[in] aType The Type value to search for. - * @param[in] aMaxLength Maximum number of bytes to read. - * @param[out] aTlv A reference to the TLV that will be copied to. - * - * @retval kErrorNone Successfully copied the TLV. - * @retval kErrorNotFound Could not find the TLV with Type @p aType. - * - */ - static Error FindTlv(const Message &aMessage, Type aType, uint16_t aMaxLength, Tlv &aTlv) - { - return ot::Tlv::FindTlv(aMessage, static_cast(aType), aMaxLength, aTlv); - } - - /** - * Reads the requested TLV out of @p aMessage. - * - * Can be used independent of whether the read TLV (from message) is an Extended TLV or not. - * - * @tparam TlvType The TlvType to search for (must be a sub-class of `Tlv`). - * - * @param[in] aMessage A reference to the message. - * @param[out] aTlv A reference to the TLV that will be copied to. - * - * @retval kErrorNone Successfully copied the TLV. - * @retval kErrorNotFound Could not find the TLV with Type @p aType. - * - */ - - template static Error FindTlv(const Message &aMessage, TlvType &aTlv) - { - return ot::Tlv::FindTlv(aMessage, aTlv); - } - /** * Indicates whether a TLV appears to be well-formed. * @@ -210,63 +173,6 @@ public: */ static bool IsValid(const Tlv &aTlv); - /** - * 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 `nullptr` if not found. - * - */ - static Tlv *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength, Type aType) - { - return AsNonConst(FindTlv(AsConst(aTlvsStart), aTlvsLength, aType)); - } - - /** - * 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 `nullptr` 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 `nullptr` if not found. - * - */ - template static TlvType *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength) - { - return As(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 `nullptr` if not found. - * - */ - template static const TlvType *FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength) - { - return As(FindTlv(aTlvsStart, aTlvsLength, static_cast(TlvType::kType))); - } - } OT_TOOL_PACKED_END; /** diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index 5171aa664..752a0e5ab 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -466,7 +466,7 @@ const MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aT commissioningDataTlv = GetCommissioningData(); VerifyOrExit(commissioningDataTlv != nullptr); - rval = MeshCoP::Tlv::FindTlv(commissioningDataTlv->GetValue(), commissioningDataTlv->GetLength(), aType); + rval = As(Tlv::FindTlv(commissioningDataTlv->GetValue(), commissioningDataTlv->GetLength(), aType)); exit: return rval;