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