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