From 964d679edc32b0f7316cacdb0652477d607f6de5 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Tue, 21 Aug 2018 08:00:49 -0700 Subject: [PATCH] Resolve ip literals and Windows localhost manually when using c-ares --- CMakeLists.txt | 38 ++++++- Makefile | 58 ++++++++--- build.yaml | 16 ++- .../filters/client_channel/parse_address.cc | 9 ++ .../filters/client_channel/parse_address.h | 3 + .../resolver/dns/c_ares/grpc_ares_wrapper.cc | 99 +++++++++++++++---- .../resolver/dns/c_ares/grpc_ares_wrapper.h | 12 ++- .../dns/c_ares/grpc_ares_wrapper_posix.cc | 5 + .../dns/c_ares/grpc_ares_wrapper_windows.cc | 70 +++++++++++++ test/core/iomgr/BUILD | 20 +++- test/core/iomgr/resolve_address_test.cc | 40 +++++++- test/cpp/naming/address_sorting_test.cc | 52 +++++----- .../generated/sources_and_headers.json | 19 +++- tools/run_tests/generated/tests.json | 32 +++++- 14 files changed, 403 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a21bb8b5fae..4cbc7597ab1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -361,7 +361,8 @@ endif() if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c resolve_address_posix_test) endif() -add_dependencies(buildtests_c resolve_address_test) +add_dependencies(buildtests_c resolve_address_using_ares_resolver_test) +add_dependencies(buildtests_c resolve_address_using_native_resolver_test) add_dependencies(buildtests_c resource_quota_test) add_dependencies(buildtests_c secure_channel_create_test) add_dependencies(buildtests_c secure_endpoint_test) @@ -8553,12 +8554,12 @@ endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) -add_executable(resolve_address_test +add_executable(resolve_address_using_ares_resolver_test test/core/iomgr/resolve_address_test.cc ) -target_include_directories(resolve_address_test +target_include_directories(resolve_address_using_ares_resolver_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include PRIVATE ${_gRPC_SSL_INCLUDE_DIR} @@ -8571,7 +8572,36 @@ target_include_directories(resolve_address_test PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} ) -target_link_libraries(resolve_address_test +target_link_libraries(resolve_address_using_ares_resolver_test + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) + +add_executable(resolve_address_using_native_resolver_test + test/core/iomgr/resolve_address_test.cc +) + + +target_include_directories(resolve_address_using_native_resolver_test + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${_gRPC_SSL_INCLUDE_DIR} + PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR} + PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR} + PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR} + PRIVATE ${_gRPC_CARES_INCLUDE_DIR} + PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR} + PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + PRIVATE ${_gRPC_NANOPB_INCLUDE_DIR} +) + +target_link_libraries(resolve_address_using_native_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util grpc diff --git a/Makefile b/Makefile index 96ea890bcb8..85de7b67c5e 100644 --- a/Makefile +++ b/Makefile @@ -1081,7 +1081,8 @@ percent_encode_fuzzer: $(BINDIR)/$(CONFIG)/percent_encode_fuzzer percent_encoding_test: $(BINDIR)/$(CONFIG)/percent_encoding_test pollset_set_test: $(BINDIR)/$(CONFIG)/pollset_set_test resolve_address_posix_test: $(BINDIR)/$(CONFIG)/resolve_address_posix_test -resolve_address_test: $(BINDIR)/$(CONFIG)/resolve_address_test +resolve_address_using_ares_resolver_test: $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test +resolve_address_using_native_resolver_test: $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test resource_quota_test: $(BINDIR)/$(CONFIG)/resource_quota_test secure_channel_create_test: $(BINDIR)/$(CONFIG)/secure_channel_create_test secure_endpoint_test: $(BINDIR)/$(CONFIG)/secure_endpoint_test @@ -1524,7 +1525,8 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/percent_encoding_test \ $(BINDIR)/$(CONFIG)/pollset_set_test \ $(BINDIR)/$(CONFIG)/resolve_address_posix_test \ - $(BINDIR)/$(CONFIG)/resolve_address_test \ + $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test \ + $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test \ $(BINDIR)/$(CONFIG)/resource_quota_test \ $(BINDIR)/$(CONFIG)/secure_channel_create_test \ $(BINDIR)/$(CONFIG)/secure_endpoint_test \ @@ -2118,8 +2120,10 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/pollset_set_test || ( echo test pollset_set_test failed ; exit 1 ) $(E) "[RUN] Testing resolve_address_posix_test" $(Q) $(BINDIR)/$(CONFIG)/resolve_address_posix_test || ( echo test resolve_address_posix_test failed ; exit 1 ) - $(E) "[RUN] Testing resolve_address_test" - $(Q) $(BINDIR)/$(CONFIG)/resolve_address_test || ( echo test resolve_address_test failed ; exit 1 ) + $(E) "[RUN] Testing resolve_address_using_ares_resolver_test" + $(Q) $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test || ( echo test resolve_address_using_ares_resolver_test failed ; exit 1 ) + $(E) "[RUN] Testing resolve_address_using_native_resolver_test" + $(Q) $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test || ( echo test resolve_address_using_native_resolver_test failed ; exit 1 ) $(E) "[RUN] Testing resource_quota_test" $(Q) $(BINDIR)/$(CONFIG)/resource_quota_test || ( echo test resource_quota_test failed ; exit 1 ) $(E) "[RUN] Testing secure_channel_create_test" @@ -14031,34 +14035,66 @@ endif endif -RESOLVE_ADDRESS_TEST_SRC = \ +RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_SRC = \ test/core/iomgr/resolve_address_test.cc \ -RESOLVE_ADDRESS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_TEST_SRC)))) +RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_SRC)))) ifeq ($(NO_SECURE),true) # You can't build secure targets if you don't have OpenSSL. -$(BINDIR)/$(CONFIG)/resolve_address_test: openssl_dep_error +$(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test: openssl_dep_error else -$(BINDIR)/$(CONFIG)/resolve_address_test: $(RESOLVE_ADDRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test: $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_test + $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_using_ares_resolver_test endif $(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a -deps_resolve_address_test: $(RESOLVE_ADDRESS_TEST_OBJS:.o=.dep) +deps_resolve_address_using_ares_resolver_test: $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) --include $(RESOLVE_ADDRESS_TEST_OBJS:.o=.dep) +-include $(RESOLVE_ADDRESS_USING_ARES_RESOLVER_TEST_OBJS:.o=.dep) +endif +endif + + +RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_SRC = \ + test/core/iomgr/resolve_address_test.cc \ + +RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test: $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/resolve_address_using_native_resolver_test + +endif + +$(OBJDIR)/$(CONFIG)/test/core/iomgr/resolve_address_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_resolve_address_using_native_resolver_test: $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(RESOLVE_ADDRESS_USING_NATIVE_RESOLVER_TEST_OBJS:.o=.dep) endif endif diff --git a/build.yaml b/build.yaml index a50a0a4ab65..b354826128d 100644 --- a/build.yaml +++ b/build.yaml @@ -3363,7 +3363,7 @@ targets: - mac - linux - posix -- name: resolve_address_test +- name: resolve_address_using_ares_resolver_test build: test language: c src: @@ -3373,6 +3373,20 @@ targets: - grpc - gpr_test_util - gpr + args: + - --resolver=ares +- name: resolve_address_using_native_resolver_test + build: test + language: c + src: + - test/core/iomgr/resolve_address_test.cc + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + args: + - --resolver=native - name: resource_quota_test cpu_cost: 30 build: test diff --git a/src/core/ext/filters/client_channel/parse_address.cc b/src/core/ext/filters/client_channel/parse_address.cc index 7e726dd5624..b94429e207e 100644 --- a/src/core/ext/filters/client_channel/parse_address.cc +++ b/src/core/ext/filters/client_channel/parse_address.cc @@ -197,3 +197,12 @@ bool grpc_parse_uri(const grpc_uri* uri, grpc_resolved_address* resolved_addr) { gpr_log(GPR_ERROR, "Can't parse scheme '%s'", uri->scheme); return false; } + +uint16_t grpc_strhtons(const char* port) { + if (strcmp(port, "http") == 0) { + return htons(80); + } else if (strcmp(port, "https") == 0) { + return htons(443); + } + return htons(static_cast(atoi(port))); +} diff --git a/src/core/ext/filters/client_channel/parse_address.h b/src/core/ext/filters/client_channel/parse_address.h index 9a88b66edcf..c2af0e6c498 100644 --- a/src/core/ext/filters/client_channel/parse_address.h +++ b/src/core/ext/filters/client_channel/parse_address.h @@ -47,4 +47,7 @@ bool grpc_parse_ipv4_hostport(const char* hostport, grpc_resolved_address* addr, bool grpc_parse_ipv6_hostport(const char* hostport, grpc_resolved_address* addr, bool log_errors); +/* Converts named or numeric port to a uint16 suitable for use in a sockaddr. */ +uint16_t grpc_strhtons(const char* port); + #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_PARSE_ADDRESS_H */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index 485998f5e44..4c795c34c8e 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -87,15 +87,6 @@ typedef struct grpc_ares_hostbyname_request { static void do_basic_init(void) { gpr_mu_init(&g_init_mu); } -static uint16_t strhtons(const char* port) { - if (strcmp(port, "http") == 0) { - return htons(80); - } else if (strcmp(port, "https") == 0) { - return htons(443); - } - return htons(static_cast(atoi(port))); -} - static void log_address_sorting_list(grpc_lb_addresses* lb_addrs, const char* input_output_str) { for (size_t i = 0; i < lb_addrs->num_addresses; i++) { @@ -139,12 +130,6 @@ void grpc_cares_wrapper_address_sorting_sort(grpc_lb_addresses* lb_addrs) { } } -/* Allow tests to access grpc_ares_wrapper_address_sorting_sort */ -void grpc_cares_wrapper_test_only_address_sorting_sort( - grpc_lb_addresses* lb_addrs) { - grpc_cares_wrapper_address_sorting_sort(lb_addrs); -} - static void grpc_ares_request_ref_locked(grpc_ares_request* r) { r->pending_queries++; } @@ -371,7 +356,8 @@ done: grpc_ares_request_unref_locked(r); } -static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( +static grpc_ares_request* +grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, @@ -454,12 +440,12 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( } r->pending_queries = 1; if (grpc_ares_query_ipv6()) { - hr = create_hostbyname_request_locked(r, host, strhtons(port), + hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port), false /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked, hr); } - hr = create_hostbyname_request_locked(r, host, strhtons(port), + hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port), false /* is_balancer */); ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked, hr); @@ -494,6 +480,79 @@ error_cleanup: return nullptr; } +static bool inner_resolve_as_ip_literal_locked(const char* name, + const char* default_port, + grpc_lb_addresses** addrs, + char** host, char** port, + char** hostport) { + gpr_split_host_port(name, host, port); + if (*host == nullptr) { + gpr_log(GPR_ERROR, + "Failed to parse %s to host:port while attempting to resolve as ip " + "literal.", + name); + return false; + } + if (*port == nullptr) { + if (default_port == nullptr) { + gpr_log(GPR_ERROR, + "No port or default port for %s while attempting to resolve as " + "ip literal.", + name); + return false; + } + *port = gpr_strdup(default_port); + } + grpc_resolved_address addr; + GPR_ASSERT(gpr_join_host_port(hostport, *host, atoi(*port))); + if (grpc_parse_ipv4_hostport(*hostport, &addr, false /* log errors */) || + grpc_parse_ipv6_hostport(*hostport, &addr, false /* log errors */)) { + GPR_ASSERT(*addrs == nullptr); + *addrs = grpc_lb_addresses_create(1, nullptr); + grpc_lb_addresses_set_address( + *addrs, 0, addr.addr, addr.len, false /* is_balancer */, + nullptr /* balancer_name */, nullptr /* user_data */); + return true; + } + return false; +} + +static bool resolve_as_ip_literal_locked(const char* name, + const char* default_port, + grpc_lb_addresses** addrs) { + char* host = nullptr; + char* port = nullptr; + char* hostport = nullptr; + bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs, + &host, &port, &hostport); + gpr_free(host); + gpr_free(port); + gpr_free(hostport); + return out; +} + +static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( + const char* dns_server, const char* name, const char* default_port, + grpc_pollset_set* interested_parties, grpc_closure* on_done, + grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json, + grpc_combiner* combiner) { + // Early out if the target is an ipv4 or ipv6 literal. + if (resolve_as_ip_literal_locked(name, default_port, addrs)) { + GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); + return nullptr; + } + // Early out if the target is localhost and we're on Windows. + if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port, + addrs)) { + GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE); + return nullptr; + } + // Look up name using c-ares lib. + return grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( + dns_server, name, default_port, interested_parties, on_done, addrs, + check_grpclb, service_config_json, combiner); +} + grpc_ares_request* (*grpc_dns_lookup_ares_locked)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, @@ -502,7 +561,9 @@ grpc_ares_request* (*grpc_dns_lookup_ares_locked)( void grpc_cancel_ares_request(grpc_ares_request* r) { if (grpc_dns_lookup_ares_locked == grpc_dns_lookup_ares_locked_impl) { - grpc_ares_ev_driver_shutdown_locked(r->ev_driver); + if (r != nullptr) { + grpc_ares_ev_driver_shutdown_locked(r->ev_driver); + } } } diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index ca5779e1d79..1bc457d4cfe 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -81,9 +81,15 @@ void grpc_ares_complete_request_locked(grpc_ares_request* request); /* E.g., return false if ipv6 is known to not be available. */ bool grpc_ares_query_ipv6(); -/* Exposed only for testing */ -void grpc_cares_wrapper_test_only_address_sorting_sort( - grpc_lb_addresses* lb_addrs); +/* Maybe (depending on the current platform) checks if "name" matches + * "localhost" and if so fills in addrs with the correct sockaddr structures. + * Returns a bool indicating whether or not such an action was performed. + * See https://github.com/grpc/grpc/issues/15158. */ +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, grpc_lb_addresses** addrs); + +/* Sorts destinations in lb_addrs according to RFC 6724. */ +void grpc_cares_wrapper_address_sorting_sort(grpc_lb_addresses* lb_addrs); #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H \ */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc index 23c0fec74f3..639eec2323f 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_posix.cc @@ -26,4 +26,9 @@ bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, grpc_lb_addresses** addrs) { + return false; +} + #endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET_ARES_EV_DRIVER) */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc index ee827e284e2..7e34784691f 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc @@ -21,9 +21,79 @@ #include "src/core/lib/iomgr/port.h" #if GRPC_ARES == 1 && defined(GPR_WINDOWS) +#include + +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/parse_address.h" #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/gpr/host_port.h" +#include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/socket_windows.h" bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } +static bool inner_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, grpc_lb_addresses** addrs, + char** host, char** port) { + gpr_split_host_port(name, host, port); + if (*host == nullptr) { + gpr_log(GPR_ERROR, + "Failed to parse %s into host:port during Windows localhost " + "resolution check.", + name); + return false; + } + if (*port == nullptr) { + if (default_port == nullptr) { + gpr_log(GPR_ERROR, + "No port or default port for %s during Windows localhost " + "resolution check.", + name); + return false; + } + *port = gpr_strdup(default_port); + } + if (gpr_stricmp(*host, "localhost") == 0) { + GPR_ASSERT(*addrs == nullptr); + *addrs = grpc_lb_addresses_create(2, nullptr); + uint16_t numeric_port = grpc_strhtons(*port); + // Append the ipv6 loopback address. + struct sockaddr_in6 ipv6_loopback_addr; + memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr)); + ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1; + ipv6_loopback_addr.sin6_family = AF_INET6; + ipv6_loopback_addr.sin6_port = numeric_port; + grpc_lb_addresses_set_address( + *addrs, 0, &ipv6_loopback_addr, sizeof(ipv6_loopback_addr), + false /* is_balancer */, nullptr /* balancer_name */, + nullptr /* user_data */); + // Append the ipv4 loopback address. + struct sockaddr_in ipv4_loopback_addr; + memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr)); + ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f; + ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01; + ipv4_loopback_addr.sin_family = AF_INET; + ipv4_loopback_addr.sin_port = numeric_port; + grpc_lb_addresses_set_address( + *addrs, 1, &ipv4_loopback_addr, sizeof(ipv4_loopback_addr), + false /* is_balancer */, nullptr /* balancer_name */, + nullptr /* user_data */); + // Let the address sorter figure out which one should be tried first. + grpc_cares_wrapper_address_sorting_sort(*addrs); + return true; + } + return false; +} + +bool grpc_ares_maybe_resolve_localhost_manually_locked( + const char* name, const char* default_port, grpc_lb_addresses** addrs) { + char* host = nullptr; + char* port = nullptr; + bool out = inner_maybe_resolve_localhost_manually_locked(name, default_port, + addrs, &host, &port); + gpr_free(host); + gpr_free(port); + return out; +} + #endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */ diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 675d9e6278c..7754bc49708 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -174,9 +174,27 @@ grpc_cc_test( ) grpc_cc_test( - name = "resolve_address_test", + name = "resolve_address_using_ares_resolver_test", srcs = ["resolve_address_test.cc"], language = "C++", + args = [ + "--resolver=ares", + ], + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "resolve_address_using_native_resolver_test", + srcs = ["resolve_address_test.cc"], + language = "C++", + args = [ + "--resolver=native", + ], deps = [ "//:gpr", "//:grpc", diff --git a/test/core/iomgr/resolve_address_test.cc b/test/core/iomgr/resolve_address_test.cc index 2fb831a6a46..52e4840c7c6 100644 --- a/test/core/iomgr/resolve_address_test.cc +++ b/test/core/iomgr/resolve_address_test.cc @@ -22,8 +22,14 @@ #include #include #include + +#include + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" +#include "test/core/util/cmdline.h" #include "test/core/util/test_config.h" static gpr_timespec test_deadline(void) { @@ -240,6 +246,28 @@ static void test_unparseable_hostports(void) { } int main(int argc, char** argv) { + // First set the resolver type based off of --resolver + const char* resolver_type = nullptr; + gpr_cmdline* cl = gpr_cmdline_create("resolve address test"); + gpr_cmdline_add_string(cl, "resolver", "Resolver type (ares or native)", + &resolver_type); + gpr_cmdline_parse(cl, argc, argv); + const char* cur_resolver = gpr_getenv("GRPC_DNS_RESOLVER"); + if (cur_resolver != nullptr && strlen(cur_resolver) != 0) { + gpr_log(GPR_INFO, "Warning: overriding resolver setting of %s", + cur_resolver); + } + if (gpr_stricmp(resolver_type, "native") == 0) { + gpr_setenv("GRPC_DNS_RESOLVER", "native"); + } else if (gpr_stricmp(resolver_type, "ares") == 0) { +#ifndef GRPC_UV + gpr_setenv("GRPC_DNS_RESOLVER", "ares"); +#endif + } else { + gpr_log(GPR_ERROR, "--resolver_type was not set to ares or native"); + abort(); + } + // Run the test. grpc_test_init(argc, argv); grpc_init(); { @@ -250,10 +278,18 @@ int main(int argc, char** argv) { test_missing_default_port(); test_ipv6_with_port(); test_ipv6_without_port(); - test_invalid_ip_addresses(); - test_unparseable_hostports(); + if (gpr_stricmp(resolver_type, "ares") != 0) { + // These tests can trigger DNS queries to the nearby nameserver + // that need to come back in order for the test to succeed. + // c-ares is prone to not using the local system caches that the + // native getaddrinfo implementations take advantage of, so running + // these unit tests under c-ares risks flakiness. + test_invalid_ip_addresses(); + test_unparseable_hostports(); + } grpc_executor_shutdown(); } + gpr_cmdline_destroy(cl); grpc_shutdown(); return 0; diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index 04c300876cc..fc6721d0ba8 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -216,7 +216,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnreachableAddresses) { {"1.2.3.4:443", AF_INET}, {"5.6.7.8:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "1.2.3.4:443", "5.6.7.8:443", @@ -235,7 +235,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv6) { {"[2607:f8b0:400a:801::1002]:443", AF_INET6}, {"1.2.3.4:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "1.2.3.4:443", "[2607:f8b0:400a:801::1002]:443", @@ -255,7 +255,7 @@ TEST_F(AddressSortingTest, TestDepriotizesUnsupportedDomainIpv4) { {"[2607:f8b0:400a:801::1002]:443", AF_INET6}, {"1.2.3.4:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[2607:f8b0:400a:801::1002]:443", "1.2.3.4:443", @@ -279,7 +279,7 @@ TEST_F(AddressSortingTest, TestDepriotizesNonMatchingScope) { {"[2000:f8b0:400a:801::1002]:443", AF_INET6}, {"[fec0::5000]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[fec0::5000]:443", "[2000:f8b0:400a:801::1002]:443", @@ -302,7 +302,7 @@ TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTable) { {"[2002::5001]:443", AF_INET6}, {"[2001::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[2001::5001]:443", "[2002::5001]:443", @@ -325,7 +325,7 @@ TEST_F(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) { {"[2001::5001]:443", AF_INET6}, {"[2002::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[2001::5001]:443", "[2002::5001]:443", @@ -348,7 +348,7 @@ TEST_F(AddressSortingTest, {"[3ffe::5001]:443", AF_INET6}, {"1.2.3.4:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs( lb_addrs, { // The AF_INET address should be IPv4-mapped by the sort, @@ -381,7 +381,7 @@ TEST_F(AddressSortingTest, {v4_compat_dest, AF_INET6}, {"[::1]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[::1]:443", v4_compat_dest, @@ -404,7 +404,7 @@ TEST_F(AddressSortingTest, {"[1234::2]:443", AF_INET6}, {"[::1]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs( lb_addrs, { @@ -428,7 +428,7 @@ TEST_F(AddressSortingTest, {"[2001::1234]:443", AF_INET6}, {"[2000::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs( lb_addrs, { // The 2000::/16 address should match the ::/0 prefix rule @@ -452,7 +452,7 @@ TEST_F( {"[2001::1231]:443", AF_INET6}, {"[2000::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[2000::5001]:443", "[2001::1231]:443", @@ -473,7 +473,7 @@ TEST_F(AddressSortingTest, {"[fec0::1234]:443", AF_INET6}, {"[fc00::5001]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[fc00::5001]:443", "[fec0::1234]:443", @@ -498,7 +498,7 @@ TEST_F( {"[::ffff:1.1.1.2]:443", AF_INET6}, {"[1234::2]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { // ::ffff:0:2 should match the v4-mapped // precedence entry and be deprioritized. @@ -525,7 +525,7 @@ TEST_F(AddressSortingTest, TestPrefersSmallerScope) { {"[3ffe::5001]:443", AF_INET6}, {"[fec0::1234]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[fec0::1234]:443", "[3ffe::5001]:443", @@ -550,7 +550,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestMatchingSrcDstPrefix) { {"[3ffe:5001::]:443", AF_INET6}, {"[3ffe:1234::]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe:1234::]:443", "[3ffe:5001::]:443", @@ -571,7 +571,7 @@ TEST_F(AddressSortingTest, {"[3ffe::5001]:443", AF_INET6}, {"[3ffe::1234]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe::1234]:443", "[3ffe::5001]:443", @@ -591,7 +591,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixStressInnerBytePrefix) { {"[3ffe:8000::]:443", AF_INET6}, {"[3ffe:2000::]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe:2000::]:443", "[3ffe:8000::]:443", @@ -611,7 +611,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersOnHighestBitOfByte) { {"[3ffe:6::]:443", AF_INET6}, {"[3ffe:c::]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe:c::]:443", "[3ffe:6::]:443", @@ -633,7 +633,7 @@ TEST_F(AddressSortingTest, TestPrefersLongestPrefixDiffersByLastBit) { {"[3ffe:1111:1111:1110::]:443", AF_INET6}, {"[3ffe:1111:1111:1111::]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe:1111:1111:1111::]:443", "[3ffe:1111:1111:1110::]:443", @@ -655,7 +655,7 @@ TEST_F(AddressSortingTest, TestStableSort) { {"[3ffe::1234]:443", AF_INET6}, {"[3ffe::1235]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe::1234]:443", "[3ffe::1235]:443", @@ -681,7 +681,7 @@ TEST_F(AddressSortingTest, TestStableSortFiveElements) { {"[3ffe::1234]:443", AF_INET6}, {"[3ffe::1235]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe::1231]:443", "[3ffe::1232]:443", @@ -702,7 +702,7 @@ TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExist) { {"[3ffe::1234]:443", AF_INET6}, {"[3ffe::1235]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[3ffe::1231]:443", "[3ffe::1232]:443", @@ -720,7 +720,7 @@ TEST_F(AddressSortingTest, TestStableSortNoSrcAddrsExistWithIpv4) { {"[::ffff:5.6.7.8]:443", AF_INET6}, {"1.2.3.4:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[::ffff:5.6.7.8]:443", "1.2.3.4:443", @@ -748,7 +748,7 @@ TEST_F(AddressSortingTest, TestStableSortV4CompatAndSiteLocalAddresses) { {"[fec0::2000]:443", AF_INET6}, {v4_compat_dest, AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { // The sort should be stable since @@ -769,7 +769,7 @@ TEST_F(AddressSortingTest, TestPrefersIpv6Loopback) { {"[::1]:443", AF_INET6}, {"127.0.0.1:443", AF_INET}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[::1]:443", "127.0.0.1:443", @@ -783,7 +783,7 @@ TEST_F(AddressSortingTest, TestPrefersIpv6LoopbackInputsFlipped) { {"127.0.0.1:443", AF_INET}, {"[::1]:443", AF_INET6}, }); - grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs); + grpc_cares_wrapper_address_sorting_sort(lb_addrs); VerifyLbAddrOutputs(lb_addrs, { "[::1]:443", "127.0.0.1:443", diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 8ea5126fdef..5d6113bc18f 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1897,7 +1897,24 @@ "headers": [], "is_filegroup": false, "language": "c", - "name": "resolve_address_test", + "name": "resolve_address_using_ares_resolver_test", + "src": [ + "test/core/iomgr/resolve_address_test.cc" + ], + "third_party": false, + "type": "target" + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "resolve_address_using_native_resolver_test", "src": [ "test/core/iomgr/resolve_address_test.cc" ], diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index fba76d69d1e..0ecc8a120a3 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -2146,7 +2146,35 @@ "uses_polling": true }, { - "args": [], + "args": [ + "--resolver=ares" + ], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": false, + "language": "c", + "name": "resolve_address_using_ares_resolver_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, + { + "args": [ + "--resolver=native" + ], "benchmark": false, "ci_platforms": [ "linux", @@ -2160,7 +2188,7 @@ "flaky": false, "gtest": false, "language": "c", - "name": "resolve_address_test", + "name": "resolve_address_using_native_resolver_test", "platforms": [ "linux", "mac",