[message] introduce FooterData<DataType> class (#10760)

This commit adds the `Message::FooterData<>` template class, which
represents data (typically metadata) associated with a `Message` that
is appended to the end of the message. It can be read later from the
message, updated (re-written) in the message, or fully removed from
it.

The `FooterData` class provides common helper methods such as
`AppendTo()`, `ReadFrom()`, `UpdateIn()`, and `RemoveFrom()` in a
generic way. This helps simplify the various `Metadata` types defined
within the OT core modules, removing repeated definitions of similar
methods for each type.
This commit is contained in:
Abtin Keshavarzian
2024-09-30 10:24:23 -07:00
committed by GitHub
parent 4434862f4c
commit 3a28b7bbdf
12 changed files with 73 additions and 102 deletions
-21
View File
@@ -1449,19 +1449,6 @@ exit:
}
}
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)
{
+2 -9
View File
@@ -315,11 +315,8 @@ public:
private:
static constexpr uint16_t kMaxCachedResponses = OPENTHREAD_CONFIG_COAP_SERVER_MAX_CACHED_RESPONSES;
struct ResponseMetadata
struct ResponseMetadata : public Message::FooterData<ResponseMetadata>
{
Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
void ReadFrom(const Message &aMessage);
TimeMilli mDequeueTime;
Ip6::MessageInfo mMessageInfo;
};
@@ -793,12 +790,8 @@ protected:
void SetResourceHandler(ResourceHandler aHandler) { mResourceHandler = aHandler; }
private:
struct Metadata
struct Metadata : public Message::FooterData<Metadata>
{
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.
+65
View File
@@ -405,6 +405,71 @@ public:
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<DataType>`.
*
* @tparam DataType The footer data type.
*/
template <typename DataType> 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<DataType>(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<DataType>(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<DataType>(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<const DataType &>(*this); }
DataType &AsDataType(void) { return static_cast<DataType &>(*this); }
};
/**
* Returns a reference to the OpenThread Instance which owns the `Message`.
*
-8
View File
@@ -334,14 +334,6 @@ exit:
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
+1 -4
View File
@@ -85,11 +85,8 @@ private:
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<JoinerEntrustMetadata>
{
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.
-12
View File
@@ -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;
+1 -5
View File
@@ -445,12 +445,8 @@ private:
NameOffsets mOffsets;
};
struct ProxyQueryInfo
struct ProxyQueryInfo : Message::FooterData<ProxyQueryInfo>
{
void ReadFrom(const ProxyQuery &aQuery);
void RemoveFrom(ProxyQuery &aQuery) const;
void UpdateIn(ProxyQuery &aQuery) const;
QueryType mType;
Ip6::MessageInfo mMessageInfo;
TimeMilli mExpireTime;
-12
View File
@@ -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.
+2 -6
View File
@@ -219,13 +219,9 @@ private:
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<Metadata>
{
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;
+1 -10
View File
@@ -236,17 +236,8 @@ private:
uint32_t mTransmitTimestampFraction; // Fraction part of above value.
} OT_TOOL_PACKED_END;
class QueryMetadata
struct QueryMetadata : public Message::FooterData<QueryMetadata>
{
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<ResponseHandler> mResponseHandler; // Response handler callback
TimeMilli mTransmissionTime; // Time when the timer should shoot for this message
-10
View File
@@ -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
+1 -5
View File
@@ -1103,12 +1103,8 @@ private:
const MessageQueue &GetQueue(void) const { return mQueue; }
private:
struct Metadata
struct Metadata : public Message::FooterData<Metadata>
{
Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
void ReadFrom(const Message &aMessage);
void RemoveFrom(Message &aMessage) const;
Ip6::Address mDestination;
TimeMilli mSendTime;
};