From 5f7aa174604a5f0f01a04ea28653d0b838e6aa51 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 16 Jan 2026 16:53:32 -0800 Subject: [PATCH] [tlv] improve encapsulation and docs for `Tlv::Info` (#12301) This change renames `Tlv::ParsedInfo` to `Tlv::Info` to make it more concise and to better reflect its purpose as a metadata holder for a TLV in a message. The member variables of `Tlv::Info` are made private and public accessor methods are introduced to interact with the object's contenet. This helps ensure that the internal representation of the parsed TLV information is not modified directly by external modules. All existing caller are updated to use the new name and the public helper getter methods. The Doxygen comments of `Tlv::Info` are also improved for better clarity. Unit test `test_tlv` is also updated to validate all the new methods. --- src/core/common/tlvs.cpp | 38 ++--- src/core/common/tlvs.hpp | 114 ++++++++++---- src/core/thread/link_metrics.cpp | 67 ++++----- src/core/thread/mle_ftd.cpp | 6 +- src/core/thread/network_diagnostic.cpp | 53 +++---- src/core/utils/history_tracker_server.cpp | 18 +-- tests/unit/test_tlv.cpp | 174 ++++++++++++++++++++++ 7 files changed, 352 insertions(+), 118 deletions(-) diff --git a/src/core/common/tlvs.cpp b/src/core/common/tlvs.cpp index ccf7bb028..1e1f138cb 100644 --- a/src/core/common/tlvs.cpp +++ b/src/core/common/tlvs.cpp @@ -65,14 +65,14 @@ Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tl Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tlv &aTlv, uint16_t &aOffset) { - Error error; - ParsedInfo info; + Error error; + Info info; SuccessOrExit(error = info.FindIn(aMessage, aType)); info.mTlvOffsetRange.ShrinkLength(aMaxSize); aMessage.ReadBytes(info.mTlvOffsetRange, &aTlv); - aOffset = info.mTlvOffsetRange.GetOffset(); + aOffset = info.GetTlvOffset(); exit: return error; @@ -80,17 +80,17 @@ exit: Error Tlv::FindTlvValueOffsetRange(const Message &aMessage, uint8_t aType, OffsetRange &aOffsetRange) { - Error error; - ParsedInfo info; + Error error; + Info info; SuccessOrExit(error = info.FindIn(aMessage, aType)); - aOffsetRange = info.mValueOffsetRange; + aOffsetRange = info.GetValueOffsetRange(); exit: return error; } -Error Tlv::ParsedInfo::ParseFrom(const Message &aMessage, uint16_t aOffset) +Error Tlv::Info::ParseFrom(const Message &aMessage, uint16_t aOffset) { OffsetRange offsetRange; @@ -98,7 +98,7 @@ Error Tlv::ParsedInfo::ParseFrom(const Message &aMessage, uint16_t aOffset) return ParseFrom(aMessage, offsetRange); } -Error Tlv::ParsedInfo::ParseFrom(const Message &aMessage, const OffsetRange &aOffsetRange) +Error Tlv::Info::ParseFrom(const Message &aMessage, const OffsetRange &aOffsetRange) { Error error; Tlv tlv; @@ -138,7 +138,7 @@ exit: return error; } -Error Tlv::ParsedInfo::FindIn(const Message &aMessage, uint8_t aType) +Error Tlv::Info::FindIn(const Message &aMessage, uint8_t aType) { Error error = kErrorNotFound; OffsetRange offsetRange; @@ -164,8 +164,8 @@ exit: Error Tlv::ReadStringTlv(const Message &aMessage, uint16_t aOffset, uint8_t aMaxStringLength, char *aValue) { - Error error = kErrorNone; - ParsedInfo info; + Error error = kErrorNone; + Info info; SuccessOrExit(error = info.ParseFrom(aMessage, aOffset)); @@ -195,8 +195,8 @@ template Error Tlv::ReadUintTlv(const Message &aMessage, uint16_t aOff Error Tlv::ReadTlvValue(const Message &aMessage, uint16_t aOffset, void *aValue, uint8_t aMinLength) { - Error error; - ParsedInfo info; + Error error; + Info info; SuccessOrExit(error = info.ParseFrom(aMessage, aOffset)); @@ -211,11 +211,11 @@ exit: Error Tlv::FindStringTlv(const Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, char *aValue) { - Error error; - ParsedInfo info; + Error error; + Info info; SuccessOrExit(error = info.FindIn(aMessage, aType)); - error = ReadStringTlv(aMessage, info.mTlvOffsetRange.GetOffset(), aMaxStringLength, aValue); + error = ReadStringTlv(aMessage, info.GetTlvOffset(), aMaxStringLength, aValue); exit: return error; @@ -223,11 +223,11 @@ exit: template Error Tlv::FindUintTlv(const Message &aMessage, uint8_t aType, UintType &aValue) { - Error error; - ParsedInfo info; + Error error; + Info info; SuccessOrExit(error = info.FindIn(aMessage, aType)); - error = ReadUintTlv(aMessage, info.mTlvOffsetRange.GetOffset(), aValue); + error = ReadUintTlv(aMessage, info.GetTlvOffset(), aValue); exit: return error; diff --git a/src/core/common/tlvs.hpp b/src/core/common/tlvs.hpp index 4b0690b07..c1aecfe42 100644 --- a/src/core/common/tlvs.hpp +++ b/src/core/common/tlvs.hpp @@ -230,52 +230,97 @@ public: // Static methods for reading/finding/appending TLVs in a `Message`. /** - * Represents information for a parsed TLV from a message. + * Represents metdata information about a TLV within a message. + * + * An `Info` object is populated by the `ParseFrom()` or `FindIn()` methods. It holds metadata about a validated + * TLV, including its type, length, whether it is extended, and its offset and value ranges within the message. */ - struct ParsedInfo + class Info { + friend class Tlv; + + public: /** - * Parses the TLV from a given message at given offset, ensures the TLV is well-formed and its header and - * value are fully contained in the message. + * Parses and validates a TLV from a message at a given offset, populating this `Info` object. * - * Can be used independent of whether the TLV is an Extended TLV or not. + * On success, this `Info` object is updated with the TLV's metadata, such as its type, length, and offset + * ranges. This method ensures the TLV header and value are well-formed and fully contained within the message. + * It can parse both standard and extended TLVs. * - * @param[in] aMessage The message to read from. - * @param[in] aOffset The offset in @p aMessage. + * @param[in] aMessage The message from which to parse the TLV. + * @param[in] aOffset The starting offset of the TLV within the message. * - * @retval kErrorNone Successfully parsed the TLV. - * @retval kErrorParse The TLV was not well-formed or not fully contained in @p aMessage. + * @retval kErrorNone Successfully parsed the TLV and populated the `Info` object. + * @retval kErrorParse The TLV was malformed or not fully contained in the message. */ Error ParseFrom(const Message &aMessage, uint16_t aOffset); /** - * Parses the TLV from a given message for a given offset range, ensures the TLV is well-formed and its header - * and value are fully contained in the offset range and the message. + * Parses and validates a TLV from a message within an offset range, populating this `Info` object. * - * Can be used independent of whether the TLV is an Extended TLV or not. + * On success, this `Info` object is updated with the TLV's metadata, such as its type, length, and offset + * ranges. This method ensures the TLV header and value are well-formed and fully contained within the given + * offset range and the message. It can parse both standard and extended TLVs. * - * @param[in] aMessage The message to read from. - * @param[in] aOffsetRange The offset range in @p aMessage. + * @param[in] aMessage The message from which to parse the TLV. + * @param[in] aOffsetRange The offset range within which the TLV must be contained. * - * @retval kErrorNone Successfully parsed the TLV. - * @retval kErrorParse The TLV was not well-formed or not contained in @p aOffsetRange or @p aMessage. + * @retval kErrorNone Successfully parsed the TLV and populated the `Info` object. + * @retval kErrorParse The TLV was malformed or not contained within the specified range. */ Error ParseFrom(const Message &aMessage, const OffsetRange &aOffsetRange); /** - * Searches in a given message starting from message offset for a TLV of given type and if found, parses - * the TLV and validates that the entire TLV is present in the message. + * Finds and parses a TLV of a given type within a message, populating this `Info` object. * - * Can be used independent of whether the TLV is an Extended TLV or not. + * This method searches the message from its `aMessage.GetOffset()`. On success, this `Info` object is updated + * with the found TLV's metadata, such as its type, length, and offset ranges. The found TLV is validated to + * ensure it is well-formed and fully contained in the message. * - * @param[in] aMessage The message to search in. - * @param[in] aType The TLV type to search for. + * @param[in] aMessage The message to search within. + * @param[in] aType The TLV type to find. * - * @retval kErrorNone Successfully found and parsed the TLV. - * @retval kErrorNotFound Could not find the TLV, or the TLV was not well-formed. + * @retval kErrorNone Successfully found and parsed the TLV, and populated the `Info` object. + * @retval kErrorNotFound No valid TLV of the given type was found. */ Error FindIn(const Message &aMessage, uint8_t aType); + /** + * Gets the TLV type. + * + * @returns The TLV type. + */ + uint8_t GetType(void) const { return mType; } + + /** + * Gets the TLV's value length. + * + * @returns The TLV's value length (in bytes). + */ + uint16_t GetLength(void) const { return mValueOffsetRange.GetLength(); } + + /** + * Indicates whether the TLV is an Extended TLV. + * + * @retval TRUE If it is an Extended TLV. + * @retval FALSE If it is not an Extended TLV. + */ + bool IsExtended(void) const { return mIsExtended; } + + /** + * Gets the offset range of the entire TLV (header and value). + * + * @returns The offset range of the entire TLV. + */ + const OffsetRange &GetTlvOffsetRange(void) const { return mTlvOffsetRange; } + + /** + * Gets the start offset of the TLV. + * + * @returns The start offset of the TLV. + */ + uint16_t GetTlvOffset(void) const { return mTlvOffsetRange.GetOffset(); } + /** * Returns the full TLV size in bytes. * @@ -283,10 +328,25 @@ public: */ uint16_t GetSize(void) const { return mTlvOffsetRange.GetLength(); } - uint8_t mType; ///< The TLV type - bool mIsExtended; ///< Whether the TLV is extended or not. - OffsetRange mTlvOffsetRange; ///< Offset range containing the full TLV. - OffsetRange mValueOffsetRange; ///< Offset range containing the TLV's value. + /** + * Gets the offset range of the TLV's value. + * + * @returns The offset range of the TLV's value. + */ + const OffsetRange &GetValueOffsetRange(void) const { return mValueOffsetRange; } + + /** + * Gets the start offset of the TLV's value. + * + * @returns The start offset of the TLV's value. + */ + uint16_t GetValueOffset(void) const { return mValueOffsetRange.GetOffset(); } + + private: + uint8_t mType; + bool mIsExtended; + OffsetRange mTlvOffsetRange; + OffsetRange mValueOffsetRange; }; /** diff --git a/src/core/thread/link_metrics.cpp b/src/core/thread/link_metrics.cpp index 01fd3f192..955823912 100644 --- a/src/core/thread/link_metrics.cpp +++ b/src/core/thread/link_metrics.cpp @@ -110,14 +110,14 @@ exit: void Initiator::HandleReport(const Message &aMessage, OffsetRange &aOffsetRange, const Ip6::Address &aAddress) { - Error error = kErrorNone; - bool hasStatus = false; - bool hasReport = false; - Tlv::ParsedInfo tlvInfo; - ReportSubTlv reportTlv; - MetricsValues values; - uint8_t status; - uint8_t typeId; + Error error = kErrorNone; + bool hasStatus = false; + bool hasReport = false; + Tlv::Info tlvInfo; + ReportSubTlv reportTlv; + MetricsValues values; + uint8_t status; + uint8_t typeId; OT_UNUSED_VARIABLE(error); @@ -129,7 +129,7 @@ void Initiator::HandleReport(const Message &aMessage, OffsetRange &aOffsetRange, { SuccessOrExit(error = tlvInfo.ParseFrom(aMessage, aOffsetRange)); - if (tlvInfo.mIsExtended) + if (tlvInfo.IsExtended()) { continue; } @@ -138,7 +138,7 @@ void Initiator::HandleReport(const Message &aMessage, OffsetRange &aOffsetRange, // - One or more Report Sub-TLVs (in case of success), or // - A single Status Sub-TLV (in case of failure). - switch (tlvInfo.mType) + switch (tlvInfo.GetType()) { case StatusSubTlv::kType: VerifyOrExit(!hasStatus && !hasReport, error = kErrorDrop); @@ -287,11 +287,11 @@ exit: Error Initiator::HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress) { - Error error = kErrorNone; - OffsetRange offsetRange; - Tlv::ParsedInfo tlvInfo; - uint8_t status; - bool hasStatus = false; + Error error = kErrorNone; + OffsetRange offsetRange; + Tlv::Info tlvInfo; + uint8_t status; + bool hasStatus = false; VerifyOrExit(mMgmtResponseCallback.IsSet()); @@ -301,12 +301,12 @@ Error Initiator::HandleManagementResponse(const Message &aMessage, const Ip6::Ad { SuccessOrExit(error = tlvInfo.ParseFrom(aMessage, offsetRange)); - if (tlvInfo.mIsExtended) + if (tlvInfo.IsExtended()) { continue; } - switch (tlvInfo.mType) + switch (tlvInfo.GetType()) { case StatusSubTlv::kType: VerifyOrExit(!hasStatus, error = kErrorParse); @@ -402,13 +402,13 @@ Subject::Subject(Instance &aInstance) Error Subject::AppendReport(Message &aMessage, const Message &aRequestMessage, Neighbor &aNeighbor) { - Error error = kErrorNone; - Tlv::ParsedInfo tlvInfo; - uint8_t queryId; - bool hasQueryId = false; - OffsetRange offsetRange; - Tlv::Bookmark tlvBookmark; - MetricsValues values; + Error error = kErrorNone; + Tlv::Info tlvInfo; + uint8_t queryId; + bool hasQueryId = false; + OffsetRange offsetRange; + Tlv::Bookmark tlvBookmark; + MetricsValues values; values.Clear(); @@ -423,22 +423,21 @@ Error Subject::AppendReport(Message &aMessage, const Message &aRequestMessage, N { SuccessOrExit(error = tlvInfo.ParseFrom(aRequestMessage, offsetRange)); - if (tlvInfo.mIsExtended) + if (tlvInfo.IsExtended()) { continue; } - switch (tlvInfo.mType) + switch (tlvInfo.GetType()) { case SubTlv::kQueryId: - SuccessOrExit(error = - Tlv::Read(aRequestMessage, tlvInfo.mTlvOffsetRange.GetOffset(), queryId)); + SuccessOrExit(error = Tlv::Read(aRequestMessage, tlvInfo.GetTlvOffset(), queryId)); hasQueryId = true; break; case SubTlv::kQueryOptions: - SuccessOrExit(error = - ReadTypeIdsFromMessage(aRequestMessage, tlvInfo.mValueOffsetRange, values.GetMetrics())); + SuccessOrExit( + error = ReadTypeIdsFromMessage(aRequestMessage, tlvInfo.GetValueOffsetRange(), values.GetMetrics())); break; default: @@ -496,7 +495,7 @@ Error Subject::HandleManagementRequest(const Message &aMessage, Neighbor &aNeigh { Error error = kErrorNone; OffsetRange offsetRange; - Tlv::ParsedInfo tlvInfo; + Tlv::Info tlvInfo; FwdProbingRegSubTlv fwdProbingSubTlv; EnhAckConfigSubTlv enhAckConfigSubTlv; Metrics metrics; @@ -516,14 +515,14 @@ Error Subject::HandleManagementRequest(const Message &aMessage, Neighbor &aNeigh SuccessOrExit(error = tlvInfo.ParseFrom(aMessage, offsetRange)); - if (tlvInfo.mIsExtended) + if (tlvInfo.IsExtended()) { continue; } - tlvOffsetRange = tlvInfo.mTlvOffsetRange; + tlvOffsetRange = tlvInfo.GetTlvOffsetRange(); - switch (tlvInfo.mType) + switch (tlvInfo.GetType()) { case SubTlv::kFwdProbingReg: subTlv = &fwdProbingSubTlv; diff --git a/src/core/thread/mle_ftd.cpp b/src/core/thread/mle_ftd.cpp index 9610b9e24..15435d3ac 100644 --- a/src/core/thread/mle_ftd.cpp +++ b/src/core/thread/mle_ftd.cpp @@ -2707,7 +2707,7 @@ void Mle::HandleDiscoveryRequest(RxInfo &aRxInfo) { Error error = kErrorNone; bool parsedDiscoveryRequestTlv = false; - Tlv::ParsedInfo tlvInfo; + Tlv::Info tlvInfo; MeshCoP::DiscoveryRequestTlvValue discoveryRequestTlvValue; MeshCoP::ExtendedPanId extPanId; OffsetRange offsetRange; @@ -2723,12 +2723,12 @@ void Mle::HandleDiscoveryRequest(RxInfo &aRxInfo) { SuccessOrExit(error = tlvInfo.ParseFrom(aRxInfo.mMessage, offsetRange)); - if (tlvInfo.mIsExtended) + if (tlvInfo.IsExtended()) { continue; } - switch (tlvInfo.mType) + switch (tlvInfo.GetType()) { case MeshCoP::Tlv::kDiscoveryRequest: SuccessOrExit(error = Tlv::Read(aRxInfo.mMessage, offsetRange.GetOffset(), diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp index e44e87521..8390e8fd6 100644 --- a/src/core/thread/network_diagnostic.cpp +++ b/src/core/thread/network_diagnostic.cpp @@ -1277,9 +1277,9 @@ void Client::ParseIp6AddrList(Ip6AddrList &aIp6Addrs, const Message &aMessage, O Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, DiagTlv &aDiagTlv) { - Error error; - uint16_t offset = (aIterator == 0) ? aMessage.GetOffset() : aIterator; - Tlv::ParsedInfo tlvInfo; + Error error; + uint16_t offset = (aIterator == 0) ? aMessage.GetOffset() : aIterator; + Tlv::Info tlvInfo; while (offset < aMessage.GetLength()) { @@ -1287,7 +1287,7 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, SuccessOrExit(error = tlvInfo.ParseFrom(aMessage, offset)); - switch (tlvInfo.mType) + switch (tlvInfo.GetType()) { case Tlv::kExtMacAddress: SuccessOrExit(error = @@ -1315,7 +1315,7 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, { ConnectivityTlvValue tlvValue; - SuccessOrExit(error = tlvValue.ParseFrom(aMessage, tlvInfo.mValueOffsetRange)); + SuccessOrExit(error = tlvValue.ParseFrom(aMessage, tlvInfo.GetValueOffsetRange())); tlvValue.GetConnectivity(AsCoreType(&aDiagTlv.mData.mConnectivity)); break; } @@ -1325,7 +1325,7 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, RouteTlv routeTlv; uint16_t bytesToRead = Min(tlvInfo.GetSize(), sizeof(routeTlv)); - VerifyOrExit(!tlvInfo.mIsExtended, error = kErrorParse); + VerifyOrExit(!tlvInfo.IsExtended(), error = kErrorParse); SuccessOrExit(error = aMessage.Read(offset, &routeTlv, bytesToRead)); VerifyOrExit(routeTlv.IsValid(), error = kErrorParse); ParseRoute(routeTlv, aDiagTlv.mData.mRoute); @@ -1349,14 +1349,13 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, static_assert(sizeof(aDiagTlv.mData.mNetworkData.m8) >= NetworkData::NetworkData::kMaxSize, "NetworkData array in `otNetworkDiagTlv` is too small"); - VerifyOrExit(tlvInfo.mValueOffsetRange.GetLength() <= NetworkData::NetworkData::kMaxSize, - error = kErrorParse); - aDiagTlv.mData.mNetworkData.mCount = static_cast(tlvInfo.mValueOffsetRange.GetLength()); - aMessage.ReadBytes(tlvInfo.mValueOffsetRange, aDiagTlv.mData.mNetworkData.m8); + VerifyOrExit(tlvInfo.GetLength() <= NetworkData::NetworkData::kMaxSize, error = kErrorParse); + aDiagTlv.mData.mNetworkData.mCount = static_cast(tlvInfo.GetLength()); + aMessage.ReadBytes(tlvInfo.GetValueOffsetRange(), aDiagTlv.mData.mNetworkData.m8); break; case Tlv::kIp6AddressList: - ParseIp6AddrList(aDiagTlv.mData.mIp6AddrList, aMessage, tlvInfo.mValueOffsetRange); + ParseIp6AddrList(aDiagTlv.mData.mIp6AddrList, aMessage, tlvInfo.GetValueOffsetRange()); break; case Tlv::kMacCounters: @@ -1389,23 +1388,25 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, case Tlv::kChildTable: { - uint16_t childInfoLength = GetArrayLength(aDiagTlv.mData.mChildTable.mTable); - ChildInfo *childInfo = &aDiagTlv.mData.mChildTable.mTable[0]; - uint8_t &childCount = aDiagTlv.mData.mChildTable.mCount; + uint16_t childInfoLength = GetArrayLength(aDiagTlv.mData.mChildTable.mTable); + ChildInfo *childInfo = &aDiagTlv.mData.mChildTable.mTable[0]; + uint8_t &childCount = aDiagTlv.mData.mChildTable.mCount; + OffsetRange offsetRange; - VerifyOrExit((tlvInfo.mValueOffsetRange.GetLength() % sizeof(ChildTableEntry)) == 0, error = kErrorParse); + VerifyOrExit((tlvInfo.GetLength() % sizeof(ChildTableEntry)) == 0, error = kErrorParse); // `DiagTlv` has a fixed array Child Table entries. If there // are more entries in the message, we read and return as // many as can fit in array and ignore the rest. - childCount = 0; + childCount = 0; + offsetRange = tlvInfo.GetValueOffsetRange(); - while (!tlvInfo.mValueOffsetRange.IsEmpty() && (childCount < childInfoLength)) + while (!offsetRange.IsEmpty() && (childCount < childInfoLength)) { ChildTableEntry entry; - SuccessOrExit(error = aMessage.Read(tlvInfo.mValueOffsetRange, entry)); + SuccessOrExit(error = aMessage.Read(offsetRange, entry)); childInfo->mTimeout = entry.GetTimeout(); childInfo->mLinkQuality = entry.GetLinkQuality(); @@ -1414,16 +1415,16 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, childCount++; childInfo++; - tlvInfo.mValueOffsetRange.AdvanceOffset(sizeof(ChildTableEntry)); + offsetRange.AdvanceOffset(sizeof(ChildTableEntry)); } break; } case Tlv::kChannelPages: - aDiagTlv.mData.mChannelPages.mCount = static_cast( - Min(tlvInfo.mValueOffsetRange.GetLength(), GetArrayLength(aDiagTlv.mData.mChannelPages.m8))); - aMessage.ReadBytes(tlvInfo.mValueOffsetRange.GetOffset(), aDiagTlv.mData.mChannelPages.m8, + aDiagTlv.mData.mChannelPages.mCount = + static_cast(Min(tlvInfo.GetLength(), GetArrayLength(aDiagTlv.mData.mChannelPages.m8))); + aMessage.ReadBytes(tlvInfo.GetValueOffset(), aDiagTlv.mData.mChannelPages.m8, aDiagTlv.mData.mChannelPages.mCount); break; @@ -1461,7 +1462,7 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, break; case Tlv::kNonPreferredChannels: - SuccessOrExit(error = MeshCoP::ChannelMaskTlv::ParseValue(aMessage, tlvInfo.mValueOffsetRange, + SuccessOrExit(error = MeshCoP::ChannelMaskTlv::ParseValue(aMessage, tlvInfo.GetValueOffsetRange(), aDiagTlv.mData.mNonPreferredChannels)); break; @@ -1475,14 +1476,14 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, } case Tlv::kBrIfAddrs: - ParseIp6AddrList(aDiagTlv.mData.mBrIfAddrList, aMessage, tlvInfo.mValueOffsetRange); + ParseIp6AddrList(aDiagTlv.mData.mBrIfAddrList, aMessage, tlvInfo.GetValueOffsetRange()); break; case Tlv::kBrLocalOmrPrefix: case Tlv::kBrLocalOnlinkPrefix: case Tlv::kBrFavoredOnLinkPrefix: case Tlv::kBrDhcp6PdOmrPrefix: - SuccessOrExit(error = aMessage.Read(tlvInfo.mValueOffsetRange, aDiagTlv.mData.mBrPrefix)); + SuccessOrExit(error = aMessage.Read(tlvInfo.GetValueOffsetRange(), aDiagTlv.mData.mBrPrefix)); break; default: @@ -1496,7 +1497,7 @@ Error Client::GetNextDiagTlv(const Coap::Message &aMessage, Iterator &aIterator, if (!skipTlv) { // Exit if a TLV is recognized and parsed successfully. - aDiagTlv.mType = tlvInfo.mType; + aDiagTlv.mType = tlvInfo.GetType(); aIterator = offset; error = kErrorNone; ExitNow(); diff --git a/src/core/utils/history_tracker_server.cpp b/src/core/utils/history_tracker_server.cpp index 3fa8caada..b60ed3592 100644 --- a/src/core/utils/history_tracker_server.cpp +++ b/src/core/utils/history_tracker_server.cpp @@ -129,13 +129,13 @@ void Server::FreeAllRelatedAnswers(Coap::Message &aFirstAnswer) void Server::PrepareAndSendAnswers(const Ip6::Address &aDestination, const Message &aRequest) { - Coap::Message *answer; - Error error; - AnswerInfo info; - OffsetRange offsetRange; - Tlv::ParsedInfo tlvInfo; - RequestTlv requestTlv; - AnswerTlv answerTlv; + Coap::Message *answer; + Error error; + AnswerInfo info; + OffsetRange offsetRange; + Tlv::Info tlvInfo; + RequestTlv requestTlv; + AnswerTlv answerTlv; if (Tlv::Find(aRequest, info.mQueryId) == kErrorNone) { @@ -152,12 +152,12 @@ void Server::PrepareAndSendAnswers(const Ip6::Address &aDestination, const Messa { SuccessOrExit(error = tlvInfo.ParseFrom(aRequest, offsetRange)); - if (tlvInfo.mIsExtended) + if (tlvInfo.IsExtended()) { continue; } - if (tlvInfo.mType == Tlv::kRequest) + if (tlvInfo.GetType() == Tlv::kRequest) { SuccessOrExit(error = aRequest.Read(offsetRange, requestTlv)); VerifyOrExit(requestTlv.IsValid(), error = kErrorParse); diff --git a/tests/unit/test_tlv.cpp b/tests/unit/test_tlv.cpp index e93886586..3d83fe5e8 100644 --- a/tests/unit/test_tlv.cpp +++ b/tests/unit/test_tlv.cpp @@ -288,11 +288,185 @@ void TestTlv(void) testFreeInstance(instance); } +void TestTlvInfo(void) +{ + Instance *instance; + Message *message; + uint16_t offset; + uint16_t len; + Tlv tlv; + ExtendedTlv extTlv; + Tlv::Info info; + + instance = testInitInstance(); + VerifyOrQuit(instance != nullptr); + message = instance->Get().Allocate(Message::kTypeOther); + VerifyOrQuit(message != nullptr); + + // Append TLV 1: Standard TLV with 1-byte value. + tlv.SetType(1); + tlv.SetLength(1); + SuccessOrQuit(message->Append(tlv)); + SuccessOrQuit(message->Append(0xaa)); + + // Append TLV 2: Extended TLV with 2-byte value. + extTlv.SetType(2); + extTlv.SetLength(2); + SuccessOrQuit(message->Append(extTlv)); + SuccessOrQuit(message->Append(0xcafe)); + + // Append TLV 3: Standard empty TLV. + tlv.SetType(3); + tlv.SetLength(0); + SuccessOrQuit(message->Append(tlv)); + + // Append TLV 4: Extended empty TLV. + extTlv.SetType(4); + extTlv.SetLength(0); + SuccessOrQuit(message->Append(extTlv)); + + // Append TLV 5: Malformed standard TLV (claims length 2, but has only 1). + tlv.SetType(5); + tlv.SetLength(2); + SuccessOrQuit(message->Append(tlv)); + SuccessOrQuit(message->Append(0x12)); + + for (uint8_t testIter = 0; testIter <= 1; testIter++) + { + offset = 0; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TLV 1 (standard, len=1) + + len = 1; + + if (testIter == 0) + { + SuccessOrQuit(info.ParseFrom(*message, offset)); + } + else + { + SuccessOrQuit(info.FindIn(*message, 1)); + } + + VerifyOrQuit(info.GetType() == 1); + VerifyOrQuit(info.GetLength() == len); + VerifyOrQuit(!info.IsExtended()); + VerifyOrQuit(info.GetSize() == sizeof(Tlv) + len); + VerifyOrQuit(info.GetTlvOffset() == offset); + VerifyOrQuit(info.GetValueOffset() == offset + sizeof(Tlv)); + VerifyOrQuit(info.GetTlvOffsetRange().GetOffset() == offset); + VerifyOrQuit(info.GetTlvOffsetRange().GetLength() == sizeof(Tlv) + len); + VerifyOrQuit(info.GetValueOffsetRange().GetOffset() == offset + sizeof(Tlv)); + VerifyOrQuit(info.GetValueOffsetRange().GetLength() == len); + + offset = info.GetTlvOffsetRange().GetEndOffset(); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TLV 2 (extended, len=2) + + len = 2; + + if (testIter == 0) + { + SuccessOrQuit(info.ParseFrom(*message, offset)); + } + else + { + SuccessOrQuit(info.FindIn(*message, 2)); + } + + VerifyOrQuit(info.GetType() == 2); + VerifyOrQuit(info.GetLength() == len); + VerifyOrQuit(info.IsExtended()); + VerifyOrQuit(info.GetSize() == sizeof(ExtendedTlv) + len); + VerifyOrQuit(info.GetTlvOffset() == offset); + VerifyOrQuit(info.GetValueOffset() == offset + sizeof(ExtendedTlv)); + VerifyOrQuit(info.GetTlvOffsetRange().GetOffset() == offset); + VerifyOrQuit(info.GetTlvOffsetRange().GetLength() == sizeof(ExtendedTlv) + len); + VerifyOrQuit(info.GetValueOffsetRange().GetOffset() == offset + sizeof(ExtendedTlv)); + VerifyOrQuit(info.GetValueOffsetRange().GetLength() == len); + + offset = info.GetTlvOffsetRange().GetEndOffset(); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TLV 3 (standard, empty) + + len = 0; + + if (testIter == 0) + { + SuccessOrQuit(info.ParseFrom(*message, offset)); + } + else + { + SuccessOrQuit(info.FindIn(*message, 3)); + } + + VerifyOrQuit(info.GetType() == 3); + VerifyOrQuit(info.GetLength() == len); + VerifyOrQuit(!info.IsExtended()); + VerifyOrQuit(info.GetSize() == sizeof(Tlv) + len); + VerifyOrQuit(info.GetTlvOffset() == offset); + VerifyOrQuit(info.GetValueOffset() == offset + sizeof(Tlv)); + VerifyOrQuit(info.GetTlvOffsetRange().GetOffset() == offset); + VerifyOrQuit(info.GetTlvOffsetRange().GetLength() == sizeof(Tlv) + len); + VerifyOrQuit(info.GetValueOffsetRange().GetOffset() == offset + sizeof(Tlv)); + VerifyOrQuit(info.GetValueOffsetRange().GetLength() == len); + + offset = info.GetTlvOffsetRange().GetEndOffset(); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // TLV 4 (extended, empty) + + len = 0; + + if (testIter == 0) + { + SuccessOrQuit(info.ParseFrom(*message, offset)); + } + else + { + SuccessOrQuit(info.FindIn(*message, 4)); + } + + VerifyOrQuit(info.GetType() == 4); + VerifyOrQuit(info.GetLength() == len); + VerifyOrQuit(info.IsExtended()); + VerifyOrQuit(info.GetSize() == sizeof(ExtendedTlv) + len); + VerifyOrQuit(info.GetTlvOffset() == offset); + VerifyOrQuit(info.GetValueOffset() == offset + sizeof(ExtendedTlv)); + VerifyOrQuit(info.GetTlvOffsetRange().GetOffset() == offset); + VerifyOrQuit(info.GetTlvOffsetRange().GetLength() == sizeof(ExtendedTlv) + len); + VerifyOrQuit(info.GetValueOffsetRange().GetOffset() == offset + sizeof(ExtendedTlv)); + VerifyOrQuit(info.GetValueOffsetRange().GetLength() == len); + + offset = info.GetTlvOffsetRange().GetEndOffset(); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Test TLV 5 (malformed) + + if (testIter == 0) + { + VerifyOrQuit(info.ParseFrom(*message, offset) == kErrorParse); + } + else + { + VerifyOrQuit(info.FindIn(*message, 5) != kErrorNone); + } + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + message->Free(); + testFreeInstance(instance); +} + } // namespace ot int main(void) { ot::TestTlv(); + ot::TestTlvInfo(); printf("All tests passed\n"); return 0; }