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; }