Matter SDK Coverage Report
Current view: top level - transport/raw - TCP.h (source / functions) Coverage Total Hit
Test: SHA:db08debc068562b264a2df3a7f3a8cc1d0b3aba1 Lines: 90.0 % 30 27
Test Date: 2025-10-02 07:10:30 Functions: 82.4 % 17 14

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2021 Project CHIP Authors
       4              :  *    All rights reserved.
       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 Connection object that maintains TCP connections.
      22              :  *      It binds to any available local addr and port and begins listening.
      23              :  */
      24              : 
      25              : #pragma once
      26              : 
      27              : #include <algorithm>
      28              : #include <new>
      29              : #include <utility>
      30              : 
      31              : #include <inet/IPAddress.h>
      32              : #include <inet/InetInterface.h>
      33              : #include <inet/TCPEndPoint.h>
      34              : #include <lib/core/CHIPCore.h>
      35              : #include <lib/support/CodeUtils.h>
      36              : #include <lib/support/PoolWrapper.h>
      37              : #include <transport/raw/ActiveTCPConnectionState.h>
      38              : #include <transport/raw/Base.h>
      39              : #include <transport/raw/TCPConfig.h>
      40              : 
      41              : namespace chip {
      42              : namespace Transport {
      43              : 
      44              : /** Defines listening parameters for setting up a TCP transport */
      45              : class TcpListenParameters
      46              : {
      47              : public:
      48           17 :     explicit TcpListenParameters(Inet::EndPointManager<Inet::TCPEndPoint> * endPointManager) : mEndPointManager(endPointManager) {}
      49            1 :     TcpListenParameters(const TcpListenParameters &) = default;
      50              :     TcpListenParameters(TcpListenParameters &&)      = default;
      51              : 
      52           17 :     Inet::EndPointManager<Inet::TCPEndPoint> * GetEndPointManager() { return mEndPointManager; }
      53              : 
      54           33 :     Inet::IPAddressType GetAddressType() const { return mAddressType; }
      55           17 :     TcpListenParameters & SetAddressType(Inet::IPAddressType type)
      56              :     {
      57           17 :         mAddressType = type;
      58              : 
      59           17 :         return *this;
      60              :     }
      61              : 
      62           32 :     uint16_t GetListenPort() const { return mListenPort; }
      63           17 :     TcpListenParameters & SetListenPort(uint16_t port)
      64              :     {
      65           17 :         mListenPort = port;
      66              : 
      67           17 :         return *this;
      68              :     }
      69              : 
      70           16 :     Inet::InterfaceId GetInterfaceId() const { return mInterfaceId; }
      71              :     TcpListenParameters & SetInterfaceId(Inet::InterfaceId id)
      72              :     {
      73              :         mInterfaceId = id;
      74              : 
      75              :         return *this;
      76              :     }
      77              : 
      78           20 :     bool IsServerListenEnabled() const { return mServerListenEnabled; }
      79            1 :     TcpListenParameters & SetServerListenEnabled(bool listenEnable)
      80              :     {
      81            1 :         mServerListenEnabled = listenEnable;
      82              : 
      83            1 :         return *this;
      84              :     }
      85              : 
      86              : private:
      87              :     Inet::EndPointManager<Inet::TCPEndPoint> * mEndPointManager;   ///< Associated endpoint factory
      88              :     Inet::IPAddressType mAddressType = Inet::IPAddressType::kIPv6; ///< type of listening socket
      89              :     uint16_t mListenPort             = CHIP_PORT;                  ///< TCP listen port
      90              :     Inet::InterfaceId mInterfaceId   = Inet::InterfaceId::Null();  ///< Interface to listen on
      91              :     bool mServerListenEnabled        = true;                       ///< TCP Server mode enabled
      92              : };
      93              : 
      94              : /**
      95              :  * Packets scheduled for sending once a connection has been established.
      96              :  */
      97              : struct PendingPacket
      98              : {
      99            5 :     PendingPacket(const PeerAddress & peerAddress, System::PacketBufferHandle && packetBuffer) :
     100            5 :         mPeerAddress(peerAddress), mPacketBuffer(std::move(packetBuffer))
     101            5 :     {}
     102              : 
     103              :     PeerAddress mPeerAddress;                 // where the packet is being sent to
     104              :     System::PacketBufferHandle mPacketBuffer; // what data needs to be sent
     105              : };
     106              : 
     107              : /** Implements a transport using TCP. */
     108              : class DLL_EXPORT TCPBase : public Base
     109              : {
     110              : 
     111              : protected:
     112              :     enum class ShouldAbort : uint8_t
     113              :     {
     114              :         Yes,
     115              :         No
     116              :     };
     117              : 
     118              :     enum class SuppressCallback : uint8_t
     119              :     {
     120              :         Yes,
     121              :         No
     122              :     };
     123              : 
     124              : public:
     125              :     using PendingPacketPoolType = PoolInterface<PendingPacket, const PeerAddress &, System::PacketBufferHandle &&>;
     126           27 :     TCPBase(ActiveTCPConnectionState * activeConnectionsBuffer, size_t bufferSize, PendingPacketPoolType & packetBuffers) :
     127           27 :         mActiveConnections(activeConnectionsBuffer), mActiveConnectionsSize(bufferSize), mPendingPackets(packetBuffers)
     128              :     {
     129              :         // activeConnectionsBuffer must be initialized by the caller.
     130           27 :     }
     131              :     ~TCPBase() override;
     132              : 
     133              :     /**
     134              :      * Initialize a TCP transport on a given port.
     135              :      *
     136              :      * @param params        TCP configuration parameters for this transport
     137              :      *
     138              :      * @details
     139              :      *   Generally send and receive ports should be the same and equal to CHIP_PORT.
     140              :      *   The class allows separate definitions to allow local execution of several
     141              :      *   Nodes.
     142              :      */
     143              :     CHIP_ERROR Init(TcpListenParameters & params);
     144              : 
     145              :     /**
     146              :      * Set the timeout (in milliseconds) for the node to wait for the TCP
     147              :      * connection attempt to complete.
     148              :      *
     149              :      */
     150              :     void SetConnectTimeout(const uint32_t connTimeoutMsecs) { mConnectTimeout = connTimeoutMsecs; }
     151              : 
     152              :     /**
     153              :      * Close the open endpoint without destroying the object
     154              :      */
     155              :     void Close() override;
     156              : 
     157              :     CHIP_ERROR SendMessage(const PeerAddress & address, System::PacketBufferHandle && msgBuf) override;
     158              :     CHIP_ERROR SendMessage(const ActiveTCPConnectionHolder & connection, System::PacketBufferHandle && msgBuf);
     159              : 
     160              :     /*
     161              :      * Connect to the given peerAddress over TCP.
     162              :      *
     163              :      * @param address           The address of the peer.
     164              :      *
     165              :      * @param appState          Context passed in by the application to be sent back
     166              :      *                          via the connection attempt complete callback when
     167              :      *                          connection attempt with peer completes.
     168              :      *
     169              :      * @param outPeerConnState  Pointer to pointer to the active TCP connection state. This is
     170              :      *                          an output parameter that is allocated by the
     171              :      *                          transport layer and held by the caller object.
     172              :      *                          This allows the caller object to abort the
     173              :      *                          connection attempt if the caller object dies
     174              :      *                          before the attempt completes.
     175              :      *
     176              :      */
     177              :     CHIP_ERROR TCPConnect(const PeerAddress & address, Transport::AppTCPConnectionCallbackCtxt * appState,
     178              :                           Transport::ActiveTCPConnectionHolder & outPeerConnState) override;
     179              : 
     180            0 :     bool CanSendToPeer(const PeerAddress & address) override
     181              :     {
     182            0 :         return (mState == TCPState::kInitialized) && (address.GetTransportType() == Type::kTcp) &&
     183            0 :             (address.GetIPAddress().Type() == mEndpointType);
     184              :     }
     185              : 
     186              :     const Optional<PeerAddress> GetConnectionPeerAddress(const Inet::TCPEndPoint * con)
     187              :     {
     188              :         ActiveTCPConnectionHolder activeConState = FindActiveConnection(con);
     189              : 
     190              :         return !activeConState.IsNull() ? MakeOptional<PeerAddress>(activeConState->mPeerAddr) : Optional<PeerAddress>::Missing();
     191              :     }
     192              : 
     193              :     /**
     194              :      * Helper method to determine if IO processing is still required for a TCP transport
     195              :      * before everything is cleaned up (socket closing is async, so after calling 'Close' on
     196              :      * the transport, some time may be needed to actually be able to close.)
     197              :      */
     198              :     bool HasActiveConnections() const;
     199              : 
     200              :     /**
     201              :      * Close all active connections.
     202              :      */
     203              :     void CloseActiveConnections();
     204              : 
     205              : private:
     206              :     // Allow tests to access private members.
     207              :     template <size_t kActiveConnectionsSize, size_t kPendingPacketSize>
     208              :     friend class TCPBaseTestAccess;
     209              : 
     210              :     /**
     211              :      * Allocate and initialize a connection from the pool.
     212              :      */
     213              :     ActiveTCPConnectionState * AllocateConnection(Inet::TCPEndPoint * endpoint, const PeerAddress & address);
     214              :     /**
     215              :      * Find an active connection to the given peer or return nullptr if
     216              :      * no active connection exists.
     217              :      */
     218              :     ActiveTCPConnectionHolder FindInUseConnection(const PeerAddress & addr);
     219              :     ActiveTCPConnectionState * FindActiveConnection(const Inet::TCPEndPoint * endPoint);
     220              : 
     221              :     /**
     222              :      * Find an allocated connection that matches the corresponding TCPEndPoint.
     223              :      */
     224              :     ActiveTCPConnectionHolder FindInUseConnection(const Inet::TCPEndPoint * endPoint);
     225              : 
     226              :     /**
     227              :      * Sends the specified message once a connection has been established.
     228              :      *
     229              :      * @param existing - an already-existing connection; must not be empty
     230              :      * @param msg - what buffer to send once a connection has been established.
     231              :      *
     232              :      * Ownership of msg is taken over and will be freed at some unspecified time
     233              :      * in the future (once connection succeeds/fails).
     234              :      */
     235              :     CHIP_ERROR SendAfterConnect(const ActiveTCPConnectionHolder & existing, System::PacketBufferHandle && msg);
     236              : 
     237              :     /**
     238              :      * Process a single received buffer from the specified peer address.
     239              :      *
     240              :      * @param endPoint the source end point from which the data comes from
     241              :      * @param peerAddress the peer the data is coming from
     242              :      * @param buffer the actual data
     243              :      *
     244              :      * Ownership of buffer is taken over and will be freed (or re-enqueued to the endPoint receive queue)
     245              :      * as needed during processing.
     246              :      */
     247              :     CHIP_ERROR ProcessReceivedBuffer(Inet::TCPEndPoint * endPoint, const PeerAddress & peerAddress,
     248              :                                      System::PacketBufferHandle && buffer);
     249              : 
     250              :     /**
     251              :      * Process a single message of the specified size from a buffer.
     252              :      *
     253              :      * @param[in]     peerAddress   The peer the data is coming from.
     254              :      * @param[in,out] state         The connection state, which contains the message. On entry, the payload points to the message
     255              :      *                              body (after the length). On exit, it points after the message (or the queue is null, if there
     256              :      *                              is no other data).
     257              :      * @param[in]     messageSize   Size of the single message.
     258              :      */
     259              :     CHIP_ERROR ProcessSingleMessage(const PeerAddress & peerAddress, ActiveTCPConnectionState & state, size_t messageSize);
     260              : 
     261              :     /**
     262              :      * Initiate a connection to the given peer. On connection completion,
     263              :      * HandleTCPConnectComplete callback would be called.
     264              :      *
     265              :      */
     266              :     CHIP_ERROR StartConnect(const PeerAddress & addr, AppTCPConnectionCallbackCtxt * appState,
     267              :                             ActiveTCPConnectionHolder & outPeerConnState);
     268              : 
     269              :     // Close an active connection (corresponding to the passed
     270              :     // ActiveTCPConnectionState object)
     271              :     // and release from the pool.
     272              :     void TCPDisconnect(ActiveTCPConnectionState & conn, bool shouldAbort = false);
     273              : 
     274              :     /**
     275              :      * Gracefully Close or Abort a given connection.
     276              :      *
     277              :      */
     278              :     void CloseConnectionInternal(ActiveTCPConnectionState & connection, CHIP_ERROR err, SuppressCallback suppressCallback);
     279              : 
     280              :     // Close the listening socket endpoint
     281              :     void CloseListeningSocket();
     282              : 
     283              :     // Callback handler for TCPEndPoint. TCP message receive handler.
     284              :     // @see TCPEndpoint::OnDataReceivedFunct
     285              :     static CHIP_ERROR HandleTCPEndPointDataReceived(Inet::TCPEndPoint * endPoint, System::PacketBufferHandle && buffer);
     286              : 
     287              :     // Callback handler for TCPEndPoint. Called when a connection has been completed.
     288              :     // @see TCPEndpoint::OnConnectCompleteFunct
     289              :     static void HandleTCPEndPointConnectComplete(Inet::TCPEndPoint * endPoint, CHIP_ERROR err);
     290              : 
     291              :     // Callback handler for TCPEndPoint. Called when a connection has been closed.
     292              :     // @see TCPEndpoint::OnConnectionClosedFunct
     293              :     static void HandleTCPEndPointConnectionClosed(Inet::TCPEndPoint * endPoint, CHIP_ERROR err);
     294              : 
     295              :     // Callback handler for TCPEndPoint. Called when a connection is received on the listening port.
     296              :     // @see TCPEndpoint::OnConnectionReceivedFunct
     297              :     static void HandleIncomingConnection(Inet::TCPEndPoint * listenEndPoint, Inet::TCPEndPoint * endPoint,
     298              :                                          const Inet::IPAddress & peerAddress, uint16_t peerPort);
     299              : 
     300              :     // Callback handler for handling accept error
     301              :     // @see TCPEndpoint::OnAcceptErrorFunct
     302              :     static void HandleAcceptError(Inet::TCPEndPoint * endPoint, CHIP_ERROR err);
     303              : 
     304              :     void InitEndpoint(Inet::TCPEndPoint * endpoint);
     305              :     CHIP_ERROR TryResetConnection(ActiveTCPConnectionState & connection);
     306              :     CHIP_ERROR PrepareBuffer(System::PacketBufferHandle & msgBuf);
     307              : 
     308              :     Inet::TCPEndPoint * mListenSocket = nullptr;                       ///< TCP socket used by the transport
     309              :     Inet::IPAddressType mEndpointType = Inet::IPAddressType::kUnknown; ///< Socket listening type
     310              :     TCPState mState                   = TCPState::kNotReady;           ///< State of the TCP transport
     311              : 
     312              :     // The configured timeout for the connection attempt to the peer, before
     313              :     // giving up.
     314              :     uint32_t mConnectTimeout = CHIP_CONFIG_TCP_CONNECT_TIMEOUT_MSECS;
     315              : 
     316              :     // Number of active and 'pending connection' endpoints
     317              :     size_t mUsedEndPointCount = 0;
     318              : 
     319              :     // Currently active connections
     320              :     ActiveTCPConnectionState * mActiveConnections;
     321              :     const size_t mActiveConnectionsSize;
     322              : 
     323              :     // Data to be sent when connections succeed
     324              :     PendingPacketPoolType & mPendingPackets;
     325              : };
     326              : 
     327              : template <size_t kActiveConnectionsSize, size_t kPendingPacketSize>
     328              : class TCP : public TCPBase
     329              : {
     330              : public:
     331          135 :     TCP() : TCPBase(mConnectionsBuffer, kActiveConnectionsSize, mPendingPackets)
     332              :     {
     333          135 :         for (size_t i = 0; i < kActiveConnectionsSize; ++i)
     334              :         {
     335          108 :             mConnectionsBuffer[i].Init(nullptr, PeerAddress::Uninitialized(), [](auto &) {});
     336              :         }
     337           27 :     }
     338              : 
     339          135 :     ~TCP() override { mPendingPackets.ReleaseAll(); }
     340              : 
     341              : private:
     342              :     ActiveTCPConnectionState mConnectionsBuffer[kActiveConnectionsSize];
     343              :     PoolImpl<PendingPacket, kPendingPacketSize, ObjectPoolMem::kInline, PendingPacketPoolType::Interface> mPendingPackets;
     344              : };
     345              : 
     346              : } // namespace Transport
     347              : } // namespace chip
        

Generated by: LCOV version 2.0-1