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