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