Matter SDK Coverage Report
Current view: top level - system - SystemPacketBuffer.h (source / functions) Coverage Total Hit
Test: SHA:6c8f029dd2432dc900f1c9245c324e69bd79e40a Lines: 100.0 % 84 84
Test Date: 2026-08-08 07:40:09 Functions: 100.0 % 43 43

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    Copyright (c) 2016-2017 Nest Labs, Inc.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : /**
      20              :  *    @file
      21              :  *      This file defines the chip::System::PacketBuffer class,
      22              :  *      which provides the mechanisms for manipulating packets of *
      23              :  *      octet-serialized data.
      24              :  */
      25              : 
      26              : #pragma once
      27              : 
      28              : // Include configuration header
      29              : #include <system/SystemPacketBufferInternal.h>
      30              : 
      31              : // Include dependent headers
      32              : #include <lib/support/BufferWriter.h>
      33              : #include <lib/support/CodeUtils.h>
      34              : #include <lib/support/DLLUtil.h>
      35              : #include <system/SystemAlignSize.h>
      36              : #include <system/SystemError.h>
      37              : 
      38              : #include <stddef.h>
      39              : #include <stdint.h>
      40              : #include <utility>
      41              : 
      42              : #if CHIP_SYSTEM_CONFIG_USE_LWIP
      43              : #include <lwip/mem.h>
      44              : #include <lwip/memp.h>
      45              : #include <lwip/pbuf.h>
      46              : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
      47              : 
      48              : namespace chip {
      49              : namespace System {
      50              : 
      51              : class PacketBufferHandle;
      52              : 
      53              : #if !CHIP_SYSTEM_CONFIG_USE_LWIP
      54              : struct pbuf
      55              : {
      56              :     struct pbuf * next;
      57              :     void * payload;
      58              :     size_t tot_len;
      59              :     size_t len;
      60              :     uint16_t ref;
      61              : #if CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_HEAP
      62              :     size_t alloc_size;
      63              : #endif
      64              : };
      65              : #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
      66              : 
      67              : /**    @class PacketBuffer
      68              :  *
      69              :  *     @brief
      70              :  *      The packet buffer class is the core structure used for manipulating packets of octet-serialized data, usually in the
      71              :  *      context of a data communications network, like Bluetooth or the Internet protocol.
      72              :  *
      73              :  *      In LwIP-based environments, this class is built on top of the pbuf structure defined in that library. In the absence of
      74              :  *      LwIP, chip provides either a malloc-based implementation, or a pool-based implementation that closely approximates the
      75              :  *      memory challenges of deeply embedded devices.
      76              :  *
      77              :  *      The PacketBuffer class, like many similar structures used in layered network stacks, provide a mechanism to reserve space
      78              :  *      for protocol headers at each layer of a configurable communication stack.  For details, see `PacketBufferHandle::New()`
      79              :  *      as well as LwIP documentation.
      80              :  *
      81              :  *      PacketBuffer objects are reference-counted, and normally held and used through a PacketBufferHandle that owns one of the
      82              :  *      counted references. When a PacketBufferHandle goes out of scope, its reference is released. To take ownership, a function
      83              :  *      takes a PacketBufferHandle by value. To borrow ownership, a function takes a `const PacketBufferHandle &`.
      84              :  *
      85              :  *      New objects of PacketBuffer class are initialized at the beginning of an allocation of memory obtained from the underlying
      86              :  *      environment, e.g. from LwIP pbuf target pools, from the standard C library heap, from an internal buffer pool. In the
      87              :  *      simple pool case, the size of the data buffer is PacketBuffer::kBlockSize.
      88              :  *
      89              :  *      PacketBuffer objects may be chained to accommodate larger payloads.  Chaining, however, is not transparent, and users of the
      90              :  *      class must explicitly decide to support chaining.  Examples of classes written with chaining support are as follows:
      91              :  *
      92              :  *          @ref chip::TLVReader
      93              :  *          @ref chip::TLVWriter
      94              :  *
      95              :  * ### PacketBuffer format
      96              :  *
      97              :  * <pre>
      98              :  *           ┌────────────────────────────────────┐
      99              :  *           │       ┌────────────────────┐       │
     100              :  *           │       │                    │◁──────┴───────▷│
     101              :  *  ┏━━━━━━━━┿━━━━━━━┿━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┓
     102              :  *  ┃ pbuf len payload ┃ reserve          ┃ data           ┃ unused                  ┃
     103              :  *  ┗━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━┛
     104              :  *  │                  │← ReservedSize() →│← DataLength() →│← AvailableDataLength() →│
     105              :  *  │                  │                  │← MaxDataLength() → · · · · · · · · · · ·→│
     106              :  *  │                  │                  Start()                                    │
     107              :  *  │← kStructureSize →│← AllocSize() → · · · · · · · · · · · · · · · · · · · · · · →│
     108              :  * </pre>
     109              :  *
     110              :  */
     111              : class DLL_EXPORT PacketBuffer : private pbuf
     112              : {
     113              : private:
     114              :     // The effective size of the packet buffer structure.
     115              : #if CHIP_SYSTEM_CONFIG_USE_LWIP
     116              :     static constexpr size_t kStructureSize = LWIP_MEM_ALIGN_SIZE(sizeof(struct ::pbuf));
     117              : #else  // CHIP_SYSTEM_CONFIG_USE_LWIP
     118              :     static constexpr size_t kStructureSize         = CHIP_SYSTEM_ALIGN_SIZE(sizeof(::chip::System::pbuf), 4u);
     119              : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
     120              : 
     121              : public:
     122              :     /**
     123              :      * The maximum size of a regular buffer an application can allocate with no protocol header reserve.
     124              :      */
     125              : #if CHIP_SYSTEM_CONFIG_USE_LWIP
     126              :     static constexpr size_t kMaxSizeWithoutReserve = LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE);
     127              : #else
     128              :     static constexpr size_t kMaxSizeWithoutReserve = CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX;
     129              : #endif
     130              : 
     131              :     /**
     132              :      * The number of bytes to reserve in a network packet buffer to contain all the possible protocol encapsulation headers
     133              :      * before the application data.
     134              :      */
     135              :     static constexpr uint16_t kDefaultHeaderReserve = CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE;
     136              : 
     137              :     /**
     138              :      * The maximum size of a regular buffer an application can allocate with the default protocol header reserve.
     139              :      */
     140              :     static constexpr size_t kMaxSize = kMaxSizeWithoutReserve - kDefaultHeaderReserve;
     141              : 
     142              :     /**
     143              :      * The maximum size of a large buffer(> IPv6 MTU) that an application can allocate with no protocol header reserve.
     144              :      */
     145              :     static constexpr size_t kLargeBufMaxSizeWithoutReserve = CHIP_SYSTEM_CONFIG_MAX_LARGE_BUFFER_SIZE_BYTES;
     146              : 
     147              :     /**
     148              :      * The maximum size of a large buffer(> IPv6 MTU) that an application can allocate with the default protocol header reserve.
     149              :      */
     150              :     static constexpr size_t kLargeBufMaxSize = kLargeBufMaxSizeWithoutReserve - kDefaultHeaderReserve;
     151              : 
     152              :     /**
     153              :      * Unified constant(both regular and large buffers) for the maximum size that an application can allocate with no
     154              :      * protocol header reserve.
     155              :      */
     156              : #if INET_CONFIG_ENABLE_TCP_ENDPOINT
     157              :     static constexpr size_t kMaxAllocSize = kLargeBufMaxSizeWithoutReserve;
     158              : #else
     159              :     static constexpr size_t kMaxAllocSize          = kMaxSizeWithoutReserve;
     160              : #endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
     161              : 
     162              :     /**
     163              :      * Return the size of the allocation including the reserved and payload data spaces but not including space
     164              :      * allocated for the PacketBuffer structure.
     165              :      *
     166              :      *  @note    The allocation size is equal to or greater than the \c aAllocSize parameter to the \c Create method).
     167              :      *
     168              :      *  @return     size of the allocation
     169              :      */
     170       201317 :     size_t AllocSize() const
     171              :     {
     172              : #if CHIP_SYSTEM_PACKETBUFFER_FROM_LWIP_STANDARD_POOL || CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_POOL
     173              :         return kMaxSizeWithoutReserve;
     174              : #elif CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_HEAP
     175       201317 :         return this->alloc_size;
     176              : #elif CHIP_SYSTEM_PACKETBUFFER_FROM_LWIP_CUSTOM_POOL
     177              :         // Temporary workaround for custom pbufs by assuming size to be PBUF_POOL_BUFSIZE
     178              :         if (this->flags & PBUF_FLAG_IS_CUSTOM)
     179              :             return LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - kStructureSize;
     180              :         else
     181              :             return LWIP_MEM_ALIGN_SIZE(memp_sizes[this->pool]) - kStructureSize;
     182              : #elif CHIP_SYSTEM_CONFIG_PACKETBUFFER_LWIP_PBUF_RAM
     183              :         return PacketBuffer::kMaxAllocSize;
     184              : #else
     185              : #error "Unimplemented PacketBuffer storage case"
     186              : #endif
     187              :     }
     188              : 
     189              :     /**
     190              :      * Get a pointer to the start of data in a buffer.
     191              :      *
     192              :      *  @return pointer to the start of data.
     193              :      */
     194       575204 :     uint8_t * Start() const { return static_cast<uint8_t *>(this->payload); }
     195              : 
     196              :     /**
     197              :      *  Set the the start of data in a buffer, adjusting length and total length accordingly.
     198              :      *
     199              :      *  @note The data within the buffer is not moved, only accounting information is changed.  The function is commonly used to
     200              :      *      either strip or prepend protocol headers in a zero-copy way.
     201              :      *
     202              :      *  @note This call should not be used on any buffer that is not the head of a buffer chain, as it only alters the current
     203              :      *      buffer.
     204              :      *
     205              :      *  @param[in] aNewStart - A pointer to where the new payload should start.  newStart will be adjusted internally to fall within
     206              :      *      the boundaries of the first buffer in the PacketBuffer chain.
     207              :      */
     208              :     void SetStart(uint8_t * aNewStart);
     209              : 
     210              :     /**
     211              :      * Get the length, in bytes, of data in a packet buffer.
     212              :      *
     213              :      *  @return length, in bytes (current payload length).
     214              :      */
     215       251893 :     size_t DataLength() const { return this->len; }
     216              : 
     217              :     /**
     218              :      * Set the length, in bytes, of data in a packet buffer, adjusting total length accordingly.
     219              :      *
     220              :      *  The function sets the length, in bytes, of the data in the buffer, adjusting the total length appropriately. When the buffer
     221              :      *  is not the head of the buffer chain (common case: the caller adds data to the last buffer in the PacketBuffer chain prior to
     222              :      *  calling higher layers), the aChainHead __must__ be passed in to properly adjust the total lengths of each buffer ahead of
     223              :      *  the current buffer.
     224              :      *
     225              :      *  @param[in] aNewLen - new length, in bytes, of this buffer.
     226              :      *
     227              :      *  @param[in,out] aChainHead - the head of the buffer chain the current buffer belongs to.  May be \c nullptr if the current
     228              :      *      buffer is the head of the buffer chain.
     229              :      */
     230              :     void SetDataLength(size_t aNewLen, const PacketBufferHandle & aChainHead);
     231        32132 :     void SetDataLength(size_t aNewLen) { SetDataLength(aNewLen, nullptr); }
     232              : 
     233              :     /**
     234              :      * Get the total length of packet data in the buffer chain.
     235              :      *
     236              :      *  @return total length, in octets.
     237              :      */
     238        82558 :     size_t TotalLength() const { return this->tot_len; }
     239              : 
     240              :     /**
     241              :      * Get the maximum amount, in bytes, of data that will fit in the buffer given the current start position and buffer size.
     242              :      *
     243              :      *  @return number of bytes that fits in the buffer given the current start position.
     244              :      */
     245              :     size_t MaxDataLength() const;
     246              : 
     247              :     /**
     248              :      * Get the number of bytes of data that can be added to the current buffer given the current start position and data length.
     249              :      *
     250              :      *  @return the length, in bytes, of data that will fit in the current buffer given the current start position and data length.
     251              :      */
     252              :     size_t AvailableDataLength() const;
     253              : 
     254              :     /**
     255              :      * Get the number of bytes within the current buffer between the start of the buffer and the current data start position.
     256              :      *
     257              :      *  @return the amount, in bytes, of space between the start of the buffer and the current data start position.
     258              :      */
     259              :     uint16_t ReservedSize() const;
     260              : 
     261              :     /**
     262              :      * Determine whether there are any additional buffers chained to the current buffer.
     263              :      *
     264              :      *  @return \c true if there is a chained buffer.
     265              :      */
     266       106490 :     bool HasChainedBuffer() const { return ChainedBuffer() != nullptr; }
     267              : 
     268              :     /**
     269              :      * Add the given packet buffer to the end of the buffer chain, adjusting the total length of each buffer in the chain
     270              :      * accordingly.
     271              :      *
     272              :      *  @note The current packet buffer must be the head of the buffer chain for the lengths to be adjusted properly.
     273              :      *
     274              :      *  @note Ownership is transferred from the argument to the `next` link at the end of the current chain.
     275              :      *
     276              :      *  @param[in] aPacket - the packet buffer to be added to the end of the current chain.
     277              :      */
     278              :     void AddToEnd(PacketBufferHandle && aPacket);
     279              : 
     280              :     /**
     281              :      * Move data from subsequent buffers in the chain into the current buffer until it is full.
     282              :      *
     283              :      *  Only the current buffer is compacted: the data within the current buffer is moved to the front of the buffer, eliminating
     284              :      *  any reserved space. The remaining available space is filled with data moved from subsequent buffers in the chain, until the
     285              :      *  current buffer is full. If a subsequent buffer in the chain is moved into the current buffer in its entirety, it is removed
     286              :      *  from the chain and freed. The method takes no parameters, returns no results and cannot fail.
     287              :      */
     288              :     void CompactHead();
     289              : 
     290              :     /**
     291              :      * Adjust the current buffer to indicate the amount of data consumed.
     292              :      *
     293              :      *  Advance the data start position in the current buffer by the specified amount, in bytes, up to the length of data in the
     294              :      *  buffer. Decrease the length and total length by the amount consumed.
     295              :      *
     296              :      *  @param[in] aConsumeLength - number of bytes to consume from the current buffer.
     297              :      */
     298              :     void ConsumeHead(size_t aConsumeLength);
     299              : 
     300              :     /**
     301              :      * Ensure the buffer has at least the specified amount of reserved space.
     302              :      *
     303              :      *  Ensure the buffer has at least the specified amount of reserved space, moving the data in the buffer forward to make room if
     304              :      *  necessary.
     305              :      *
     306              :      *  @param[in] aReservedSize - number of bytes desired for the headers.
     307              :      *
     308              :      *  @return \c true if the requested reserved size is available, \c false if there's not enough room in the buffer.
     309              :      */
     310              :     CHECK_RETURN_VALUE bool EnsureReservedSize(uint16_t aReservedSize);
     311              : 
     312              :     /**
     313              :      * Align the buffer payload on the specified bytes boundary.
     314              :      *
     315              :      *  Moving the payload in the buffer forward if necessary.
     316              :      *
     317              :      *  @param[in] aAlignBytes - specifies number of bytes alignment for the payload start pointer.
     318              :      *
     319              :      *  @return \c true if alignment is successful, \c false if there's not enough room in the buffer.
     320              :      */
     321              :     bool AlignPayload(uint16_t aAlignBytes);
     322              : 
     323              :     /**
     324              :      * Return the next buffer in a buffer chain.
     325              :      *
     326              :      *  If there is no next buffer, the handle will have \c IsNull() \c true.
     327              :      *
     328              :      *  @return a handle to the next buffer in the buffer chain.
     329              :      */
     330              :     CHECK_RETURN_VALUE PacketBufferHandle Next();
     331              : 
     332              :     /**
     333              :      * Return the last buffer in a buffer chain.
     334              :      *
     335              :      *  @return a handle to the last buffer in the buffer chain.
     336              :      */
     337              :     CHECK_RETURN_VALUE PacketBufferHandle Last();
     338              : 
     339              :     /**
     340              :      * Copies data from the payloads of a chain of packet buffers until a given amount of data has been copied.
     341              :      *
     342              :      * @param[in]  buf             Destination buffer; must be at least @a length bytes.
     343              :      * @param[in]  length          Destination buffer length.
     344              :      *
     345              :      * @retval #CHIP_ERROR_BUFFER_TOO_SMALL If the total length of the payloads in the chain is less than the requested @a length.
     346              :      * @retval #CHIP_ERROR_INTERNAL         In case of an inconsistency in the buffer chain.
     347              :      * @retval #CHIP_NO_ERROR               If the requested payload has been copied.
     348              :      */
     349              :     CHIP_ERROR Read(uint8_t * buf, size_t length) const;
     350              :     template <size_t N>
     351           24 :     inline CHIP_ERROR Read(uint8_t (&buf)[N]) const
     352              :     {
     353           24 :         return Read(buf, N);
     354              :     }
     355              : 
     356              :     /**
     357              :      * Perform an implementation-defined check on the validity of a PacketBuffer pointer.
     358              :      *
     359              :      * Unless enabled by #CHIP_CONFIG_MEMORY_DEBUG_CHECKS == 1, this function does nothing.
     360              :      *
     361              :      * When enabled, it performs an implementation- and configuration-defined check on
     362              :      * the validity of the packet buffer. It MAY log an error and/or abort the program
     363              :      * if the packet buffer or the implementation-defined memory management system is in
     364              :      * a faulty state. (Some configurations may not actually perform any check.)
     365              :      *
     366              :      * @note  A null pointer is not considered faulty.
     367              :      *
     368              :      *  @param[in] buffer - the packet buffer to check.
     369              :      */
     370        97910 :     static void Check(const PacketBuffer * buffer)
     371              :     {
     372              : #if CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK
     373              :         InternalCheck(buffer);
     374              : #endif
     375        97910 :     }
     376              : 
     377              : private:
     378              :     // Memory required for a maximum-size PacketBuffer.
     379              :     static constexpr uint16_t kBlockSize = PacketBuffer::kStructureSize + PacketBuffer::kMaxSizeWithoutReserve;
     380              : 
     381              :     // Note: this condition includes DOXYGEN to work around a Doxygen error. DOXYGEN is never defined in any actual build.
     382              : #if CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_POOL || defined(DOXYGEN)
     383              :     typedef union
     384              :     {
     385              :         pbuf Header;
     386              :         uint8_t Block[PacketBuffer::kBlockSize];
     387              :     } BufferPoolElement;
     388              :     static BufferPoolElement sBufferPool[CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE];
     389              :     static PacketBuffer * sFreeList;
     390              :     static PacketBuffer * BuildFreeList();
     391              : #endif // CHIP_SYSTEM_PACKETBUFFER_FROM_CHIP_POOL || defined(DOXYGEN)
     392              : 
     393              : #if CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK
     394              :     static void InternalCheck(const PacketBuffer * buffer);
     395              : #endif
     396              : 
     397              :     void AddRef();
     398              :     bool HasSoleOwnership() const { return (this->ref == 1); }
     399              :     static void Free(PacketBuffer * aPacket);
     400              :     static PacketBuffer * FreeHead(PacketBuffer * aPacket);
     401              : 
     402       280503 :     PacketBuffer * ChainedBuffer() const { return static_cast<PacketBuffer *>(this->next); }
     403              :     PacketBuffer * Consume(size_t aConsumeLength);
     404              :     void Clear();
     405              :     void SetDataLength(size_t aNewLen, PacketBuffer * aChainHead);
     406              : 
     407              :     /**
     408              :      * Get a pointer to the start of the reserved space (which comes before the
     409              :      * payload).  The actual reserved space is the ReservedSize() bytes starting
     410              :      * at this pointer.
     411              :      */
     412              :     uint8_t * ReserveStart();
     413              :     const uint8_t * ReserveStart() const;
     414              : 
     415              :     friend class PacketBufferHandle;
     416              :     friend class TestSystemPacketBuffer;
     417              : };
     418              : 
     419              : static_assert(sizeof(pbuf) == sizeof(PacketBuffer), "PacketBuffer must not have additional members");
     420              : 
     421              : /**
     422              :  * @class PacketBufferHandle
     423              :  *
     424              :  * @brief
     425              :  *  Tracks ownership of a PacketBuffer.
     426              :  *
     427              :  *  PacketBuffer objects are reference-counted, and normally held and used through a PacketBufferHandle that owns one of the
     428              :  *  counted references. When a PacketBufferHandle goes out of scope, its reference is released. To take ownership, a function
     429              :  *  takes a PacketBufferHandle by value. To borrow ownership, a function takes a `const PacketBufferHandle &`.
     430              :  */
     431              : class DLL_EXPORT PacketBufferHandle
     432              : {
     433              : public:
     434              :     /**
     435              :      * Construct an empty PacketBufferHandle.
     436              :      */
     437       191284 :     PacketBufferHandle() : mBuffer(nullptr) {}
     438        41046 :     PacketBufferHandle(decltype(nullptr)) : mBuffer(nullptr) {}
     439              : 
     440              :     /**
     441              :      * Construct a PacketBufferHandle that takes ownership of a PacketBuffer from another.
     442              :      */
     443       118140 :     PacketBufferHandle(PacketBufferHandle && aOther)
     444       118140 :     {
     445       118140 :         mBuffer        = aOther.mBuffer;
     446       118140 :         aOther.mBuffer = nullptr;
     447       118140 :     }
     448              : 
     449       475628 :     ~PacketBufferHandle() { *this = nullptr; }
     450              : 
     451              :     /**
     452              :      * Take ownership of a PacketBuffer from another PacketBufferHandle, freeing any existing owned buffer.
     453              :      */
     454       158002 :     PacketBufferHandle & operator=(PacketBufferHandle && aOther)
     455              :     {
     456       158002 :         if (mBuffer != nullptr)
     457              :         {
     458         4473 :             PacketBuffer::Free(mBuffer);
     459              :         }
     460       158002 :         mBuffer        = aOther.mBuffer;
     461       158002 :         aOther.mBuffer = nullptr;
     462       158002 :         return *this;
     463              :     }
     464              : 
     465              :     /**
     466              :      * Free any buffer owned by this handle.
     467              :      */
     468       523357 :     PacketBufferHandle & operator=(decltype(nullptr))
     469              :     {
     470       523357 :         if (mBuffer != nullptr)
     471              :         {
     472       103424 :             PacketBuffer::Free(mBuffer);
     473              :         }
     474       523357 :         mBuffer = nullptr;
     475       523357 :         return *this;
     476              :     }
     477              : 
     478              :     /**
     479              :      * Get a new handle to an existing buffer.
     480              :      *
     481              :      * @return a PacketBufferHandle that shares ownership with this.
     482              :      */
     483        58173 :     PacketBufferHandle Retain() const
     484              :     {
     485        58173 :         mBuffer->AddRef();
     486        58173 :         return PacketBufferHandle(mBuffer);
     487              :     }
     488              : 
     489              :     /**
     490              :      * Access a PackerBuffer's public methods.
     491              :      */
     492      1012547 :     PacketBuffer * operator->() const { return mBuffer; }
     493              : 
     494              :     /**
     495              :      * Test whether this PacketBufferHandle is empty, or conversely owns a PacketBuffer.
     496              :      *
     497              :      * @return \c true if this PacketBufferHandle is empty; return \c false if it owns a PacketBuffer.
     498              :      */
     499       188144 :     bool IsNull() const { return mBuffer == nullptr; }
     500              : 
     501              :     /**
     502              :      * Test whether the PacketBuffer owned by this PacketBufferHandle has unique ownership.
     503              :      *
     504              :      * @return \c true if the PacketBuffer owned by this PacketBufferHandle is solely owned; return \c false if
     505              :      * it has more than one ownership.
     506              :      */
     507              :     bool HasSoleOwnership() const { return mBuffer->HasSoleOwnership(); }
     508              : 
     509              :     /**
     510              :      *  Detach and return the head of a buffer chain while updating this handle to point to the remaining buffers.
     511              :      *  The current buffer must be the head of the chain.
     512              :      *
     513              :      *  This PacketBufferHandle now holds the ownership formerly held by the head of the chain.
     514              :      *  The returned PacketBufferHandle holds the ownership formerly held by this.
     515              :      *
     516              :      *  @return the detached buffer formerly at the head of the buffer chain.
     517              :      */
     518              :     CHECK_RETURN_VALUE PacketBufferHandle PopHead();
     519              : 
     520              :     /**
     521              :      * Free the first buffer in a chain.
     522              :      *
     523              :      *  @note When the buffer chain is referenced by multiple handles, `FreeHead()` will detach the head, but will not forcibly
     524              :      *  deallocate the head buffer.
     525              :      */
     526           50 :     void FreeHead()
     527              :     {
     528              :         // `PacketBuffer::FreeHead()` frees the current head; this takes ownership from the `next` link.
     529           50 :         mBuffer = PacketBuffer::FreeHead(mBuffer);
     530           50 :     }
     531              : 
     532              :     /**
     533              :      * Add the given packet buffer to the end of the buffer chain, adjusting the total length of each buffer in the chain
     534              :      * accordingly.
     535              :      *
     536              :      *  @note The current packet buffer handle must either be the head of the buffer chain for the lengths to be adjusted properly,
     537              :      *        or be null (in which case it becomes the head).
     538              :      *
     539              :      *  @note Ownership is transferred from the argument to the `next` link at the end of the current chain,
     540              :      *        or to the handle if it's currently null.
     541              :      *
     542              :      *  @param[in] aPacket - the packet buffer to be added to the end of the current chain.
     543              :      */
     544         4173 :     void AddToEnd(PacketBufferHandle && aPacket)
     545              :     {
     546         4173 :         if (IsNull())
     547              :         {
     548         1149 :             mBuffer         = aPacket.mBuffer;
     549         1149 :             aPacket.mBuffer = nullptr;
     550              :         }
     551              :         else
     552              :         {
     553         3024 :             mBuffer->AddToEnd(std::move(aPacket));
     554              :         }
     555         4173 :     }
     556              : 
     557              :     /**
     558              :      * Consume data in a chain of buffers.
     559              :      *
     560              :      *  Consume data in a chain of buffers starting with the current buffer and proceeding through the remaining buffers in the
     561              :      *  chain. Each buffer that is completely consumed is freed and the handle holds the first buffer (if any) containing the
     562              :      *  remaining data. The current buffer must be the head of the buffer chain.
     563              :      *
     564              :      *  @param[in] aConsumeLength - number of bytes to consume from the current chain.
     565              :      */
     566         6510 :     void Consume(size_t aConsumeLength) { mBuffer = mBuffer->Consume(aConsumeLength); }
     567              : 
     568              :     /**
     569              :      * Copy the given buffer to a right-sized buffer if applicable.
     570              :      *
     571              :      * Only operates on single buffers (for chains, use \c CompactHead() and RightSize the tail).
     572              :      * Requires that this handle be the only reference to the underlying buffer.
     573              :      */
     574         8059 :     void RightSize()
     575              :     {
     576              : #if CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHTSIZE
     577         8059 :         InternalRightSize();
     578              : #endif
     579         8059 :     }
     580              : 
     581              :     /**
     582              :      * Get a new handle to a raw PacketBuffer pointer.
     583              :      *
     584              :      * @brief The caller's ownership is transferred to this.
     585              :      *
     586              :      * @note This should only be used in low-level code, e.g. to import buffers from LwIP or a similar stack.
     587              :      */
     588            7 :     static PacketBufferHandle Adopt(PacketBuffer * buffer) { return PacketBufferHandle(buffer); }
     589              : #if CHIP_SYSTEM_CONFIG_USE_LWIP
     590              :     static PacketBufferHandle Adopt(pbuf * buffer) { return Adopt(reinterpret_cast<PacketBuffer *>(buffer)); }
     591              : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
     592              : 
     593              :     /**
     594              :      * Advance this PacketBufferHandle to the next buffer in a chain.
     595              :      *
     596              :      *  @note This differs from `FreeHead()` in that it does not touch any content in the currently referenced packet buffer;
     597              :      *      it only changes which buffer this handle owns. (Note that this could result in the previous buffer being freed,
     598              :      *      if there is no other owner.) `Advance()` is designed to be used with an additional handle to traverse a buffer chain,
     599              :      *      whereas `FreeHead()` modifies a chain.
     600              :      */
     601         1401 :     void Advance() { *this = Hold(mBuffer->ChainedBuffer()); }
     602              : 
     603              :     /**
     604              :      * Export a raw PacketBuffer pointer.
     605              :      *
     606              :      * @brief The PacketBufferHandle's ownership is transferred to the caller.
     607              :      *
     608              :      * @note This should only be used in low-level code. The caller owns one counted reference to the \c PacketBuffer
     609              :      *       and is responsible for managing it safely.
     610              :      *
     611              :      * @note The ref-qualifier `&&` requires the caller to use `std::move` to emphasize that ownership is
     612              :      *       moved out of this handle.
     613              :      */
     614        12001 :     CHECK_RETURN_VALUE PacketBuffer * UnsafeRelease() &&
     615              :     {
     616        12001 :         PacketBuffer::Check(mBuffer);
     617        12001 :         PacketBuffer * buffer = mBuffer;
     618        12001 :         mBuffer               = nullptr;
     619        12001 :         return buffer;
     620              :     }
     621              : 
     622              :     /**
     623              :      * Allocates a packet buffer.
     624              :      *
     625              :      *  A packet buffer is conceptually divided into two parts:
     626              :      *  @li  Space reserved for network protocol headers. The size of this space normally defaults to a value determined
     627              :      *       by the network layer configuration, but can be given explicity by \c aReservedSize for special cases.
     628              :      *  @li  Space for application data. The minimum size of this space is given by \c aAvailableSize, and then \c Start()
     629              :      *       provides a pointer to the start of this space.
     630              :      *
     631              :      *  Fails and returns \c nullptr if no memory is available, or if the size requested is too large.
     632              :      *  When the sum of \a aAvailableSize and \a aReservedSize is no greater than \c PacketBuffer::kMaxSizeWithoutReserve,
     633              :      *  that is guaranteed not to be too large.
     634              :      *
     635              :      *  On success, it is guaranteed that \c AvailableDataSize() is no less than \a aAvailableSize.
     636              :      *
     637              :      *  @param[in]  aAvailableSize  Minimum number of octets to for application data (at `Start()`).
     638              :      *  @param[in]  aReservedSize   Number of octets to reserve for protocol headers (before `Start()`).
     639              :      *
     640              :      *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
     641              :      */
     642              :     static PacketBufferHandle New(size_t aAvailableSize, uint16_t aReservedSize = PacketBuffer::kDefaultHeaderReserve);
     643              : 
     644              :     /**
     645              :      * Allocates a packet buffer with initial contents.
     646              :      *
     647              :      *  @param[in]  aData           Initial buffer contents.
     648              :      *  @param[in]  aDataSize       Size of initial buffer contents.
     649              :      *  @param[in]  aAdditionalSize Size of additional application data space after the initial contents.
     650              :      *  @param[in]  aReservedSize   Number of octets to reserve for protocol headers.
     651              :      *
     652              :      *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
     653              :      */
     654              :     static PacketBufferHandle NewWithData(const void * aData, size_t aDataSize, size_t aAdditionalSize = 0,
     655              :                                           uint16_t aReservedSize = PacketBuffer::kDefaultHeaderReserve);
     656              : 
     657              :     /**
     658              :      * Creates a copy of a packet buffer (or chain).
     659              :      *
     660              :      * @returns empty handle on allocation failure. Otherwise, the returned buffer has the same sizes and contents as the original.
     661              :      */
     662              :     PacketBufferHandle CloneData() const;
     663              : 
     664              :     /**
     665              :      * Perform an implementation-defined check on the validity of a PacketBufferHandle.
     666              :      *
     667              :      * Unless enabled by #CHIP_CONFIG_MEMORY_DEBUG_CHECKS == 1, this function does nothing.
     668              :      *
     669              :      * When enabled, it performs an implementation- and configuration-defined check on
     670              :      * the validity of the packet buffer. It MAY log an error and/or abort the program
     671              :      * if the packet buffer or the implementation-defined memory management system is in
     672              :      * a faulty state. (Some configurations may not actually perform any check.)
     673              :      *
     674              :      * @note  A null handle is not considered faulty.
     675              :      */
     676              :     void Check() const
     677              :     {
     678              : #if CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK
     679              :         PacketBuffer::Check(mBuffer);
     680              : #endif
     681              :     }
     682              : 
     683         4525 :     bool operator==(const PacketBufferHandle & aOther) const { return mBuffer == aOther.mBuffer; }
     684              : 
     685              : protected:
     686              : #if CHIP_SYSTEM_CONFIG_USE_LWIP
     687              :     // For use via LwIPPacketBufferView only.
     688              :     static struct pbuf * GetLwIPpbuf(const PacketBufferHandle & handle)
     689              :     {
     690              :         PacketBuffer::Check(handle.mBuffer);
     691              :         return static_cast<struct pbuf *>(handle.mBuffer);
     692              :     }
     693              : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
     694              : 
     695              : private:
     696              :     PacketBufferHandle(const PacketBufferHandle &)             = delete;
     697              :     PacketBufferHandle & operator=(const PacketBufferHandle &) = delete;
     698              : 
     699              :     // The caller's ownership is transferred to this.
     700       125158 :     explicit PacketBufferHandle(PacketBuffer * buffer) : mBuffer(buffer) {}
     701              : 
     702         2580 :     static PacketBufferHandle Hold(PacketBuffer * buffer)
     703              :     {
     704         2580 :         if (buffer != nullptr)
     705              :         {
     706         1775 :             buffer->AddRef();
     707              :         }
     708         2580 :         return PacketBufferHandle(buffer);
     709              :     }
     710              : 
     711        19825 :     PacketBuffer * Get() const { return mBuffer; }
     712         2106 :     PacketBuffer * GetNext() const { return static_cast<PacketBuffer *>(mBuffer->next); }
     713              : 
     714              : #if CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHTSIZE
     715              :     void InternalRightSize();
     716              : #endif
     717              : 
     718              :     PacketBuffer * mBuffer;
     719              : 
     720              :     friend class PacketBuffer;
     721              :     friend class TestSystemPacketBuffer;
     722              : };
     723              : 
     724        45612 : inline void PacketBuffer::SetDataLength(size_t aNewLen, const PacketBufferHandle & aChainHead)
     725              : {
     726        45612 :     SetDataLength(aNewLen, aChainHead.mBuffer);
     727        45612 : }
     728              : 
     729           93 : inline PacketBufferHandle PacketBuffer::Next()
     730              : {
     731           93 :     return PacketBufferHandle::Hold(ChainedBuffer());
     732              : }
     733              : 
     734         1080 : inline PacketBufferHandle PacketBuffer::Last()
     735              : {
     736         1080 :     PacketBuffer * p = this;
     737         1560 :     while (p->HasChainedBuffer())
     738          480 :         p = p->ChainedBuffer();
     739         1080 :     return PacketBufferHandle::Hold(p);
     740              : }
     741              : 
     742              : } // namespace System
     743              : 
     744              : namespace Encoding {
     745              : 
     746              : class PacketBufferWriterUtil
     747              : {
     748              : private:
     749              :     template <typename>
     750              :     friend class PacketBufferWriterBase;
     751              :     static System::PacketBufferHandle Finalize(BufferWriter & aBufferWriter, System::PacketBufferHandle & aPacket);
     752              : };
     753              : 
     754              : /**
     755              :  * BufferWriter backed by packet buffer.
     756              :  *
     757              :  * Typical use:
     758              :  *  @code
     759              :  *      PacketBufferWriter buf(PacketBufferHandle::New(maximumLength));
     760              :  *      if (buf.IsNull()) { return CHIP_ERROR_NO_MEMORY; }
     761              :  *      buf.Put(...);
     762              :  *      ...
     763              :  *      PacketBufferHandle handle = buf.Finalize();
     764              :  *      if (handle.IsNull()) { return CHIP_ERROR_BUFFER_TOO_SMALL; }
     765              :  *      // valid data
     766              :  *  @endcode
     767              :  */
     768              : template <class Writer>
     769              : class PacketBufferWriterBase : public Writer
     770              : {
     771              : public:
     772              :     /**
     773              :      * Constructs a BufferWriter that writes into a packet buffer, using all available space.
     774              :      *
     775              :      *  @param[in]  aPacket  A handle to PacketBuffer, to be used as backing store for the BufferWriter.
     776              :      *                       May be null, e.g. when it holds the result of a failed allocation; the
     777              :      *                       resulting BufferWriter is null and accepts no data.
     778              :      */
     779           36 :     PacketBufferWriterBase(System::PacketBufferHandle && aPacket) : Writer(WritableSpan(aPacket)) { mPacket = std::move(aPacket); }
     780              : 
     781              :     /**
     782              :      * Constructs a BufferWriter that writes into a packet buffer, using no more than the requested space.
     783              :      *
     784              :      *  @param[in]  aPacket A handle to PacketBuffer, to be used as backing store for the BufferWriter.
     785              :      *                      May be null, e.g. when it holds the result of a failed allocation; the
     786              :      *                      resulting BufferWriter is null and accepts no data.
     787              :      *  @param[in]  aSize   Maximum number of octets to write into the packet buffer.
     788              :      */
     789           62 :     PacketBufferWriterBase(System::PacketBufferHandle && aPacket, size_t aSize) : Writer(WritableSpan(aPacket, aSize))
     790              :     {
     791           62 :         mPacket = std::move(aPacket);
     792           62 :     }
     793              : 
     794              :     /**
     795              :      * Test whether this PacketBufferWriter is null, or conversely owns a PacketBuffer.
     796              :      *
     797              :      * @retval true     The PacketBufferWriter is null; it does not own a PacketBuffer. This implies either that
     798              :      *                  construction failed, or that \c Finalize() has previously been called to release the buffer.
     799              :      * @retval false    The PacketBufferWriter owns a PacketBuffer, which can be written using BufferWriter \c Put() methods,
     800              :      *                  and (assuming no overflow) obtained by calling \c Finalize().
     801              :      */
     802           75 :     bool IsNull() const { return mPacket.IsNull(); }
     803              : 
     804              :     /**
     805              :      * Obtain the backing packet buffer, if it is valid.
     806              :      *
     807              :      *  If construction succeeded, \c Finalize() has not already been called, and \c BufferWriter::Fit() is true,
     808              :      *  the caller takes ownership of a buffer containing the desired data. Otherwise, the returned handle tests null,
     809              :      *  and any underlying storage has been released.
     810              :      *
     811              :      *  @return     A packet buffer handle.
     812              :      */
     813           98 :     System::PacketBufferHandle Finalize() { return PacketBufferWriterUtil::Finalize(*this, mPacket); }
     814              : 
     815              : private:
     816              :     /**
     817              :      * The region of \a aPacket available for writing, truncated to \a aMaxSize. Empty if the handle is
     818              :      * null, which is how a failed allocation reaches the constructors.
     819              :      */
     820           98 :     static MutableByteSpan WritableSpan(const System::PacketBufferHandle & aPacket, size_t aMaxSize = SIZE_MAX)
     821              :     {
     822           98 :         VerifyOrReturnValue(!aPacket.IsNull(), MutableByteSpan());
     823           96 :         return MutableByteSpan(aPacket->Start() + aPacket->DataLength(),
     824          192 :                                std::min(aMaxSize, static_cast<size_t>(aPacket->AvailableDataLength())));
     825              :     }
     826              : 
     827              :     System::PacketBufferHandle mPacket;
     828              : };
     829              : 
     830              : using PacketBufferWriter = PacketBufferWriterBase<chip::Encoding::BufferWriter>;
     831              : 
     832              : namespace LittleEndian {
     833              : using PacketBufferWriter = PacketBufferWriterBase<chip::Encoding::LittleEndian::BufferWriter>;
     834              : } // namespace LittleEndian
     835              : 
     836              : namespace BigEndian {
     837              : using PacketBufferWriter = PacketBufferWriterBase<chip::Encoding::BigEndian::BufferWriter>;
     838              : } // namespace BigEndian
     839              : 
     840              : } // namespace Encoding
     841              : 
     842              : } // namespace chip
     843              : 
     844              : #if CHIP_SYSTEM_CONFIG_USE_LWIP
     845              : 
     846              : namespace chip {
     847              : 
     848              : namespace Inet {
     849              : class UDPEndPointImplLwIP;
     850              : } // namespace Inet
     851              : 
     852              : namespace System {
     853              : 
     854              : /**
     855              :  * Provide low-level access to a raw `pbuf *`, limited to specific classes that interface with LwIP.
     856              :  */
     857              : class LwIPPacketBufferView : public PacketBufferHandle
     858              : {
     859              : private:
     860              :     /**
     861              :      * Borrow a raw LwIP `pbuf *`.
     862              :      *
     863              :      * @brief The caller has access but no ownership.
     864              :      *
     865              :      * @note This should be used ONLY by low-level code interfacing with LwIP.
     866              :      */
     867              :     static struct pbuf * UnsafeGetLwIPpbuf(const PacketBufferHandle & handle) { return PacketBufferHandle::GetLwIPpbuf(handle); }
     868              :     friend class Inet::UDPEndPointImplLwIP;
     869              : };
     870              : 
     871              : } // namespace System
     872              : } // namespace chip
     873              : 
     874              : #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
        

Generated by: LCOV version 2.0-1