diff --git a/src/BUILD.gn b/src/BUILD.gn index 2a24d53c8fce01..741b6e8c9856f2 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -47,6 +47,7 @@ if (chip_build_tests) { "${chip_root}/src/access/tests", "${chip_root}/src/crypto/tests", "${chip_root}/src/inet/tests", + "${chip_root}/src/lib/address_resolve/tests", "${chip_root}/src/lib/asn1/tests", "${chip_root}/src/lib/core/tests", "${chip_root}/src/messaging/tests", diff --git a/src/app/OperationalSessionSetup.cpp b/src/app/OperationalSessionSetup.cpp index 2997c877c4beee..f4e76ed700a370 100644 --- a/src/app/OperationalSessionSetup.cpp +++ b/src/app/OperationalSessionSetup.cpp @@ -306,6 +306,15 @@ void OperationalSessionSetup::OnSessionEstablishmentError(CHIP_ERROR error) VerifyOrReturn(mState != State::Uninitialized && mState != State::NeedsAddress, ChipLogError(Controller, "HandleCASEConnectionFailure was called while the device was not initialized")); + if (CHIP_ERROR_TIMEOUT == error) + { + if (CHIP_NO_ERROR == Resolver::Instance().TryNextResult(mAddressLookupHandle)) + { + MoveToState(State::ResolvingAddress); + return; + } + } + DequeueConnectionCallbacks(error); // Do not touch `this` instance anymore; it has been destroyed in DequeueConnectionCallbacks. } diff --git a/src/lib/address_resolve/AddressResolve.h b/src/lib/address_resolve/AddressResolve.h index fd8483beb5ee57..11c0959e3357df 100644 --- a/src/lib/address_resolve/AddressResolve.h +++ b/src/lib/address_resolve/AddressResolve.h @@ -204,6 +204,21 @@ class Resolver /// in progress) virtual CHIP_ERROR LookupNode(const NodeLookupRequest & request, Impl::NodeLookupHandle & handle) = 0; + /// Inform the Lookup handle that the previous node lookup was not sufficient + /// for the purpose of the caller (e.g establishing a session fails with the + /// result of the previous lookup), and that more data is needed. + /// + /// If this returns CHIP_NO_ERROR, the following is expected: + /// - The listener OnNodeAddressResolved will be called with the additional data. + /// - handle must NOT be destroyed while the lookup is in progress (it + /// is part of an internal 'lookup list') + /// - handle must NOT be reused (the lookup is done on a per-node basis + /// and maintains lookup data internally while the operation is still + /// in progress) + /// + /// If no additional data is available at the time of the request, it returns CHIP_ERROR_WELL_EMPTY. + virtual CHIP_ERROR TryNextResult(Impl::NodeLookupHandle & handle) = 0; + /// Stops an active lookup request. /// /// Caller controlls weather the `fail` callback of the handle is invoked or not by using diff --git a/src/lib/address_resolve/AddressResolve_DefaultImpl.cpp b/src/lib/address_resolve/AddressResolve_DefaultImpl.cpp index c687f0121b4641..8140d0055f1b2e 100644 --- a/src/lib/address_resolve/AddressResolve_DefaultImpl.cpp +++ b/src/lib/address_resolve/AddressResolve_DefaultImpl.cpp @@ -30,41 +30,27 @@ void NodeLookupHandle::ResetForLookup(System::Clock::Timestamp now, const NodeLo { mRequestStartTime = now; mRequest = request; - mBestResult = ResolveResult(); - mBestAddressScore = Dnssd::IPAddressSorter::IpScore::kInvalid; + mResults = NodeLookupResults(); } void NodeLookupHandle::LookupResult(const ResolveResult & result) { + auto score = Dnssd::IPAddressSorter::ScoreIpAddress(result.address.GetIPAddress(), result.address.GetInterface()); + [[maybe_unused]] bool success = mResults.UpdateResults(result, score); + #if CHIP_PROGRESS_LOGGING char addr_string[Transport::PeerAddress::kMaxToStringSize]; result.address.ToString(addr_string); -#endif - auto newScore = Dnssd::IPAddressSorter::ScoreIpAddress(result.address.GetIPAddress(), result.address.GetInterface()); - if (to_underlying(newScore) > to_underlying(mBestAddressScore)) + if (success) { - mBestResult = result; - mBestAddressScore = newScore; - - if (!mBestResult.address.GetIPAddress().IsIPv6LinkLocal()) - { - // Only use the DNS-SD resolution's InterfaceID for addresses that are IPv6 LLA. - // For all other addresses, we should rely on the device's routing table to route messages sent. - // Forcing messages down an InterfaceId might fail. For example, in bridged networks like Thread, - // mDNS advertisements are not usually received on the same interface the peer is reachable on. - mBestResult.address.SetInterface(Inet::InterfaceId::Null()); - ChipLogDetail(Discovery, "Lookup clearing interface for non LL address"); - } - -#if CHIP_PROGRESS_LOGGING - ChipLogProgress(Discovery, "%s: new best score: %u", addr_string, to_underlying(mBestAddressScore)); + ChipLogProgress(Discovery, "%s: new best score: %u", addr_string, to_underlying(score)); } else { - ChipLogProgress(Discovery, "%s: score has not improved: %u", addr_string, to_underlying(newScore)); -#endif + ChipLogProgress(Discovery, "%s: score has not improved: %u", addr_string, to_underlying(score)); } +#endif } System::Clock::Timeout NodeLookupHandle::NextEventTimeout(System::Clock::Timestamp now) @@ -98,9 +84,10 @@ NodeLookupAction NodeLookupHandle::NextAction(System::Clock::Timestamp now) } // Minimal time to search reached. If any IP available, ready to return it. - if (mBestAddressScore != Dnssd::IPAddressSorter::IpScore::kInvalid) + if (HasLookupResult()) { - return NodeLookupAction::Success(mBestResult); + auto result = TakeLookupResult(); + return NodeLookupAction::Success(result); } // Give up if the maximum search time has been reached @@ -112,6 +99,63 @@ NodeLookupAction NodeLookupHandle::NextAction(System::Clock::Timestamp now) return NodeLookupAction::KeepSearching(); } +bool NodeLookupResults::UpdateResults(const ResolveResult & result, const Dnssd::IPAddressSorter::IpScore newScore) +{ + uint8_t insertAtIndex = 0; + for (; insertAtIndex < kNodeLookupResultsLen; insertAtIndex++) + { + if (insertAtIndex >= count) + { + // This is a new entry. + break; + } + + auto & oldAddress = results[insertAtIndex].address; + auto oldScore = Dnssd::IPAddressSorter::ScoreIpAddress(oldAddress.GetIPAddress(), oldAddress.GetInterface()); + if (newScore > oldScore) + { + // This is a score update, it will replace a previous entry. + break; + } + } + + if (insertAtIndex == kNodeLookupResultsLen) + { + return false; + } + + // Move the following valid entries one level down. + for (auto i = count; i > insertAtIndex; i--) + { + if (i >= kNodeLookupResultsLen) + { + continue; + } + + results[i] = results[i - 1]; + } + + // If the number of valid entries is less than the size of the array there is an additional entry. + if (count < kNodeLookupResultsLen) + { + count++; + } + + auto & updatedResult = results[insertAtIndex]; + updatedResult = result; + if (!updatedResult.address.GetIPAddress().IsIPv6LinkLocal()) + { + // Only use the DNS-SD resolution's InterfaceID for addresses that are IPv6 LLA. + // For all other addresses, we should rely on the device's routing table to route messages sent. + // Forcing messages down an InterfaceId might fail. For example, in bridged networks like Thread, + // mDNS advertisements are not usually received on the same interface the peer is reachable on. + updatedResult.address.SetInterface(Inet::InterfaceId::Null()); + ChipLogDetail(Discovery, "Lookup clearing interface for non LL address"); + } + + return true; +} + CHIP_ERROR Resolver::LookupNode(const NodeLookupRequest & request, Impl::NodeLookupHandle & handle) { VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); @@ -123,6 +167,24 @@ CHIP_ERROR Resolver::LookupNode(const NodeLookupRequest & request, Impl::NodeLoo return CHIP_NO_ERROR; } +CHIP_ERROR Resolver::TryNextResult(Impl::NodeLookupHandle & handle) +{ + VerifyOrReturnError(mSystemLayer != nullptr, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(!mActiveLookups.Contains(&handle), CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(handle.HasLookupResult(), CHIP_ERROR_WELL_EMPTY); + + return mSystemLayer->ScheduleWork(&OnTryNextResult, static_cast(&handle)); +} + +void Resolver::OnTryNextResult(System::Layer * layer, void * context) +{ + auto handle = static_cast(context); + auto listener = handle->GetListener(); + auto peerId = handle->GetRequest().GetPeerId(); + auto result = handle->TakeLookupResult(); + listener->OnNodeAddressResolved(peerId, result); +} + CHIP_ERROR Resolver::CancelLookup(Impl::NodeLookupHandle & handle, FailureCallback cancel_method) { VerifyOrReturnError(handle.IsActive(), CHIP_ERROR_INVALID_ARGUMENT); diff --git a/src/lib/address_resolve/AddressResolve_DefaultImpl.h b/src/lib/address_resolve/AddressResolve_DefaultImpl.h index bb3114a8b1d085..a70e3466326716 100644 --- a/src/lib/address_resolve/AddressResolve_DefaultImpl.h +++ b/src/lib/address_resolve/AddressResolve_DefaultImpl.h @@ -26,6 +26,8 @@ namespace chip { namespace AddressResolve { namespace Impl { +constexpr uint8_t kNodeLookupResultsLen = CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS; + enum class NodeLookupResult { kKeepSearching, // keep the current search active @@ -33,6 +35,35 @@ enum class NodeLookupResult kLookupSuccess, // final status: success }; +struct NodeLookupResults +{ + ResolveResult results[kNodeLookupResultsLen] = {}; + uint8_t count = 0; // number of valid ResolveResult + uint8_t consumed = 0; // number of already read ResolveResult + + bool UpdateResults(const ResolveResult & result, Dnssd::IPAddressSorter::IpScore score); + + bool HasValidResult() const { return count > consumed; } + + ResolveResult ConsumeResult() + { + VerifyOrDie(HasValidResult()); + return results[consumed++]; + } + +#if CHIP_DETAIL_LOGGING + void LogDetail() const + { + for (unsigned i = 0; i < count; i++) + { + char addr_string[Transport::PeerAddress::kMaxToStringSize]; + results[i].address.ToString(addr_string); + ChipLogDetail(Discovery, "\t#%d: %s", i + 1, addr_string); + } + } +#endif // CHIP_DETAIL_LOGGING +}; + /// Action to take when some resolve data /// has been received by an active lookup class NodeLookupAction @@ -92,7 +123,7 @@ class NodeLookupAction /// An implementation of a node lookup handle /// /// Keeps track of time requests as well as the current -/// "best" IP address found. +/// "best" IPs addresses found. class NodeLookupHandle : public NodeLookupHandleBase { public: @@ -116,15 +147,20 @@ class NodeLookupHandle : public NodeLookupHandleBase /// any active searches) NodeLookupAction NextAction(System::Clock::Timestamp now); + /// Does the node have any valid lookup result? + bool HasLookupResult() const { return mResults.HasValidResult(); } + + /// Return the next valid lookup result. + ResolveResult TakeLookupResult() { return mResults.ConsumeResult(); } + /// Return when the next timer (min or max lookup time) is required to /// be triggered for this lookup handle System::Clock::Timeout NextEventTimeout(System::Clock::Timestamp now); private: - System::Clock::Timestamp mRequestStartTime; + NodeLookupResults mResults; NodeLookupRequest mRequest; // active request to process - AddressResolve::ResolveResult mBestResult; - Dnssd::IPAddressSorter::IpScore mBestAddressScore; + System::Clock::Timestamp mRequestStartTime; }; class Resolver : public ::chip::AddressResolve::Resolver, public Dnssd::OperationalResolveDelegate @@ -136,6 +172,7 @@ class Resolver : public ::chip::AddressResolve::Resolver, public Dnssd::Operatio CHIP_ERROR Init(System::Layer * systemLayer) override; CHIP_ERROR LookupNode(const NodeLookupRequest & request, Impl::NodeLookupHandle & handle) override; + CHIP_ERROR TryNextResult(Impl::NodeLookupHandle & handle) override; CHIP_ERROR CancelLookup(Impl::NodeLookupHandle & handle, FailureCallback cancel_method) override; void Shutdown() override; @@ -146,6 +183,7 @@ class Resolver : public ::chip::AddressResolve::Resolver, public Dnssd::Operatio private: static void OnResolveTimer(System::Layer * layer, void * context) { static_cast(context)->HandleTimer(); } + static void OnTryNextResult(System::Layer * layer, void * context); /// Timer on lookup node events: min and max search times. void HandleTimer(); diff --git a/src/lib/address_resolve/BUILD.gn b/src/lib/address_resolve/BUILD.gn index d952ff83313991..a4cdc3af668163 100644 --- a/src/lib/address_resolve/BUILD.gn +++ b/src/lib/address_resolve/BUILD.gn @@ -15,16 +15,7 @@ import("//build_overrides/build.gni") import("//build_overrides/chip.gni") -declare_args() { - # Define as "default" to include the built in resolution strategy in - # CHIP (i.e. sources within this directory). - # - # Define as "custom" to only have relevant type definitions included - # in which case the application is expected to provide a - # CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER - # include to use - chip_address_resolve_strategy = "default" -} +import("address_resolve.gni") config("default_address_resolve_config") { defines = [ "CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER=" ] diff --git a/src/lib/address_resolve/address_resolve.gni b/src/lib/address_resolve/address_resolve.gni new file mode 100644 index 00000000000000..71f015f9d0993b --- /dev/null +++ b/src/lib/address_resolve/address_resolve.gni @@ -0,0 +1,24 @@ +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +declare_args() { + # Define as "default" to include the built in resolution strategy in + # CHIP (i.e. sources within this directory). + # + # Define as "custom" to only have relevant type definitions included + # in which case the application is expected to provide a + # CHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER + # include to use + chip_address_resolve_strategy = "default" +} diff --git a/src/lib/address_resolve/tests/BUILD.gn b/src/lib/address_resolve/tests/BUILD.gn new file mode 100644 index 00000000000000..cd4327d9b4797a --- /dev/null +++ b/src/lib/address_resolve/tests/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2022 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") +import("//build_overrides/nlunit_test.gni") + +import("${chip_root}/src/lib/address_resolve/address_resolve.gni") + +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "libAddressResolveTests" + + if (chip_address_resolve_strategy == "default") { + test_sources = [ "TestAddressResolve_DefaultImpl.cpp" ] + } + + public_deps = [ + "${chip_root}/src/lib/address_resolve", + "${chip_root}/src/lib/support:testing", + "${chip_root}/src/protocols", + "${nlunit_test_root}:nlunit-test", + ] +} diff --git a/src/lib/address_resolve/tests/TestAddressResolve_DefaultImpl.cpp b/src/lib/address_resolve/tests/TestAddressResolve_DefaultImpl.cpp new file mode 100644 index 00000000000000..05d2491475ecef --- /dev/null +++ b/src/lib/address_resolve/tests/TestAddressResolve_DefaultImpl.cpp @@ -0,0 +1,197 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include + +#include + +using namespace chip; +using namespace chip::AddressResolve; + +namespace { + +constexpr uint8_t kNumberOfAvailableSlots = CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS; + +Transport::PeerAddress GetAddressWithLowScore(uint16_t port = CHIP_PORT, Inet::InterfaceId interfaceId = Inet::InterfaceId::Null()) +{ + // Embedded IPv4 + Inet::IPAddress ipAddress; + Inet::IPAddress::FromString("0:0:0:0:0:0:111.22.33.44", ipAddress); + + return Transport::PeerAddress::UDP(ipAddress, port, interfaceId); +} + +Transport::PeerAddress GetAddressWithMediumScore(uint16_t port = CHIP_PORT, + Inet::InterfaceId interfaceId = Inet::InterfaceId::Null()) +{ + // Unique Local + Inet::IPAddress ipAddress; + Inet::IPAddress::FromString("fdff:aabb:ccdd:1::4", ipAddress); + + return Transport::PeerAddress::UDP(ipAddress, port, interfaceId); +} + +Transport::PeerAddress GetAddressWithHighScore(uint16_t port = CHIP_PORT, Inet::InterfaceId interfaceId = Inet::InterfaceId::Null()) +{ + // Global Unicast + Inet::IPAddress ipAddress; + Inet::IPAddress::FromString("2001::aabb:ccdd:2233:4455", ipAddress); + + return Transport::PeerAddress::UDP(ipAddress, port, interfaceId); +} + +void TestLookupResult(nlTestSuite * inSuite, void * inContext) +{ + ResolveResult lowResult; + lowResult.address = GetAddressWithLowScore(); + + ResolveResult mediumResult; + mediumResult.address = GetAddressWithMediumScore(); + + ResolveResult highResult; + highResult.address = GetAddressWithHighScore(); + + ResolveResult outResult; + + AddressResolve::NodeLookupHandle handle; + + auto now = System::SystemClock().GetMonotonicTimestamp(); + auto request = NodeLookupRequest(chip::PeerId(1, 2)); + handle.ResetForLookup(now, request); + + // Check that no result exists. + NL_TEST_ASSERT(inSuite, !handle.HasLookupResult()); + + // Fill a single slot. + handle.LookupResult(lowResult); + + // Check that a result exists. + NL_TEST_ASSERT(inSuite, handle.HasLookupResult()); + + // Check that the result match what has been inserted. + outResult = handle.TakeLookupResult(); + NL_TEST_ASSERT(inSuite, lowResult.address == outResult.address); + + // Check that the result has been consumed properly + NL_TEST_ASSERT(inSuite, !handle.HasLookupResult()); + + handle.ResetForLookup(now, request); + + // Fill all the possible slots. + for (auto i = 0; i < kNumberOfAvailableSlots; i++) + { + handle.LookupResult(lowResult); + } + + // Read back all results and validate that they match the input. + for (auto i = 0; i < kNumberOfAvailableSlots; i++) + { + NL_TEST_ASSERT(inSuite, handle.HasLookupResult()); + outResult = handle.TakeLookupResult(); + NL_TEST_ASSERT(inSuite, lowResult.address == outResult.address); + } + + // Check that the results has been consumed properly. + NL_TEST_ASSERT(inSuite, !handle.HasLookupResult()); + + handle.ResetForLookup(now, request); + + // Fill all the possible slots by giving it 2 times more results than the available slots. + for (auto i = 0; i < kNumberOfAvailableSlots * 2; i++) + { + handle.LookupResult(lowResult); + } + + // Read back all results and validate that they match the input. + for (auto i = 0; i < kNumberOfAvailableSlots; i++) + { + NL_TEST_ASSERT(inSuite, handle.HasLookupResult()); + outResult = handle.TakeLookupResult(); + NL_TEST_ASSERT(inSuite, lowResult.address == outResult.address); + } + + // Check that the results has been consumed properly. + NL_TEST_ASSERT(inSuite, !handle.HasLookupResult()); + + handle.ResetForLookup(now, request); + + // Fill all the possible slots. + for (auto i = 0; i < kNumberOfAvailableSlots; i++) + { + handle.LookupResult(lowResult); + } + + // Add a result with a medium score and ensure it sits at the top. + handle.LookupResult(mediumResult); + NL_TEST_ASSERT(inSuite, handle.HasLookupResult()); + outResult = handle.TakeLookupResult(); + NL_TEST_ASSERT(inSuite, mediumResult.address == outResult.address); + + handle.ResetForLookup(now, request); + + // Fill all the possible slots. + for (auto i = 0; i < kNumberOfAvailableSlots; i++) + { + handle.LookupResult(lowResult); + } + + // Add a result with a medium score and a result with a high score and ensure the result with the high score comes first. + handle.LookupResult(mediumResult); + handle.LookupResult(highResult); + NL_TEST_ASSERT(inSuite, handle.HasLookupResult()); + outResult = handle.TakeLookupResult(); + NL_TEST_ASSERT(inSuite, highResult.address == outResult.address); + + if (kNumberOfAvailableSlots > 1) + { + // Ensure the second result is the medium result. + NL_TEST_ASSERT(inSuite, handle.HasLookupResult()); + outResult = handle.TakeLookupResult(); + NL_TEST_ASSERT(inSuite, mediumResult.address == outResult.address); + } + + if (kNumberOfAvailableSlots > 2) + { + // Ensure that all the other results are low results. + for (auto i = 2; i < kNumberOfAvailableSlots; i++) + { + NL_TEST_ASSERT(inSuite, handle.HasLookupResult()); + outResult = handle.TakeLookupResult(); + NL_TEST_ASSERT(inSuite, lowResult.address == outResult.address); + } + } + + // Check that the results has been consumed properly. + NL_TEST_ASSERT(inSuite, !handle.HasLookupResult()); +} + +const nlTest sTests[] = { + NL_TEST_DEF("TestLookupResult", TestLookupResult), // + NL_TEST_SENTINEL() // +}; + +} // namespace + +int TestAddressResolve_DefaultImpl() +{ + nlTestSuite theSuite = { "AddressResolve_DefaultImpl", sTests, nullptr, nullptr }; + nlTestRunner(&theSuite, nullptr); + return nlTestRunnerStats(&theSuite); +} + +CHIP_REGISTER_TEST_SUITE(TestAddressResolve_DefaultImpl) diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index aaa28d079441ab..3dec51ea121746 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1270,6 +1270,17 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_MINMDNS_MAX_PARALLEL_RESOLVES 2 #endif // CHIP_CONFIG_MINMDNS_MAX_PARALLEL_RESOLVES +/** + * def CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS + * + * @brief Determines the maximum number of node resolve results (PeerAddresses) to keep + * for establishing an operational session. + * + */ +#ifndef CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS +#define CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS 1 +#endif // CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS + /* * @def CHIP_CONFIG_NETWORK_COMMISSIONING_DEBUG_TEXT_BUFFER_SIZE * diff --git a/src/platform/Darwin/SystemPlatformConfig.h b/src/platform/Darwin/SystemPlatformConfig.h index 19df50055af2ac..76995250738a69 100644 --- a/src/platform/Darwin/SystemPlatformConfig.h +++ b/src/platform/Darwin/SystemPlatformConfig.h @@ -44,3 +44,4 @@ struct ChipDeviceEvent; #define CHIP_SYSTEM_CONFIG_PLATFORM_LOG_INCLUDE // ========== Platform-specific Configuration Overrides ========= +#define CHIP_CONFIG_MDNS_RESOLVE_LOOKUP_RESULTS 5