From a737be4f3aa4c010939b9ab6632d0443c3ac9763 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 20 Feb 2026 09:12:36 -0800 Subject: [PATCH] [message] add `ReadAtAndAdvanceOffset()` helper method (#12503) This commit adds `ReadAtAndAdvanceOffset()` to the `Message` class to simplify reading data from the message at the current message offset and then advancing the message offset. This pattern is commonly used when processing message headers sequentially. The new method helps reduce code verbosity and ensures the offset is always advanced by the correct size. The new helper is adopted in various core modules including DHCPv6, IPv6, 6LoWPAN, MLE, and UDP processing. --- src/core/common/message.cpp | 11 +++++++++++ src/core/common/message.hpp | 28 ++++++++++++++++++++++++++++ src/core/net/dhcp6_client.cpp | 3 +-- src/core/net/dhcp6_server.cpp | 3 +-- src/core/net/ip6.cpp | 6 ++---- src/core/net/udp6.cpp | 5 ++--- src/core/thread/lowpan.cpp | 11 +++-------- src/core/thread/mle.cpp | 12 ++++-------- 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp index 2c18c4f7a..ffa595b31 100644 --- a/src/core/common/message.cpp +++ b/src/core/common/message.cpp @@ -663,6 +663,17 @@ exit: return error; } +Error Message::ReadAtAndAdvanceOffset(void *aBuf, uint16_t aLength) +{ + Error error; + + SuccessOrExit(error = Read(GetOffset(), aBuf, aLength)); + MoveOffset(aLength); + +exit: + return error; +} + bool Message::CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher) const { uint16_t bytesToCompare = aLength; diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp index e01ddfefd..289a60359 100644 --- a/src/core/common/message.hpp +++ b/src/core/common/message.hpp @@ -925,6 +925,34 @@ public: return Read(aOffsetRange, &aObject, sizeof(ObjectType)); } + /** + * Reads a given number of bytes from the message at the current message offset and advances the message offset. + * + * @param[out] aBuf A pointer to a data buffer to copy the read bytes into. + * @param[in] aLength Number of bytes to read. + * + * @retval kErrorNone Requested bytes were successfully read from message. Message offset is advanced. + * @retval kErrorParse Not enough bytes remaining to read the requested @p aLength. Message offset is unchanged. + */ + Error ReadAtAndAdvanceOffset(void *aBuf, uint16_t aLength); + + /** + * Reads an object from the message at the current message offset and advances the message offset. + * + * @tparam ObjectType The object type to read from the message. + * + * @param[out] aObject A reference to the object to read into. + * + * @retval kErrorNone Object @p aObject was successfully read from message. Message offset is advanced. + * @retval kErrorParse Not enough bytes remaining in message to read the entire object. Offset is unchanged. + */ + template Error ReadAtAndAdvanceOffset(ObjectType &aObject) + { + static_assert(!TypeTraits::IsPointer::kValue, "ObjectType must not be a pointer"); + + return ReadAtAndAdvanceOffset(&aObject, sizeof(ObjectType)); + } + /** * Compares the bytes in the message at a given offset with a given byte array. * diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp index 46177b9bb..294e860a4 100644 --- a/src/core/net/dhcp6_client.cpp +++ b/src/core/net/dhcp6_client.cpp @@ -358,8 +358,7 @@ void Client::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessag Header header; - SuccessOrExit(aMessage.Read(aMessage.GetOffset(), header)); - aMessage.MoveOffset(sizeof(header)); + SuccessOrExit(aMessage.ReadAtAndAdvanceOffset(header)); if ((header.GetMsgType() == kMsgTypeReply) && (header.GetTransactionId() == mTransactionId)) { diff --git a/src/core/net/dhcp6_server.cpp b/src/core/net/dhcp6_server.cpp index 17211ad0e..2d449c940 100644 --- a/src/core/net/dhcp6_server.cpp +++ b/src/core/net/dhcp6_server.cpp @@ -177,8 +177,7 @@ void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessag { Header header; - SuccessOrExit(aMessage.Read(aMessage.GetOffset(), header)); - aMessage.MoveOffset(sizeof(header)); + SuccessOrExit(aMessage.ReadAtAndAdvanceOffset(header)); VerifyOrExit((header.GetMsgType() == kMsgTypeSolicit)); diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 4f42a1cda..e9d0f8b19 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -800,15 +800,13 @@ Error Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto) Error Ip6::HandleFragment(Message &aMessage) { - Error error = kErrorNone; + Error error; FragmentHeader fragmentHeader; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), fragmentHeader)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(fragmentHeader)); VerifyOrExit(fragmentHeader.GetOffset() == 0 && !fragmentHeader.IsMoreFlagSet(), error = kErrorDrop); - aMessage.MoveOffset(sizeof(fragmentHeader)); - exit: return error; } diff --git a/src/core/net/udp6.cpp b/src/core/net/udp6.cpp index 83c5d5fca..cfa3e4f09 100644 --- a/src/core/net/udp6.cpp +++ b/src/core/net/udp6.cpp @@ -450,13 +450,12 @@ Error Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo) Error error = kErrorNone; Header udpHeader; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), udpHeader)); - #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION SuccessOrExit(error = Checksum::VerifyMessageChecksum(aMessage, aMessageInfo, kProtoUdp)); #endif - aMessage.MoveOffset(sizeof(udpHeader)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(udpHeader)); + aMessageInfo.mPeerPort = udpHeader.GetSourcePort(); aMessageInfo.mSockPort = udpHeader.GetDestinationPort(); diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp index e289ee8b5..284b2c31c 100644 --- a/src/core/thread/lowpan.cpp +++ b/src/core/thread/lowpan.cpp @@ -261,7 +261,7 @@ Error Lowpan::Compress(Message &aMessage, uint8_t headerDepth = 0; uint8_t headerMaxDepth = aHeaderDepth; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), ip6Header)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(ip6Header)); FindContextToCompressAddress(ip6Header.GetSource(), srcContext); FindContextToCompressAddress(ip6Header.GetDestination(), dstContext); @@ -395,8 +395,6 @@ Error Lowpan::Compress(Message &aMessage, headerDepth++; - aMessage.MoveOffset(sizeof(ip6Header)); - nextHeader = static_cast(ip6Header.GetNextHeader()); while (headerDepth < headerMaxDepth) @@ -450,8 +448,7 @@ Error Lowpan::CompressExtensionHeader(Message &aMessage, FrameBuilder &aFrameBui uint16_t padLength = 0; uint8_t tmpByte; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), extHeader)); - aMessage.MoveOffset(sizeof(extHeader)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(extHeader)); tmpByte = kExtHdrDispatch | kExtHdrEidHbh; @@ -526,7 +523,7 @@ Error Lowpan::CompressUdp(Message &aMessage, FrameBuilder &aFrameBuilder) uint16_t source; uint16_t destination; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), udpHeader)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(udpHeader)); source = udpHeader.GetSourcePort(); destination = udpHeader.GetDestinationPort(); @@ -556,8 +553,6 @@ Error Lowpan::CompressUdp(Message &aMessage, FrameBuilder &aFrameBuilder) SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(udpHeader.GetChecksum())); - aMessage.MoveOffset(sizeof(udpHeader)); - exit: if (error != kErrorNone) { diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index ac6c6071d..4175d9411 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1564,13 +1564,11 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn VerifyOrExit(aMessageInfo.GetHopLimit() == kMleHopLimit, error = kErrorParse); - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), securitySuite)); - aMessage.MoveOffset(sizeof(securitySuite)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(securitySuite)); if (securitySuite == kNoSecurity) { - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), command)); - aMessage.MoveOffset(sizeof(command)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(command)); switch (command) { @@ -1593,8 +1591,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn VerifyOrExit(!IsDisabled(), error = kErrorInvalidState); VerifyOrExit(securitySuite == k154Security, error = kErrorParse); - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), header)); - aMessage.MoveOffset(sizeof(header)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(header)); VerifyOrExit(header.IsSecurityControlValid(), error = kErrorParse); @@ -1604,8 +1601,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn SuccessOrExit( error = ProcessMessageSecurity(Crypto::AesCcm::kDecrypt, aMessage, aMessageInfo, aMessage.GetOffset(), header)); - IgnoreError(aMessage.Read(aMessage.GetOffset(), command)); - aMessage.MoveOffset(sizeof(command)); + IgnoreError(aMessage.ReadAtAndAdvanceOffset(command)); extAddr.SetFromIid(aMessageInfo.GetPeerAddr().GetIid()); neighbor = (command == kCommandChildIdResponse) ? mNeighborTable.FindParent(extAddr)