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