LCOV - code coverage report
Current view: top level - lib/dnssd - Resolver_ImplMinimalMdns.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 106 270 39.3 %
Date: 2024-02-15 08:20:41 Functions: 20 41 48.8 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  *    Copyright (c) 2021 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             : #include "Resolver.h"
      19             : 
      20             : #include <limits>
      21             : 
      22             : #include <lib/core/CHIPConfig.h>
      23             : #include <lib/dnssd/ActiveResolveAttempts.h>
      24             : #include <lib/dnssd/IncrementalResolve.h>
      25             : #include <lib/dnssd/MinimalMdnsServer.h>
      26             : #include <lib/dnssd/ServiceNaming.h>
      27             : #include <lib/dnssd/minimal_mdns/Logging.h>
      28             : #include <lib/dnssd/minimal_mdns/Parser.h>
      29             : #include <lib/dnssd/minimal_mdns/QueryBuilder.h>
      30             : #include <lib/dnssd/minimal_mdns/RecordData.h>
      31             : #include <lib/dnssd/minimal_mdns/core/FlatAllocatedQName.h>
      32             : #include <lib/support/CHIPMemString.h>
      33             : #include <lib/support/logging/CHIPLogging.h>
      34             : #include <tracing/macros.h>
      35             : 
      36             : // MDNS servers will receive all broadcast packets over the network.
      37             : // Disable 'invalid packet' messages because the are expected and common
      38             : // These logs are useful for debug only
      39             : #undef MINMDNS_RESOLVER_OVERLY_VERBOSE
      40             : 
      41             : namespace chip {
      42             : namespace Dnssd {
      43             : namespace {
      44             : 
      45             : constexpr size_t kMdnsMaxPacketSize = 1024;
      46             : constexpr uint16_t kMdnsPort        = 5353;
      47             : 
      48             : using namespace mdns::Minimal;
      49             : 
      50             : /// Handles processing of minmdns packet data.
      51             : ///
      52             : /// Can process multiple incremental resolves based on SRV data and allows
      53             : /// retrieval of pending (e.g. to ask for AAAA) and complete data items.
      54             : ///
      55             : class PacketParser : private ParserDelegate
      56             : {
      57             : public:
      58          87 :     PacketParser(ActiveResolveAttempts & activeResolves) : mActiveResolves(activeResolves) {}
      59             : 
      60             :     /// Goes through the given SRV records within a response packet
      61             :     /// and sets up data resolution
      62             :     void ParseSrvRecords(const BytesRange & packet);
      63             : 
      64             :     /// Goes through non-SRV records and feeds them through the initialized
      65             :     /// SRV record parsing.
      66             :     ///
      67             :     /// Must be called AFTER ParseSrvRecords has been called.
      68             :     void ParseNonSrvRecords(Inet::InterfaceId interface, const BytesRange & packet);
      69             : 
      70          32 :     IncrementalResolver * ResolverBegin() { return mResolvers; }
      71          96 :     IncrementalResolver * ResolverEnd() { return mResolvers + kMinMdnsNumParallelResolvers; }
      72             : 
      73             : private:
      74             :     // ParserDelegate implementation
      75             :     void OnHeader(ConstHeaderRef & header) override;
      76             :     void OnQuery(const QueryData & data) override;
      77             :     void OnResource(ResourceType type, const ResourceData & data) override;
      78             : 
      79             :     /// Called IFF data is of SRV type and we are in SRV initialization state
      80             :     ///
      81             :     /// Initializes a resolver with the given SRV content as long as
      82             :     /// inactive resolvers exist.
      83             :     void ParseSRVResource(const ResourceData & data);
      84             : 
      85             :     /// Called IFF parsing state is in RecordParsing
      86             :     ///
      87             :     /// Forwards the resource to all active resolvers.
      88             :     void ParseResource(const ResourceData & data);
      89             : 
      90             :     enum class RecordParsingState
      91             :     {
      92             :         kIdle,
      93             :         kSrvInitialization,
      94             :         kRecordParsing,
      95             :     };
      96             : 
      97             :     static constexpr size_t kMinMdnsNumParallelResolvers = CHIP_CONFIG_MINMDNS_MAX_PARALLEL_RESOLVES;
      98             : 
      99             :     // Individual parse set
     100             :     bool mIsResponse               = false;
     101             :     Inet::InterfaceId mInterfaceId = Inet::InterfaceId::Null();
     102             :     BytesRange mPacketRange;
     103             :     RecordParsingState mParsingState = RecordParsingState::kIdle;
     104             : 
     105             :     // resolvers kept between parse steps
     106             :     ActiveResolveAttempts & mActiveResolves;
     107             :     IncrementalResolver mResolvers[kMinMdnsNumParallelResolvers];
     108             : };
     109             : 
     110          64 : void PacketParser::OnHeader(ConstHeaderRef & header)
     111             : {
     112          64 :     mIsResponse = header.GetFlags().IsResponse();
     113             : 
     114             : #ifdef MINMDNS_RESOLVER_OVERLY_VERBOSE
     115             :     if (header.GetFlags().IsTruncated())
     116             :     {
     117             :         // MinMdns does not cache data, so receiving piecewise data does not work
     118             :         ChipLogError(Discovery, "Truncated responses not supported for address resolution");
     119             :     }
     120             : #endif
     121          64 : }
     122             : 
     123           0 : void PacketParser::OnQuery(const QueryData & data)
     124             : {
     125             :     // Ignore queries:
     126             :     //   - unicast answers will include the corresponding query in the answer
     127             :     //     packet, however that is not interesting for the resolver.
     128           0 : }
     129             : 
     130         576 : void PacketParser::OnResource(ResourceType type, const ResourceData & data)
     131             : {
     132         576 :     if (!mIsResponse)
     133             :     {
     134           0 :         return;
     135             :     }
     136             : 
     137         576 :     switch (mParsingState)
     138             :     {
     139         288 :     case RecordParsingState::kSrvInitialization: {
     140         288 :         if (data.GetType() != QType::SRV)
     141             :         {
     142         256 :             return;
     143             :         }
     144          32 :         mdns::Minimal::Logging::LogReceivedResource(data);
     145          32 :         ParseSRVResource(data);
     146          32 :         break;
     147             :     }
     148         288 :     case RecordParsingState::kRecordParsing:
     149         288 :         if (data.GetType() != QType::SRV)
     150             :         {
     151             :             // SRV packets logged during 'SrvInitialization' phase
     152         256 :             mdns::Minimal::Logging::LogReceivedResource(data);
     153             :         }
     154         288 :         ParseResource(data);
     155         288 :         break;
     156           0 :     case RecordParsingState::kIdle:
     157           0 :         ChipLogError(Discovery, "Illegal state: received DNSSD resource while IDLE");
     158           0 :         break;
     159             :     }
     160             : }
     161             : 
     162         288 : void PacketParser::ParseResource(const ResourceData & data)
     163             : {
     164         864 :     for (auto & resolver : mResolvers)
     165             :     {
     166         576 :         if (resolver.IsActive())
     167             :         {
     168         288 :             CHIP_ERROR err = resolver.OnRecord(mInterfaceId, data, mPacketRange);
     169             : 
     170             :             //
     171             :             // CHIP_ERROR_NO_MEMORY usually gets returned when we have no more memory available to hold the
     172             :             // resolved data. This gets emitted fairly frequently in dense environments or when receiving records
     173             :             // from devices with lots of interfaces. Consequently, don't log that unless we have DNS verbosity
     174             :             // logging enabled.
     175             :             //
     176         288 :             if (err != CHIP_NO_ERROR)
     177             :             {
     178             : #if !CHIP_MINMDNS_HIGH_VERBOSITY
     179           0 :                 if (err != CHIP_ERROR_NO_MEMORY)
     180             : #endif
     181           0 :                     ChipLogError(Discovery, "DNSSD parse error: %" CHIP_ERROR_FORMAT, err.Format());
     182             :             }
     183             :         }
     184             :     }
     185             : 
     186             :     // Once an IP address is received, stop requesting it.
     187         288 :     if (data.GetType() == QType::AAAA)
     188             :     {
     189          32 :         mActiveResolves.CompleteIpResolution(data.GetName());
     190             :     }
     191         288 : }
     192             : 
     193          32 : void PacketParser::ParseSRVResource(const ResourceData & data)
     194             : {
     195          32 :     SrvRecord srv;
     196          32 :     if (!srv.Parse(data.GetData(), mPacketRange))
     197             :     {
     198           0 :         ChipLogError(Discovery, "Packet data reporter failed to parse SRV record");
     199          32 :         return;
     200             :     }
     201             : 
     202          96 :     for (auto & resolver : mResolvers)
     203             :     {
     204          64 :         if (resolver.IsActive() && (resolver.GetRecordName() == data.GetName()))
     205             :         {
     206           0 :             ChipLogDetail(Discovery, "SRV record already actively processed.");
     207           0 :             return;
     208             :         }
     209             :     }
     210             : 
     211          32 :     for (auto & resolver : mResolvers)
     212             :     {
     213          32 :         if (resolver.IsActive())
     214             :         {
     215           0 :             continue;
     216             :         }
     217             : 
     218          32 :         CHIP_ERROR err = resolver.InitializeParsing(data.GetName(), srv);
     219          32 :         if (err != CHIP_NO_ERROR)
     220             :         {
     221             :             // Receiving records that we do not need to parse is normal:
     222             :             // MinMDNS may receive all DNSSD packets on the network, only
     223             :             // interested in a subset that is matter-specific
     224             : #ifdef MINMDNS_RESOLVER_OVERLY_VERBOSE
     225             :             ChipLogError(Discovery, "Could not start SRV record processing: %" CHIP_ERROR_FORMAT, err.Format());
     226             : #endif
     227             :         }
     228             : 
     229             :         // Done finding an inactive resolver and attempting to use it.
     230          32 :         return;
     231             :     }
     232             : 
     233             : #if CHIP_MINMDNS_HIGH_VERBOSITY
     234             :     ChipLogError(Discovery, "Insufficient parsers to process all SRV entries.");
     235             : #endif
     236             : }
     237             : 
     238          32 : void PacketParser::ParseSrvRecords(const BytesRange & packet)
     239             : {
     240             :     MATTER_TRACE_SCOPE("Searching SRV Records", "PacketParser");
     241             : 
     242          32 :     mParsingState = RecordParsingState::kSrvInitialization;
     243          32 :     mPacketRange  = packet;
     244             : 
     245          32 :     if (!ParsePacket(packet, this))
     246             :     {
     247           0 :         ChipLogError(Discovery, "DNSSD packet parsing failed (for SRV records)");
     248             :     }
     249             : 
     250          32 :     mParsingState = RecordParsingState::kIdle;
     251          32 : }
     252             : 
     253          32 : void PacketParser::ParseNonSrvRecords(Inet::InterfaceId interface, const BytesRange & packet)
     254             : {
     255             :     MATTER_TRACE_SCOPE("Searching NON-SRV Records", "PacketParser");
     256             : 
     257          32 :     mParsingState = RecordParsingState::kRecordParsing;
     258          32 :     mPacketRange  = packet;
     259          32 :     mInterfaceId  = interface;
     260             : 
     261          32 :     if (!ParsePacket(packet, this))
     262             :     {
     263           0 :         ChipLogError(Discovery, "DNSSD packet parsing failed (for non-srv records)");
     264             :     }
     265             : 
     266          32 :     mParsingState = RecordParsingState::kIdle;
     267          32 : }
     268             : 
     269             : class MinMdnsResolver : public Resolver, public MdnsPacketDelegate
     270             : {
     271             : public:
     272          29 :     MinMdnsResolver() : mActiveResolves(&chip::System::SystemClock()), mPacketParser(mActiveResolves)
     273             :     {
     274          29 :         GlobalMinimalMdnsServer::Instance().SetResponseDelegate(this);
     275          29 :     }
     276          29 :     ~MinMdnsResolver() { SetDiscoveryContext(nullptr); }
     277             : 
     278             :     //// MdnsPacketDelegate implementation
     279             :     void OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info) override;
     280             : 
     281             :     ///// Resolver implementation
     282             :     CHIP_ERROR Init(chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * udpEndPointManager) override;
     283             :     bool IsInitialized() override;
     284             :     void Shutdown() override;
     285           1 :     void SetOperationalDelegate(OperationalResolveDelegate * delegate) override { mOperationalDelegate = delegate; }
     286             :     CHIP_ERROR ResolveNodeId(const PeerId & peerId) override;
     287             :     void NodeIdResolutionNoLongerNeeded(const PeerId & peerId) override;
     288             :     CHIP_ERROR DiscoverCommissionableNodes(DiscoveryFilter filter, DiscoveryContext & context) override;
     289             :     CHIP_ERROR DiscoverCommissioners(DiscoveryFilter filter, DiscoveryContext & context) override;
     290             :     CHIP_ERROR StopDiscovery(DiscoveryContext & context) override;
     291             :     CHIP_ERROR ReconfirmRecord(const char * hostname, Inet::IPAddress address, Inet::InterfaceId interfaceId) override;
     292             : 
     293             : private:
     294             :     OperationalResolveDelegate * mOperationalDelegate = nullptr;
     295             :     DiscoveryContext * mDiscoveryContext              = nullptr;
     296             :     System::Layer * mSystemLayer                      = nullptr;
     297             :     ActiveResolveAttempts mActiveResolves;
     298             :     PacketParser mPacketParser;
     299             : 
     300             :     void SetDiscoveryContext(DiscoveryContext * context);
     301             :     void ScheduleIpAddressResolve(SerializedQNameIterator hostName);
     302             : 
     303             :     CHIP_ERROR SendAllPendingQueries();
     304             :     CHIP_ERROR ScheduleRetries();
     305             : 
     306             :     /// Prepare a query for the given schedule attempt
     307             :     CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt & attempt);
     308             : 
     309             :     /// Prepare a query for specific resolve types
     310             :     CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Browse & data, bool firstSend);
     311             :     CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Resolve & data, bool firstSend);
     312             :     CHIP_ERROR BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::IpResolve & data, bool firstSend);
     313             : 
     314             :     /// Clear any incremental resolver that is not waiting for a AAAA address.
     315             :     void ExpireIncrementalResolvers();
     316             :     void AdvancePendingResolverStates();
     317             : 
     318             :     static void RetryCallback(System::Layer *, void * self);
     319             : 
     320             :     CHIP_ERROR BrowseNodes(DiscoveryType type, DiscoveryFilter subtype);
     321             :     template <typename... Args>
     322           0 :     mdns::Minimal::FullQName CheckAndAllocateQName(Args &&... parts)
     323             :     {
     324           0 :         size_t requiredSize = mdns::Minimal::FlatAllocatedQName::RequiredStorageSize(parts...);
     325           0 :         if (requiredSize > kMaxQnameSize)
     326             :         {
     327           0 :             return mdns::Minimal::FullQName();
     328             :         }
     329           0 :         return mdns::Minimal::FlatAllocatedQName::Build(qnameStorage, parts...);
     330             :     }
     331             :     static constexpr int kMaxQnameSize = 100;
     332             :     char qnameStorage[kMaxQnameSize];
     333             : };
     334             : 
     335          29 : void MinMdnsResolver::SetDiscoveryContext(DiscoveryContext * context)
     336             : {
     337          29 :     if (mDiscoveryContext != nullptr)
     338             :     {
     339           0 :         mDiscoveryContext->Release();
     340             :     }
     341             : 
     342          29 :     if (context != nullptr)
     343             :     {
     344           0 :         context->Retain();
     345             :     }
     346             : 
     347          29 :     mDiscoveryContext = context;
     348          29 : }
     349             : 
     350           0 : void MinMdnsResolver::ScheduleIpAddressResolve(SerializedQNameIterator hostName)
     351             : {
     352           0 :     HeapQName target(hostName);
     353           0 :     if (!target.IsOk())
     354             :     {
     355           0 :         ChipLogError(Discovery, "Memory allocation error for IP address resolution");
     356           0 :         return;
     357             :     }
     358           0 :     mActiveResolves.MarkPending(ActiveResolveAttempts::ScheduledAttempt::IpResolve(std::move(target)));
     359           0 : }
     360             : 
     361          32 : void MinMdnsResolver::AdvancePendingResolverStates()
     362             : {
     363             :     MATTER_TRACE_SCOPE("Advance pending resolve states", "MinMdnsResolver");
     364             : 
     365          96 :     for (IncrementalResolver * resolver = mPacketParser.ResolverBegin(); resolver != mPacketParser.ResolverEnd(); resolver++)
     366             :     {
     367          64 :         if (!resolver->IsActive())
     368             :         {
     369          32 :             continue;
     370             :         }
     371             : 
     372          32 :         IncrementalResolver::RequiredInformationFlags missing = resolver->GetMissingRequiredInformation();
     373             : 
     374          32 :         if (missing.Has(IncrementalResolver::RequiredInformationBitFlags::kIpAddress))
     375             :         {
     376           0 :             ScheduleIpAddressResolve(resolver->GetTargetHostName());
     377           0 :             continue;
     378             :         }
     379             : 
     380          32 :         if (missing.HasAny())
     381             :         {
     382             :             // Expect either IP missing (ask for it) or done. Anything else is not handled
     383           0 :             ChipLogError(Discovery, "Unexpected state: cannot advance resolver with missing information");
     384           0 :             resolver->ResetToInactive();
     385           0 :             continue;
     386             :         }
     387             : 
     388             :         // SUCCESS. Call the delegates
     389          32 :         if (resolver->IsActiveCommissionParse())
     390             :         {
     391             :             MATTER_TRACE_SCOPE("Active commissioning delegate call", "MinMdnsResolver");
     392          32 :             DiscoveredNodeData nodeData;
     393             : 
     394          32 :             CHIP_ERROR err = resolver->Take(nodeData);
     395          32 :             if (err != CHIP_NO_ERROR)
     396             :             {
     397           0 :                 ChipLogError(Discovery, "Failed to take discovery result: %" CHIP_ERROR_FORMAT, err.Format());
     398           0 :                 continue;
     399             :             }
     400             : 
     401             :             // TODO: Ideally commissioning delegates should be aware of the
     402             :             //       node types they receive, however they are currently not
     403             :             //       so try to help out by only calling the delegate when an
     404             :             //       active browse exists.
     405             :             //
     406             :             // This is NOT ok and probably we should have separate comissioner
     407             :             // or commissionable delegates or pass in a node type argument.
     408          32 :             bool discoveredNodeIsRelevant = false;
     409             : 
     410          32 :             switch (resolver->GetCurrentType())
     411             :             {
     412           0 :             case IncrementalResolver::ServiceNameType::kCommissioner:
     413           0 :                 discoveredNodeIsRelevant = mActiveResolves.HasBrowseFor(chip::Dnssd::DiscoveryType::kCommissionerNode);
     414           0 :                 mActiveResolves.CompleteCommissioner(nodeData);
     415           0 :                 break;
     416          32 :             case IncrementalResolver::ServiceNameType::kCommissionable:
     417          32 :                 discoveredNodeIsRelevant = mActiveResolves.HasBrowseFor(chip::Dnssd::DiscoveryType::kCommissionableNode);
     418          32 :                 mActiveResolves.CompleteCommissionable(nodeData);
     419          32 :                 break;
     420           0 :             default:
     421           0 :                 ChipLogError(Discovery, "Unexpected type for commission data parsing");
     422           0 :                 continue;
     423             :             }
     424             : 
     425          32 :             if (discoveredNodeIsRelevant)
     426             :             {
     427           0 :                 if (mDiscoveryContext != nullptr)
     428             :                 {
     429           0 :                     mDiscoveryContext->OnNodeDiscovered(nodeData);
     430             :                 }
     431             :                 else
     432             :                 {
     433             : #if CHIP_MINMDNS_HIGH_VERBOSITY
     434             :                     ChipLogError(Discovery, "No delegate to report commissioning node discovery");
     435             : #endif
     436             :                 }
     437             :             }
     438          32 :         }
     439           0 :         else if (resolver->IsActiveOperationalParse())
     440             :         {
     441             :             MATTER_TRACE_SCOPE("Active operational delegate call", "MinMdnsResolver");
     442           0 :             ResolvedNodeData nodeData;
     443             : 
     444           0 :             CHIP_ERROR err = resolver->Take(nodeData);
     445           0 :             if (err != CHIP_NO_ERROR)
     446             :             {
     447           0 :                 ChipLogError(Discovery, "Failed to take discovery result: %" CHIP_ERROR_FORMAT, err.Format());
     448             :             }
     449             : 
     450           0 :             mActiveResolves.Complete(nodeData.operationalData.peerId);
     451           0 :             if (mOperationalDelegate != nullptr)
     452             :             {
     453           0 :                 mOperationalDelegate->OnOperationalNodeResolved(nodeData);
     454             :             }
     455             :             else
     456             :             {
     457             : #if CHIP_MINMDNS_HIGH_VERBOSITY
     458             :                 ChipLogError(Discovery, "No delegate to report operational node discovery");
     459             : #endif
     460             :             }
     461           0 :         }
     462             :         else
     463             :         {
     464           0 :             ChipLogError(Discovery, "Unexpected state: record type unknown");
     465           0 :             resolver->ResetToInactive();
     466             :         }
     467             :     }
     468          32 : }
     469             : 
     470          32 : void MinMdnsResolver::OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info)
     471             : {
     472             :     MATTER_TRACE_SCOPE("Received MDNS Packet", "MinMdnsResolver");
     473             : 
     474             :     // Fill up any relevant data
     475          32 :     mPacketParser.ParseSrvRecords(data);
     476          32 :     mPacketParser.ParseNonSrvRecords(info->Interface, data);
     477             : 
     478          32 :     AdvancePendingResolverStates();
     479             : 
     480          32 :     ScheduleRetries();
     481          32 : }
     482             : 
     483           1 : CHIP_ERROR MinMdnsResolver::Init(chip::Inet::EndPointManager<chip::Inet::UDPEndPoint> * udpEndPointManager)
     484             : {
     485             :     /// Note: we do not double-check the port as we assume the APP will always use
     486             :     /// the same udpEndPointManager and port for mDNS.
     487           1 :     mSystemLayer = &udpEndPointManager->SystemLayer();
     488             : 
     489           1 :     if (GlobalMinimalMdnsServer::Server().IsListening())
     490             :     {
     491           0 :         return CHIP_NO_ERROR;
     492             :     }
     493             : 
     494           1 :     return GlobalMinimalMdnsServer::Instance().StartServer(udpEndPointManager, kMdnsPort);
     495             : }
     496             : 
     497           1 : bool MinMdnsResolver::IsInitialized()
     498             : {
     499           1 :     return GlobalMinimalMdnsServer::Server().IsListening();
     500             : }
     501             : 
     502           1 : void MinMdnsResolver::Shutdown()
     503             : {
     504           1 :     GlobalMinimalMdnsServer::Instance().ShutdownServer();
     505           1 : }
     506             : 
     507           0 : CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Browse & data,
     508             :                                        bool firstSend)
     509             : {
     510           0 :     mdns::Minimal::FullQName qname;
     511             : 
     512           0 :     switch (data.type)
     513             :     {
     514           0 :     case DiscoveryType::kOperational:
     515           0 :         qname = CheckAndAllocateQName(kOperationalServiceName, kOperationalProtocol, kLocalDomain);
     516           0 :         break;
     517           0 :     case DiscoveryType::kCommissionableNode:
     518           0 :         if (data.filter.type == DiscoveryFilterType::kNone)
     519             :         {
     520           0 :             qname = CheckAndAllocateQName(kCommissionableServiceName, kCommissionProtocol, kLocalDomain);
     521             :         }
     522           0 :         else if (data.filter.type == DiscoveryFilterType::kInstanceName)
     523             :         {
     524           0 :             qname = CheckAndAllocateQName(data.filter.instanceName, kCommissionableServiceName, kCommissionProtocol, kLocalDomain);
     525             :         }
     526             :         else
     527             :         {
     528             :             char subtypeStr[Common::kSubTypeMaxLength + 1];
     529           0 :             ReturnErrorOnFailure(MakeServiceSubtype(subtypeStr, sizeof(subtypeStr), data.filter));
     530           0 :             qname = CheckAndAllocateQName(subtypeStr, kSubtypeServiceNamePart, kCommissionableServiceName, kCommissionProtocol,
     531             :                                           kLocalDomain);
     532             :         }
     533           0 :         break;
     534           0 :     case DiscoveryType::kCommissionerNode:
     535           0 :         if (data.filter.type == DiscoveryFilterType::kNone)
     536             :         {
     537           0 :             qname = CheckAndAllocateQName(kCommissionerServiceName, kCommissionProtocol, kLocalDomain);
     538             :         }
     539             :         else
     540             :         {
     541             :             char subtypeStr[Common::kSubTypeMaxLength + 1];
     542           0 :             ReturnErrorOnFailure(MakeServiceSubtype(subtypeStr, sizeof(subtypeStr), data.filter));
     543           0 :             qname = CheckAndAllocateQName(subtypeStr, kSubtypeServiceNamePart, kCommissionerServiceName, kCommissionProtocol,
     544             :                                           kLocalDomain);
     545             :         }
     546           0 :         break;
     547           0 :     case DiscoveryType::kUnknown:
     548           0 :         break;
     549             :     }
     550             : 
     551           0 :     ReturnErrorCodeIf(!qname.nameCount, CHIP_ERROR_NO_MEMORY);
     552             : 
     553           0 :     mdns::Minimal::Query query(qname);
     554             :     query
     555           0 :         .SetClass(QClass::IN)           //
     556           0 :         .SetType(QType::ANY)            //
     557           0 :         .SetAnswerViaUnicast(firstSend) //
     558             :         ;
     559             : 
     560           0 :     mdns::Minimal::Logging::LogSendingQuery(query);
     561           0 :     builder.AddQuery(query);
     562             : 
     563           0 :     return CHIP_NO_ERROR;
     564             : }
     565             : 
     566           0 : CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::Resolve & data,
     567             :                                        bool firstSend)
     568             : {
     569           0 :     char nameBuffer[kMaxOperationalServiceNameSize] = "";
     570             : 
     571             :     // Node and fabricid are encoded in server names.
     572           0 :     ReturnErrorOnFailure(MakeInstanceName(nameBuffer, sizeof(nameBuffer), data.peerId));
     573             : 
     574           0 :     const char * instanceQName[] = { nameBuffer, kOperationalServiceName, kOperationalProtocol, kLocalDomain };
     575           0 :     Query query(instanceQName);
     576             : 
     577             :     query
     578           0 :         .SetClass(QClass::IN)           //
     579           0 :         .SetType(QType::ANY)            //
     580           0 :         .SetAnswerViaUnicast(firstSend) //
     581             :         ;
     582             : 
     583           0 :     mdns::Minimal::Logging::LogSendingQuery(query);
     584           0 :     builder.AddQuery(query);
     585             : 
     586           0 :     return CHIP_NO_ERROR;
     587             : }
     588             : 
     589           0 : CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt::IpResolve & data,
     590             :                                        bool firstSend)
     591             : {
     592             : 
     593           0 :     Query query(data.hostName.Content());
     594             : 
     595             :     query
     596           0 :         .SetClass(QClass::IN)           //
     597           0 :         .SetType(QType::AAAA)           //
     598           0 :         .SetAnswerViaUnicast(firstSend) //
     599             :         ;
     600             : 
     601           0 :     mdns::Minimal::Logging::LogSendingQuery(query);
     602           0 :     builder.AddQuery(query);
     603             : 
     604           0 :     return CHIP_NO_ERROR;
     605             : }
     606             : 
     607           0 : CHIP_ERROR MinMdnsResolver::BuildQuery(QueryBuilder & builder, const ActiveResolveAttempts::ScheduledAttempt & attempt)
     608             : {
     609           0 :     if (attempt.IsResolve())
     610             :     {
     611           0 :         ReturnErrorOnFailure(BuildQuery(builder, attempt.ResolveData(), attempt.firstSend));
     612             :     }
     613           0 :     else if (attempt.IsBrowse())
     614             :     {
     615           0 :         ReturnErrorOnFailure(BuildQuery(builder, attempt.BrowseData(), attempt.firstSend));
     616             :     }
     617           0 :     else if (attempt.IsIpResolve())
     618             :     {
     619           0 :         ReturnErrorOnFailure(BuildQuery(builder, attempt.IpResolveData(), attempt.firstSend));
     620             :     }
     621             :     else
     622             :     {
     623           0 :         return CHIP_ERROR_INVALID_ARGUMENT;
     624             :     }
     625             : 
     626           0 :     ReturnErrorCodeIf(!builder.Ok(), CHIP_ERROR_INTERNAL);
     627           0 :     return CHIP_NO_ERROR;
     628             : }
     629             : 
     630           0 : CHIP_ERROR MinMdnsResolver::SendAllPendingQueries()
     631             : {
     632             :     while (true)
     633             :     {
     634           0 :         Optional<ActiveResolveAttempts::ScheduledAttempt> resolve = mActiveResolves.NextScheduled();
     635             : 
     636           0 :         if (!resolve.HasValue())
     637             :         {
     638           0 :             break;
     639             :         }
     640             : 
     641           0 :         System::PacketBufferHandle buffer = System::PacketBufferHandle::New(kMdnsMaxPacketSize);
     642           0 :         ReturnErrorCodeIf(buffer.IsNull(), CHIP_ERROR_NO_MEMORY);
     643             : 
     644           0 :         QueryBuilder builder(std::move(buffer));
     645           0 :         builder.Header().SetMessageId(0);
     646             : 
     647           0 :         ReturnErrorOnFailure(BuildQuery(builder, resolve.Value()));
     648             : 
     649           0 :         if (resolve.Value().firstSend)
     650             :         {
     651           0 :             ReturnErrorOnFailure(GlobalMinimalMdnsServer::Server().BroadcastUnicastQuery(builder.ReleasePacket(), kMdnsPort));
     652             :         }
     653             :         else
     654             :         {
     655           0 :             ReturnErrorOnFailure(GlobalMinimalMdnsServer::Server().BroadcastSend(builder.ReleasePacket(), kMdnsPort));
     656             :         }
     657           0 :     }
     658             : 
     659           0 :     ExpireIncrementalResolvers();
     660             : 
     661           0 :     return ScheduleRetries();
     662             : }
     663             : 
     664           0 : void MinMdnsResolver::ExpireIncrementalResolvers()
     665             : {
     666             :     // once all queries are sent, if any SRV cannot receive AAAA addresses, expire it
     667           0 :     for (IncrementalResolver * resolver = mPacketParser.ResolverBegin(); resolver != mPacketParser.ResolverEnd(); resolver++)
     668             :     {
     669           0 :         if (!resolver->IsActive())
     670             :         {
     671           0 :             continue;
     672             :         }
     673             : 
     674           0 :         IncrementalResolver::RequiredInformationFlags missing = resolver->GetMissingRequiredInformation();
     675           0 :         if (missing.Has(IncrementalResolver::RequiredInformationBitFlags::kIpAddress))
     676             :         {
     677           0 :             if (mActiveResolves.IsWaitingForIpResolutionFor(resolver->GetTargetHostName()))
     678             :             {
     679           0 :                 continue;
     680             :             }
     681             :         }
     682             : 
     683             :         // mark as expired: not waiting for anything
     684           0 :         resolver->ResetToInactive();
     685             :     }
     686           0 : }
     687             : 
     688           0 : CHIP_ERROR MinMdnsResolver::DiscoverCommissionableNodes(DiscoveryFilter filter, DiscoveryContext & context)
     689             : {
     690             :     // minmdns currently supports only one discovery context at a time so override the previous context
     691           0 :     SetDiscoveryContext(&context);
     692             : 
     693           0 :     return BrowseNodes(DiscoveryType::kCommissionableNode, filter);
     694             : }
     695             : 
     696           0 : CHIP_ERROR MinMdnsResolver::DiscoverCommissioners(DiscoveryFilter filter, DiscoveryContext & context)
     697             : {
     698             :     // minmdns currently supports only one discovery context at a time so override the previous context
     699           0 :     SetDiscoveryContext(&context);
     700             : 
     701           0 :     return BrowseNodes(DiscoveryType::kCommissionerNode, filter);
     702             : }
     703             : 
     704           0 : CHIP_ERROR MinMdnsResolver::StopDiscovery(DiscoveryContext & context)
     705             : {
     706           0 :     SetDiscoveryContext(nullptr);
     707             : 
     708           0 :     return mActiveResolves.CompleteAllBrowses();
     709             : }
     710             : 
     711           0 : CHIP_ERROR MinMdnsResolver::ReconfirmRecord(const char * hostname, Inet::IPAddress address, Inet::InterfaceId interfaceId)
     712             : {
     713           0 :     return CHIP_ERROR_NOT_IMPLEMENTED;
     714             : }
     715             : 
     716           0 : CHIP_ERROR MinMdnsResolver::BrowseNodes(DiscoveryType type, DiscoveryFilter filter)
     717             : {
     718           0 :     mActiveResolves.MarkPending(filter, type);
     719             : 
     720           0 :     return SendAllPendingQueries();
     721             : }
     722             : 
     723           0 : CHIP_ERROR MinMdnsResolver::ResolveNodeId(const PeerId & peerId)
     724             : {
     725           0 :     mActiveResolves.MarkPending(peerId);
     726             : 
     727           0 :     return SendAllPendingQueries();
     728             : }
     729             : 
     730           0 : void MinMdnsResolver::NodeIdResolutionNoLongerNeeded(const PeerId & peerId)
     731             : {
     732           0 :     mActiveResolves.NodeIdResolutionNoLongerNeeded(peerId);
     733           0 : }
     734             : 
     735          32 : CHIP_ERROR MinMdnsResolver::ScheduleRetries()
     736             : {
     737             :     MATTER_TRACE_SCOPE("Schedule retries", "MinMdnsResolver");
     738             : 
     739          32 :     ReturnErrorCodeIf(mSystemLayer == nullptr, CHIP_ERROR_INCORRECT_STATE);
     740          32 :     mSystemLayer->CancelTimer(&RetryCallback, this);
     741             : 
     742          32 :     Optional<System::Clock::Timeout> delay = mActiveResolves.GetTimeUntilNextExpectedResponse();
     743             : 
     744          32 :     if (!delay.HasValue())
     745             :     {
     746          32 :         return CHIP_NO_ERROR;
     747             :     }
     748             : 
     749           0 :     return mSystemLayer->StartTimer(delay.Value(), &RetryCallback, this);
     750          32 : }
     751             : 
     752           0 : void MinMdnsResolver::RetryCallback(System::Layer *, void * self)
     753             : {
     754           0 :     reinterpret_cast<MinMdnsResolver *>(self)->SendAllPendingQueries();
     755           0 : }
     756             : 
     757             : MinMdnsResolver gResolver;
     758             : 
     759             : } // namespace
     760             : 
     761           6 : Resolver & chip::Dnssd::Resolver::Instance()
     762             : {
     763           6 :     return gResolver;
     764             : }
     765             : 
     766             : } // namespace Dnssd
     767             : } // namespace chip

Generated by: LCOV version 1.14