Matter SDK Coverage Report
Current view: top level - lib/dnssd - Resolver_ImplMinimalMdns.cpp (source / functions) Coverage Total Hit
Test: SHA:e98a48c2e59f85a25417956e1d105721433aa5d1 Lines: 36.7 % 283 104
Test Date: 2026-01-09 16:53:50 Functions: 48.8 % 41 20

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

Generated by: LCOV version 2.0-1