diff --git a/api/envoy/config/cluster/v3/cluster.proto b/api/envoy/config/cluster/v3/cluster.proto index 34a8608e9e0ea..33caa28b598fc 100644 --- a/api/envoy/config/cluster/v3/cluster.proto +++ b/api/envoy/config/cluster/v3/cluster.proto @@ -129,6 +129,8 @@ message Cluster { // If V4_PREFERRED is specified, the DNS resolver will first perform a lookup for addresses in the // IPv4 family and fallback to a lookup for addresses in the IPv6 family. i.e., the callback // target will only get v6 addresses if there were NO v4 addresses to return. + // If ALL is specified, the DNS resolver will perform a lookup for both IPv4 and IPv6 families, + // and return all resolved addresses. // For cluster types other than // :ref:`STRICT_DNS` and // :ref:`LOGICAL_DNS`, @@ -140,6 +142,7 @@ message Cluster { V4_ONLY = 1; V6_ONLY = 2; V4_PREFERRED = 3; + ALL = 4; } enum ClusterProtocolSelection { diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index 91c8b0e351bfc..22912424a7128 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -43,6 +43,7 @@ New Features * bootstrap: added :ref:`typed_dns_resolver_config ` in the bootstrap to support DNS resolver as an extension. * cluster: added :ref:`typed_dns_resolver_config ` in the cluster to support DNS resolver as an extension. * config: added :ref:`environment_variable ` to the :ref:`DataSource `. +* dns: added :ref:`ALL ` option to return both IPv4 and IPv6 addresses. * dns_cache: added :ref:`typed_dns_resolver_config ` in the dns_cache to support DNS resolver as an extension. * dns_filter: added :ref:`typed_dns_resolver_config ` in the dns_filter to support DNS resolver as an extension. * dns_resolver: added :ref:`CaresDnsResolverConfig` to support c-ares DNS resolver as an extension. diff --git a/envoy/network/dns.h b/envoy/network/dns.h index 38dd39bf45760..072829c027657 100644 --- a/envoy/network/dns.h +++ b/envoy/network/dns.h @@ -46,7 +46,7 @@ struct DnsResponse { const std::chrono::seconds ttl_; }; -enum class DnsLookupFamily { V4Only, V6Only, Auto, V4Preferred }; +enum class DnsLookupFamily { V4Only, V6Only, Auto, V4Preferred, All }; /** * An asynchronous DNS resolver. diff --git a/source/common/upstream/upstream_impl.cc b/source/common/upstream/upstream_impl.cc index 353b1d572f128..5d1ae1280dd47 100644 --- a/source/common/upstream/upstream_impl.cc +++ b/source/common/upstream/upstream_impl.cc @@ -1777,6 +1777,8 @@ getDnsLookupFamilyFromEnum(envoy::config::cluster::v3::Cluster::DnsLookupFamily return Network::DnsLookupFamily::Auto; case envoy::config::cluster::v3::Cluster::V4_PREFERRED: return Network::DnsLookupFamily::V4Preferred; + case envoy::config::cluster::v3::Cluster::ALL: + return Network::DnsLookupFamily::All; default: NOT_REACHED_GCOVR_EXCL_LINE; } diff --git a/source/extensions/network/dns_resolver/apple/apple_dns_impl.cc b/source/extensions/network/dns_resolver/apple/apple_dns_impl.cc index bc7677679fb34..69448d6a0a70f 100644 --- a/source/extensions/network/dns_resolver/apple/apple_dns_impl.cc +++ b/source/extensions/network/dns_resolver/apple/apple_dns_impl.cc @@ -141,7 +141,8 @@ AppleDnsResolverImpl::PendingResolution::PendingResolution(AppleDnsResolverImpl& const std::string& dns_name, DnsLookupFamily dns_lookup_family) : parent_(parent), callback_(callback), dispatcher_(dispatcher), dns_name_(dns_name), - pending_cb_({ResolutionStatus::Success, {}, {}}), dns_lookup_family_(dns_lookup_family) {} + pending_response_({ResolutionStatus::Success, {}, {}, {}}), + dns_lookup_family_(dns_lookup_family) {} AppleDnsResolverImpl::PendingResolution::~PendingResolution() { ENVOY_LOG(debug, "Destroying PendingResolution for {}", dns_name_); @@ -183,7 +184,7 @@ void AppleDnsResolverImpl::PendingResolution::onEventCallback(uint32_t events) { // Similar to receiving an error in onDNSServiceGetAddrInfoReply, an error while processing fd // events indicates that the sd_ref state is broken. // Therefore, finish resolving with an error. - pending_cb_.status_ = ResolutionStatus::Failure; + pending_response_.status_ = ResolutionStatus::Failure; finishResolve(); } } @@ -191,29 +192,39 @@ void AppleDnsResolverImpl::PendingResolution::onEventCallback(uint32_t events) { std::list& AppleDnsResolverImpl::PendingResolution::finalAddressList() { switch (dns_lookup_family_) { case DnsLookupFamily::V4Only: - return pending_cb_.v4_responses_; + return pending_response_.v4_responses_; case DnsLookupFamily::V6Only: - return pending_cb_.v6_responses_; + return pending_response_.v6_responses_; case DnsLookupFamily::Auto: // Per API docs only give v4 if v6 is not available. - if (pending_cb_.v6_responses_.empty()) { - return pending_cb_.v4_responses_; + if (pending_response_.v6_responses_.empty()) { + return pending_response_.v4_responses_; } - return pending_cb_.v6_responses_; + return pending_response_.v6_responses_; case DnsLookupFamily::V4Preferred: // Per API docs only give v6 if v4 is not available. - if (pending_cb_.v4_responses_.empty()) { - return pending_cb_.v6_responses_; + if (pending_response_.v4_responses_.empty()) { + return pending_response_.v6_responses_; } - return pending_cb_.v4_responses_; + return pending_response_.v4_responses_; + case DnsLookupFamily::All: + ASSERT(pending_response_.all_responses_.empty()); + pending_response_.all_responses_.insert(pending_response_.all_responses_.end(), + pending_response_.v4_responses_.begin(), + pending_response_.v4_responses_.end()); + pending_response_.all_responses_.insert(pending_response_.all_responses_.end(), + pending_response_.v6_responses_.begin(), + pending_response_.v6_responses_.end()); + return pending_response_.all_responses_; } NOT_REACHED_GCOVR_EXCL_LINE; } void AppleDnsResolverImpl::PendingResolution::finishResolve() { ENVOY_LOG_EVENT(debug, "apple_dns_resolution_complete", - "dns resolution for {} completed with status {}", dns_name_, pending_cb_.status_); - callback_(pending_cb_.status_, std::move(finalAddressList())); + "dns resolution for {} completed with status {}", dns_name_, + pending_response_.status_); + callback_(pending_response_.status_, std::move(finalAddressList())); if (owned_) { ENVOY_LOG(debug, "Resolution for {} completed (async)", dns_name_); @@ -235,6 +246,7 @@ DNSServiceErrorType AppleDnsResolverImpl::PendingResolution::dnsServiceGetAddrIn break; case DnsLookupFamily::Auto: case DnsLookupFamily::V4Preferred: + case DnsLookupFamily::All: /* We want to make sure we don't get any address that is not routable. Passing 0 * to apple's `DNSServiceGetAddrInfo` will make a best attempt to filter out IPv6 * or IPv4 addresses depending on what's routable, per Apple's documentation: @@ -291,9 +303,9 @@ void AppleDnsResolverImpl::PendingResolution::onDNSServiceGetAddrInfoReply( if (error_code != kDNSServiceErr_NoError) { parent_.chargeGetAddrInfoErrorStats(error_code); - pending_cb_.status_ = ResolutionStatus::Failure; - pending_cb_.v4_responses_.clear(); - pending_cb_.v6_responses_.clear(); + pending_response_.status_ = ResolutionStatus::Failure; + pending_response_.v4_responses_.clear(); + pending_response_.v6_responses_.clear(); finishResolve(); // Note: Nothing can follow this call to flushPendingQueries due to deletion of this @@ -310,10 +322,10 @@ void AppleDnsResolverImpl::PendingResolution::onDNSServiceGetAddrInfoReply( ENVOY_LOG(debug, "Address to add address={}, ttl={}", dns_response.address_->ip()->addressAsString(), ttl); if (dns_response.address_->ip()->ipv4()) { - pending_cb_.v4_responses_.push_back(dns_response); + pending_response_.v4_responses_.push_back(dns_response); } else { ASSERT(dns_response.address_->ip()->ipv6()); - pending_cb_.v6_responses_.push_back(dns_response); + pending_response_.v6_responses_.push_back(dns_response); } } diff --git a/source/extensions/network/dns_resolver/apple/apple_dns_impl.h b/source/extensions/network/dns_resolver/apple/apple_dns_impl.h index 214a60bc01b40..421d14fe29e73 100644 --- a/source/extensions/network/dns_resolver/apple/apple_dns_impl.h +++ b/source/extensions/network/dns_resolver/apple/apple_dns_impl.h @@ -109,10 +109,11 @@ class AppleDnsResolverImpl : public DnsResolver, protected Logger::Loggable v4_responses_; std::list v6_responses_; + std::list all_responses_; }; AppleDnsResolverImpl& parent_; @@ -128,7 +129,7 @@ class AppleDnsResolverImpl : public DnsResolver, protected Logger::Loggable address_list; - ResolutionStatus resolution_status; if (status == ARES_SUCCESS) { - resolution_status = ResolutionStatus::Success; + pending_response_.status_ = ResolutionStatus::Success; + if (addrinfo != nullptr && addrinfo->nodes != nullptr) { if (addrinfo->nodes->ai_family == AF_INET) { for (const ares_addrinfo_node* ai = addrinfo->nodes; ai != nullptr; ai = ai->ai_next) { @@ -146,7 +145,7 @@ void DnsResolverImpl::PendingResolution::onAresGetAddrInfoCallback(int status, i address.sin_port = 0; address.sin_addr = reinterpret_cast(ai->ai_addr)->sin_addr; - address_list.emplace_back( + pending_response_.address_list_.emplace_back( DnsResponse(std::make_shared(&address), std::chrono::seconds(ai->ai_ttl))); } @@ -157,21 +156,19 @@ void DnsResolverImpl::PendingResolution::onAresGetAddrInfoCallback(int status, i address.sin6_family = AF_INET6; address.sin6_port = 0; address.sin6_addr = reinterpret_cast(ai->ai_addr)->sin6_addr; - address_list.emplace_back( + pending_response_.address_list_.emplace_back( DnsResponse(std::make_shared(address), std::chrono::seconds(ai->ai_ttl))); } } } - if (!address_list.empty()) { + if (!pending_response_.address_list_.empty() && dns_lookup_family_ != DnsLookupFamily::All) { completed_ = true; } ASSERT(addrinfo != nullptr); ares_freeaddrinfo(addrinfo); - } else { - resolution_status = ResolutionStatus::Failure; } if (timeouts > 0) { @@ -179,44 +176,21 @@ void DnsResolverImpl::PendingResolution::onAresGetAddrInfoCallback(int status, i } if (completed_) { - if (!cancelled_) { - // Use a raw try here because it is used in both main thread and filter. - // Can not convert to use status code as there may be unexpected exceptions in server fuzz - // tests, which must be handled. Potential exception may come from getAddressWithPort() or - // portFromTcpUrl(). - // TODO(chaoqin-li1123): remove try catch pattern here once we figure how to handle unexpected - // exception in fuzz tests. - ENVOY_LOG_EVENT(debug, "cares_dns_resolution_complete", - "dns resolution for {} completed with status {}", dns_name_, - resolution_status); - - TRY_NEEDS_AUDIT { callback_(resolution_status, std::move(address_list)); } - catch (const EnvoyException& e) { - ENVOY_LOG(critical, "EnvoyException in c-ares callback: {}", e.what()); - dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); }); - } - catch (const std::exception& e) { - ENVOY_LOG(critical, "std::exception in c-ares callback: {}", e.what()); - dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); }); - } - catch (...) { - ENVOY_LOG(critical, "Unknown exception in c-ares callback"); - dispatcher_.post([] { throw EnvoyException("unknown"); }); - } - } - if (owned_) { - delete this; - return; - } + finishResolve(); + // Nothing can follow a call to finishResolve due to the deletion of this object upon + // finishResolve(). + return; } - if (!completed_ && fallback_if_failed_) { - fallback_if_failed_ = false; + if (dual_resolution_) { + dual_resolution_ = false; + // Perform a second lookup for DnsLookupFamily::Auto and DnsLookupFamily::V4Preferred, given + // that the first lookup failed to return any addresses. Note that DnsLookupFamily::All issues + // both lookups concurrently so there is no need to fire a second lookup here. if (dns_lookup_family_ == DnsLookupFamily::Auto) { getAddrInfo(AF_INET); - } else { - ASSERT(dns_lookup_family_ == DnsLookupFamily::V4Preferred); + } else if (dns_lookup_family_ == DnsLookupFamily::V4Preferred) { getAddrInfo(AF_INET6); } @@ -226,6 +200,40 @@ void DnsResolverImpl::PendingResolution::onAresGetAddrInfoCallback(int status, i } } +void DnsResolverImpl::PendingResolution::finishResolve() { + if (!cancelled_) { + // Use a raw try here because it is used in both main thread and filter. + // Can not convert to use status code as there may be unexpected exceptions in server fuzz + // tests, which must be handled. Potential exception may come from getAddressWithPort() or + // portFromTcpUrl(). + // TODO(chaoqin-li1123): remove try catch pattern here once we figure how to handle unexpected + // exception in fuzz tests. + ENVOY_LOG_EVENT(debug, "cares_dns_resolution_complete", + "dns resolution for {} completed with status {}", dns_name_, + pending_response_.status_); + + TRY_NEEDS_AUDIT { + callback_(pending_response_.status_, std::move(pending_response_.address_list_)); + } + catch (const EnvoyException& e) { + ENVOY_LOG(critical, "EnvoyException in c-ares callback: {}", e.what()); + dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); }); + } + catch (const std::exception& e) { + ENVOY_LOG(critical, "std::exception in c-ares callback: {}", e.what()); + dispatcher_.post([s = std::string(e.what())] { throw EnvoyException(s); }); + } + catch (...) { + ENVOY_LOG(critical, "Unknown exception in c-ares callback"); + dispatcher_.post([] { throw EnvoyException("unknown"); }); + } + } + if (owned_) { + delete this; + return; + } +} + void DnsResolverImpl::updateAresTimer() { // Update the timeout for events. timeval timeout; @@ -286,15 +294,28 @@ ActiveDnsQuery* DnsResolverImpl::resolve(const std::string& dns_name, auto pending_resolution = std::make_unique( *this, callback, dispatcher_, channel_, dns_name, dns_lookup_family); if (dns_lookup_family == DnsLookupFamily::Auto || - dns_lookup_family == DnsLookupFamily::V4Preferred) { - pending_resolution->fallback_if_failed_ = true; + dns_lookup_family == DnsLookupFamily::V4Preferred || + dns_lookup_family == DnsLookupFamily::All) { + pending_resolution->dual_resolution_ = true; } - if (dns_lookup_family == DnsLookupFamily::V4Only || - dns_lookup_family == DnsLookupFamily::V4Preferred) { + switch (dns_lookup_family) { + case DnsLookupFamily::V4Only: + case DnsLookupFamily::V4Preferred: + pending_resolution->getAddrInfo(AF_INET); + break; + case DnsLookupFamily::V6Only: + case DnsLookupFamily::Auto: + pending_resolution->getAddrInfo(AF_INET6); + break; + // NOTE: DnsLookupFamily::All performs both lookups concurrently as addresses from both families + // are being requested. + case DnsLookupFamily::All: pending_resolution->getAddrInfo(AF_INET); - } else { pending_resolution->getAddrInfo(AF_INET6); + break; + default: + NOT_REACHED_GCOVR_EXCL_LINE; } if (pending_resolution->completed_) { diff --git a/source/extensions/network/dns_resolver/cares/dns_impl.h b/source/extensions/network/dns_resolver/cares/dns_impl.h index 19532bbf18bbf..cfb637b5b172c 100644 --- a/source/extensions/network/dns_resolver/cares/dns_impl.h +++ b/source/extensions/network/dns_resolver/cares/dns_impl.h @@ -66,6 +66,15 @@ class DnsResolverImpl : public DnsResolver, protected Logger::Loggable address_list_; + }; + DnsResolverImpl& parent_; // Caller supplied callback to invoke on query completion or error. const ResolveCb callback_; @@ -78,12 +87,18 @@ class DnsResolverImpl : public DnsResolver, protected Logger::Loggableip()->ipv6()); break; - // In CI these modes could return either V4 or V6 with the non-mocked API calls. But - // regardless of the family all returned addresses need to be one _or_ the other. + // In CI these modes could return either IPv4 or IPv6 with the non-mocked API calls. + // But regardless of the family all returned addresses need to be one _or_ the other. case DnsLookupFamily::V4Preferred: case DnsLookupFamily::Auto: // Set the expectation for subsequent responses based on the first one. @@ -116,6 +116,14 @@ class AppleDnsImplTest : public testing::Test { EXPECT_NE(nullptr, result.address_->ip()->ipv6()); } break; + // All could be either IPv4 or IPv6. + case DnsLookupFamily::All: + if (result.address_->ip()->ipv4()) { + EXPECT_NE(nullptr, result.address_->ip()->ipv4()); + } else { + EXPECT_NE(nullptr, result.address_->ip()->ipv6()); + } + break; default: NOT_REACHED_GCOVR_EXCL_LINE; } @@ -276,6 +284,10 @@ TEST_F(AppleDnsImplTest, DnsIpAddressVersionV6Only) { EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::V6Only, DnsResolver::ResolutionStatus::Success, true)); dispatcher_->run(Event::Dispatcher::RunType::Block); + + EXPECT_NE(nullptr, resolveWithExpectations("google.com", DnsLookupFamily::All, + DnsResolver::ResolutionStatus::Success, true)); + dispatcher_->run(Event::Dispatcher::RunType::Block); } // dns_sd is very opaque and does not explicitly call out the state that is kept across queries. @@ -317,6 +329,10 @@ TEST_F(AppleDnsImplTest, DnsIpAddressVersionInvalid) { EXPECT_NE(nullptr, resolveWithExpectations("invalidDnsName", DnsLookupFamily::V6Only, DnsResolver::ResolutionStatus::Failure, false)); dispatcher_->run(Event::Dispatcher::RunType::Block); + + EXPECT_NE(nullptr, resolveWithExpectations("invalidDnsName", DnsLookupFamily::All, + DnsResolver::ResolutionStatus::Failure, false)); + dispatcher_->run(Event::Dispatcher::RunType::Block); } TEST_F(AppleDnsImplTest, CallbackException) { @@ -441,7 +457,8 @@ class AppleDnsImplFakeApiTest : public testing::Test { enum AddressType { V4, V6, Both }; - void fallbackWith(DnsLookupFamily dns_lookup_family, AddressType address_type) { + void fallbackWith(DnsLookupFamily dns_lookup_family, AddressType address_type, + uint32_t expected_address_size = 1) { const std::string hostname = "foo.com"; sockaddr_in addr4; addr4.sin_family = AF_INET; @@ -468,10 +485,10 @@ class AppleDnsImplFakeApiTest : public testing::Test { auto query = resolver_->resolve( hostname, dns_lookup_family, - [&dns_callback_executed, dns_lookup_family, address_type]( + [&dns_callback_executed, dns_lookup_family, address_type, expected_address_size]( DnsResolver::ResolutionStatus status, std::list&& response) -> void { EXPECT_EQ(DnsResolver::ResolutionStatus::Success, status); - EXPECT_EQ(1, response.size()); + EXPECT_EQ(expected_address_size, response.size()); if (dns_lookup_family == DnsLookupFamily::Auto) { if (address_type == AddressType::V4) { @@ -488,6 +505,23 @@ class AppleDnsImplFakeApiTest : public testing::Test { EXPECT_NE(nullptr, response.front().address_->ip()->ipv4()); } } + + if (dns_lookup_family == DnsLookupFamily::All) { + switch (address_type) { + case AddressType::V4: + EXPECT_NE(nullptr, response.front().address_->ip()->ipv4()); + break; + case AddressType::V6: + EXPECT_NE(nullptr, response.front().address_->ip()->ipv6()); + break; + case AddressType::Both: + EXPECT_NE(nullptr, response.front().address_->ip()->ipv4()); + EXPECT_NE(nullptr, response.back().address_->ip()->ipv6()); + break; + default: + NOT_REACHED_GCOVR_EXCL_LINE; + } + } dns_callback_executed.Notify(); }); ASSERT_NE(nullptr, query); @@ -746,6 +780,7 @@ TEST_F(AppleDnsImplFakeApiTest, MultipleAddresses) { dns_callback_executed.WaitForNotification(); } +// TODO: write a TEST_P harness to eliminate duplication. TEST_F(AppleDnsImplFakeApiTest, AutoOnlyV6IfBothV6andV4) { fallbackWith(DnsLookupFamily::Auto, AddressType::Both); } @@ -770,6 +805,18 @@ TEST_F(AppleDnsImplFakeApiTest, V4PreferredV4IfOnlyV4) { fallbackWith(DnsLookupFamily::V4Preferred, AddressType::V4); } +TEST_F(AppleDnsImplFakeApiTest, AllIfBothV6andV4) { + fallbackWith(DnsLookupFamily::All, AddressType::Both, 2 /* expected_address_size*/); +} + +TEST_F(AppleDnsImplFakeApiTest, AllV6IfOnlyV6) { + fallbackWith(DnsLookupFamily::All, AddressType::V6); +} + +TEST_F(AppleDnsImplFakeApiTest, AllV4IfOnlyV4) { + fallbackWith(DnsLookupFamily::All, AddressType::V4); +} + TEST_F(AppleDnsImplFakeApiTest, MultipleAddressesSecondOneFails) { const std::string hostname = "foo.com"; sockaddr_in addr4; diff --git a/test/extensions/network/dns_resolver/cares/dns_impl_test.cc b/test/extensions/network/dns_resolver/cares/dns_impl_test.cc index 2387b80c3795e..d60dc911e65f6 100644 --- a/test/extensions/network/dns_resolver/cares/dns_impl_test.cc +++ b/test/extensions/network/dns_resolver/cares/dns_impl_test.cc @@ -45,6 +45,7 @@ using testing::IsSupersetOf; using testing::NiceMock; using testing::Not; using testing::Return; +using testing::UnorderedElementsAreArray; namespace Envoy { namespace Network { @@ -656,7 +657,7 @@ class DnsImplTest : public testing::TestWithParam { if (address == "localhost" && lookup_family == DnsLookupFamily::V4Only) { EXPECT_THAT(address_as_string_list, IsSupersetOf(expected_results)); } else { - EXPECT_EQ(expected_results, address_as_string_list); + EXPECT_THAT(address_as_string_list, UnorderedElementsAreArray(expected_results)); } for (const auto& expected_absent_result : expected_absent_results) { @@ -1004,6 +1005,33 @@ TEST_P(DnsImplTest, V4PreferredV4IfOnlyV4) { dispatcher_->run(Event::Dispatcher::RunType::Block); } +TEST_P(DnsImplTest, AllIfBothV6andV4) { + server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); + server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); + + EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, + DnsResolver::ResolutionStatus::Success, + {{"201.134.56.7"}, {"1::2"}}, {}, absl::nullopt)); + dispatcher_->run(Event::Dispatcher::RunType::Block); +} + +TEST_P(DnsImplTest, AllV6IfOnlyV6) { + server_->addHosts("some.good.domain", {"1::2"}, RecordType::AAAA); + + EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, + DnsResolver::ResolutionStatus::Success, {{"1::2"}}, {}, + absl::nullopt)); + dispatcher_->run(Event::Dispatcher::RunType::Block); +} + +TEST_P(DnsImplTest, AllV4IfOnlyV4) { + server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); + EXPECT_NE(nullptr, resolveWithExpectations("some.good.domain", DnsLookupFamily::All, + DnsResolver::ResolutionStatus::Success, + {{"201.134.56.7"}}, {}, absl::nullopt)); + dispatcher_->run(Event::Dispatcher::RunType::Block); +} + // Validate working of cancellation provided by ActiveDnsQuery return. TEST_P(DnsImplTest, Cancel) { server_->addHosts("some.good.domain", {"201.134.56.7"}, RecordType::A); diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index bfc60ecaec0dc..8b126d806e499 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -637,6 +637,7 @@ evbuffer evbuffers evconnlistener evented +eventfd evwatch exe execlp