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/platform/messagepool.h>
43 
44 #include "common/code_utils.hpp"
45 #include "common/encoding.hpp"
46 #include "common/linked_list.hpp"
47 #include "common/locator.hpp"
48 #include "common/non_copyable.hpp"
49 #include "common/pool.hpp"
50 #include "common/type_traits.hpp"
51 #include "mac/mac_types.hpp"
52 #include "thread/child_mask.hpp"
53 #include "thread/link_quality.hpp"
54 
55 /**
56  * This struct represents an opaque (and empty) type for an OpenThread message buffer.
57  *
58  */
59 struct otMessage
60 {
61 };
62 
63 namespace ot {
64 
65 namespace Crypto {
66 
67 class Sha256;
68 class HmacSha256;
69 
70 } // namespace Crypto
71 
72 /**
73  * @addtogroup core-message
74  *
75  * @brief
76  *   This module includes definitions for the message buffer pool and message buffers.
77  *
78  * @{
79  *
80  */
81 
82 /**
83  * This macro frees a given message buffer if not nullptr.
84  *
85  * This macro and the ones that follow contain small but common code patterns used in many of the core modules. They
86  * are intentionally defined as macros instead of inline methods/functions to ensure that they are fully inlined.
87  * Note that an `inline` method/function is not necessarily always inlined by the toolchain and not inlining such
88  * small implementations can add a rather large code-size overhead.
89  *
90  * @param[in] aMessage    A pointer to a `Message` to free (can be nullptr).
91  *
92  */
93 #define FreeMessage(aMessage)      \
94     do                             \
95     {                              \
96         if ((aMessage) != nullptr) \
97         {                          \
98             (aMessage)->Free();    \
99         }                          \
100     } while (false)
101 
102 /**
103  * This macro frees a given message buffer if a given `Error` indicates an error.
104  *
105  * The parameter @p aMessage can be nullptr in which case this macro does nothing.
106  *
107  * @param[in] aMessage    A pointer to a `Message` to free (can be nullptr).
108  * @param[in] aError      The `Error` to check.
109  *
110  */
111 #define FreeMessageOnError(aMessage, aError)                     \
112     do                                                           \
113     {                                                            \
114         if (((aError) != kErrorNone) && ((aMessage) != nullptr)) \
115         {                                                        \
116             (aMessage)->Free();                                  \
117         }                                                        \
118     } while (false)
119 
120 /**
121  * This macro frees a given message buffer if a given `Error` indicates an error and sets the `aMessage` to `nullptr`.
122  *
123  * @param[in] aMessage    A pointer to a `Message` to free (can be nullptr).
124  * @param[in] aError      The `Error` to check.
125  *
126  */
127 #define FreeAndNullMessageOnError(aMessage, aError)              \
128     do                                                           \
129     {                                                            \
130         if (((aError) != kErrorNone) && ((aMessage) != nullptr)) \
131         {                                                        \
132             (aMessage)->Free();                                  \
133             (aMessage) = nullptr;                                \
134         }                                                        \
135     } while (false)
136 
137 constexpr uint16_t kNumBuffers = OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS;
138 constexpr uint16_t kBufferSize = OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE;
139 
140 class Message;
141 class MessagePool;
142 class MessageQueue;
143 class PriorityQueue;
144 class ThreadLinkInfo;
145 
146 /**
147  * This structure contains metadata about a Message.
148  *
149  */
150 struct MessageMetadata
151 {
152     Message *    mNext;        ///< A pointer to the next Message in a doubly linked list.
153     Message *    mPrev;        ///< A pointer to the previous Message in a doubly linked list.
154     MessagePool *mMessagePool; ///< Identifies the message pool for this message.
155     union
156     {
157         MessageQueue * mMessage;  ///< Identifies the message queue (if any) where this message is queued.
158         PriorityQueue *mPriority; ///< Identifies the priority queue (if any) where this message is queued.
159     } mQueue;                     ///< Identifies the queue (if any) where this message is queued.
160 
161     uint32_t mDatagramTag;    ///< The datagram tag used for 6LoWPAN fragmentation or identification used for IPv6
162                               ///< fragmentation.
163     uint16_t    mReserved;    ///< Number of header bytes reserved for the message.
164     uint16_t    mLength;      ///< Number of bytes within the message.
165     uint16_t    mOffset;      ///< A byte offset within the message.
166     RssAverager mRssAverager; ///< The averager maintaining the received signal strength (RSS) average.
167 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
168     LqiAverager mLqiAverager; ///< The averager maintaining the Link quality indicator (LQI) average.
169 #endif
170 
171     ChildMask mChildMask; ///< A ChildMask to indicate which sleepy children need to receive this.
172     uint16_t  mMeshDest;  ///< Used for unicast non-link-local messages.
173     uint8_t   mTimeout;   ///< Seconds remaining before dropping the message.
174     union
175     {
176         uint16_t mPanId;   ///< Used for MLE Discover Request and Response messages.
177         uint8_t  mChannel; ///< Used for MLE Announce.
178     } mPanIdChannel;       ///< Used for MLE Discover Request, Response, and Announce messages.
179 
180     uint8_t mType : 3;          ///< Identifies the type of message.
181     uint8_t mSubType : 4;       ///< Identifies the message sub type.
182     bool    mDirectTx : 1;      ///< Used to indicate whether a direct transmission is required.
183     bool    mLinkSecurity : 1;  ///< Indicates whether or not link security is enabled.
184     uint8_t mPriority : 2;      ///< Identifies the message priority level (higher value is higher priority).
185     bool    mInPriorityQ : 1;   ///< Indicates whether the message is queued in normal or priority queue.
186     bool    mTxSuccess : 1;     ///< Indicates whether the direct tx of the message was successful.
187     bool    mDoNotEvict : 1;    ///< Indicates whether or not this message may be evicted.
188     bool    mMulticastLoop : 1; ///< Indicates whether or not this multicast message may be looped back.
189 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
190     bool    mTimeSync : 1;      ///< Indicates whether the message is also used for time sync purpose.
191     int64_t mNetworkTimeOffset; ///< The time offset to the Thread network time, in microseconds.
192     uint8_t mTimeSyncSeq;       ///< The time sync sequence.
193 #endif
194 #if OPENTHREAD_CONFIG_MULTI_RADIO
195     uint8_t mRadioType : 2;      ///< The radio link type the message was received on, or should be sent on.
196     bool    mIsRadioTypeSet : 1; ///< Indicates whether the radio type is set.
197 
198     static_assert(Mac::kNumRadioTypes <= (1 << 2), "mRadioType bitfield cannot store all radio type values");
199 #endif
200 };
201 
202 /**
203  * This class represents a Message buffer.
204  *
205  */
206 class Buffer : public otMessageBuffer, public LinkedListEntry<Buffer>
207 {
208     friend class Message;
209     friend class LinkedListEntry<Buffer>;
210 
211 public:
212     /**
213      * This method returns a pointer to the next message buffer.
214      *
215      * @returns A pointer to the next message buffer.
216      *
217      */
GetNextBuffer(void)218     Buffer *GetNextBuffer(void) { return GetNext(); }
219 
220     /**
221      * This method returns a pointer to the next message buffer.
222      *
223      * @returns A pointer to the next message buffer.
224      *
225      */
GetNextBuffer(void) const226     const Buffer *GetNextBuffer(void) const { return GetNext(); }
227 
228     /**
229      * This method sets the pointer to the next message buffer.
230      *
231      * @param[in] aNext  A pointer to the next buffer.
232      *
233      */
SetNextBuffer(Buffer * aNext)234     void SetNextBuffer(Buffer *aNext) { SetNext(aNext); }
235 
236 private:
237     /**
238      * This method returns the message metadata in the first message buffer.
239      *
240      * @returns The message metadata structure.
241      *
242      */
GetMetadata(void)243     MessageMetadata &GetMetadata(void) { return mBuffer.mHead.mMetadata; }
244 
245     /**
246      * This method returns the message metadata in the first message buffer.
247      *
248      * @returns The message metadata structure.
249      *
250      */
GetMetadata(void) const251     const MessageMetadata &GetMetadata(void) const { return mBuffer.mHead.mMetadata; }
252 
253     /**
254      * This method returns a pointer to the first byte of data in the first message buffer.
255      *
256      * @returns A pointer to the first data byte.
257      *
258      */
GetFirstData(void)259     uint8_t *GetFirstData(void) { return mBuffer.mHead.mData; }
260 
261     /**
262      * This method returns a pointer to the first byte of data in the first message buffer.
263      *
264      * @returns A pointer to the first data byte.
265      *
266      */
GetFirstData(void) const267     const uint8_t *GetFirstData(void) const { return mBuffer.mHead.mData; }
268 
269     /**
270      * This method returns a pointer to the first data byte of a subsequent message buffer.
271      *
272      * @returns A pointer to the first data byte.
273      *
274      */
GetData(void)275     uint8_t *GetData(void) { return mBuffer.mData; }
276 
277     /**
278      * This method returns a pointer to the first data byte of a subsequent message buffer.
279      *
280      * @returns A pointer to the first data byte.
281      *
282      */
GetData(void) const283     const uint8_t *GetData(void) const { return mBuffer.mData; }
284 
285     static constexpr uint16_t kBufferDataSize     = kBufferSize - sizeof(otMessageBuffer);
286     static constexpr uint16_t kHeadBufferDataSize = kBufferDataSize - sizeof(MessageMetadata);
287 
288 protected:
289     union
290     {
291         struct
292         {
293             MessageMetadata mMetadata;
294             uint8_t         mData[kHeadBufferDataSize];
295         } mHead;
296         uint8_t mData[kBufferDataSize];
297     } mBuffer;
298 };
299 
300 /**
301  * This class represents a message.
302  *
303  */
304 class Message : public otMessage, public Buffer
305 {
306     friend class Checksum;
307     friend class Crypto::HmacSha256;
308     friend class Crypto::Sha256;
309     friend class MessagePool;
310     friend class MessageQueue;
311     friend class PriorityQueue;
312 
313 public:
314     /**
315      * This enumeration represents the message type.
316      *
317      */
318     enum Type : uint8_t
319     {
320         kTypeIp6          = 0, ///< A full uncompressed IPv6 packet
321         kType6lowpan      = 1, ///< A 6lowpan frame
322         kTypeSupervision  = 2, ///< A child supervision frame.
323         kTypeMacEmptyData = 3, ///< An empty MAC data frame.
324         kTypeOther        = 4, ///< Other (data) message.
325     };
326 
327     /**
328      * This enumeration represents the message sub-type.
329      *
330      */
331     enum SubType : uint8_t
332     {
333         kSubTypeNone                   = 0,  ///< None
334         kSubTypeMleAnnounce            = 1,  ///< MLE Announce
335         kSubTypeMleDiscoverRequest     = 2,  ///< MLE Discover Request
336         kSubTypeMleDiscoverResponse    = 3,  ///< MLE Discover Response
337         kSubTypeJoinerEntrust          = 4,  ///< Joiner Entrust
338         kSubTypeMplRetransmission      = 5,  ///< MPL next retransmission message
339         kSubTypeMleGeneral             = 6,  ///< General MLE
340         kSubTypeJoinerFinalizeResponse = 7,  ///< Joiner Finalize Response
341         kSubTypeMleChildUpdateRequest  = 8,  ///< MLE Child Update Request
342         kSubTypeMleDataResponse        = 9,  ///< MLE Data Response
343         kSubTypeMleChildIdRequest      = 10, ///< MLE Child ID Request
344     };
345 
346     enum Priority : uint8_t
347     {
348         kPriorityLow    = OT_MESSAGE_PRIORITY_LOW,      ///< Low priority level.
349         kPriorityNormal = OT_MESSAGE_PRIORITY_NORMAL,   ///< Normal priority level.
350         kPriorityHigh   = OT_MESSAGE_PRIORITY_HIGH,     ///< High priority level.
351         kPriorityNet    = OT_MESSAGE_PRIORITY_HIGH + 1, ///< Network Control priority level.
352     };
353 
354     static constexpr uint8_t kNumPriorities = 4; ///< Number of priority levels.
355 
356     /**
357      * This enumeration represents the link security mode (used by `Settings` constructor).
358      *
359      */
360     enum LinkSecurityMode : uint8_t
361     {
362         kNoLinkSecurity,   ///< Link security disabled (no link security).
363         kWithLinkSecurity, ///< Link security enabled.
364     };
365 
366     /**
367      * This enumeration represents the message ownership model when a `Message` instance is passed to a method/function.
368      *
369      */
370     enum Ownership : uint8_t
371     {
372         /**
373          * This value indicates that the method/function receiving a `Message` instance should take custody of the
374          * message (e.g., the method should `Free()` the message if no longer needed).
375          *
376          */
377         kTakeCustody,
378 
379         /**
380          * This value indicates that the method/function receiving a `Message` instance does not own the message (e.g.,
381          * it should not `Free()` or `Enqueue()` it in a queue). The receiving method/function should create a
382          * copy/clone of the message to keep (if/when needed).
383          *
384          */
385         kCopyToUse,
386     };
387 
388     /**
389      * This class represents settings used for creating a new message.
390      *
391      */
392     class Settings
393     {
394     public:
395         /**
396          * This constructor initializes the Settings object.
397          *
398          * @param[in]  aSecurityMode  A link security mode.
399          * @param[in]  aPriority      A message priority.
400          *
401          */
402         Settings(LinkSecurityMode aSecurityMode, Priority aPriority);
403 
404         /**
405          * This constructor initializes the `Settings` object from a given `otMessageSettings`.
406          *
407          * @param[in] aSettings  A pointer to `otMessageSettings` to covert from. If nullptr default settings (link
408          *                       security enabled with `kPriorityNormal` priority) would be used.
409          *
410          */
411         explicit Settings(const otMessageSettings *aSettings);
412 
413         /**
414          * This method gets the message priority.
415          *
416          * @returns The message priority.
417          *
418          */
GetPriority(void) const419         Priority GetPriority(void) const { return mPriority; }
420 
421         /**
422          * This method indicates whether the link security should be enabled.
423          *
424          * @returns TRUE if link security should be enabled, FALSE otherwise.
425          *
426          */
IsLinkSecurityEnabled(void) const427         bool IsLinkSecurityEnabled(void) const { return mLinkSecurityEnabled; }
428 
429         /**
430          * This static method returns the default settings with link security enabled and `kPriorityNormal` priority.
431          *
432          * @returns A reference to the default settings (link security enable and `kPriorityNormal` priority).
433          *
434          */
GetDefault(void)435         static const Settings &GetDefault(void) { return kDefault; }
436 
437     private:
438         static const Settings kDefault;
439 
440         bool     mLinkSecurityEnabled;
441         Priority mPriority;
442     };
443 
444     /**
445      * This method frees this message buffer.
446      *
447      */
448     void Free(void);
449 
450     /**
451      * This method returns a pointer to the next message.
452      *
453      * @returns A pointer to the next message in the list or nullptr if at the end of the list.
454      *
455      */
456     Message *GetNext(void) const;
457 
458     /**
459      * This method returns the number of bytes in the message.
460      *
461      * @returns The number of bytes in the message.
462      *
463      */
GetLength(void) const464     uint16_t GetLength(void) const { return GetMetadata().mLength; }
465 
466     /**
467      * This method sets the number of bytes in the message.
468      *
469      * @param[in]  aLength  Requested number of bytes in the message.
470      *
471      * @retval kErrorNone    Successfully set the length of the message.
472      * @retval kErrorNoBufs  Failed to grow the size of the message because insufficient buffers were available.
473      *
474      */
475     Error SetLength(uint16_t aLength);
476 
477     /**
478      * This method returns the number of buffers in the message.
479      *
480      */
481     uint8_t GetBufferCount(void) const;
482 
483     /**
484      * This method returns the byte offset within the message.
485      *
486      * @returns A byte offset within the message.
487      *
488      */
GetOffset(void) const489     uint16_t GetOffset(void) const { return GetMetadata().mOffset; }
490 
491     /**
492      * This method moves the byte offset within the message.
493      *
494      * @param[in]  aDelta  The number of bytes to move the current offset, which may be positive or negative.
495      *
496      */
497     void MoveOffset(int aDelta);
498 
499     /**
500      * This method sets the byte offset within the message.
501      *
502      * @param[in]  aOffset  The byte offset within the message.
503      *
504      */
505     void SetOffset(uint16_t aOffset);
506 
507     /**
508      * This method returns the type of the message.
509      *
510      * @returns The type of the message.
511      *
512      */
GetType(void) const513     Type GetType(void) const { return static_cast<Type>(GetMetadata().mType); }
514 
515     /**
516      * This method sets the message type.
517      *
518      * @param[in]  aType  The message type.
519      *
520      */
SetType(Type aType)521     void SetType(Type aType) { GetMetadata().mType = aType; }
522 
523     /**
524      * This method returns the sub type of the message.
525      *
526      * @returns The sub type of the message.
527      *
528      */
GetSubType(void) const529     SubType GetSubType(void) const { return static_cast<SubType>(GetMetadata().mSubType); }
530 
531     /**
532      * This method sets the message sub type.
533      *
534      * @param[in]  aSubType  The message sub type.
535      *
536      */
SetSubType(SubType aSubType)537     void SetSubType(SubType aSubType) { GetMetadata().mSubType = aSubType; }
538 
539     /**
540      * This method returns whether or not the message is of MLE subtype.
541      *
542      * @retval TRUE   If message is of MLE subtype.
543      * @retval FALSE  If message is not of MLE subtype.
544      *
545      */
546     bool IsSubTypeMle(void) const;
547 
548     /**
549      * This method checks whether this multicast message may be looped back.
550      *
551      * @retval TRUE   If message may be looped back.
552      * @retval FALSE  If message must not be looped back.
553      *
554      */
GetMulticastLoop(void) const555     bool GetMulticastLoop(void) const { return GetMetadata().mMulticastLoop; }
556 
557     /**
558      * This method sets whether multicast may be looped back.
559      *
560      * @param[in]  aMulticastLoop  Whether allow looping back multicast.
561      *
562      */
SetMulticastLoop(bool aMulticastLoop)563     void SetMulticastLoop(bool aMulticastLoop) { GetMetadata().mMulticastLoop = aMulticastLoop; }
564 
565     /**
566      * This method returns the message priority level.
567      *
568      * @returns The priority level associated with this message.
569      *
570      */
GetPriority(void) const571     Priority GetPriority(void) const { return static_cast<Priority>(GetMetadata().mPriority); }
572 
573     /**
574      * This method sets the messages priority.
575      * If the message is already queued in a priority queue, changing the priority ensures to
576      * update the message in the associated queue.
577      *
578      * @param[in]  aPriority  The message priority level.
579      *
580      * @retval kErrorNone          Successfully set the priority for the message.
581      * @retval kErrorInvalidArgs   Priority level is not invalid.
582      *
583      */
584     Error SetPriority(Priority aPriority);
585 
586     /**
587      * This static method convert a `Priority` to a string.
588      *
589      * @param[in] aPriority  The priority level.
590      *
591      * @returns A string representation of @p aPriority.
592      *
593      */
594     static const char *PriorityToString(Priority aPriority);
595 
596     /**
597      * This method prepends bytes to the front of the message.
598      *
599      * On success, this method grows the message by @p aLength bytes.
600      *
601      * @param[in]  aBuf     A pointer to a data buffer (can be `nullptr` to grow message without writing bytes).
602      * @param[in]  aLength  The number of bytes to prepend.
603      *
604      * @retval kErrorNone    Successfully prepended the bytes.
605      * @retval kErrorNoBufs  Not enough reserved bytes in the message.
606      *
607      */
608     Error PrependBytes(const void *aBuf, uint16_t aLength);
609 
610     /**
611      * This method prepends an object to the front of the message.
612      *
613      * On success, this method grows the message by the size of the object.
614      *
615      * @tparam    ObjectType   The object type to prepend to the message.
616      *
617      * @param[in] aObject      A reference to the object to prepend to the message.
618      *
619      * @retval kErrorNone    Successfully prepended the object.
620      * @retval kErrorNoBufs  Not enough reserved bytes in the message.
621      *
622      */
Prepend(const ObjectType & aObject)623     template <typename ObjectType> Error Prepend(const ObjectType &aObject)
624     {
625         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
626 
627         return PrependBytes(&aObject, sizeof(ObjectType));
628     }
629 
630     /**
631      * This method removes header bytes from the message.
632      *
633      * @param[in]  aLength  Number of header bytes to remove.
634      *
635      */
636     void RemoveHeader(uint16_t aLength);
637 
638     /**
639      * This method appends bytes to the end of the message.
640      *
641      * On success, this method grows the message by @p aLength bytes.
642      *
643      * @param[in]  aBuf     A pointer to a data buffer (MUST not be `nullptr`).
644      * @param[in]  aLength  The number of bytes to append.
645      *
646      * @retval kErrorNone    Successfully appended the bytes.
647      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
648      *
649      */
650     Error AppendBytes(const void *aBuf, uint16_t aLength);
651 
652     /**
653      * This method appends bytes read from another or potentially the same message to the end of the current message.
654      *
655      * On success, this method grows the message by @p aLength bytes.
656      *
657      * @param[in] aMessage   The message to read the bytes from (it can be the same as the current message).
658      * @param[in] aOffset    The offset in @p aMessage to start reading the bytes from.
659      * @param[in] aLength    The number of bytes to read from @p aMessage and append.
660      *
661      * @retval kErrorNone    Successfully appended the bytes.
662      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
663      * @retval kErrorParse   Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset.
664      *
665      */
666     Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
667 
668     /**
669      * This method appends an object to the end of the message.
670      *
671      * On success, this method grows the message by the size of the appended object
672      *
673      * @tparam    ObjectType   The object type to append to the message.
674      *
675      * @param[in] aObject      A reference to the object to append to the message.
676      *
677      * @retval kErrorNone    Successfully appended the object.
678      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
679      *
680      */
Append(const ObjectType & aObject)681     template <typename ObjectType> Error Append(const ObjectType &aObject)
682     {
683         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
684 
685         return AppendBytes(&aObject, sizeof(ObjectType));
686     }
687 
688     /**
689      * This method reads bytes from the message.
690      *
691      * @param[in]  aOffset  Byte offset within the message to begin reading.
692      * @param[out] aBuf     A pointer to a data buffer to copy the read bytes into.
693      * @param[in]  aLength  Number of bytes to read.
694      *
695      * @returns The number of bytes read.
696      *
697      */
698     uint16_t ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
699 
700     /**
701      * This method reads a given number of bytes from the message.
702      *
703      * If there are fewer bytes available in the message than the requested read length, the available bytes will be
704      * read and copied into @p aBuf. In this case `kErrorParse` will be returned.
705      *
706      * @param[in]  aOffset  Byte offset within the message to begin reading.
707      * @param[out] aBuf     A pointer to a data buffer to copy the read bytes into.
708      * @param[in]  aLength  Number of bytes to read.
709      *
710      * @retval kErrorNone     @p aLength bytes were successfully read from message.
711      * @retval kErrorParse    Not enough bytes remaining in message to read the entire object.
712      *
713      */
714     Error Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
715 
716     /**
717      * This method reads an object from the message.
718      *
719      * If there are fewer bytes available in the message than the requested object size, the available bytes will be
720      * read and copied into @p aObject (@p aObject will be read partially). In this case `kErrorParse` will
721      * be returned.
722      *
723      * @tparam     ObjectType   The object type to read from the message.
724      *
725      * @param[in]  aOffset      Byte offset within the message to begin reading.
726      * @param[out] aObject      A reference to the object to read into.
727      *
728      * @retval kErrorNone     Object @p aObject was successfully read from message.
729      * @retval kErrorParse    Not enough bytes remaining in message to read the entire object.
730      *
731      */
Read(uint16_t aOffset,ObjectType & aObject) const732     template <typename ObjectType> Error Read(uint16_t aOffset, ObjectType &aObject) const
733     {
734         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
735 
736         return Read(aOffset, &aObject, sizeof(ObjectType));
737     }
738 
739     /**
740      * This method compares the bytes in the message at a given offset with a given byte array.
741      *
742      * If there are fewer bytes available in the message than the requested @p aLength, the comparison is treated as
743      * failure (returns FALSE).
744      *
745      * @param[in]  aOffset    Byte offset within the message to read from for the comparison.
746      * @param[in]  aBuf       A pointer to a data buffer to compare with the bytes from message.
747      * @param[in]  aLength    Number of bytes in @p aBuf.
748      *
749      * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf,
750      *          FALSE otherwise.
751      *
752      */
753     bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength) const;
754 
755     /**
756      * This method compares the bytes in the message at a given offset with bytes read from another message.
757      *
758      * If either message has fewer bytes available than the requested @p aLength, the comparison is treated as failure
759      * (returns FALSE).
760      *
761      * @param[in]  aOffset        Byte offset within the message to read from for the comparison.
762      * @param[in]  aOtherMessage  The other message to compare with.
763      * @param[in]  aOtherOffset   Byte offset within @p aOtherMessage to read from for the comparison.
764      * @param[in]  aLength        Number of bytes to compare.
765      *
766      * @returns TRUE if there are enough bytes available in both messages and they all match. FALSE otherwise.
767      *
768      */
769     bool CompareBytes(uint16_t aOffset, const Message &aOtherMessage, uint16_t aOtherOffset, uint16_t aLength) const;
770 
771     /**
772      * This method compares the bytes in the message at a given offset with an object.
773      *
774      * The bytes in the message are compared with the bytes in @p aObject. If there are fewer bytes available in the
775      * message than the requested object size, it is treated as failed comparison (returns FALSE).
776      *
777      * @tparam     ObjectType   The object type to compare with the bytes in message.
778      *
779      * @param[in] aOffset      Byte offset within the message to read from for the comparison.
780      * @param[in] aObject      A reference to the object to compare with the message bytes.
781      *
782      * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes in @p aObject,
783      *          FALSE otherwise.
784      *
785      */
Compare(uint16_t aOffset,const ObjectType & aObject) const786     template <typename ObjectType> bool Compare(uint16_t aOffset, const ObjectType &aObject) const
787     {
788         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
789 
790         return CompareBytes(aOffset, &aObject, sizeof(ObjectType));
791     }
792 
793     /**
794      * This method writes bytes to the message.
795      *
796      * This method will not resize the message. The given data to write (with @p aLength bytes) MUST fit within the
797      * existing message buffer (from the given offset @p aOffset up to the message's length).
798      *
799      * @param[in]  aOffset  Byte offset within the message to begin writing.
800      * @param[in]  aBuf     A pointer to a data buffer.
801      * @param[in]  aLength  Number of bytes to write.
802      *
803      */
804     void WriteBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength);
805 
806     /**
807      * This methods writes an object to the message.
808      *
809      * This method will not resize the message. The entire given object (all its bytes) MUST fit within the existing
810      * message buffer (from the given offset @p aOffset up to the message's length).
811      *
812      * @tparam     ObjectType   The object type to write to the message.
813      *
814      * @param[in]  aOffset      Byte offset within the message to begin writing.
815      * @param[in]  aObject      A reference to the object to write.
816      *
817      */
Write(uint16_t aOffset,const ObjectType & aObject)818     template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject)
819     {
820         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
821 
822         WriteBytes(aOffset, &aObject, sizeof(ObjectType));
823     }
824 
825     /**
826      * This method copies bytes from one message to another.
827      *
828      * If source and destination messages are the same, `CopyTo()` can be used to perform a backward copy, but
829      * it MUST not be used to forward copy within the same message (i.e., when source and destination messages are the
830      * same and source offset is smaller than the destination offset).
831      *
832      * @param[in] aSourceOffset       Byte offset within the source message to begin reading.
833      * @param[in] aDestinationOffset  Byte offset within the destination message to begin writing.
834      * @param[in] aLength             Number of bytes to copy.
835      * @param[in] aMessage            Message to copy to.
836      *
837      * @returns The number of bytes copied.
838      *
839      */
840     uint16_t CopyTo(uint16_t aSourceOffset, uint16_t aDestinationOffset, uint16_t aLength, Message &aMessage) const;
841 
842     /**
843      * This method creates a copy of the message.
844      *
845      * It allocates the new message from the same message pool as the original one and copies @p aLength octets
846      * of the payload. The `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the
847      * cloned message are also copied from the original one.
848      *
849      * @param[in] aLength  Number of payload bytes to copy.
850      *
851      * @returns A pointer to the message or nullptr if insufficient message buffers are available.
852      *
853      */
854     Message *Clone(uint16_t aLength) const;
855 
856     /**
857      * This method creates a copy of the message.
858      *
859      * It allocates the new message from the same message pool as the original one and copies the entire payload. The
860      * `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
861      * copied from the original one.
862      *
863      * @returns A pointer to the message or nullptr if insufficient message buffers are available.
864      *
865      */
Clone(void) const866     Message *Clone(void) const { return Clone(GetLength()); }
867 
868     /**
869      * This method returns the datagram tag used for 6LoWPAN fragmentation or the identification used for IPv6
870      * fragmentation.
871      *
872      * @returns The 6LoWPAN datagram tag or the IPv6 fragment identification.
873      *
874      */
GetDatagramTag(void) const875     uint32_t GetDatagramTag(void) const { return GetMetadata().mDatagramTag; }
876 
877     /**
878      * This method sets the datagram tag used for 6LoWPAN fragmentation.
879      *
880      * @param[in]  aTag  The 6LoWPAN datagram tag.
881      *
882      */
SetDatagramTag(uint32_t aTag)883     void SetDatagramTag(uint32_t aTag) { GetMetadata().mDatagramTag = aTag; }
884 
885     /**
886      * This method returns whether or not the message forwarding is scheduled for the child.
887      *
888      * @param[in]  aChildIndex  The index into the child table.
889      *
890      * @retval TRUE   If the message is scheduled to be forwarded to the child.
891      * @retval FALSE  If the message is not scheduled to be forwarded to the child.
892      *
893      */
894     bool GetChildMask(uint16_t aChildIndex) const;
895 
896     /**
897      * This method unschedules forwarding of the message to the child.
898      *
899      * @param[in]  aChildIndex  The index into the child table.
900      *
901      */
902     void ClearChildMask(uint16_t aChildIndex);
903 
904     /**
905      * This method schedules forwarding of the message to the child.
906      *
907      * @param[in]  aChildIndex  The index into the child table.
908      *
909      */
910     void SetChildMask(uint16_t aChildIndex);
911 
912     /**
913      * This method returns whether or not the message forwarding is scheduled for at least one child.
914      *
915      * @retval TRUE   If message forwarding is scheduled for at least one child.
916      * @retval FALSE  If message forwarding is not scheduled for any child.
917      *
918      */
919     bool IsChildPending(void) const;
920 
921     /**
922      * This method returns the RLOC16 of the mesh destination.
923      *
924      * @note Only use this for non-link-local unicast messages.
925      *
926      * @returns The IEEE 802.15.4 Destination PAN ID.
927      *
928      */
GetMeshDest(void) const929     uint16_t GetMeshDest(void) const { return GetMetadata().mMeshDest; }
930 
931     /**
932      * This method sets the RLOC16 of the mesh destination.
933      *
934      * @note Only use this when sending non-link-local unicast messages.
935      *
936      * @param[in]  aMeshDest  The IEEE 802.15.4 Destination PAN ID.
937      *
938      */
SetMeshDest(uint16_t aMeshDest)939     void SetMeshDest(uint16_t aMeshDest) { GetMetadata().mMeshDest = aMeshDest; }
940 
941     /**
942      * This method returns the IEEE 802.15.4 Destination PAN ID.
943      *
944      * @note Only use this when sending MLE Discover Request or Response messages.
945      *
946      * @returns The IEEE 802.15.4 Destination PAN ID.
947      *
948      */
GetPanId(void) const949     uint16_t GetPanId(void) const { return GetMetadata().mPanIdChannel.mPanId; }
950 
951     /**
952      * This method sets the IEEE 802.15.4 Destination PAN ID.
953      *
954      * @note Only use this when sending MLE Discover Request or Response messages.
955      *
956      * @param[in]  aPanId  The IEEE 802.15.4 Destination PAN ID.
957      *
958      */
SetPanId(uint16_t aPanId)959     void SetPanId(uint16_t aPanId) { GetMetadata().mPanIdChannel.mPanId = aPanId; }
960 
961     /**
962      * This method returns the IEEE 802.15.4 Channel to use for transmission.
963      *
964      * @note Only use this when sending MLE Announce messages.
965      *
966      * @returns The IEEE 802.15.4 Channel to use for transmission.
967      *
968      */
GetChannel(void) const969     uint8_t GetChannel(void) const { return GetMetadata().mPanIdChannel.mChannel; }
970 
971     /**
972      * This method sets the IEEE 802.15.4 Channel to use for transmission.
973      *
974      * @note Only use this when sending MLE Announce messages.
975      *
976      * @param[in]  aChannel  The IEEE 802.15.4 Channel to use for transmission.
977      *
978      */
SetChannel(uint8_t aChannel)979     void SetChannel(uint8_t aChannel) { GetMetadata().mPanIdChannel.mChannel = aChannel; }
980 
981     /**
982      * This method returns the timeout used for 6LoWPAN reassembly.
983      *
984      * @returns The time remaining in seconds.
985      *
986      */
GetTimeout(void) const987     uint8_t GetTimeout(void) const { return GetMetadata().mTimeout; }
988 
989     /**
990      * This method sets the timeout used for 6LoWPAN reassembly.
991      *
992      * @param[in]  aTimeout  The timeout value.
993      *
994      */
SetTimeout(uint8_t aTimeout)995     void SetTimeout(uint8_t aTimeout) { GetMetadata().mTimeout = aTimeout; }
996 
997     /**
998      * This method decrements the timeout.
999      *
1000      */
DecrementTimeout(void)1001     void DecrementTimeout(void) { GetMetadata().mTimeout--; }
1002 
1003     /**
1004      * This method returns whether or not message forwarding is scheduled for direct transmission.
1005      *
1006      * @retval TRUE   If message forwarding is scheduled for direct transmission.
1007      * @retval FALSE  If message forwarding is not scheduled for direct transmission.
1008      *
1009      */
GetDirectTransmission(void) const1010     bool GetDirectTransmission(void) const { return GetMetadata().mDirectTx; }
1011 
1012     /**
1013      * This method unschedules forwarding using direct transmission.
1014      *
1015      */
ClearDirectTransmission(void)1016     void ClearDirectTransmission(void) { GetMetadata().mDirectTx = false; }
1017 
1018     /**
1019      * This method schedules forwarding using direct transmission.
1020      *
1021      */
SetDirectTransmission(void)1022     void SetDirectTransmission(void) { GetMetadata().mDirectTx = true; }
1023 
1024     /**
1025      * This method indicates whether the direct transmission of message was successful.
1026      *
1027      * @retval TRUE   If direct transmission of message was successful (all fragments were delivered and acked).
1028      * @retval FALSE  If direct transmission of message failed (at least one fragment failed).
1029      *
1030      */
GetTxSuccess(void) const1031     bool GetTxSuccess(void) const { return GetMetadata().mTxSuccess; }
1032 
1033     /**
1034      * This method sets whether the direct transmission of message was successful.
1035      *
1036      * @param[in] aTxSuccess   TRUE if the direct transmission is successful, FALSE otherwise (i.e., at least one
1037      *                         fragment transmission failed).
1038      *
1039      */
SetTxSuccess(bool aTxSuccess)1040     void SetTxSuccess(bool aTxSuccess) { GetMetadata().mTxSuccess = aTxSuccess; }
1041 
1042     /**
1043      * This method indicates whether the message may be evicted.
1044      *
1045      * @retval TRUE   If the message must not be evicted.
1046      * @retval FALSE  If the message may be evicted.
1047      *
1048      */
GetDoNotEvict(void) const1049     bool GetDoNotEvict(void) const { return GetMetadata().mDoNotEvict; }
1050 
1051     /**
1052      * This method sets whether the message may be evicted.
1053      *
1054      * @param[in]  aDoNotEvict  TRUE if the message may not be evicted, FALSE otherwise.
1055      *
1056      */
SetDoNotEvict(bool aDoNotEvict)1057     void SetDoNotEvict(bool aDoNotEvict) { GetMetadata().mDoNotEvict = aDoNotEvict; }
1058 
1059     /**
1060      * This method indicates whether or not link security is enabled for the message.
1061      *
1062      * @retval TRUE   If link security is enabled.
1063      * @retval FALSE  If link security is not enabled.
1064      *
1065      */
IsLinkSecurityEnabled(void) const1066     bool IsLinkSecurityEnabled(void) const { return GetMetadata().mLinkSecurity; }
1067 
1068     /**
1069      * This method sets whether or not link security is enabled for the message.
1070      *
1071      * @param[in]  aEnabled  TRUE if link security is enabled, FALSE otherwise.
1072      *
1073      */
SetLinkSecurityEnabled(bool aEnabled)1074     void SetLinkSecurityEnabled(bool aEnabled) { GetMetadata().mLinkSecurity = aEnabled; }
1075 
1076     /**
1077      * This method updates the average RSS (Received Signal Strength) associated with the message by adding the given
1078      * RSS value to the average. Note that a message can be composed of multiple 802.15.4 data frame fragments each
1079      * received with a different signal strength.
1080      *
1081      * @param[in] aRss A new RSS value (in dBm) to be added to average.
1082      *
1083      */
AddRss(int8_t aRss)1084     void AddRss(int8_t aRss) { IgnoreError(GetMetadata().mRssAverager.Add(aRss)); }
1085 
1086     /**
1087      * This method returns the average RSS (Received Signal Strength) associated with the message.
1088      *
1089      * @returns The current average RSS value (in dBm) or OT_RADIO_RSSI_INVALID if no average is available.
1090      *
1091      */
GetAverageRss(void) const1092     int8_t GetAverageRss(void) const { return GetMetadata().mRssAverager.GetAverage(); }
1093 
1094     /**
1095      * This method returns a const reference to RssAverager of the message.
1096      *
1097      * @returns A const reference to the RssAverager of the message.
1098      *
1099      */
GetRssAverager(void) const1100     const RssAverager &GetRssAverager(void) const { return GetMetadata().mRssAverager; }
1101 
1102 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1103     /**
1104      * This method updates the average LQI (Link Quality Indicator) associated with the message.
1105      *
1106      * The given LQI value would be added to the average. Note that a message can be composed of multiple 802.15.4
1107      * frame fragments each received with a different signal strength.
1108      *
1109      * @param[in] aLQI A new LQI value (has no unit) to be added to average.
1110      *
1111      */
AddLqi(uint8_t aLqi)1112     void AddLqi(uint8_t aLqi) { GetMetadata().mLqiAverager.Add(aLqi); }
1113 
1114     /**
1115      * This method returns the average LQI (Link Quality Indicator) associated with the message.
1116      *
1117      * @returns The current average LQI value (in dBm) or OT_RADIO_LQI_NONE if no average is available.
1118      *
1119      */
GetAverageLqi(void) const1120     uint8_t GetAverageLqi(void) const { return GetMetadata().mLqiAverager.GetAverage(); }
1121 
1122     /**
1123      * This mehod returns the count of frames counted so far.
1124      *
1125      * @retruns The count of frames that have been counted.
1126      *
1127      */
GetPsduCount(void) const1128     uint8_t GetPsduCount(void) const { return GetMetadata().mLqiAverager.GetCount(); }
1129 #endif
1130 
1131     /**
1132      * This method sets the message's link info properties (PAN ID, link security, RSS) from a given `ThreadLinkInfo`.
1133      *
1134      * @param[in] aLinkInfo   The `ThreadLinkInfo` instance from which to set message's related properties.
1135      *
1136      */
1137     void SetLinkInfo(const ThreadLinkInfo &aLinkInfo);
1138 
1139     /**
1140      * This method returns a pointer to the message queue (if any) where this message is queued.
1141      *
1142      * @returns A pointer to the message queue or nullptr if not in any message queue.
1143      *
1144      */
GetMessageQueue(void) const1145     MessageQueue *GetMessageQueue(void) const
1146     {
1147         return (!GetMetadata().mInPriorityQ) ? GetMetadata().mQueue.mMessage : nullptr;
1148     }
1149 
1150     /**
1151      * This method returns a pointer to the priority message queue (if any) where this message is queued.
1152      *
1153      * @returns A pointer to the priority queue or nullptr if not in any priority queue.
1154      *
1155      */
GetPriorityQueue(void) const1156     PriorityQueue *GetPriorityQueue(void) const
1157     {
1158         return (GetMetadata().mInPriorityQ) ? GetMetadata().mQueue.mPriority : nullptr;
1159     }
1160 
1161     /**
1162      * This method indicates whether or not the message is also used for time sync purpose.
1163      *
1164      * When OPENTHREAD_CONFIG_TIME_SYNC_ENABLE is 0, this method always return false.
1165      *
1166      * @retval TRUE   If the message is also used for time sync purpose.
1167      * @retval FALSE  If the message is not used for time sync purpose.
1168      *
1169      */
1170     bool IsTimeSync(void) const;
1171 
1172 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1173     /**
1174      * This method sets whether or not the message is also used for time sync purpose.
1175      *
1176      * @param[in]  aEnabled  TRUE if the message is also used for time sync purpose, FALSE otherwise.
1177      *
1178      */
SetTimeSync(bool aEnabled)1179     void SetTimeSync(bool aEnabled) { GetMetadata().mTimeSync = aEnabled; }
1180 
1181     /**
1182      * This method sets the offset to network time.
1183      *
1184      * @param[in]  aNetworkTimeOffset  The offset to network time.
1185      *
1186      */
SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1187     void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) { GetMetadata().mNetworkTimeOffset = aNetworkTimeOffset; }
1188 
1189     /**
1190      * This method gets the offset to network time.
1191      *
1192      * @returns  The offset to network time.
1193      *
1194      */
GetNetworkTimeOffset(void) const1195     int64_t GetNetworkTimeOffset(void) const { return GetMetadata().mNetworkTimeOffset; }
1196 
1197     /**
1198      * This method sets the time sync sequence.
1199      *
1200      * @param[in]  aTimeSyncSeq  The time sync sequence.
1201      *
1202      */
SetTimeSyncSeq(uint8_t aTimeSyncSeq)1203     void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { GetMetadata().mTimeSyncSeq = aTimeSyncSeq; }
1204 
1205     /**
1206      * This method gets the time sync sequence.
1207      *
1208      * @returns  The time sync sequence.
1209      *
1210      */
GetTimeSyncSeq(void) const1211     uint8_t GetTimeSyncSeq(void) const { return GetMetadata().mTimeSyncSeq; }
1212 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1213 
1214 #if OPENTHREAD_CONFIG_MULTI_RADIO
1215     /**
1216      * This method indicates whether the radio type is set.
1217      *
1218      * @retval TRUE   If the radio type is set.
1219      * @retval FALSE  If the radio type is not set.
1220      *
1221      */
IsRadioTypeSet(void) const1222     bool IsRadioTypeSet(void) const { return GetMetadata().mIsRadioTypeSet; }
1223 
1224     /**
1225      * This method gets the radio link type the message was received on, or should be sent on.
1226      *
1227      * This method should be used only when `IsRadioTypeSet()` returns `true`.
1228      *
1229      * @returns The radio link type of the message.
1230      *
1231      */
GetRadioType(void) const1232     Mac::RadioType GetRadioType(void) const { return static_cast<Mac::RadioType>(GetMetadata().mRadioType); }
1233 
1234     /**
1235      * This method sets the radio link type the message was received on, or should be sent on.
1236      *
1237      * @param[in] aRadioType   A radio link type of the message.
1238      *
1239      */
SetRadioType(Mac::RadioType aRadioType)1240     void SetRadioType(Mac::RadioType aRadioType)
1241     {
1242         GetMetadata().mIsRadioTypeSet = true;
1243         GetMetadata().mRadioType      = aRadioType;
1244     }
1245 
1246     /**
1247      * This method clears any previously set radio type on the message.
1248      *
1249      * After calling this method, `IsRadioTypeSet()` returns false until radio type is set (`SetRadioType()`).
1250      *
1251      */
ClearRadioType(void)1252     void ClearRadioType(void) { GetMetadata().mIsRadioTypeSet = false; }
1253 
1254 #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
1255 
1256 private:
1257     /**
1258      * This method returns a pointer to the message pool to which this message belongs
1259      *
1260      * @returns A pointer to the message pool.
1261      *
1262      */
GetMessagePool(void) const1263     MessagePool *GetMessagePool(void) const { return GetMetadata().mMessagePool; }
1264 
1265     /**
1266      * This method sets the message pool this message to which this message belongs.
1267      *
1268      * @param[in] aMessagePool  A pointer to the message pool
1269      *
1270      */
SetMessagePool(MessagePool * aMessagePool)1271     void SetMessagePool(MessagePool *aMessagePool) { GetMetadata().mMessagePool = aMessagePool; }
1272 
1273     /**
1274      * This method returns `true` if the message is enqueued in any queue (`MessageQueue` or `PriorityQueue`).
1275      *
1276      * @returns `true` if the message is in any queue, `false` otherwise.
1277      *
1278      */
IsInAQueue(void) const1279     bool IsInAQueue(void) const { return (GetMetadata().mQueue.mMessage != nullptr); }
1280 
1281     /**
1282      * This method sets the message queue information for the message.
1283      *
1284      * @param[in]  aMessageQueue  A pointer to the message queue where this message is queued.
1285      *
1286      */
1287     void SetMessageQueue(MessageQueue *aMessageQueue);
1288 
1289     /**
1290      * This method sets the message queue information for the message.
1291      *
1292      * @param[in]  aPriorityQueue  A pointer to the priority queue where this message is queued.
1293      *
1294      */
1295     void SetPriorityQueue(PriorityQueue *aPriorityQueue);
1296 
1297     /**
1298      * This method returns a reference to the `mNext` pointer.
1299      *
1300      * @returns A reference to the mNext pointer.
1301      *
1302      */
Next(void)1303     Message *&Next(void) { return GetMetadata().mNext; }
1304 
1305     /**
1306      * This method returns a reference to the `mNext` pointer (const pointer).
1307      *
1308      *
1309      * @returns A reference to the mNext pointer.
1310      *
1311      */
Next(void) const1312     Message *const &Next(void) const { return GetMetadata().mNext; }
1313 
1314     /**
1315      * This method returns a reference to the `mPrev` pointer.
1316      *
1317      * @returns A reference to the mPrev pointer.
1318      *
1319      */
Prev(void)1320     Message *&Prev(void) { return GetMetadata().mPrev; }
1321 
1322     /**
1323      * This method returns the number of reserved header bytes.
1324      *
1325      * @returns The number of reserved header bytes.
1326      *
1327      */
GetReserved(void) const1328     uint16_t GetReserved(void) const { return GetMetadata().mReserved; }
1329 
1330     /**
1331      * This method sets the number of reserved header bytes.
1332      *
1333      * @param[in] aReservedHeader  The number of header bytes to reserve.
1334      *
1335      */
SetReserved(uint16_t aReservedHeader)1336     void SetReserved(uint16_t aReservedHeader) { GetMetadata().mReserved = aReservedHeader; }
1337 
1338     /**
1339      * This method adds or frees message buffers to meet the requested length.
1340      *
1341      * @param[in]  aLength  The number of bytes that the message buffer needs to handle.
1342      *
1343      * @retval kErrorNone    Successfully resized the message.
1344      * @retval kErrorNoBufs  Could not grow the message due to insufficient available message buffers.
1345      *
1346      */
1347     Error ResizeMessage(uint16_t aLength);
1348 
1349 private:
1350     struct Chunk
1351     {
GetDataot::Message::Chunk1352         const uint8_t *GetData(void) const { return mData; }
GetLengthot::Message::Chunk1353         uint16_t       GetLength(void) const { return mLength; }
1354 
1355         const uint8_t *mData;   // Pointer to start of chunk data buffer.
1356         uint16_t       mLength; // Length of chunk data (in bytes).
1357         const Buffer * mBuffer; // Buffer containing the chunk
1358     };
1359 
1360     struct WritableChunk : public Chunk
1361     {
GetDataot::Message::WritableChunk1362         uint8_t *GetData(void) const { return const_cast<uint8_t *>(mData); }
1363     };
1364 
1365     void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, Chunk &chunk) const;
1366     void GetNextChunk(uint16_t &aLength, Chunk &aChunk) const;
1367 
GetFirstChunk(uint16_t aOffset,uint16_t & aLength,WritableChunk & aChunk)1368     void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, WritableChunk &aChunk)
1369     {
1370         const_cast<const Message *>(this)->GetFirstChunk(aOffset, aLength, static_cast<Chunk &>(aChunk));
1371     }
1372 
GetNextChunk(uint16_t & aLength,WritableChunk & aChunk)1373     void GetNextChunk(uint16_t &aLength, WritableChunk &aChunk)
1374     {
1375         const_cast<const Message *>(this)->GetNextChunk(aLength, static_cast<Chunk &>(aChunk));
1376     }
1377 };
1378 
1379 /**
1380  * This class implements a message queue.
1381  *
1382  */
1383 class MessageQueue : public otMessageQueue
1384 {
1385     friend class Message;
1386     friend class PriorityQueue;
1387 
1388 public:
1389     /**
1390      * This enumeration represents a position (head or tail) in the queue. This is used to specify where a new message
1391      * should be added in the queue.
1392      *
1393      */
1394     enum QueuePosition : uint8_t
1395     {
1396         kQueuePositionHead, ///< Indicates the head (front) of the list.
1397         kQueuePositionTail, ///< Indicates the tail (end) of the list.
1398     };
1399 
1400     /**
1401      * This constructor initializes the message queue.
1402      *
1403      */
1404     MessageQueue(void);
1405 
1406     /**
1407      * This method returns a pointer to the first message.
1408      *
1409      * @returns A pointer to the first message.
1410      *
1411      */
1412     Message *GetHead(void) const;
1413 
1414     /**
1415      * This method adds a message to the end of the list.
1416      *
1417      * @param[in]  aMessage  The message to add.
1418      *
1419      */
Enqueue(Message & aMessage)1420     void Enqueue(Message &aMessage) { Enqueue(aMessage, kQueuePositionTail); }
1421 
1422     /**
1423      * This method adds a message at a given position (head/tail) of the list.
1424      *
1425      * @param[in]  aMessage  The message to add.
1426      * @param[in]  aPosition The position (head or tail) where to add the message.
1427      *
1428      */
1429     void Enqueue(Message &aMessage, QueuePosition aPosition);
1430 
1431     /**
1432      * This method removes a message from the list.
1433      *
1434      * @param[in]  aMessage  The message to remove.
1435      *
1436      */
1437     void Dequeue(Message &aMessage);
1438 
1439     /**
1440      * This method removes a message from the queue and frees it.
1441      *
1442      * @param[in]  aMessage  The message to remove and free.
1443      *
1444      */
1445     void DequeueAndFree(Message &aMessage);
1446 
1447     /**
1448      * This method removes and frees all messages from the queue.
1449      *
1450      */
1451     void DequeueAndFreeAll(void);
1452 
1453     /**
1454      * This method returns the number of messages and buffers enqueued.
1455      *
1456      * @param[out]  aMessageCount  Returns the number of messages enqueued.
1457      * @param[out]  aBufferCount   Returns the number of buffers enqueued.
1458      *
1459      */
1460     void GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const;
1461 
1462 private:
1463     /**
1464      * This method returns the tail of the list (last message in the list)
1465      *
1466      * @returns A pointer to the tail of the list.
1467      *
1468      */
GetTail(void) const1469     Message *GetTail(void) const { return static_cast<Message *>(mData); }
1470 
1471     /**
1472      * This method set the tail of the list.
1473      *
1474      * @param[in]  aMessage  A pointer to the message to set as new tail.
1475      *
1476      */
SetTail(Message * aMessage)1477     void SetTail(Message *aMessage) { mData = aMessage; }
1478 };
1479 
1480 /**
1481  * This class implements a priority queue.
1482  *
1483  */
1484 class PriorityQueue
1485 {
1486     friend class Message;
1487     friend class MessageQueue;
1488     friend class MessagePool;
1489 
1490 public:
1491     /**
1492      * This constructor initializes the priority queue.
1493      *
1494      */
1495     PriorityQueue(void);
1496 
1497     /**
1498      * This method returns a pointer to the first message.
1499      *
1500      * @returns A pointer to the first message.
1501      *
1502      */
1503     Message *GetHead(void) const;
1504 
1505     /**
1506      * This method returns a pointer to the first message for a given priority level.
1507      *
1508      * @param[in] aPriority   Priority level.
1509      *
1510      * @returns A pointer to the first message with given priority level or nullptr if there is no messages with
1511      *          this priority level.
1512      *
1513      */
1514     Message *GetHeadForPriority(Message::Priority aPriority) const;
1515 
1516     /**
1517      * This method adds a message to the queue.
1518      *
1519      * @param[in]  aMessage  The message to add.
1520      *
1521      */
1522     void Enqueue(Message &aMessage);
1523 
1524     /**
1525      * This method removes a message from the list.
1526      *
1527      * @param[in]  aMessage  The message to remove.
1528      *
1529      */
1530     void Dequeue(Message &aMessage);
1531 
1532     /**
1533      * This method removes a message from the queue and frees it.
1534      *
1535      * @param[in]  aMessage  The message to remove and free.
1536      *
1537      */
1538     void DequeueAndFree(Message &aMessage);
1539 
1540     /**
1541      * This method removes and frees all messages from the queue.
1542      *
1543      */
1544     void DequeueAndFreeAll(void);
1545 
1546     /**
1547      * This method returns the number of messages and buffers enqueued.
1548      *
1549      * @param[out]  aMessageCount  Returns the number of messages enqueued.
1550      * @param[out]  aBufferCount   Returns the number of buffers enqueued.
1551      *
1552      */
1553     void GetInfo(uint16_t &aMessageCount, uint16_t &aBufferCount) const;
1554 
1555     /**
1556      * This method returns the tail of the list (last message in the list)
1557      *
1558      * @returns A pointer to the tail of the list.
1559      *
1560      */
1561     Message *GetTail(void) const;
1562 
1563 private:
1564     /**
1565      * This method increases (moves forward) the given priority while ensuring to wrap from
1566      * priority value `kNumPriorities` -1 back to 0.
1567      *
1568      * @param[in] aPriority  A given priority level
1569      *
1570      * @returns Increased/Moved forward priority level
1571      */
PrevPriority(uint8_t aPriority) const1572     uint8_t PrevPriority(uint8_t aPriority) const
1573     {
1574         return (aPriority == Message::kNumPriorities - 1) ? 0 : (aPriority + 1);
1575     }
1576 
1577     /**
1578      * This private method finds the first non-nullptr tail starting from the given priority level and moving forward.
1579      * It wraps from priority value `kNumPriorities` -1 back to 0.
1580      *
1581      * aStartPriorityLevel  Starting priority level.
1582      *
1583      * @returns The first non-nullptr tail pointer, or nullptr if all the
1584      *
1585      */
1586     Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const;
1587 
1588 private:
1589     Message *mTails[Message::kNumPriorities]; ///< Tail pointers associated with different priority levels.
1590 };
1591 
1592 /**
1593  * This class represents a message pool
1594  *
1595  */
1596 class MessagePool : public InstanceLocator, private NonCopyable
1597 {
1598     friend class Message;
1599     friend class MessageQueue;
1600     friend class PriorityQueue;
1601 
1602 public:
1603     /**
1604      * This constructor initializes the object.
1605      *
1606      */
1607     explicit MessagePool(Instance &aInstance);
1608 
1609     /**
1610      * This method is used to obtain a new message.
1611      *
1612      * The link security is enabled by default on the newly obtained message.
1613      *
1614      * @param[in]  aType           The message type.
1615      * @param[in]  aReserveHeader  The number of header bytes to reserve.
1616      * @param[in]  aPriority       The priority level of the message.
1617      *
1618      * @returns A pointer to the message or nullptr if no message buffers are available.
1619      *
1620      */
1621     Message *New(Message::Type aType, uint16_t aReserveHeader, Message::Priority aPriority);
1622 
1623 public:
1624     /**
1625      * This method is used to obtain a new message with specified settings.
1626      *
1627      * @param[in]  aType           The message type.
1628      * @param[in]  aReserveHeader  The number of header bytes to reserve.
1629      * @param[in]  aSettings       The message settings.
1630      *
1631      * @returns A pointer to the message or nullptr if no message buffers are available.
1632      *
1633      */
1634     Message *New(Message::Type            aType,
1635                  uint16_t                 aReserveHeader,
1636                  const Message::Settings &aSettings = Message::Settings::GetDefault());
1637 
1638     /**
1639      * This method is used to free a message and return all message buffers to the buffer pool.
1640      *
1641      * @param[in]  aMessage  The message to free.
1642      *
1643      */
1644     void Free(Message *aMessage);
1645 
1646     /**
1647      * This method returns the number of free buffers.
1648      *
1649      * @returns The number of free buffers.
1650      *
1651      */
1652     uint16_t GetFreeBufferCount(void) const;
1653 
1654     /**
1655      * This method returns the total number of buffers.
1656      *
1657      * @returns The total number of buffers.
1658      *
1659      */
1660     uint16_t GetTotalBufferCount(void) const;
1661 
1662 private:
1663     Buffer *NewBuffer(Message::Priority aPriority);
1664     void    FreeBuffers(Buffer *aBuffer);
1665     Error   ReclaimBuffers(Message::Priority aPriority);
1666 
1667 #if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
1668     uint16_t                  mNumFreeBuffers;
1669     Pool<Buffer, kNumBuffers> mBufferPool;
1670 #endif
1671 };
1672 
1673 /**
1674  * @}
1675  *
1676  */
1677 
1678 } // namespace ot
1679 
1680 #endif // MESSAGE_HPP_
1681