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