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,