Report mdns results from all interfaces instead of the highest prioriā€¦ (#35597)

* [chip-tool] Add discover find-commissionable-by-instance-name command

* Report mdns results from all interfaces instead of the highest priority interface

* Update DnssdContexts.cpp
diff --git a/examples/chip-tool/commands/discover/Commands.h b/examples/chip-tool/commands/discover/Commands.h
index d308d4a..d70191f 100644
--- a/examples/chip-tool/commands/discover/Commands.h
+++ b/examples/chip-tool/commands/discover/Commands.h
@@ -84,6 +84,7 @@
         make_unique<DiscoverCommissionableByCommissioningModeCommand>(credsIssuerConfig),
         make_unique<DiscoverCommissionableByVendorIdCommand>(credsIssuerConfig),
         make_unique<DiscoverCommissionableByDeviceTypeCommand>(credsIssuerConfig),
+        make_unique<DiscoverCommissionableByInstanceNameCommand>(credsIssuerConfig),
         make_unique<DiscoverCommissionersCommand>(credsIssuerConfig),
     };
 
diff --git a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp
index ad5e7fe..35d833e 100644
--- a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp
+++ b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.cpp
@@ -122,3 +122,11 @@
     chip::Dnssd::DiscoveryFilter filter(chip::Dnssd::DiscoveryFilterType::kDeviceType, mDeviceType);
     return mCommissioner->DiscoverCommissionableNodes(filter);
 }
+
+CHIP_ERROR DiscoverCommissionableByInstanceNameCommand::RunCommand()
+{
+    mCommissioner = &CurrentCommissioner();
+    mCommissioner->RegisterDeviceDiscoveryDelegate(this);
+    chip::Dnssd::DiscoveryFilter filter(chip::Dnssd::DiscoveryFilterType::kInstanceName, mInstanceName);
+    return mCommissioner->DiscoverCommissionableNodes(filter);
+}
diff --git a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.h b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.h
index d1fec30..2ba81b6 100644
--- a/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.h
+++ b/examples/chip-tool/commands/discover/DiscoverCommissionablesCommand.h
@@ -159,3 +159,19 @@
     // TODO: possibly 32-bit - see spec issue #3226
     uint16_t mDeviceType;
 };
+
+class DiscoverCommissionableByInstanceNameCommand : public DiscoverCommissionablesCommandBase
+{
+public:
+    DiscoverCommissionableByInstanceNameCommand(CredentialIssuerCommands * credsIssuerConfig) :
+        DiscoverCommissionablesCommandBase("find-commissionable-by-instance-name", credsIssuerConfig)
+    {
+        AddArgument("value", &mInstanceName);
+    }
+
+    /////////// CHIPCommand Interface /////////
+    CHIP_ERROR RunCommand() override;
+
+private:
+    char * mInstanceName;
+};
diff --git a/src/lib/dnssd/Discovery_ImplPlatform.cpp b/src/lib/dnssd/Discovery_ImplPlatform.cpp
index 54947cd..6f98ac7 100644
--- a/src/lib/dnssd/Discovery_ImplPlatform.cpp
+++ b/src/lib/dnssd/Discovery_ImplPlatform.cpp
@@ -43,7 +43,7 @@
 {
     DiscoveryContext * discoveryContext = static_cast<DiscoveryContext *>(context);
 
-    if (error != CHIP_NO_ERROR)
+    if (error != CHIP_NO_ERROR && error != CHIP_ERROR_IN_PROGRESS)
     {
         discoveryContext->Release();
         return;
@@ -55,7 +55,13 @@
 
     nodeData.Get<CommissionNodeData>().LogDetail();
     discoveryContext->OnNodeDiscovered(nodeData);
-    discoveryContext->Release();
+
+    // CHIP_ERROR_IN_PROGRESS indicates that more results are coming, so don't release
+    // the context yet.
+    if (error == CHIP_NO_ERROR)
+    {
+        discoveryContext->Release();
+    }
 }
 
 static void HandleNodeOperationalBrowse(void * context, DnssdService * result, CHIP_ERROR error)
diff --git a/src/platform/Darwin/DnssdContexts.cpp b/src/platform/Darwin/DnssdContexts.cpp
index 9d293c0..e6b590d 100644
--- a/src/platform/Darwin/DnssdContexts.cpp
+++ b/src/platform/Darwin/DnssdContexts.cpp
@@ -564,88 +564,78 @@
     };
 #endif // TARGET_OS_TV
 
