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

Generated by: LCOV version 2.0-1