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