-    for (auto interfaceIndex : priorityInterfaceIndices)
+    std::vector<InterfaceKey> interfacesOrder;
+    for (auto priorityInterfaceIndex : priorityInterfaceIndices)
     {
-        if (interfaceIndex == 0)
+        if (priorityInterfaceIndex == 0)
         {
             // Not actually an interface we have, since if_nametoindex
             // returned 0.
             continue;
         }
 
-        if (TryReportingResultsForInterfaceIndex(static_cast<uint32_t>(interfaceIndex)))
+        for (auto & interface : interfaces)
         {
-            return;
-        }
-    }
-
-    for (auto & interface : interfaces)
-    {
-        if (TryReportingResultsForInterfaceIndex(interface.first.interfaceId, interface.first.hostname,
-                                                 interface.first.isSRPResult))
-        {
-            return;
-        }
-    }
-
-    ChipLogError(Discovery, "Successfully finalizing resolve for %s without finding any actual IP addresses.",
-                 instanceName.c_str());
-}
-
-bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex, const std::string & hostname, bool isSRPResult)
-{
-    InterfaceKey interfaceKey = { interfaceIndex, hostname, isSRPResult };
-    auto & interface          = interfaces[interfaceKey];
-    auto & ips                = interface.addresses;
-
-    // Some interface may not have any ips, just ignore them.
-    if (ips.size() == 0)
-    {
-        return false;
-    }
-
-    ChipLogProgress(Discovery, "Mdns: Resolve success on interface %" PRIu32, interfaceIndex);
-
-    auto & service = interface.service;
-    auto addresses = Span<Inet::IPAddress>(ips.data(), ips.size());
-    if (nullptr == callback)
-    {
-        auto delegate = static_cast<DiscoverNodeDelegate *>(context);
-        DiscoveredNodeData nodeData;
-
-        // Check whether mType (service name) exactly matches with operational service name
-        if (strcmp(service.mType, kOperationalServiceName) == 0)
-        {
-            service.ToDiscoveredOperationalNodeBrowseData(nodeData);
-        }
-        else
-        {
-            service.ToDiscoveredCommissionNodeData(addresses, nodeData);
-        }
-        delegate->OnNodeDiscovered(nodeData);
-    }
-    else
-    {
-        callback(context, &service, addresses, CHIP_NO_ERROR);
-    }
-
-    return true;
-}
-
-bool ResolveContext::TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex)
-{
-    for (auto & interface : interfaces)
-    {
-        if (interface.first.interfaceId == interfaceIndex)
-        {
-            if (TryReportingResultsForInterfaceIndex(interface.first.interfaceId, interface.first.hostname,
-                                                     interface.first.isSRPResult))
+            if (interface.second.HasAddresses() && priorityInterfaceIndex == interface.first.interfaceId)
             {
-                return true;
+                interfacesOrder.push_back(interface.first);
             }
         }
     }
-    return false;
+
+    for (auto & interface : interfaces)
+    {
+        // Skip interfaces that have already been prioritized to avoid duplicate results
+        auto interfaceKey = std::find(std::begin(interfacesOrder), std::end(interfacesOrder), interface.first);
+        if (interfaceKey != std::end(interfacesOrder))
+        {
+            continue;
+        }
+
+        // Some interface may not have any ips, just ignore them.
+        if (!interface.second.HasAddresses())
+        {
+            continue;
+        }
+
+        interfacesOrder.push_back(interface.first);
+    }
+
+    for (auto & interfaceKey : interfacesOrder)
+    {
+        auto & interfaceInfo = interfaces[interfaceKey];
+        auto & service       = interfaceInfo.service;
+        auto & ips           = interfaceInfo.addresses;
+        auto addresses       = Span<Inet::IPAddress>(ips.data(), ips.size());
+
+        ChipLogProgress(Discovery, "Mdns: Resolve success on interface %" PRIu32, interfaceKey.interfaceId);
+
+        if (nullptr == callback)
+        {
+            auto delegate = static_cast<DiscoverNodeDelegate *>(context);
+            DiscoveredNodeData nodeData;
+
+            // Check whether mType (service name) exactly matches with operational service name
+            if (strcmp(service.mType, kOperationalServiceName) == 0)
+            {
+                service.ToDiscoveredOperationalNodeBrowseData(nodeData);
+            }
+            else
+            {
+                service.ToDiscoveredCommissionNodeData(addresses, nodeData);
+            }
+            delegate->OnNodeDiscovered(nodeData);
+        }
+        else
+        {
+            CHIP_ERROR error = &interfaceKey == &interfacesOrder.back() ? CHIP_NO_ERROR : CHIP_ERROR_IN_PROGRESS;
+            callback(context, &service, addresses, error);
+        }
+    }
+
+    VerifyOrDo(interfacesOrder.size(),
+               ChipLogError(Discovery, "Successfully finalizing resolve for %s without finding any actual IP addresses.",
+                            instanceName.c_str()));
 }
 
 void ResolveContext::SRPTimerExpiredCallback(chip::System::Layer * systemLayer, void * callbackContext)
diff --git a/src/platform/Darwin/DnssdImpl.h b/src/platform/Darwin/DnssdImpl.h
index d4cd05f..9d10b4b 100644
--- a/src/platform/Darwin/DnssdImpl.h
+++ b/src/platform/Darwin/DnssdImpl.h
@@ -233,6 +233,7 @@
     std::vector<Inet::IPAddress> addresses;
     std::string fullyQualifiedDomainName;
     bool isDNSLookUpRequested = false;
+    bool HasAddresses() const { return addresses.size() != 0; };
 };
 
 struct InterfaceKey
@@ -247,6 +248,11 @@
              (this->isSRPResult < other.isSRPResult));
     }
 
+    inline bool operator==(const InterfaceKey & other) const
+    {
+        return this->interfaceId == other.interfaceId && this->hostname == other.hostname && this->isSRPResult == other.isSRPResult;
+    }
+
     uint32_t interfaceId;
     std::string hostname;
     bool isSRPResult = false;
@@ -310,16 +316,6 @@
      *
      */
     void CancelSRPTimerIfRunning();
-
-private:
-    /**
-     * Try reporting the results we got on the provided interface index.
-     * Returns true if information was reported, false if not (e.g. if there
-     * were no IP addresses, etc).
-     */
-    bool TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex, const std::string & hostname, bool isSRPResult);
-
-    bool TryReportingResultsForInterfaceIndex(uint32_t interfaceIndex);
 };
 
 } // namespace Dnssd