LCOV - code coverage report
Current view: top level - system - SystemPacketBuffer.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 67 78 85.9 %
Date: 2024-02-15 08:20:41 Functions: 28 32 87.5 %

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

Generated by: LCOV version 1.14