blob: 1d15ec80fee73282f4e776e25afcb381879bddca [file] [log] [blame]
/*
* 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 MESSAGE_HPP_
#define MESSAGE_HPP_
#include "openthread-core-config.h"
#include <stdint.h>
#include <openthread/message.h>
#include <openthread/platform/messagepool.h>
#include "common/code_utils.hpp"
#include "common/encoding.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/pool.hpp"
#include "mac/mac_types.hpp"
#include "thread/child_mask.hpp"
#include "thread/link_quality.hpp"
namespace ot {
/**
* @addtogroup core-message
*
* @brief
* This module includes definitions for the message buffer pool and message buffers.
*
* @{
*
*/
enum
{
kNumBuffers = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS,
kBufferSize = OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE,
};
class Message;
class MessagePool;
class MessageQueue;
class PriorityQueue;
/**
* This structure contains metadata about a Message.
*
*/
struct MessageMetadata
{
Message * mNext; ///< A pointer to the next Message in a doubly linked list.
Message * mPrev; ///< A pointer to the previous Message in a doubly linked list.
MessagePool *mMessagePool; ///< Identifies the message pool for this message.
union
{
MessageQueue * mMessage; ///< Identifies the message queue (if any) where this message is queued.
PriorityQueue *mPriority; ///< Identifies the priority queue (if any) where this message is queued.
} mQueue; ///< Identifies the queue (if any) where this message is queued.
uint32_t mDatagramTag; ///< The datagram tag used for 6LoWPAN fragmentation or identification used for IPv6
///< fragmentation.
uint16_t mReserved; ///< Number of header bytes reserved for the message.
uint16_t mLength; ///< Number of bytes within the message.
uint16_t mOffset; ///< A byte offset within the message.
RssAverager mRssAverager; ///< The averager maintaining the received signal strength (RSS) average.
ChildMask mChildMask; ///< A ChildMask to indicate which sleepy children need to receive this.
uint16_t mMeshDest; ///< Used for unicast non-link-local messages.
uint8_t mTimeout; ///< Seconds remaining before dropping the message.
union
{
uint16_t mPanId; ///< Used for MLE Discover Request and Response messages.
uint8_t mChannel; ///< Used for MLE Announce.
} mPanIdChannel; ///< Used for MLE Discover Request, Response, and Announce messages.
uint8_t mType : 2; ///< Identifies the type of message.
uint8_t mSubType : 4; ///< Identifies the message sub type.
bool mDirectTx : 1; ///< Used to indicate whether a direct transmission is required.
bool mLinkSecurity : 1; ///< Indicates whether or not link security is enabled.
uint8_t mPriority : 2; ///< Identifies the message priority level (higher value is higher priority).
bool mInPriorityQ : 1; ///< Indicates whether the message is queued in normal or priority queue.
bool mTxSuccess : 1; ///< Indicates whether the direct tx of the message was successful.
bool mDoNotEvict : 1; ///< Indicates whether or not this message may be evicted.
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
bool mTimeSync : 1; ///< Indicates whether the message is also used for time sync purpose.
uint8_t mTimeSyncSeq; ///< The time sync sequence.
int64_t mNetworkTimeOffset; ///< The time offset to the Thread network time, in microseconds.
#endif
};
/**
* This class represents a Message buffer.
*
*/
class Buffer : public otMessage, public LinkedListEntry<Buffer>
{
friend class Message;
public:
/**
* This method returns a pointer to the next message buffer.
*
* @returns A pointer to the next message buffer.
*
*/
Buffer *GetNextBuffer(void) { return GetNext(); }
/**
* This method returns a pointer to the next message buffer.
*
* @returns A pointer to the next message buffer.
*
*/
const Buffer *GetNextBuffer(void) const { return GetNext(); }
/**
* This method sets the pointer to the next message buffer.
*
* @param[in] aNext A pointer to the next buffer.
*
*/
void SetNextBuffer(Buffer *aNext) { SetNext(aNext); }
private:
/**
* This method returns the message metadata in the first message buffer.
*
* @returns The message metadata structure.
*
*/
MessageMetadata &GetMetadata(void) { return mBuffer.mHead.mMetadata; }
/**
* This method returns the message metadata in the first message buffer.
*
* @returns The message metadata structure.
*
*/
const MessageMetadata &GetMetadata(void) const { return mBuffer.mHead.mMetadata; }
/**
* This method returns a pointer to the first byte of data in the first message buffer.
*
* @returns A pointer to the first data byte.
*
*/
uint8_t *GetFirstData(void) { return mBuffer.mHead.mData; }
/**
* This method returns a pointer to the first byte of data in the first message buffer.
*
* @returns A pointer to the first data byte.
*
*/
const uint8_t *GetFirstData(void) const { return mBuffer.mHead.mData; }
/**
* This method returns a pointer to the first data byte of a subsequent message buffer.
*
* @returns A pointer to the first data byte.
*
*/
uint8_t *GetData(void) { return mBuffer.mData; }
/**
* This method returns a pointer to the first data byte of a subsequent message buffer.
*
* @returns A pointer to the first data byte.
*
*/
const uint8_t *GetData(void) const { return mBuffer.mData; }
enum
{
kBufferDataSize = kBufferSize - sizeof(otMessage),
kHeadBufferDataSize = kBufferDataSize - sizeof(MessageMetadata),
};
protected:
union
{
struct
{
MessageMetadata mMetadata;
uint8_t mData[kHeadBufferDataSize];
} mHead;
uint8_t mData[kBufferDataSize];
} mBuffer;
};
/**
* This class represents a message.
*
*/
class Message : public Buffer
{
friend class MessagePool;
friend class MessageQueue;
friend class PriorityQueue;
public:
/**
* This enumeration represents the message type.
*
*/
enum Type
{
kTypeIp6 = 0, ///< A full uncompressed IPv6 packet
kType6lowpan = 1, ///< A 6lowpan frame
kTypeSupervision = 2, ///< A child supervision frame.
kTypeOther = 3, ///< Other (data) message.
};
/**
* This enumeration represents the message sub-type.
*
*/
enum SubType
{
kSubTypeNone = 0, ///< None
kSubTypeMleAnnounce = 1, ///< MLE Announce
kSubTypeMleDiscoverRequest = 2, ///< MLE Discover Request
kSubTypeMleDiscoverResponse = 3, ///< MLE Discover Response
kSubTypeJoinerEntrust = 4, ///< Joiner Entrust
kSubTypeMplRetransmission = 5, ///< MPL next retransmission message
kSubTypeMleGeneral = 6, ///< General MLE
kSubTypeJoinerFinalizeResponse = 7, ///< Joiner Finalize Response
kSubTypeMleChildUpdateRequest = 8, ///< MLE Child Update Request
kSubTypeMleDataResponse = 9, ///< MLE Data Response
kSubTypeMleChildIdRequest = 10, ///< MLE Child ID Request
};
enum Priority
{
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.
};
enum
{
kNumPriorities = 4, ///< Number of priority levels.
};
/**
* This enumeration represents the link security mode (used by `Settings` constructor).
*
*/
enum LinkSecurityMode
{
kNoLinkSecurity, ///< Link security disabled (no link security).
kWithLinkSecurity, ///< Link security enabled.
};
/**
* This class represents settings used for creating a new message.
*
*/
class Settings
{
public:
/**
* This constructor initializes the Settings object.
*
* @param[in] aSecurityMode A link security mode.
* @param[in] aPriority A message priority.
*
*/
Settings(LinkSecurityMode aSecurityMode, Priority aPriority);
/**
* This constructor initializes the `Settings` object from a given `otMessageSettings`.
*
* @param[in] aSettings A pointer to `otMessageSettings` to covert from. If nullptr default settings (link
* security enabled with `kPriorityNormal` priority) would be used.
*
*/
Settings(const otMessageSettings *aSettings);
/**
* This method gets the message priority.
*
* @returns The message priority.
*
*/
Priority GetPriority(void) const { return mPriority; }
/**
* This method indicates whether the link security should be enabled.
*
* @returns TRUE if link security should be enabled, FALSE otherwise.
*
*/
bool IsLinkSecurityEnabled(void) const { return mLinkSecurityEnabled; }
/**
* This static method 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 kDefault; }
private:
static const Settings kDefault;
bool mLinkSecurityEnabled;
Priority mPriority;
};
/**
* This method frees this message buffer.
*
*/
void Free(void);
/**
* This method 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;
/**
* This method returns the number of bytes in the message.
*
* @returns The number of bytes in the message.
*/
uint16_t GetLength(void) const { return GetMetadata().mLength; }
/**
* This method sets the number of bytes in the message.
*
* @param[in] aLength Requested number of bytes in the message.
*
* @retval OT_ERROR_NONE Successfully set the length of the message.
* @retval OT_ERROR_NO_BUFS Failed to grow the size of the message because insufficient buffers were available.
*
*/
otError SetLength(uint16_t aLength);
/**
* This method returns the number of buffers in the message.
*
*/
uint8_t GetBufferCount(void) const;
/**
* This method returns the byte offset within the message.
*
* @returns A byte offset within the message.
*
*/
uint16_t GetOffset(void) const { return GetMetadata().mOffset; }
/**
* This method 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(int aDelta);
/**
* This method sets the byte offset within the message.
*
* @param[in] aOffset The byte offset within the message.
*
*/
void SetOffset(uint16_t aOffset);
/**
* This method returns the type of the message.
*
* @returns The type of the message.
*
*/
Type GetType(void) const { return static_cast<Type>(GetMetadata().mType); }
/**
* This method sets the message type.
*
* @param[in] aType The message type.
*
*/
void SetType(Type aType) { GetMetadata().mType = aType; }
/**
* This method returns the sub type of the message.
*
* @returns The sub type of the message.
*
*/
SubType GetSubType(void) const { return static_cast<SubType>(GetMetadata().mSubType); }
/**
* This method sets the message sub type.
*
* @param[in] aSubType The message sub type.
*
*/
void SetSubType(SubType aSubType) { GetMetadata().mSubType = aSubType; }
/**
* This method returns whether or not the message is of MLE subtype.
*
* @retval TRUE If message is of MLE subtype.
* @retval FALSE If message is not of MLE subtype.
*
*/
bool IsSubTypeMle(void) const;
/**
* This method returns the message priority level.
*
* @returns The priority level associated with this message.
*
*/
Priority GetPriority(void) const { return static_cast<Priority>(GetMetadata().mPriority); }
/**
* This method sets the messages priority.
* If the message is already queued in a priority queue, changing the priority ensures to
* update the message in the associated queue.
*
* @param[in] aPriority The message priority level.
*
* @retval OT_ERROR_NONE Successfully set the priority for the message.
* @retval OT_ERROR_INVALID_ARGS Priority level is not invalid.
*
*/
otError SetPriority(Priority aPriority);
/**
* This method 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.
* @param[in] aLength The number of bytes to prepend.
*
* @retval OT_ERROR_NONE Successfully prepended the bytes.
* @retval OT_ERROR_NO_BUFS Not enough reserved bytes in the message.
*
*/
otError Prepend(const void *aBuf, uint16_t aLength);
/**
* This method removes header bytes from the message.
*
* @param[in] aLength Number of header bytes to remove.
*
*/
void RemoveHeader(uint16_t aLength);
/**
* This method 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.
* @param[in] aLength The number of bytes to append.
*
* @retval OT_ERROR_NONE Successfully appended the bytes.
* @retval OT_ERROR_NO_BUFS Insufficient available buffers to grow the message.
*
*/
otError Append(const void *aBuf, uint16_t aLength);
/**
* This method reads bytes from the message.
*
* @param[in] aOffset Byte offset within the message to begin reading.
* @param[in] aLength Number of bytes to read.
* @param[in] aBuf A pointer to a data buffer.
*
* @returns The number of bytes read.
*
*/
uint16_t Read(uint16_t aOffset, uint16_t aLength, void *aBuf) const;
/**
* This method writes bytes to the message.
*
* @param[in] aOffset Byte offset within the message to begin writing.
* @param[in] aLength Number of bytes to write.
* @param[in] aBuf A pointer to a data buffer.
*
* @returns The number of bytes written.
*
*/
int Write(uint16_t aOffset, uint16_t aLength, const void *aBuf);
/**
* This method copies bytes from one message to another.
*
* @param[in] aSourceOffset Byte offset within the source message to begin reading.
* @param[in] aDestinationOffset Byte offset within the destination message to begin writing.
* @param[in] aLength Number of bytes to copy.
* @param[in] aMessage Message to copy to.
*
* @returns The number of bytes copied.
*
*/
int CopyTo(uint16_t aSourceOffset, uint16_t aDestinationOffset, uint16_t aLength, Message &aMessage) const;
/**
* This method creates a copy of the message.
*
* It allocates the new message from the same message pool as the original one and copies @p aLength octets
* of the payload. The `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the
* cloned message are also copied from the original one.
*
* @param[in] aLength Number of payload bytes to copy.
*
* @returns A pointer to the message or nullptr if insufficient message buffers are available.
*
*/
Message *Clone(uint16_t aLength) const;
/**
* This method creates a copy of the message.
*
* It allocates the new message from the same message pool as the original one and copies the entire payload. The
* `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
* copied from the original one.
*
* @returns A pointer to the message or nullptr if insufficient message buffers are available.
*
*/
Message *Clone(void) const { return Clone(GetLength()); }
/**
* This method 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; }
/**
* This method sets the datagram tag used for 6LoWPAN fragmentation.
*
* @param[in] aTag The 6LoWPAN datagram tag.
*
*/
void SetDatagramTag(uint32_t aTag) { GetMetadata().mDatagramTag = aTag; }
/**
* This method returns whether or not the message forwarding is scheduled for the child.
*
* @param[in] aChildIndex The index into the child table.
*
* @retval TRUE If the message is scheduled to be forwarded to the child.
* @retval FALSE If the message is not scheduled to be forwarded to the child.
*
*/
bool GetChildMask(uint16_t aChildIndex) const;
/**
* This method unschedules forwarding of the message to the child.
*
* @param[in] aChildIndex The index into the child table.
*
*/
void ClearChildMask(uint16_t aChildIndex);
/**
* This method schedules forwarding of the message to the child.
*
* @param[in] aChildIndex The index into the child table.
*
*/
void SetChildMask(uint16_t aChildIndex);
/**
* This method returns whether or not the message forwarding is scheduled for at least one child.
*
* @retval TRUE If message forwarding is scheduled for at least one child.
* @retval FALSE If message forwarding is not scheduled for any child.
*
*/
bool IsChildPending(void) const;
/**
* This method 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; }
/**
* This method 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; }
/**
* This method returns the IEEE 802.15.4 Destination PAN ID.
*
* @note Only use this when sending MLE Discover Request or Response messages.
*
* @returns The IEEE 802.15.4 Destination PAN ID.
*
*/
uint16_t GetPanId(void) const { return GetMetadata().mPanIdChannel.mPanId; }
/**
* This method 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().mPanIdChannel.mPanId = aPanId; }
/**
* This method 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().mPanIdChannel.mChannel; }
/**
* This method 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().mPanIdChannel.mChannel = aChannel; }
/**
* This method returns the timeout used for 6LoWPAN reassembly.
*
* @returns The time remaining in seconds.
*
*/
uint8_t GetTimeout(void) const { return GetMetadata().mTimeout; }
/**
* This method sets the timeout used for 6LoWPAN reassembly.
*
* @param[in] aTimeout The timeout value.
*
*/
void SetTimeout(uint8_t aTimeout) { GetMetadata().mTimeout = aTimeout; }
/**
* This method decrements the timeout.
*
*/
void DecrementTimeout(void) { GetMetadata().mTimeout--; }
/**
* This method 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 GetDirectTransmission(void) const { return GetMetadata().mDirectTx; }
/**
* This method unschedules forwarding using direct transmission.
*
*/
void ClearDirectTransmission(void) { GetMetadata().mDirectTx = false; }
/**
* This method schedules forwarding using direct transmission.
*
*/
void SetDirectTransmission(void) { GetMetadata().mDirectTx = true; }
/**
* This method 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; }
/**
* This method 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; }
/**
* This method 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; }
/**
* This method 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; }
/**
* This method 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; }
/**
* This method 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; }
/**
* This method 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)); }
/**
* This method returns the average RSS (Received Signal Strength) associated with the message.
*
* @returns The current average RSS value (in dBm) or OT_RADIO_RSSI_INVALID if no average is available.
*
*/
int8_t GetAverageRss(void) const { return GetMetadata().mRssAverager.GetAverage(); }
/**
* This method 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; }
/**
* This static method updates a checksum.
*
* @param[in] aChecksum The checksum value to update.
* @param[in] aValue The 16-bit value to update @p aChecksum with.
*
* @returns The updated checksum.
*
*/
static uint16_t UpdateChecksum(uint16_t aChecksum, uint16_t aValue);
/**
* This static method updates a checksum.
*
* @param[in] aChecksum The checksum value to update.
* @param[in] aBuf A pointer to a buffer.
* @param[in] aLength The number of bytes in @p aBuf.
*
* @returns The updated checksum.
*
*/
static uint16_t UpdateChecksum(uint16_t aChecksum, const void *aBuf, uint16_t aLength);
/**
* This method is used to update a checksum value.
*
* @param[in] aChecksum Initial checksum value.
* @param[in] aOffset Byte offset within the message to begin checksum computation.
* @param[in] aLength Number of bytes to compute the checksum over.
*
* @retval The updated checksum value.
*
*/
uint16_t UpdateChecksum(uint16_t aChecksum, uint16_t aOffset, uint16_t aLength) const;
/**
* This method returns a pointer to the message queue (if any) where this message is queued.
*
* @returns A pointer to the message queue or nullptr if not in any message queue.
*
*/
MessageQueue *GetMessageQueue(void) const
{
return (!GetMetadata().mInPriorityQ) ? GetMetadata().mQueue.mMessage : nullptr;
}
/**
* This method returns a pointer to the priority message queue (if any) where this message is queued.
*
* @returns A pointer to the priority queue or nullptr if not in any priority queue.
*
*/
PriorityQueue *GetPriorityQueue(void) const
{
return (GetMetadata().mInPriorityQ) ? GetMetadata().mQueue.mPriority : nullptr;
}
/**
* This method 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
/**
* This method 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; }
/**
* This method sets the offset to network time.
*
* @param[in] aNetworkTimeOffset The offset to network time.
*
*/
void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) { GetMetadata().mNetworkTimeOffset = aNetworkTimeOffset; }
/**
* This method gets the offset to network time.
*
* @returns The offset to network time.
*
*/
int64_t GetNetworkTimeOffset(void) const { return GetMetadata().mNetworkTimeOffset; }
/**
* This method sets the time sync sequence.
*
* @param[in] aTimeSyncSeq The time sync sequence.
*
*/
void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { GetMetadata().mTimeSyncSeq = aTimeSyncSeq; }
/**
* This method gets the time sync sequence.
*
* @returns The time sync sequence.
*
*/
uint8_t GetTimeSyncSeq(void) const { return GetMetadata().mTimeSyncSeq; }
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
private:
/**
* This method returns a pointer to the message pool to which this message belongs
*
* @returns A pointer to the message pool.
*
*/
MessagePool *GetMessagePool(void) const { return GetMetadata().mMessagePool; }
/**
* This method sets the message pool this message to which this message belongs.
*
* @param[in] aMessagePool A pointer to the message pool
*
*/
void SetMessagePool(MessagePool *aMessagePool) { GetMetadata().mMessagePool = aMessagePool; }
/**
* This method returns `true` if the message is enqueued in any queue (`MessageQueue` or `PriorityQueue`).
*
* @returns `true` if the message is in any queue, `false` otherwise.
*
*/
bool IsInAQueue(void) const { return (GetMetadata().mQueue.mMessage != nullptr); }
/**
* This method sets the message queue information for the message.
*
* @param[in] aMessageQueue A pointer to the message queue where this message is queued.
*
*/
void SetMessageQueue(MessageQueue *aMessageQueue);
/**
* This method sets the message queue information for the message.
*
* @param[in] aPriorityQueue A pointer to the priority queue where this message is queued.
*
*/
void SetPriorityQueue(PriorityQueue *aPriorityQueue);
/**
* This method returns a reference to the `mNext` pointer.
*
* @returns A reference to the mNext pointer.
*
*/
Message *&Next(void) { return GetMetadata().mNext; }
/**
* This method returns a reference to the `mNext` pointer (const pointer).
*
*
* @returns A reference to the mNext pointer.
*
*/
Message *const &Next(void) const { return GetMetadata().mNext; }
/**
* This method returns a reference to the `mPrev` pointer.
*
* @returns A reference to the mPrev pointer.
*
*/
Message *&Prev(void) { return GetMetadata().mPrev; }
/**
* This method returns the number of reserved header bytes.
*
* @returns The number of reserved header bytes.
*
*/
uint16_t GetReserved(void) const { return GetMetadata().mReserved; }
/**
* This method sets the number of reserved header bytes.
*
* @param[in] aReservedHeader The number of header bytes to reserve.
*
*/
void SetReserved(uint16_t aReservedHeader) { GetMetadata().mReserved = aReservedHeader; }
/**
* This method adds or frees message buffers to meet the requested length.
*
* @param[in] aLength The number of bytes that the message buffer needs to handle.
*
* @retval OT_ERROR_NONE Successfully resized the message.
* @retval OT_ERROR_NO_BUFS Could not grow the message due to insufficient available message buffers.
*
*/
otError ResizeMessage(uint16_t aLength);
};
/**
* This class implements a message queue.
*
*/
class MessageQueue : public otMessageQueue
{
friend class Message;
friend class PriorityQueue;
public:
/**
* This enumeration 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
{
kQueuePositionHead, ///< Indicates the head (front) of the list.
kQueuePositionTail, ///< Indicates the tail (end) of the list.
};
/**
* This constructor initializes the message queue.
*
*/
MessageQueue(void);
/**
* This method returns a pointer to the first message.
*
* @returns A pointer to the first message.
*
*/
Message *GetHead(void) const;
/**
* This method adds a message to the end of the list.
*
* @param[in] aMessage The message to add.
*
*/
void Enqueue(Message &aMessage) { Enqueue(aMessage, kQueuePositionTail); }
/**
* This method 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);
/**
* This method removes a message from the list.
*
* @param[in] aMessage The message to remove.
*
*/
void Dequeue(Message &aMessage);
/**
* This method returns the number of messages and buffers enqueued.
*
* @param[out] aMessageCount Returns the number of messages enqueued.
* @param[out] aBufferCount Returns the number of buffers enqueued.
*
*/
void GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const;
private:
/**
* This method returns the tail of the list (last message in the list)
*
* @returns A pointer to the tail of the list.
*
*/
Message *GetTail(void) const { return static_cast<Message *>(mData); }
/**
* This method set the tail of the list.
*
* @param[in] aMessage A pointer to the message to set as new tail.
*
*/
void SetTail(Message *aMessage) { mData = aMessage; }
};
/**
* This class implements a priority queue.
*
*/
class PriorityQueue
{
friend class Message;
friend class MessageQueue;
friend class MessagePool;
public:
/**
* This constructor initializes the priority queue.
*
*/
PriorityQueue(void);
/**
* This method returns a pointer to the first message.
*
* @returns A pointer to the first message.
*
*/
Message *GetHead(void) const;
/**
* This method 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) const;
/**
* This method adds a message to the queue.
*
* @param[in] aMessage The message to add.
*
*/
void Enqueue(Message &aMessage);
/**
* This method removes a message from the list.
*
* @param[in] aMessage The message to remove.
*
*/
void Dequeue(Message &aMessage);
/**
* This method returns the number of messages and buffers enqueued.
*
* @param[out] aMessageCount Returns the number of messages enqueued.
* @param[out] aBufferCount Returns the number of buffers enqueued.
*
*/
void GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const;
/**
* This method returns the tail of the list (last message in the list)
*
* @returns A pointer to the tail of the list.
*
*/
Message *GetTail(void) const;
private:
/**
* This method increases (moves forward) the given priority while ensuring to wrap from
* priority value `kNumPriorities` -1 back to 0.
*
* @param[in] aPriority A given priority level
*
* @returns Increased/Moved forward priority level
*/
uint8_t PrevPriority(uint8_t aPriority) const
{
return (aPriority == Message::kNumPriorities - 1) ? 0 : (aPriority + 1);
}
/**
* This private method finds the first non-nullptr tail starting from the given priority level and moving forward.
* It wraps from priority value `kNumPriorities` -1 back to 0.
*
* aStartPriorityLevel Starting priority level.
*
* @returns The first non-nullptr tail pointer, or nullptr if all the
*
*/
Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const;
private:
Message *mTails[Message::kNumPriorities]; ///< Tail pointers associated with different priority levels.
};
/**
* This class represents a message pool
*
*/
class MessagePool : public InstanceLocator, private NonCopyable
{
friend class Message;
friend class MessageQueue;
friend class PriorityQueue;
public:
/**
* This constructor initializes the object.
*
*/
explicit MessagePool(Instance &aInstance);
/**
* This method is used to obtain a new message.
*
* The link security is enabled by default on the newly obtained message.
*
* @param[in] aType The message type.
* @param[in] aReserveHeader The number of header bytes to reserve.
* @param[in] aPriority The priority level of the message.
*
* @returns A pointer to the message or nullptr if no message buffers are available.
*
*/
Message *New(Message::Type aType, uint16_t aReserveHeader, Message::Priority aPriority);
public:
/**
* This method is used to obtain 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 *New(Message::Type aType,
uint16_t aReserveHeader,
const Message::Settings &aSettings = Message::Settings::GetDefault());
/**
* This method 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);
/**
* This method returns the number of free buffers.
*
* @returns The number of free buffers.
*
*/
uint16_t GetFreeBufferCount(void) const;
private:
Buffer *NewBuffer(Message::Priority aPriority);
void FreeBuffers(Buffer *aBuffer);
otError ReclaimBuffers(int aNumBuffers, Message::Priority aPriority);
#if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT == 0
uint16_t mNumFreeBuffers;
Pool<Buffer, kNumBuffers> mBufferPool;
#endif
};
/**
* @}
*
*/
} // namespace ot
#endif // MESSAGE_HPP_