Matter SDK Coverage Report
Current view: top level - lib/dnssd - Types.h (source / functions) Coverage Total Hit
Test: SHA:9151e79d6b5c010f18e3a3da0b048f38196f06c6 Lines: 61.0 % 41 25
Test Date: 2025-07-02 07:09:01 Functions: 52.9 % 17 9

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

Generated by: LCOV version 2.0-1