Matter SDK Coverage Report
Current view: top level - transport/raw - PeerAddress.h (source / functions) Coverage Total Hit
Test: SHA:704d97f9c619242ad76fcf75aeabc67802fa72d4 Lines: 68.8 % 93 64
Test Date: 2026-05-18 07:37:39 Functions: 81.2 % 32 26

            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 <cstdio>
      27              : #include <inet/IPAddress.h>
      28              : #include <inet/InetInterface.h>
      29              : #include <lib/core/CHIPConfig.h>
      30              : #include <lib/core/DataModelTypes.h>
      31              : #include <lib/support/CHIPMemString.h>
      32              : 
      33              : namespace chip {
      34              : namespace Transport {
      35              : 
      36              : /**
      37              :  * Communication path defines how two peers communicate.
      38              :  *
      39              :  * When a peer contacts another peer, it defines how the peers communicate.
      40              :  *
      41              :  * Once communication between two peers is established, the same transport
      42              :  * path should be used: a peer contacting another peer over UDP will receive
      43              :  * messages back over UDP. A communication channel established over TCP
      44              :  * will keep the same TCP channel.
      45              :  *
      46              :  */
      47              : 
      48              : /**
      49              :  * Here we specified Type to be uint8_t, so the PeerAddress can be serialized easily.
      50              :  */
      51              : enum class Type : uint8_t
      52              : {
      53              :     kUndefined,
      54              :     kUdp,
      55              :     kBle,
      56              :     kTcp,
      57              :     kWiFiPAF,
      58              :     kNfc,
      59              :     kThreadMeshcop,
      60              :     kLast = kThreadMeshcop, // This is not an actual transport type, it just refers to the last transport type
      61              : };
      62              : 
      63              : /**
      64              :  * Describes how a peer on a CHIP network can be addressed.
      65              :  */
      66              : class PeerAddress
      67              : {
      68              : public:
      69       927132 :     constexpr PeerAddress() : mTransportType(Type::kUndefined), mId{ .mRemoteId = kUndefinedNodeId } {}
      70         1040 :     constexpr PeerAddress(const Inet::IPAddress & addr, Type type) :
      71         1040 :         mIPAddress(addr), mTransportType(type), mId{ .mRemoteId = kUndefinedNodeId }
      72         1040 :     {}
      73         5940 :     constexpr PeerAddress(Type type) : mTransportType(type), mId{ .mRemoteId = kUndefinedNodeId } {}
      74            0 :     constexpr PeerAddress(Type type, NodeId remoteId) : mTransportType(type), mId{ .mRemoteId = remoteId } {}
      75              : 
      76            0 :     constexpr PeerAddress(PeerAddress &&)        = default;
      77        92215 :     constexpr PeerAddress(const PeerAddress &)   = default;
      78        18435 :     PeerAddress & operator=(const PeerAddress &) = default;
      79          235 :     PeerAddress & operator=(PeerAddress &&)      = default;
      80              : 
      81        15252 :     const Inet::IPAddress & GetIPAddress() const { return mIPAddress; }
      82            1 :     PeerAddress & SetIPAddress(const Inet::IPAddress & addr)
      83              :     {
      84            1 :         mIPAddress = addr;
      85            1 :         return *this;
      86              :     }
      87              : 
      88            0 :     NodeId GetRemoteId() const { return mId.mRemoteId; }
      89              : 
      90              :     // NB: 0xFFFF is not allowed for NFC ShortId.
      91              :     uint16_t GetNFCShortId() const { return mId.mNFCShortId; }
      92              : 
      93       134439 :     Type GetTransportType() const { return mTransportType; }
      94            0 :     PeerAddress & SetTransportType(Type type)
      95              :     {
      96            0 :         mTransportType = type;
      97            0 :         return *this;
      98              :     }
      99              : 
     100        15926 :     uint16_t GetPort() const { return mPort; }
     101        16908 :     PeerAddress & SetPort(uint16_t port)
     102              :     {
     103        16908 :         mPort = port;
     104        16908 :         return *this;
     105              :     }
     106              : 
     107          170 :     Inet::InterfaceId GetInterface() const { return mInterface; }
     108        15176 :     PeerAddress & SetInterface(Inet::InterfaceId interface)
     109              :     {
     110        15176 :         mInterface = interface;
     111        15176 :         return *this;
     112              :     }
     113              : 
     114              :     bool IsInitialized() const { return mTransportType != Type::kUndefined; }
     115              : 
     116            1 :     bool IsMulticast() { return Type::kUdp == mTransportType && mIPAddress.IsIPv6Multicast(); }
     117              : 
     118              :     bool operator==(const PeerAddress & other) const;
     119        14898 :     bool operator!=(const PeerAddress & other) const { return !(*this == other); }
     120              : 
     121              :     /// Maximum size of the string outputes by ToString. Format is of the form:
     122              :     /// "UDP:<ip>:<port>"
     123              :     static constexpr size_t kMaxToStringSize = 3 // type: UDP/TCP/BLE
     124              :         + 1                                      // splitter :
     125              :         + 2                                      // brackets around address
     126              :         + Inet::IPAddress::kMaxStringLength      // address
     127              :         + 1                                      // splitter %
     128              :         + Inet::InterfaceId::kMaxIfNameLength    // interface
     129              :         + 1                                      // splitter :
     130              :         + 5                                      // port: 16 bit interger
     131              :         + 1;                                     // NullTerminator
     132              : 
     133              :     template <size_t N>
     134        15266 :     inline void ToString(char (&buf)[N]) const
     135              :     {
     136        15266 :         ToString(buf, N);
     137        15266 :     }
     138              : 
     139        15266 :     void ToString(char * buf, size_t bufSize) const
     140              :     {
     141              :         char ip_addr[Inet::IPAddress::kMaxStringLength];
     142              : 
     143        15266 :         char interface[Inet::InterfaceId::kMaxIfNameLength + 1] = {}; // +1 to prepend '%'
     144        15266 :         if (mInterface.IsPresent())
     145              :         {
     146            0 :             interface[0]   = '%';
     147            0 :             interface[1]   = 0;
     148            0 :             CHIP_ERROR err = mInterface.GetInterfaceName(interface + 1, sizeof(interface) - 1);
     149            0 :             if (err != CHIP_NO_ERROR)
     150              :             {
     151            0 :                 Platform::CopyString(interface, sizeof(interface), "%(err)");
     152              :             }
     153              :         }
     154              : 
     155        15266 :         switch (mTransportType)
     156              :         {
     157           47 :         case Type::kUndefined:
     158           47 :             snprintf(buf, bufSize, "UNDEFINED");
     159           47 :             break;
     160        15108 :         case Type::kUdp:
     161        15108 :             mIPAddress.ToString(ip_addr);
     162              : #if INET_CONFIG_ENABLE_IPV4
     163        15108 :             if (mIPAddress.IsIPv4())
     164            0 :                 snprintf(buf, bufSize, "UDP:%s%s:%d", ip_addr, interface, mPort);
     165              :             else
     166              : #endif
     167        15108 :                 snprintf(buf, bufSize, "UDP:[%s%s]:%d", ip_addr, interface, mPort);
     168        15108 :             break;
     169          110 :         case Type::kTcp:
     170          110 :             mIPAddress.ToString(ip_addr);
     171              : #if INET_CONFIG_ENABLE_IPV4
     172          110 :             if (mIPAddress.IsIPv4())
     173           32 :                 snprintf(buf, bufSize, "TCP:%s%s:%d", ip_addr, interface, mPort);
     174              :             else
     175              : #endif
     176           78 :                 snprintf(buf, bufSize, "TCP:[%s%s]:%d", ip_addr, interface, mPort);
     177          110 :             break;
     178            0 :         case Type::kWiFiPAF:
     179            0 :             snprintf(buf, bufSize, "Wi-Fi PAF");
     180            0 :             break;
     181            1 :         case Type::kBle:
     182              :             // Note that BLE does not currently use any specific address.
     183            1 :             snprintf(buf, bufSize, "BLE");
     184            1 :             break;
     185            0 :         case Type::kNfc:
     186            0 :             snprintf(buf, bufSize, "NFC:%d", mId.mNFCShortId);
     187            0 :             break;
     188            0 :         case Type::kThreadMeshcop:
     189            0 :             mIPAddress.ToString(ip_addr);
     190              : #if INET_CONFIG_ENABLE_IPV4
     191            0 :             if (mIPAddress.IsIPv4())
     192            0 :                 snprintf(buf, bufSize, "ThreadMeshcop:%s:%d", ip_addr, mPort);
     193              :             else
     194              : #endif
     195            0 :                 snprintf(buf, bufSize, "ThreadMeshcop:[%s]:%d", ip_addr, mPort);
     196            0 :             break;
     197            0 :         default:
     198            0 :             snprintf(buf, bufSize, "ERROR");
     199            0 :             break;
     200              :         }
     201        15266 :     }
     202              : 
     203              :     /****** Factory methods for convenience ******/
     204              : 
     205         1288 :     static constexpr PeerAddress Uninitialized() { return PeerAddress(Type::kUndefined); }
     206              : 
     207            1 :     static constexpr PeerAddress BLE() { return PeerAddress(Type::kBle); }
     208              : 
     209              :     // NB: 0xFFFF is not allowed for NFC ShortId.
     210              :     static constexpr PeerAddress NFC() { return PeerAddress(kUndefinedNFCShortId()); }
     211              :     static constexpr PeerAddress NFC(const uint16_t shortId) { return PeerAddress(shortId); }
     212              : 
     213              :     static PeerAddress ThreadMeshcop(const Inet::IPAddress & addr, uint16_t port)
     214              :     {
     215              :         return PeerAddress(Type::kThreadMeshcop).SetIPAddress(addr).SetPort(port);
     216              :     }
     217              : 
     218          967 :     static PeerAddress UDP(const Inet::IPAddress & addr) { return PeerAddress(addr, Type::kUdp); }
     219          885 :     static PeerAddress UDP(const Inet::IPAddress & addr, uint16_t port) { return UDP(addr).SetPort(port); }
     220              : 
     221              :     /**
     222              :      * Parses a PeerAddress from the given IP address string with UDP type. For example,
     223              :      * "192.168.1.4", "fe80::2", "fe80::1%wlan0". Notably this will also include the network scope
     224              :      * ID in either index or name form (e.g. %wlan0, %14).
     225              :      */
     226              :     static PeerAddress UDP(char * addrStr, uint16_t port) { return PeerAddress::FromString(addrStr, port, Type::kUdp); }
     227           61 :     static PeerAddress UDP(const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId interface)
     228              :     {
     229           61 :         return UDP(addr).SetPort(port).SetInterface(interface);
     230              :     }
     231           73 :     static PeerAddress TCP(const Inet::IPAddress & addr) { return PeerAddress(addr, Type::kTcp); }
     232           36 :     static PeerAddress TCP(const Inet::IPAddress & addr, uint16_t port) { return TCP(addr).SetPort(port); }
     233              : 
     234              :     /**
     235              :      * Parses a PeerAddress from the given IP address string with TCP type. For example,
     236              :      * "192.168.1.4", "fe80::2", "fe80::1%wlan0". Notably this will also include the network scope
     237              :      * ID in either index or name form (e.g. %wlan0, %14).
     238              :      */
     239              :     static PeerAddress TCP(char * addrStr, uint16_t port) { return PeerAddress::FromString(addrStr, port, Type::kTcp); }
     240           37 :     static PeerAddress TCP(const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId interface)
     241              :     {
     242           37 :         return TCP(addr).SetPort(port).SetInterface(interface);
     243              :     }
     244              : 
     245            0 :     static constexpr PeerAddress WiFiPAF(NodeId remoteId) { return PeerAddress(Type::kWiFiPAF, remoteId); }
     246              : 
     247            7 :     static PeerAddress BuildMatterPerGroupMulticastAddress(chip::FabricId fabric, chip::GroupId group)
     248              :     {
     249            7 :         constexpr uint8_t scope        = 0x05; // Site-Local
     250            7 :         constexpr uint8_t prefixLength = 0x40; // 64-bit long network prefix field
     251              :         // The network prefix portion of the Multicast Address is the 64-bit bitstring formed by concatenating:
     252              :         // * 0xFD to designate a locally assigned ULA prefix
     253              :         // * The upper 56-bits of the Fabric ID for the network in big-endian order
     254            7 :         const uint64_t prefix = 0xfd00000000000000 | ((fabric >> 8) & 0x00ffffffffffffff);
     255              :         // The 32-bit group identifier portion of the Multicast Address is the 32-bits formed by:
     256              :         // * The lower 8-bits of the Fabric ID
     257              :         // * 0x00
     258              :         // * The 16-bits Group Identifier in big-endian order
     259            7 :         uint32_t groupId = static_cast<uint32_t>((fabric << 24) & 0xff000000) | group;
     260            7 :         return UDP(Inet::IPAddress::MakeIPv6PrefixMulticast(scope, prefixLength, prefix, groupId));
     261              :     }
     262              : 
     263            0 :     static PeerAddress BuildMatterIanaMulticastAddress() { return UDP(Inet::IPAddress::MakeIPv6MatterIANAMulticastAddr()); }
     264              : 
     265              : private:
     266              :     constexpr PeerAddress(uint16_t shortId) : mTransportType(Type::kNfc), mId{ .mNFCShortId = shortId } {}
     267              : 
     268              :     static PeerAddress FromString(char * addrStr, uint16_t port, Type type)
     269              :     {
     270              :         Inet::IPAddress addr;
     271              :         Inet::InterfaceId interfaceId;
     272              :         Inet::IPAddress::FromString(addrStr, addr, interfaceId);
     273              :         return PeerAddress(addr, type).SetPort(port).SetInterface(interfaceId);
     274              :     }
     275              : 
     276              :     static constexpr uint16_t kUndefinedNFCShortId() { return 0xFFFF; }
     277              : 
     278              :     Inet::IPAddress mIPAddress   = {};
     279              :     Type mTransportType          = Type::kUndefined;
     280              :     uint16_t mPort               = CHIP_PORT; ///< Relevant for UDP data sending.
     281              :     Inet::InterfaceId mInterface = Inet::InterfaceId::Null();
     282              : 
     283              :     union Id
     284              :     {
     285              :         NodeId mRemoteId;
     286              :         uint16_t mNFCShortId;
     287              :     } mId;
     288              : };
     289              : 
     290              : } // namespace Transport
     291              : } // namespace chip
        

Generated by: LCOV version 2.0-1