LCOV - code coverage report
Current view: top level - lib/dnssd - Types.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 29 44 65.9 %
Date: 2024-02-15 08:20:41 Functions: 11 18 61.1 %

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

Generated by: LCOV version 1.14