Matter SDK Coverage Report
Current view: top level - lib/dnssd - IncrementalResolve.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 62.5 % 16 10
Test Date: 2025-01-17 19:00:11 Functions: 63.6 % 11 7

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2022 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              : #pragma once
      18              : 
      19              : #include <lib/dnssd/Resolver.h>
      20              : #include <lib/dnssd/Types.h>
      21              : #include <lib/dnssd/minimal_mdns/Parser.h>
      22              : #include <lib/dnssd/minimal_mdns/RecordData.h>
      23              : #include <lib/dnssd/minimal_mdns/core/QName.h>
      24              : #include <lib/support/BitFlags.h>
      25              : #include <lib/support/Variant.h>
      26              : 
      27              : namespace chip {
      28              : namespace Dnssd {
      29              : 
      30              : /// Allows storing and retrieving of a SerializedQName for later recall.
      31              : ///
      32              : /// This is a convenience storage as MDNS generally provides data as QNames
      33              : /// and comparisons between QNames is more convenient than replacing them with
      34              : /// null-terminated character strings.
      35              : class StoredServerName
      36              : {
      37              : public:
      38          252 :     StoredServerName() {}
      39              : 
      40           25 :     void Clear() { memset(mNameBuffer, 0, sizeof(mNameBuffer)); }
      41              : 
      42              :     /// Set the underlying value. Will return CHIP_ERROR_NO_MEMORY
      43              :     /// on insufficient storage space.
      44              :     ///
      45              :     /// If insufficient space, buffer will be cleared.
      46              :     CHIP_ERROR Set(mdns::Minimal::SerializedQNameIterator value);
      47              : 
      48              :     /// Return the underlying value in this object.
      49              :     ///
      50              :     /// Value valid as long as this object is valid and underlying Set() is
      51              :     /// not called.
      52              :     mdns::Minimal::SerializedQNameIterator Get() const;
      53              : 
      54              : private:
      55              :     // Try to have space for at least:
      56              :     //  L1234._sub._matterc._udp.local      => 30 chars
      57              :     //  <fabric>-<node>._matter._tcp.local  => 52 chars
      58              :     //  <hostname>.local (where hostname is kHostNameMaxLength == 16)
      59              :     //
      60              :     // This does not try to optimize out ".local" suffix which is always expected
      61              :     // since comparisons are easier when suffix is still present.
      62              :     static constexpr size_t kMaxStoredNameLength = 64;
      63              : 
      64              :     uint8_t mNameBuffer[kMaxStoredNameLength] = {};
      65              : };
      66              : 
      67              : /// Incrementally accumulates data from DNSSD packets. It is geared twoards
      68              : /// resource-constrained dns-sd querier implementations.
      69              : ///
      70              : /// It all starts with processing SRV records which define the type of record
      71              : /// (could be operational, commissionable or commissioner), after which the
      72              : /// additional data is accumulated, specifically TXT information and A/AAAA
      73              : ///
      74              : /// Class can also be used to determine what additional data is missing from a
      75              : /// record so that additional DNSSD queries can be made recursively (e.g. if
      76              : /// only a SRV/TXT records are available, ask for AAAA records).
      77              : class IncrementalResolver
      78              : {
      79              : public:
      80              :     // Elements that the incremental resolve still needs
      81              :     enum class RequiredInformationBitFlags : uint8_t
      82              :     {
      83              :         kSrvInitialization = (1 << 0), // server being initialized
      84              :         kIpAddress         = (1 << 1), // IP address missing
      85              :     };
      86              :     using RequiredInformationFlags = BitFlags<RequiredInformationBitFlags>;
      87              : 
      88              :     // Type of service name that is contained in this resolver
      89              :     enum class ServiceNameType
      90              :     {
      91              :         kInvalid, // not a matter service name
      92              :         kOperational,
      93              :         kCommissioner,
      94              :         kCommissionable,
      95              :     };
      96              : 
      97          126 :     IncrementalResolver() = default;
      98              : 
      99              :     /// Checks if object has been initialized using the `InitializeParsing`
     100              :     /// method.
     101          384 :     bool IsActive() const { return mSpecificResolutionData.Valid(); }
     102              : 
     103           36 :     bool IsActiveCommissionParse() const { return mSpecificResolutionData.Is<CommissionNodeData>(); }
     104            0 :     bool IsActiveOperationalParse() const { return mSpecificResolutionData.Is<OperationalNodeData>(); }
     105              : 
     106           12 :     ServiceNameType GetCurrentType() const { return mServiceNameType; }
     107              : 
     108            0 :     PeerId OperationalParsePeerId() const
     109              :     {
     110            0 :         VerifyOrReturnValue(IsActiveOperationalParse(), PeerId());
     111            0 :         return mSpecificResolutionData.Get<OperationalNodeData>().peerId;
     112              :     }
     113              : 
     114              :     /// Start parsing a new record. SRV records are the records we are mainly
     115              :     /// interested on, after which TXT and A/AAAA are looked for.
     116              :     ///
     117              :     /// If this function returns with error, the object will be in an inactive state.
     118              :     CHIP_ERROR InitializeParsing(mdns::Minimal::SerializedQNameIterator name, const uint64_t ttl,
     119              :                                  const mdns::Minimal::SrvRecord & srv);
     120              : 
     121              :     /// Notify that a new record is being processed.
     122              :     /// Will handle filtering and processing of data to determine if the entry is relevant for
     123              :     /// the current resolver.
     124              :     ///
     125              :     /// Providing a data that is not relevant to the current parser is not considered and error,
     126              :     /// however if the resource fails parsing completely an error will be returned.
     127              :     ///
     128              :     ///
     129              :     /// [data] represents the record received via [interface] and [packetRange] represents the range
     130              :     /// of valid bytes within the packet for the purpose of QName parsing
     131              :     CHIP_ERROR OnRecord(Inet::InterfaceId interface, const mdns::Minimal::ResourceData & data,
     132              :                         mdns::Minimal::BytesRange packetRange);
     133              : 
     134              :     /// Return what additional data is required until the object can be extracted
     135              :     ///
     136              :     /// If `!GetREquiredInformation().HasAny()` the parsed information is ready
     137              :     /// to be processed.
     138              :     RequiredInformationFlags GetMissingRequiredInformation() const;
     139              : 
     140              :     /// Fetch the target host name set by `InitializeParsing`
     141              :     ///
     142              :     /// VALIDITY: Data references internal storage of this object and is valid as long
     143              :     ///           as this object is valid and InitializeParsing is not called again.
     144            0 :     mdns::Minimal::SerializedQNameIterator GetTargetHostName() const { return mTargetHostName.Get(); }
     145              : 
     146              :     /// Fetch the record name set by `InitializeParsing`.
     147              :     ///
     148              :     /// VALIDITY: Data references internal storage of this object and is valid as long
     149              :     ///           as this object is valid and InitializeParsing is not called again.
     150            0 :     mdns::Minimal::SerializedQNameIterator GetRecordName() const { return mRecordName.Get(); }
     151              : 
     152              :     /// Take the current value of the object and clear it once returned.
     153              :     ///
     154              :     /// Object must be in `IsActive()` for this to succeed.
     155              :     /// Data will be returned (and cleared) even if not yet complete based
     156              :     /// on `GetMissingRequiredInformation()`. This method takes as much data as
     157              :     /// it was parsed so far.
     158              :     CHIP_ERROR Take(DiscoveredNodeData & outputData);
     159              : 
     160              :     /// Take the current value of the object and clear it once returned.
     161              :     ///
     162              :     /// Object must be in `IsActiveOperationalParse()` for this to succeed.
     163              :     /// Data will be returned (and cleared) even if not yet complete based
     164              :     /// on `GetMissingRequiredInformation()`. This method takes as much data as
     165              :     /// it was parsed so far.
     166              :     CHIP_ERROR Take(ResolvedNodeData & outputData);
     167              : 
     168              :     /// Clears current state, setting as inactive
     169           15 :     void ResetToInactive()
     170              :     {
     171           15 :         mCommonResolutionData.Reset();
     172           15 :         mSpecificResolutionData = ParsedRecordSpecificData();
     173           15 :     }
     174              : 
     175              : private:
     176              :     /// Notify that a PTR record can be parsed.
     177              :     ///
     178              :     /// Input data MUST have GetType() == QType::TXT
     179              :     CHIP_ERROR OnTxtRecord(const mdns::Minimal::ResourceData & data, mdns::Minimal::BytesRange packetRange);
     180              : 
     181              :     /// Notify that a new IP address has been found.
     182              :     ///
     183              :     /// This is to be called on both A (if IPv4 support is enabled) and AAAA
     184              :     /// addresses.
     185              :     ///
     186              :     /// Prerequisite: IP address belongs to the right nost name
     187              :     CHIP_ERROR OnIpAddress(Inet::InterfaceId interface, const Inet::IPAddress & addr);
     188              : 
     189              :     using ParsedRecordSpecificData = Variant<OperationalNodeData, CommissionNodeData>;
     190              : 
     191              :     StoredServerName mRecordName;     // Record name for what is parsed (SRV/PTR/TXT)
     192              :     StoredServerName mTargetHostName; // `Target` for the SRV record
     193              :     ServiceNameType mServiceNameType = ServiceNameType::kInvalid;
     194              :     CommonResolutionData mCommonResolutionData;
     195              :     ParsedRecordSpecificData mSpecificResolutionData;
     196              : };
     197              : 
     198              : } // namespace Dnssd
     199              : } // namespace chip
        

Generated by: LCOV version 2.0-1