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