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