[tlv] add helper method to find/read TLVs in a sequence of TLVs (#9538)

This commit moves the helper methods to find a specific TLV in a
sequence of TLVs from the `MeshCoP::Tlv` class to the base `Tlv`
class. This makes these helper methods accessible to all subclasses.
This commit is contained in:
Abtin Keshavarzian
2023-10-16 12:50:59 -07:00
committed by GitHub
parent 66eaeec41a
commit 4808b76c88
6 changed files with 98 additions and 123 deletions
+29 -1
View File
@@ -271,7 +271,7 @@ template Error Tlv::FindUintTlv<uint8_t>(const Message &aMessage, uint8_t aType,
template Error Tlv::FindUintTlv<uint16_t>(const Message &aMessage, uint8_t aType, uint16_t &aValue);
template Error Tlv::FindUintTlv<uint32_t>(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<const Tlv *>(reinterpret_cast<const uint8_t *>(aTlvsStart) + aTlvsLength);
for (tlv = reinterpret_cast<const Tlv *>(aTlvsStart); tlv < end; tlv = tlv->GetNext())
{
VerifyOrExit((tlv + 1) <= end, tlv = nullptr);
if (tlv->IsExtended())
{
VerifyOrExit((As<ExtendedTlv>(tlv) + 1) <= As<ExtendedTlv>(end), tlv = nullptr);
}
VerifyOrExit(tlv->GetNext() <= end, tlv = nullptr);
if (tlv->GetType() == aType)
{
ExitNow();
}
}
tlv = nullptr;
exit:
return tlv;
}
} // namespace ot
+67 -1
View File
@@ -39,6 +39,7 @@
#include <openthread/thread.h>
#include <openthread/platform/toolchain.h>
#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 <typename TlvType> static TlvType *Find(void *aTlvsStart, uint16_t aTlvsLength)
{
return static_cast<TlvType *>(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 <typename TlvType> static const TlvType *Find(const void *aTlvsStart, uint16_t aTlvsLength)
{
return static_cast<const TlvType *>(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);
+1 -1
View File
@@ -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>(Tlv::FindTlv(mTlvs, mLength, aType)); }
void Dataset::ConvertTo(Info &aDatasetInfo) const
{
-25
View File
@@ -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<const Tlv *>(aTlvsStart + aTlvsLength);
for (tlv = reinterpret_cast<const Tlv *>(aTlvsStart); tlv < end; tlv = tlv->GetNext())
{
VerifyOrExit((tlv + 1) <= end, tlv = nullptr);
VerifyOrExit(!tlv->IsExtended() ||
(reinterpret_cast<const ExtendedTlv *>(tlv) + 1 <= reinterpret_cast<const ExtendedTlv *>(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();
-94
View File
@@ -163,43 +163,6 @@ public:
*/
const Tlv *GetNext(void) const { return As<Tlv>(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<uint8_t>(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 <typename TlvType> 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 <typename TlvType> static TlvType *FindTlv(uint8_t *aTlvsStart, uint16_t aTlvsLength)
{
return As<TlvType>(FindTlv(aTlvsStart, aTlvsLength, static_cast<Tlv::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] 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 <typename TlvType> static const TlvType *FindTlv(const uint8_t *aTlvsStart, uint16_t aTlvsLength)
{
return As<TlvType>(FindTlv(aTlvsStart, aTlvsLength, static_cast<Tlv::Type>(TlvType::kType)));
}
} OT_TOOL_PACKED_END;
/**
+1 -1
View File
@@ -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<MeshCoP::Tlv>(Tlv::FindTlv(commissioningDataTlv->GetValue(), commissioningDataTlv->GetLength(), aType));
exit:
return rval;