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