diff --git a/src/core/common/tlvs.cpp b/src/core/common/tlvs.cpp index 9e9db1b98..6844024a8 100644 --- a/src/core/common/tlvs.cpp +++ b/src/core/common/tlvs.cpp @@ -253,25 +253,38 @@ template Error Tlv::AppendUintTlv(Message &aMessage, uint8_t aType, ui Error Tlv::AppendEmptyTlv(Message &aMessage, uint8_t aType) { return AppendTlv(aMessage, aType, nullptr, 0); } -Error Tlv::AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint16_t aLength) +Error Tlv::AppendTlvHeader(Message &aMessage, uint8_t aType, uint16_t aLength) { - Error error = kErrorNone; - ExtendedTlv extTlv; - Tlv tlv; + uint16_t size; + + union + { + Tlv tlv; + ExtendedTlv extTlv; + }; + + tlv.SetType(aType); if (aLength > kBaseTlvMaxLength) { - extTlv.SetType(aType); extTlv.SetLength(aLength); - SuccessOrExit(error = aMessage.Append(extTlv)); + size = sizeof(ExtendedTlv); } else { - tlv.SetType(aType); tlv.SetLength(static_cast(aLength)); - SuccessOrExit(error = aMessage.Append(tlv)); + size = sizeof(Tlv); } + return aMessage.AppendBytes(&tlv, size); +} + +Error Tlv::AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint16_t aLength) +{ + Error error; + + SuccessOrExit(error = AppendTlvHeader(aMessage, aType, aLength)); + VerifyOrExit(aLength > 0); error = aMessage.AppendBytes(aValue, aLength); @@ -279,16 +292,25 @@ exit: return error; } +Error Tlv::AppendTlvWithValueFromMessage(Message &aMessage, + uint8_t aType, + const Message &aValueMsg, + const OffsetRange &aValueMsgOffsetRange) +{ + Error error; + + SuccessOrExit(error = AppendTlvHeader(aMessage, aType, aValueMsgOffsetRange.GetLength())); + error = aMessage.AppendBytesFromMessage(aValueMsg, aValueMsgOffsetRange); + +exit: + return error; +} + Error Tlv::StartTlv(Message &aMessage, uint8_t aType, Bookmark &aBookmark) { - Tlv tlv; - - tlv.SetType(aType); - tlv.SetLength(0); - aBookmark = aMessage.GetLength(); - return aMessage.Append(tlv); + return AppendTlvHeader(aMessage, aType, 0); } Error Tlv::AdjustTlv(Message &aMessage, Bookmark aBookmark) diff --git a/src/core/common/tlvs.hpp b/src/core/common/tlvs.hpp index 12a46835a..d7ed2cdad 100644 --- a/src/core/common/tlvs.hpp +++ b/src/core/common/tlvs.hpp @@ -598,6 +598,25 @@ public: */ static Error AppendTlv(Message &aMessage, uint8_t aType, const void *aValue, uint16_t aLength); + /** + * Appends a TLV with a given type and value read from another message. + * + * This method automatically formats the TLV as an Extended TLV if the length exceeds `kBaseTlvMaxLength` (254). + * + * @param[in] aMessage The message to append the TLV to. + * @param[in] aType The TLV type to append. + * @param[in] aValueMsg The message to read the TLV value from. + * @param[in] aValueMsgOffsetRange The offset range in @p aValueMsg to read the value from. + * + * @retval kErrorNone Successfully appended the TLV. + * @retval kErrorNoBufs Insufficient available buffers to grow the message. + * @retval kErrorParse Not enough bytes in @p aValueMsg to read the @p aValueMsgOffsetRange. + */ + static Error AppendTlvWithValueFromMessage(Message &aMessage, + uint8_t aType, + const Message &aValueMsg, + const OffsetRange &aValueMsgOffsetRange); + /** * Appends a TLV with a given type and value to a message. * @@ -820,6 +839,7 @@ protected: static const uint8_t kExtendedLength = 255; // Extended Length value. private: + static Error AppendTlvHeader(Message &aMessage, uint8_t aType, uint16_t aLength); static Error FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint16_t aLength); static Error FindStringTlv(const Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, char *aValue); static Error AppendStringTlv(Message &aMessage, uint8_t aType, uint8_t aMaxStringLength, const char *aValue); diff --git a/src/core/meshcop/commissioner.cpp b/src/core/meshcop/commissioner.cpp index 16d48af5f..dec9ee6b2 100644 --- a/src/core/meshcop/commissioner.cpp +++ b/src/core/meshcop/commissioner.cpp @@ -971,7 +971,7 @@ Error Commissioner::SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo OT_UNUSED_VARIABLE(aMessageInfo); Error error = kErrorNone; - ExtendedTlv tlv; + OffsetRange offsetRange; OwnedPtr message; Kek kek; @@ -989,10 +989,9 @@ Error Commissioner::SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo SuccessOrExit(error = Tlv::Append(*message, kek)); } - tlv.SetType(Tlv::kJoinerDtlsEncapsulation); - tlv.SetLength(aMessage.GetLength()); - SuccessOrExit(error = message->Append(tlv)); - SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, 0, aMessage.GetLength())); + offsetRange.InitFromMessageFullLength(aMessage); + SuccessOrExit( + error = Tlv::AppendTlvWithValueFromMessage(*message, Tlv::kJoinerDtlsEncapsulation, aMessage, offsetRange)); SuccessOrExit(error = Get().SendMessageToRloc(*message, mJoinerRloc)); message.Release(); diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index 243635826..f61cbc237 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -118,7 +118,6 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a { Error error; Coap::Message *message = nullptr; - ExtendedTlv tlv; uint16_t borderAgentRloc; OffsetRange offsetRange; @@ -134,11 +133,8 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a SuccessOrExit(error = Tlv::Append(*message, Get().GetRloc16())); offsetRange.InitFromMessageOffsetToEnd(aMessage); - - tlv.SetType(Tlv::kJoinerDtlsEncapsulation); - tlv.SetLength(offsetRange.GetLength()); - SuccessOrExit(error = message->Append(tlv)); - SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange)); + SuccessOrExit( + error = Tlv::AppendTlvWithValueFromMessage(*message, Tlv::kJoinerDtlsEncapsulation, aMessage, offsetRange)); SuccessOrExit(error = Get().SendMessageToRloc(*message, borderAgentRloc)); diff --git a/src/core/meshcop/tcat_agent.cpp b/src/core/meshcop/tcat_agent.cpp index 74b80a1cf..67cafe2cd 100644 --- a/src/core/meshcop/tcat_agent.cpp +++ b/src/core/meshcop/tcat_agent.cpp @@ -693,26 +693,12 @@ Error TcatAgent::HandlePing(const Message &aIncomingMessage, const OffsetRange &aOffsetRange, bool &aResponse) { - Error error = kErrorNone; - ot::ExtendedTlv extTlv; - ot::Tlv tlv; + Error error; VerifyOrExit(aOffsetRange.GetLength() <= kPingPayloadMaxLength, error = kErrorParse); - if (aOffsetRange.GetLength() > ot::Tlv::kBaseTlvMaxLength) - { - extTlv.SetType(kTlvResponseWithPayload); - extTlv.SetLength(aOffsetRange.GetLength()); - SuccessOrExit(error = aOutgoingMessage.Append(extTlv)); - } - else - { - tlv.SetType(kTlvResponseWithPayload); - tlv.SetLength(static_cast(aOffsetRange.GetLength())); - SuccessOrExit(error = aOutgoingMessage.Append(tlv)); - } - - SuccessOrExit(error = aOutgoingMessage.AppendBytesFromMessage(aIncomingMessage, aOffsetRange)); + SuccessOrExit(error = Tlv::AppendTlvWithValueFromMessage(aOutgoingMessage, kTlvResponseWithPayload, + aIncomingMessage, aOffsetRange)); aResponse = true; exit: