mirror of
https://github.com/espressif/openthread.git
synced 2026-09-25 10:27:37 +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.
|
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.
|
* Represents settings used for creating a new message.
|
||||||
*/
|
*/
|
||||||
@@ -1595,6 +1605,59 @@ public:
|
|||||||
|
|
||||||
#endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
|
#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:
|
protected:
|
||||||
class OT_GSL_POINTER ConstIterator : public ItemPtrIterator<const Message, ConstIterator>
|
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))
|
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)
|
if (supervisionMessage != nullptr)
|
||||||
{
|
{
|
||||||
@@ -158,7 +160,7 @@ exit:
|
|||||||
return;
|
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;
|
const Message *match = nullptr;
|
||||||
uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
|
uint16_t childIndex = Get<ChildTable>().GetChildIndex(aChild);
|
||||||
@@ -260,7 +262,7 @@ void IndirectSender::RequestMessageUpdate(Child &aChild)
|
|||||||
|
|
||||||
VerifyOrExit(!aChild.IsWaitingForMessageUpdate());
|
VerifyOrExit(!aChild.IsWaitingForMessageUpdate());
|
||||||
|
|
||||||
newMessage = FindQueuedMessageForSleepyChild(aChild, AcceptAnyMessage);
|
newMessage = FindQueuedMessageForSleepyChild(aChild, Message::AcceptAny);
|
||||||
|
|
||||||
VerifyOrExit(curMessage != newMessage);
|
VerifyOrExit(curMessage != newMessage);
|
||||||
|
|
||||||
@@ -303,7 +305,7 @@ exit:
|
|||||||
|
|
||||||
void IndirectSender::UpdateIndirectMessage(Child &aChild)
|
void IndirectSender::UpdateIndirectMessage(Child &aChild)
|
||||||
{
|
{
|
||||||
Message *message = FindQueuedMessageForSleepyChild(aChild, AcceptAnyMessage);
|
Message *message = FindQueuedMessageForSleepyChild(aChild, Message::AcceptAny);
|
||||||
|
|
||||||
aChild.SetWaitingForMessageUpdate(false);
|
aChild.SetWaitingForMessageUpdate(false);
|
||||||
aChild.SetIndirectMessage(message);
|
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
|
#endif // OPENTHREAD_FTD
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||||
|
|||||||
@@ -137,16 +137,6 @@ public:
|
|||||||
"mQueuedMessageCount cannot fit max required!");
|
"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.
|
* 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
|
* 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.
|
* 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.
|
* @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));
|
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
|
* 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.
|
* 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.
|
* @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
|
* 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.
|
* 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 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.
|
* @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);
|
return (FindQueuedMessageForSleepyChild(aChild, aChecker) != nullptr);
|
||||||
}
|
}
|
||||||
@@ -279,9 +269,6 @@ private:
|
|||||||
void UpdateIndirectMessage(Child &aChild);
|
void UpdateIndirectMessage(Child &aChild);
|
||||||
void RequestMessageUpdate(Child &aChild);
|
void RequestMessageUpdate(Child &aChild);
|
||||||
void ClearMessagesForRemovedChildren(void);
|
void ClearMessagesForRemovedChildren(void);
|
||||||
|
|
||||||
static bool AcceptAnyMessage(const Message &aMessage);
|
|
||||||
static bool AcceptSupervisionMessage(const Message &aMessage);
|
|
||||||
#endif // OPENTHREAD_FTD
|
#endif // OPENTHREAD_FTD
|
||||||
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
|
|||||||
@@ -162,17 +162,15 @@ public:
|
|||||||
void SetRxOnWhenIdle(bool aRxOnWhenIdle);
|
void SetRxOnWhenIdle(bool aRxOnWhenIdle);
|
||||||
|
|
||||||
#if OPENTHREAD_FTD
|
#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.
|
* Removes and frees messages queued for a child, based on a given predicate.
|
||||||
*
|
*
|
||||||
* The `aChild` can be either sleepy or non-sleepy.
|
* The `aChild` can be either sleepy or non-sleepy.
|
||||||
*
|
*
|
||||||
* @param[in] aChild The child whose messages are to be evaluated.
|
* @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
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -259,11 +259,11 @@ exit:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshForwarder::RemoveMessagesForChild(Child &aChild, MessageChecker &aMessageChecker)
|
void MeshForwarder::RemoveMessagesForChild(Child &aChild, Message::Checker aChecker)
|
||||||
{
|
{
|
||||||
for (Message &message : mSendQueue)
|
for (Message &message : mSendQueue)
|
||||||
{
|
{
|
||||||
if (!aMessageChecker(message))
|
if (!aChecker(message))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2429,8 +2429,6 @@ private:
|
|||||||
|
|
||||||
DeclareTmfResponseHandlerIn(Mle, HandleAddressSolicitResponse);
|
DeclareTmfResponseHandlerIn(Mle, HandleAddressSolicitResponse);
|
||||||
|
|
||||||
static bool IsMessageMleSubType(const Message &aMessage);
|
|
||||||
static bool IsMessageChildUpdateRequest(const Message &aMessage);
|
|
||||||
static void HandleAdvertiseTrickleTimer(TrickleTimer &aTimer);
|
static void HandleAdvertiseTrickleTimer(TrickleTimer &aTimer);
|
||||||
|
|
||||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||||
|
|||||||
@@ -2022,13 +2022,6 @@ exit:
|
|||||||
return error;
|
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)
|
void Mle::HandleChildIdRequest(RxInfo &aRxInfo)
|
||||||
{
|
{
|
||||||
Error error = kErrorNone;
|
Error error = kErrorNone;
|
||||||
@@ -2059,7 +2052,7 @@ void Mle::HandleChildIdRequest(RxInfo &aRxInfo)
|
|||||||
|
|
||||||
SuccessOrExit(error = aRxInfo.mMessage.ReadAndMatchResponseTlvWith(child->GetChallenge()));
|
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));
|
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
|
// to the sleepy child if there is one already
|
||||||
// queued.
|
// 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);
|
VerifyOrExit((message = NewMleMessage(kCommandChildUpdateRequest)) != nullptr, error = kErrorNoBufs);
|
||||||
SuccessOrExit(error = message->AppendSourceAddressAndLeaderDataTlvs());
|
SuccessOrExit(error = message->AppendSourceAddressAndLeaderDataTlvs());
|
||||||
|
|||||||
Reference in New Issue
Block a user