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 bool mAllowLookbackToHost : 1; // Whether the message is allowed to be looped back to host.
221 uint8_t mOrigin : 2; // 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 * Appends bytes to the end of the message.
671 *
672 * On success, this method grows the message by @p aLength bytes.
673 *
674 * @param[in] aBuf A pointer to a data buffer (MUST not be `nullptr`).
675 * @param[in] aLength The number of bytes to append.
676 *
677 * @retval kErrorNone Successfully appended the bytes.
678 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
679 *
680 */
681 Error AppendBytes(const void *aBuf, uint16_t aLength);
682
683 /**
684 * Appends bytes read from another or potentially the same message to the end of the current message.
685 *
686 * On success, this method grows the message by @p aLength bytes.
687 *
688 * @param[in] aMessage The message to read the bytes from (it can be the same as the current message).
689 * @param[in] aOffset The offset in @p aMessage to start reading the bytes from.
690 * @param[in] aLength The number of bytes to read from @p aMessage and append.
691 *
692 * @retval kErrorNone Successfully appended the bytes.
693 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
694 * @retval kErrorParse Not enough bytes in @p aMessage to read @p aLength bytes from @p aOffset.
695 *
696 */
697 Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
698
699 /**
700 * Appends an object to the end of the message.
701 *
702 * On success, this method grows the message by the size of the appended object
703 *
704 * @tparam ObjectType The object type to append to the message.
705 *
706 * @param[in] aObject A reference to the object to append to the message.
707 *
708 * @retval kErrorNone Successfully appended the object.
709 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
710 *
711 */
Append(const ObjectType & aObject)712 template <typename ObjectType> Error Append(const ObjectType &aObject)
713 {
714 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
715
716 return AppendBytes(&aObject, sizeof(ObjectType));
717 }
718
719 /**
720 * Appends bytes from a given `Data` instance to the end of the message.
721 *
722 * On success, this method grows the message by the size of the appended data.
723 *
724 * @tparam kDataLengthType Determines the data length type (`uint8_t` or `uint16_t`).
725 *
726 * @param[in] aData A reference to `Data` to append to the message.
727 *
728 * @retval kErrorNone Successfully appended the bytes from @p aData.
729 * @retval kErrorNoBufs Insufficient available buffers to grow the message.
730 *
731 */
AppendData(const Data<kDataLengthType> & aData)732 template <DataLengthType kDataLengthType> Error AppendData(const Data<kDataLengthType> &aData)
733 {
734 return AppendBytes(aData.GetBytes(), aData.GetLength());
735 }
736
737 /**
738 * Reads bytes from the message.
739 *
740 * @param[in] aOffset Byte offset within the message to begin reading.
741 * @param[out] aBuf A pointer to a data buffer to copy the read bytes into.
742 * @param[in] aLength Number of bytes to read.
743 *
744 * @returns The number of bytes read.
745 *
746 */
747 uint16_t ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
748
749 /**
750 * Reads a given number of bytes from the message.
751 *
752 * If there are fewer bytes available in the message than the requested read length, the available bytes will be
753 * read and copied into @p aBuf. In this case `kErrorParse` will be returned.
754 *
755 * @param[in] aOffset Byte offset within the message to begin reading.
756 * @param[out] aBuf A pointer to a data buffer to copy the read bytes into.
757 * @param[in] aLength Number of bytes to read.
758 *
759 * @retval kErrorNone @p aLength bytes were successfully read from message.
760 * @retval kErrorParse Not enough bytes remaining in message to read the entire object.
761 *
762 */
763 Error Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
764
765 /**
766 * Reads an object from the message.
767 *
768 * If there are fewer bytes available in the message than the requested object size, the available bytes will be
769 * read and copied into @p aObject (@p aObject will be read partially). In this case `kErrorParse` will
770 * be returned.
771 *
772 * @tparam ObjectType The object type to read from the message.
773 *
774 * @param[in] aOffset Byte offset within the message to begin reading.
775 * @param[out] aObject A reference to the object to read into.
776 *
777 * @retval kErrorNone Object @p aObject was successfully read from message.
778 * @retval kErrorParse Not enough bytes remaining in message to read the entire object.
779 *
780 */
Read(uint16_t aOffset,ObjectType & aObject) const781 template <typename ObjectType> Error Read(uint16_t aOffset, ObjectType &aObject) const
782 {
783 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
784
785 return Read(aOffset, &aObject, sizeof(ObjectType));
786 }
787
788 /**
789 * Compares the bytes in the message at a given offset with a given byte array.
790 *
791 * If there are fewer bytes available in the message than the requested @p aLength, the comparison is treated as
792 * failure (returns FALSE).
793 *
794 * @param[in] aOffset Byte offset within the message to read from for the comparison.
795 * @param[in] aBuf A pointer to a data buffer to compare with the bytes from message.
796 * @param[in] aLength Number of bytes in @p aBuf.
797 * @param[in] aMatcher A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are directly
798 * compared.
799 *
800 * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf,
801 * FALSE otherwise.
802 *
803 */
804 bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher = nullptr) const;
805
806 /**
807 * Compares the bytes in the message at a given offset with bytes read from another message.
808 *
809 * If either message has fewer bytes available than the requested @p aLength, the comparison is treated as failure
810 * (returns FALSE).
811 *
812 * @param[in] aOffset Byte offset within the message to read from for the comparison.
813 * @param[in] aOtherMessage The other message to compare with.
814 * @param[in] aOtherOffset Byte offset within @p aOtherMessage to read from for the comparison.
815 * @param[in] aLength Number of bytes to compare.
816 * @param[in] aMatcher A `ByteMatcher` function pointer to match the bytes. If `nullptr` then bytes are
817 * directly compared.
818 *
819 * @returns TRUE if there are enough bytes available in both messages and they all match. FALSE otherwise.
820 *
821 */
822 bool CompareBytes(uint16_t aOffset,
823 const Message &aOtherMessage,
824 uint16_t aOtherOffset,
825 uint16_t aLength,
826 ByteMatcher aMatcher = nullptr) const;
827
828 /**
829 * Compares the bytes in the message at a given offset with an object.
830 *
831 * The bytes in the message are compared with the bytes in @p aObject. If there are fewer bytes available in the
832 * message than the requested object size, it is treated as failed comparison (returns FALSE).
833 *
834 * @tparam ObjectType The object type to compare with the bytes in message.
835 *
836 * @param[in] aOffset Byte offset within the message to read from for the comparison.
837 * @param[in] aObject A reference to the object to compare with the message bytes.
838 *
839 * @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes in @p aObject,
840 * FALSE otherwise.
841 *
842 */
Compare(uint16_t aOffset,const ObjectType & aObject) const843 template <typename ObjectType> bool Compare(uint16_t aOffset, const ObjectType &aObject) const
844 {
845 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
846
847 return CompareBytes(aOffset, &aObject, sizeof(ObjectType));
848 }
849
850 /**
851 * Writes bytes to the message.
852 *
853 * Will not resize the message. The given data to write (with @p aLength bytes) MUST fit within the
854 * existing message buffer (from the given offset @p aOffset up to the message's length).
855 *
856 * @param[in] aOffset Byte offset within the message to begin writing.
857 * @param[in] aBuf A pointer to a data buffer.
858 * @param[in] aLength Number of bytes to write.
859 *
860 */
861 void WriteBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength);
862
863 /**
864 * Writes bytes read from another or potentially the same message to the message at a given offset.
865 *
866 * Will not resize the message. The bytes to write (with @p aLength) MUST fit within the existing
867 * message buffer (from the given @p aWriteOffset up to the message's length).
868 *
869 * Can be used to copy bytes within the same message in either direction, i.e., copy forward where
870 * `aWriteOffset > aReadOffset` or copy backward where `aWriteOffset < aReadOffset`.
871 *
872 * @param[in] aWriteOffset Byte offset within this message to begin writing.
873 * @param[in] aMessage The message to read the bytes from.
874 * @param[in] aReadOffset The offset in @p aMessage to start reading the bytes from.
875 * @param[in] aLength The number of bytes to read from @p aMessage and write.
876 *
877 */
878 void WriteBytesFromMessage(uint16_t aWriteOffset, const Message &aMessage, uint16_t aReadOffset, uint16_t aLength);
879
880 /**
881 * Writes an object to the message.
882 *
883 * Will not resize the message. The entire given object (all its bytes) MUST fit within the existing
884 * message buffer (from the given offset @p aOffset up to the message's length).
885 *
886 * @tparam ObjectType The object type to write to the message.
887 *
888 * @param[in] aOffset Byte offset within the message to begin writing.
889 * @param[in] aObject A reference to the object to write.
890 *
891 */
Write(uint16_t aOffset,const ObjectType & aObject)892 template <typename ObjectType> void Write(uint16_t aOffset, const ObjectType &aObject)
893 {
894 static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
895
896 WriteBytes(aOffset, &aObject, sizeof(ObjectType));
897 }
898
899 /**
900 * Writes bytes from a given `Data` instance to the message.
901 *
902 * Will not resize the message. The given data to write MUST fit within the existing message buffer
903 * (from the given offset @p aOffset up to the message's length).
904 *
905 * @tparam kDataLengthType Determines the data length type (`uint8_t` or `uint16_t`).
906 *
907 * @param[in] aOffset Byte offset within the message to begin writing.
908 * @param[in] aData The `Data` to write to the message.
909 *
910 */
WriteData(uint16_t aOffset,const Data<kDataLengthType> & aData)911 template <DataLengthType kDataLengthType> void WriteData(uint16_t aOffset, const Data<kDataLengthType> &aData)
912 {
913 WriteBytes(aOffset, aData.GetBytes(), aData.GetLength());
914 }
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 @p aLength octets
920 * of the payload. The `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the
921 * cloned message are also copied from the original one.
922 *
923 * @param[in] aLength Number of payload bytes to copy.
924 *
925 * @returns A pointer to the message or nullptr if insufficient message buffers are available.
926 *
927 */
928 Message *Clone(uint16_t aLength) const;
929
930 /**
931 * Creates a copy of the message.
932 *
933 * It allocates the new message from the same message pool as the original one and copies the entire payload. The
934 * `Type`, `SubType`, `LinkSecurity`, `Offset`, `InterfaceId`, and `Priority` fields on the cloned message are also
935 * copied from the original one.
936 *
937 * @returns A pointer to the message or `nullptr` if insufficient message buffers are available.
938 *
939 */
Clone(void) const940 Message *Clone(void) const { return Clone(GetLength()); }
941
942 /**
943 * Returns the datagram tag used for 6LoWPAN fragmentation or the identification used for IPv6
944 * fragmentation.
945 *
946 * @returns The 6LoWPAN datagram tag or the IPv6 fragment identification.
947 *
948 */
GetDatagramTag(void) const949 uint32_t GetDatagramTag(void) const { return GetMetadata().mDatagramTag; }
950
951 /**
952 * Sets the datagram tag used for 6LoWPAN fragmentation.
953 *
954 * @param[in] aTag The 6LoWPAN datagram tag.
955 *
956 */
SetDatagramTag(uint32_t aTag)957 void SetDatagramTag(uint32_t aTag) { GetMetadata().mDatagramTag = aTag; }
958
959 #if OPENTHREAD_FTD
960 /**
961 * Returns whether or not the message forwarding is scheduled for the child.
962 *
963 * @param[in] aChildIndex The index into the child table.
964 *
965 * @retval TRUE If the message is scheduled to be forwarded to the child.
966 * @retval FALSE If the message is not scheduled to be forwarded to the child.
967 *
968 */
969 bool GetChildMask(uint16_t aChildIndex) const;
970
971 /**
972 * Unschedules forwarding of the message to the child.
973 *
974 * @param[in] aChildIndex The index into the child table.
975 *
976 */
977 void ClearChildMask(uint16_t aChildIndex);
978
979 /**
980 * Schedules forwarding of the message to the child.
981 *
982 * @param[in] aChildIndex The index into the child table.
983 *
984 */
985 void SetChildMask(uint16_t aChildIndex);
986
987 /**
988 * Returns whether or not the message forwarding is scheduled for at least one child.
989 *
990 * @retval TRUE If message forwarding is scheduled for at least one child.
991 * @retval FALSE If message forwarding is not scheduled for any child.
992 *
993 */
994 bool IsChildPending(void) const;
995 #endif // OPENTHREAD_FTD
996
997 /**
998 * Returns the RLOC16 of the mesh destination.
999 *
1000 * @note Only use this for non-link-local unicast messages.
1001 *
1002 * @returns The IEEE 802.15.4 Destination PAN ID.
1003 *
1004 */
GetMeshDest(void) const1005 uint16_t GetMeshDest(void) const { return GetMetadata().mMeshDest; }
1006
1007 /**
1008 * Sets the RLOC16 of the mesh destination.
1009 *
1010 * @note Only use this when sending non-link-local unicast messages.
1011 *
1012 * @param[in] aMeshDest The IEEE 802.15.4 Destination PAN ID.
1013 *
1014 */
SetMeshDest(uint16_t aMeshDest)1015 void SetMeshDest(uint16_t aMeshDest) { GetMetadata().mMeshDest = aMeshDest; }
1016
1017 /**
1018 * Returns the IEEE 802.15.4 Destination PAN ID.
1019 *
1020 * @note Only use this when sending MLE Discover Request or Response messages.
1021 *
1022 * @returns The IEEE 802.15.4 Destination PAN ID.
1023 *
1024 */
GetPanId(void) const1025 uint16_t GetPanId(void) const { return GetMetadata().mPanId; }
1026
1027 /**
1028 * Sets the IEEE 802.15.4 Destination PAN ID.
1029 *
1030 * @note Only use this when sending MLE Discover Request or Response messages.
1031 *
1032 * @param[in] aPanId The IEEE 802.15.4 Destination PAN ID.
1033 *
1034 */
SetPanId(uint16_t aPanId)1035 void SetPanId(uint16_t aPanId) { GetMetadata().mPanId = aPanId; }
1036
1037 /**
1038 * Returns the IEEE 802.15.4 Channel to use for transmission.
1039 *
1040 * @note Only use this when sending MLE Announce messages.
1041 *
1042 * @returns The IEEE 802.15.4 Channel to use for transmission.
1043 *
1044 */
GetChannel(void) const1045 uint8_t GetChannel(void) const { return GetMetadata().mChannel; }
1046
1047 /**
1048 * Sets the IEEE 802.15.4 Channel to use for transmission.
1049 *
1050 * @note Only use this when sending MLE Announce messages.
1051 *
1052 * @param[in] aChannel The IEEE 802.15.4 Channel to use for transmission.
1053 *
1054 */
SetChannel(uint8_t aChannel)1055 void SetChannel(uint8_t aChannel) { GetMetadata().mChannel = aChannel; }
1056
1057 /**
1058 * Returns the message timestamp.
1059 *
1060 * @returns The message timestamp.
1061 *
1062 */
GetTimestamp(void) const1063 TimeMilli GetTimestamp(void) const { return GetMetadata().mTimestamp; }
1064
1065 /**
1066 * Sets the message timestamp to a given time.
1067 *
1068 * @param[in] aTimestamp The timestamp value.
1069 *
1070 */
SetTimestamp(TimeMilli aTimestamp)1071 void SetTimestamp(TimeMilli aTimestamp) { GetMetadata().mTimestamp = aTimestamp; }
1072
1073 /**
1074 * Sets the message timestamp to the current time.
1075 *
1076 */
SetTimestampToNow(void)1077 void SetTimestampToNow(void) { SetTimestamp(TimerMilli::GetNow()); }
1078
1079 /**
1080 * Returns whether or not message forwarding is scheduled for direct transmission.
1081 *
1082 * @retval TRUE If message forwarding is scheduled for direct transmission.
1083 * @retval FALSE If message forwarding is not scheduled for direct transmission.
1084 *
1085 */
IsDirectTransmission(void) const1086 bool IsDirectTransmission(void) const { return GetMetadata().mDirectTx; }
1087
1088 /**
1089 * Unschedules forwarding using direct transmission.
1090 *
1091 */
ClearDirectTransmission(void)1092 void ClearDirectTransmission(void) { GetMetadata().mDirectTx = false; }
1093
1094 /**
1095 * Schedules forwarding using direct transmission.
1096 *
1097 */
SetDirectTransmission(void)1098 void SetDirectTransmission(void) { GetMetadata().mDirectTx = true; }
1099
1100 /**
1101 * Indicates whether the direct transmission of message was successful.
1102 *
1103 * @retval TRUE If direct transmission of message was successful (all fragments were delivered and acked).
1104 * @retval FALSE If direct transmission of message failed (at least one fragment failed).
1105 *
1106 */
GetTxSuccess(void) const1107 bool GetTxSuccess(void) const { return GetMetadata().mTxSuccess; }
1108
1109 /**
1110 * Sets whether the direct transmission of message was successful.
1111 *
1112 * @param[in] aTxSuccess TRUE if the direct transmission is successful, FALSE otherwise (i.e., at least one
1113 * fragment transmission failed).
1114 *
1115 */
SetTxSuccess(bool aTxSuccess)1116 void SetTxSuccess(bool aTxSuccess) { GetMetadata().mTxSuccess = aTxSuccess; }
1117
1118 /**
1119 * Indicates whether the message may be evicted.
1120 *
1121 * @retval TRUE If the message must not be evicted.
1122 * @retval FALSE If the message may be evicted.
1123 *
1124 */
GetDoNotEvict(void) const1125 bool GetDoNotEvict(void) const { return GetMetadata().mDoNotEvict; }
1126
1127 /**
1128 * Sets whether the message may be evicted.
1129 *
1130 * @param[in] aDoNotEvict TRUE if the message may not be evicted, FALSE otherwise.
1131 *
1132 */
SetDoNotEvict(bool aDoNotEvict)1133 void SetDoNotEvict(bool aDoNotEvict) { GetMetadata().mDoNotEvict = aDoNotEvict; }
1134
1135 /**
1136 * Indicates whether the message is waiting for an address query resolution.
1137 *
1138 * @retval TRUE If the message is waiting for address query resolution.
1139 * @retval FALSE If the message is not waiting for address query resolution.
1140 *
1141 */
IsResolvingAddress(void) const1142 bool IsResolvingAddress(void) const { return GetMetadata().mResolvingAddress; }
1143
1144 /**
1145 * Sets whether the message is waiting for an address query resolution.
1146 *
1147 * @param[in] aResolvingAddress TRUE if message is waiting for address resolution, FALSE otherwise.
1148 *
1149 */
SetResolvingAddress(bool aResolvingAddress)1150 void SetResolvingAddress(bool aResolvingAddress) { GetMetadata().mResolvingAddress = aResolvingAddress; }
1151
1152 /**
1153 * Indicates whether the message is allowed to be looped back to host.
1154 *
1155 * @retval TRUE If the message is allowed to be looped back to host.
1156 * @retval FALSE If the message is not allowed to be looped back to host.
1157 *
1158 */
IsLoopbackToHostAllowed(void) const1159 bool IsLoopbackToHostAllowed(void) const { return GetMetadata().mAllowLookbackToHost; }
1160
1161 /**
1162 * Sets whether or not allow the message to be looped back to host.
1163 *
1164 * @param[in] aAllowLoopbackToHost Whether or not allow the message to be looped back to host.
1165 *
1166 */
SetLoopbackToHostAllowed(bool aAllowLoopbackToHost)1167 void SetLoopbackToHostAllowed(bool aAllowLoopbackToHost)
1168 {
1169 GetMetadata().mAllowLookbackToHost = aAllowLoopbackToHost;
1170 }
1171
1172 /**
1173 * Gets the message origin.
1174 *
1175 * @returns An enum representing the origin of the message.
1176 *
1177 */
GetOrigin(void) const1178 Origin GetOrigin(void) const { return static_cast<Origin>(GetMetadata().mOrigin); }
1179
1180 /**
1181 * Sets the message origin.
1182 *
1183 * @param[in] aOrigin An enum representing the origin of the message.
1184 *
1185 */
SetOrigin(Origin aOrigin)1186 void SetOrigin(Origin aOrigin) { GetMetadata().mOrigin = aOrigin; }
1187
1188 /**
1189 * Indicates whether or not the message origin is Thread Netif.
1190 *
1191 * @retval TRUE If the message origin is Thread Netif.
1192 * @retval FALSE If the message origin is not Thread Netif.
1193 *
1194 */
IsOriginThreadNetif(void) const1195 bool IsOriginThreadNetif(void) const { return GetOrigin() == kOriginThreadNetif; }
1196
1197 /**
1198 * Indicates whether or not the message origin is a trusted source on host.
1199 *
1200 * @retval TRUE If the message origin is a trusted source on host.
1201 * @retval FALSE If the message origin is not a trusted source on host.
1202 *
1203 */
IsOriginHostTrusted(void) const1204 bool IsOriginHostTrusted(void) const { return GetOrigin() == kOriginHostTrusted; }
1205
1206 /**
1207 * Indicates whether or not the message origin is an untrusted source on host.
1208 *
1209 * @retval TRUE If the message origin is an untrusted source on host.
1210 * @retval FALSE If the message origin is not an untrusted source on host.
1211 *
1212 */
IsOriginHostUntrusted(void) const1213 bool IsOriginHostUntrusted(void) const { return GetOrigin() == kOriginHostUntrusted; }
1214
1215 /**
1216 * Indicates whether or not link security is enabled for the message.
1217 *
1218 * @retval TRUE If link security is enabled.
1219 * @retval FALSE If link security is not enabled.
1220 *
1221 */
IsLinkSecurityEnabled(void) const1222 bool IsLinkSecurityEnabled(void) const { return GetMetadata().mLinkSecurity; }
1223
1224 /**
1225 * Sets whether or not link security is enabled for the message.
1226 *
1227 * @param[in] aEnabled TRUE if link security is enabled, FALSE otherwise.
1228 *
1229 */
SetLinkSecurityEnabled(bool aEnabled)1230 void SetLinkSecurityEnabled(bool aEnabled) { GetMetadata().mLinkSecurity = aEnabled; }
1231
1232 /**
1233 * Updates the average RSS (Received Signal Strength) associated with the message by adding the given
1234 * RSS value to the average. Note that a message can be composed of multiple 802.15.4 data frame fragments each
1235 * received with a different signal strength.
1236 *
1237 * @param[in] aRss A new RSS value (in dBm) to be added to average.
1238 *
1239 */
AddRss(int8_t aRss)1240 void AddRss(int8_t aRss) { IgnoreError(GetMetadata().mRssAverager.Add(aRss)); }
1241
1242 /**
1243 * Returns the average RSS (Received Signal Strength) associated with the message.
1244 *
1245 * @returns The current average RSS value (in dBm) or `Radio::kInvalidRssi` if no average is available.
1246 *
1247 */
GetAverageRss(void) const1248 int8_t GetAverageRss(void) const { return GetMetadata().mRssAverager.GetAverage(); }
1249
1250 /**
1251 * Returns a const reference to RssAverager of the message.
1252 *
1253 * @returns A const reference to the RssAverager of the message.
1254 *
1255 */
GetRssAverager(void) const1256 const RssAverager &GetRssAverager(void) const { return GetMetadata().mRssAverager; }
1257
1258 #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
1259 /**
1260 * Updates the average LQI (Link Quality Indicator) associated with the message.
1261 *
1262 * The given LQI value would be added to the average. Note that a message can be composed of multiple 802.15.4
1263 * frame fragments each received with a different signal strength.
1264 *
1265 * @param[in] aLqi A new LQI value (has no unit) to be added to average.
1266 *
1267 */
AddLqi(uint8_t aLqi)1268 void AddLqi(uint8_t aLqi) { GetMetadata().mLqiAverager.Add(aLqi); }
1269
1270 /**
1271 * Returns the average LQI (Link Quality Indicator) associated with the message.
1272 *
1273 * @returns The current average LQI value (in dBm) or OT_RADIO_LQI_NONE if no average is available.
1274 *
1275 */
GetAverageLqi(void) const1276 uint8_t GetAverageLqi(void) const { return GetMetadata().mLqiAverager.GetAverage(); }
1277
1278 /**
1279 * Returns the count of frames counted so far.
1280 *
1281 * @returns The count of frames that have been counted.
1282 *
1283 */
GetPsduCount(void) const1284 uint8_t GetPsduCount(void) const { return GetMetadata().mLqiAverager.GetCount(); }
1285 #endif
1286
1287 /**
1288 * Sets the message's link info properties (PAN ID, link security, RSS) from a given `ThreadLinkInfo`.
1289 *
1290 * @param[in] aLinkInfo The `ThreadLinkInfo` instance from which to set message's related properties.
1291 *
1292 */
1293 void SetLinkInfo(const ThreadLinkInfo &aLinkInfo);
1294
1295 /**
1296 * Returns a pointer to the message queue (if any) where this message is queued.
1297 *
1298 * @returns A pointer to the message queue or `nullptr` if not in any message queue.
1299 *
1300 */
GetMessageQueue(void) const1301 MessageQueue *GetMessageQueue(void) const
1302 {
1303 return !GetMetadata().mInPriorityQ ? static_cast<MessageQueue *>(GetMetadata().mQueue) : nullptr;
1304 }
1305
1306 /**
1307 * Returns a pointer to the priority message queue (if any) where this message is queued.
1308 *
1309 * @returns A pointer to the priority queue or `nullptr` if not in any priority queue.
1310 *
1311 */
GetPriorityQueue(void) const1312 PriorityQueue *GetPriorityQueue(void) const
1313 {
1314 return GetMetadata().mInPriorityQ ? static_cast<PriorityQueue *>(GetMetadata().mQueue) : nullptr;
1315 }
1316
1317 /**
1318 * Indicates whether or not the message is also used for time sync purpose.
1319 *
1320 * When OPENTHREAD_CONFIG_TIME_SYNC_ENABLE is 0, this method always return false.
1321 *
1322 * @retval TRUE If the message is also used for time sync purpose.
1323 * @retval FALSE If the message is not used for time sync purpose.
1324 *
1325 */
1326 bool IsTimeSync(void) const;
1327
1328 #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1329 /**
1330 * Sets whether or not the message is also used for time sync purpose.
1331 *
1332 * @param[in] aEnabled TRUE if the message is also used for time sync purpose, FALSE otherwise.
1333 *
1334 */
SetTimeSync(bool aEnabled)1335 void SetTimeSync(bool aEnabled) { GetMetadata().mTimeSync = aEnabled; }
1336
1337 /**
1338 * Sets the offset to network time.
1339 *
1340 * @param[in] aNetworkTimeOffset The offset to network time.
1341 *
1342 */
SetNetworkTimeOffset(int64_t aNetworkTimeOffset)1343 void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) { GetMetadata().mNetworkTimeOffset = aNetworkTimeOffset; }
1344
1345 /**
1346 * Gets the offset to network time.
1347 *
1348 * @returns The offset to network time.
1349 *
1350 */
GetNetworkTimeOffset(void) const1351 int64_t GetNetworkTimeOffset(void) const { return GetMetadata().mNetworkTimeOffset; }
1352
1353 /**
1354 * Sets the time sync sequence.
1355 *
1356 * @param[in] aTimeSyncSeq The time sync sequence.
1357 *
1358 */
SetTimeSyncSeq(uint8_t aTimeSyncSeq)1359 void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { GetMetadata().mTimeSyncSeq = aTimeSyncSeq; }
1360
1361 /**
1362 * Gets the time sync sequence.
1363 *
1364 * @returns The time sync sequence.
1365 *
1366 */
GetTimeSyncSeq(void) const1367 uint8_t GetTimeSyncSeq(void) const { return GetMetadata().mTimeSyncSeq; }
1368 #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
1369
1370 #if OPENTHREAD_CONFIG_MULTI_RADIO
1371 /**
1372 * Indicates whether the radio type is set.
1373 *
1374 * @retval TRUE If the radio type is set.
1375 * @retval FALSE If the radio type is not set.
1376 *
1377 */
IsRadioTypeSet(void) const1378 bool IsRadioTypeSet(void) const { return GetMetadata().mIsRadioTypeSet; }
1379
1380 /**
1381 * Gets the radio link type the message was received on, or should be sent on.
1382 *
1383 * Should be used only when `IsRadioTypeSet()` returns `true`.
1384 *
1385 * @returns The radio link type of the message.
1386 *
1387 */
GetRadioType(void) const1388 Mac::RadioType GetRadioType(void) const { return static_cast<Mac::RadioType>(GetMetadata().mRadioType); }
1389
1390 /**
1391 * Sets the radio link type the message was received on, or should be sent on.
1392 *
1393 * @param[in] aRadioType A radio link type of the message.
1394 *
1395 */
SetRadioType(Mac::RadioType aRadioType)1396 void SetRadioType(Mac::RadioType aRadioType)
1397 {
1398 GetMetadata().mIsRadioTypeSet = true;
1399 GetMetadata().mRadioType = aRadioType;
1400 }
1401
1402 /**
1403 * Clears any previously set radio type on the message.
1404 *
1405 * After calling this method, `IsRadioTypeSet()` returns false until radio type is set (`SetRadioType()`).
1406 *
1407 */
ClearRadioType(void)1408 void ClearRadioType(void) { GetMetadata().mIsRadioTypeSet = false; }
1409
1410 #endif // #if OPENTHREAD_CONFIG_MULTI_RADIO
1411
1412 protected:
1413 class ConstIterator : public ItemPtrIterator<const Message, ConstIterator>
1414 {
1415 friend class ItemPtrIterator<const Message, ConstIterator>;
1416
1417 public:
1418 ConstIterator(void) = default;
1419
ConstIterator(const Message * aMessage)1420 explicit ConstIterator(const Message *aMessage)
1421 : ItemPtrIterator(aMessage)
1422 {
1423 }
1424
1425 private:
Advance(void)1426 void Advance(void) { mItem = mItem->GetNext(); }
1427 };
1428
1429 class Iterator : public ItemPtrIterator<Message, Iterator>
1430 {
1431 friend class ItemPtrIterator<Message, Iterator>;
1432
1433 public:
Iterator(void)1434 Iterator(void)
1435 : mNext(nullptr)
1436 {
1437 }
1438
Iterator(Message * aMessage)1439 explicit Iterator(Message *aMessage)
1440 : ItemPtrIterator(aMessage)
1441 , mNext(NextMessage(aMessage))
1442 {
1443 }
1444
1445 private:
1446 void Advance(void);
NextMessage(Message * aMessage)1447 static Message *NextMessage(Message *aMessage) { return (aMessage != nullptr) ? aMessage->GetNext() : nullptr; }
1448
1449 Message *mNext;
1450 };
1451
GetReserved(void) const1452 uint16_t GetReserved(void) const { return GetMetadata().mReserved; }
SetReserved(uint16_t aReservedHeader)1453 void SetReserved(uint16_t aReservedHeader) { GetMetadata().mReserved = aReservedHeader; }
1454
1455 private:
1456 class Chunk : public Data<kWithUint16Length>
1457 {
1458 public:
GetBuffer(void) const1459 const Buffer *GetBuffer(void) const { return mBuffer; }
SetBuffer(const Buffer * aBuffer)1460 void SetBuffer(const Buffer *aBuffer) { mBuffer = aBuffer; }
1461
1462 private:
1463 const Buffer *mBuffer; // Buffer containing the chunk
1464 };
1465
1466 class MutableChunk : public Chunk
1467 {
1468 public:
GetBytes(void)1469 uint8_t *GetBytes(void) { return AsNonConst(Chunk::GetBytes()); }
1470 };
1471
1472 void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, Chunk &aChunk) const;
1473 void GetNextChunk(uint16_t &aLength, Chunk &aChunk) const;
1474
GetFirstChunk(uint16_t aOffset,uint16_t & aLength,MutableChunk & aChunk)1475 void GetFirstChunk(uint16_t aOffset, uint16_t &aLength, MutableChunk &aChunk)
1476 {
1477 AsConst(this)->GetFirstChunk(aOffset, aLength, static_cast<Chunk &>(aChunk));
1478 }
1479
GetNextChunk(uint16_t & aLength,MutableChunk & aChunk)1480 void GetNextChunk(uint16_t &aLength, MutableChunk &aChunk)
1481 {
1482 AsConst(this)->GetNextChunk(aLength, static_cast<Chunk &>(aChunk));
1483 }
1484
GetMessagePool(void) const1485 MessagePool *GetMessagePool(void) const { return GetMetadata().mMessagePool; }
SetMessagePool(MessagePool * aMessagePool)1486 void SetMessagePool(MessagePool *aMessagePool) { GetMetadata().mMessagePool = aMessagePool; }
1487
IsInAQueue(void) const1488 bool IsInAQueue(void) const { return (GetMetadata().mQueue != nullptr); }
1489 void SetMessageQueue(MessageQueue *aMessageQueue);
1490 void SetPriorityQueue(PriorityQueue *aPriorityQueue);
1491
Next(void)1492 Message *&Next(void) { return GetMetadata().mNext; }
Next(void) const1493 Message *const &Next(void) const { return GetMetadata().mNext; }
Prev(void)1494 Message *&Prev(void) { return GetMetadata().mPrev; }
1495
NextOf(Message * aMessage)1496 static Message *NextOf(Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; }
NextOf(const Message * aMessage)1497 static const Message *NextOf(const Message *aMessage) { return (aMessage != nullptr) ? aMessage->Next() : nullptr; }
1498
1499 Error ResizeMessage(uint16_t aLength);
1500 };
1501
1502 /**
1503 * Implements a message queue.
1504 *
1505 */
1506 class MessageQueue : public otMessageQueue
1507 {
1508 friend class Message;
1509 friend class PriorityQueue;
1510
1511 public:
1512 typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue.
1513
1514 /**
1515 * Represents a position (head or tail) in the queue. This is used to specify where a new message
1516 * should be added in the queue.
1517 *
1518 */
1519 enum QueuePosition : uint8_t
1520 {
1521 kQueuePositionHead, ///< Indicates the head (front) of the list.
1522 kQueuePositionTail, ///< Indicates the tail (end) of the list.
1523 };
1524
1525 /**
1526 * Initializes the message queue.
1527 *
1528 */
MessageQueue(void)1529 MessageQueue(void) { SetTail(nullptr); }
1530
1531 /**
1532 * Returns a pointer to the first message.
1533 *
1534 * @returns A pointer to the first message.
1535 *
1536 */
GetHead(void)1537 Message *GetHead(void) { return Message::NextOf(GetTail()); }
1538
1539 /**
1540 * Returns a pointer to the first message.
1541 *
1542 * @returns A pointer to the first message.
1543 *
1544 */
GetHead(void) const1545 const Message *GetHead(void) const { return Message::NextOf(GetTail()); }
1546
1547 /**
1548 * Adds a message to the end of the list.
1549 *
1550 * @param[in] aMessage The message to add.
1551 *
1552 */
Enqueue(Message & aMessage)1553 void Enqueue(Message &aMessage) { Enqueue(aMessage, kQueuePositionTail); }
1554
1555 /**
1556 * Adds a message at a given position (head/tail) of the list.
1557 *
1558 * @param[in] aMessage The message to add.
1559 * @param[in] aPosition The position (head or tail) where to add the message.
1560 *
1561 */
1562 void Enqueue(Message &aMessage, QueuePosition aPosition);
1563
1564 /**
1565 * Removes a message from the list.
1566 *
1567 * @param[in] aMessage The message to remove.
1568 *
1569 */
1570 void Dequeue(Message &aMessage);
1571
1572 /**
1573 * Removes a message from the queue and frees it.
1574 *
1575 * @param[in] aMessage The message to remove and free.
1576 *
1577 */
1578 void DequeueAndFree(Message &aMessage);
1579
1580 /**
1581 * Removes and frees all messages from the queue.
1582 *
1583 */
1584 void DequeueAndFreeAll(void);
1585
1586 /**
1587 * Gets the information about number of messages and buffers in the queue.
1588 *
1589 * Updates `aInfo` and adds number of message/buffers in the message queue to the corresponding member
1590 * variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method (e.g.,
1591 * clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues to add
1592 * up the number of messages/buffers on different queues.
1593 *
1594 * @param[out] aInfo A reference to `Info` structure to update.ni
1595 *
1596 */
1597 void GetInfo(Info &aInfo) const;
1598
1599 // The following methods are intended to support range-based `for`
1600 // loop iteration over the queue entries and should not be used
1601 // directly. The range-based `for` works correctly even if the
1602 // current entry is removed from the queue during iteration.
1603
1604 Message::Iterator begin(void);
end(void)1605 Message::Iterator end(void) { return Message::Iterator(); }
1606
1607 Message::ConstIterator begin(void) const;
end(void) const1608 Message::ConstIterator end(void) const { return Message::ConstIterator(); }
1609
1610 private:
GetTail(void)1611 Message *GetTail(void) { return static_cast<Message *>(mData); }
GetTail(void) const1612 const Message *GetTail(void) const { return static_cast<const Message *>(mData); }
SetTail(Message * aMessage)1613 void SetTail(Message *aMessage) { mData = aMessage; }
1614 };
1615
1616 /**
1617 * Implements a priority queue.
1618 *
1619 */
1620 class PriorityQueue : private Clearable<PriorityQueue>
1621 {
1622 friend class Message;
1623 friend class MessageQueue;
1624 friend class MessagePool;
1625 friend class Clearable<PriorityQueue>;
1626
1627 public:
1628 typedef otMessageQueueInfo Info; ///< This struct represents info (number of messages/buffers) about a queue.
1629
1630 /**
1631 * Initializes the priority queue.
1632 *
1633 */
PriorityQueue(void)1634 PriorityQueue(void) { Clear(); }
1635
1636 /**
1637 * Returns a pointer to the first message.
1638 *
1639 * @returns A pointer to the first message.
1640 *
1641 */
GetHead(void)1642 Message *GetHead(void) { return AsNonConst(AsConst(this)->GetHead()); }
1643
1644 /**
1645 * Returns a pointer to the first message.
1646 *
1647 * @returns A pointer to the first message.
1648 *
1649 */
1650 const Message *GetHead(void) const;
1651
1652 /**
1653 * Returns a pointer to the first message for a given priority level.
1654 *
1655 * @param[in] aPriority Priority level.
1656 *
1657 * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with
1658 * this priority level.
1659 *
1660 */
GetHeadForPriority(Message::Priority aPriority)1661 Message *GetHeadForPriority(Message::Priority aPriority)
1662 {
1663 return AsNonConst(AsConst(this)->GetHeadForPriority(aPriority));
1664 }
1665
1666 /**
1667 * Returns a pointer to the first message for a given priority level.
1668 *
1669 * @param[in] aPriority Priority level.
1670 *
1671 * @returns A pointer to the first message with given priority level or `nullptr` if there is no messages with
1672 * this priority level.
1673 *
1674 */
1675 const Message *GetHeadForPriority(Message::Priority aPriority) const;
1676
1677 /**
1678 * Adds a message to the queue.
1679 *
1680 * @param[in] aMessage The message to add.
1681 *
1682 */
1683 void Enqueue(Message &aMessage);
1684
1685 /**
1686 * Removes a message from the list.
1687 *
1688 * @param[in] aMessage The message to remove.
1689 *
1690 */
1691 void Dequeue(Message &aMessage);
1692
1693 /**
1694 * Removes a message from the queue and frees it.
1695 *
1696 * @param[in] aMessage The message to remove and free.
1697 *
1698 */
1699 void DequeueAndFree(Message &aMessage);
1700
1701 /**
1702 * Removes and frees all messages from the queue.
1703 *
1704 */
1705 void DequeueAndFreeAll(void);
1706
1707 /**
1708 * Returns the tail of the list (last message in the list).
1709 *
1710 * @returns A pointer to the tail of the list.
1711 *
1712 */
GetTail(void)1713 Message *GetTail(void) { return AsNonConst(AsConst(this)->GetTail()); }
1714
1715 /**
1716 * Returns the tail of the list (last message in the list).
1717 *
1718 * @returns A pointer to the tail of the list.
1719 *
1720 */
1721 const Message *GetTail(void) const;
1722
1723 /**
1724 * Gets the information about number of messages and buffers in the priority queue.
1725 *
1726 * Updates `aInfo` array and adds number of message/buffers in the message queue to the corresponding
1727 * member variable in `aInfo`. The caller needs to make sure `aInfo` is initialized before calling this method
1728 * (e.g., clearing `aInfo`). Same `aInfo` can be passed in multiple calls of `GetInfo(aInfo)` on different queues
1729 * to add up the number of messages/buffers on different queues.
1730 *
1731 * @param[out] aInfo A reference to an `Info` structure to update.
1732 *
1733 */
1734 void GetInfo(Info &aInfo) const;
1735
1736 // The following methods are intended to support range-based `for`
1737 // loop iteration over the queue entries and should not be used
1738 // directly. The range-based `for` works correctly even if the
1739 // current entry is removed from the queue during iteration.
1740
1741 Message::Iterator begin(void);
end(void)1742 Message::Iterator end(void) { return Message::Iterator(); }
1743
1744 Message::ConstIterator begin(void) const;
end(void) const1745 Message::ConstIterator end(void) const { return Message::ConstIterator(); }
1746
1747 private:
PrevPriority(uint8_t aPriority) const1748 uint8_t PrevPriority(uint8_t aPriority) const
1749 {
1750 return (aPriority == Message::kNumPriorities - 1) ? 0 : (aPriority + 1);
1751 }
1752
1753 const Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel) const;
1754
FindFirstNonNullTail(Message::Priority aStartPriorityLevel)1755 Message *FindFirstNonNullTail(Message::Priority aStartPriorityLevel)
1756 {
1757 return AsNonConst(AsConst(this)->FindFirstNonNullTail(aStartPriorityLevel));
1758 }
1759
1760 Message *mTails[Message::kNumPriorities]; // Tail pointers associated with different priority levels.
1761 };
1762
1763 /**
1764 * Represents a message pool
1765 *
1766 */
1767 class MessagePool : public InstanceLocator, private NonCopyable
1768 {
1769 friend class Message;
1770 friend class MessageQueue;
1771 friend class PriorityQueue;
1772
1773 public:
1774 /**
1775 * Initializes the object.
1776 *
1777 */
1778 explicit MessagePool(Instance &aInstance);
1779
1780 /**
1781 * Allocates a new message with specified settings.
1782 *
1783 * @param[in] aType The message type.
1784 * @param[in] aReserveHeader The number of header bytes to reserve.
1785 * @param[in] aSettings The message settings.
1786 *
1787 * @returns A pointer to the message or `nullptr` if no message buffers are available.
1788 *
1789 */
1790 Message *Allocate(Message::Type aType, uint16_t aReserveHeader, const Message::Settings &aSettings);
1791
1792 /**
1793 * Allocates a new message of a given type using default settings.
1794 *
1795 * @param[in] aType The message type.
1796 *
1797 * @returns A pointer to the message or `nullptr` if no message buffers are available.
1798 *
1799 */
1800 Message *Allocate(Message::Type aType);
1801
1802 /**
1803 * Allocates a new message with a given type and reserved length using default settings.
1804 *
1805 * @param[in] aType The message type.
1806 * @param[in] aReserveHeader The number of header bytes to reserve.
1807 *
1808 * @returns A pointer to the message or `nullptr` if no message buffers are available.
1809 *
1810 */
1811 Message *Allocate(Message::Type aType, uint16_t aReserveHeader);
1812
1813 /**
1814 * Is used to free a message and return all message buffers to the buffer pool.
1815 *
1816 * @param[in] aMessage The message to free.
1817 *
1818 */
1819 void Free(Message *aMessage);
1820
1821 /**
1822 * Returns the number of free buffers.
1823 *
1824 * @returns The number of free buffers, or 0xffff (UINT16_MAX) if number is unknown.
1825 *
1826 */
1827 uint16_t GetFreeBufferCount(void) const;
1828
1829 /**
1830 * Returns the total number of buffers.
1831 *
1832 * @returns The total number of buffers, or 0xffff (UINT16_MAX) if number is unknown.
1833 *
1834 */
1835 uint16_t GetTotalBufferCount(void) const;
1836
1837 /**
1838 * Returns the maximum number of buffers in use at the same time since OT stack initialization or
1839 * since last call to `ResetMaxUsedBufferCount()`.
1840 *
1841 * @returns The maximum number of buffers in use at the same time so far (buffer allocation watermark).
1842 *
1843 */
GetMaxUsedBufferCount(void) const1844 uint16_t GetMaxUsedBufferCount(void) const { return mMaxAllocated; }
1845
1846 /**
1847 * Resets the tracked maximum number of buffers in use.
1848 *
1849 * @sa GetMaxUsedBufferCount
1850 *
1851 */
ResetMaxUsedBufferCount(void)1852 void ResetMaxUsedBufferCount(void) { mMaxAllocated = mNumAllocated; }
1853
1854 private:
1855 Buffer *NewBuffer(Message::Priority aPriority);
1856 void FreeBuffers(Buffer *aBuffer);
1857 Error ReclaimBuffers(Message::Priority aPriority);
1858
1859 #if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE
1860 Pool<Buffer, kNumBuffers> mBufferPool;
1861 #endif
1862 uint16_t mNumAllocated;
1863 uint16_t mMaxAllocated;
1864 };
1865
GetInstance(void) const1866 inline Instance &Message::GetInstance(void) const { return GetMessagePool()->GetInstance(); }
1867
1868 /**
1869 * @}
1870 *
1871 */
1872
1873 DefineCoreType(otMessageBuffer, Buffer);
1874 DefineCoreType(otMessageSettings, Message::Settings);
1875 DefineCoreType(otMessage, Message);
1876 DefineCoreType(otMessageQueue, MessageQueue);
1877
1878 DefineMapEnum(otMessageOrigin, Message::Origin);
1879
1880 } // namespace ot
1881
1882 #endif // MESSAGE_HPP_
1883