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

Generated by: LCOV version 2.0-1