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