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