| /* |
| * Copyright (c) 2016, The OpenThread Authors. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the copyright holder nor the |
| * names of its contributors may be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @file |
| * This file includes definitions for the message buffer pool and message buffers. |
| */ |
| |
| #ifndef OT_CORE_COMMON_MESSAGE_HPP_ |
| #define OT_CORE_COMMON_MESSAGE_HPP_ |
| |
| #include "openthread-core-config.h" |
| |
| #include <stdint.h> |
| |
| #include <openthread/message.h> |
| #include <openthread/nat64.h> |
| #include <openthread/platform/messagepool.h> |
| |
| #include "common/as_core_type.hpp" |
| #include "common/clearable.hpp" |
| #include "common/code_utils.hpp" |
| #include "common/const_cast.hpp" |
| #include "common/data.hpp" |
| #include "common/encoding.hpp" |
| #include "common/iterator_utils.hpp" |
| #include "common/linked_list.hpp" |
| #include "common/locator.hpp" |
| #include "common/non_copyable.hpp" |
| #include "common/offset_range.hpp" |
| #include "common/pool.hpp" |
| #include "common/timer.hpp" |
| #include "common/type_traits.hpp" |
| #include "mac/mac_types.hpp" |
| #include "thread/child_mask.hpp" |
| #include "thread/link_quality.hpp" |
| #include "thread/thread_link_info.hpp" |
| |
| /** |
| * Represents an opaque (and empty) type for an OpenThread message buffer. |
| */ |
| struct otMessage |
| { |
| }; |
| |
| namespace ot { |
| |
| class UnitTester; |
| template <typename UintType> class CrcCalculator; |
| |
| namespace Crypto { |
| |
| class AesCcm; |
| class Sha256; |
| class HmacSha256; |
| |
| } // namespace Crypto |
| |
| /** |
| * @addtogroup core-message |
| * |
| * @brief |
| * This module includes definitions for the message buffer pool and message buffers. |
| * |
| * @{ |
| */ |
| |
| /** |
| * Frees a given message buffer if not `nullptr`. |
| * |
| * And the ones that follow contain small but common code patterns used in many of the core modules. They |
| * are intentionally defined as macros instead of inline methods/functions to ensure that they are fully inlined. |
| * Note that an `inline` method/function is not necessarily always inlined by the toolchain and not inlining such |
| * small implementations can add a rather large code-size overhead. |
| * |
| * @param[in] aMessage A pointer to a `Message` to free (can be `nullptr`). |
| */ |
| #define FreeMessage(aMessage) \ |
| do \ |
| { \ |
| if ((aMessage) != nullptr) \ |
| { \ |
| (aMessage)->Free(); \ |
| } \ |
| } while (false) |
| |
| /** |
| * Frees a given message buffer if a given `Error` indicates an error. |
| * |
| * The parameter @p aMessage can be `nullptr` in which case this macro does nothing. |
| * |
| * @param[in] aMessage A pointer to a `Message` to free (can be `nullptr`). |
| * @param[in] aError The `Error` to check. |
| */ |
| #define FreeMessageOnError(aMessage, aError) \ |
| do \ |
| { \ |
| if (((aError) != kErrorNone) && ((aMessage) != nullptr)) \ |
| { \ |
| (aMessage)->Free(); \ |
| } \ |
| } while (false) |
| |
| /** |
| * Frees a given message buffer if a given `Error` indicates an error and sets the `aMessage` to `nullptr`. |
| * |
| * @param[in] aMessage A pointer to a `Message` to free (can be `nullptr`). |
| * @param[in] aError The `Error` to check. |
| */ |
| #define FreeAndNullMessageOnError(aMessage, aError) \ |
| do \ |
| { \ |
| if (((aError) != kErrorNone) && ((aMessage) != nullptr)) \ |
| { \ |
| (aMessage)->Free(); \ |
| (aMessage) = nullptr; \ |
| } \ |
| } while (false) |
| |
| class Message; |
| class MessagePool; |
| class MessageQueue; |
| class PriorityQueue; |
| |
| /** |
| * Represents the link security mode indicating whether to use MAC (layer two) security. |
| */ |
| enum LinkSecurityMode : bool |
| { |
| kNoLinkSecurity = false, ///< Link security disabled (no link security). |
| kWithLinkSecurity = true, ///< Link security enabled. |
| }; |
| |
| /** |
| * Represents the clone mode indicating how the reserved header should be configured on the cloned message. |
| */ |
| enum CloneMode : uint8_t |
| { |
| kNoReservedHeader, ///< The clone message will have no reserved header. |
| kSameReservedHeader ///< The clone message will have the same reserved header size as the original `Message`. |
| }; |
| |
| /** |
| * Represents a Message buffer. |
| */ |
| class Buffer : public otMessageBuffer, public LinkedListEntry<Buffer> |
| { |
| friend class Message; |
| |
| public: |
| static constexpr uint16_t kSize = OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE; ///< Size of buffer in bytes. |
| |
| typedef otMessageTxCallback TxCallback; ///< Message TX callback. |
| |
| /** |
| * Returns a pointer to the next message buffer. |
| * |
| * @returns A pointer to the next message buffer. |
| */ |
| Buffer *GetNextBuffer(void) { return GetNext(); } |
| |
| /** |
| * Returns a pointer to the next message buffer. |
| * |
| * @returns A pointer to the next message buffer. |
| */ |
| const Buffer *GetNextBuffer(void) const { return GetNext(); } |
| |
| /** |
| * Sets the pointer to the next message buffer. |
| * |
| * @param[in] aNext A pointer to the next buffer. |
| */ |
| void SetNextBuffer(Buffer *aNext) { SetNext(aNext); } |
| |
| protected: |
| struct Metadata |
| { |
| #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE |
| Instance *mInstance; |
| #endif |
| bool mDirectTx : 1; // Whether a direct transmission is required. |
| bool mLinkSecurity : 1; // Whether link security is enabled. |
| bool mInPriorityQ : 1; // Whether the message is queued in normal or priority queue. |
| bool mTxSuccess : 1; // Whether the direct tx of the message was successful. |
| bool mDoNotEvict : 1; // Whether this message may be evicted. |
| bool mMulticastLoop : 1; // Whether this multicast message may be looped back. |
| bool mResolvingAddress : 1; // Whether the message is pending an address query resolution. |
| bool mAllowLookbackToHost : 1; // Whether the message is allowed to be looped back to host. |
| bool mIsDstPanIdBroadcast : 1; // Whether the dest PAN ID is broadcast. |
| #if OPENTHREAD_CONFIG_MULTI_RADIO |
| bool mIsRadioTypeSet : 1; // Whether the radio type is set. |
| #endif |
| #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE |
| bool mTimeSync : 1; // Whether the message is also used for time sync purpose. |
| #endif |
| uint8_t mPriority : 2; // The message priority level (higher value is higher priority). |
| uint8_t mOrigin : 2; // The origin of the message. |
| #if OPENTHREAD_CONFIG_MULTI_RADIO |
| uint8_t mRadioType : 2; // The radio link type the message was received on, or should be sent on. |
| static_assert(Mac::kNumRadioTypes <= (1 << 2), "mRadioType bitfield cannot store all radio type values"); |
| #endif |
| uint8_t mType : 3; // The message type. |
| uint8_t mSubType : 4; // The message sub type. |
| uint8_t mMleCommand; // The MLE command type (used when `mSubType is `Mle`). |
| uint8_t mChannel; // The message channel (used for MLE Announce). |
| #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE |
| uint8_t mTimeSyncSeq; // The time sync sequence. |
| #endif |
| uint16_t mLength; // Current message length (number of bytes). |
| uint16_t mOffset; // A byte offset within the message. |
| uint16_t mReserved; // Number of reserved bytes (for header). |
| uint16_t mMeshDest; // Used for unicast non-link-local messages. |
| uint16_t mPanId; // PAN ID (used for MLE Discover Request and Response). |
| uint32_t mDatagramTag; // The datagram tag used for 6LoWPAN frags or IPv6fragmentation. |
| #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE |
| int64_t mNetworkTimeOffset; // The time offset to the Thread network time, in microseconds. |
| #endif |
| TimeMilli mTimestamp; // The message timestamp. |
| Message *mNext; // Next message in a doubly linked list. |
| Message *mPrev; // Previous message in a doubly linked list. |
| TxCallback mTxCallback; // The callback to inform message TX success or failure. |
| void *mTxContext; // The arbitrary context associated with `mTxCallback`. |
| RssAverager mRssAverager; // The averager maintaining the received signal strength (RSS) average. |
| LqiAverager mLqiAverager; // The averager maintaining the Link quality indicator (LQI) average. |
| #if OPENTHREAD_FTD |
| ChildMask mChildMask; // ChildMask to indicate which sleepy children need to receive this. |
| #endif |
| }; |
| |
| static_assert(kSize > sizeof(Metadata) + sizeof(otMessageBuffer), "Metadata does not fit in a single buffer"); |
| |
| static constexpr uint16_t kBufferDataSize = kSize - sizeof(otMessageBuffer); |
| static constexpr uint16_t kHeadBufferDataSize = kBufferDataSize - sizeof(Metadata); |
| |
| Metadata &GetMetadata(void) { return mBuffer.mHead.mMetadata; } |
| const Metadata &GetMetadata(void) const { return mBuffer.mHead.mMetadata; } |
| |
| uint8_t *GetFirstData(void) { return mBuffer.mHead.mData; } |
| const uint8_t *GetFirstData(void) const { return mBuffer.mHead.mData; } |
| |
| uint8_t *GetData(void) { return mBuffer.mData; } |
| const uint8_t *GetData(void) const { return mBuffer.mData; } |
| |
| private: |
| union |
| { |
| struct |
| { |
| Metadata mMetadata; |
| uint8_t mData[kHeadBufferDataSize]; |
| } mHead; |
| uint8_t mData[kBufferDataSize]; |
| } mBuffer; |
| }; |
| |
| static_assert(sizeof(Buffer) >= Buffer::kSize, |
| "Buffer size is not valid. Increase OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE."); |
| |
| /** |
| * Represents a message. |
| */ |
| class Message : public otMessage, public Buffer, public GetProvider<Message> |
| { |
| friend class Checksum; |
| friend class CrcCalculator<uint16_t>; |
| friend class CrcCalculator<uint32_t>; |
| friend class Crypto::HmacSha256; |
| friend class Crypto::Sha256; |
| friend class Crypto::AesCcm; |
| friend class MessagePool; |
| friend class MessageQueue; |
| friend class PriorityQueue; |
| friend class ot::UnitTester; |
| |
| public: |
| /** |
| * Represents the message type. |
| */ |
| enum Type : uint8_t |
| { |
| kTypeIp6 = 0, ///< A full uncompressed IPv6 packet |
| kType6lowpan = 1, ///< A 6lowpan frame |
| kTypeSupervision = 2, ///< A child supervision frame. |
| kTypeMacEmptyData = 3, ///< An empty MAC data frame. |
| kTypeIp4 = 4, ///< A full uncompressed IPv4 packet, for NAT64. |
| kTypeBle = 5, ///< A BLE payload message. |
| kTypeOther = 6, ///< Other (data) message. |
| }; |
| |
| /** |
| * Represents the message sub-type. |
| */ |
| enum SubType : uint8_t |
| { |
| kSubTypeNone = 0, ///< None |
| kSubTypeMle = 1, ///< MLE message |
| kSubTypeMplRetransmission = 2, ///< MPL next retransmission message |
| kSubTypeJoinerEntrust = 3, ///< Joiner Entrust |
| kSubTypeJoinerFinalizeResponse = 4, ///< Joiner Finalize Response |
| |
| }; |
| |
| enum Priority : uint8_t |
| { |
| kPriorityLow = OT_MESSAGE_PRIORITY_LOW, ///< Low priority level. |
| kPriorityNormal = OT_MESSAGE_PRIORITY_NORMAL, ///< Normal priority level. |
| kPriorityHigh = OT_MESSAGE_PRIORITY_HIGH, ///< High priority level. |
| kPriorityNet = OT_MESSAGE_PRIORITY_HIGH + 1, ///< Network Control priority level. |
| }; |
| |
| static constexpr uint8_t kNumPriorities = 4; ///< Number of priority levels. |
| |
| /** |
| * Represents an IPv6 message origin. |
| */ |
| enum Origin : uint8_t |
| { |
| kOriginThreadNetif = OT_MESSAGE_ORIGIN_THREAD_NETIF, // Message from Thread Netif. |
| kOriginHostTrusted = OT_MESSAGE_ORIGIN_HOST_TRUSTED, // Message from a trusted source on host. |
| kOriginHostUntrusted = OT_MESSAGE_ORIGIN_HOST_UNTRUSTED, // Message from an untrusted source on host. |
| }; |
| |
| /** |
| * Represents settings used for creating a new message. |
| */ |
| class Settings : public otMessageSettings |
| { |
| public: |
| /** |
| * Initializes the `Settings` object. |
| * |
| * @param[in] aSecurityMode A link security mode. |
| * @param[in] aPriority A message priority. |
| */ |
| Settings(LinkSecurityMode aSecurityMode, Priority aPriority); |
| |
| /** |
| * Initializes the `Settings` with a given message priority and link security enabled. |
| * |
| * @param[in] aPriority A message priority. |
| */ |
| explicit Settings(Priority aPriority) |
| : Settings(kWithLinkSecurity, aPriority) |
| { |
| } |
| |
| /** |
| * Gets the message priority. |
| * |
| * @returns The message priority. |
| */ |
| Priority GetPriority(void) const { return static_cast<Priority>(mPriority); } |
| |
| /** |
| * Indicates whether the link security should be enabled. |
| * |
| * @returns TRUE if link security should be enabled, FALSE otherwise. |
| */ |
| bool IsLinkSecurityEnabled(void) const { return mLinkSecurityEnabled; } |
| |
| /** |
| * Converts a pointer to an `otMessageSettings` to a `Settings`. |
| * |
| * @param[in] aSettings A pointer to `otMessageSettings` to convert from. |
| * If it is `nullptr`, then the default settings `GetDefault()` will be used. |
| * |
| * @returns A reference to the converted `Settings` or the default if @p aSettings is `nullptr`. |
| */ |
| static const Settings &From(const otMessageSettings *aSettings); |
| |
| /** |
| * Returns the default settings with link security enabled and `kPriorityNormal` priority. |
| * |
| * @returns A reference to the default settings (link security enable and `kPriorityNormal` priority). |
| */ |
| static const Settings &GetDefault(void) { return static_cast<const Settings &>(kDefault); } |
| |
| private: |
| 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`. |
| * |
| * @returns A reference to the `Instance`. |
| */ |
| #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE |
| Instance &GetInstance(void) const { return *GetMetadata().mInstance; } |
| #else |
| Instance &GetInstance(void) const { return GetSingleInstance(); } |
| #endif |
| |
| /** |
| * Frees this message buffer. |
| */ |
| void Free(void); |
| |
| /** |
| * Returns a pointer to the next message. |
| * |
| * @returns A pointer to the next message in the list or `nullptr` if at the end of the list. |
| */ |
| Message *GetNext(void) const { return Next(); } |
| |
| /** |
| * Returns the number of bytes in the message. |
| * |
| * @returns The number of bytes in the message. |
| */ |
| uint16_t GetLength(void) const { return GetMetadata().mLength; } |
| |
| /** |
| * Sets the number of bytes in the message. |
| * |
| * @param[in] aLength Requested number of bytes in the message. |
| * |
| * @retval kErrorNone Successfully set the length of the message. |
| * @retval kErrorNoBufs Failed to grow the size of the message because insufficient buffers were available. |
| */ |
| Error SetLength(uint16_t aLength); |
| |
| /** |
| * Increases the message length by a given number of bytes. |
| * |
| * @param[in] aSize The number of bytes to increase the message length by. |
| * |
| * @retval kErrorNone Successfully increased the length of the message. |
| * @retval kErrorNoBufs Failed to allocate new buffers to grow the message. |
| */ |
| Error IncreaseLength(uint16_t aSize); |
| |
| /** |
| * Returns the number of buffers in the message. |
| */ |
| uint8_t GetBufferCount(void) const; |
| |
| /** |
| * Returns the byte offset within the message. |
| * |
| * @returns A byte offset within the message. |
| */ |
| uint16_t GetOffset(void) const { return GetMetadata().mOffset; } |
| |
| /** |
| * Moves the byte offset within the message. |
| * |
| * @param[in] aDelta The number of bytes to move the current offset, which may be positive or negative. |
| */ |
| void MoveOffset(int16_t aDelta); |
| |
| /** |
| * Sets the byte offset within the message. |
| * |
| * @param[in] aOffset The byte offset within the message. |
| */ |
| void SetOffset(uint16_t aOffset); |
| |
| /** |
| * Determines the length (number of bytes) in the message from the current message offset to the end of the message. |
| * |
| * @return Number of bytes in the message starting from the current message offset to the end of the message. |
| */ |
| uint16_t DetermineLengthAfterOffset(void) const; |
| |
| /** |
| * Returns the type of the message. |
| * |
| * @returns The type of the message. |
| */ |
| Type GetType(void) const { return static_cast<Type>(GetMetadata().mType); } |
| |
| /** |
| * Sets the message type. |
| * |
| * @param[in] aType The message type. |
| */ |
| void SetType(Type aType) { GetMetadata().mType = aType; } |
| |
| /** |
| * Returns the sub type of the message. |
| * |
| * @returns The sub type of the message. |
| */ |
| SubType GetSubType(void) const { return static_cast<SubType>(GetMetadata().mSubType); } |
| |
| /** |
| * Sets the message sub type. |
| * |
| * @param[in] aSubType The message sub type. |
| */ |
| void SetSubType(SubType aSubType) { GetMetadata().mSubType = aSubType; } |
| |
| /** |
| * Indicates whether or not the message is of MLE sub type. |
| * |
| * @retval TRUE The message is of MLE sub type. |
| * @retval FALSE The message is not of MLE sub type. |
| */ |
| bool IsSubTypeMle(void) const { return (GetSubType() == kSubTypeMle); } |
| |
| /** |
| * Indicates whether or not the message is a given MLE command. |
| * |
| * It checks `IsSubTypeMle()` and then if `GetMleCommand()` is the same as `aMleCommand`. |
| * |
| * @param[in] aMleCommand The MLE command type. |
| * |
| * @retval TRUE The message is an MLE command of @p aMleCommand type. |
| * @retval FALSE The message is not an MLE command of @p aMleCommand type. |
| */ |
| bool IsMleCommand(Mle::Command aMleCommand) const; |
| |
| /** |
| * Gets the MLE command type. |
| * |
| * Caller MUST ensure that message sub type is `kSubTypeMle` before calling this method. Otherwise the returned |
| * value is not meaningful. |
| * |
| * @returns The message's MLE command type. |
| */ |
| Mle::Command GetMleCommand(void) const { return static_cast<Mle::Command>(GetMetadata().mMleCommand); } |
| |
| /** |
| * Set the MLE command type of message. |
| * |
| * Caller should also set the sub type to `kSubTypeMle`. |
| * |
| * @param[in] aMleCommand The MLE command type. |
| */ |
| void SetMleCommand(Mle::Command aMleCommand) { GetMetadata().mMleCommand = aMleCommand; } |
| |
| /** |
| * Checks whether this multicast message may be looped back. |
| * |
| * @retval TRUE If message may be looped back. |
| * @retval FALSE If message must not be looped back. |
| */ |
| bool GetMulticastLoop(void) const { return GetMetadata().mMulticastLoop; } |
| |
| /** |
| * Sets whether multicast may be looped back. |
| * |
| * @param[in] aMulticastLoop Whether allow looping back multicast. |
| */ |
| void SetMulticastLoop(bool aMulticastLoop) { GetMetadata().mMulticastLoop = aMulticastLoop; } |
| |
| /** |
| * Returns the message priority level. |
| * |
| * @returns The priority level associated with this message. |
| */ |
| Priority GetPriority(void) const { return static_cast<Priority>(GetMetadata().mPriority); } |
| |
| /** |
| * Sets the messages priority. |
| * |
| * If the message is already enqueued in a priority queue, the priority cannot be changed and `kErrorInvalidState` |
| * is returned. |
| * |
| * @param[in] aPriority The message priority level. |
| * |
| * @retval kErrorNone Successfully set the priority for the message. |
| * @retval kErrorInvalidArgs Priority level is not invalid. |
| * @retval kErrorInvalidState Message is already queued in a priority queue. |
| */ |
| Error SetPriority(Priority aPriority); |
| |
| /** |
| * Convert a `Priority` to a string. |
| * |
| * @param[in] aPriority The priority level. |
| * |
| * @returns A string representation of @p aPriority. |
| */ |
| static const char *PriorityToString(Priority aPriority); |
| |
| /** |
| * Registers a callback to be notified of a message's transmission outcome. |
| * |
| * The registered `TxCallback` provides notification of the transmission status of the message from this device to |
| * an immediate neighbor (one hop). It doesn't indicate delivery to the final multi-hop destination. |
| * |
| * For unicast messages, `kErrorNone` callback error signifies successful delivery and MAC acknowledgment for all |
| * fragments of the message to an immediate neighbor, irrespective of whether direct or indirect TX is used. For |
| * multicast messages, `kErrorNone` indicates successful broadcast of all fragments. Note that no MAC-level ack |
| * is expected for broadcast frame transmissions. |
| * |
| * Only one callback can be registered per `Message`. Subsequent calls replace any existing callback. If the |
| * message is never actually sent, the callback will still be invoked when the message is freed, with `kErrorDrop` |
| * as the error. |
| * |
| * @param[in] aCallback The `TxCallback` function to register with the message. |
| * @param[in] aContext An arbitrary context that will be passed when @p aCallback is invoked. |
| */ |
| void RegisterTxCallback(TxCallback aCallback, void *aContext); |
| |
| /** |
| * Invokes the registered `TxCallback` on the `Message` with the given error status. |
| * |
| * The `TxCallback` is a one-time callback, meaning it's automatically cleared once it's invoked. |
| * |
| * @param[in] aError The error to report. |
| */ |
| void InvokeTxCallback(Error aError); |
| |
| /** |
| * Prepends bytes to the front of the message. |
| * |
| * On success, this method grows the message by @p aLength bytes. |
| * |
| * @param[in] aBuf A pointer to a data buffer (can be `nullptr` to grow message without writing bytes). |
| * @param[in] aLength The number of bytes to prepend. |
| * |
| * @retval kErrorNone Successfully prepended the bytes. |
| * @retval kErrorNoBufs Not enough reserved bytes in the message. |
| */ |
| Error PrependBytes(const void *aBuf, uint16_t aLength); |
| |
| /** |
| * Prepends an object to the front of the message. |
| * |
| * On success, this method grows the message by the size of the object. |
| * |
| * @tparam ObjectType The object type to prepend to the message. |
| * |
| * @param[in] aObject A reference to the object to prepend to the message. |
| * |
| * @retval kErrorNone Successfully prepended the object. |
| * @retval kErrorNoBufs Not enough reserved bytes in the message. |
| */ |
| template <typename ObjectType> Error Prepend(const ObjectType &aObject) |
| { |
| static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); |
| |
| return PrependBytes(&aObject, sizeof(ObjectType)); |
| } |
| |
| /** |
| * Removes header bytes from the message at start of message. |
| * |
| * The caller MUST ensure that message contains the bytes to be removed, i.e. `aOffset` is smaller than the message |
| * length. |
| * |
| * @param[in] aLength Number of header bytes to remove from start of `Message`. |
| */ |
| void RemoveHeader(uint16_t aLength); |
| |
| /** |
| * Removes header bytes from the message at a given offset. |
| * |
| * Shrinks the message. The existing header bytes before @p aOffset are copied forward and replace the |
| * removed bytes. |
| * |
| * The caller MUST ensure that message contains the bytes to be removed, i.e. `aOffset + aLength` is smaller than |
| * the message length. |
| * |
| * @param[in] aOffset The offset to start removing. |
| * @param[in] aLength Number of header bytes to remove. |
| */ |
| void RemoveHeader(uint16_t aOffset, uint16_t aLength); |
| |
| /** |
| * Grows the message to make space for new header bytes at a given offset. |
| * |
| * Grows the message header (similar to `PrependBytes()`). The existing header bytes from start to |
| * `aOffset + aLength` are then copied backward to make room for the new header bytes. Note that this method does |
| * not change the bytes from @p aOffset up @p aLength (the new inserted header range). Caller can write to this |
| * range to update the bytes after successful return from this method. |
| * |
| * @param[in] aOffset The offset at which to insert the header bytes |
| * @param[in] aLength Number of header bytes to insert. |
| * |
| * @retval kErrorNone Successfully grown the message and copied the existing header bytes. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| Error InsertHeader(uint16_t aOffset, uint16_t aLength); |
| |
| /** |
| * Removes footer bytes from the end of the message. |
| * |
| * The caller should ensure the message contains the bytes to be removed, otherwise as many bytes as available |
| * will be removed. |
| * |
| * @param[in] aLength Number of footer bytes to remove from end of the `Message`. |
| */ |
| void RemoveFooter(uint16_t aLength); |
| |
| /** |
| * Appends bytes to the end of the message. |
| * |
| * On success, this method grows the message by @p aLength bytes. |
| * |
| * @param[in] aBuf A pointer to a data buffer (MUST not be `nullptr`). |
| * @param[in] aLength The number of bytes to append. |
| * |
| * @retval kErrorNone Successfully appended the bytes. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| Error AppendBytes(const void *aBuf, uint16_t aLength); |
| |
| /** |
| * Appends bytes read from another or potentially the same message to the end of the current message. |
| * |
| * On success, this method grows the message by @p aLength bytes. |
| * |
| * @param[in] aMessage The message to read the bytes from (it can be the same as the current message). |
| * @param[in] aOffset The offset in @p aMessage to start reading the bytes from. |
| * @param[in] aLength The number of bytes to read from @p aMessage and append. |
| * |
| * @retval kErrorNone Successfully appended the bytes. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| * @retval kErrorParse Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset. |
| */ |
| Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength); |
| |
| /** |
| * Appends bytes read from another or potentially the same message to the end of the current message. |
| * |
| * @param[in] aMessage The message to read the bytes from (it can be the same as the current message). |
| * @param[in] aOffsetRange The offset range in @p aMessage to read bytes from. |
| * |
| * @retval kErrorNone Successfully appended the bytes. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| * @retval kErrorParse Not enough bytes in @p aMessage to read @p aOffsetRange. |
| */ |
| Error AppendBytesFromMessage(const Message &aMessage, const OffsetRange &aOffsetRange); |
| |
| /** |
| * Appends an object to the end of the message. |
| * |
| * On success, this method grows the message by the size of the appended object |
| * |
| * @tparam ObjectType The object type to append to the message. |
| * |
| * @param[in] aObject A reference to the object to append to the message. |
| * |
| * @retval kErrorNone Successfully appended the object. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| template <typename ObjectType> Error Append(const ObjectType &aObject) |
| { |
| static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); |
| |
| return AppendBytes(&aObject, sizeof(ObjectType)); |
| } |
| |
| /** |
| * Appends bytes from a given `Data` instance to the end of the message. |
| * |
| * On success, this method grows the message by the size of the appended data. |
| * |
| * @tparam kDataLengthType Determines the data length type (`uint8_t` or `uint16_t`). |
| * |
| * @param[in] aData A reference to `Data` to append to the message. |
| * |
| * @retval kErrorNone Successfully appended the bytes from @p aData. |
| * @retval kErrorNoBufs Insufficient available buffers to grow the message. |
| */ |
| template <DataLengthType kDataLengthType> Error AppendData(const Data<kDataLengthType> &aData) |
| { |
| return AppendBytes(aData.GetBytes(), aData.GetLength()); |
| } |
| |
| /** |
| * Reads bytes from the message. |
| * |
| * The provided buffer @p aBuf MUST contain at least @p aLength bytes. |
| * |
| * If there are fewer bytes available in the message than the requested @p aLength, the available bytes are read |
| * and copied into @p aBuf. This method returns the actual number of bytes successfully read from the message and |
| * written into @p aBuf. |
| * |
| * @param[in] aOffset Byte offset within the message to begin reading. |
| * @param[out] aBuf A pointer to a data buffer to copy the read bytes into. |
| * @param[in] aLength Number of bytes to read. |
| * |
| * @returns The number of bytes read. |
| */ |
| uint16_t ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) const; |
| |
| /** |
| * Reads bytes from the message. |
| * |
| * If there are fewer bytes available in the message than the provided length in @p aOffsetRange, the available |
| * bytes are read and copied into @p aBuf. This method returns the actual number of bytes successfully read from |
| * the message and written into @p aBuf. |
| * |
| * @param[in] aOffsetRange The offset range in the message to read bytes from. |
| * @param[out] aBuf A pointer to a data buffer to copy the read bytes into. |
| * |
| * @returns The number of bytes read. |
| */ |
| uint16_t ReadBytes(const OffsetRange &aOffsetRange, void *aBuf) const; |
| |
| /** |
| * Reads a given number of bytes from the message. |
| * |
| * @param[in] aOffset Byte offset within the message to begin reading. |
| * @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 @p aLength bytes were successfully read from message. |
| * @retval kErrorParse Not enough bytes remaining in message to read the entire object. |
| */ |
| Error Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const; |
| |
| /** |
| * Reads a given number of bytes from the message. |
| * |
| * @param[in] aOffsetRange The offset range in the message to read from. |
| * @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. |
| * @retval kErrorParse Not enough bytes remaining to read the requested @p aLength. |
| */ |
| Error Read(const OffsetRange &aOffsetRange, void *aBuf, uint16_t aLength) const; |
| |
| /** |
| * Reads an object from the message. |
| * |
| * @tparam ObjectType The object type to read from the message. |
| * |
| * @param[in] aOffset Byte offset within the message to begin reading. |
| * @param[out] aObject A reference to the object to read into. |
| * |
| * @retval kErrorNone Object @p aObject was successfully read from message. |
| * @retval kErrorParse Not enough bytes remaining in message to read the entire object. |
| */ |
| template <typename ObjectType> Error Read(uint16_t aOffset, ObjectType &aObject) const |
| { |
| static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); |
| |
| return Read(aOffset, &aObject, sizeof(ObjectType)); |
| } |
| |
| /** |
| * Reads an object from the message. |
| * |
| * @tparam ObjectType The object type to read from the message. |
| * |
| * @param[in] aOffsetRange The offset range in the message to read from. |
| * @param[out] aObject A reference to the object to read into. |
| * |
| * @retval kErrorNone Object @p aObject was successfully read from message. |
| * @retval kErrorParse Not enough bytes remaining in message to read the entire object. |
| */ |
| template <typename ObjectType> Error Read(const OffsetRange &aOffsetRange, ObjectType &aObject) const |
| { |
| static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); |
| |
| 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 <typename ObjectType> Error ReadAtAndAdvanceOffset(ObjectType &aObject) |
| { |
| static_assert(!TypeTraits::IsPointer<ObjectType>::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. |
| * |
| * If there are fewer bytes available in the message than the requested @p aLength, the comparison is treated as |
| * failure (returns FALSE). |
| * |
| * @param[in] aOffset Byte offset within the message to read from for the comparison. |
| * @param[in] aBuf A pointer to a data buffer to compare with the bytes from message. |
| * @param[in] aLength Number of bytes in @p aBuf. |
| * @param[in] aMatcher A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are directly |
| * compared. |
| * |
| * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf, |
| * FALSE otherwise. |
| */ |
| bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher = nullptr) const; |
| |
| /** |
| * Compares the bytes in the message from a given offset range with a given byte array. |
| * |
| * If there are fewer bytes available in the message than @p aOffsetRange, the comparison is treated as failure |
| * (returns FALSE). |
| * |
| * @param[in] aOffsetRange The offset range in the message to read from for the comparison. |
| * @param[in] aBuf A pointer to a data buffer to compare with the bytes from message. |
| * @param[in] aMatcher A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are directly |
| * compared. |
| * |
| * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf, |
| * FALSE otherwise. |
| */ |
| bool CompareBytes(const OffsetRange &aOffsetRange, const void *aBuf, ByteMatcher aMatcher = nullptr) const; |
| |
| /** |
| * Compares the bytes in the message at a given offset with bytes read from another message. |
| * |
| * If either message has fewer bytes available than the requested @p aLength, the comparison is treated as failure |
| * (returns FALSE). |
| * |
| * @param[in] aOffset Byte offset within the message to read from for the comparison. |
| * @param[in] aOtherMessage The other message to compare with. |
| * @param[in] aOtherOffset Byte offset within @p aOtherMessage to read from for the comparison. |
| * @param[in] aLength Number of bytes to compare. |
| * @param[in] aMatcher A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are |
| * directly compared. |
| * |
| * @returns TRUE if there are enough bytes available in both messages and they all match. FALSE otherwise. |
| */ |
| bool CompareBytes(uint16_t aOffset, |
| const Message &aOtherMessage, |
| uint16_t aOtherOffset, |
| uint16_t aLength, |
| ByteMatcher aMatcher = nullptr) const; |
| |
| /** |
| * Compares the bytes in the message at a given offset with an object. |
| * |
| * The bytes in the message are compared with the bytes in @p aObject. If there are fewer bytes available in the |
| * message than the requested object size, it is treated as failed comparison (returns FALSE). |
| * |
| * @tparam ObjectType The object type to compare with the bytes in message. |
| * |
| * @param[in] aOffset Byte offset within the message to read from for the comparison. |
| * @param[in] aObject A reference to the object to compare with the message bytes. |
| * |
| * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes in @p aObject, |
| * FALSE otherwise. |
| */ |
| template <typename ObjectType> bool Compare(uint16_t aOffset, const ObjectType &aObject) const |
| { |
| static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); |
| |
| return CompareBytes(aOffset, &aObject, sizeof(ObjectType)); |
| } |
| |
| /** |
| * Writes bytes to the message. |
| * |
| * Will not resize the message. The given data to write (with @p aLength bytes) MUST fit within the |
| * existing message buffer (from the given offset @p aOffset up to the message's length). |
| * |
| * @param[in] aOffset Byte offset within the message to begin writing. |
| * @param[in] aBuf A pointer to a data buffer. |
| * @param[in] aLength Number of bytes to write. |
| */ |
| void WriteBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength); |
| |
| /** |
| * Writes bytes read from another or potentially the same message to the message at a given offset. |
| * |
| * Will not resize the message. The bytes to write (with @p aLength) MUST fit within the existing |
| * message buffer (from the given @p aWriteOffset up to the message's length). |
| * |
| * Can be used to copy bytes within the same message in either direction, i.e., copy forward where |
| * `aWriteOffset > aReadOffset` or copy backward where `aWriteOffset < aReadOffset`. |
| * |
| * @param[in] aWriteOffset Byte offset within this message to begin writing. |
| * @param[in] aMessage The message to read the bytes from. |
| * @param[in] aReadOffset The offset in @p aMessage to start reading the bytes from. |
| * @param[in] aLength The number of bytes to read from @p aMessage and write. |
| */ |
| void WriteBytesFromMessage(uint16_t aWriteOffset, const Message &aMessage, uint16_t aReadOffset, uint16_t aLength); |
| |
| /** |
| * Writes an object to the message. |
| * |
| * Will not resize the message. The entire given object (all its bytes) MUST fit within the existing |
| * message buffer (from the given offset @p aOffset up to the message's length). |
| * |
| * @tparam ObjectType The object type to write to the message. |
| * |
| * @param[in] aOffset Byte offset within the message to begin writing. |
| * @param[in] aObject A reference to the object to write. |
| */ |
| template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject) |
| { |
| static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer"); |
| |
| WriteBytes(aOffset, &aObject, sizeof(ObjectType)); |
| } |
| |
| /** |
| * Writes bytes from a given `Data` instance to the message. |
| * |
| * Will not resize the message. The given data to write MUST fit within the existing message buffer |
| * (from the given offset @p aOffset up to the message's length). |
| * |
| * @tparam kDataLengthType Determines the data length type (`uint8_t` or `uint16_t`). |
| * |
| * @param[in] aOffset Byte offset within the message to begin writing. |
| * @param[in] aData The `Data` to write to the message. |
| */ |
| template <DataLengthType kDataLengthType> void WriteData(uint16_t aOffset, const Data<kDataLengthType> &aData) |
| { |
| WriteBytes(aOffset, aData.GetBytes(), aData.GetLength()); |
| } |
| |
| /** |
| * Creates a copy of the message using a given configuration. |
| * |
| * The `Type`, `SubType`, `LinkSecurity`, `Offset`, `Priority`, `LoopbackToHostAllowed`, `Origin`, `Timestamp`, |
| * `MeshDest`, `PanId`, `Channel`, `RssAverager`, `LqiAverager`, and `TimeSync` fields on the cloned message are |
| * also copied from the original one. |
| * |
| * @param[in] aLength Number of message bytes to copy. |
| * @param[in] aReserveHeader Number of header bytes to reserve in the new cloned message. |
| * |
| * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. |
| */ |
| Message *Clone(uint16_t aLength, uint16_t aReserveHeader) const; |
| |
| /** |
| * Creates a copy of the message. |
| * |
| * @tparam kMode Specifies the clone mode (whether to keep the same reserved header size or have none). |
| * |
| * See the non-templated `Clone()` method for details on which message fields are also copied. |
| * |
| * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. |
| */ |
| template <CloneMode kMode> Message *Clone(void) const; |
| |
| /** |
| * Creates a copy of the message. |
| * |
| * @tparam kMode Specifies the clone mode (whether to keep the same reserved header size or have none). |
| * |
| * See the non-templated `Clone()` method for details on which message fields are also copied. |
| * |
| * @param[in] aLength Number of message bytes to copy. |
| * |
| * @returns A pointer to the message or `nullptr` if insufficient message buffers are available. |
| */ |
| template <CloneMode kMode> Message *Clone(uint16_t aLength) const; |
| |
| /** |
| * Returns the datagram tag used for 6LoWPAN fragmentation or the identification used for IPv6 |
| * fragmentation. |
| * |
| * @returns The 6LoWPAN datagram tag or the IPv6 fragment identification. |
| */ |
| uint32_t GetDatagramTag(void) const { return GetMetadata().mDatagramTag; } |
| |
| /** |
| * Sets the datagram tag used for 6LoWPAN fragmentation. |
| * |
| * @param[in] aTag The 6LoWPAN datagram tag. |
| */ |
| void SetDatagramTag(uint32_t aTag) { GetMetadata().mDatagramTag = aTag; } |
| |
| #if OPENTHREAD_FTD |
| /** |
| * Gets the indirect transmission `ChildMask` associated with this `Message`. |
| * |
| * The `ChildMask` indicates the set of children for which this message is scheduled for indirect transmission. |
| * |
| * @returns A reference to the indirect transmission `ChildMask`. |
| */ |
| ChildMask &GetIndirectTxChildMask(void) { return GetMetadata().mChildMask; } |
| |
| /** |
| * Gets the indirect transmission `ChildMask` associated with this `Message`. |
| * |
| * The `ChildMask` indicates the set of children for which this message is scheduled for indirect transmission. |
| * |
| * @returns A reference to the indirect transmission `ChildMask`. |
| */ |
| const ChildMask &GetIndirectTxChildMask(void) const { return GetMetadata().mChildMask; } |
| #endif |
| |
| /** |
| * Returns the RLOC16 of the mesh destination. |
| * |
| * @note Only use this for non-link-local unicast messages. |
| * |
| * @returns The IEEE 802.15.4 Destination PAN ID. |
| */ |
| uint16_t GetMeshDest(void) const { return GetMetadata().mMeshDest; } |
| |
| /** |
| * Sets the RLOC16 of the mesh destination. |
| * |
| * @note Only use this when sending non-link-local unicast messages. |
| * |
| * @param[in] aMeshDest The IEEE 802.15.4 Destination PAN ID. |
| */ |
| void SetMeshDest(uint16_t aMeshDest) { GetMetadata().mMeshDest = aMeshDest; } |
| |
| /** |
| * Returns the IEEE 802.15.4 Source or Destination PAN ID. |
| * |
| * For a message received over the Thread radio, specifies the Source PAN ID when present in MAC header, otherwise |
| * specifies the Destination PAN ID. |
| * |
| * For a message to be sent over the Thread radio, this is set and used for MLE Discover Request or Response |
| * messages. |
| * |
| * @returns The IEEE 802.15.4 PAN ID. |
| */ |
| uint16_t GetPanId(void) const { return GetMetadata().mPanId; } |
| |
| /** |
| * Sets the IEEE 802.15.4 Destination PAN ID. |
| * |
| * @note Only use this when sending MLE Discover Request or Response messages. |
| * |
| * @param[in] aPanId The IEEE 802.15.4 Destination PAN ID. |
| */ |
| void SetPanId(uint16_t aPanId) { GetMetadata().mPanId = aPanId; } |
| |
| /** |
| * Indicates whether the Destination PAN ID is broadcast. |
| * |
| * This is applicable for messages received over Thread radio. |
| * |
| * @retval TRUE The Destination PAN ID is broadcast. |
| * @retval FALSE The Destination PAN ID is not broadcast. |
| */ |
| bool IsDstPanIdBroadcast(void) const { return GetMetadata().mIsDstPanIdBroadcast; } |
| |
| /** |
| * Returns the IEEE 802.15.4 Channel to use for transmission. |
| * |
| * @note Only use this when sending MLE Announce messages. |
| * |
| * @returns The IEEE 802.15.4 Channel to use for transmission. |
| */ |
| uint8_t GetChannel(void) const { return GetMetadata().mChannel; } |
| |
| /** |
| * Sets the IEEE 802.15.4 Channel to use for transmission. |
| * |
| * @note Only use this when sending MLE Announce messages. |
| * |
| * @param[in] aChannel The IEEE 802.15.4 Channel to use for transmission. |
| */ |
| void SetChannel(uint8_t aChannel) { GetMetadata().mChannel = aChannel; } |
| |
| /** |
| * Returns the message timestamp. |
| * |
| * @returns The message timestamp. |
| */ |
| TimeMilli GetTimestamp(void) const { return GetMetadata().mTimestamp; } |
| |
| /** |
| * Sets the message timestamp to a given time. |
| * |
| * @param[in] aTimestamp The timestamp value. |
| */ |
| void SetTimestamp(TimeMilli aTimestamp) { GetMetadata().mTimestamp = aTimestamp; } |
| |
| /** |
| * Sets the message timestamp to the current time. |
| */ |
| void SetTimestampToNow(void) { SetTimestamp(TimerMilli::GetNow()); } |
| |
| /** |
| * Returns whether or not message forwarding is scheduled for direct transmission. |
| * |
| * @retval TRUE If message forwarding is scheduled for direct transmission. |
| * @retval FALSE If message forwarding is not scheduled for direct transmission. |
| */ |
| bool IsDirectTransmission(void) const { return GetMetadata().mDirectTx; } |
| |
| /** |
| * Unschedules forwarding using direct transmission. |
| */ |
| void ClearDirectTransmission(void) { GetMetadata().mDirectTx = false; } |
| |
| /** |
| * Schedules forwarding using direct transmission. |
| */ |
| void SetDirectTransmission(void) { GetMetadata().mDirectTx = true; } |
| |
| /** |
| * Indicates whether the direct transmission of message was successful. |
| * |
| * @retval TRUE If direct transmission of message was successful (all fragments were delivered and acked). |
| * @retval FALSE If direct transmission of message failed (at least one fragment failed). |
| */ |
| bool GetTxSuccess(void) const { return GetMetadata().mTxSuccess; } |
| |
| /** |
| * Sets whether the direct transmission of message was successful. |
| * |
| * @param[in] aTxSuccess TRUE if the direct transmission is successful, FALSE otherwise (i.e., at least one |
| * fragment transmission failed). |
| */ |
| void SetTxSuccess(bool aTxSuccess) { GetMetadata().mTxSuccess = aTxSuccess; } |
| |
| /** |
| * Indicates whether the message may be evicted. |
| * |
| * @retval TRUE If the message must not be evicted. |
| * @retval FALSE If the message may be evicted. |
| */ |
| bool GetDoNotEvict(void) const { return GetMetadata().mDoNotEvict; } |
| |
| /** |
| * Sets whether the message may be evicted. |
| * |
| * @param[in] aDoNotEvict TRUE if the message may not be evicted, FALSE otherwise. |
| */ |
| void SetDoNotEvict(bool aDoNotEvict) { GetMetadata().mDoNotEvict = aDoNotEvict; } |
| |
| /** |
| * Indicates whether the message is waiting for an address query resolution. |
| * |
| * @retval TRUE If the message is waiting for address query resolution. |
| * @retval FALSE If the message is not waiting for address query resolution. |
| */ |
| bool IsResolvingAddress(void) const { return GetMetadata().mResolvingAddress; } |
| |
| /** |
| * Sets whether the message is waiting for an address query resolution. |
| * |
| * @param[in] aResolvingAddress TRUE if message is waiting for address resolution, FALSE otherwise. |
| */ |
| void SetResolvingAddress(bool aResolvingAddress) { GetMetadata().mResolvingAddress = aResolvingAddress; } |
| |
| /** |
| * Indicates whether the message is allowed to be looped back to host. |
| * |
| * @retval TRUE If the message is allowed to be looped back to host. |
| * @retval FALSE If the message is not allowed to be looped back to host. |
| */ |
| bool IsLoopbackToHostAllowed(void) const { return GetMetadata().mAllowLookbackToHost; } |
| |
| /** |
| * Sets whether or not allow the message to be looped back to host. |
| * |
| * @param[in] aAllowLoopbackToHost Whether or not allow the message to be looped back to host. |
| */ |
| void SetLoopbackToHostAllowed(bool aAllowLoopbackToHost) |
| { |
| GetMetadata().mAllowLookbackToHost = aAllowLoopbackToHost; |
| } |
| |
| /** |
| * Gets the message origin. |
| * |
| * @returns An enum representing the origin of the message. |
| */ |
| Origin GetOrigin(void) const { return static_cast<Origin>(GetMetadata().mOrigin); } |
| |
| /** |
| * Sets the message origin. |
| * |
| * @param[in] aOrigin An enum representing the origin of the message. |
| */ |
| void SetOrigin(Origin aOrigin) { GetMetadata().mOrigin = aOrigin; } |
| |
| /** |
| * Indicates whether or not the message origin is Thread Netif. |
| * |
| * @retval TRUE If the message origin is Thread Netif. |
| * @retval FALSE If the message origin is not Thread Netif. |
| */ |
| bool IsOriginThreadNetif(void) const { return GetOrigin() == kOriginThreadNetif; } |
| |
| /** |
| * Indicates whether or not the message origin is a trusted source on host. |
| * |
| * @retval TRUE If the message origin is a trusted source on host. |
| * @retval FALSE If the message origin is not a trusted source on host. |
| */ |
| bool IsOriginHostTrusted(void) const { return GetOrigin() == kOriginHostTrusted; } |
| |
| /** |
| * Indicates whether or not the message origin is an untrusted source on host. |
| * |
| * @retval TRUE If the message origin is an untrusted source on host. |
| * @retval FALSE If the message origin is not an untrusted source on host. |
| */ |
| bool IsOriginHostUntrusted(void) const { return GetOrigin() == kOriginHostUntrusted; } |
| |
| /** |
| * Indicates whether or not link security is enabled for the message. |
| * |
| * @retval TRUE If link security is enabled. |
| * @retval FALSE If link security is not enabled. |
| */ |
| bool IsLinkSecurityEnabled(void) const { return GetMetadata().mLinkSecurity; } |
| |
| /** |
| * Sets whether or not link security is enabled for the message. |
| * |
| * @param[in] aEnabled TRUE if link security is enabled, FALSE otherwise. |
| */ |
| void SetLinkSecurityEnabled(bool aEnabled) { GetMetadata().mLinkSecurity = aEnabled; } |
| |
| /** |
| * Updates the average RSS (Received Signal Strength) associated with the message by adding the given |
| * RSS value to the average. Note that a message can be composed of multiple 802.15.4 data frame fragments each |
| * received with a different signal strength. |
| * |
| * @param[in] aRss A new RSS value (in dBm) to be added to average. |
| */ |
| void AddRss(int8_t aRss) { IgnoreError(GetMetadata().mRssAverager.Add(aRss)); } |
| |
| /** |
| * Returns the average RSS (Received Signal Strength) associated with the message. |
| * |
| * @returns The current average RSS value (in dBm) or `Radio::kInvalidRssi` if no average is available. |
| */ |
| int8_t GetAverageRss(void) const { return GetMetadata().mRssAverager.GetAverage(); } |
| |
| /** |
| * Returns a const reference to RssAverager of the message. |
| * |
| * @returns A const reference to the RssAverager of the message. |
| */ |
| const RssAverager &GetRssAverager(void) const { return GetMetadata().mRssAverager; } |
| |
| /** |
| * Updates the average LQI (Link Quality Indicator) associated with the message. |
| * |
| * The given LQI value would be added to the average. Note that a message can be composed of multiple 802.15.4 |
| * frame fragments each received with a different signal strength. |
| * |
| * @param[in] aLqi A new LQI value (has no unit) to be added to average. |
| */ |
| void AddLqi(uint8_t aLqi) { GetMetadata().mLqiAverager.Add(aLqi); } |
| |
| /** |
| * Returns the average LQI (Link Quality Indicator) associated with the message. |
| * |
| * @returns The current average LQI value (in dBm) or OT_RADIO_LQI_NONE if no average is available. |
| */ |
| uint8_t GetAverageLqi(void) const { return GetMetadata().mLqiAverager.GetAverage(); } |
| |
| /** |
| * Returns the count of frames counted so far. |
| * |
| * @returns The count of frames that have been counted. |
| */ |
| uint8_t GetPsduCount(void) const { return GetMetadata().mLqiAverager.GetCount(); } |
| |
| /** |
| * Returns a const reference to LqiAverager of the message. |
| * |
| * @returns A const reference to the LqiAverager of the message. |
| */ |
| const LqiAverager &GetLqiAverager(void) const { return GetMetadata().mLqiAverager; } |
| |
| /** |
| * Retrieves `ThreadLinkInfo` from the message if received over Thread radio with origin `kOriginThreadNetif`. |
| * |
| * @pram[out] aLinkInfo A reference to a `ThreadLinkInfo` to populate. |
| * |
| * @retval kErrorNone Successfully retrieved the link info, @p `aLinkInfo` is updated. |
| * @retval kErrorNotFound Message origin is not `kOriginThreadNetif`. |
| */ |
| Error GetLinkInfo(ThreadLinkInfo &aLinkInfo) const; |
| |
| /** |
| * Sets the message's link info properties (PAN ID, link security, RSS) from a given `ThreadLinkInfo`. |
| * |
| * @param[in] aLinkInfo The `ThreadLinkInfo` instance from which to set message's related properties. |
| */ |
| void UpdateLinkInfoFrom(const ThreadLinkInfo &aLinkInfo); |
| |
| /** |
| * Indicates whether or not the message is also used for time sync purpose. |
| * |
| * When OPENTHREAD_CONFIG_TIME_SYNC_ENABLE is 0, this method always return false. |
| * |
| * @retval TRUE If the message is also used for time sync purpose. |
| * @retval FALSE If the message is not used for time sync purpose. |
| */ |
| bool IsTimeSync(void) const; |
| |
| #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE |
| /** |
| * Sets whether or not the message is also used for time sync purpose. |
| * |
| * @param[in] aEnabled TRUE if the message is also used for time sync purpose, FALSE otherwise. |
| */ |
| void SetTimeSync(bool aEnabled) { GetMetadata().mTimeSync = aEnabled; } |
| |
| /** |
| * Sets the offset to network time. |
| * |
| * @param[in] aNetworkTimeOffset The offset to network time. |
| */ |
| void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) { GetMetadata().mNetworkTimeOffset = aNetworkTimeOffset; } |
| |
| /** |
| * Gets the offset to network time. |
| * |
| * @returns The offset to network time. |
| */ |
| int64_t GetNetworkTimeOffset(void) const { return GetMetadata().mNetworkTimeOffset; } |
| |
| /** |
| * Sets the time sync sequence. |
| * |
| * @param[in] aTimeSyncSeq The time sync sequence. |
| */ |
| void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { GetMetadata().mTimeSyncSeq = aTimeSyncSeq; } |
| |
| /** |
| * Gets the time sync sequence. |
| * |
| * @returns The time sync sequence. |
| */ |
| uint8_t GetTimeSyncSeq(void) const { return GetMetadata().mTimeSyncSeq; } |
| #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE |
| |
| #if OPENTHREAD_CONFIG_MULTI_RADIO |
| /** |
| * Indicates whether the radio type is set. |
| * |
| * @retval TRUE If the radio type is set. |
| * @retval FALSE If the radio type is not set. |
| */ |
| bool IsRadioTypeSet(void) const { return GetMetadata().mIsRadioTypeSet; } |
| |
| /** |
| * Gets the radio link type the message was received on, or should be sent on. |
| * |
| * Should be used only when `IsRadioTypeSet()` returns `true`. |
| * |
| * @returns The radio link type of the message. |
| */ |
| Mac::RadioType GetRadioType(void) const { return static_cast<Mac::RadioType>(GetMetadata().mRadioType); } |
| |
| /** |
| * Sets the radio link type the message was received on, or should be sent on. |
| * |
| * @param[in] aRadioType A radio link type of the message. |
| */ |
| void SetRadioType(Mac::RadioType aRadioType) |
| { |
| GetMetadata().mIsRadioTypeSet = true; |
| GetMetadata().mRadioType = aRadioType; |
| } |
| |
| /** |
| * Clears any previously set radio type on the message. |
| * |
| * After calling this method, `IsRadioTypeSet()` returns false until radio type is set (`SetRadioType()`). |
| */ |
| void ClearRadioType(void) { GetMetadata().mIsRadioTypeSet = false; } |
| |
| #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO |
| |
| protected: |
| class ConstIterator : public ItemPtrIterator<const Message, ConstIterator> |
| { |
| friend class ItemPtrIterator<const Message, ConstIterator>; |
| |
| public: |
| ConstIterator(void) = default; |
| |
| explicit ConstIterator(const Message *aMessage) |
| : ItemPtrIterator(aMessage) |
| { |
| } |
| |
| private: |
| void Advance(void) { mItem = mItem->GetNext(); } |
| }; |
| |
| class Iterator : public ItemPtrIterator<Message, Iterator> |
| { |
| friend class ItemPtrIterator<Message, Iterator>; |
| |
| public: |
| Iterator(void) |
| : mNext(nullptr) |
| { |
| } |
| |
| explicit Iterator(Message *aMessage) |
| : ItemPtrIterator(aMessage) |
| , mNext(NextMessage(aMessage)) |
| { |
| } |
| |
| private: |
| void Advance(void); |
| static Message *NextMessage(Message *aMessage) { return (aMessage != nullptr) ? aMessage->GetNext() : nullptr; } |
| |
| Message *mNext; |
| }; |
| |
| uint16_t GetReserved(void) const { return GetMetadata().mReserved; } |
| void SetReserved(uint16_t aReservedHeader) { GetMetadata().mReserved = aReservedHeader; } |
| |
| private: |
| class Chunk : public Data<kWithUint16Length> |
| { |
| public: |
| const Buffer *GetBuffer(void) const { return mBuffer; } |
| void SetBuffer(const Buffer *aBuffer) { mBuffer = aBuffer; } |
| |
| private: |
| const Buffer *mBuffer; // Buffer containing the chunk |
| }; |
| |
| class MutableChunk : public Chunk |
| { |
| public: |
| uint8_t *GetBytes(void) { return AsNonConst(Chunk::GetBytes()); } |
| }; |
| |
| void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, Chunk &aChunk) const; |
| void GetNextChunk(uint16_t &aLength, Chunk &aChunk) const; |
| |
| void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, MutableChunk &aChunk) |
| { |
| AsConst(this)->GetFirstChunk(aOffset, aLength, static_cast<Chunk &>(aChunk)); |
| } |
| |
| void GetNextChunk(uint16_t &aLength, MutableChunk &aChunk) |
| { |
| AsConst(this)->GetNextChunk(aLength, static_cast<Chunk &>(aChunk)); |
| } |
| |
| void MarkAsNotInAQueue(void); |
| bool IsInAQueue(void) const { return (Prev() != this); } |
| bool IsInAPriorityQueue(void) const { return GetMetadata().mInPriorityQ; } |
| |
| void SetRssAverager(const RssAverager &aRssAverager) { GetMetadata().mRssAverager = aRssAverager; } |
| void SetLqiAverager(const LqiAverager &aLqiAverager) { GetMetadata().mLqiAverager = aLqiAverager; } |
| |
| Message *&Next(void) { return GetMetadata().mNext; } |
| Message *const &Next(void) const { return GetMetadata().mNext; } |
| Message *&Prev(void) { return GetMetadata().mPrev; } |
| Message *const &Prev(void) const { return GetMetadata().mPrev; } |
| |
| static Message *NextOf(Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; } |
| static const Message *NextOf(const Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; } |
| |
| Error ResizeMessage(uint16_t aLength); |
| }; |
| |
| /** |
| * Implements a message queue. |
| */ |
| class MessageQueue : public otMessageQueue, public Clearable<MessageQueue>, private NonCopyable |
| { |
| friend class Message; |
| friend class PriorityQueue; |
| |
| public: |
| typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue. |
| |
| /** |
| * Represents a position (head or tail) in the queue. This is used to specify where a new message |
| * should be added in the queue. |
| */ |
| enum QueuePosition : uint8_t |
| { |
| kQueuePositionHead, ///< Indicates the head (front) of the list. |
| kQueuePositionTail, ///< Indicates the tail (end) of the list. |
| }; |
| |
| /** |
| * Initializes the message queue. |
| */ |
| MessageQueue(void) { Clear(); } |
| |
| #if OPENTHREAD_PLATFORM_NEXUS |
| /** |
| * Destructor of `MessageQueue`. |
| */ |
| ~MessageQueue(void) { DequeueAndFreeAll(); } |
| #endif |
| |
| /** |
| * Returns a pointer to the first message. |
| * |
| * @returns A pointer to the first message. |
| */ |
| Message *GetHead(void) { return static_cast<Message *>(mData); } |
| |
| /** |
| * Returns a pointer to the first message. |
| * |
| * @returns A pointer to the first message. |
| */ |
| const Message *GetHead(void) const { return static_cast<const Message *>(mData); } |
| |
| /** |
| * Adds a message to the end of the list. |
| * |
| * @param[in] aMessage The message to add. |
| */ |
| void Enqueue(Message &aMessage) { Enqueue(aMessage, kQueuePositionTail); } |
| |
| /** |
| * Adds a message at a given position (head/tail) of the list. |
| * |
| * @param[in] aMessage The message to add. |
| * @param[in] aPosition The position (head or tail) where to add the message. |
| */ |
| void Enqueue(Message &aMessage, QueuePosition aPosition); |
| |
| /** |
| * Removes a message from the list. |
| * |
| * @param[in] aMessage The message to remove. |
| */ |
| void Dequeue(Message &aMessage); |
| |
| /** |
| * Removes a message from the queue and frees it. |
| * |
| * @param[in] aMessage The message to remove and free. |
| */ |
| void DequeueAndFree(Message &aMessage); |
| |
| /** |
| * Removes and frees all messages from the queue. |
| */ |
| void DequeueAndFreeAll(void); |
| |
| /** |
| * Gets the information about number of messages and buffers in the queue. |
| * |
| * @param[out] aInfo A reference to `Info` structure to update. |
| */ |
| void GetInfo(Info &aInfo) const; |
| |
| /** |
| * Adds the queue statistics from one queue `Info` to another. |
| * |
| * Aggregates queue information by adding the counts (e.g., number of messages, buffers, total bytes) from |
| * @p aOther to the corresponding counts in @p aInfo. |
| * |
| * @param[in,out] aInfo A queue `Info` to update. |
| * @param[in] aOther A queue `Info` to add to @p aInfo. |
| */ |
| static void AddQueueInfos(Info &aInfo, const Info &aOther); |
| |
| // The following methods are intended to support range-based `for` |
| // loop iteration over the queue entries and should not be used |
| // directly. The range-based `for` works correctly even if the |
| // current entry is removed from the queue during iteration. |
| |
| Message::Iterator begin(void); |
| Message::Iterator end(void) { return Message::Iterator(); } |
| |
| Message::ConstIterator begin(void) const; |
| Message::ConstIterator end(void) const { return Message::ConstIterator(); } |
| |
| private: |
| void SetHead(Message *aMessage) { mData = aMessage; } |
| Message *GetTail(void) { return static_cast<Message *>(mData2); } |
| const Message *GetTail(void) const { return static_cast<const Message *>(mData2); } |
| void SetTail(Message *aMessage) { mData2 = aMessage; } |
| }; |
| |
| /** |
| * Implements a priority queue. |
| */ |
| class PriorityQueue : private Clearable<PriorityQueue>, private NonCopyable |
| { |
| friend class Message; |
| friend class MessageQueue; |
| friend class MessagePool; |
| friend class Clearable<PriorityQueue>; |
| |
| public: |
| typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue. |
| |
| /** |
| * Initializes the priority queue. |
| */ |
| PriorityQueue(void) { Clear(); } |
| |
| #if OPENTHREAD_PLATFORM_NEXUS |
| /** |
| * Destructor of `PriorityQueue`. |
| */ |
| ~PriorityQueue(void) { DequeueAndFreeAll(); } |
| #endif |
| |
| /** |
| * Returns a pointer to the first message. |
| * |
| * @returns A pointer to the first message. |
| */ |
| Message *GetHead(void) { return mHead; } |
| |
| /** |
| * Returns a pointer to the first message. |
| * |
| * @returns A pointer to the first message. |
| */ |
| const Message *GetHead(void) const { return mHead; } |
| |
| /** |
| * Returns a pointer to the first message for a given priority level. |
| * |
| * @param[in] aPriority Priority level. |
| * |
| * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with |
| * this priority level. |
| */ |
| Message *GetHeadForPriority(Message::Priority aPriority) |
| { |
| return AsNonConst(AsConst(this)->GetHeadForPriority(aPriority)); |
| } |
| |
| /** |
| * Returns a pointer to the first message for a given priority level. |
| * |
| * @param[in] aPriority Priority level. |
| * |
| * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with |
| * this priority level. |
| */ |
| const Message *GetHeadForPriority(Message::Priority aPriority) const; |
| |
| /** |
| * Adds a message to the queue. |
| * |
| * @param[in] aMessage The message to add. |
| */ |
| void Enqueue(Message &aMessage); |
| |
| /** |
| * Removes a message from the list. |
| * |
| * @param[in] aMessage The message to remove. |
| */ |
| void Dequeue(Message &aMessage); |
| |
| /** |
| * Removes a message from the queue and frees it. |
| * |
| * @param[in] aMessage The message to remove and free. |
| */ |
| void DequeueAndFree(Message &aMessage); |
| |
| /** |
| * Removes and frees all messages from the queue. |
| */ |
| void DequeueAndFreeAll(void); |
| |
| /** |
| * Returns the tail of the list (last message in the list). |
| * |
| * @returns A pointer to the tail of the list. |
| */ |
| Message *GetTail(void) { return AsNonConst(AsConst(this)->GetTail()); } |
| |
| /** |
| * Returns the tail of the list (last message in the list). |
| * |
| * @returns A pointer to the tail of the list. |
| */ |
| const Message *GetTail(void) const; |
| |
| /** |
| * Gets the information about number of messages and buffers in the priority queue. |
| * |
| * Updates `aInfo` array and adds number of message/buffers in the message queue to the corresponding |
| * member variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method |
| * (e.g., clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues |
| * to add up the number of messages/buffers on different queues. |
| * |
| * @param[out] aInfo A reference to an `Info` structure to update. |
| */ |
| void GetInfo(Info &aInfo) const; |
| |
| // The following methods are intended to support range-based `for` |
| // loop iteration over the queue entries and should not be used |
| // directly. The range-based `for` works correctly even if the |
| // current entry is removed from the queue during iteration. |
| |
| Message::Iterator begin(void); |
| Message::Iterator end(void) { return Message::Iterator(); } |
| |
| Message::ConstIterator begin(void) const; |
| Message::ConstIterator end(void) const { return Message::ConstIterator(); } |
| |
| private: |
| const Message *FindTailForPriorityOrHigher(uint8_t aPriority) const; |
| |
| Message *FindTailForPriorityOrHigher(uint8_t aPriority) |
| { |
| return AsNonConst(AsConst(this)->FindTailForPriorityOrHigher(aPriority)); |
| } |
| |
| Message *mHead; |
| Message *mTails[Message::kNumPriorities]; // Tail pointers associated with different priority levels. |
| }; |
| |
| /** |
| * Represents a message pool |
| */ |
| class MessagePool : public InstanceLocator, private NonCopyable |
| { |
| friend class Message; |
| friend class MessageQueue; |
| friend class PriorityQueue; |
| |
| public: |
| /** |
| * Initializes the object. |
| */ |
| explicit MessagePool(Instance &aInstance); |
| |
| #if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT |
| /** |
| * Tears down the object and releases platform managed resources. |
| */ |
| ~MessagePool(void); |
| #endif |
| |
| /** |
| * Allocates a new message with specified settings. |
| * |
| * @param[in] aType The message type. |
| * @param[in] aReserveHeader The number of header bytes to reserve. |
| * @param[in] aSettings The message settings. |
| * |
| * @returns A pointer to the message or `nullptr` if no message buffers are available. |
| */ |
| Message *Allocate(Message::Type aType, uint16_t aReserveHeader, const Message::Settings &aSettings); |
| |
| /** |
| * Allocates a new message of a given type using default settings. |
| * |
| * @param[in] aType The message type. |
| * |
| * @returns A pointer to the message or `nullptr` if no message buffers are available. |
| */ |
| Message *Allocate(Message::Type aType); |
| |
| /** |
| * Allocates a new message with a given type and reserved length using default settings. |
| * |
| * @param[in] aType The message type. |
| * @param[in] aReserveHeader The number of header bytes to reserve. |
| * |
| * @returns A pointer to the message or `nullptr` if no message buffers are available. |
| */ |
| Message *Allocate(Message::Type aType, uint16_t aReserveHeader); |
| |
| /** |
| * Is used to free a message and return all message buffers to the buffer pool. |
| * |
| * @param[in] aMessage The message to free. |
| */ |
| void Free(Message *aMessage); |
| |
| /** |
| * Returns the number of free buffers. |
| * |
| * @returns The number of free buffers, or 0xffff (UINT16_MAX) if number is unknown. |
| */ |
| uint16_t GetFreeBufferCount(void) const; |
| |
| /** |
| * Returns the total number of buffers. |
| * |
| * @returns The total number of buffers, or 0xffff (UINT16_MAX) if number is unknown. |
| */ |
| uint16_t GetTotalBufferCount(void) const; |
| |
| /** |
| * Returns the maximum number of buffers in use at the same time since OT stack initialization or |
| * since last call to `ResetMaxUsedBufferCount()`. |
| * |
| * @returns The maximum number of buffers in use at the same time so far (buffer allocation watermark). |
| */ |
| uint16_t GetMaxUsedBufferCount(void) const { return mMaxAllocated; } |
| |
| /** |
| * Resets the tracked maximum number of buffers in use. |
| * |
| * @sa GetMaxUsedBufferCount |
| */ |
| void ResetMaxUsedBufferCount(void) { mMaxAllocated = mNumAllocated; } |
| |
| private: |
| static constexpr uint16_t kNumBuffers = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS; |
| |
| Buffer *NewBuffer(Message::Priority aPriority); |
| void FreeBuffers(Buffer *aBuffer); |
| Error ReclaimBuffers(Message::Priority aPriority); |
| |
| #if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE |
| Pool<Buffer, kNumBuffers> mBufferPool; |
| #endif |
| uint16_t mNumAllocated; |
| uint16_t mMaxAllocated; |
| }; |
| |
| // Declare specializations of `Message::Clone<CloneMode>()` (implemented in `message.cpp`). |
| template <> Message *Message::Clone<kNoReservedHeader>(void) const; |
| template <> Message *Message::Clone<kSameReservedHeader>(void) const; |
| template <> Message *Message::Clone<kNoReservedHeader>(uint16_t aLength) const; |
| template <> Message *Message::Clone<kSameReservedHeader>(uint16_t aLength) const; |
| |
| /** |
| * @} |
| */ |
| |
| DefineCoreType(otMessageBuffer, Buffer); |
| DefineCoreType(otMessageSettings, Message::Settings); |
| DefineCoreType(otMessage, Message); |
| DefineCoreType(otMessageQueue, MessageQueue); |
| |
| DefineMapEnum(otMessageOrigin, Message::Origin); |
| |
| } // namespace ot |
| |
| #endif // OT_CORE_COMMON_MESSAGE_HPP_ |