Matter SDK Coverage Report
Current view: top level - transport/raw - TCP.h (source / functions) Coverage Total Hit
Test: SHA:f84fe08d06f240e801b5d923f8a938a9938ca110 Lines: 70.0 % 30 21
Test Date: 2025-02-22 08:08:07 Functions: 75.0 % 16 12

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

Generated by: LCOV version 2.0-1