diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index 8f4a7b816f6..179122397de 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -1449,19 +1449,6 @@ void CoapBase::ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo } } -void CoapBase::Metadata::ReadFrom(const Message &aMessage) -{ - uint16_t length = aMessage.GetLength(); - - OT_ASSERT(length >= sizeof(*this)); - IgnoreError(aMessage.Read(length - sizeof(*this), *this)); -} - -void CoapBase::Metadata::UpdateIn(Message &aMessage) const -{ - aMessage.Write(aMessage.GetLength() - sizeof(*this), *this); -} - ResponsesQueue::ResponsesQueue(Instance &aInstance) : mTimer(aInstance, ResponsesQueue::HandleTimer, this) { @@ -1596,14 +1583,6 @@ void ResponsesQueue::HandleTimer(void) mTimer.FireAt(nextDequeueTime); } -void ResponsesQueue::ResponseMetadata::ReadFrom(const Message &aMessage) -{ - uint16_t length = aMessage.GetLength(); - - OT_ASSERT(length >= sizeof(*this)); - IgnoreError(aMessage.Read(length - sizeof(*this), *this)); -} - /// Return product of @p aValueA and @p aValueB if no overflow otherwise 0. static uint32_t Multiply(uint32_t aValueA, uint32_t aValueB) { diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index f558bb0c52b..03f0d4b4de9 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -315,11 +315,8 @@ class ResponsesQueue private: static constexpr uint16_t kMaxCachedResponses = OPENTHREAD_CONFIG_COAP_SERVER_MAX_CACHED_RESPONSES; - struct ResponseMetadata + struct ResponseMetadata : public Message::FooterData { - Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } - void ReadFrom(const Message &aMessage); - TimeMilli mDequeueTime; Ip6::MessageInfo mMessageInfo; }; @@ -793,12 +790,8 @@ class CoapBase : public InstanceLocator, private NonCopyable void SetResourceHandler(ResourceHandler aHandler) { mResourceHandler = aHandler; } private: - struct Metadata + struct Metadata : public Message::FooterData { - Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } - void ReadFrom(const Message &aMessage); - void UpdateIn(Message &aMessage) const; - Ip6::Address mSourceAddress; // IPv6 address of the message source. Ip6::Address mDestinationAddress; // IPv6 address of the message destination. uint16_t mDestinationPort; // UDP port of the message destination. diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp index 1cb6100375e..c3f6187faf9 100644 --- a/src/core/common/message.hpp +++ b/src/core/common/message.hpp @@ -405,6 +405,71 @@ class Message : public otMessage, public Buffer, public GetProvider static const otMessageSettings kDefault; }; + /** + * Represents footer data appended to the end of a `Message`. + * + * This data typically represents some metadata associated with the `Message` that is appended to its end. It can + * be read later from the message, updated (re-written) in the message, or fully removed from it. + * + * Users of `FooterData` MUST follow CRTP-style inheritance, i.e., the `DataType` itself MUST publicly inherit + * from `FooterData`. + * + * @tparam DataType The footer data type. + */ + template class FooterData + { + public: + /** + * Appends the footer data to the end of a given message. + * + * @param[in,out] aMessage The message to append to. + * + * @retval kErrorNone Successfully appended the footer data. + * @retval kErrorNoBufs Insufficient available buffers to grow the message. + */ + Error AppendTo(Message &aMessage) const { return aMessage.Append(AsDataType()); } + + /** + * Reads the footer data from a given message. + * + * Caller MUST ensure data was successfully appended to the message beforehand. Otherwise behavior is undefined. + * + * @param[in] aMessage The message to read from. + */ + void ReadFrom(const Message &aMessage) + { + IgnoreError(aMessage.Read(aMessage.GetLength() - sizeof(DataType), AsDataType())); + } + + /** + * Updates the footer data in a given message (rewriting over the previously appended data). + * + * Caller MUST ensure data was successfully appended to the message beforehand. Otherwise behavior is undefined. + * + * @param[in,out] aMessage The message to update. + */ + void UpdateIn(Message &aMessage) const + { + aMessage.Write(aMessage.GetLength() - sizeof(DataType), AsDataType()); + } + + /** + * Removes the footer data from a given message. + * + * Caller MUST ensure data was successfully appended to the message beforehand. Otherwise behavior is undefined. + * + * @param[in,out] aMessage The message to remove the data from. + */ + void RemoveFrom(Message &aMessage) const { aMessage.RemoveFooter(sizeof(DataType)); } + + protected: + FooterData(void) = default; + + private: + const DataType &AsDataType(void) const { return static_cast(*this); } + DataType &AsDataType(void) { return static_cast(*this); } + }; + /** * Returns a reference to the OpenThread Instance which owns the `Message`. * diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index efe84beb617..e7f6d2d1e17 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -334,14 +334,6 @@ void JoinerRouter::HandleJoinerEntrustResponse(Coap::Message *aMessage, return; } -void JoinerRouter::JoinerEntrustMetadata::ReadFrom(const Message &aMessage) -{ - uint16_t length = aMessage.GetLength(); - - OT_ASSERT(length >= sizeof(*this)); - IgnoreError(aMessage.Read(length - sizeof(*this), *this)); -} - } // namespace MeshCoP } // namespace ot diff --git a/src/core/meshcop/joiner_router.hpp b/src/core/meshcop/joiner_router.hpp index 662413ca8a5..b817bd31c6b 100644 --- a/src/core/meshcop/joiner_router.hpp +++ b/src/core/meshcop/joiner_router.hpp @@ -85,11 +85,8 @@ class JoinerRouter : public InstanceLocator, private NonCopyable static constexpr uint16_t kDefaultJoinerUdpPort = OPENTHREAD_CONFIG_JOINER_UDP_PORT; static constexpr uint32_t kJoinerEntrustTxDelay = 50; // in msec - struct JoinerEntrustMetadata + struct JoinerEntrustMetadata : public Message::FooterData { - Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } - void ReadFrom(const Message &aMessage); - Ip6::MessageInfo mMessageInfo; // Message info of the message to send. TimeMilli mSendTime; // Time when the message shall be sent. Kek mKek; // KEK used by MAC layer to encode this message. diff --git a/src/core/net/dnssd_server.cpp b/src/core/net/dnssd_server.cpp index c72faebf4a0..31c085351c5 100644 --- a/src/core/net/dnssd_server.cpp +++ b/src/core/net/dnssd_server.cpp @@ -1123,18 +1123,6 @@ void Server::ConstructFullServiceSubTypeName(const char *aServiceType, fullName.Append("%s._sub.%s.%s", aSubTypeLabel, aServiceType, kDefaultDomainName); } -void Server::ProxyQueryInfo::ReadFrom(const ProxyQuery &aQuery) -{ - SuccessOrAssert(aQuery.Read(aQuery.GetLength() - sizeof(ProxyQueryInfo), *this)); -} - -void Server::ProxyQueryInfo::RemoveFrom(ProxyQuery &aQuery) const { aQuery.RemoveFooter(sizeof(ProxyQueryInfo)); } - -void Server::ProxyQueryInfo::UpdateIn(ProxyQuery &aQuery) const -{ - aQuery.Write(aQuery.GetLength() - sizeof(ProxyQueryInfo), *this); -} - Error Server::Response::ExtractServiceInstanceLabel(const char *aInstanceName, Name::LabelBuffer &aLabel) { uint16_t offset; diff --git a/src/core/net/dnssd_server.hpp b/src/core/net/dnssd_server.hpp index c18af7f631b..d5e2daad29e 100644 --- a/src/core/net/dnssd_server.hpp +++ b/src/core/net/dnssd_server.hpp @@ -445,12 +445,8 @@ class Server : public InstanceLocator, private NonCopyable NameOffsets mOffsets; }; - struct ProxyQueryInfo + struct ProxyQueryInfo : Message::FooterData { - void ReadFrom(const ProxyQuery &aQuery); - void RemoveFrom(ProxyQuery &aQuery) const; - void UpdateIn(ProxyQuery &aQuery) const; - QueryType mType; Ip6::MessageInfo mMessageInfo; TimeMilli mExpireTime; diff --git a/src/core/net/ip6_mpl.cpp b/src/core/net/ip6_mpl.cpp index b0ffd9138f2..f36ffd35c7c 100644 --- a/src/core/net/ip6_mpl.cpp +++ b/src/core/net/ip6_mpl.cpp @@ -446,18 +446,6 @@ void Mpl::HandleRetransmissionTimer(void) mRetransmissionTimer.FireAt(nextTime); } -void Mpl::Metadata::ReadFrom(const Message &aMessage) -{ - uint16_t length = aMessage.GetLength(); - - OT_ASSERT(length >= sizeof(*this)); - IgnoreError(aMessage.Read(length - sizeof(*this), *this)); -} - -void Mpl::Metadata::RemoveFrom(Message &aMessage) const { aMessage.RemoveFooter(sizeof(*this)); } - -void Mpl::Metadata::UpdateIn(Message &aMessage) const { aMessage.Write(aMessage.GetLength() - sizeof(*this), *this); } - void Mpl::Metadata::GenerateNextTransmissionTime(TimeMilli aCurrentTime, uint8_t aInterval) { // Emulate Trickle timer behavior and set up the next retransmission within [0,I) range. diff --git a/src/core/net/ip6_mpl.hpp b/src/core/net/ip6_mpl.hpp index 697790d21f7..8f88564dccc 100644 --- a/src/core/net/ip6_mpl.hpp +++ b/src/core/net/ip6_mpl.hpp @@ -219,13 +219,9 @@ class Mpl : public InstanceLocator, private NonCopyable static constexpr uint8_t kChildRetransmissions = 0; // MPL retransmissions for Children. static constexpr uint8_t kRouterRetransmissions = 2; // MPL retransmissions for Routers. - struct Metadata + struct Metadata : public Message::FooterData { - Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } - void ReadFrom(const Message &aMessage); - void RemoveFrom(Message &aMessage) const; - void UpdateIn(Message &aMessage) const; - void GenerateNextTransmissionTime(TimeMilli aCurrentTime, uint8_t aInterval); + void GenerateNextTransmissionTime(TimeMilli aCurrentTime, uint8_t aInterval); TimeMilli mTransmissionTime; uint16_t mSeedId; diff --git a/src/core/net/sntp_client.hpp b/src/core/net/sntp_client.hpp index a0ebd1dc2b1..103089fbe93 100644 --- a/src/core/net/sntp_client.hpp +++ b/src/core/net/sntp_client.hpp @@ -236,17 +236,8 @@ class Client : private NonCopyable uint32_t mTransmitTimestampFraction; // Fraction part of above value. } OT_TOOL_PACKED_END; - class QueryMetadata + struct QueryMetadata : public Message::FooterData { - public: - Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } - void ReadFrom(const Message &aMessage) - { - IgnoreError(aMessage.Read(aMessage.GetLength() - sizeof(*this), *this)); - } - - void UpdateIn(Message &aMessage) const { aMessage.Write(aMessage.GetLength() - sizeof(*this), *this); } - uint32_t mTransmitTimestamp; // Time at client when request departed for server Callback mResponseHandler; // Response handler callback TimeMilli mTransmissionTime; // Time when the timer should shoot for this message diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index bcc13430479..f1bf2454ec5 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -4413,16 +4413,6 @@ void Mle::DelayedSender::RemoveMessage(Message::SubType aSubType, } } -void Mle::DelayedSender::Metadata::ReadFrom(const Message &aMessage) -{ - uint16_t length = aMessage.GetLength(); - - OT_ASSERT(length >= sizeof(*this)); - IgnoreError(aMessage.Read(length - sizeof(*this), *this)); -} - -void Mle::DelayedSender::Metadata::RemoveFrom(Message &aMessage) const { aMessage.RemoveFooter(sizeof(*this)); } - //--------------------------------------------------------------------------------------------------------------------- // TxMessage diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 7de278f2141..c763436d3d9 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1103,12 +1103,8 @@ class Mle : public InstanceLocator, private NonCopyable const MessageQueue &GetQueue(void) const { return mQueue; } private: - struct Metadata + struct Metadata : public Message::FooterData { - Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); } - void ReadFrom(const Message &aMessage); - void RemoveFrom(Message &aMessage) const; - Ip6::Address mDestination; TimeMilli mSendTime; };