LCOV - code coverage report
Current view: top level - transport/raw - TCP.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 10 17 58.8 %
Date: 2024-02-15 08:20:41 Functions: 6 8 75.0 %

          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/Base.h>
      38             : 
      39             : namespace chip {
      40             : namespace Transport {
      41             : 
      42             : /** Defines listening parameters for setting up a TCP transport */
      43             : class TcpListenParameters
      44             : {
      45             : public:
      46             :     explicit TcpListenParameters(Inet::EndPointManager<Inet::TCPEndPoint> * endPointManager) : mEndPointManager(endPointManager) {}
      47             :     TcpListenParameters(const TcpListenParameters &) = default;
      48             :     TcpListenParameters(TcpListenParameters &&)      = default;
      49             : 
      50           5 :     Inet::EndPointManager<Inet::TCPEndPoint> * GetEndPointManager() { return mEndPointManager; }
      51             : 
      52          10 :     Inet::IPAddressType GetAddressType() const { return mAddressType; }
      53             :     TcpListenParameters & SetAddressType(Inet::IPAddressType type)
      54             :     {
      55             :         mAddressType = type;
      56             : 
      57             :         return *this;
      58             :     }
      59             : 
      60           5 :     uint16_t GetListenPort() const { return mListenPort; }
      61             :     TcpListenParameters & SetListenPort(uint16_t port)
      62             :     {
      63             :         mListenPort = port;
      64             : 
      65             :         return *this;
      66             :     }
      67             : 
      68           5 :     Inet::InterfaceId GetInterfaceId() const { return mInterfaceId; }
      69             :     TcpListenParameters & SetInterfaceId(Inet::InterfaceId id)
      70             :     {
      71             :         mInterfaceId = id;
      72             : 
      73             :         return *this;
      74             :     }
      75             : 
      76             : private:
      77             :     Inet::EndPointManager<Inet::TCPEndPoint> * mEndPointManager;   ///< Associated endpoint factory
      78             :     Inet::IPAddressType mAddressType = Inet::IPAddressType::kIPv6; ///< type of listening socket
      79             :     uint16_t mListenPort             = CHIP_PORT;                  ///< TCP listen port
      80             :     Inet::InterfaceId mInterfaceId   = Inet::InterfaceId::Null();  ///< Interface to listen on
      81             : };
      82             : 
      83             : /**
      84             :  * Packets scheduled for sending once a connection has been established.
      85             :  */
      86             : struct PendingPacket
      87             : {
      88             :     PendingPacket(const PeerAddress & peerAddress, System::PacketBufferHandle && packetBuffer) :
      89             :         mPeerAddress(peerAddress), mPacketBuffer(std::move(packetBuffer))
      90             :     {}
      91             : 
      92             :     PeerAddress mPeerAddress;                 // where the packet is being sent to
      93             :     System::PacketBufferHandle mPacketBuffer; // what data needs to be sent
      94             : };
      95             : 
      96             : /** Implements a transport using TCP. */
      97             : class DLL_EXPORT TCPBase : public Base
      98             : {
      99             :     /**
     100             :      *  The State of the TCP connection
     101             :      */
     102             :     enum class State
     103             :     {
     104             :         kNotReady    = 0, /**< State before initialization. */
     105             :         kInitialized = 1, /**< State after class is listening and ready. */
     106             :     };
     107             : 
     108             : protected:
     109             :     /**
     110             :      *  State for each active connection
     111             :      */
     112             :     struct ActiveConnectionState
     113             :     {
     114           0 :         void Init(Inet::TCPEndPoint * endPoint)
     115             :         {
     116           0 :             mEndPoint = endPoint;
     117           0 :             mReceived = nullptr;
     118           0 :         }
     119             : 
     120           6 :         void Free()
     121             :         {
     122           6 :             mEndPoint->Free();
     123           6 :             mEndPoint = nullptr;
     124           6 :             mReceived = nullptr;
     125           6 :         }
     126          67 :         bool InUse() const { return mEndPoint != nullptr; }
     127             : 
     128             :         // Associated endpoint.
     129             :         Inet::TCPEndPoint * mEndPoint;
     130             : 
     131             :         // Buffers received but not yet consumed.
     132             :         System::PacketBufferHandle mReceived;
     133             :     };
     134             : 
     135             : public:
     136             :     using PendingPacketPoolType = PoolInterface<PendingPacket, const PeerAddress &, System::PacketBufferHandle &&>;
     137             :     TCPBase(ActiveConnectionState * activeConnectionsBuffer, size_t bufferSize, PendingPacketPoolType & packetBuffers) :
     138             :         mActiveConnections(activeConnectionsBuffer), mActiveConnectionsSize(bufferSize), mPendingPackets(packetBuffers)
     139             :     {
     140             :         // activeConnectionsBuffer must be initialized by the caller.
     141             :     }
     142             :     ~TCPBase() override;
     143             : 
     144             :     /**
     145             :      * Initialize a TCP transport on a given port.
     146             :      *
     147             :      * @param params        TCP configuration parameters for this transport
     148             :      *
     149             :      * @details
     150             :      *   Generally send and receive ports should be the same and equal to CHIP_PORT.
     151             :      *   The class allows separate definitions to allow local execution of several
     152             :      *   Nodes.
     153             :      */
     154             :     CHIP_ERROR Init(TcpListenParameters & params);
     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             :     void Disconnect(const PeerAddress & address) override;
     164             : 
     165           0 :     bool CanSendToPeer(const PeerAddress & address) override
     166             :     {
     167           0 :         return (mState == State::kInitialized) && (address.GetTransportType() == Type::kTcp) &&
     168           0 :             (address.GetIPAddress().Type() == mEndpointType);
     169             :     }
     170             : 
     171             :     /**
     172             :      * Helper method to determine if IO processing is still required for a TCP transport
     173             :      * before everything is cleaned up (socket closing is async, so after calling 'Close' on
     174             :      * the transport, some time may be needed to actually be able to close.)
     175             :      */
     176             :     bool HasActiveConnections() const;
     177             : 
     178             :     /**
     179             :      * Close all active connections.
     180             :      */
     181             :     void CloseActiveConnections();
     182             : 
     183             : private:
     184             :     friend class TCPTest;
     185             : 
     186             :     /**
     187             :      * Find an active connection to the given peer or return nullptr if
     188             :      * no active connection exists.
     189             :      */
     190             :     ActiveConnectionState * FindActiveConnection(const PeerAddress & addr);
     191             :     ActiveConnectionState * FindActiveConnection(const Inet::TCPEndPoint * endPoint);
     192             : 
     193             :     /**
     194             :      * Sends the specified message once a connection has been established.
     195             :      *
     196             :      * @param addr - what peer to connect to
     197             :      * @param msg - what buffer to send once a connection has been established.
     198             :      *
     199             :      * Ownership of msg is taken over and will be freed at some unspecified time
     200             :      * in the future (once connection succeeds/fails).
     201             :      */
     202             :     CHIP_ERROR SendAfterConnect(const PeerAddress & addr, System::PacketBufferHandle && msg);
     203             : 
     204             :     /**
     205             :      * Process a single received buffer from the specified peer address.
     206             :      *
     207             :      * @param endPoint the source end point from which the data comes from
     208             :      * @param peerAddress the peer the data is coming from
     209             :      * @param buffer the actual data
     210             :      *
     211             :      * Ownership of buffer is taken over and will be freed (or re-enqueued to the endPoint receive queue)
     212             :      * as needed during processing.
     213             :      */
     214             :     CHIP_ERROR ProcessReceivedBuffer(Inet::TCPEndPoint * endPoint, const PeerAddress & peerAddress,
     215             :                                      System::PacketBufferHandle && buffer);
     216             : 
     217             :     /**
     218             :      * Process a single message of the specified size from a buffer.
     219             :      *
     220             :      * @param[in]     peerAddress   The peer the data is coming from.
     221             :      * @param[in,out] state         The connection state, which contains the message. On entry, the payload points to the message
     222             :      *                              body (after the length). On exit, it points after the message (or the queue is null, if there
     223             :      *                              is no other data).
     224             :      * @param[in]     messageSize   Size of the single message.
     225             :      */
     226             :     CHIP_ERROR ProcessSingleMessage(const PeerAddress & peerAddress, ActiveConnectionState * state, uint16_t messageSize);
     227             : 
     228             :     // Release an active connection (corresponding to the passed TCPEndPoint)
     229             :     // from the pool.
     230             :     void ReleaseActiveConnection(Inet::TCPEndPoint * endPoint);
     231             : 
     232             :     // Callback handler for TCPEndPoint. TCP message receive handler.
     233             :     // @see TCPEndpoint::OnDataReceivedFunct
     234             :     static CHIP_ERROR OnTcpReceive(Inet::TCPEndPoint * endPoint, System::PacketBufferHandle && buffer);
     235             : 
     236             :     // Callback handler for TCPEndPoint. Called when a connection has been completed.
     237             :     // @see TCPEndpoint::OnConnectCompleteFunct
     238             :     static void OnConnectionComplete(Inet::TCPEndPoint * endPoint, CHIP_ERROR err);
     239             : 
     240             :     // Callback handler for TCPEndPoint. Called when a connection has been closed.
     241             :     // @see TCPEndpoint::OnConnectionClosedFunct
     242             :     static void OnConnectionClosed(Inet::TCPEndPoint * endPoint, CHIP_ERROR err);
     243             : 
     244             :     // Callback handler for TCPEndPoint. Callend when a peer closes the connection.
     245             :     // @see TCPEndpoint::OnPeerCloseFunct
     246             :     static void OnPeerClosed(Inet::TCPEndPoint * endPoint);
     247             : 
     248             :     // Callback handler for TCPEndPoint. Called when a connection is received on the listening port.
     249             :     // @see TCPEndpoint::OnConnectionReceivedFunct
     250             :     static void OnConnectionReceived(Inet::TCPEndPoint * listenEndPoint, Inet::TCPEndPoint * endPoint,
     251             :                                      const Inet::IPAddress & peerAddress, uint16_t peerPort);
     252             : 
     253             :     // Called on accept error
     254             :     // @see TCPEndpoint::OnAcceptErrorFunct
     255             :     static void OnAcceptError(Inet::TCPEndPoint * endPoint, CHIP_ERROR err);
     256             : 
     257             :     Inet::TCPEndPoint * mListenSocket = nullptr;                       ///< TCP socket used by the transport
     258             :     Inet::IPAddressType mEndpointType = Inet::IPAddressType::kUnknown; ///< Socket listening type
     259             :     State mState                      = State::kNotReady;              ///< State of the TCP transport
     260             : 
     261             :     // Number of active and 'pending connection' endpoints
     262             :     size_t mUsedEndPointCount = 0;
     263             : 
     264             :     // Currently active connections
     265             :     ActiveConnectionState * mActiveConnections;
     266             :     const size_t mActiveConnectionsSize;
     267             : 
     268             :     // Data to be sent when connections succeed
     269             :     PendingPacketPoolType & mPendingPackets;
     270             : };
     271             : 
     272             : template <size_t kActiveConnectionsSize, size_t kPendingPacketSize>
     273             : class TCP : public TCPBase
     274             : {
     275             : public:
     276             :     TCP() : TCPBase(mConnectionsBuffer, kActiveConnectionsSize, mPendingPackets)
     277             :     {
     278             :         for (size_t i = 0; i < kActiveConnectionsSize; ++i)
     279             :         {
     280             :             mConnectionsBuffer[i].Init(nullptr);
     281             :         }
     282             :     }
     283             :     ~TCP() override { mPendingPackets.ReleaseAll(); }
     284             : 
     285             : private:
     286             :     friend class TCPTest;
     287             :     TCPBase::ActiveConnectionState mConnectionsBuffer[kActiveConnectionsSize];
     288             :     PoolImpl<PendingPacket, kPendingPacketSize, ObjectPoolMem::kInline, PendingPacketPoolType::Interface> mPendingPackets;
     289             : };
     290             : 
     291             : } // namespace Transport
     292             : } // namespace chip

Generated by: LCOV version 1.14