1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for the message buffer pool and message buffers.
32  */
33 
34 #ifndef MESSAGE_HPP_
35 #define MESSAGE_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stdint.h>
40 
41 #include <openthread/message.h>
42 #include <openthread/nat64.h>
43 #include <openthread/platform/messagepool.h>
44 
45 #include "common/as_core_type.hpp"
46 #include "common/clearable.hpp"
47 #include "common/code_utils.hpp"
48 #include "common/const_cast.hpp"
49 #include "common/data.hpp"
50 #include "common/encoding.hpp"
51 #include "common/iterator_utils.hpp"
52 #include "common/linked_list.hpp"
53 #include "common/locator.hpp"
54 #include "common/non_copyable.hpp"
55 #include "common/offset_range.hpp"
56 #include "common/pool.hpp"
57 #include "common/timer.hpp"
58 #include "common/type_traits.hpp"
59 #include "mac/mac_types.hpp"
60 #include "thread/child_mask.hpp"
61 #include "thread/link_quality.hpp"
62 
63 /**
64  * Represents an opaque (and empty) type for an OpenThread message buffer.
65  */
66 struct otMessage
67 {
68 };
69 
70 namespace ot {
71 
72 namespace Crypto {
73 
74 class AesCcm;
75 class Sha256;
76 class HmacSha256;
77 
78 } // namespace Crypto
79 
80 /**
81  * @addtogroup core-message
82  *
83  * @brief
84  *   This module includes definitions for the message buffer pool and message buffers.
85  *
86  * @{
87  */
88 
89 /**
90  * Frees a given message buffer if not `nullptr`.
91  *
92  * And the ones that follow contain small but common code patterns used in many of the core modules. They
93  * are intentionally defined as macros instead of inline methods/functions to ensure that they are fully inlined.
94  * Note that an `inline` method/function is not necessarily always inlined by the toolchain and not inlining such
95  * small implementations can add a rather large code-size overhead.
96  *
97  * @param[in] aMessage    A pointer to a `Message` to free (can be `nullptr`).
98  */
99 #define FreeMessage(aMessage)      \
100     do                             \
101     {                              \
102         if ((aMessage) != nullptr) \
103         {                          \
104             (aMessage)->Free();    \
105         }                          \
106     } while (false)
107 
108 /**
109  * Frees a given message buffer if a given `Error` indicates an error.
110  *
111  * The parameter @p aMessage can be `nullptr` in which case this macro does nothing.
112  *
113  * @param[in] aMessage    A pointer to a `Message` to free (can be `nullptr`).
114  * @param[in] aError      The `Error` to check.
115  */
116 #define FreeMessageOnError(aMessage, aError)                     \
117     do                                                           \
118     {                                                            \
119         if (((aError) != kErrorNone) && ((aMessage) != nullptr)) \
120         {                                                        \
121             (aMessage)->Free();                                  \
122         }                                                        \
123     } while (false)
124 
125 /**
126  * Frees a given message buffer if a given `Error` indicates an error and sets the `aMessage` to `nullptr`.
127  *
128  * @param[in] aMessage    A pointer to a `Message` to free (can be `nullptr`).
129  * @param[in] aError      The `Error` to check.
130  */
131 #define FreeAndNullMessageOnError(aMessage, aError)              \
132     do                                                           \
133     {                                                            \
134         if (((aError) != kErrorNone) && ((aMessage) != nullptr)) \
135         {                                                        \
136             (aMessage)->Free();                                  \
137             (aMessage) = nullptr;                                \
138         }                                                        \
139     } while (false)
140 
141 constexpr uint16_t kNumBuffers = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS;
142 constexpr uint16_t kBufferSize = OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE;
143 
144 class Message;
145 class MessagePool;
146 class MessageQueue;
147 class PriorityQueue;
148 class ThreadLinkInfo;
149 
150 /**
151  * Represents the link security mode indicating whether to use MAC (layer two) security.
152  */
153 enum LinkSecurityMode : bool
154 {
155     kNoLinkSecurity   = false, ///< Link security disabled (no link security).
156     kWithLinkSecurity = true,  ///< Link security enabled.
157 };
158 
159 /**
160  * Represents a Message buffer.
161  */
162 class Buffer : public otMessageBuffer, public LinkedListEntry<Buffer>
163 {
164     friend class Message;
165 
166 public:
167     /**
168      * Returns a pointer to the next message buffer.
169      *
170      * @returns A pointer to the next message buffer.
171      */
GetNextBuffer(void)172     Buffer *GetNextBuffer(void) { return GetNext(); }
173 
174     /**
175      * Returns a pointer to the next message buffer.
176      *
177      * @returns A pointer to the next message buffer.
178      */
GetNextBuffer(void) const179     const Buffer *GetNextBuffer(void) const { return GetNext(); }
180 
181     /**
182      * Sets the pointer to the next message buffer.
183      *
184      * @param[in] aNext  A pointer to the next buffer.
185      */
SetNextBuffer(Buffer * aNext)186     void SetNextBuffer(Buffer *aNext) { SetNext(aNext); }
187 
188 protected:
189     struct Metadata
190     {
191         bool mDirectTx : 1;            // Whether a direct transmission is required.
192         bool mLinkSecurity : 1;        // Whether link security is enabled.
193         bool mInPriorityQ : 1;         // Whether the message is queued in normal or priority queue.
194         bool mTxSuccess : 1;           // Whether the direct tx of the message was successful.
195         bool mDoNotEvict : 1;          // Whether this message may be evicted.
196         bool mMulticastLoop : 1;       // Whether this multicast message may be looped back.
197         bool mResolvingAddress : 1;    // Whether the message is pending an address query resolution.
198         bool mAllowLookbackToHost : 1; // Whether the message is allowed to be looped back to host.
199         bool mIsDstPanIdBroadcast : 1; // Whether the dest PAN ID is broadcast.
200 #if OPENTHREAD_CONFIG_MULTI_RADIO
201         bool mIsRadioTypeSet : 1; // Whether the radio type is set.
202 #endif
203 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
204         bool mTimeSync : 1; // Whether the message is also used for time sync purpose.
205 #endif
206         uint8_t mPriority : 2; // The message priority level (higher value is higher priority).
207         uint8_t mOrigin : 2;   // The origin of the message.
208 #if OPENTHREAD_CONFIG_MULTI_RADIO
209         uint8_t mRadioType : 2; // The radio link type the message was received on, or should be sent on.
210         static_assert(Mac::kNumRadioTypes <= (1 << 2), "mRadioType bitfield cannot store all radio type values");
211 #endif
212         uint8_t mType : 3;    // The message type.
213         uint8_t mSubType : 4; // The message sub type.
214         uint8_t mMleCommand;  // The MLE command type (used when `mSubType is `Mle`).
215         uint8_t mChannel;     // The message channel (used for MLE Announce).
216 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
217         uint8_t mTimeSyncSeq; // The time sync sequence.
218 #endif
219         uint16_t mLength;      // Current message length (number of bytes).
220         uint16_t mOffset;      // A byte offset within the message.
221         uint16_t mReserved;    // Number of reserved bytes (for header).
222         uint16_t mMeshDest;    // Used for unicast non-link-local messages.
223         uint16_t mPanId;       // PAN ID (used for MLE Discover Request and Response).
224         uint32_t mDatagramTag; // The datagram tag used for 6LoWPAN frags or IPv6fragmentation.
225 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
226         int64_t mNetworkTimeOffset; // The time offset to the Thread network time, in microseconds.
227 #endif
228         TimeMilli    mTimestamp;   // The message timestamp.
229         Message     *mNext;        // Next message in a doubly linked list.
230         Message     *mPrev;        // Previous message in a doubly linked list.
231         MessagePool *mMessagePool; // Message pool for this message.
232         void        *mQueue;       // The queue where message is queued (if any). Queue type from `mInPriorityQ`.
233         RssAverager  mRssAverager; // The averager maintaining the received signal strength (RSS) average.
234         LqiAverager  mLqiAverager; // The averager maintaining the Link quality indicator (LQI) average.
235 #if OPENTHREAD_FTD
236         ChildMask mChildMask; // ChildMask to indicate which sleepy children need to receive this.
237 #endif
238     };
239 
240     static_assert(kBufferSize > sizeof(Metadata) + sizeof(otMessageBuffer), "Metadata does not fit in a single buffer");
241 
242     static constexpr uint16_t kBufferDataSize     = kBufferSize - sizeof(otMessageBuffer);
243     static constexpr uint16_t kHeadBufferDataSize = kBufferDataSize - sizeof(Metadata);
244 
GetMetadata(void)245     Metadata       &GetMetadata(void) { return mBuffer.mHead.mMetadata; }
GetMetadata(void) const246     const Metadata &GetMetadata(void) const { return mBuffer.mHead.mMetadata; }
247 
GetFirstData(void)248     uint8_t       *GetFirstData(void) { return mBuffer.mHead.mData; }
GetFirstData(void) const249     const uint8_t *GetFirstData(void) const { return mBuffer.mHead.mData; }
250 
GetData(void)251     uint8_t       *GetData(void) { return mBuffer.mData; }
GetData(void) const252     const uint8_t *GetData(void) const { return mBuffer.mData; }
253 
254 private:
255     union
256     {
257         struct
258         {
259             Metadata mMetadata;
260             uint8_t  mData[kHeadBufferDataSize];
261         } mHead;
262         uint8_t mData[kBufferDataSize];
263     } mBuffer;
264 };
265 
266 static_assert(sizeof(Buffer) >= kBufferSize,
267               "Buffer size is not valid. Increase OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE.");
268 
269 /**
270  * Represents a message.
271  */
272 class Message : public otMessage, public Buffer, public GetProvider<Message>
273 {
274     friend class Checksum;
275     friend class Crypto::HmacSha256;
276     friend class Crypto::Sha256;
277     friend class Crypto::AesCcm;
278     friend class MessagePool;
279     friend class MessageQueue;
280     friend class PriorityQueue;
281 
282 public:
283     /**
284      * Represents the message type.
285      */
286     enum Type : uint8_t
287     {
288         kTypeIp6          = 0, ///< A full uncompressed IPv6 packet
289         kType6lowpan      = 1, ///< A 6lowpan frame
290         kTypeSupervision  = 2, ///< A child supervision frame.
291         kTypeMacEmptyData = 3, ///< An empty MAC data frame.
292         kTypeIp4          = 4, ///< A full uncompressed IPv4 packet, for NAT64.
293         kTypeBle          = 5, ///< A BLE payload message.
294         kTypeOther        = 6, ///< Other (data) message.
295     };
296 
297     /**
298      * Represents the message sub-type.
299      */
300     enum SubType : uint8_t
301     {
302         kSubTypeNone                   = 0, ///< None
303         kSubTypeMle                    = 1, ///< MLE message
304         kSubTypeMplRetransmission      = 2, ///< MPL next retransmission message
305         kSubTypeJoinerEntrust          = 3, ///< Joiner Entrust
306         kSubTypeJoinerFinalizeResponse = 4, ///< Joiner Finalize Response
307 
308     };
309 
310     enum Priority : uint8_t
311     {
312         kPriorityLow    = OT_MESSAGE_PRIORITY_LOW,      ///< Low priority level.
313         kPriorityNormal = OT_MESSAGE_PRIORITY_NORMAL,   ///< Normal priority level.
314         kPriorityHigh   = OT_MESSAGE_PRIORITY_HIGH,     ///< High priority level.
315         kPriorityNet    = OT_MESSAGE_PRIORITY_HIGH + 1, ///< Network Control priority level.
316     };
317 
318     static constexpr uint8_t kNumPriorities = 4; ///< Number of priority levels.
319 
320     /**
321      * Represents the message ownership model when a `Message` instance is passed to a method/function.
322      */
323     enum Ownership : uint8_t
324     {
325         /**
326          * This value indicates that the method/function receiving a `Message` instance should take custody of the
327          * message (e.g., the method should `Free()` the message if no longer needed).
328          */
329         kTakeCustody,
330 
331         /**
332          * This value indicates that the method/function receiving a `Message` instance does not own the message (e.g.,
333          * it should not `Free()` or `Enqueue()` it in a queue). The receiving method/function should create a
334          * copy/clone of the message to keep (if/when needed).
335          */
336         kCopyToUse,
337     };
338 
339     /**
340      * Represents an IPv6 message origin.
341      */
342     enum Origin : uint8_t
343     {
344         kOriginThreadNetif   = OT_MESSAGE_ORIGIN_THREAD_NETIF,   // Message from Thread Netif.
345         kOriginHostTrusted   = OT_MESSAGE_ORIGIN_HOST_TRUSTED,   // Message from a trusted source on host.
346         kOriginHostUntrusted = OT_MESSAGE_ORIGIN_HOST_UNTRUSTED, // Message from an untrusted source on host.
347     };
348 
349     /**
350      * Represents settings used for creating a new message.
351      */
352     class Settings : public otMessageSettings
353     {
354     public:
355         /**
356          * Initializes the `Settings` object.
357          *
358          * @param[in]  aSecurityMode  A link security mode.
359          * @param[in]  aPriority      A message priority.
360          */
361         Settings(LinkSecurityMode aSecurityMode, Priority aPriority);
362 
363         /**
364          * Initializes the `Settings` with a given message priority and link security enabled.
365          *
366          * @param[in]  aPriority      A message priority.
367          */
Settings(Priority aPriority)368         explicit Settings(Priority aPriority)
369             : Settings(kWithLinkSecurity, aPriority)
370         {
371         }
372 
373         /**
374          * Gets the message priority.
375          *
376          * @returns The message priority.
377          */
GetPriority(void) const378         Priority GetPriority(void) const { return static_cast<Priority>(mPriority); }
379 
380         /**
381          * Indicates whether the link security should be enabled.
382          *
383          * @returns TRUE if link security should be enabled, FALSE otherwise.
384          */
IsLinkSecurityEnabled(void) const385         bool IsLinkSecurityEnabled(void) const { return mLinkSecurityEnabled; }
386 
387         /**
388          * Converts a pointer to an `otMessageSettings` to a `Settings`.
389          *
390          * @param[in] aSettings  A pointer to `otMessageSettings` to convert from.
391          *                       If it is `nullptr`, then the default settings `GetDefault()` will be used.
392          *
393          * @returns A reference to the converted `Settings` or the default if @p aSettings is `nullptr`.
394          */
395         static const Settings &From(const otMessageSettings *aSettings);
396 
397         /**
398          * Returns the default settings with link security enabled and `kPriorityNormal` priority.
399          *
400          * @returns A reference to the default settings (link security enable and `kPriorityNormal` priority).
401          */
GetDefault(void)402         static const Settings &GetDefault(void) { return static_cast<const Settings &>(kDefault); }
403 
404     private:
405         static const otMessageSettings kDefault;
406     };
407 
408     /**
409      * Represents footer data appended to the end of a `Message`.
410      *
411      * This data typically represents some metadata associated with the `Message` that is appended to its end. It can
412      * be read later from the message, updated (re-written) in the message, or fully removed from it.
413      *
414      * Users of `FooterData` MUST follow CRTP-style inheritance, i.e., the `DataType` itself MUST publicly inherit
415      * from `FooterData<DataType>`.
416      *
417      * @tparam DataType   The footer data type.
418      */
419     template <typename DataType> class FooterData
420     {
421     public:
422         /**
423          * Appends the footer data to the end of a given message.
424          *
425          * @param[in,out] aMessage   The message to append to.
426          *
427          * @retval kErrorNone    Successfully appended the footer data.
428          * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
429          */
AppendTo(Message & aMessage) const430         Error AppendTo(Message &aMessage) const { return aMessage.Append<DataType>(AsDataType()); }
431 
432         /**
433          * Reads the footer data from a given message.
434          *
435          * Caller MUST ensure data was successfully appended to the message beforehand. Otherwise behavior is undefined.
436          *
437          * @param[in] aMessage   The message to read from.
438          */
ReadFrom(const Message & aMessage)439         void ReadFrom(const Message &aMessage)
440         {
441             IgnoreError(aMessage.Read<DataType>(aMessage.GetLength() - sizeof(DataType), AsDataType()));
442         }
443 
444         /**
445          * Updates the footer data in a given message (rewriting over the previously appended data).
446          *
447          * Caller MUST ensure data was successfully appended to the message beforehand. Otherwise behavior is undefined.
448          *
449          * @param[in,out] aMessage   The message to update.
450          */
UpdateIn(Message & aMessage) const451         void UpdateIn(Message &aMessage) const
452         {
453             aMessage.Write<DataType>(aMessage.GetLength() - sizeof(DataType), AsDataType());
454         }
455 
456         /**
457          * Removes the footer data from a given message.
458          *
459          * Caller MUST ensure data was successfully appended to the message beforehand. Otherwise behavior is undefined.
460          *
461          * @param[in,out] aMessage   The message to remove the data from.
462          */
RemoveFrom(Message & aMessage) const463         void RemoveFrom(Message &aMessage) const { aMessage.RemoveFooter(sizeof(DataType)); }
464 
465     protected:
466         FooterData(void) = default;
467 
468     private:
AsDataType(void) const469         const DataType &AsDataType(void) const { return static_cast<const DataType &>(*this); }
AsDataType(void)470         DataType       &AsDataType(void) { return static_cast<DataType &>(*this); }
471     };
472 
473     /**
474      * Returns a reference to the OpenThread Instance which owns the `Message`.
475      *
476      * @returns A reference to the `Instance`.
477      */
478     Instance &GetInstance(void) const;
479 
480     /**
481      * Frees this message buffer.
482      */
483     void Free(void);
484 
485     /**
486      * Returns a pointer to the next message.
487      *
488      * @returns A pointer to the next message in the list or `nullptr` if at the end of the list.
489      */
490     Message *GetNext(void) const;
491 
492     /**
493      * Returns the number of bytes in the message.
494      *
495      * @returns The number of bytes in the message.
496      */
GetLength(void) const497     uint16_t GetLength(void) const { return GetMetadata().mLength; }
498 
499     /**
500      * Sets the number of bytes in the message.
501      *
502      * @param[in]  aLength  Requested number of bytes in the message.
503      *
504      * @retval kErrorNone    Successfully set the length of the message.
505      * @retval kErrorNoBufs  Failed to grow the size of the message because insufficient buffers were available.
506      */
507     Error SetLength(uint16_t aLength);
508 
509     /**
510      * Returns the number of buffers in the message.
511      */
512     uint8_t GetBufferCount(void) const;
513 
514     /**
515      * Returns the byte offset within the message.
516      *
517      * @returns A byte offset within the message.
518      */
GetOffset(void) const519     uint16_t GetOffset(void) const { return GetMetadata().mOffset; }
520 
521     /**
522      * Moves the byte offset within the message.
523      *
524      * @param[in]  aDelta  The number of bytes to move the current offset, which may be positive or negative.
525      */
526     void MoveOffset(int aDelta);
527 
528     /**
529      * Sets the byte offset within the message.
530      *
531      * @param[in]  aOffset  The byte offset within the message.
532      */
533     void SetOffset(uint16_t aOffset);
534 
535     /**
536      * Returns the type of the message.
537      *
538      * @returns The type of the message.
539      */
GetType(void) const540     Type GetType(void) const { return static_cast<Type>(GetMetadata().mType); }
541 
542     /**
543      * Sets the message type.
544      *
545      * @param[in]  aType  The message type.
546      */
SetType(Type aType)547     void SetType(Type aType) { GetMetadata().mType = aType; }
548 
549     /**
550      * Returns the sub type of the message.
551      *
552      * @returns The sub type of the message.
553      */
GetSubType(void) const554     SubType GetSubType(void) const { return static_cast<SubType>(GetMetadata().mSubType); }
555 
556     /**
557      * Sets the message sub type.
558      *
559      * @param[in]  aSubType  The message sub type.
560      */
SetSubType(SubType aSubType)561     void SetSubType(SubType aSubType) { GetMetadata().mSubType = aSubType; }
562 
563     /**
564      * Indicates whether or not the message is of MLE sub type.
565      *
566      * @retval TRUE   The message is of MLE sub type.
567      * @retval FALSE  The message is not of MLE sub type.
568      */
IsSubTypeMle(void) const569     bool IsSubTypeMle(void) const { return (GetSubType() == kSubTypeMle); }
570 
571     /**
572      * Indicates whether or not the message is a given MLE command.
573      *
574      * It checks `IsSubTypeMle()` and then if `GetMleCommand()` is the same as `aMleCommand`.
575      *
576      * @param[in] aMleCommand  The MLE command type.
577      *
578      * @retval TRUE  The message is an MLE command of @p aMleCommand type.
579      * @retval FALSE The message is not an MLE command of @p aMleCommand type.
580      */
581     bool IsMleCommand(Mle::Command aMleCommand) const;
582 
583     /**
584      * Gets the MLE command type.
585      *
586      * Caller MUST ensure that message sub type is `kSubTypeMle` before calling this method. Otherwise the returned
587      * value is not meaningful.
588      *
589      * @returns The message's MLE command type.
590      */
GetMleCommand(void) const591     Mle::Command GetMleCommand(void) const { return static_cast<Mle::Command>(GetMetadata().mMleCommand); }
592 
593     /**
594      * Set the MLE command type of message.
595      *
596      * Caller should also set the sub type to `kSubTypeMle`.
597      *
598      * @param[in] aMleCommand  The MLE command type.
599      */
SetMleCommand(Mle::Command aMleCommand)600     void SetMleCommand(Mle::Command aMleCommand) { GetMetadata().mMleCommand = aMleCommand; }
601 
602     /**
603      * Checks whether this multicast message may be looped back.
604      *
605      * @retval TRUE   If message may be looped back.
606      * @retval FALSE  If message must not be looped back.
607      */
GetMulticastLoop(void) const608     bool GetMulticastLoop(void) const { return GetMetadata().mMulticastLoop; }
609 
610     /**
611      * Sets whether multicast may be looped back.
612      *
613      * @param[in]  aMulticastLoop  Whether allow looping back multicast.
614      */
SetMulticastLoop(bool aMulticastLoop)615     void SetMulticastLoop(bool aMulticastLoop) { GetMetadata().mMulticastLoop = aMulticastLoop; }
616 
617     /**
618      * Returns the message priority level.
619      *
620      * @returns The priority level associated with this message.
621      */
GetPriority(void) const622     Priority GetPriority(void) const { return static_cast<Priority>(GetMetadata().mPriority); }
623 
624     /**
625      * Sets the messages priority.
626      * If the message is already queued in a priority queue, changing the priority ensures to
627      * update the message in the associated queue.
628      *
629      * @param[in]  aPriority  The message priority level.
630      *
631      * @retval kErrorNone          Successfully set the priority for the message.
632      * @retval kErrorInvalidArgs   Priority level is not invalid.
633      */
634     Error SetPriority(Priority aPriority);
635 
636     /**
637      * Convert a `Priority` to a string.
638      *
639      * @param[in] aPriority  The priority level.
640      *
641      * @returns A string representation of @p aPriority.
642      */
643     static const char *PriorityToString(Priority aPriority);
644 
645     /**
646      * Prepends bytes to the front of the message.
647      *
648      * On success, this method grows the message by @p aLength bytes.
649      *
650      * @param[in]  aBuf     A pointer to a data buffer (can be `nullptr` to grow message without writing bytes).
651      * @param[in]  aLength  The number of bytes to prepend.
652      *
653      * @retval kErrorNone    Successfully prepended the bytes.
654      * @retval kErrorNoBufs  Not enough reserved bytes in the message.
655      */
656     Error PrependBytes(const void *aBuf, uint16_t aLength);
657 
658     /**
659      * Prepends an object to the front of the message.
660      *
661      * On success, this method grows the message by the size of the object.
662      *
663      * @tparam    ObjectType   The object type to prepend to the message.
664      *
665      * @param[in] aObject      A reference to the object to prepend to the message.
666      *
667      * @retval kErrorNone    Successfully prepended the object.
668      * @retval kErrorNoBufs  Not enough reserved bytes in the message.
669      */
Prepend(const ObjectType & aObject)670     template <typename ObjectType> Error Prepend(const ObjectType &aObject)
671     {
672         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
673 
674         return PrependBytes(&aObject, sizeof(ObjectType));
675     }
676 
677     /**
678      * Removes header bytes from the message at start of message.
679      *
680      * The caller MUST ensure that message contains the bytes to be removed, i.e. `aOffset` is smaller than the message
681      * length.
682      *
683      * @param[in]  aLength  Number of header bytes to remove from start of `Message`.
684      */
685     void RemoveHeader(uint16_t aLength);
686 
687     /**
688      * Removes header bytes from the message at a given offset.
689      *
690      * Shrinks the message. The existing header bytes before @p aOffset are copied forward and replace the
691      * removed bytes.
692      *
693      * The caller MUST ensure that message contains the bytes to be removed, i.e. `aOffset + aLength` is smaller than
694      * the message length.
695      *
696      * @param[in]  aOffset  The offset to start removing.
697      * @param[in]  aLength  Number of header bytes to remove.
698      */
699     void RemoveHeader(uint16_t aOffset, uint16_t aLength);
700 
701     /**
702      * Grows the message to make space for new header bytes at a given offset.
703      *
704      * Grows the message header (similar to `PrependBytes()`). The existing header bytes from start to
705      * `aOffset + aLength` are then copied backward to make room for the new header bytes. Note that this method does
706      * not change the bytes from @p aOffset up @p aLength (the new inserted header range). Caller can write to this
707      * range to update the bytes after successful return from this method.
708      *
709      * @param[in] aOffset   The offset at which to insert the header bytes
710      * @param[in] aLength   Number of header bytes to insert.
711      *
712      * @retval kErrorNone    Successfully grown the message and copied the existing header bytes.
713      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
714      */
715     Error InsertHeader(uint16_t aOffset, uint16_t aLength);
716 
717     /**
718      * Removes footer bytes from the end of the message.
719      *
720      * The caller should ensure the message contains the bytes to be removed, otherwise as many bytes as available
721      * will be removed.
722      *
723      * @param[in] aLength   Number of footer bytes to remove from end of the `Message`.
724      */
725     void RemoveFooter(uint16_t aLength);
726 
727     /**
728      * Appends bytes to the end of the message.
729      *
730      * On success, this method grows the message by @p aLength bytes.
731      *
732      * @param[in]  aBuf     A pointer to a data buffer (MUST not be `nullptr`).
733      * @param[in]  aLength  The number of bytes to append.
734      *
735      * @retval kErrorNone    Successfully appended the bytes.
736      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
737      */
738     Error AppendBytes(const void *aBuf, uint16_t aLength);
739 
740     /**
741      * Appends bytes read from another or potentially the same message to the end of the current message.
742      *
743      * On success, this method grows the message by @p aLength bytes.
744      *
745      * @param[in] aMessage   The message to read the bytes from (it can be the same as the current message).
746      * @param[in] aOffset    The offset in @p aMessage to start reading the bytes from.
747      * @param[in] aLength    The number of bytes to read from @p aMessage and append.
748      *
749      * @retval kErrorNone    Successfully appended the bytes.
750      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
751      * @retval kErrorParse   Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset.
752      */
753     Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
754 
755     /**
756      * Appends bytes read from another or potentially the same message to the end of the current message.
757      *
758      * @param[in] aMessage     The message to read the bytes from (it can be the same as the current message).
759      * @param[in] aOffsetRange The offset range in @p aMessage to read bytes from.
760      *
761      * @retval kErrorNone    Successfully appended the bytes.
762      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
763      * @retval kErrorParse   Not enough bytes in @p aMessage to read @p aOffsetRange.
764      */
765     Error AppendBytesFromMessage(const Message &aMessage, const OffsetRange &aOffsetRange);
766 
767     /**
768      * Appends an object to the end of the message.
769      *
770      * On success, this method grows the message by the size of the appended object
771      *
772      * @tparam    ObjectType   The object type to append to the message.
773      *
774      * @param[in] aObject      A reference to the object to append to the message.
775      *
776      * @retval kErrorNone    Successfully appended the object.
777      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
778      */
Append(const ObjectType & aObject)779     template <typename ObjectType> Error Append(const ObjectType &aObject)
780     {
781         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
782 
783         return AppendBytes(&aObject, sizeof(ObjectType));
784     }
785 
786     /**
787      * Appends bytes from a given `Data` instance to the end of the message.
788      *
789      * On success, this method grows the message by the size of the appended data.
790      *
791      * @tparam    kDataLengthType   Determines the data length type (`uint8_t` or `uint16_t`).
792      *
793      * @param[in] aData      A reference to `Data` to append to the message.
794      *
795      * @retval kErrorNone    Successfully appended the bytes from @p aData.
796      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
797      */
AppendData(const Data<kDataLengthType> & aData)798     template <DataLengthType kDataLengthType> Error AppendData(const Data<kDataLengthType> &aData)
799     {
800         return AppendBytes(aData.GetBytes(), aData.GetLength());
801     }
802 
803     /**
804      * Reads bytes from the message.
805      *
806      * The provided buffer @p aBuf MUST contain at least @p aLength bytes.
807      *
808      * If there are fewer bytes available in the message than the requested @p aLength, the available bytes are read
809      * and copied into @p aBuf. This method returns the actual number of bytes successfully read from the message and
810      * written into @p aBuf.
811      *
812      * @param[in]  aOffset  Byte offset within the message to begin reading.
813      * @param[out] aBuf     A pointer to a data buffer to copy the read bytes into.
814      * @param[in]  aLength  Number of bytes to read.
815      *
816      * @returns The number of bytes read.
817      */
818     uint16_t ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
819 
820     /**
821      * Reads bytes from the message.
822      *
823      * If there are fewer bytes available in the message than the provided length in @p aOffsetRange, the available
824      * bytes are read and copied into @p aBuf. This method returns the actual number of bytes successfully read from
825      * the message and written into @p aBuf.
826      *
827      * @param[in]  aOffsetRange  The offset range in the message to read bytes from.
828      * @param[out] aBuf          A pointer to a data buffer to copy the read bytes into.
829      *
830      * @returns The number of bytes read.
831      */
832     uint16_t ReadBytes(const OffsetRange &aOffsetRange, void *aBuf) const;
833 
834     /**
835      * Reads a given number of bytes from the message.
836      *
837      * @param[in]  aOffset  Byte offset within the message to begin reading.
838      * @param[out] aBuf     A pointer to a data buffer to copy the read bytes into.
839      * @param[in]  aLength  Number of bytes to read.
840      *
841      * @retval kErrorNone     @p aLength bytes were successfully read from message.
842      * @retval kErrorParse    Not enough bytes remaining in message to read the entire object.
843      */
844     Error Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
845 
846     /**
847      * Reads a given number of bytes from the message.
848      *
849      * @param[in]  aOffsetRange  The offset range in the message to read from.
850      * @param[out] aBuf          A pointer to a data buffer to copy the read bytes into.
851      * @param[in]  aLength       Number of bytes to read.
852      *
853      * @retval kErrorNone     Requested bytes were successfully read from message.
854      * @retval kErrorParse    Not enough bytes remaining to read the requested @p aLength.
855      */
856     Error Read(const OffsetRange &aOffsetRange, void *aBuf, uint16_t aLength) const;
857 
858     /**
859      * Reads an object from the message.
860      *
861      * @tparam     ObjectType   The object type to read from the message.
862      *
863      * @param[in]  aOffset      Byte offset within the message to begin reading.
864      * @param[out] aObject      A reference to the object to read into.
865      *
866      * @retval kErrorNone     Object @p aObject was successfully read from message.
867      * @retval kErrorParse    Not enough bytes remaining in message to read the entire object.
868      */
Read(uint16_t aOffset,ObjectType & aObject) const869     template <typename ObjectType> Error Read(uint16_t aOffset, ObjectType &aObject) const
870     {
871         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
872 
873         return Read(aOffset, &aObject, sizeof(ObjectType));
874     }
875 
876     /**
877      * Reads an object from the message.
878      *
879      * @tparam     ObjectType   The object type to read from the message.
880      *
881      * @param[in]  aOffsetRange  The offset range in the message to read from.
882      * @param[out] aObject       A reference to the object to read into.
883      *
884      * @retval kErrorNone     Object @p aObject was successfully read from message.
885      * @retval kErrorParse    Not enough bytes remaining in message to read the entire object.
886      */
Read(const OffsetRange & aOffsetRange,ObjectType & aObject) const887     template <typename ObjectType> Error Read(const OffsetRange &aOffsetRange, ObjectType &aObject) const
888     {
889         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
890 
891         return Read(aOffsetRange, &aObject, sizeof(ObjectType));
892     }
893 
894     /**
895      * Compares the bytes in the message at a given offset with a given byte array.
896      *
897      * If there are fewer bytes available in the message than the requested @p aLength, the comparison is treated as
898      * failure (returns FALSE).
899      *
900      * @param[in]  aOffset    Byte offset within the message to read from for the comparison.
901      * @param[in]  aBuf       A pointer to a data buffer to compare with the bytes from message.
902      * @param[in]  aLength    Number of bytes in @p aBuf.
903      * @param[in]  aMatcher   A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are directly
904      *                        compared.
905      *
906      * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf,
907      *          FALSE otherwise.
908      */
909     bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher = nullptr) const;
910 
911     /**
912      * Compares the bytes in the message at a given offset with bytes read from another message.
913      *
914      * If either message has fewer bytes available than the requested @p aLength, the comparison is treated as failure
915      * (returns FALSE).
916      *
917      * @param[in]  aOffset        Byte offset within the message to read from for the comparison.
918      * @param[in]  aOtherMessage  The other message to compare with.
919      * @param[in]  aOtherOffset   Byte offset within @p aOtherMessage to read from for the comparison.
920      * @param[in]  aLength        Number of bytes to compare.
921      * @param[in]  aMatcher       A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are
922      *                            directly compared.
923      *
924      * @returns TRUE if there are enough bytes available in both messages and they all match. FALSE otherwise.
925      */
926     bool CompareBytes(uint16_t       aOffset,
927                       const Message &aOtherMessage,
928                       uint16_t       aOtherOffset,
929                       uint16_t       aLength,
930                       ByteMatcher    aMatcher = nullptr) const;
931 
932     /**
933      * Compares the bytes in the message at a given offset with an object.
934      *
935      * The bytes in the message are compared with the bytes in @p aObject. If there are fewer bytes available in the
936      * message than the requested object size, it is treated as failed comparison (returns FALSE).
937      *
938      * @tparam     ObjectType   The object type to compare with the bytes in message.
939      *
940      * @param[in] aOffset      Byte offset within the message to read from for the comparison.
941      * @param[in] aObject      A reference to the object to compare with the message bytes.
942      *
943      * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes in @p aObject,
944      *          FALSE otherwise.
945      */
Compare(uint16_t aOffset,const ObjectType & aObject) const946     template <typename ObjectType> bool Compare(uint16_t aOffset, const ObjectType &aObject) const
947     {
948         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
949 
950         return CompareBytes(aOffset, &aObject, sizeof(ObjectType));
951     }
952 
953     /**
954      * Writes bytes to the message.
955      *
956      * Will not resize the message. The given data to write (with @p aLength bytes) MUST fit within the
957      * existing message buffer (from the given offset @p aOffset up to the message's length).
958      *
959      * @param[in]  aOffset  Byte offset within the message to begin writing.
960      * @param[in]  aBuf     A pointer to a data buffer.
961      * @param[in]  aLength  Number of bytes to write.
962      */
963     void WriteBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength);
964 
965     /**
966      * Writes bytes read from another or potentially the same message to the message at a given offset.
967      *
968      * Will not resize the message. The bytes to write (with @p aLength) MUST fit within the existing
969      * message buffer (from the given @p aWriteOffset up to the message's length).
970      *
971      * Can be used to copy bytes within the same message in either direction, i.e., copy forward where
972      * `aWriteOffset > aReadOffset` or copy backward where `aWriteOffset < aReadOffset`.
973      *
974      * @param[in] aWriteOffset  Byte offset within this message to begin writing.
975      * @param[in] aMessage      The message to read the bytes from.
976      * @param[in] aReadOffset   The offset in @p aMessage to start reading the bytes from.
977      * @param[in] aLength       The number of bytes to read from @p aMessage and write.
978      */
979     void WriteBytesFromMessage(uint16_t aWriteOffset, const Message &aMessage, uint16_t aReadOffset, uint16_t aLength);
980 
981     /**
982      * Writes an object to the message.
983      *
984      * Will not resize the message. The entire given object (all its bytes) MUST fit within the existing
985      * message buffer (from the given offset @p aOffset up to the message's length).
986      *
987      * @tparam     ObjectType   The object type to write to the message.
988      *
989      * @param[in]  aOffset      Byte offset within the message to begin writing.
990      * @param[in]  aObject      A reference to the object to write.
991      */
Write(uint16_t aOffset,const ObjectType & aObject)992     template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject)
993     {
994         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
995 
996         WriteBytes(aOffset, &aObject, sizeof(ObjectType));
997     }
998 
999     /**
1000      * Writes bytes from a given `Data` instance to the message.
1001      *
1002      * Will not resize the message. The given data to write MUST fit within the existing message buffer
1003      * (from the given offset @p aOffset up to the message's length).
1004      *
1005      * @tparam     kDataLengthType   Determines the data length type (`uint8_t` or `uint16_t`).
1006      *
1007      * @param[in]  aOffset    Byte offset within the message to begin writing.
1008      * @param[in]  aData      The `Data` to write to the message.
1009      */
WriteData(uint16_t aOffset,const Data<kDataLengthType> & aData)1010     template <DataLengthType kDataLengthType> void WriteData(uint16_t aOffset, const Data<kDataLengthType> &aData)
1011     {
1012         WriteBytes(aOffset, aData.GetBytes(), aData.GetLength());
1013     }
1014 
1015     /**
1016      * Creates a copy of the message.
1017      *
1018      * It allocates the new message from the same message pool as the original one and copies @p aLength octets
1019      * of the payload. The `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the
1020      * cloned message are also copied from the original one.
1021      *
1022      * @param[in] aLength  Number of payload bytes to copy.
1023      *
1024      * @returns A pointer to the message or nullptr if insufficient message buffers are available.
1025      */
1026     Message *Clone(uint16_t aLength) const;
1027 
1028     /**
1029      * Creates a copy of the message.
1030      *
1031      * It allocates the new message from the same message pool as the original one and copies the entire payload. The
1032      * `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
1033      * copied from the original one.
1034      *
1035      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
1036      */
Clone(void) const1037     Message *Clone(void) const { return Clone(GetLength()); }
1038 
1039     /**
1040      * Returns the datagram tag used for 6LoWPAN fragmentation or the identification used for IPv6
1041      * fragmentation.
1042      *
1043      * @returns The 6LoWPAN datagram tag or the IPv6 fragment identification.
1044      */
GetDatagramTag(void) const1045     uint32_t GetDatagramTag(void) const { return GetMetadata().mDatagramTag; }
1046 
1047     /**
1048      * Sets the datagram tag used for 6LoWPAN fragmentation.
1049      *
1050      * @param[in]  aTag  The 6LoWPAN datagram tag.
1051      */
SetDatagramTag(uint32_t aTag)1052     void SetDatagramTag(uint32_t aTag) { GetMetadata().mDatagramTag = aTag; }
1053 
1054 #if OPENTHREAD_FTD
1055     /**
1056      * Gets the indirect transmission `ChildMask` associated with this `Message`.
1057      *
1058      * The `ChildMask` indicates the set of children for which this message is scheduled for indirect transmission.
1059      *
1060      * @returns A reference to the indirect transmission `ChildMask`.
1061      */
GetIndirectTxChildMask(void)1062     ChildMask &GetIndirectTxChildMask(void) { return GetMetadata().mChildMask; }
1063 
1064     /**
1065      * Gets the indirect transmission `ChildMask` associated with this `Message`.
1066      *
1067      * The `ChildMask` indicates the set of children for which this message is scheduled for indirect transmission.
1068      *
1069      * @returns A reference to the indirect transmission `ChildMask`.
1070      */
GetIndirectTxChildMask(void) const1071     const ChildMask &GetIndirectTxChildMask(void) const { return GetMetadata().mChildMask; }
1072 #endif
1073 
1074     /**
1075      * Returns the RLOC16 of the mesh destination.
1076      *
1077      * @note Only use this for non-link-local unicast messages.
1078      *
1079      * @returns The IEEE 802.15.4 Destination PAN ID.
1080      */
GetMeshDest(void) const1081     uint16_t GetMeshDest(void) const { return GetMetadata().mMeshDest; }
1082 
1083     /**
1084      * Sets the RLOC16 of the mesh destination.
1085      *
1086      * @note Only use this when sending non-link-local unicast messages.
1087      *
1088      * @param[in]  aMeshDest  The IEEE 802.15.4 Destination PAN ID.
1089      */
SetMeshDest(uint16_t aMeshDest)1090     void SetMeshDest(uint16_t aMeshDest) { GetMetadata().mMeshDest = aMeshDest; }
1091 
1092     /**
1093      * Returns the IEEE 802.15.4 Source or Destination PAN ID.
1094      *
1095      * For a message received over the Thread radio, specifies the Source PAN ID when present in MAC header, otherwise
1096      * specifies the Destination PAN ID.
1097      *
1098      * For a message to be sent over the Thread radio, this is set and used for MLE Discover Request or Response
1099      * messages.
1100      *
1101      * @returns The IEEE 802.15.4 PAN ID.
1102      */
GetPanId(void) const1103     uint16_t GetPanId(void) const { return GetMetadata().mPanId; }
1104 
1105     /**
1106      * Sets the IEEE 802.15.4 Destination PAN ID.
1107      *
1108      * @note Only use this when sending MLE Discover Request or Response messages.
1109      *
1110      * @param[in]  aPanId  The IEEE 802.15.4 Destination PAN ID.
1111      */
SetPanId(uint16_t aPanId)1112     void SetPanId(uint16_t aPanId) { GetMetadata().mPanId = aPanId; }
1113 
1114     /**
1115      * Indicates whether the Destination PAN ID is broadcast.
1116      *
1117      * This is applicable for messages received over Thread radio.
1118      *
1119      * @retval TRUE   The Destination PAN ID is broadcast.
1120      * @retval FALSE  The Destination PAN ID is not broadcast.
1121      */
IsDstPanIdBroadcast(void) const1122     bool IsDstPanIdBroadcast(void) const { return GetMetadata().mIsDstPanIdBroadcast; }
1123 
1124     /**
1125      * Returns the IEEE 802.15.4 Channel to use for transmission.
1126      *
1127      * @note Only use this when sending MLE Announce messages.
1128      *
1129      * @returns The IEEE 802.15.4 Channel to use for transmission.
1130      */
GetChannel(void) const1131     uint8_t GetChannel(void) const { return GetMetadata().mChannel; }
1132 
1133     /**
1134      * Sets the IEEE 802.15.4 Channel to use for transmission.
1135      *
1136      * @note Only use this when sending MLE Announce messages.
1137      *
1138      * @param[in]  aChannel  The IEEE 802.15.4 Channel to use for transmission.
1139      */
SetChannel(uint8_t aChannel)1140     void SetChannel(uint8_t aChannel) { GetMetadata().mChannel = aChannel; }
1141 
1142     /**
1143      * Returns the message timestamp.
1144      *
1145      * @returns The message timestamp.
1146      */
GetTimestamp(void) const1147     TimeMilli GetTimestamp(void) const { return GetMetadata().mTimestamp; }
1148 
1149     /**
1150      * Sets the message timestamp to a given time.
1151      *
1152      * @param[in] aTimestamp   The timestamp value.
1153      */
SetTimestamp(TimeMilli aTimestamp)1154     void SetTimestamp(TimeMilli aTimestamp) { GetMetadata().mTimestamp = aTimestamp; }
1155 
1156     /**
1157      * Sets the message timestamp to the current time.
1158      */
SetTimestampToNow(void)1159     void SetTimestampToNow(void) { SetTimestamp(TimerMilli::GetNow()); }
1160 
1161     /**
1162      * Returns whether or not message forwarding is scheduled for direct transmission.
1163      *
1164      * @retval TRUE   If message forwarding is scheduled for direct transmission.
1165      * @retval FALSE  If message forwarding is not scheduled for direct transmission.
1166      */
IsDirectTransmission(void) const1167     bool IsDirectTransmission(void) const { return GetMetadata().mDirectTx; }
1168 
1169     /**
1170      * Unschedules forwarding using direct transmission.
1171      */
ClearDirectTransmission(void)1172     void ClearDirectTransmission(void) { GetMetadata().mDirectTx = false; }
1173 
1174     /**
1175      * Schedules forwarding using direct transmission.
1176      */
SetDirectTransmission(void)1177     void SetDirectTransmission(void) { GetMetadata().mDirectTx = true; }
1178 
1179     /**
1180      * Indicates whether the direct transmission of message was successful.
1181      *
1182      * @retval TRUE   If direct transmission of message was successful (all fragments were delivered and acked).
1183      * @retval FALSE  If direct transmission of message failed (at least one fragment failed).
1184      */
GetTxSuccess(void) const1185     bool GetTxSuccess(void) const { return GetMetadata().mTxSuccess; }
1186 
1187     /**
1188      * Sets whether the direct transmission of message was successful.
1189      *
1190      * @param[in] aTxSuccess   TRUE if the direct transmission is successful, FALSE otherwise (i.e., at least one
1191      *                         fragment transmission failed).
1192      */
SetTxSuccess(bool aTxSuccess)1193     void SetTxSuccess(bool aTxSuccess) { GetMetadata().mTxSuccess = aTxSuccess; }
1194 
1195     /**
1196      * Indicates whether the message may be evicted.
1197      *
1198      * @retval TRUE   If the message must not be evicted.
1199      * @retval FALSE  If the message may be evicted.
1200      */
GetDoNotEvict(void) const1201     bool GetDoNotEvict(void) const { return GetMetadata().mDoNotEvict; }
1202 
1203     /**
1204      * Sets whether the message may be evicted.
1205      *
1206      * @param[in]  aDoNotEvict  TRUE if the message may not be evicted, FALSE otherwise.
1207      */
SetDoNotEvict(bool aDoNotEvict)1208     void SetDoNotEvict(bool aDoNotEvict) { GetMetadata().mDoNotEvict = aDoNotEvict; }
1209 
1210     /**
1211      * Indicates whether the message is waiting for an address query resolution.
1212      *
1213      * @retval TRUE   If the message is waiting for address query resolution.
1214      * @retval FALSE  If the message is not waiting for address query resolution.
1215      */
IsResolvingAddress(void) const1216     bool IsResolvingAddress(void) const { return GetMetadata().mResolvingAddress; }
1217 
1218     /**
1219      * Sets whether the message is waiting for an address query resolution.
1220      *
1221      * @param[in] aResolvingAddress    TRUE if message is waiting for address resolution, FALSE otherwise.
1222      */
SetResolvingAddress(bool aResolvingAddress)1223     void SetResolvingAddress(bool aResolvingAddress) { GetMetadata().mResolvingAddress = aResolvingAddress; }
1224 
1225     /**
1226      * Indicates whether the message is allowed to be looped back to host.
1227      *
1228      * @retval TRUE   If the message is allowed to be looped back to host.
1229      * @retval FALSE  If the message is not allowed to be looped back to host.
1230      */
IsLoopbackToHostAllowed(void) const1231     bool IsLoopbackToHostAllowed(void) const { return GetMetadata().mAllowLookbackToHost; }
1232 
1233     /**
1234      * Sets whether or not allow the message to be looped back to host.
1235      *
1236      * @param[in] aAllowLoopbackToHost  Whether or not allow the message to be looped back to host.
1237      */
SetLoopbackToHostAllowed(bool aAllowLoopbackToHost)1238     void SetLoopbackToHostAllowed(bool aAllowLoopbackToHost)
1239     {
1240         GetMetadata().mAllowLookbackToHost = aAllowLoopbackToHost;
1241     }
1242 
1243     /**
1244      * Gets the message origin.
1245      *
1246      * @returns An enum representing the origin of the message.
1247      */
GetOrigin(void) const1248     Origin GetOrigin(void) const { return static_cast<Origin>(GetMetadata().mOrigin); }
1249 
1250     /**
1251      * Sets the message origin.
1252      *
1253      * @param[in]  aOrigin  An enum representing the origin of the message.
1254      */
SetOrigin(Origin aOrigin)1255     void SetOrigin(Origin aOrigin) { GetMetadata().mOrigin = aOrigin; }
1256 
1257     /**
1258      * Indicates whether or not the message origin is Thread Netif.
1259      *
1260      * @retval TRUE   If the message origin is Thread Netif.
1261      * @retval FALSE  If the message origin is not Thread Netif.
1262      */
IsOriginThreadNetif(void) const1263     bool IsOriginThreadNetif(void) const { return GetOrigin() == kOriginThreadNetif; }
1264 
1265     /**
1266      * Indicates whether or not the message origin is a trusted source on host.
1267      *
1268      * @retval TRUE   If the message origin is a trusted source on host.
1269      * @retval FALSE  If the message origin is not a trusted source on host.
1270      */
IsOriginHostTrusted(void) const1271     bool IsOriginHostTrusted(void) const { return GetOrigin() == kOriginHostTrusted; }
1272 
1273     /**
1274      * Indicates whether or not the message origin is an untrusted source on host.
1275      *
1276      * @retval TRUE   If the message origin is an untrusted source on host.
1277      * @retval FALSE  If the message origin is not an untrusted source on host.
1278      */
IsOriginHostUntrusted(void) const1279     bool IsOriginHostUntrusted(void) const { return GetOrigin() == kOriginHostUntrusted; }
1280 
1281     /**
1282      * Indicates whether or not link security is enabled for the message.
1283      *
1284      * @retval TRUE   If link security is enabled.
1285      * @retval FALSE  If link security is not enabled.
1286      */
IsLinkSecurityEnabled(void) const1287     bool IsLinkSecurityEnabled(void) const { return GetMetadata().mLinkSecurity; }
1288 
1289     /**
1290      * Sets whether or not link security is enabled for the message.
1291      *
1292      * @param[in]  aEnabled  TRUE if link security is enabled, FALSE otherwise.
1293      */
SetLinkSecurityEnabled(bool aEnabled)1294     void SetLinkSecurityEnabled(bool aEnabled) { GetMetadata().mLinkSecurity = aEnabled; }
1295 
1296     /**
1297      * Updates the average RSS (Received Signal Strength) associated with the message by adding the given
1298      * RSS value to the average. Note that a message can be composed of multiple 802.15.4 data frame fragments each
1299      * received with a different signal strength.
1300      *
1301      * @param[in] aRss A new RSS value (in dBm) to be added to average.
1302      */
AddRss(int8_t aRss)1303     void AddRss(int8_t aRss) { IgnoreError(GetMetadata().mRssAverager.Add(aRss)); }
1304 
1305     /**
1306      * Returns the average RSS (Received Signal Strength) associated with the message.
1307      *
1308      * @returns The current average RSS value (in dBm) or `Radio::kInvalidRssi` if no average is available.
1309      */
GetAverageRss(void) const1310     int8_t GetAverageRss(void) const { return GetMetadata().mRssAverager.GetAverage(); }
1311 
1312     /**
1313      * Returns a const reference to RssAverager of the message.
1314      *
1315      * @returns A const reference to the RssAverager of the message.
1316      */
GetRssAverager(void) const1317     const RssAverager &GetRssAverager(void) const { return GetMetadata().mRssAverager; }
1318 
1319     /**
1320      * Updates the average LQI (Link Quality Indicator) associated with the message.
1321      *
1322      * The given LQI value would be added to the average. Note that a message can be composed of multiple 802.15.4
1323      * frame fragments each received with a different signal strength.
1324      *
1325      * @param[in] aLqi A new LQI value (has no unit) to be added to average.
1326      */
AddLqi(uint8_t aLqi)1327     void AddLqi(uint8_t aLqi) { GetMetadata().mLqiAverager.Add(aLqi); }
1328 
1329     /**
1330      * Returns the average LQI (Link Quality Indicator) associated with the message.
1331      *
1332      * @returns The current average LQI value (in dBm) or OT_RADIO_LQI_NONE if no average is available.
1333      */
GetAverageLqi(void) const1334     uint8_t GetAverageLqi(void) const { return GetMetadata().mLqiAverager.GetAverage(); }
1335 
1336     /**
1337      * Returns the count of frames counted so far.
1338      *
1339      * @returns The count of frames that have been counted.
1340      */
GetPsduCount(void) const1341     uint8_t GetPsduCount(void) const { return GetMetadata().mLqiAverager.GetCount(); }
1342 
1343     /**
1344      * Returns a const reference to LqiAverager of the message.
1345      *
1346      * @returns A const reference to the LqiAverager of the message.
1347      */
GetLqiAverager(void) const1348     const LqiAverager &GetLqiAverager(void) const { return GetMetadata().mLqiAverager; }
1349 
1350     /**
1351      * Retrieves `ThreadLinkInfo` from the message if received over Thread radio with origin `kOriginThreadNetif`.
1352      *
1353      * @pram[out] aLinkInfo     A reference to a `ThreadLinkInfo` to populate.
1354      *
1355      * @retval kErrorNone       Successfully retrieved the link info, @p `aLinkInfo` is updated.
1356      * @retval kErrorNotFound   Message origin is not `kOriginThreadNetif`.
1357      */
1358     Error GetLinkInfo(ThreadLinkInfo &aLinkInfo) const;
1359 
1360     /**
1361      * Sets the message's link info properties (PAN ID, link security, RSS) from a given `ThreadLinkInfo`.
1362      *
1363      * @param[in] aLinkInfo   The `ThreadLinkInfo` instance from which to set message's related properties.
1364      */
1365     void UpdateLinkInfoFrom(const ThreadLinkInfo &aLinkInfo);
1366 
1367     /**
1368      * Returns a pointer to the message queue (if any) where this message is queued.
1369      *
1370      * @returns A pointer to the message queue or `nullptr` if not in any message queue.
1371      */
GetMessageQueue(void) const1372     MessageQueue *GetMessageQueue(void) const
1373     {
1374         return !GetMetadata().mInPriorityQ ? static_cast<MessageQueue *>(GetMetadata().mQueue) : nullptr;
1375     }
1376 
1377     /**
1378      * Returns a pointer to the priority message queue (if any) where this message is queued.
1379      *
1380      * @returns A pointer to the priority queue or `nullptr` if not in any priority queue.
1381      */
GetPriorityQueue(void) const1382     PriorityQueue *GetPriorityQueue(void) const
1383     {
1384         return GetMetadata().mInPriorityQ ? static_cast<PriorityQueue *>(GetMetadata().mQueue) : nullptr;
1385     }
1386 
1387     /**
1388      * Indicates whether or not the message is also used for time sync purpose.
1389      *
1390      * When OPENTHREAD_CONFIG_TIME_SYNC_ENABLE is 0, this method always return false.
1391      *
1392      * @retval TRUE   If the message is also used for time sync purpose.
1393      * @retval FALSE  If the message is not used for time sync purpose.
1394      */
1395     bool IsTimeSync(void) const;
1396 
1397 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1398     /**
1399      * Sets whether or not the message is also used for time sync purpose.
1400      *
1401      * @param[in]  aEnabled  TRUE if the message is also used for time sync purpose, FALSE otherwise.
1402      */
SetTimeSync(bool aEnabled)1403     void SetTimeSync(bool aEnabled) { GetMetadata().mTimeSync = aEnabled; }
1404 
1405     /**
1406      * Sets the offset to network time.
1407      *
1408      * @param[in]  aNetworkTimeOffset  The offset to network time.
1409      */
SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1410     void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) { GetMetadata().mNetworkTimeOffset = aNetworkTimeOffset; }
1411 
1412     /**
1413      * Gets the offset to network time.
1414      *
1415      * @returns  The offset to network time.
1416      */
GetNetworkTimeOffset(void) const1417     int64_t GetNetworkTimeOffset(void) const { return GetMetadata().mNetworkTimeOffset; }
1418 
1419     /**
1420      * Sets the time sync sequence.
1421      *
1422      * @param[in]  aTimeSyncSeq  The time sync sequence.
1423      */
SetTimeSyncSeq(uint8_t aTimeSyncSeq)1424     void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { GetMetadata().mTimeSyncSeq = aTimeSyncSeq; }
1425 
1426     /**
1427      * Gets the time sync sequence.
1428      *
1429      * @returns  The time sync sequence.
1430      */
GetTimeSyncSeq(void) const1431     uint8_t GetTimeSyncSeq(void) const { return GetMetadata().mTimeSyncSeq; }
1432 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1433 
1434 #if OPENTHREAD_CONFIG_MULTI_RADIO
1435     /**
1436      * Indicates whether the radio type is set.
1437      *
1438      * @retval TRUE   If the radio type is set.
1439      * @retval FALSE  If the radio type is not set.
1440      */
IsRadioTypeSet(void) const1441     bool IsRadioTypeSet(void) const { return GetMetadata().mIsRadioTypeSet; }
1442 
1443     /**
1444      * Gets the radio link type the message was received on, or should be sent on.
1445      *
1446      * Should be used only when `IsRadioTypeSet()` returns `true`.
1447      *
1448      * @returns The radio link type of the message.
1449      */
GetRadioType(void) const1450     Mac::RadioType GetRadioType(void) const { return static_cast<Mac::RadioType>(GetMetadata().mRadioType); }
1451 
1452     /**
1453      * Sets the radio link type the message was received on, or should be sent on.
1454      *
1455      * @param[in] aRadioType   A radio link type of the message.
1456      */
SetRadioType(Mac::RadioType aRadioType)1457     void SetRadioType(Mac::RadioType aRadioType)
1458     {
1459         GetMetadata().mIsRadioTypeSet = true;
1460         GetMetadata().mRadioType      = aRadioType;
1461     }
1462 
1463     /**
1464      * Clears any previously set radio type on the message.
1465      *
1466      * After calling this method, `IsRadioTypeSet()` returns false until radio type is set (`SetRadioType()`).
1467      */
ClearRadioType(void)1468     void ClearRadioType(void) { GetMetadata().mIsRadioTypeSet = false; }
1469 
1470 #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
1471 
1472 protected:
1473     class ConstIterator : public ItemPtrIterator<const Message, ConstIterator>
1474     {
1475         friend class ItemPtrIterator<const Message, ConstIterator>;
1476 
1477     public:
1478         ConstIterator(void) = default;
1479 
ConstIterator(const Message * aMessage)1480         explicit ConstIterator(const Message *aMessage)
1481             : ItemPtrIterator(aMessage)
1482         {
1483         }
1484 
1485     private:
Advance(void)1486         void Advance(void) { mItem = mItem->GetNext(); }
1487     };
1488 
1489     class Iterator : public ItemPtrIterator<Message, Iterator>
1490     {
1491         friend class ItemPtrIterator<Message, Iterator>;
1492 
1493     public:
Iterator(void)1494         Iterator(void)
1495             : mNext(nullptr)
1496         {
1497         }
1498 
Iterator(Message * aMessage)1499         explicit Iterator(Message *aMessage)
1500             : ItemPtrIterator(aMessage)
1501             , mNext(NextMessage(aMessage))
1502         {
1503         }
1504 
1505     private:
1506         void            Advance(void);
NextMessage(Message * aMessage)1507         static Message *NextMessage(Message *aMessage) { return (aMessage != nullptr) ? aMessage->GetNext() : nullptr; }
1508 
1509         Message *mNext;
1510     };
1511 
GetReserved(void) const1512     uint16_t GetReserved(void) const { return GetMetadata().mReserved; }
SetReserved(uint16_t aReservedHeader)1513     void     SetReserved(uint16_t aReservedHeader) { GetMetadata().mReserved = aReservedHeader; }
1514 
1515 private:
1516     class Chunk : public Data<kWithUint16Length>
1517     {
1518     public:
GetBuffer(void) const1519         const Buffer *GetBuffer(void) const { return mBuffer; }
SetBuffer(const Buffer * aBuffer)1520         void          SetBuffer(const Buffer *aBuffer) { mBuffer = aBuffer; }
1521 
1522     private:
1523         const Buffer *mBuffer; // Buffer containing the chunk
1524     };
1525 
1526     class MutableChunk : public Chunk
1527     {
1528     public:
GetBytes(void)1529         uint8_t *GetBytes(void) { return AsNonConst(Chunk::GetBytes()); }
1530     };
1531 
1532     void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, Chunk &aChunk) const;
1533     void GetNextChunk(uint16_t &aLength, Chunk &aChunk) const;
1534 
GetFirstChunk(uint16_t aOffset,uint16_t & aLength,MutableChunk & aChunk)1535     void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, MutableChunk &aChunk)
1536     {
1537         AsConst(this)->GetFirstChunk(aOffset, aLength, static_cast<Chunk &>(aChunk));
1538     }
1539 
GetNextChunk(uint16_t & aLength,MutableChunk & aChunk)1540     void GetNextChunk(uint16_t &aLength, MutableChunk &aChunk)
1541     {
1542         AsConst(this)->GetNextChunk(aLength, static_cast<Chunk &>(aChunk));
1543     }
1544 
GetMessagePool(void) const1545     MessagePool *GetMessagePool(void) const { return GetMetadata().mMessagePool; }
SetMessagePool(MessagePool * aMessagePool)1546     void         SetMessagePool(MessagePool *aMessagePool) { GetMetadata().mMessagePool = aMessagePool; }
1547 
IsInAQueue(void) const1548     bool IsInAQueue(void) const { return (GetMetadata().mQueue != nullptr); }
1549     void SetMessageQueue(MessageQueue *aMessageQueue);
1550     void SetPriorityQueue(PriorityQueue *aPriorityQueue);
1551 
SetRssAverager(const RssAverager & aRssAverager)1552     void SetRssAverager(const RssAverager &aRssAverager) { GetMetadata().mRssAverager = aRssAverager; }
SetLqiAverager(const LqiAverager & aLqiAverager)1553     void SetLqiAverager(const LqiAverager &aLqiAverager) { GetMetadata().mLqiAverager = aLqiAverager; }
1554 
Next(void)1555     Message       *&Next(void) { return GetMetadata().mNext; }
Next(void) const1556     Message *const &Next(void) const { return GetMetadata().mNext; }
Prev(void)1557     Message       *&Prev(void) { return GetMetadata().mPrev; }
1558 
NextOf(Message * aMessage)1559     static Message       *NextOf(Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; }
NextOf(const Message * aMessage)1560     static const Message *NextOf(const Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; }
1561 
1562     Error ResizeMessage(uint16_t aLength);
1563 };
1564 
1565 /**
1566  * Implements a message queue.
1567  */
1568 class MessageQueue : public otMessageQueue
1569 {
1570     friend class Message;
1571     friend class PriorityQueue;
1572 
1573 public:
1574     typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue.
1575 
1576     /**
1577      * Represents a position (head or tail) in the queue. This is used to specify where a new message
1578      * should be added in the queue.
1579      */
1580     enum QueuePosition : uint8_t
1581     {
1582         kQueuePositionHead, ///< Indicates the head (front) of the list.
1583         kQueuePositionTail, ///< Indicates the tail (end) of the list.
1584     };
1585 
1586     /**
1587      * Initializes the message queue.
1588      */
MessageQueue(void)1589     MessageQueue(void) { SetTail(nullptr); }
1590 
1591     /**
1592      * Returns a pointer to the first message.
1593      *
1594      * @returns A pointer to the first message.
1595      */
GetHead(void)1596     Message *GetHead(void) { return Message::NextOf(GetTail()); }
1597 
1598     /**
1599      * Returns a pointer to the first message.
1600      *
1601      * @returns A pointer to the first message.
1602      */
GetHead(void) const1603     const Message *GetHead(void) const { return Message::NextOf(GetTail()); }
1604 
1605     /**
1606      * Adds a message to the end of the list.
1607      *
1608      * @param[in]  aMessage  The message to add.
1609      */
Enqueue(Message & aMessage)1610     void Enqueue(Message &aMessage) { Enqueue(aMessage, kQueuePositionTail); }
1611 
1612     /**
1613      * Adds a message at a given position (head/tail) of the list.
1614      *
1615      * @param[in]  aMessage  The message to add.
1616      * @param[in]  aPosition The position (head or tail) where to add the message.
1617      */
1618     void Enqueue(Message &aMessage, QueuePosition aPosition);
1619 
1620     /**
1621      * Removes a message from the list.
1622      *
1623      * @param[in]  aMessage  The message to remove.
1624      */
1625     void Dequeue(Message &aMessage);
1626 
1627     /**
1628      * Removes a message from the queue and frees it.
1629      *
1630      * @param[in]  aMessage  The message to remove and free.
1631      */
1632     void DequeueAndFree(Message &aMessage);
1633 
1634     /**
1635      * Removes and frees all messages from the queue.
1636      */
1637     void DequeueAndFreeAll(void);
1638 
1639     /**
1640      * Gets the information about number of messages and buffers in the queue.
1641      *
1642      * Updates `aInfo` and adds number of message/buffers in the message queue to the corresponding member
1643      * variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method (e.g.,
1644      * clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues to add
1645      * up the number of messages/buffers on different queues.
1646      *
1647      * @param[out] aInfo  A reference to `Info` structure to update.ni
1648      */
1649     void GetInfo(Info &aInfo) const;
1650 
1651     // The following methods are intended to support range-based `for`
1652     // loop iteration over the queue entries and should not be used
1653     // directly. The range-based `for` works correctly even if the
1654     // current entry is removed from the queue during iteration.
1655 
1656     Message::Iterator begin(void);
end(void)1657     Message::Iterator end(void) { return Message::Iterator(); }
1658 
1659     Message::ConstIterator begin(void) const;
end(void) const1660     Message::ConstIterator end(void) const { return Message::ConstIterator(); }
1661 
1662 private:
GetTail(void)1663     Message       *GetTail(void) { return static_cast<Message *>(mData); }
GetTail(void) const1664     const Message *GetTail(void) const { return static_cast<const Message *>(mData); }
SetTail(Message * aMessage)1665     void           SetTail(Message *aMessage) { mData = aMessage; }
1666 };
1667 
1668 /**
1669  * Implements a priority queue.
1670  */
1671 class PriorityQueue : private Clearable<PriorityQueue>
1672 {
1673     friend class Message;
1674     friend class MessageQueue;
1675     friend class MessagePool;
1676     friend class Clearable<PriorityQueue>;
1677 
1678 public:
1679     typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue.
1680 
1681     /**
1682      * Initializes the priority queue.
1683      */
PriorityQueue(void)1684     PriorityQueue(void) { Clear(); }
1685 
1686     /**
1687      * Returns a pointer to the first message.
1688      *
1689      * @returns A pointer to the first message.
1690      */
GetHead(void)1691     Message *GetHead(void) { return AsNonConst(AsConst(this)->GetHead()); }
1692 
1693     /**
1694      * Returns a pointer to the first message.
1695      *
1696      * @returns A pointer to the first message.
1697      */
1698     const Message *GetHead(void) const;
1699 
1700     /**
1701      * Returns a pointer to the first message for a given priority level.
1702      *
1703      * @param[in] aPriority   Priority level.
1704      *
1705      * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with
1706      *          this priority level.
1707      */
GetHeadForPriority(Message::Priority aPriority)1708     Message *GetHeadForPriority(Message::Priority aPriority)
1709     {
1710         return AsNonConst(AsConst(this)->GetHeadForPriority(aPriority));
1711     }
1712 
1713     /**
1714      * Returns a pointer to the first message for a given priority level.
1715      *
1716      * @param[in] aPriority   Priority level.
1717      *
1718      * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with
1719      *          this priority level.
1720      */
1721     const Message *GetHeadForPriority(Message::Priority aPriority) const;
1722 
1723     /**
1724      * Adds a message to the queue.
1725      *
1726      * @param[in]  aMessage  The message to add.
1727      */
1728     void Enqueue(Message &aMessage);
1729 
1730     /**
1731      * Removes a message from the list.
1732      *
1733      * @param[in]  aMessage  The message to remove.
1734      */
1735     void Dequeue(Message &aMessage);
1736 
1737     /**
1738      * Removes a message from the queue and frees it.
1739      *
1740      * @param[in]  aMessage  The message to remove and free.
1741      */
1742     void DequeueAndFree(Message &aMessage);
1743 
1744     /**
1745      * Removes and frees all messages from the queue.
1746      */
1747     void DequeueAndFreeAll(void);
1748 
1749     /**
1750      * Returns the tail of the list (last message in the list).
1751      *
1752      * @returns A pointer to the tail of the list.
1753      */
GetTail(void)1754     Message *GetTail(void) { return AsNonConst(AsConst(this)->GetTail()); }
1755 
1756     /**
1757      * Returns the tail of the list (last message in the list).
1758      *
1759      * @returns A pointer to the tail of the list.
1760      */
1761     const Message *GetTail(void) const;
1762 
1763     /**
1764      * Gets the information about number of messages and buffers in the priority queue.
1765      *
1766      * Updates `aInfo` array and adds number of message/buffers in the message queue to the corresponding
1767      * member variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method
1768      * (e.g., clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues
1769      * to add up the number of messages/buffers on different queues.
1770      *
1771      * @param[out] aInfo  A reference to an `Info` structure to update.
1772      */
1773     void GetInfo(Info &aInfo) const;
1774 
1775     // The following methods are intended to support range-based `for`
1776     // loop iteration over the queue entries and should not be used
1777     // directly. The range-based `for` works correctly even if the
1778     // current entry is removed from the queue during iteration.
1779 
1780     Message::Iterator begin(void);
end(void)1781     Message::Iterator end(void) { return Message::Iterator(); }
1782 
1783     Message::ConstIterator begin(void) const;
end(void) const1784     Message::ConstIterator end(void) const { return Message::ConstIterator(); }
1785 
1786 private:
PrevPriority(uint8_t aPriority) const1787     uint8_t PrevPriority(uint8_t aPriority) const
1788     {
1789         return (aPriority == Message::kNumPriorities - 1) ? 0 : (aPriority + 1);
1790     }
1791 
1792     const Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const;
1793 
FindFirstNonNullTail(Message::Priority aStartPriorityLevel)1794     Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel)
1795     {
1796         return AsNonConst(AsConst(this)->FindFirstNonNullTail(aStartPriorityLevel));
1797     }
1798 
1799     Message *mTails[Message::kNumPriorities]; // Tail pointers associated with different priority levels.
1800 };
1801 
1802 /**
1803  * Represents a message pool
1804  */
1805 class MessagePool : public InstanceLocator, private NonCopyable
1806 {
1807     friend class Message;
1808     friend class MessageQueue;
1809     friend class PriorityQueue;
1810 
1811 public:
1812     /**
1813      * Initializes the object.
1814      */
1815     explicit MessagePool(Instance &aInstance);
1816 
1817     /**
1818      * Allocates a new message with specified settings.
1819      *
1820      * @param[in]  aType           The message type.
1821      * @param[in]  aReserveHeader  The number of header bytes to reserve.
1822      * @param[in]  aSettings       The message settings.
1823      *
1824      * @returns A pointer to the message or `nullptr` if no message buffers are available.
1825      */
1826     Message *Allocate(Message::Type aType, uint16_t aReserveHeader, const Message::Settings &aSettings);
1827 
1828     /**
1829      * Allocates a new message of a given type using default settings.
1830      *
1831      * @param[in]  aType           The message type.
1832      *
1833      * @returns A pointer to the message or `nullptr` if no message buffers are available.
1834      */
1835     Message *Allocate(Message::Type aType);
1836 
1837     /**
1838      * Allocates a new message with a given type and reserved length using default settings.
1839      *
1840      * @param[in]  aType           The message type.
1841      * @param[in]  aReserveHeader  The number of header bytes to reserve.
1842      *
1843      * @returns A pointer to the message or `nullptr` if no message buffers are available.
1844      */
1845     Message *Allocate(Message::Type aType, uint16_t aReserveHeader);
1846 
1847     /**
1848      * Is used to free a message and return all message buffers to the buffer pool.
1849      *
1850      * @param[in]  aMessage  The message to free.
1851      */
1852     void Free(Message *aMessage);
1853 
1854     /**
1855      * Returns the number of free buffers.
1856      *
1857      * @returns The number of free buffers, or 0xffff (UINT16_MAX) if number is unknown.
1858      */
1859     uint16_t GetFreeBufferCount(void) const;
1860 
1861     /**
1862      * Returns the total number of buffers.
1863      *
1864      * @returns The total number of buffers, or 0xffff (UINT16_MAX) if number is unknown.
1865      */
1866     uint16_t GetTotalBufferCount(void) const;
1867 
1868     /**
1869      * Returns the maximum number of buffers in use at the same time since OT stack initialization or
1870      * since last call to `ResetMaxUsedBufferCount()`.
1871      *
1872      * @returns The maximum number of buffers in use at the same time so far (buffer allocation watermark).
1873      */
GetMaxUsedBufferCount(void) const1874     uint16_t GetMaxUsedBufferCount(void) const { return mMaxAllocated; }
1875 
1876     /**
1877      * Resets the tracked maximum number of buffers in use.
1878      *
1879      * @sa GetMaxUsedBufferCount
1880      */
ResetMaxUsedBufferCount(void)1881     void ResetMaxUsedBufferCount(void) { mMaxAllocated = mNumAllocated; }
1882 
1883 private:
1884     Buffer *NewBuffer(Message::Priority aPriority);
1885     void    FreeBuffers(Buffer *aBuffer);
1886     Error   ReclaimBuffers(Message::Priority aPriority);
1887 
1888 #if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
1889     Pool<Buffer, kNumBuffers> mBufferPool;
1890 #endif
1891     uint16_t mNumAllocated;
1892     uint16_t mMaxAllocated;
1893 };
1894 
GetInstance(void) const1895 inline Instance &Message::GetInstance(void) const { return GetMessagePool()->GetInstance(); }
1896 
1897 /**
1898  * @}
1899  */
1900 
1901 DefineCoreType(otMessageBuffer, Buffer);
1902 DefineCoreType(otMessageSettings, Message::Settings);
1903 DefineCoreType(otMessage, Message);
1904 DefineCoreType(otMessageQueue, MessageQueue);
1905 
1906 DefineMapEnum(otMessageOrigin, Message::Origin);
1907 
1908 } // namespace ot
1909 
1910 #endif // MESSAGE_HPP_
1911