From 34fdb542b5dafcd84dcb0ce2137bb0ee2049aaaa Mon Sep 17 00:00:00 2001 From: Ming-Chuan Date: Thu, 21 Oct 2021 14:17:19 +0800 Subject: [PATCH] Add resolver for binder transport URI scheme (#27529) This commit is part of the effort to create binder channel with GRPC_CLIENT_CHANNEL type. The resolver will be used during name resolution, and the result will later be used to identify the corresponding endpoint binder in SubchannelConnector. Besides the unit test, this change is tested with other changes locally end to end on real device. --- BUILD | 18 ++ CMakeLists.txt | 38 ++++ Makefile | 2 + build_autogenerated.yaml | 11 ++ config.m4 | 2 + config.w32 | 2 + gRPC-Core.podspec | 1 + grpc.gemspec | 1 + grpc.gyp | 2 + package.xml | 1 + .../client_channel/resolver/binder/README.md | 9 + .../resolver/binder/binder_resolver.cc | 139 ++++++++++++++ .../plugin_registry/grpc_plugin_registry.cc | 10 + src/python/grpcio/grpc_core_dependencies.py | 1 + test/core/client_channel/resolvers/BUILD | 14 ++ .../resolvers/binder_resolver_test.cc | 181 ++++++++++++++++++ tools/doxygen/Doxyfile.c++.internal | 1 + tools/doxygen/Doxyfile.core.internal | 2 + tools/run_tests/generated/tests.json | 24 +++ 19 files changed, 459 insertions(+) create mode 100644 src/core/ext/filters/client_channel/resolver/binder/README.md create mode 100644 src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc create mode 100644 test/core/client_channel/resolvers/binder_resolver_test.cc diff --git a/BUILD b/BUILD index 5aae602ebed..b90d3e18487 100644 --- a/BUILD +++ b/BUILD @@ -1928,6 +1928,7 @@ grpc_cc_library( "grpc_resolver_fake", "grpc_resolver_dns_native", "grpc_resolver_sockaddr", + "grpc_resolver_binder", "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_server_insecure", "grpc_transport_inproc", @@ -2968,6 +2969,23 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "grpc_resolver_binder", + srcs = [ + "src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc", + ], + external_deps = [ + "absl/strings", + ], + language = "c++", + deps = [ + "gpr_base", + "grpc_base", + "grpc_client_channel", + "slice", + ], +) + grpc_cc_library( name = "grpc_resolver_fake", srcs = ["src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc"], diff --git a/CMakeLists.txt b/CMakeLists.txt index 88bb75abd50..6f9f00b9d82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -751,6 +751,7 @@ if(gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx bdp_estimator_test) endif() + add_dependencies(buildtests_cxx binder_resolver_test) add_dependencies(buildtests_cxx binder_server_test) add_dependencies(buildtests_cxx binder_transport_test) add_dependencies(buildtests_cxx bitset_test) @@ -1529,6 +1530,7 @@ add_library(grpc src/core/ext/filters/client_channel/local_subchannel_pool.cc src/core/ext/filters/client_channel/proxy_mapper_registry.cc src/core/ext/filters/client_channel/resolver.cc + src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc @@ -2365,6 +2367,7 @@ add_library(grpc_unsecure src/core/ext/filters/client_channel/local_subchannel_pool.cc src/core/ext/filters/client_channel/proxy_mapper_registry.cc src/core/ext/filters/client_channel/resolver.cc + src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc @@ -8295,6 +8298,41 @@ endif() endif() if(gRPC_BUILD_TESTS) +add_executable(binder_resolver_test + test/core/client_channel/resolvers/binder_resolver_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(binder_resolver_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(binder_resolver_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + +endif() +if(gRPC_BUILD_TESTS) + add_executable(binder_server_test ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc diff --git a/Makefile b/Makefile index bad402e45c7..fa660d063be 100644 --- a/Makefile +++ b/Makefile @@ -1082,6 +1082,7 @@ LIBGRPC_SRC = \ src/core/ext/filters/client_channel/local_subchannel_pool.cc \ src/core/ext/filters/client_channel/proxy_mapper_registry.cc \ src/core/ext/filters/client_channel/resolver.cc \ + src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ @@ -1764,6 +1765,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/filters/client_channel/local_subchannel_pool.cc \ src/core/ext/filters/client_channel/proxy_mapper_registry.cc \ src/core/ext/filters/client_channel/resolver.cc \ + src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index 09db7946bf3..4fdbed6ccb8 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -996,6 +996,7 @@ libs: - src/core/ext/filters/client_channel/local_subchannel_pool.cc - src/core/ext/filters/client_channel/proxy_mapper_registry.cc - src/core/ext/filters/client_channel/resolver.cc + - src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc @@ -1968,6 +1969,7 @@ libs: - src/core/ext/filters/client_channel/local_subchannel_pool.cc - src/core/ext/filters/client_channel/proxy_mapper_registry.cc - src/core/ext/filters/client_channel/resolver.cc + - src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc - src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc @@ -4609,6 +4611,15 @@ targets: - posix - mac uses_polling: false +- name: binder_resolver_test + gtest: true + build: test + language: c++ + headers: [] + src: + - test/core/client_channel/resolvers/binder_resolver_test.cc + deps: + - grpc_test_util - name: binder_server_test gtest: true build: test diff --git a/config.m4 b/config.m4 index 721365d8989..9bfff142adc 100644 --- a/config.m4 +++ b/config.m4 @@ -77,6 +77,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/filters/client_channel/local_subchannel_pool.cc \ src/core/ext/filters/client_channel/proxy_mapper_registry.cc \ src/core/ext/filters/client_channel/resolver.cc \ + src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \ @@ -1074,6 +1075,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/round_robin) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/weighted_target) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/xds) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/binder) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/c_ares) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/dns/native) diff --git a/config.w32 b/config.w32 index 849335d2b73..3b18fa79da0 100644 --- a/config.w32 +++ b/config.w32 @@ -43,6 +43,7 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\filters\\client_channel\\local_subchannel_pool.cc " + "src\\core\\ext\\filters\\client_channel\\proxy_mapper_registry.cc " + "src\\core\\ext\\filters\\client_channel\\resolver.cc " + + "src\\core\\ext\\filters\\client_channel\\resolver\\binder\\binder_resolver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_event_engine.cc " + "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_posix.cc " + @@ -1073,6 +1074,7 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\weighted_target"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\xds"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\binder"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\dns\\native"); diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index 89cedca67f8..18feb147e7d 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -257,6 +257,7 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/proxy_mapper_registry.h', 'src/core/ext/filters/client_channel/resolver.cc', 'src/core/ext/filters/client_channel/resolver.h', + 'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc', diff --git a/grpc.gemspec b/grpc.gemspec index e2d63d1c2fc..de7cbc64d07 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -177,6 +177,7 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.h ) s.files += %w( src/core/ext/filters/client_channel/resolver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver.h ) + s.files += %w( src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h ) s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc ) diff --git a/grpc.gyp b/grpc.gyp index 81b7f97f316..fd67abbdfb5 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -523,6 +523,7 @@ 'src/core/ext/filters/client_channel/local_subchannel_pool.cc', 'src/core/ext/filters/client_channel/proxy_mapper_registry.cc', 'src/core/ext/filters/client_channel/resolver.cc', + 'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', @@ -1180,6 +1181,7 @@ 'src/core/ext/filters/client_channel/local_subchannel_pool.cc', 'src/core/ext/filters/client_channel/proxy_mapper_registry.cc', 'src/core/ext/filters/client_channel/resolver.cc', + 'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', diff --git a/package.xml b/package.xml index f26e9ed734e..8dd1784584f 100644 --- a/package.xml +++ b/package.xml @@ -157,6 +157,7 @@ + diff --git a/src/core/ext/filters/client_channel/resolver/binder/README.md b/src/core/ext/filters/client_channel/resolver/binder/README.md new file mode 100644 index 00000000000..b60296765d5 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/binder/README.md @@ -0,0 +1,9 @@ +Support for resolving the scheme used by binder transport implementation. + +The URI's authority is required to be empty. + +The path is used as the identifiers of endpoint binder objects and the length +limit of the identifier is the same as unix socket length limit. + +The length limit of the path should at least be 100 characters long. This is +guaranteed by `static_assert` in the implementation. diff --git a/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc b/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc new file mode 100644 index 00000000000..68f21c80e1a --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc @@ -0,0 +1,139 @@ +// Copyright 2021 gRPC 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 "src/core/lib/iomgr/port.h" + +#ifdef GRPC_HAVE_UNIX_SOCKET + +#include + +#include +#include + +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gpr/string.h" + +namespace grpc_core { +namespace { + +class BinderResolver : public Resolver { + public: + BinderResolver(ServerAddressList addresses, ResolverArgs args) + : result_handler_(std::move(args.result_handler)), + addresses_(std::move(addresses)), + channel_args_(grpc_channel_args_copy(args.args)) {} + + ~BinderResolver() override { grpc_channel_args_destroy(channel_args_); }; + + void StartLocked() override { + Result result; + result.addresses = std::move(addresses_); + result.args = channel_args_; + channel_args_ = nullptr; + result_handler_->ReturnResult(std::move(result)); + } + + void ShutdownLocked() override {} + + private: + std::unique_ptr result_handler_; + ServerAddressList addresses_; + const grpc_channel_args* channel_args_ = nullptr; +}; + +class BinderResolverFactory : public ResolverFactory { + public: + bool IsValidUri(const URI& uri) const override { + return ParseUri(uri, nullptr); + } + + OrphanablePtr CreateResolver(ResolverArgs args) const override { + ServerAddressList addresses; + if (!ParseUri(args.uri, &addresses)) return nullptr; + return MakeOrphanable(std::move(addresses), + std::move(args)); + } + + const char* scheme() const override { return "binder"; } + + private: + static grpc_error_handle BinderAddrPopulate( + absl::string_view path, grpc_resolved_address* resolved_addr) { + path = absl::StripPrefix(path, "/"); + if (path.empty()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING("path is empty"); + } + // Store parsed path in a unix socket so it can be reinterpreted as + // sockaddr. An invalid address family (AF_MAX) is set to make sure it won't + // be accidentally used. + memset(resolved_addr, 0, sizeof(*resolved_addr)); + struct sockaddr_un* un = + reinterpret_cast(resolved_addr->addr); + un->sun_family = AF_MAX; + static_assert(sizeof(un->sun_path) >= 101, + "unix socket path size is unexpectedly short"); + if (path.size() + 1 > sizeof(un->sun_path)) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + absl::StrCat(path, " is too long to be handled")); + } + // `un` has already be set to zero, no need to append null after the string + memcpy(un->sun_path, path.data(), path.size()); + resolved_addr->len = + static_cast(sizeof(un->sun_family) + path.size() + 1); + return GRPC_ERROR_NONE; + } + + static bool ParseUri(const URI& uri, ServerAddressList* addresses) { + grpc_resolved_address addr; + { + if (!uri.authority().empty()) { + gpr_log(GPR_ERROR, "authority is not supported in binder scheme"); + return false; + } + grpc_error_handle error = BinderAddrPopulate(uri.path(), &addr); + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, "%s", grpc_error_std_string(error).c_str()); + GRPC_ERROR_UNREF(error); + return false; + } + } + if (addresses != nullptr) { + addresses->emplace_back(addr, nullptr /* args */); + } + return true; + } +}; + +} // namespace +} // namespace grpc_core + +void grpc_resolver_binder_init() { + grpc_core::ResolverRegistry::Builder::RegisterResolverFactory( + absl::make_unique()); +} + +void grpc_resolver_binder_shutdown() {} + +#else + +void grpc_resolver_binder_init() {} + +void grpc_resolver_binder_shutdown() {} + +#endif diff --git a/src/core/plugin_registry/grpc_plugin_registry.cc b/src/core/plugin_registry/grpc_plugin_registry.cc index 134b9d34f05..39bfaed4f84 100644 --- a/src/core/plugin_registry/grpc_plugin_registry.cc +++ b/src/core/plugin_registry/grpc_plugin_registry.cc @@ -87,6 +87,11 @@ void GoogleCloud2ProdResolverShutdown(); } // namespace grpc_core #endif +#ifdef GPR_SUPPORT_BINDER_TRANSPORT +void grpc_resolver_binder_init(void); +void grpc_resolver_binder_shutdown(void); +#endif + void grpc_register_built_in_plugins(void) { grpc_register_plugin(grpc_chttp2_plugin_init, grpc_chttp2_plugin_shutdown); grpc_register_plugin(grpc_core::ServiceConfigParserInit, @@ -136,6 +141,11 @@ void grpc_register_built_in_plugins(void) { grpc_register_plugin(grpc_core::GoogleCloud2ProdResolverInit, grpc_core::GoogleCloud2ProdResolverShutdown); #endif + +#ifdef GPR_SUPPORT_BINDER_TRANSPORT + grpc_register_plugin(grpc_resolver_binder_init, + grpc_resolver_binder_shutdown); +#endif } namespace grpc_core { diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index fe2f0b4498a..a7d256dc16b 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -52,6 +52,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/filters/client_channel/local_subchannel_pool.cc', 'src/core/ext/filters/client_channel/proxy_mapper_registry.cc', 'src/core/ext/filters/client_channel/resolver.cc', + 'src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc', 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc', diff --git a/test/core/client_channel/resolvers/BUILD b/test/core/client_channel/resolvers/BUILD index b50f4373eba..224df41d229 100644 --- a/test/core/client_channel/resolvers/BUILD +++ b/test/core/client_channel/resolvers/BUILD @@ -18,6 +18,20 @@ grpc_package(name = "test/core/client_channel/resolvers") licenses(["notice"]) +grpc_cc_test( + name = "binder_resolver_test", + srcs = ["binder_resolver_test.cc"], + external_deps = [ + "gtest", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "dns_resolver_connectivity_using_ares_test", srcs = ["dns_resolver_connectivity_test.cc"], diff --git a/test/core/client_channel/resolvers/binder_resolver_test.cc b/test/core/client_channel/resolvers/binder_resolver_test.cc new file mode 100644 index 00000000000..4065a393891 --- /dev/null +++ b/test/core/client_channel/resolvers/binder_resolver_test.cc @@ -0,0 +1,181 @@ +// Copyright 2021 gRPC 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 "src/core/lib/iomgr/port.h" +#include "test/core/util/test_config.h" + +#ifdef GRPC_HAVE_UNIX_SOCKET + +#include + +#include + +#include +#include +#include + +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/channel/channel_args.h" + +// Registers the factory with `grpc_core::ResolverRegistry`. Defined in +// binder_resolver.cc +void grpc_resolver_binder_init(void); + +namespace { + +class BinderResolverTest : public ::testing::Test { + public: + BinderResolverTest() { + factory_ = grpc_core::ResolverRegistry::LookupResolverFactory("binder"); + } + ~BinderResolverTest() override {} + static void SetUpTestSuite() { + grpc_init(); + if (grpc_core::ResolverRegistry::LookupResolverFactory("binder") == + nullptr) { + // Binder resolver will only be registered on platforms that support + // binder transport. If it is not registered on current platform, we + // manually register it here for testing purpose. + grpc_resolver_binder_init(); + ASSERT_TRUE(grpc_core::ResolverRegistry::LookupResolverFactory("binder")); + } + } + static void TearDownTestSuite() { grpc_shutdown(); } + + void SetUp() override { ASSERT_TRUE(factory_); } + + class ResultHandler : public grpc_core::Resolver::ResultHandler { + public: + ResultHandler() = default; + + explicit ResultHandler(const std::string& expected_binder_id) + : expect_result_(true), expected_binder_id_(expected_binder_id) {} + + void ReturnResult(grpc_core::Resolver::Result result) override { + EXPECT_TRUE(expect_result_); + ASSERT_TRUE(result.addresses.size() == 1); + grpc_core::ServerAddress addr = result.addresses[0]; + const struct sockaddr_un* un = + reinterpret_cast(addr.address().addr); + EXPECT_EQ(addr.address().len, + sizeof(un->sun_family) + expected_binder_id_.length() + 1); + EXPECT_EQ(un->sun_family, AF_MAX); + EXPECT_EQ(un->sun_path, expected_binder_id_); + } + + void ReturnError(grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + + private: + // Whether we expect ReturnResult function to be invoked + bool expect_result_ = false; + + std::string expected_binder_id_; + }; + + void TestSucceeds(const char* string, const std::string& expected_path) { + gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string, + factory_->scheme()); + grpc_core::ExecCtx exec_ctx; + absl::StatusOr uri = grpc_core::URI::Parse(string); + ASSERT_TRUE(uri.ok()) << uri.status().ToString(); + grpc_core::ResolverArgs args; + args.uri = std::move(*uri); + args.result_handler = + absl::make_unique(expected_path); + grpc_core::OrphanablePtr resolver = + factory_->CreateResolver(std::move(args)); + ASSERT_TRUE(resolver != nullptr); + resolver->StartLocked(); + } + + void TestFails(const char* string) { + gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string, + factory_->scheme()); + grpc_core::ExecCtx exec_ctx; + absl::StatusOr uri = grpc_core::URI::Parse(string); + ASSERT_TRUE(uri.ok()) << uri.status().ToString(); + grpc_core::ResolverArgs args; + args.uri = std::move(*uri); + args.result_handler = + absl::make_unique(); + grpc_core::OrphanablePtr resolver = + factory_->CreateResolver(std::move(args)); + EXPECT_TRUE(resolver == nullptr); + } + + private: + grpc_core::ResolverFactory* factory_; +}; + +} // namespace + +// Authority is not allowed +TEST_F(BinderResolverTest, AuthorityPresents) { + TestFails("binder://example"); + TestFails("binder://google.com"); + TestFails("binder://google.com/test"); +} + +// Path cannot be empty +TEST_F(BinderResolverTest, EmptyPath) { + TestFails("binder:"); + TestFails("binder:/"); + TestFails("binder://"); +} + +TEST_F(BinderResolverTest, PathLength) { + // Note that we have a static assert in binder_resolver.cc that checks + // sizeof(sockaddr_un::sun_path) is greater than 100 + + // 100 character path should be fine + TestSucceeds(("binder:l" + std::string(98, 'o') + "g").c_str(), + "l" + std::string(98, 'o') + "g"); + + // 200 character path most likely will fail + TestFails(("binder:l" + std::string(198, 'o') + "g").c_str()); +} + +TEST_F(BinderResolverTest, SlashPrefixes) { + TestSucceeds("binder:///test", "test"); + TestSucceeds("binder:////test", "/test"); +} + +TEST_F(BinderResolverTest, ValidCases) { + TestSucceeds("binder:[[", "[["); + TestSucceeds("binder:google!com", "google!com"); + TestSucceeds("binder:test/", "test/"); + TestSucceeds("binder:test:", "test:"); + + TestSucceeds("binder:e", "e"); + TestSucceeds("binder:example", "example"); + TestSucceeds("binder:google.com", "google.com"); + TestSucceeds("binder:~", "~"); + TestSucceeds("binder:12345", "12345"); + TestSucceeds( + "binder:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._" + "~", + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~"); +} + +#endif + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + grpc::testing::TestEnvironment env(argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 694155faed0..b1f6ff44fa8 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1114,6 +1114,7 @@ src/core/ext/filters/client_channel/proxy_mapper_registry.cc \ src/core/ext/filters/client_channel/proxy_mapper_registry.h \ src/core/ext/filters/client_channel/resolver.cc \ src/core/ext/filters/client_channel/resolver.h \ +src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \ diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 79da53a775c..d09a5e498ee 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -939,6 +939,8 @@ src/core/ext/filters/client_channel/proxy_mapper_registry.h \ src/core/ext/filters/client_channel/resolver.cc \ src/core/ext/filters/client_channel/resolver.h \ src/core/ext/filters/client_channel/resolver/README.md \ +src/core/ext/filters/client_channel/resolver/binder/README.md \ +src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h \ src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc \ diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 0df688f96cd..6bbed15c436 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -3379,6 +3379,30 @@ ], "uses_polling": false }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [], + "flaky": false, + "gtest": true, + "language": "c++", + "name": "binder_resolver_test", + "platforms": [ + "linux", + "mac", + "posix", + "windows" + ], + "uses_polling": true + }, { "args": [], "benchmark": false,