LCOV - code coverage report
Current view: top level - lib/dnssd - Advertiser.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 65 78 83.3 %
Date: 2024-02-15 08:20:41 Functions: 39 48 81.2 %

          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             : #pragma once
      19             : 
      20             : #include <algorithm>
      21             : #include <cstdint>
      22             : 
      23             : #include <lib/core/CHIPError.h>
      24             : #include <lib/core/Optional.h>
      25             : #include <lib/core/PeerId.h>
      26             : #include <lib/dnssd/TxtFields.h>
      27             : #include <lib/support/CHIPMemString.h>
      28             : #include <lib/support/SafeString.h>
      29             : #include <lib/support/Span.h>
      30             : 
      31             : namespace chip {
      32             : namespace Dnssd {
      33             : 
      34             : static constexpr uint16_t kMdnsPort = 5353;
      35             : // Need 8 bytes to fit a thread mac.
      36             : static constexpr size_t kMaxMacSize = 8;
      37             : 
      38             : enum class CommssionAdvertiseMode : uint8_t
      39             : {
      40             :     kCommissionableNode,
      41             :     kCommissioner,
      42             : };
      43             : 
      44             : enum class CommissioningMode
      45             : {
      46             :     kDisabled,       // Commissioning Mode is disabled, CM=0 in DNS-SD key/value pairs
      47             :     kEnabledBasic,   // Basic Commissioning Mode, CM=1 in DNS-SD key/value pairs
      48             :     kEnabledEnhanced // Enhanced Commissioning Mode, CM=2 in DNS-SD key/value pairs
      49             : };
      50             : 
      51             : enum class ICDModeAdvertise : uint8_t
      52             : {
      53             :     kNone, // The device does not support the LIT feature-set. No ICD= key is advertised in DNS-SD.
      54             :     kSIT,  // The ICD supports the LIT feature-set, but is currently operating as a SIT. ICD=0 in DNS-SD key/value pairs.
      55             :     kLIT,  // The ICD is currently operating as a LIT. ICD=1 in DNS-SD key/value pairs.
      56             : };
      57             : 
      58             : template <class Derived>
      59             : class BaseAdvertisingParams
      60             : {
      61             : public:
      62             :     static constexpr uint8_t kCommonTxtMaxNumber     = KeyCount(TxtKeyUse::kCommon);
      63             :     static constexpr size_t kCommonTxtMaxKeySize     = MaxKeyLen(TxtKeyUse::kCommon);
      64             :     static constexpr size_t kCommonTxtMaxValueSize   = MaxValueLen(TxtKeyUse::kCommon);
      65             :     static constexpr size_t kCommonTxtTotalKeySize   = TotalKeyLen(TxtKeyUse::kCommon);
      66             :     static constexpr size_t kCommonTxtTotalValueSize = TotalValueLen(TxtKeyUse::kCommon);
      67             : 
      68           8 :     Derived & SetPort(uint16_t port)
      69             :     {
      70           8 :         mPort = port;
      71           8 :         return *reinterpret_cast<Derived *>(this);
      72             :     }
      73          20 :     uint16_t GetPort() const { return mPort; }
      74             : 
      75           8 :     Derived & SetInterfaceId(Inet::InterfaceId interfaceId)
      76             :     {
      77           8 :         mInterfaceId = interfaceId;
      78           8 :         return *reinterpret_cast<Derived *>(this);
      79             :     }
      80             : 
      81             :     Inet::InterfaceId GetInterfaceId() const { return mInterfaceId; }
      82             : 
      83           8 :     Derived & EnableIpV4(bool enable)
      84             :     {
      85           8 :         mEnableIPv4 = enable;
      86           8 :         return *reinterpret_cast<Derived *>(this);
      87             :     }
      88          20 :     bool IsIPv4Enabled() const { return mEnableIPv4; }
      89           8 :     Derived & SetMac(chip::ByteSpan mac)
      90             :     {
      91           8 :         mMacLength = std::min(mac.size(), kMaxMacSize);
      92           8 :         memcpy(mMacStorage, mac.data(), mMacLength);
      93           8 :         return *reinterpret_cast<Derived *>(this);
      94             :     }
      95          20 :     const chip::ByteSpan GetMac() const { return chip::ByteSpan(mMacStorage, mMacLength); }
      96             : 
      97             :     // Common Flags
      98           8 :     Derived & SetLocalMRPConfig(const Optional<ReliableMessageProtocolConfig> & config)
      99             :     {
     100           8 :         mLocalMRPConfig = config;
     101           8 :         return *reinterpret_cast<Derived *>(this);
     102             :     }
     103          20 :     const Optional<ReliableMessageProtocolConfig> & GetLocalMRPConfig() const { return mLocalMRPConfig; }
     104             : 
     105             :     // NOTE: The SetTcpSupported API is deprecated and not compliant with 1.3. T flag should not be set.
     106             :     Derived & SetTcpSupported(Optional<bool> tcpSupported)
     107             :     {
     108             :         mTcpSupported = tcpSupported;
     109             :         return *reinterpret_cast<Derived *>(this);
     110             :     }
     111          20 :     Optional<bool> GetTcpSupported() const { return mTcpSupported; }
     112             : 
     113             :     Derived & SetICDModeToAdvertise(ICDModeAdvertise operatingMode)
     114             :     {
     115             :         mICDModeAdvertise = operatingMode;
     116             :         return *reinterpret_cast<Derived *>(this);
     117             :     }
     118          27 :     ICDModeAdvertise GetICDModeToAdvertise() const { return mICDModeAdvertise; }
     119             : 
     120             : private:
     121             :     uint16_t mPort                   = CHIP_PORT;
     122             :     Inet::InterfaceId mInterfaceId   = Inet::InterfaceId::Null();
     123             :     bool mEnableIPv4                 = true;
     124             :     uint8_t mMacStorage[kMaxMacSize] = {};
     125             :     size_t mMacLength                = 0;
     126             :     Optional<ReliableMessageProtocolConfig> mLocalMRPConfig;
     127             :     Optional<bool> mTcpSupported;
     128             :     ICDModeAdvertise mICDModeAdvertise = ICDModeAdvertise::kNone;
     129             : };
     130             : 
     131             : /// Defines parameters required for advertising a CHIP node
     132             : /// over mDNS as an 'operationally ready' node.
     133             : class OperationalAdvertisingParameters : public BaseAdvertisingParams<OperationalAdvertisingParameters>
     134             : {
     135             : public:
     136             :     // Operational uses only common keys
     137             :     static constexpr uint8_t kTxtMaxNumber     = kCommonTxtMaxNumber;
     138             :     static constexpr uint8_t kTxtMaxKeySize    = kCommonTxtMaxKeySize;
     139             :     static constexpr uint8_t kTxtMaxValueSize  = kCommonTxtMaxValueSize;
     140             :     static constexpr size_t kTxtTotalKeySize   = kCommonTxtTotalKeySize;
     141             :     static constexpr size_t kTxtTotalValueSize = kCommonTxtTotalValueSize;
     142             : 
     143           0 :     OperationalAdvertisingParameters & SetPeerId(const PeerId & peerId)
     144             :     {
     145           0 :         mPeerId = peerId;
     146           0 :         return *this;
     147             :     }
     148          16 :     PeerId GetPeerId() const { return mPeerId; }
     149             : 
     150             :     CompressedFabricId GetCompressedFabricId() const { return mPeerId.GetCompressedFabricId(); }
     151             : 
     152             : private:
     153             :     PeerId mPeerId;
     154             : };
     155             : 
     156             : class CommissionAdvertisingParameters : public BaseAdvertisingParams<CommissionAdvertisingParameters>
     157             : {
     158             : public:
     159             :     static constexpr uint8_t kTxtMaxNumber     = kCommonTxtMaxNumber + KeyCount(TxtKeyUse::kCommission);
     160             :     static constexpr uint8_t kTxtMaxKeySize    = std::max(kCommonTxtMaxKeySize, MaxKeyLen(TxtKeyUse::kCommission));
     161             :     static constexpr uint8_t kTxtMaxValueSize  = std::max(kCommonTxtMaxValueSize, MaxValueLen(TxtKeyUse::kCommission));
     162             :     static constexpr size_t kTxtTotalKeySize   = kCommonTxtTotalKeySize + TotalKeyLen(TxtKeyUse::kCommission);
     163             :     static constexpr size_t kTxtTotalValueSize = kCommonTxtTotalValueSize + TotalValueLen(TxtKeyUse::kCommission);
     164             : 
     165           8 :     CommissionAdvertisingParameters & SetShortDiscriminator(uint8_t discriminator)
     166             :     {
     167           8 :         mShortDiscriminator = discriminator;
     168           8 :         return *this;
     169             :     }
     170          20 :     uint8_t GetShortDiscriminator() const { return mShortDiscriminator; }
     171             : 
     172           8 :     CommissionAdvertisingParameters & SetLongDiscriminator(uint16_t discriminator)
     173             :     {
     174           8 :         mLongDiscriminator = discriminator;
     175           8 :         return *this;
     176             :     }
     177          32 :     uint16_t GetLongDiscriminator() const { return mLongDiscriminator; }
     178             : 
     179           8 :     CommissionAdvertisingParameters & SetVendorId(Optional<uint16_t> vendorId)
     180             :     {
     181           8 :         mVendorId = vendorId;
     182           8 :         return *this;
     183             :     }
     184          54 :     Optional<uint16_t> GetVendorId() const { return mVendorId; }
     185             : 
     186           8 :     CommissionAdvertisingParameters & SetProductId(Optional<uint16_t> productId)
     187             :     {
     188           8 :         mProductId = productId;
     189           8 :         return *this;
     190             :     }
     191          31 :     Optional<uint16_t> GetProductId() const { return mProductId; }
     192             : 
     193           8 :     CommissionAdvertisingParameters & SetCommissioningMode(CommissioningMode mode)
     194             :     {
     195           8 :         mCommissioningMode = mode;
     196           8 :         return *this;
     197             :     }
     198          32 :     CommissioningMode GetCommissioningMode() const { return mCommissioningMode; }
     199             : 
     200           0 :     CommissionAdvertisingParameters & SetDeviceType(Optional<uint32_t> deviceType)
     201             :     {
     202           0 :         mDeviceType = deviceType;
     203           0 :         return *this;
     204             :     }
     205          30 :     Optional<uint32_t> GetDeviceType() const { return mDeviceType; }
     206             : 
     207           0 :     CommissionAdvertisingParameters & SetDeviceName(Optional<const char *> deviceName)
     208             :     {
     209           0 :         if (deviceName.HasValue())
     210             :         {
     211           0 :             Platform::CopyString(mDeviceName, sizeof(mDeviceName), deviceName.Value());
     212           0 :             mDeviceNameHasValue = true;
     213             :         }
     214             :         else
     215             :         {
     216           0 :             mDeviceNameHasValue = false;
     217             :         }
     218           0 :         return *this;
     219             :     }
     220          15 :     Optional<const char *> GetDeviceName() const
     221             :     {
     222          15 :         return mDeviceNameHasValue ? Optional<const char *>::Value(mDeviceName) : Optional<const char *>::Missing();
     223             :     }
     224             : 
     225             :     CommissionAdvertisingParameters & SetRotatingDeviceId(Optional<const char *> rotatingId)
     226             :     {
     227             :         if (rotatingId.HasValue())
     228             :         {
     229             :             Platform::CopyString(mRotatingId, sizeof(mRotatingId), rotatingId.Value());
     230             :             mRotatingIdHasValue = true;
     231             :         }
     232             :         else
     233             :         {
     234             :             mRotatingIdHasValue = false;
     235             :         }
     236             :         return *this;
     237             :     }
     238          15 :     Optional<const char *> GetRotatingDeviceId() const
     239             :     {
     240          15 :         return mRotatingIdHasValue ? Optional<const char *>::Value(mRotatingId) : Optional<const char *>::Missing();
     241             :     }
     242             : 
     243           8 :     CommissionAdvertisingParameters & SetPairingInstruction(Optional<const char *> pairingInstr)
     244             :     {
     245           8 :         if (pairingInstr.HasValue())
     246             :         {
     247           8 :             Platform::CopyString(mPairingInstr, sizeof(mPairingInstr), pairingInstr.Value());
     248           8 :             mPairingInstrHasValue = true;
     249             :         }
     250             :         else
     251             :         {
     252           0 :             mPairingInstrHasValue = false;
     253             :         }
     254           8 :         return *this;
     255             :     }
     256          23 :     Optional<const char *> GetPairingInstruction() const
     257             :     {
     258          23 :         return mPairingInstrHasValue ? Optional<const char *>::Value(mPairingInstr) : Optional<const char *>::Missing();
     259             :     }
     260             : 
     261           8 :     CommissionAdvertisingParameters & SetPairingHint(Optional<uint16_t> pairingHint)
     262             :     {
     263           8 :         mPairingHint = pairingHint;
     264           8 :         return *this;
     265             :     }
     266          23 :     Optional<uint16_t> GetPairingHint() const { return mPairingHint; }
     267             : 
     268           8 :     CommissionAdvertisingParameters & SetCommissionAdvertiseMode(CommssionAdvertiseMode mode)
     269             :     {
     270           8 :         mMode = mode;
     271           8 :         return *this;
     272             :     }
     273          84 :     CommssionAdvertiseMode GetCommissionAdvertiseMode() const { return mMode; }
     274             : 
     275             :     CommissionAdvertisingParameters & SetCommissionerPasscodeSupported(Optional<bool> commissionerPasscodeSupported)
     276             :     {
     277             :         mCommissionerPasscodeSupported = commissionerPasscodeSupported;
     278             :         return *this;
     279             :     }
     280           8 :     Optional<bool> GetCommissionerPasscodeSupported() const { return mCommissionerPasscodeSupported; }
     281             : 
     282             : private:
     283             :     uint8_t mShortDiscriminator          = 0;
     284             :     uint16_t mLongDiscriminator          = 0; // 12-bit according to spec
     285             :     CommssionAdvertiseMode mMode         = CommssionAdvertiseMode::kCommissionableNode;
     286             :     CommissioningMode mCommissioningMode = CommissioningMode::kEnabledBasic;
     287             :     chip::Optional<uint16_t> mVendorId;
     288             :     chip::Optional<uint16_t> mProductId;
     289             :     chip::Optional<uint32_t> mDeviceType;
     290             :     chip::Optional<uint16_t> mPairingHint;
     291             : 
     292             :     char mDeviceName[kKeyDeviceNameMaxLength + 1];
     293             :     bool mDeviceNameHasValue = false;
     294             : 
     295             :     char mRotatingId[kKeyRotatingDeviceIdMaxLength + 1];
     296             :     bool mRotatingIdHasValue = false;
     297             : 
     298             :     char mPairingInstr[kKeyPairingInstructionMaxLength + 1];
     299             :     bool mPairingInstrHasValue = false;
     300             : 
     301             :     Optional<bool> mCommissionerPasscodeSupported;
     302             : };
     303             : 
     304             : /**
     305             :  * Interface for advertising CHIP DNS-SD services.
     306             :  *
     307             :  * A user of this interface must first initialize the advertiser using the `Init` method.
     308             :  *
     309             :  * Then, whenever advertised services need to be refreshed, the following sequence of events must
     310             :  * occur:
     311             :  * 1. Call the `RemoveServices` method.
     312             :  * 2. Call one of the `Advertise` methods for each service to be added or updated.
     313             :  * 3. Call the `FinalizeServiceUpdate` method to finalize the update and apply all pending changes.
     314             :  */
     315             : class ServiceAdvertiser
     316             : {
     317             : public:
     318           2 :     virtual ~ServiceAdvertiser() {}
     319             : 
     320             :     /**
     321             :      * Initializes the advertiser.
     322             :      *
     323             :      * The method must be called before other methods of this class.
     324             :      * If the advertiser has already been initialized, the method exits immediately with no error.
     325             :      */
     326             :     virtual CHIP_ERROR Init(chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * udpEndPointManager) = 0;
     327             : 
     328             :     /**
     329             :      * Returns whether the advertiser has completed the initialization.
     330             :      *
     331             :      * Returns true if the advertiser is ready to advertise services.
     332             :      */
     333             :     virtual bool IsInitialized() = 0;
     334             : 
     335             :     /**
     336             :      * Shuts down the advertiser.
     337             :      */
     338             :     virtual void Shutdown() = 0;
     339             : 
     340             :     /**
     341             :      * Removes or marks all services being advertised for removal.
     342             :      *
     343             :      * Depending on the implementation, the method may either stop advertising existing services
     344             :      * immediately, or mark them for removal upon the subsequent `FinalizeServiceUpdate` method call.
     345             :      */
     346             :     virtual CHIP_ERROR RemoveServices() = 0;
     347             : 
     348             :     /**
     349             :      * Advertises the given operational node service.
     350             :      */
     351             :     virtual CHIP_ERROR Advertise(const OperationalAdvertisingParameters & params) = 0;
     352             : 
     353             :     /**
     354             :      * Advertises the given commissionable/commissioner node service.
     355             :      */
     356             :     virtual CHIP_ERROR Advertise(const CommissionAdvertisingParameters & params) = 0;
     357             : 
     358             :     /**
     359             :      * Finalizes updating advertised services.
     360             :      *
     361             :      * This method can be used by some implementations to apply changes made with the `RemoveServices`
     362             :      * and `Advertise` methods in case they could not be applied immediately.
     363             :      */
     364             :     virtual CHIP_ERROR FinalizeServiceUpdate() = 0;
     365             : 
     366             :     /**
     367             :      * Returns the commissionable node service instance name formatted as hex string.
     368             :      */
     369             :     virtual CHIP_ERROR GetCommissionableInstanceName(char * instanceName, size_t maxLength) const = 0;
     370             : 
     371             :     /**
     372             :      * Generates an updated commissionable instance name.  This happens
     373             :      * automatically when Init() is called, but may be needed at other times as
     374             :      * well.
     375             :      */
     376             :     virtual CHIP_ERROR UpdateCommissionableInstanceName() = 0;
     377             : 
     378             :     /// Provides the system-wide implementation of the service advertiser
     379             :     static ServiceAdvertiser & Instance();
     380             : };
     381             : 
     382             : } // namespace Dnssd
     383             : } // namespace chip

Generated by: LCOV version 1.14