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  * This struct 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  * This macro frees a given message buffer if not `nullptr`.
92  *
93  * This macro 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  * This macro 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  * This macro 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  * This class represents a Message buffer.
156  *
157  */
158 class Buffer : public otMessageBuffer, public LinkedListEntry<Buffer>
159 {
160     friend class Message;
161 
162 public:
163     /**
164      * This method 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      * This method 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      * This method 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 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
204         LqiAverager mLqiAverager; // The averager maintaining the Link quality indicator (LQI) average.
205 #endif
206         ChildMask mChildMask; // ChildMask to indicate which sleepy children need to receive this.
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 #if OPENTHREAD_CONFIG_MULTI_RADIO
219         uint8_t mRadioType : 2;      // The radio link type the message was received on, or should be sent on.
220         bool    mIsRadioTypeSet : 1; // Whether the radio type is set.
221         static_assert(Mac::kNumRadioTypes <= (1 << 2), "mRadioType bitfield cannot store all radio type values");
222 #endif
223 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
224         bool    mTimeSync : 1;      // Whether the message is also used for time sync purpose.
225         int64_t mNetworkTimeOffset; // The time offset to the Thread network time, in microseconds.
226         uint8_t mTimeSyncSeq;       // The time sync sequence.
227 #endif
228     };
229 
230     static_assert(kBufferSize > sizeof(Metadata) + sizeof(otMessageBuffer), "Metadata does not fit in a single buffer");
231 
232     static constexpr uint16_t kBufferDataSize     = kBufferSize - sizeof(otMessageBuffer);
233     static constexpr uint16_t kHeadBufferDataSize = kBufferDataSize - sizeof(Metadata);
234 
GetMetadata(void)235     Metadata       &GetMetadata(void) { return mBuffer.mHead.mMetadata; }
GetMetadata(void) const236     const Metadata &GetMetadata(void) const { return mBuffer.mHead.mMetadata; }
237 
GetFirstData(void)238     uint8_t       *GetFirstData(void) { return mBuffer.mHead.mData; }
GetFirstData(void) const239     const uint8_t *GetFirstData(void) const { return mBuffer.mHead.mData; }
240 
GetData(void)241     uint8_t       *GetData(void) { return mBuffer.mData; }
GetData(void) const242     const uint8_t *GetData(void) const { return mBuffer.mData; }
243 
244 private:
245     union
246     {
247         struct
248         {
249             Metadata mMetadata;
250             uint8_t  mData[kHeadBufferDataSize];
251         } mHead;
252         uint8_t mData[kBufferDataSize];
253     } mBuffer;
254 };
255 
256 static_assert(sizeof(Buffer) >= kBufferSize,
257               "Buffer size is not valid. Increase OPENTHREAD_CONFIG_MESSAGE_BUFFER_SIZE.");
258 
259 /**
260  * This class represents a message.
261  *
262  */
263 class Message : public otMessage, public Buffer, public GetProvider<Message>
264 {
265     friend class Checksum;
266     friend class Crypto::HmacSha256;
267     friend class Crypto::Sha256;
268     friend class Crypto::AesCcm;
269     friend class MessagePool;
270     friend class MessageQueue;
271     friend class PriorityQueue;
272 
273 public:
274     /**
275      * This enumeration represents the message type.
276      *
277      */
278     enum Type : uint8_t
279     {
280         kTypeIp6          = 0, ///< A full uncompressed IPv6 packet
281         kType6lowpan      = 1, ///< A 6lowpan frame
282         kTypeSupervision  = 2, ///< A child supervision frame.
283         kTypeMacEmptyData = 3, ///< An empty MAC data frame.
284         kTypeIp4          = 4, ///< A full uncompressed IPv4 packet, for NAT64.
285         kTypeOther        = 5, ///< Other (data) message.
286     };
287 
288     /**
289      * This enumeration represents the message sub-type.
290      *
291      */
292     enum SubType : uint8_t
293     {
294         kSubTypeNone                   = 0,  ///< None
295         kSubTypeMleAnnounce            = 1,  ///< MLE Announce
296         kSubTypeMleDiscoverRequest     = 2,  ///< MLE Discover Request
297         kSubTypeMleDiscoverResponse    = 3,  ///< MLE Discover Response
298         kSubTypeJoinerEntrust          = 4,  ///< Joiner Entrust
299         kSubTypeMplRetransmission      = 5,  ///< MPL next retransmission message
300         kSubTypeMleGeneral             = 6,  ///< General MLE
301         kSubTypeJoinerFinalizeResponse = 7,  ///< Joiner Finalize Response
302         kSubTypeMleChildUpdateRequest  = 8,  ///< MLE Child Update Request
303         kSubTypeMleDataResponse        = 9,  ///< MLE Data Response
304         kSubTypeMleChildIdRequest      = 10, ///< MLE Child ID Request
305         kSubTypeMleDataRequest         = 11, ///< MLE Data Request
306     };
307 
308     enum Priority : uint8_t
309     {
310         kPriorityLow    = OT_MESSAGE_PRIORITY_LOW,      ///< Low priority level.
311         kPriorityNormal = OT_MESSAGE_PRIORITY_NORMAL,   ///< Normal priority level.
312         kPriorityHigh   = OT_MESSAGE_PRIORITY_HIGH,     ///< High priority level.
313         kPriorityNet    = OT_MESSAGE_PRIORITY_HIGH + 1, ///< Network Control priority level.
314     };
315 
316     static constexpr uint8_t kNumPriorities = 4; ///< Number of priority levels.
317 
318     /**
319      * This enumeration represents the link security mode (used by `Settings` constructor).
320      *
321      */
322     enum LinkSecurityMode : bool
323     {
324         kNoLinkSecurity   = false, ///< Link security disabled (no link security).
325         kWithLinkSecurity = true,  ///< Link security enabled.
326     };
327 
328     /**
329      * This enumeration represents the message ownership model when a `Message` instance is passed to a method/function.
330      *
331      */
332     enum Ownership : uint8_t
333     {
334         /**
335          * This value indicates that the method/function receiving a `Message` instance should take custody of the
336          * message (e.g., the method should `Free()` the message if no longer needed).
337          *
338          */
339         kTakeCustody,
340 
341         /**
342          * This value indicates that the method/function receiving a `Message` instance does not own the message (e.g.,
343          * it should not `Free()` or `Enqueue()` it in a queue). The receiving method/function should create a
344          * copy/clone of the message to keep (if/when needed).
345          *
346          */
347         kCopyToUse,
348     };
349 
350     /**
351      * This class represents settings used for creating a new message.
352      *
353      */
354     class Settings : public otMessageSettings
355     {
356     public:
357         /**
358          * This constructor initializes the `Settings` object.
359          *
360          * @param[in]  aSecurityMode  A link security mode.
361          * @param[in]  aPriority      A message priority.
362          *
363          */
364         Settings(LinkSecurityMode aSecurityMode, Priority aPriority);
365 
366         /**
367          * This constructor initializes the `Settings` with a given message priority and link security enabled.
368          *
369          * @param[in]  aPriority      A message priority.
370          *
371          */
Settings(Priority aPriority)372         explicit Settings(Priority aPriority)
373             : Settings(kWithLinkSecurity, aPriority)
374         {
375         }
376 
377         /**
378          * This method gets the message priority.
379          *
380          * @returns The message priority.
381          *
382          */
GetPriority(void) const383         Priority GetPriority(void) const { return static_cast<Priority>(mPriority); }
384 
385         /**
386          * This method indicates whether the link security should be enabled.
387          *
388          * @returns TRUE if link security should be enabled, FALSE otherwise.
389          *
390          */
IsLinkSecurityEnabled(void) const391         bool IsLinkSecurityEnabled(void) const { return mLinkSecurityEnabled; }
392 
393         /**
394          * This static method converts a pointer to an `otMessageSettings` to a `Settings`.
395          *
396          * @param[in] aSettings  A pointer to `otMessageSettings` to covert from.
397          *                       If it is `nullptr`, then the default settings `GetDefault()` will be used.
398          *
399          * @returns A reference to the converted `Settings` or the default if @p aSettings is `nullptr`.
400          *
401          */
402         static const Settings &From(const otMessageSettings *aSettings);
403 
404         /**
405          * This static method returns the default settings with link security enabled and `kPriorityNormal` priority.
406          *
407          * @returns A reference to the default settings (link security enable and `kPriorityNormal` priority).
408          *
409          */
GetDefault(void)410         static const Settings &GetDefault(void) { return static_cast<const Settings &>(kDefault); }
411 
412     private:
413         static const otMessageSettings kDefault;
414     };
415 
416     /**
417      * This method returns a reference to the OpenThread Instance which owns the `Message`.
418      *
419      * @returns A reference to the `Instance`.
420      *
421      */
422     Instance &GetInstance(void) const;
423 
424     /**
425      * This method frees this message buffer.
426      *
427      */
428     void Free(void);
429 
430     /**
431      * This method returns a pointer to the next message.
432      *
433      * @returns A pointer to the next message in the list or `nullptr` if at the end of the list.
434      *
435      */
436     Message *GetNext(void) const;
437 
438     /**
439      * This method returns the number of bytes in the message.
440      *
441      * @returns The number of bytes in the message.
442      *
443      */
GetLength(void) const444     uint16_t GetLength(void) const { return GetMetadata().mLength; }
445 
446     /**
447      * This method sets the number of bytes in the message.
448      *
449      * @param[in]  aLength  Requested number of bytes in the message.
450      *
451      * @retval kErrorNone    Successfully set the length of the message.
452      * @retval kErrorNoBufs  Failed to grow the size of the message because insufficient buffers were available.
453      *
454      */
455     Error SetLength(uint16_t aLength);
456 
457     /**
458      * This method returns the number of buffers in the message.
459      *
460      */
461     uint8_t GetBufferCount(void) const;
462 
463     /**
464      * This method returns the byte offset within the message.
465      *
466      * @returns A byte offset within the message.
467      *
468      */
GetOffset(void) const469     uint16_t GetOffset(void) const { return GetMetadata().mOffset; }
470 
471     /**
472      * This method moves the byte offset within the message.
473      *
474      * @param[in]  aDelta  The number of bytes to move the current offset, which may be positive or negative.
475      *
476      */
477     void MoveOffset(int aDelta);
478 
479     /**
480      * This method sets the byte offset within the message.
481      *
482      * @param[in]  aOffset  The byte offset within the message.
483      *
484      */
485     void SetOffset(uint16_t aOffset);
486 
487     /**
488      * This method returns the type of the message.
489      *
490      * @returns The type of the message.
491      *
492      */
GetType(void) const493     Type GetType(void) const { return static_cast<Type>(GetMetadata().mType); }
494 
495     /**
496      * This method sets the message type.
497      *
498      * @param[in]  aType  The message type.
499      *
500      */
SetType(Type aType)501     void SetType(Type aType) { GetMetadata().mType = aType; }
502 
503     /**
504      * This method returns the sub type of the message.
505      *
506      * @returns The sub type of the message.
507      *
508      */
GetSubType(void) const509     SubType GetSubType(void) const { return static_cast<SubType>(GetMetadata().mSubType); }
510 
511     /**
512      * This method sets the message sub type.
513      *
514      * @param[in]  aSubType  The message sub type.
515      *
516      */
SetSubType(SubType aSubType)517     void SetSubType(SubType aSubType) { GetMetadata().mSubType = aSubType; }
518 
519     /**
520      * This method returns whether or not the message is of MLE subtype.
521      *
522      * @retval TRUE   If message is of MLE subtype.
523      * @retval FALSE  If message is not of MLE subtype.
524      *
525      */
526     bool IsSubTypeMle(void) const;
527 
528     /**
529      * This method checks whether this multicast message may be looped back.
530      *
531      * @retval TRUE   If message may be looped back.
532      * @retval FALSE  If message must not be looped back.
533      *
534      */
GetMulticastLoop(void) const535     bool GetMulticastLoop(void) const { return GetMetadata().mMulticastLoop; }
536 
537     /**
538      * This method sets whether multicast may be looped back.
539      *
540      * @param[in]  aMulticastLoop  Whether allow looping back multicast.
541      *
542      */
SetMulticastLoop(bool aMulticastLoop)543     void SetMulticastLoop(bool aMulticastLoop) { GetMetadata().mMulticastLoop = aMulticastLoop; }
544 
545     /**
546      * This method returns the message priority level.
547      *
548      * @returns The priority level associated with this message.
549      *
550      */
GetPriority(void) const551     Priority GetPriority(void) const { return static_cast<Priority>(GetMetadata().mPriority); }
552 
553     /**
554      * This method sets the messages priority.
555      * If the message is already queued in a priority queue, changing the priority ensures to
556      * update the message in the associated queue.
557      *
558      * @param[in]  aPriority  The message priority level.
559      *
560      * @retval kErrorNone          Successfully set the priority for the message.
561      * @retval kErrorInvalidArgs   Priority level is not invalid.
562      *
563      */
564     Error SetPriority(Priority aPriority);
565 
566     /**
567      * This static method convert a `Priority` to a string.
568      *
569      * @param[in] aPriority  The priority level.
570      *
571      * @returns A string representation of @p aPriority.
572      *
573      */
574     static const char *PriorityToString(Priority aPriority);
575 
576     /**
577      * This method prepends bytes to the front of the message.
578      *
579      * On success, this method grows the message by @p aLength bytes.
580      *
581      * @param[in]  aBuf     A pointer to a data buffer (can be `nullptr` to grow message without writing bytes).
582      * @param[in]  aLength  The number of bytes to prepend.
583      *
584      * @retval kErrorNone    Successfully prepended the bytes.
585      * @retval kErrorNoBufs  Not enough reserved bytes in the message.
586      *
587      */
588     Error PrependBytes(const void *aBuf, uint16_t aLength);
589 
590     /**
591      * This method prepends an object to the front of the message.
592      *
593      * On success, this method grows the message by the size of the object.
594      *
595      * @tparam    ObjectType   The object type to prepend to the message.
596      *
597      * @param[in] aObject      A reference to the object to prepend to the message.
598      *
599      * @retval kErrorNone    Successfully prepended the object.
600      * @retval kErrorNoBufs  Not enough reserved bytes in the message.
601      *
602      */
Prepend(const ObjectType & aObject)603     template <typename ObjectType> Error Prepend(const ObjectType &aObject)
604     {
605         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
606 
607         return PrependBytes(&aObject, sizeof(ObjectType));
608     }
609 
610     /**
611      * This method removes header bytes from the message at start of message.
612      *
613      * The caller MUST ensure that message contains the bytes to be removed, i.e. `aOffset` is smaller than the message
614      * length.
615      *
616      * @param[in]  aLength  Number of header bytes to remove from start of `Message`.
617      *
618      */
619     void RemoveHeader(uint16_t aLength);
620 
621     /**
622      * This method removes header bytes from the message at a given offset.
623      *
624      * This method shrinks the message. The existing header bytes before @p aOffset are copied forward and replace the
625      * removed bytes.
626      *
627      * The caller MUST ensure that message contains the bytes to be removed, i.e. `aOffset + aLength` is smaller than
628      * the message length.
629      *
630      * @param[in]  aOffset  The offset to start removing.
631      * @param[in]  aLength  Number of header bytes to remove.
632      *
633      */
634     void RemoveHeader(uint16_t aOffset, uint16_t aLength);
635 
636     /**
637      * This method grows the message to make space for new header bytes at a given offset.
638      *
639      * This method grows the message header (similar to `PrependBytes()`). The existing header bytes from start to
640      * `aOffset + aLength` are then copied backward to make room for the new header bytes. Note that this method does
641      * not change the bytes from @p aOffset up @p aLength (the new inserted header range). Caller can write to this
642      * range to update the bytes after successful return from this method.
643      *
644      * @param[in] aOffset   The offset at which to insert the header bytes
645      * @param[in] aLength   Number of header bytes to insert.
646      *
647      * @retval kErrorNone    Successfully grown the message and copied the existing header bytes.
648      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
649      *
650      */
651     Error InsertHeader(uint16_t aOffset, uint16_t aLength);
652 
653     /**
654      * This method appends bytes to the end of the message.
655      *
656      * On success, this method grows the message by @p aLength bytes.
657      *
658      * @param[in]  aBuf     A pointer to a data buffer (MUST not be `nullptr`).
659      * @param[in]  aLength  The number of bytes to append.
660      *
661      * @retval kErrorNone    Successfully appended the bytes.
662      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
663      *
664      */
665     Error AppendBytes(const void *aBuf, uint16_t aLength);
666 
667     /**
668      * This method appends bytes read from another or potentially the same message to the end of the current message.
669      *
670      * On success, this method grows the message by @p aLength bytes.
671      *
672      * @param[in] aMessage   The message to read the bytes from (it can be the same as the current message).
673      * @param[in] aOffset    The offset in @p aMessage to start reading the bytes from.
674      * @param[in] aLength    The number of bytes to read from @p aMessage and append.
675      *
676      * @retval kErrorNone    Successfully appended the bytes.
677      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
678      * @retval kErrorParse   Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset.
679      *
680      */
681     Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
682 
683     /**
684      * This method appends an object to the end of the message.
685      *
686      * On success, this method grows the message by the size of the appended object
687      *
688      * @tparam    ObjectType   The object type to append to the message.
689      *
690      * @param[in] aObject      A reference to the object to append to the message.
691      *
692      * @retval kErrorNone    Successfully appended the object.
693      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
694      *
695      */
Append(const ObjectType & aObject)696     template <typename ObjectType> Error Append(const ObjectType &aObject)
697     {
698         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
699 
700         return AppendBytes(&aObject, sizeof(ObjectType));
701     }
702 
703     /**
704      * This method appends bytes from a given `Data` instance to the end of the message.
705      *
706      * On success, this method grows the message by the size of the appended data.
707      *
708      * @tparam    kDataLengthType   Determines the data length type (`uint8_t` or `uint16_t`).
709      *
710      * @param[in] aData      A reference to `Data` to append to the message.
711      *
712      * @retval kErrorNone    Successfully appended the bytes from @p aData.
713      * @retval kErrorNoBufs  Insufficient available buffers to grow the message.
714      *
715      */
AppendData(const Data<kDataLengthType> & aData)716     template <DataLengthType kDataLengthType> Error AppendData(const Data<kDataLengthType> &aData)
717     {
718         return AppendBytes(aData.GetBytes(), aData.GetLength());
719     }
720 
721     /**
722      * This method reads bytes from the message.
723      *
724      * @param[in]  aOffset  Byte offset within the message to begin reading.
725      * @param[out] aBuf     A pointer to a data buffer to copy the read bytes into.
726      * @param[in]  aLength  Number of bytes to read.
727      *
728      * @returns The number of bytes read.
729      *
730      */
731     uint16_t ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
732 
733     /**
734      * This method reads a given number of bytes from the message.
735      *
736      * If there are fewer bytes available in the message than the requested read length, the available bytes will be
737      * read and copied into @p aBuf. In this case `kErrorParse` will be returned.
738      *
739      * @param[in]  aOffset  Byte offset within the message to begin reading.
740      * @param[out] aBuf     A pointer to a data buffer to copy the read bytes into.
741      * @param[in]  aLength  Number of bytes to read.
742      *
743      * @retval kErrorNone     @p aLength bytes were successfully read from message.
744      * @retval kErrorParse    Not enough bytes remaining in message to read the entire object.
745      *
746      */
747     Error Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
748 
749     /**
750      * This method reads an object from the message.
751      *
752      * If there are fewer bytes available in the message than the requested object size, the available bytes will be
753      * read and copied into @p aObject (@p aObject will be read partially). In this case `kErrorParse` will
754      * be returned.
755      *
756      * @tparam     ObjectType   The object type to read from the message.
757      *
758      * @param[in]  aOffset      Byte offset within the message to begin reading.
759      * @param[out] aObject      A reference to the object to read into.
760      *
761      * @retval kErrorNone     Object @p aObject was successfully read from message.
762      * @retval kErrorParse    Not enough bytes remaining in message to read the entire object.
763      *
764      */
Read(uint16_t aOffset,ObjectType & aObject) const765     template <typename ObjectType> Error Read(uint16_t aOffset, ObjectType &aObject) const
766     {
767         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
768 
769         return Read(aOffset, &aObject, sizeof(ObjectType));
770     }
771 
772     /**
773      * This method compares the bytes in the message at a given offset with a given byte array.
774      *
775      * If there are fewer bytes available in the message than the requested @p aLength, the comparison is treated as
776      * failure (returns FALSE).
777      *
778      * @param[in]  aOffset    Byte offset within the message to read from for the comparison.
779      * @param[in]  aBuf       A pointer to a data buffer to compare with the bytes from message.
780      * @param[in]  aLength    Number of bytes in @p aBuf.
781      * @param[in]  aMatcher   A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are directly
782      *                        compared.
783      *
784      * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf,
785      *          FALSE otherwise.
786      *
787      */
788     bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher = nullptr) const;
789 
790     /**
791      * This method compares the bytes in the message at a given offset with bytes read from another message.
792      *
793      * If either message has fewer bytes available than the requested @p aLength, the comparison is treated as failure
794      * (returns FALSE).
795      *
796      * @param[in]  aOffset        Byte offset within the message to read from for the comparison.
797      * @param[in]  aOtherMessage  The other message to compare with.
798      * @param[in]  aOtherOffset   Byte offset within @p aOtherMessage to read from for the comparison.
799      * @param[in]  aLength        Number of bytes to compare.
800      * @param[in]  aMatcher       A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are
801      *                            directly compared.
802      *
803      * @returns TRUE if there are enough bytes available in both messages and they all match. FALSE otherwise.
804      *
805      */
806     bool CompareBytes(uint16_t       aOffset,
807                       const Message &aOtherMessage,
808                       uint16_t       aOtherOffset,
809                       uint16_t       aLength,
810                       ByteMatcher    aMatcher = nullptr) const;
811 
812     /**
813      * This method compares the bytes in the message at a given offset with an object.
814      *
815      * The bytes in the message are compared with the bytes in @p aObject. If there are fewer bytes available in the
816      * message than the requested object size, it is treated as failed comparison (returns FALSE).
817      *
818      * @tparam     ObjectType   The object type to compare with the bytes in message.
819      *
820      * @param[in] aOffset      Byte offset within the message to read from for the comparison.
821      * @param[in] aObject      A reference to the object to compare with the message bytes.
822      *
823      * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes in @p aObject,
824      *          FALSE otherwise.
825      *
826      */
Compare(uint16_t aOffset,const ObjectType & aObject) const827     template <typename ObjectType> bool Compare(uint16_t aOffset, const ObjectType &aObject) const
828     {
829         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
830 
831         return CompareBytes(aOffset, &aObject, sizeof(ObjectType));
832     }
833 
834     /**
835      * This method writes bytes to the message.
836      *
837      * This method will not resize the message. The given data to write (with @p aLength bytes) MUST fit within the
838      * existing message buffer (from the given offset @p aOffset up to the message's length).
839      *
840      * @param[in]  aOffset  Byte offset within the message to begin writing.
841      * @param[in]  aBuf     A pointer to a data buffer.
842      * @param[in]  aLength  Number of bytes to write.
843      *
844      */
845     void WriteBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength);
846 
847     /**
848      * This method writes bytes read from another or potentially the same message to the message at a given offset.
849      *
850      * This method will not resize the message. The bytes to write (with @p aLength) MUST fit within the existing
851      * message buffer (from the given @p aWriteOffset up to the message's length).
852      *
853      * This method can be used to copy bytes within the same message in either direction, i.e., copy forward where
854      * `aWriteOffset > aReadOffset` or copy backward where `aWriteOffset < aReadOffset`.
855      *
856      * @param[in] aWriteOffset  Byte offset within this message to begin writing.
857      * @param[in] aMessage      The message to read the bytes from.
858      * @param[in] aReadOffset   The offset in @p aMessage to start reading the bytes from.
859      * @param[in] aLength       The number of bytes to read from @p aMessage and write.
860      *
861      */
862     void WriteBytesFromMessage(uint16_t aWriteOffset, const Message &aMessage, uint16_t aReadOffset, uint16_t aLength);
863 
864     /**
865      * This methods writes an object to the message.
866      *
867      * This method will not resize the message. The entire given object (all its bytes) MUST fit within the existing
868      * message buffer (from the given offset @p aOffset up to the message's length).
869      *
870      * @tparam     ObjectType   The object type to write to the message.
871      *
872      * @param[in]  aOffset      Byte offset within the message to begin writing.
873      * @param[in]  aObject      A reference to the object to write.
874      *
875      */
Write(uint16_t aOffset,const ObjectType & aObject)876     template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject)
877     {
878         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
879 
880         WriteBytes(aOffset, &aObject, sizeof(ObjectType));
881     }
882 
883     /**
884      * This method writes bytes from a given `Data` instance to the message.
885      *
886      * This method will not resize the message. The given data to write MUST fit within the existing message buffer
887      * (from the given offset @p aOffset up to the message's length).
888      *
889      * @tparam     kDataLengthType   Determines the data length type (`uint8_t` or `uint16_t`).
890      *
891      * @param[in]  aOffset    Byte offset within the message to begin writing.
892      * @param[in]  aData      The `Data` to write to the message.
893      *
894      */
WriteData(uint16_t aOffset,const Data<kDataLengthType> & aData)895     template <DataLengthType kDataLengthType> void WriteData(uint16_t aOffset, const Data<kDataLengthType> &aData)
896     {
897         WriteBytes(aOffset, aData.GetBytes(), aData.GetLength());
898     }
899 
900     /**
901      * This method creates a copy of the message.
902      *
903      * It allocates the new message from the same message pool as the original one and copies @p aLength octets
904      * of the payload. The `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the
905      * cloned message are also copied from the original one.
906      *
907      * @param[in] aLength  Number of payload bytes to copy.
908      *
909      * @returns A pointer to the message or nullptr if insufficient message buffers are available.
910      *
911      */
912     Message *Clone(uint16_t aLength) const;
913 
914     /**
915      * This method creates a copy of the message.
916      *
917      * It allocates the new message from the same message pool as the original one and copies the entire payload. The
918      * `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
919      * copied from the original one.
920      *
921      * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
922      *
923      */
Clone(void) const924     Message *Clone(void) const { return Clone(GetLength()); }
925 
926     /**
927      * This method returns the datagram tag used for 6LoWPAN fragmentation or the identification used for IPv6
928      * fragmentation.
929      *
930      * @returns The 6LoWPAN datagram tag or the IPv6 fragment identification.
931      *
932      */
GetDatagramTag(void) const933     uint32_t GetDatagramTag(void) const { return GetMetadata().mDatagramTag; }
934 
935     /**
936      * This method sets the datagram tag used for 6LoWPAN fragmentation.
937      *
938      * @param[in]  aTag  The 6LoWPAN datagram tag.
939      *
940      */
SetDatagramTag(uint32_t aTag)941     void SetDatagramTag(uint32_t aTag) { GetMetadata().mDatagramTag = aTag; }
942 
943     /**
944      * This method returns whether or not the message forwarding is scheduled for the child.
945      *
946      * @param[in]  aChildIndex  The index into the child table.
947      *
948      * @retval TRUE   If the message is scheduled to be forwarded to the child.
949      * @retval FALSE  If the message is not scheduled to be forwarded to the child.
950      *
951      */
952     bool GetChildMask(uint16_t aChildIndex) const;
953 
954     /**
955      * This method unschedules forwarding of the message to the child.
956      *
957      * @param[in]  aChildIndex  The index into the child table.
958      *
959      */
960     void ClearChildMask(uint16_t aChildIndex);
961 
962     /**
963      * This method schedules forwarding of the message to the child.
964      *
965      * @param[in]  aChildIndex  The index into the child table.
966      *
967      */
968     void SetChildMask(uint16_t aChildIndex);
969 
970     /**
971      * This method returns whether or not the message forwarding is scheduled for at least one child.
972      *
973      * @retval TRUE   If message forwarding is scheduled for at least one child.
974      * @retval FALSE  If message forwarding is not scheduled for any child.
975      *
976      */
977     bool IsChildPending(void) const;
978 
979     /**
980      * This method returns the RLOC16 of the mesh destination.
981      *
982      * @note Only use this for non-link-local unicast messages.
983      *
984      * @returns The IEEE 802.15.4 Destination PAN ID.
985      *
986      */
GetMeshDest(void) const987     uint16_t GetMeshDest(void) const { return GetMetadata().mMeshDest; }
988 
989     /**
990      * This method sets the RLOC16 of the mesh destination.
991      *
992      * @note Only use this when sending non-link-local unicast messages.
993      *
994      * @param[in]  aMeshDest  The IEEE 802.15.4 Destination PAN ID.
995      *
996      */
SetMeshDest(uint16_t aMeshDest)997     void SetMeshDest(uint16_t aMeshDest) { GetMetadata().mMeshDest = aMeshDest; }
998 
999     /**
1000      * This method returns the IEEE 802.15.4 Destination PAN ID.
1001      *
1002      * @note Only use this when sending MLE Discover Request or Response messages.
1003      *
1004      * @returns The IEEE 802.15.4 Destination PAN ID.
1005      *
1006      */
GetPanId(void) const1007     uint16_t GetPanId(void) const { return GetMetadata().mPanId; }
1008 
1009     /**
1010      * This method sets the IEEE 802.15.4 Destination PAN ID.
1011      *
1012      * @note Only use this when sending MLE Discover Request or Response messages.
1013      *
1014      * @param[in]  aPanId  The IEEE 802.15.4 Destination PAN ID.
1015      *
1016      */
SetPanId(uint16_t aPanId)1017     void SetPanId(uint16_t aPanId) { GetMetadata().mPanId = aPanId; }
1018 
1019     /**
1020      * This method returns the IEEE 802.15.4 Channel to use for transmission.
1021      *
1022      * @note Only use this when sending MLE Announce messages.
1023      *
1024      * @returns The IEEE 802.15.4 Channel to use for transmission.
1025      *
1026      */
GetChannel(void) const1027     uint8_t GetChannel(void) const { return GetMetadata().mChannel; }
1028 
1029     /**
1030      * This method sets the IEEE 802.15.4 Channel to use for transmission.
1031      *
1032      * @note Only use this when sending MLE Announce messages.
1033      *
1034      * @param[in]  aChannel  The IEEE 802.15.4 Channel to use for transmission.
1035      *
1036      */
SetChannel(uint8_t aChannel)1037     void SetChannel(uint8_t aChannel) { GetMetadata().mChannel = aChannel; }
1038 
1039     /**
1040      * This method returns the message timestamp.
1041      *
1042      * @returns The message timestamp.
1043      *
1044      */
GetTimestamp(void) const1045     TimeMilli GetTimestamp(void) const { return GetMetadata().mTimestamp; }
1046 
1047     /**
1048      * This method sets the message timestamp to a given time.
1049      *
1050      * @param[in] aTimestamp   The timestamp value.
1051      *
1052      */
SetTimestamp(TimeMilli aTimestamp)1053     void SetTimestamp(TimeMilli aTimestamp) { GetMetadata().mTimestamp = aTimestamp; }
1054 
1055     /**
1056      * This method sets the message timestamp to the current time.
1057      *
1058      */
SetTimestampToNow(void)1059     void SetTimestampToNow(void) { SetTimestamp(TimerMilli::GetNow()); }
1060 
1061     /**
1062      * This method returns whether or not message forwarding is scheduled for direct transmission.
1063      *
1064      * @retval TRUE   If message forwarding is scheduled for direct transmission.
1065      * @retval FALSE  If message forwarding is not scheduled for direct transmission.
1066      *
1067      */
IsDirectTransmission(void) const1068     bool IsDirectTransmission(void) const { return GetMetadata().mDirectTx; }
1069 
1070     /**
1071      * This method unschedules forwarding using direct transmission.
1072      *
1073      */
ClearDirectTransmission(void)1074     void ClearDirectTransmission(void) { GetMetadata().mDirectTx = false; }
1075 
1076     /**
1077      * This method schedules forwarding using direct transmission.
1078      *
1079      */
SetDirectTransmission(void)1080     void SetDirectTransmission(void) { GetMetadata().mDirectTx = true; }
1081 
1082     /**
1083      * This method indicates whether the direct transmission of message was successful.
1084      *
1085      * @retval TRUE   If direct transmission of message was successful (all fragments were delivered and acked).
1086      * @retval FALSE  If direct transmission of message failed (at least one fragment failed).
1087      *
1088      */
GetTxSuccess(void) const1089     bool GetTxSuccess(void) const { return GetMetadata().mTxSuccess; }
1090 
1091     /**
1092      * This method sets whether the direct transmission of message was successful.
1093      *
1094      * @param[in] aTxSuccess   TRUE if the direct transmission is successful, FALSE otherwise (i.e., at least one
1095      *                         fragment transmission failed).
1096      *
1097      */
SetTxSuccess(bool aTxSuccess)1098     void SetTxSuccess(bool aTxSuccess) { GetMetadata().mTxSuccess = aTxSuccess; }
1099 
1100     /**
1101      * This method indicates whether the message may be evicted.
1102      *
1103      * @retval TRUE   If the message must not be evicted.
1104      * @retval FALSE  If the message may be evicted.
1105      *
1106      */
GetDoNotEvict(void) const1107     bool GetDoNotEvict(void) const { return GetMetadata().mDoNotEvict; }
1108 
1109     /**
1110      * This method sets whether the message may be evicted.
1111      *
1112      * @param[in]  aDoNotEvict  TRUE if the message may not be evicted, FALSE otherwise.
1113      *
1114      */
SetDoNotEvict(bool aDoNotEvict)1115     void SetDoNotEvict(bool aDoNotEvict) { GetMetadata().mDoNotEvict = aDoNotEvict; }
1116 
1117     /**
1118      * This method indicates whether the message is waiting for an address query resolution.
1119      *
1120      * @retval TRUE   If the message is waiting for address query resolution.
1121      * @retval FALSE  If the message is not waiting for address query resolution.
1122      *
1123      */
IsResolvingAddress(void) const1124     bool IsResolvingAddress(void) const { return GetMetadata().mResolvingAddress; }
1125 
1126     /**
1127      * This method sets whether the message is waiting for an address query resolution.
1128      *
1129      * @param[in] aResolvingAddress    TRUE if message is waiting for address resolution, FALSE otherwise.
1130      *
1131      */
SetResolvingAddress(bool aResolvingAddress)1132     void SetResolvingAddress(bool aResolvingAddress) { GetMetadata().mResolvingAddress = aResolvingAddress; }
1133 
1134     /**
1135      * This method indicates whether or not link security is enabled for the message.
1136      *
1137      * @retval TRUE   If link security is enabled.
1138      * @retval FALSE  If link security is not enabled.
1139      *
1140      */
IsLinkSecurityEnabled(void) const1141     bool IsLinkSecurityEnabled(void) const { return GetMetadata().mLinkSecurity; }
1142 
1143     /**
1144      * This method sets whether or not link security is enabled for the message.
1145      *
1146      * @param[in]  aEnabled  TRUE if link security is enabled, FALSE otherwise.
1147      *
1148      */
SetLinkSecurityEnabled(bool aEnabled)1149     void SetLinkSecurityEnabled(bool aEnabled) { GetMetadata().mLinkSecurity = aEnabled; }
1150 
1151     /**
1152      * This method updates the average RSS (Received Signal Strength) associated with the message by adding the given
1153      * RSS value to the average. Note that a message can be composed of multiple 802.15.4 data frame fragments each
1154      * received with a different signal strength.
1155      *
1156      * @param[in] aRss A new RSS value (in dBm) to be added to average.
1157      *
1158      */
AddRss(int8_t aRss)1159     void AddRss(int8_t aRss) { IgnoreError(GetMetadata().mRssAverager.Add(aRss)); }
1160 
1161     /**
1162      * This method returns the average RSS (Received Signal Strength) associated with the message.
1163      *
1164      * @returns The current average RSS value (in dBm) or `Radio::kInvalidRssi` if no average is available.
1165      *
1166      */
GetAverageRss(void) const1167     int8_t GetAverageRss(void) const { return GetMetadata().mRssAverager.GetAverage(); }
1168 
1169     /**
1170      * This method returns a const reference to RssAverager of the message.
1171      *
1172      * @returns A const reference to the RssAverager of the message.
1173      *
1174      */
GetRssAverager(void) const1175     const RssAverager &GetRssAverager(void) const { return GetMetadata().mRssAverager; }
1176 
1177 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1178     /**
1179      * This method updates the average LQI (Link Quality Indicator) associated with the message.
1180      *
1181      * The given LQI value would be added to the average. Note that a message can be composed of multiple 802.15.4
1182      * frame fragments each received with a different signal strength.
1183      *
1184      * @param[in] aLqi A new LQI value (has no unit) to be added to average.
1185      *
1186      */
AddLqi(uint8_t aLqi)1187     void AddLqi(uint8_t aLqi) { GetMetadata().mLqiAverager.Add(aLqi); }
1188 
1189     /**
1190      * This method returns the average LQI (Link Quality Indicator) associated with the message.
1191      *
1192      * @returns The current average LQI value (in dBm) or OT_RADIO_LQI_NONE if no average is available.
1193      *
1194      */
GetAverageLqi(void) const1195     uint8_t GetAverageLqi(void) const { return GetMetadata().mLqiAverager.GetAverage(); }
1196 
1197     /**
1198      * This method returns the count of frames counted so far.
1199      *
1200      * @returns The count of frames that have been counted.
1201      *
1202      */
GetPsduCount(void) const1203     uint8_t GetPsduCount(void) const { return GetMetadata().mLqiAverager.GetCount(); }
1204 #endif
1205 
1206     /**
1207      * This method sets the message's link info properties (PAN ID, link security, RSS) from a given `ThreadLinkInfo`.
1208      *
1209      * @param[in] aLinkInfo   The `ThreadLinkInfo` instance from which to set message's related properties.
1210      *
1211      */
1212     void SetLinkInfo(const ThreadLinkInfo &aLinkInfo);
1213 
1214     /**
1215      * This method returns a pointer to the message queue (if any) where this message is queued.
1216      *
1217      * @returns A pointer to the message queue or `nullptr` if not in any message queue.
1218      *
1219      */
GetMessageQueue(void) const1220     MessageQueue *GetMessageQueue(void) const
1221     {
1222         return !GetMetadata().mInPriorityQ ? static_cast<MessageQueue *>(GetMetadata().mQueue) : nullptr;
1223     }
1224 
1225     /**
1226      * This method returns a pointer to the priority message queue (if any) where this message is queued.
1227      *
1228      * @returns A pointer to the priority queue or `nullptr` if not in any priority queue.
1229      *
1230      */
GetPriorityQueue(void) const1231     PriorityQueue *GetPriorityQueue(void) const
1232     {
1233         return GetMetadata().mInPriorityQ ? static_cast<PriorityQueue *>(GetMetadata().mQueue) : nullptr;
1234     }
1235 
1236     /**
1237      * This method indicates whether or not the message is also used for time sync purpose.
1238      *
1239      * When OPENTHREAD_CONFIG_TIME_SYNC_ENABLE is 0, this method always return false.
1240      *
1241      * @retval TRUE   If the message is also used for time sync purpose.
1242      * @retval FALSE  If the message is not used for time sync purpose.
1243      *
1244      */
1245     bool IsTimeSync(void) const;
1246 
1247 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1248     /**
1249      * This method sets whether or not the message is also used for time sync purpose.
1250      *
1251      * @param[in]  aEnabled  TRUE if the message is also used for time sync purpose, FALSE otherwise.
1252      *
1253      */
SetTimeSync(bool aEnabled)1254     void SetTimeSync(bool aEnabled) { GetMetadata().mTimeSync = aEnabled; }
1255 
1256     /**
1257      * This method sets the offset to network time.
1258      *
1259      * @param[in]  aNetworkTimeOffset  The offset to network time.
1260      *
1261      */
SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1262     void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) { GetMetadata().mNetworkTimeOffset = aNetworkTimeOffset; }
1263 
1264     /**
1265      * This method gets the offset to network time.
1266      *
1267      * @returns  The offset to network time.
1268      *
1269      */
GetNetworkTimeOffset(void) const1270     int64_t GetNetworkTimeOffset(void) const { return GetMetadata().mNetworkTimeOffset; }
1271 
1272     /**
1273      * This method sets the time sync sequence.
1274      *
1275      * @param[in]  aTimeSyncSeq  The time sync sequence.
1276      *
1277      */
SetTimeSyncSeq(uint8_t aTimeSyncSeq)1278     void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { GetMetadata().mTimeSyncSeq = aTimeSyncSeq; }
1279 
1280     /**
1281      * This method gets the time sync sequence.
1282      *
1283      * @returns  The time sync sequence.
1284      *
1285      */
GetTimeSyncSeq(void) const1286     uint8_t GetTimeSyncSeq(void) const { return GetMetadata().mTimeSyncSeq; }
1287 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1288 
1289 #if OPENTHREAD_CONFIG_MULTI_RADIO
1290     /**
1291      * This method indicates whether the radio type is set.
1292      *
1293      * @retval TRUE   If the radio type is set.
1294      * @retval FALSE  If the radio type is not set.
1295      *
1296      */
IsRadioTypeSet(void) const1297     bool IsRadioTypeSet(void) const { return GetMetadata().mIsRadioTypeSet; }
1298 
1299     /**
1300      * This method gets the radio link type the message was received on, or should be sent on.
1301      *
1302      * This method should be used only when `IsRadioTypeSet()` returns `true`.
1303      *
1304      * @returns The radio link type of the message.
1305      *
1306      */
GetRadioType(void) const1307     Mac::RadioType GetRadioType(void) const { return static_cast<Mac::RadioType>(GetMetadata().mRadioType); }
1308 
1309     /**
1310      * This method sets the radio link type the message was received on, or should be sent on.
1311      *
1312      * @param[in] aRadioType   A radio link type of the message.
1313      *
1314      */
SetRadioType(Mac::RadioType aRadioType)1315     void SetRadioType(Mac::RadioType aRadioType)
1316     {
1317         GetMetadata().mIsRadioTypeSet = true;
1318         GetMetadata().mRadioType      = aRadioType;
1319     }
1320 
1321     /**
1322      * This method clears any previously set radio type on the message.
1323      *
1324      * After calling this method, `IsRadioTypeSet()` returns false until radio type is set (`SetRadioType()`).
1325      *
1326      */
ClearRadioType(void)1327     void ClearRadioType(void) { GetMetadata().mIsRadioTypeSet = false; }
1328 
1329 #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
1330 
1331 protected:
1332     class ConstIterator : public ItemPtrIterator<const Message, ConstIterator>
1333     {
1334         friend class ItemPtrIterator<const Message, ConstIterator>;
1335 
1336     public:
1337         ConstIterator(void) = default;
1338 
ConstIterator(const Message * aMessage)1339         explicit ConstIterator(const Message *aMessage)
1340             : ItemPtrIterator(aMessage)
1341         {
1342         }
1343 
1344     private:
Advance(void)1345         void Advance(void) { mItem = mItem->GetNext(); }
1346     };
1347 
1348     class Iterator : public ItemPtrIterator<Message, Iterator>
1349     {
1350         friend class ItemPtrIterator<Message, Iterator>;
1351 
1352     public:
Iterator(void)1353         Iterator(void)
1354             : mNext(nullptr)
1355         {
1356         }
1357 
Iterator(Message * aMessage)1358         explicit Iterator(Message *aMessage)
1359             : ItemPtrIterator(aMessage)
1360             , mNext(NextMessage(aMessage))
1361         {
1362         }
1363 
1364     private:
1365         void            Advance(void);
NextMessage(Message * aMessage)1366         static Message *NextMessage(Message *aMessage) { return (aMessage != nullptr) ? aMessage->GetNext() : nullptr; }
1367 
1368         Message *mNext;
1369     };
1370 
GetReserved(void) const1371     uint16_t GetReserved(void) const { return GetMetadata().mReserved; }
SetReserved(uint16_t aReservedHeader)1372     void     SetReserved(uint16_t aReservedHeader) { GetMetadata().mReserved = aReservedHeader; }
1373 
1374 private:
1375     class Chunk : public Data<kWithUint16Length>
1376     {
1377     public:
GetBuffer(void) const1378         const Buffer *GetBuffer(void) const { return mBuffer; }
SetBuffer(const Buffer * aBuffer)1379         void          SetBuffer(const Buffer *aBuffer) { mBuffer = aBuffer; }
1380 
1381     private:
1382         const Buffer *mBuffer; // Buffer containing the chunk
1383     };
1384 
1385     class MutableChunk : public Chunk
1386     {
1387     public:
GetBytes(void)1388         uint8_t *GetBytes(void) { return AsNonConst(Chunk::GetBytes()); }
1389     };
1390 
1391     void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, Chunk &aChunk) const;
1392     void GetNextChunk(uint16_t &aLength, Chunk &aChunk) const;
1393 
GetFirstChunk(uint16_t aOffset,uint16_t & aLength,MutableChunk & aChunk)1394     void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, MutableChunk &aChunk)
1395     {
1396         AsConst(this)->GetFirstChunk(aOffset, aLength, static_cast<Chunk &>(aChunk));
1397     }
1398 
GetNextChunk(uint16_t & aLength,MutableChunk & aChunk)1399     void GetNextChunk(uint16_t &aLength, MutableChunk &aChunk)
1400     {
1401         AsConst(this)->GetNextChunk(aLength, static_cast<Chunk &>(aChunk));
1402     }
1403 
GetMessagePool(void) const1404     MessagePool *GetMessagePool(void) const { return GetMetadata().mMessagePool; }
SetMessagePool(MessagePool * aMessagePool)1405     void         SetMessagePool(MessagePool *aMessagePool) { GetMetadata().mMessagePool = aMessagePool; }
1406 
IsInAQueue(void) const1407     bool IsInAQueue(void) const { return (GetMetadata().mQueue != nullptr); }
1408     void SetMessageQueue(MessageQueue *aMessageQueue);
1409     void SetPriorityQueue(PriorityQueue *aPriorityQueue);
1410 
Next(void)1411     Message       *&Next(void) { return GetMetadata().mNext; }
Next(void) const1412     Message *const &Next(void) const { return GetMetadata().mNext; }
Prev(void)1413     Message       *&Prev(void) { return GetMetadata().mPrev; }
1414 
NextOf(Message * aMessage)1415     static Message       *NextOf(Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; }
NextOf(const Message * aMessage)1416     static const Message *NextOf(const Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; }
1417 
1418     Error ResizeMessage(uint16_t aLength);
1419 };
1420 
1421 /**
1422  * This class implements a message queue.
1423  *
1424  */
1425 class MessageQueue : public otMessageQueue
1426 {
1427     friend class Message;
1428     friend class PriorityQueue;
1429 
1430 public:
1431     typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue.
1432 
1433     /**
1434      * This enumeration represents a position (head or tail) in the queue. This is used to specify where a new message
1435      * should be added in the queue.
1436      *
1437      */
1438     enum QueuePosition : uint8_t
1439     {
1440         kQueuePositionHead, ///< Indicates the head (front) of the list.
1441         kQueuePositionTail, ///< Indicates the tail (end) of the list.
1442     };
1443 
1444     /**
1445      * This constructor initializes the message queue.
1446      *
1447      */
MessageQueue(void)1448     MessageQueue(void) { SetTail(nullptr); }
1449 
1450     /**
1451      * This method returns a pointer to the first message.
1452      *
1453      * @returns A pointer to the first message.
1454      *
1455      */
GetHead(void)1456     Message *GetHead(void) { return Message::NextOf(GetTail()); }
1457 
1458     /**
1459      * This method returns a pointer to the first message.
1460      *
1461      * @returns A pointer to the first message.
1462      *
1463      */
GetHead(void) const1464     const Message *GetHead(void) const { return Message::NextOf(GetTail()); }
1465 
1466     /**
1467      * This method adds a message to the end of the list.
1468      *
1469      * @param[in]  aMessage  The message to add.
1470      *
1471      */
Enqueue(Message & aMessage)1472     void Enqueue(Message &aMessage) { Enqueue(aMessage, kQueuePositionTail); }
1473 
1474     /**
1475      * This method adds a message at a given position (head/tail) of the list.
1476      *
1477      * @param[in]  aMessage  The message to add.
1478      * @param[in]  aPosition The position (head or tail) where to add the message.
1479      *
1480      */
1481     void Enqueue(Message &aMessage, QueuePosition aPosition);
1482 
1483     /**
1484      * This method removes a message from the list.
1485      *
1486      * @param[in]  aMessage  The message to remove.
1487      *
1488      */
1489     void Dequeue(Message &aMessage);
1490 
1491     /**
1492      * This method removes a message from the queue and frees it.
1493      *
1494      * @param[in]  aMessage  The message to remove and free.
1495      *
1496      */
1497     void DequeueAndFree(Message &aMessage);
1498 
1499     /**
1500      * This method removes and frees all messages from the queue.
1501      *
1502      */
1503     void DequeueAndFreeAll(void);
1504 
1505     /**
1506      * This method gets the information about number of messages and buffers in the queue.
1507      *
1508      * This method updates `aInfo` and adds number of message/buffers in the message queue to the corresponding member
1509      * variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method (e.g.,
1510      * clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues to add
1511      * up the number of messages/buffers on different queues.
1512      *
1513      * @param[out] aInfo  A reference to `Info` structure to update.ni
1514      *
1515      */
1516     void GetInfo(Info &aInfo) const;
1517 
1518     // The following methods are intended to support range-based `for`
1519     // loop iteration over the queue entries and should not be used
1520     // directly. The range-based `for` works correctly even if the
1521     // current entry is removed from the queue during iteration.
1522 
1523     Message::Iterator begin(void);
end(void)1524     Message::Iterator end(void) { return Message::Iterator(); }
1525 
1526     Message::ConstIterator begin(void) const;
end(void) const1527     Message::ConstIterator end(void) const { return Message::ConstIterator(); }
1528 
1529 private:
GetTail(void)1530     Message       *GetTail(void) { return static_cast<Message *>(mData); }
GetTail(void) const1531     const Message *GetTail(void) const { return static_cast<const Message *>(mData); }
SetTail(Message * aMessage)1532     void           SetTail(Message *aMessage) { mData = aMessage; }
1533 };
1534 
1535 /**
1536  * This class implements a priority queue.
1537  *
1538  */
1539 class PriorityQueue : private Clearable<PriorityQueue>
1540 {
1541     friend class Message;
1542     friend class MessageQueue;
1543     friend class MessagePool;
1544     friend class Clearable<PriorityQueue>;
1545 
1546 public:
1547     typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue.
1548 
1549     /**
1550      * This constructor initializes the priority queue.
1551      *
1552      */
PriorityQueue(void)1553     PriorityQueue(void) { Clear(); }
1554 
1555     /**
1556      * This method returns a pointer to the first message.
1557      *
1558      * @returns A pointer to the first message.
1559      *
1560      */
GetHead(void)1561     Message *GetHead(void) { return AsNonConst(AsConst(this)->GetHead()); }
1562 
1563     /**
1564      * This method returns a pointer to the first message.
1565      *
1566      * @returns A pointer to the first message.
1567      *
1568      */
1569     const Message *GetHead(void) const;
1570 
1571     /**
1572      * This method returns a pointer to the first message for a given priority level.
1573      *
1574      * @param[in] aPriority   Priority level.
1575      *
1576      * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with
1577      *          this priority level.
1578      *
1579      */
GetHeadForPriority(Message::Priority aPriority)1580     Message *GetHeadForPriority(Message::Priority aPriority)
1581     {
1582         return AsNonConst(AsConst(this)->GetHeadForPriority(aPriority));
1583     }
1584 
1585     /**
1586      * This method returns a pointer to the first message for a given priority level.
1587      *
1588      * @param[in] aPriority   Priority level.
1589      *
1590      * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with
1591      *          this priority level.
1592      *
1593      */
1594     const Message *GetHeadForPriority(Message::Priority aPriority) const;
1595 
1596     /**
1597      * This method adds a message to the queue.
1598      *
1599      * @param[in]  aMessage  The message to add.
1600      *
1601      */
1602     void Enqueue(Message &aMessage);
1603 
1604     /**
1605      * This method removes a message from the list.
1606      *
1607      * @param[in]  aMessage  The message to remove.
1608      *
1609      */
1610     void Dequeue(Message &aMessage);
1611 
1612     /**
1613      * This method removes a message from the queue and frees it.
1614      *
1615      * @param[in]  aMessage  The message to remove and free.
1616      *
1617      */
1618     void DequeueAndFree(Message &aMessage);
1619 
1620     /**
1621      * This method removes and frees all messages from the queue.
1622      *
1623      */
1624     void DequeueAndFreeAll(void);
1625 
1626     /**
1627      * This method returns the tail of the list (last message in the list).
1628      *
1629      * @returns A pointer to the tail of the list.
1630      *
1631      */
GetTail(void)1632     Message *GetTail(void) { return AsNonConst(AsConst(this)->GetTail()); }
1633 
1634     /**
1635      * This method returns the tail of the list (last message in the list).
1636      *
1637      * @returns A pointer to the tail of the list.
1638      *
1639      */
1640     const Message *GetTail(void) const;
1641 
1642     /**
1643      * This method gets the information about number of messages and buffers in the priority queue.
1644      *
1645      * This method updates `aInfo` array and adds number of message/buffers in the message queue to the corresponding
1646      * member variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method
1647      * (e.g., clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues
1648      * to add up the number of messages/buffers on different queues.
1649      *
1650      * @param[out] aInfo  A reference to an `Info` structure to update.
1651      *
1652      */
1653     void GetInfo(Info &aInfo) const;
1654 
1655     // The following methods are intended to support range-based `for`
1656     // loop iteration over the queue entries and should not be used
1657     // directly. The range-based `for` works correctly even if the
1658     // current entry is removed from the queue during iteration.
1659 
1660     Message::Iterator begin(void);
end(void)1661     Message::Iterator end(void) { return Message::Iterator(); }
1662 
1663     Message::ConstIterator begin(void) const;
end(void) const1664     Message::ConstIterator end(void) const { return Message::ConstIterator(); }
1665 
1666 private:
PrevPriority(uint8_t aPriority) const1667     uint8_t PrevPriority(uint8_t aPriority) const
1668     {
1669         return (aPriority == Message::kNumPriorities - 1) ? 0 : (aPriority + 1);
1670     }
1671 
1672     const Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const;
1673 
FindFirstNonNullTail(Message::Priority aStartPriorityLevel)1674     Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel)
1675     {
1676         return AsNonConst(AsConst(this)->FindFirstNonNullTail(aStartPriorityLevel));
1677     }
1678 
1679     Message *mTails[Message::kNumPriorities]; // Tail pointers associated with different priority levels.
1680 };
1681 
1682 /**
1683  * This class represents a message pool
1684  *
1685  */
1686 class MessagePool : public InstanceLocator, private NonCopyable
1687 {
1688     friend class Message;
1689     friend class MessageQueue;
1690     friend class PriorityQueue;
1691 
1692 public:
1693     /**
1694      * This constructor initializes the object.
1695      *
1696      */
1697     explicit MessagePool(Instance &aInstance);
1698 
1699     /**
1700      * This method allocates a new message with specified settings.
1701      *
1702      * @param[in]  aType           The message type.
1703      * @param[in]  aReserveHeader  The number of header bytes to reserve.
1704      * @param[in]  aSettings       The message settings.
1705      *
1706      * @returns A pointer to the message or `nullptr` if no message buffers are available.
1707      *
1708      */
1709     Message *Allocate(Message::Type aType, uint16_t aReserveHeader, const Message::Settings &aSettings);
1710 
1711     /**
1712      * This method allocates a new message of a given type using default settings.
1713      *
1714      * @param[in]  aType           The message type.
1715      *
1716      * @returns A pointer to the message or `nullptr` if no message buffers are available.
1717      *
1718      */
1719     Message *Allocate(Message::Type aType);
1720 
1721     /**
1722      * This method allocates a new message with a given type and reserved length using default settings.
1723      *
1724      * @param[in]  aType           The message type.
1725      * @param[in]  aReserveHeader  The number of header bytes to reserve.
1726      *
1727      * @returns A pointer to the message or `nullptr` if no message buffers are available.
1728      *
1729      */
1730     Message *Allocate(Message::Type aType, uint16_t aReserveHeader);
1731 
1732     /**
1733      * This method is used to free a message and return all message buffers to the buffer pool.
1734      *
1735      * @param[in]  aMessage  The message to free.
1736      *
1737      */
1738     void Free(Message *aMessage);
1739 
1740     /**
1741      * This method returns the number of free buffers.
1742      *
1743      * @returns The number of free buffers, or 0xffff (UINT16_MAX) if number is unknown.
1744      *
1745      */
1746     uint16_t GetFreeBufferCount(void) const;
1747 
1748     /**
1749      * This method returns the total number of buffers.
1750      *
1751      * @returns The total number of buffers, or 0xffff (UINT16_MAX) if number is unknown.
1752      *
1753      */
1754     uint16_t GetTotalBufferCount(void) const;
1755 
1756     /**
1757      * This method returns the maximum number of buffers in use at the same time since OT stack initialization or
1758      * since last call to `ResetMaxUsedBufferCount()`.
1759      *
1760      * @returns The maximum number of buffers in use at the same time so far (buffer allocation watermark).
1761      *
1762      */
GetMaxUsedBufferCount(void) const1763     uint16_t GetMaxUsedBufferCount(void) const { return mMaxAllocated; }
1764 
1765     /**
1766      * This method resets the tracked maximum number of buffers in use.
1767      *
1768      * @sa GetMaxUsedBufferCount
1769      *
1770      */
ResetMaxUsedBufferCount(void)1771     void ResetMaxUsedBufferCount(void) { mMaxAllocated = mNumAllocated; }
1772 
1773 private:
1774     Buffer *NewBuffer(Message::Priority aPriority);
1775     void    FreeBuffers(Buffer *aBuffer);
1776     Error   ReclaimBuffers(Message::Priority aPriority);
1777 
1778 #if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
1779     Pool<Buffer, kNumBuffers> mBufferPool;
1780 #endif
1781     uint16_t mNumAllocated;
1782     uint16_t mMaxAllocated;
1783 };
1784 
GetInstance(void) const1785 inline Instance &Message::GetInstance(void) const { return GetMessagePool()->GetInstance(); }
1786 
1787 /**
1788  * @}
1789  *
1790  */
1791 
1792 DefineCoreType(otMessageBuffer, Buffer);
1793 DefineCoreType(otMessageSettings, Message::Settings);
1794 DefineCoreType(otMessage, Message);
1795 DefineCoreType(otMessageQueue, MessageQueue);
1796 
1797 } // namespace ot
1798 
1799 #endif // MESSAGE_HPP_
1800