The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
5.1 KiB
162 lines
5.1 KiB
// |
|
// Copyright 2015 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 <grpc/support/port_platform.h> |
|
|
|
#include "src/core/resolver/resolver_registry.h" |
|
|
|
#include "absl/status/status.h" |
|
#include "absl/status/statusor.h" |
|
#include "absl/strings/ascii.h" |
|
#include "absl/strings/str_cat.h" |
|
#include "absl/strings/str_format.h" |
|
|
|
#include <grpc/support/log.h> |
|
|
|
namespace grpc_core { |
|
|
|
// |
|
// ResolverRegistry::Builder |
|
// |
|
|
|
ResolverRegistry::Builder::Builder() { Reset(); } |
|
|
|
void ResolverRegistry::Builder::SetDefaultPrefix(std::string default_prefix) { |
|
state_.default_prefix = std::move(default_prefix); |
|
} |
|
|
|
namespace { |
|
|
|
bool IsLowerCase(absl::string_view str) { |
|
for (unsigned char c : str) { |
|
if (absl::ascii_isalpha(c) && !absl::ascii_islower(c)) return false; |
|
} |
|
return true; |
|
} |
|
|
|
} // namespace |
|
|
|
void ResolverRegistry::Builder::RegisterResolverFactory( |
|
std::unique_ptr<ResolverFactory> factory) { |
|
GPR_ASSERT(IsLowerCase(factory->scheme())); |
|
auto p = state_.factories.emplace(factory->scheme(), std::move(factory)); |
|
GPR_ASSERT(p.second); |
|
} |
|
|
|
bool ResolverRegistry::Builder::HasResolverFactory( |
|
absl::string_view scheme) const { |
|
return state_.factories.find(scheme) != state_.factories.end(); |
|
} |
|
|
|
void ResolverRegistry::Builder::Reset() { |
|
state_.factories.clear(); |
|
state_.default_prefix = "dns:///"; |
|
} |
|
|
|
ResolverRegistry ResolverRegistry::Builder::Build() { |
|
return ResolverRegistry(std::move(state_)); |
|
} |
|
|
|
// |
|
// ResolverRegistry |
|
// |
|
|
|
bool ResolverRegistry::IsValidTarget(absl::string_view target) const { |
|
std::string canonical_target; |
|
URI uri; |
|
ResolverFactory* factory = |
|
FindResolverFactory(target, &uri, &canonical_target); |
|
if (factory == nullptr) return false; |
|
return factory->IsValidUri(uri); |
|
} |
|
|
|
OrphanablePtr<Resolver> ResolverRegistry::CreateResolver( |
|
absl::string_view target, const ChannelArgs& args, |
|
grpc_pollset_set* pollset_set, |
|
std::shared_ptr<WorkSerializer> work_serializer, |
|
std::unique_ptr<Resolver::ResultHandler> result_handler) const { |
|
std::string canonical_target; |
|
ResolverArgs resolver_args; |
|
ResolverFactory* factory = |
|
FindResolverFactory(target, &resolver_args.uri, &canonical_target); |
|
if (factory == nullptr) return nullptr; |
|
resolver_args.args = args; |
|
resolver_args.pollset_set = pollset_set; |
|
resolver_args.work_serializer = std::move(work_serializer); |
|
resolver_args.result_handler = std::move(result_handler); |
|
return factory->CreateResolver(std::move(resolver_args)); |
|
} |
|
|
|
std::string ResolverRegistry::GetDefaultAuthority( |
|
absl::string_view target) const { |
|
std::string canonical_target; |
|
URI uri; |
|
ResolverFactory* factory = |
|
FindResolverFactory(target, &uri, &canonical_target); |
|
if (factory == nullptr) return ""; |
|
return factory->GetDefaultAuthority(uri); |
|
} |
|
|
|
std::string ResolverRegistry::AddDefaultPrefixIfNeeded( |
|
absl::string_view target) const { |
|
std::string canonical_target; |
|
URI uri; |
|
FindResolverFactory(target, &uri, &canonical_target); |
|
return canonical_target.empty() ? std::string(target) : canonical_target; |
|
} |
|
|
|
ResolverFactory* ResolverRegistry::LookupResolverFactory( |
|
absl::string_view scheme) const { |
|
auto it = state_.factories.find(scheme); |
|
if (it == state_.factories.end()) return nullptr; |
|
return it->second.get(); |
|
} |
|
|
|
// Returns the factory for the scheme of \a target. If \a target does |
|
// not parse as a URI, prepends \a default_prefix_ and tries again. |
|
// If URI parsing is successful (in either attempt), sets \a uri to |
|
// point to the parsed URI. |
|
ResolverFactory* ResolverRegistry::FindResolverFactory( |
|
absl::string_view target, URI* uri, std::string* canonical_target) const { |
|
GPR_ASSERT(uri != nullptr); |
|
absl::StatusOr<URI> tmp_uri = URI::Parse(target); |
|
ResolverFactory* factory = |
|
tmp_uri.ok() ? LookupResolverFactory(tmp_uri->scheme()) : nullptr; |
|
if (factory != nullptr) { |
|
*uri = std::move(*tmp_uri); |
|
return factory; |
|
} |
|
*canonical_target = absl::StrCat(state_.default_prefix, target); |
|
absl::StatusOr<URI> tmp_uri2 = URI::Parse(*canonical_target); |
|
factory = tmp_uri2.ok() ? LookupResolverFactory(tmp_uri2->scheme()) : nullptr; |
|
if (factory != nullptr) { |
|
*uri = std::move(*tmp_uri2); |
|
return factory; |
|
} |
|
if (!tmp_uri.ok() || !tmp_uri2.ok()) { |
|
gpr_log(GPR_ERROR, "%s", |
|
absl::StrFormat("Error parsing URI(s). '%s':%s; '%s':%s", target, |
|
tmp_uri.status().ToString(), *canonical_target, |
|
tmp_uri2.status().ToString()) |
|
.c_str()); |
|
return nullptr; |
|
} |
|
gpr_log(GPR_ERROR, "Don't know how to resolve '%s' or '%s'.", |
|
std::string(target).c_str(), canonical_target->c_str()); |
|
return nullptr; |
|
} |
|
|
|
} // namespace grpc_core
|
|
|