LCOV - code coverage report
Current view: top level - transport/raw - PeerAddress.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 43 71 60.6 %
Date: 2024-02-15 08:20:41 Functions: 16 24 66.7 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2020 Project CHIP Authors
       4             :  *
       5             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6             :  *    you may not use this file except in compliance with the License.
       7             :  *    You may obtain a copy of the License at
       8             :  *
       9             :  *        http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  *    Unless required by applicable law or agreed to in writing, software
      12             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  *    See the License for the specific language governing permissions and
      15             :  *    limitations under the License.
      16             :  */
      17             : 
      18             : /**
      19             :  * @brief
      20             :  *    File contains definitions on how a connection to a peer can be defined.
      21             :  *
      22             :  */
      23             : 
      24             : #pragma once
      25             : 
      26             : #include <inet/IPAddress.h>
      27             : #include <inet/InetInterface.h>
      28             : #include <lib/core/CHIPConfig.h>
      29             : #include <lib/core/DataModelTypes.h>
      30             : #include <lib/support/CHIPMemString.h>
      31             : 
      32             : namespace chip {
      33             : namespace Transport {
      34             : 
      35             : /**
      36             :  * Communication path defines how two peers communicate.
      37             :  *
      38             :  * When a peer contacts another peer, it defines how the peers communicate.
      39             :  *
      40             :  * Once communication between two peers is established, the same transport
      41             :  * path should be used: a peer contacting another peer over UDP will receive
      42             :  * messages back over UDP. A communication channel established over TCP
      43             :  * will keep the same TCP channel.
      44             :  *
      45             :  */
      46             : 
      47             : /**
      48             :  * Here we specified Type to be uint8_t, so the PeerAddress can be serialized easily.
      49             :  */
      50             : enum class Type : uint8_t
      51             : {
      52             :     kUndefined,
      53             :     kUdp,
      54             :     kBle,
      55             :     kTcp,
      56             : };
      57             : 
      58             : /**
      59             :  * Describes how a peer on a CHIP network can be addressed.
      60             :  */
      61             : class PeerAddress
      62             : {
      63             : public:
      64         149 :     PeerAddress() : mIPAddress(Inet::IPAddress::Any), mTransportType(Type::kUndefined) {}
      65           0 :     PeerAddress(const Inet::IPAddress & addr, Type type) : mIPAddress(addr), mTransportType(type) {}
      66           0 :     PeerAddress(Type type) : mTransportType(type) {}
      67             : 
      68             :     PeerAddress(PeerAddress &&)                  = default;
      69           0 :     PeerAddress(const PeerAddress &)             = default;
      70       10732 :     PeerAddress & operator=(const PeerAddress &) = default;
      71           2 :     PeerAddress & operator=(PeerAddress &&)      = default;
      72             : 
      73           6 :     const Inet::IPAddress & GetIPAddress() const { return mIPAddress; }
      74           0 :     PeerAddress & SetIPAddress(const Inet::IPAddress & addr)
      75             :     {
      76           0 :         mIPAddress = addr;
      77           0 :         return *this;
      78             :     }
      79             : 
      80       44953 :     Type GetTransportType() const { return mTransportType; }
      81             :     PeerAddress & SetTransportType(Type type)
      82             :     {
      83             :         mTransportType = type;
      84             :         return *this;
      85             :     }
      86             : 
      87           9 :     uint16_t GetPort() const { return mPort; }
      88          12 :     PeerAddress & SetPort(uint16_t port)
      89             :     {
      90          12 :         mPort = port;
      91          12 :         return *this;
      92             :     }
      93             : 
      94         104 :     Inet::InterfaceId GetInterface() const { return mInterface; }
      95          15 :     PeerAddress & SetInterface(Inet::InterfaceId interface)
      96             :     {
      97          15 :         mInterface = interface;
      98          15 :         return *this;
      99             :     }
     100             : 
     101             :     bool IsInitialized() const { return mTransportType != Type::kUndefined; }
     102             : 
     103             :     bool IsMulticast() { return Type::kUdp == mTransportType && mIPAddress.IsIPv6Multicast(); }
     104             : 
     105        9398 :     bool operator==(const PeerAddress & other) const
     106             :     {
     107       18568 :         return (mTransportType == other.mTransportType) && (mIPAddress == other.mIPAddress) && (mPort == other.mPort) &&
     108       18568 :             (mInterface == other.mInterface);
     109             :     }
     110             : 
     111        9389 :     bool operator!=(const PeerAddress & other) const { return !(*this == other); }
     112             : 
     113             :     /// Maximum size of the string outputes by ToString. Format is of the form:
     114             :     /// "UDP:<ip>:<port>"
     115             :     static constexpr size_t kMaxToStringSize = 3 // type: UDP/TCP/BLE
     116             :         + 1                                      // splitter :
     117             :         + 2                                      // brackets around address
     118             :         + Inet::IPAddress::kMaxStringLength      // address
     119             :         + 1                                      // splitter %
     120             :         + Inet::InterfaceId::kMaxIfNameLength    // interface
     121             :         + 1                                      // splitter :
     122             :         + 5                                      // port: 16 bit interger
     123             :         + 1;                                     // NullTerminator
     124             : 
     125             :     template <size_t N>
     126        9614 :     inline void ToString(char (&buf)[N]) const
     127             :     {
     128        9614 :         ToString(buf, N);
     129        9614 :     }
     130             : 
     131        9614 :     void ToString(char * buf, size_t bufSize) const
     132             :     {
     133             :         char ip_addr[Inet::IPAddress::kMaxStringLength];
     134             : 
     135        9614 :         char interface[Inet::InterfaceId::kMaxIfNameLength + 1] = {}; // +1 to prepend '%'
     136        9614 :         if (mInterface.IsPresent())
     137             :         {
     138           0 :             interface[0]   = '%';
     139           0 :             interface[1]   = 0;
     140           0 :             CHIP_ERROR err = mInterface.GetInterfaceName(interface + 1, sizeof(interface) - 1);
     141           0 :             if (err != CHIP_NO_ERROR)
     142             :             {
     143           0 :                 Platform::CopyString(interface, sizeof(interface), "%(err)");
     144             :             }
     145             :         }
     146             : 
     147        9614 :         switch (mTransportType)
     148             :         {
     149          47 :         case Type::kUndefined:
     150          47 :             snprintf(buf, bufSize, "UNDEFINED");
     151          47 :             break;
     152        9567 :         case Type::kUdp:
     153        9567 :             mIPAddress.ToString(ip_addr);
     154             : #if INET_CONFIG_ENABLE_IPV4
     155        9567 :             if (mIPAddress.IsIPv4())
     156           0 :                 snprintf(buf, bufSize, "UDP:%s%s:%d", ip_addr, interface, mPort);
     157             :             else
     158             : #endif
     159        9567 :                 snprintf(buf, bufSize, "UDP:[%s%s]:%d", ip_addr, interface, mPort);
     160        9567 :             break;
     161           0 :         case Type::kTcp:
     162           0 :             mIPAddress.ToString(ip_addr);
     163             : #if INET_CONFIG_ENABLE_IPV4
     164           0 :             if (mIPAddress.IsIPv4())
     165           0 :                 snprintf(buf, bufSize, "TCP:%s%s:%d", ip_addr, interface, mPort);
     166             :             else
     167             : #endif
     168           0 :                 snprintf(buf, bufSize, "TCP:[%s%s]:%d", ip_addr, interface, mPort);
     169           0 :             break;
     170           0 :         case Type::kBle:
     171             :             // Note that BLE does not currently use any specific address.
     172           0 :             snprintf(buf, bufSize, "BLE");
     173           0 :             break;
     174           0 :         default:
     175           0 :             snprintf(buf, bufSize, "ERROR");
     176           0 :             break;
     177             :         }
     178        9614 :     }
     179             : 
     180             :     /****** Factory methods for convenience ******/
     181             : 
     182             :     static PeerAddress Uninitialized() { return PeerAddress(Inet::IPAddress::Any, Type::kUndefined); }
     183             : 
     184           0 :     static PeerAddress BLE() { return PeerAddress(Type::kBle); }
     185           0 :     static PeerAddress UDP(const Inet::IPAddress & addr) { return PeerAddress(addr, Type::kUdp); }
     186           0 :     static PeerAddress UDP(const Inet::IPAddress & addr, uint16_t port) { return UDP(addr).SetPort(port); }
     187             : 
     188             :     /**
     189             :      * Parses a PeerAddress from the given IP address string with UDP type. For example,
     190             :      * "192.168.1.4", "fe80::2", "fe80::1%wlan0". Notably this will also include the network scope
     191             :      * ID in either index or name form (e.g. %wlan0, %14).
     192             :      */
     193             :     static PeerAddress UDP(char * addrStr, uint16_t port) { return PeerAddress::FromString(addrStr, port, Type::kUdp); }
     194           2 :     static PeerAddress UDP(const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId interface)
     195             :     {
     196           2 :         return UDP(addr).SetPort(port).SetInterface(interface);
     197             :     }
     198           0 :     static PeerAddress TCP(const Inet::IPAddress & addr) { return PeerAddress(addr, Type::kTcp); }
     199             :     static PeerAddress TCP(const Inet::IPAddress & addr, uint16_t port) { return TCP(addr).SetPort(port); }
     200             : 
     201             :     /**
     202             :      * Parses a PeerAddress from the given IP address string with TCP type. For example,
     203             :      * "192.168.1.4", "fe80::2", "fe80::1%wlan0". Notably this will also include the network scope
     204             :      * ID in either index or name form (e.g. %wlan0, %14).
     205             :      */
     206             :     static PeerAddress TCP(char * addrStr, uint16_t port) { return PeerAddress::FromString(addrStr, port, Type::kTcp); }
     207          12 :     static PeerAddress TCP(const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId interface)
     208             :     {
     209          12 :         return TCP(addr).SetPort(port).SetInterface(interface);
     210             :     }
     211             : 
     212           2 :     static PeerAddress Multicast(chip::FabricId fabric, chip::GroupId group)
     213             :     {
     214           2 :         constexpr uint8_t scope        = 0x05; // Site-Local
     215           2 :         constexpr uint8_t prefixLength = 0x40; // 64-bit long network prefix field
     216             :         // The network prefix portion of the Multicast Address is the 64-bit bitstring formed by concatenating:
     217             :         // * 0xFD to designate a locally assigned ULA prefix
     218             :         // * The upper 56-bits of the Fabric ID for the network in big-endian order
     219           2 :         const uint64_t prefix = 0xfd00000000000000 | ((fabric >> 8) & 0x00ffffffffffffff);
     220             :         // The 32-bit group identifier portion of the Multicast Address is the 32-bits formed by:
     221             :         // * The lower 8-bits of the Fabric ID
     222             :         // * 0x00
     223             :         // * The 16-bits Group Identifier in big-endian order
     224           2 :         uint32_t groupId = static_cast<uint32_t>((fabric << 24) & 0xff000000) | group;
     225           2 :         return UDP(Inet::IPAddress::MakeIPv6PrefixMulticast(scope, prefixLength, prefix, groupId));
     226             :     }
     227             : 
     228             : private:
     229             :     static PeerAddress FromString(char * addrStr, uint16_t port, Type type)
     230             :     {
     231             :         Inet::IPAddress addr;
     232             :         Inet::InterfaceId interfaceId;
     233             :         Inet::IPAddress::FromString(addrStr, addr, interfaceId);
     234             :         return PeerAddress(addr, type).SetPort(port).SetInterface(interfaceId);
     235             :     }
     236             :     Inet::IPAddress mIPAddress   = {};
     237             :     Type mTransportType          = Type::kUndefined;
     238             :     uint16_t mPort               = CHIP_PORT; ///< Relevant for UDP data sending.
     239             :     Inet::InterfaceId mInterface = Inet::InterfaceId::Null();
     240             : };
     241             : 
     242             : } // namespace Transport
     243             : } // namespace chip

Generated by: LCOV version 1.14