Matter SDK Coverage Report
Current view: top level - lib/dnssd - Types.h (source / functions) Coverage Total Hit
Test: SHA:f1767a8b0a3778fdf31b1d979afbdf544892fd94 Lines: 91.1 % 45 41
Test Date: 2026-06-03 07:35:21 Functions: 84.2 % 19 16

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2024 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              : #pragma once
      19              : 
      20              : #include <cstdint>
      21              : #include <cstring>
      22              : #include <optional>
      23              : 
      24              : #include <inet/IPAddress.h>
      25              : #include <inet/InetInterface.h>
      26              : #include <lib/core/CHIPError.h>
      27              : #include <lib/core/PeerId.h>
      28              : #include <lib/dnssd/Constants.h>
      29              : #include <lib/support/BytesToHex.h>
      30              : #include <lib/support/Variant.h>
      31              : #include <lib/support/logging/CHIPLogging.h>
      32              : #include <messaging/ReliableMessageProtocolConfig.h>
      33              : #include <platform/CHIPDeviceConfig.h>
      34              : 
      35              : namespace chip {
      36              : namespace Dnssd {
      37              : 
      38              : enum class JointFabricMode : uint8_t
      39              : {
      40              :     kAvailable     = 1 << 0, // This device is capable of acting as a Joint Fabric Administrator.
      41              :     kAdministrator = 1 << 1, // This device is acting as a Joint Fabric Administrator.
      42              :     kAnchor        = 1 << 2, // This device is acting as a Joint Fabric Anchor Administrator.
      43              :     kDatastore     = 1 << 3  // This device is acting as a Joint Fabric Datastore.
      44              : };
      45              : 
      46              : enum class DiscoveryFilterType : uint8_t
      47              : {
      48              :     kNone,
      49              :     kShortDiscriminator,
      50              :     kLongDiscriminator,
      51              :     kVendorId,
      52              :     kDeviceType,
      53              :     kCommissioningMode,
      54              :     kInstanceName,
      55              :     kCommissioner,
      56              :     kCompressedFabricId,
      57              : };
      58              : 
      59              : struct DiscoveryFilter
      60              : {
      61              :     DiscoveryFilterType type;
      62              :     uint64_t code             = 0;
      63              :     const char * instanceName = nullptr;
      64            5 :     DiscoveryFilter() : type(DiscoveryFilterType::kNone), code(0) {}
      65           14 :     DiscoveryFilter(const DiscoveryFilterType newType) : type(newType) {}
      66           59 :     DiscoveryFilter(const DiscoveryFilterType newType, uint64_t newCode) : type(newType), code(newCode) {}
      67              :     DiscoveryFilter(const DiscoveryFilterType newType, const char * newInstanceName) : type(newType), instanceName(newInstanceName)
      68              :     {}
      69            9 :     bool operator==(const DiscoveryFilter & other) const
      70              :     {
      71            9 :         if (type != other.type)
      72              :         {
      73            0 :             return false;
      74              :         }
      75            9 :         if (type == DiscoveryFilterType::kInstanceName)
      76              :         {
      77            0 :             return (instanceName != nullptr) && (other.instanceName != nullptr) && (strcmp(instanceName, other.instanceName) == 0);
      78              :         }
      79              : 
      80            9 :         return code == other.code;
      81              :     }
      82              : };
      83              : 
      84              : enum class DiscoveryType
      85              : {
      86              :     kUnknown,
      87              :     kOperational,
      88              :     kCommissionableNode,
      89              :     kCommissionerNode
      90              : };
      91              : 
      92              : struct CommonResolutionData
      93              : {
      94              :     static constexpr unsigned kMaxIPAddresses = CHIP_DEVICE_CONFIG_MAX_DISCOVERED_IP_ADDRESSES;
      95              : 
      96              :     Inet::InterfaceId interfaceId;
      97              : 
      98              :     size_t numIPs = 0; // number of valid IP addresses
      99              :     Inet::IPAddress ipAddress[kMaxIPAddresses];
     100              : 
     101              :     uint16_t port                         = 0;
     102              :     char hostName[kHostNameMaxLength + 1] = {};
     103              :     bool supportsTcpClient                = false;
     104              :     bool supportsTcpServer                = false;
     105              :     std::optional<bool> isICDOperatingAsLIT;
     106              :     std::optional<System::Clock::Milliseconds32> mrpRetryIntervalIdle;
     107              :     std::optional<System::Clock::Milliseconds32> mrpRetryIntervalActive;
     108              :     std::optional<System::Clock::Milliseconds16> mrpRetryActiveThreshold;
     109              : 
     110          777 :     CommonResolutionData() { Reset(); }
     111              : 
     112          145 :     bool IsValid() const { return !IsHost("") && (numIPs > 0) && (ipAddress[0] != chip::Inet::IPAddress::Any); }
     113              : 
     114            1 :     ReliableMessageProtocolConfig GetRemoteMRPConfig() const
     115              :     {
     116            1 :         const ReliableMessageProtocolConfig defaultConfig = GetDefaultMRPConfig();
     117            2 :         return ReliableMessageProtocolConfig(GetMrpRetryIntervalIdle().value_or(defaultConfig.mIdleRetransTimeout),
     118            1 :                                              GetMrpRetryIntervalActive().value_or(defaultConfig.mActiveRetransTimeout),
     119            2 :                                              GetMrpRetryActiveThreshold().value_or(defaultConfig.mActiveThresholdTime));
     120              :     }
     121           19 :     std::optional<System::Clock::Milliseconds32> GetMrpRetryIntervalIdle() const { return mrpRetryIntervalIdle; }
     122           19 :     std::optional<System::Clock::Milliseconds32> GetMrpRetryIntervalActive() const { return mrpRetryIntervalActive; }
     123           17 :     std::optional<System::Clock::Milliseconds16> GetMrpRetryActiveThreshold() const { return mrpRetryActiveThreshold; }
     124              : 
     125           12 :     bool IsDeviceTreatedAsSleepy(const ReliableMessageProtocolConfig * defaultMRPConfig) const
     126              :     {
     127              :         // If either session interval (Idle - SII, Active - SAI) has a value and that value is greater
     128              :         // than the value passed to this function, then the peer device will be treated as if it is
     129              :         // a Sleepy End Device (SED)
     130           26 :         return (mrpRetryIntervalIdle.has_value() && (*mrpRetryIntervalIdle > defaultMRPConfig->mIdleRetransTimeout)) ||
     131           26 :             (mrpRetryIntervalActive.has_value() && (*mrpRetryIntervalActive > defaultMRPConfig->mActiveRetransTimeout));
     132              :     }
     133              : 
     134          145 :     bool IsHost(const char * host) const { return strcmp(host, hostName) == 0; }
     135              : 
     136          793 :     void Reset()
     137              :     {
     138          793 :         memset(hostName, 0, sizeof(hostName));
     139          793 :         mrpRetryIntervalIdle    = std::nullopt;
     140          793 :         mrpRetryIntervalActive  = std::nullopt;
     141          793 :         mrpRetryActiveThreshold = std::nullopt;
     142          793 :         isICDOperatingAsLIT     = std::nullopt;
     143          793 :         numIPs                  = 0;
     144          793 :         port                    = 0;
     145          793 :         supportsTcpClient       = false;
     146          793 :         supportsTcpServer       = false;
     147          793 :         interfaceId             = Inet::InterfaceId::Null();
     148         4758 :         for (auto & addr : ipAddress)
     149              :         {
     150         3965 :             addr = chip::Inet::IPAddress::Any;
     151              :         }
     152          793 :     }
     153              : 
     154              :     void LogDetail() const
     155              :     {
     156              :         if (!IsHost(""))
     157              :         {
     158              :             ChipLogDetail(Discovery, "\tHostname: %s", hostName);
     159              :         }
     160              : #if CHIP_DETAIL_LOGGING
     161              :         for (unsigned j = 0; j < numIPs; j++)
     162              :         {
     163              :             char buf[Inet::IPAddress::kMaxStringLength];
     164              :             char * ipAddressOut = ipAddress[j].ToString(buf);
     165              :             ChipLogDetail(Discovery, "\tIP Address #%d: %s", j + 1, ipAddressOut);
     166              :         }
     167              : #endif // CHIP_DETAIL_LOGGING
     168              :         if (port > 0)
     169              :         {
     170              :             ChipLogDetail(Discovery, "\tPort: %u", port);
     171              :         }
     172              :         if (mrpRetryIntervalIdle.has_value())
     173              :         {
     174              :             ChipLogDetail(Discovery, "\tMrp Interval idle: %" PRIu32 " ms", mrpRetryIntervalIdle->count());
     175              :         }
     176              :         else
     177              :         {
     178              :             ChipLogDetail(Discovery, "\tMrp Interval idle: not present");
     179              :         }
     180              :         if (mrpRetryIntervalActive.has_value())
     181              :         {
     182              :             ChipLogDetail(Discovery, "\tMrp Interval active: %" PRIu32 " ms", mrpRetryIntervalActive->count());
     183              :         }
     184              :         else
     185              :         {
     186              :             ChipLogDetail(Discovery, "\tMrp Interval active: not present");
     187              :         }
     188              :         if (mrpRetryActiveThreshold.has_value())
     189              :         {
     190              :             ChipLogDetail(Discovery, "\tMrp Active Threshold: %u ms", mrpRetryActiveThreshold->count());
     191              :         }
     192              :         else
     193              :         {
     194              :             ChipLogDetail(Discovery, "\tMrp Active Threshold: not present");
     195              :         }
     196              :         ChipLogDetail(Discovery, "\tTCP Client Supported: %d", supportsTcpClient);
     197              :         ChipLogDetail(Discovery, "\tTCP Server Supported: %d", supportsTcpServer);
     198              :         if (isICDOperatingAsLIT.has_value())
     199              :         {
     200              :             ChipLogDetail(Discovery, "\tThe ICD operates in %s", *isICDOperatingAsLIT ? "LIT" : "SIT");
     201              :         }
     202              :         else
     203              :         {
     204              :             ChipLogDetail(Discovery, "\tICD: not present");
     205              :         }
     206              :     }
     207              : };
     208              : 
     209              : /// Data that is specific to Operational Discovery of nodes
     210              : struct OperationalNodeData
     211              : {
     212              :     PeerId peerId;
     213              :     bool hasZeroTTL;
     214            0 :     void Reset() { peerId = PeerId(); }
     215              : };
     216              : 
     217              : struct OperationalNodeBrowseData : public OperationalNodeData
     218              : {
     219            0 :     OperationalNodeBrowseData() { Reset(); };
     220              :     void LogDetail() const
     221              :     {
     222              :         ChipLogDetail(Discovery, "Discovered Operational node:\r\n");
     223              :         ChipLogDetail(Discovery, "\tNode Instance: " ChipLogFormatPeerId, ChipLogValuePeerId(peerId));
     224              :         ChipLogDetail(Discovery, "\thasZeroTTL: %s\r\n", hasZeroTTL ? "true" : "false");
     225              :     }
     226              : };
     227              : 
     228              : inline constexpr size_t kMaxDeviceNameLen         = 32;
     229              : inline constexpr size_t kMaxRotatingIdLen         = 50;
     230              : inline constexpr size_t kMaxPairingInstructionLen = 128;
     231              : 
     232              : /// Data that is specific to commisionable/commissioning node discovery
     233              : struct CommissionNodeData : public CommonResolutionData
     234              : {
     235              :     size_t rotatingIdLen                                      = 0;
     236              :     uint32_t deviceType                                       = 0;
     237              :     uint16_t longDiscriminator                                = 0;
     238              :     uint16_t vendorId                                         = 0;
     239              :     uint16_t productId                                        = 0;
     240              :     uint16_t pairingHint                                      = 0;
     241              :     uint8_t commissioningMode                                 = 0;
     242              :     bool supportsCommissionerGeneratedPasscode                = false;
     243              :     uint8_t rotatingId[kMaxRotatingIdLen]                     = {};
     244              :     char instanceName[Commission::kInstanceNameMaxLength + 1] = {};
     245              :     char deviceName[kMaxDeviceNameLen + 1]                    = {};
     246              :     char pairingInstruction[kMaxPairingInstructionLen + 1]    = {};
     247              :     bool threadMeshcop                                        = false;
     248              : #if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
     249              :     BitFlags<JointFabricMode> jointFabricMode;
     250              : #endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
     251              : 
     252          414 :     CommissionNodeData() {}
     253              : 
     254           40 :     void Reset()
     255              :     {
     256              :         // Let constructor clear things as default
     257           40 :         this->~CommissionNodeData();
     258           40 :         new (this) CommissionNodeData();
     259           40 :     }
     260              : 
     261              :     bool IsInstanceName(const char * instance) const { return strcmp(instance, instanceName) == 0; }
     262              : 
     263              :     void LogDetail() const
     264              :     {
     265              :         ChipLogDetail(Discovery, "Discovered commissionable/commissioner node:");
     266              :         CommonResolutionData::LogDetail();
     267              : 
     268              :         if (rotatingIdLen > 0)
     269              :         {
     270              :             char rotatingIdString[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
     271              :             TEMPORARY_RETURN_IGNORED Encoding::BytesToUppercaseHexString(rotatingId, rotatingIdLen, rotatingIdString,
     272              :                                                                          sizeof(rotatingIdString));
     273              :             ChipLogDetail(Discovery, "\tRotating ID: %s", rotatingIdString);
     274              :         }
     275              :         if (strlen(deviceName) != 0)
     276              :         {
     277              :             ChipLogDetail(Discovery, "\tDevice Name: %s", deviceName);
     278              :         }
     279              :         if (vendorId > 0)
     280              :         {
     281              :             ChipLogDetail(Discovery, "\tVendor ID: %u", vendorId);
     282              :         }
     283              :         if (productId > 0)
     284              :         {
     285              :             ChipLogDetail(Discovery, "\tProduct ID: %u", productId);
     286              :         }
     287              :         if (deviceType > 0)
     288              :         {
     289              :             ChipLogDetail(Discovery, "\tDevice Type: %" PRIu32, deviceType);
     290              :         }
     291              :         if (longDiscriminator > 0)
     292              :         {
     293              :             ChipLogDetail(Discovery, "\tLong Discriminator: %u", longDiscriminator);
     294              :         }
     295              :         if (strlen(pairingInstruction) != 0)
     296              :         {
     297              :             ChipLogDetail(Discovery, "\tPairing Instruction: %s", pairingInstruction);
     298              :         }
     299              :         if (pairingHint > 0)
     300              :         {
     301              :             ChipLogDetail(Discovery, "\tPairing Hint: %u", pairingHint);
     302              :         }
     303              :         if (!IsInstanceName(""))
     304              :         {
     305              :             ChipLogDetail(Discovery, "\tInstance Name: %s", instanceName);
     306              :         }
     307              :         ChipLogDetail(Discovery, "\tCommissioning Mode: %u", commissioningMode);
     308              :         ChipLogDetail(Discovery, "\tSupports Commissioner Generated Passcode: %s",
     309              :                       supportsCommissionerGeneratedPasscode ? "true" : "false");
     310              : #if CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
     311              :         ChipLogDetail(Discovery, "\tJoint Fabric Mode: 0x%02X", jointFabricMode.Raw());
     312              : #endif // CHIP_DEVICE_CONFIG_ENABLE_JOINT_FABRIC
     313              :     }
     314              : };
     315              : 
     316              : struct ResolvedNodeData
     317              : {
     318              :     CommonResolutionData resolutionData;
     319              :     OperationalNodeData operationalData;
     320              : 
     321              :     void LogNodeIdResolved() const
     322              :     {
     323              : #if CHIP_PROGRESS_LOGGING
     324              :         // Would be nice to log the interface id, but sorting out how to do so
     325              :         // across our different InterfaceId implementations is a pain.
     326              :         ChipLogProgress(Discovery, "Node ID resolved for " ChipLogFormatPeerId, ChipLogValuePeerId(operationalData.peerId));
     327              :         resolutionData.LogDetail();
     328              : #endif // CHIP_PROGRESS_LOGGING
     329              :     }
     330              : };
     331              : 
     332              : using DiscoveredNodeData = Variant<CommissionNodeData, OperationalNodeBrowseData>;
     333              : 
     334              : /// Callbacks for discovering nodes advertising both operational and non-operational status:
     335              : ///   - Commissioners
     336              : ///   - Nodes in commissioning modes over IP (e.g. ethernet devices, devices already
     337              : ///     connected to thread/wifi or devices with a commissioning window open)
     338              : ///   - Operational nodes
     339              : class DiscoverNodeDelegate
     340              : {
     341              : public:
     342           36 :     virtual ~DiscoverNodeDelegate() = default;
     343              : 
     344              :     /// Called within the CHIP event loop once a node is discovered.
     345              :     ///
     346              :     /// May be called multiple times as more nodes send their answer to a
     347              :     /// multicast discovery query
     348              :     virtual void OnNodeDiscovered(const DiscoveredNodeData & nodeData) = 0;
     349              : };
     350              : 
     351              : } // namespace Dnssd
     352              : } // namespace chip
        

Generated by: LCOV version 2.0-1