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