mirror of
https://github.com/espressif/openthread.git
synced 2026-09-24 09:57:38 +00:00
[message] define Message::Checker and common predicate helpers (#13641)
This commit harmonizes message filtering and predicate checking across core modules by defining a common `Message::Checker` type and providing reusable simpler `Accept*` helper functions in the `Message` class. Previously, `IndirectSender` and `MeshForwarder` defined their own local predicate typedefs (`MessageChecker`), and callers like `IndirectSender` and `Mle` implemented ad-hoc static checker functions.
This commit is contained in:
@@ -351,6 +351,16 @@ public:
|
||||
kOriginHostUntrusted = OT_MESSAGE_ORIGIN_HOST_UNTRUSTED, // Message from an untrusted source on host.
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a predicate function reference which is used to check or filter a message.
|
||||
*
|
||||
* @param[in] aMessage The message to check.
|
||||
*
|
||||
* @retval TRUE If the message matches the criteria.
|
||||
* @retval FALSE If the message does not match the criteria.
|
||||
*/
|
||||
typedef bool (&Checker)(const Message &aMessage);
|
||||
|
||||
/**
|
||||
* Represents settings used for creating a new message.
|
||||
*/
|
||||
@@ -1595,6 +1605,59 @@ public:
|
||||
|
||||
#endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Helper common predicate `Checker` functions
|
||||
|
||||
/**
|
||||
* Predicate checker function that matches and accepts any message.
|
||||
*
|
||||
* @param[in] aMessage The message to check.
|
||||
*
|
||||
* @retval TRUE Always matches and accepts the message.
|
||||
*/
|
||||
static bool AcceptAny(const Message &aMessage)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Predicate checker function that checks whether a message matches a specific type.
|
||||
*
|
||||
* @tparam kType The message type to match.
|
||||
*
|
||||
* @param[in] aMessage The message to check.
|
||||
*
|
||||
* @retval TRUE The message type matches @p kType.
|
||||
* @retval FALSE The message type does not match @p kType.
|
||||
*/
|
||||
template <Type kType> static bool AcceptType(const Message &aMessage) { return aMessage.GetType() == kType; }
|
||||
|
||||
/**
|
||||
* Predicate checker function that checks whether a message is of MLE subtype.
|
||||
*
|
||||
* @param[in] aMessage The message to check.
|
||||
*
|
||||
* @retval TRUE The message is of MLE subtype.
|
||||
* @retval FALSE The message is not of MLE subtype.
|
||||
*/
|
||||
static bool AcceptAnyMle(const Message &aMessage) { return aMessage.IsSubTypeMle(); }
|
||||
|
||||
/**
|
||||
* Predicate checker function that checks whether a message is a specific MLE command.
|
||||
*
|
||||
* @tparam kMleCommand The MLE command to match.
|
||||
*
|
||||
* @param[in] aMessage The message to check.
|
||||
*
|
||||
* @retval TRUE The message is an MLE command of @p kMleCommand type.
|
||||
* @retval FALSE The message is not an MLE command of @p kMleCommand type.
|
||||
*/
|
||||
template <Mle::Command kMleCommand> static bool AcceptMle(const Message &aMessage)
|
||||
{
|
||||
return aMessage.IsMleCommand(kMleCommand);
|
||||
}
|
||||
|
||||
protected:
|
||||
class OT_GSL_POINTER ConstIterator : public ItemPtrIterator<const Message, ConstIterator>
|
||||
{
|
||||
|
||||
@@ -104,7 +104,9 @@ void IndirectSender::AddMessageForSleepyChild(Message &aMessage, Child &aChild)
|
||||
|
||||
if ((aMessage.GetType() != Message::kTypeSupervision) && (aChild.GetIndirectMessageCount() > 1))
|
||||
{
|
||||
Message *supervisionMessage = FindQueuedMessageForSleepyChild(aChild, AcceptSupervisionMessage);
|
||||
Message *supervisionMessage;
|
||||
|
||||
supervisionMessage = FindQueuedMessageForSleepyChild(aChild, Message::AcceptType<Message::kTypeSupervision>);
|
||||
|
||||
if (supervisionMessage != nullptr)
|
||||
{
|
||||
@@ -158,7 +160,7 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
const Message *IndirectSender::FindQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker) const
|
||||
const Message *IndirectSender::FindQueuedMessageForSleepyChild(const Child &aChild, Message::Checker aChecker) const
|
||||
{
|
||||
const Message *match = nullptr;
|
||||
uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
|
||||
@@ -260,7 +262,7 @@ void IndirectSender::RequestMessageUpdate(Child &aChild)
|
||||
|
||||
VerifyOrExit(!aChild.IsWaitingForMessageUpdate());
|
||||
|
||||
newMessage = FindQueuedMessageForSleepyChild(aChild, AcceptAnyMessage);
|
||||
newMessage = FindQueuedMessageForSleepyChild(aChild, Message::AcceptAny);
|
||||
|
||||
VerifyOrExit(curMessage != newMessage);
|
||||
|
||||
@@ -303,7 +305,7 @@ exit:
|
||||
|
||||
void IndirectSender::UpdateIndirectMessage(Child &aChild)
|
||||
{
|
||||
Message *message = FindQueuedMessageForSleepyChild(aChild, AcceptAnyMessage);
|
||||
Message *message = FindQueuedMessageForSleepyChild(aChild, Message::AcceptAny);
|
||||
|
||||
aChild.SetWaitingForMessageUpdate(false);
|
||||
aChild.SetIndirectMessage(message);
|
||||
@@ -533,18 +535,6 @@ void IndirectSender::ClearMessagesForRemovedChildren(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool IndirectSender::AcceptAnyMessage(const Message &aMessage)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IndirectSender::AcceptSupervisionMessage(const Message &aMessage)
|
||||
{
|
||||
return aMessage.GetType() == Message::kTypeSupervision;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
|
||||
@@ -137,16 +137,6 @@ public:
|
||||
"mQueuedMessageCount cannot fit max required!");
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents a predicate function for checking if a given `Message` meets specific criteria.
|
||||
*
|
||||
* @param[in] aMessage The message to evaluate.
|
||||
*
|
||||
* @retval TRUE If the @p aMessage satisfies the predicate condition.
|
||||
* @retval FALSE If the @p aMessage does not satisfy the predicate condition.
|
||||
*/
|
||||
typedef bool (&MessageChecker)(const Message &aMessage);
|
||||
|
||||
/**
|
||||
* Initializes the object.
|
||||
*
|
||||
@@ -195,7 +185,7 @@ public:
|
||||
|
||||
/**
|
||||
* Finds the first queued message for a given sleepy child that also satisfies the conditions of a given
|
||||
* `MessageChecker`.
|
||||
* `Message::Checker`.
|
||||
*
|
||||
* The caller MUST ensure that @p aChild is sleepy.
|
||||
*
|
||||
@@ -204,14 +194,14 @@ public:
|
||||
*
|
||||
* @returns A pointer to the matching queued message, or `nullptr` if none is found.
|
||||
*/
|
||||
Message *FindQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker)
|
||||
Message *FindQueuedMessageForSleepyChild(const Child &aChild, Message::Checker aChecker)
|
||||
{
|
||||
return AsNonConst(AsConst(this)->FindQueuedMessageForSleepyChild(aChild, aChecker));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first queued message for a given sleepy child that also satisfies the conditions of a given
|
||||
* `MessageChecker`.
|
||||
* `Message::Checker`.
|
||||
*
|
||||
* The caller MUST ensure that @p aChild is sleepy.
|
||||
*
|
||||
@@ -220,11 +210,11 @@ public:
|
||||
*
|
||||
* @returns A pointer to the matching queued message, or `nullptr` if none is found.
|
||||
*/
|
||||
const Message *FindQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker) const;
|
||||
const Message *FindQueuedMessageForSleepyChild(const Child &aChild, Message::Checker aChecker) const;
|
||||
|
||||
/**
|
||||
* Indicates whether there is any queued message for a given sleepy child that also satisfies the conditions of a
|
||||
* given `MessageChecker`.
|
||||
* given `Message::Checker`.
|
||||
*
|
||||
* The caller MUST ensure that @p aChild is sleepy.
|
||||
*
|
||||
@@ -234,7 +224,7 @@ public:
|
||||
* @retval TRUE There is a queued message satisfying @p aChecker for sleepy child @p aChild.
|
||||
* @retval FALSE There is no queued message satisfying @p aChecker for sleepy child @p aChild.
|
||||
*/
|
||||
bool HasQueuedMessageForSleepyChild(const Child &aChild, MessageChecker aChecker) const
|
||||
bool HasQueuedMessageForSleepyChild(const Child &aChild, Message::Checker aChecker) const
|
||||
{
|
||||
return (FindQueuedMessageForSleepyChild(aChild, aChecker) != nullptr);
|
||||
}
|
||||
@@ -279,9 +269,6 @@ private:
|
||||
void UpdateIndirectMessage(Child &aChild);
|
||||
void RequestMessageUpdate(Child &aChild);
|
||||
void ClearMessagesForRemovedChildren(void);
|
||||
|
||||
static bool AcceptAnyMessage(const Message &aMessage);
|
||||
static bool AcceptSupervisionMessage(const Message &aMessage);
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
bool mEnabled;
|
||||
|
||||
@@ -162,17 +162,15 @@ public:
|
||||
void SetRxOnWhenIdle(bool aRxOnWhenIdle);
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
typedef IndirectSender::MessageChecker MessageChecker; ///< General predicate function checking a message.
|
||||
|
||||
/**
|
||||
* Removes and frees messages queued for a child, based on a given predicate.
|
||||
*
|
||||
* The `aChild` can be either sleepy or non-sleepy.
|
||||
*
|
||||
* @param[in] aChild The child whose messages are to be evaluated.
|
||||
* @param[in] aMessageChecker The predicate function to filter messages.
|
||||
* @param[in] aChecker The predicate function to filter messages.
|
||||
*/
|
||||
void RemoveMessagesForChild(Child &aChild, MessageChecker aMessageChecker);
|
||||
void RemoveMessagesForChild(Child &aChild, Message::Checker aChecker);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -259,11 +259,11 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MeshForwarder::RemoveMessagesForChild(Child &aChild, MessageChecker &aMessageChecker)
|
||||
void MeshForwarder::RemoveMessagesForChild(Child &aChild, Message::Checker aChecker)
|
||||
{
|
||||
for (Message &message : mSendQueue)
|
||||
{
|
||||
if (!aMessageChecker(message))
|
||||
if (!aChecker(message))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2429,8 +2429,6 @@ private:
|
||||
|
||||
DeclareTmfResponseHandlerIn(Mle, HandleAddressSolicitResponse);
|
||||
|
||||
static bool IsMessageMleSubType(const Message &aMessage);
|
||||
static bool IsMessageChildUpdateRequest(const Message &aMessage);
|
||||
static void HandleAdvertiseTrickleTimer(TrickleTimer &aTimer);
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||
|
||||
@@ -2022,13 +2022,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool Mle::IsMessageMleSubType(const Message &aMessage) { return aMessage.IsSubTypeMle(); }
|
||||
|
||||
bool Mle::IsMessageChildUpdateRequest(const Message &aMessage)
|
||||
{
|
||||
return aMessage.IsMleCommand(kCommandChildUpdateRequest);
|
||||
}
|
||||
|
||||
void Mle::HandleChildIdRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -2059,7 +2052,7 @@ void Mle::HandleChildIdRequest(RxInfo &aRxInfo)
|
||||
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadAndMatchResponseTlvWith(child->GetChallenge()));
|
||||
|
||||
Get<MeshForwarder>().RemoveMessagesForChild(*child, IsMessageMleSubType);
|
||||
Get<MeshForwarder>().RemoveMessagesForChild(*child, Message::AcceptAnyMle);
|
||||
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadFrameCounterTlvs(linkFrameCounter, mleFrameCounter));
|
||||
|
||||
@@ -2939,10 +2932,11 @@ Error Mle::SendChildUpdateRequestToChild(Child &aChild)
|
||||
// to the sleepy child if there is one already
|
||||
// queued.
|
||||
|
||||
VerifyOrExit(!Get<IndirectSender>().HasQueuedMessageForSleepyChild(aChild, IsMessageChildUpdateRequest));
|
||||
VerifyOrExit(!Get<IndirectSender>().HasQueuedMessageForSleepyChild(
|
||||
aChild, Message::AcceptMle<kCommandChildUpdateRequest>));
|
||||
}
|
||||
|
||||
Get<MeshForwarder>().RemoveMessagesForChild(aChild, IsMessageChildUpdateRequest);
|
||||
Get<MeshForwarder>().RemoveMessagesForChild(aChild, Message::AcceptMle<kCommandChildUpdateRequest>);
|
||||
|
||||
VerifyOrExit((message = NewMleMessage(kCommandChildUpdateRequest)) != nullptr, error = kErrorNoBufs);
|
||||
SuccessOrExit(error = message->AppendSourceAddressAndLeaderDataTlvs());
|
||||
|
||||
Reference in New Issue
Block a user