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