1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/ext/filters/client_channel/resolver_registry.h"
22
23 #include <string.h>
24
25 #include "absl/container/inlined_vector.h"
26 #include "absl/strings/str_cat.h"
27 #include "absl/strings/str_format.h"
28
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.h>
31 #include <grpc/support/string_util.h>
32
33 namespace grpc_core {
34
35 namespace {
36
37 class RegistryState {
38 public:
RegistryState()39 RegistryState() : default_prefix_(gpr_strdup("dns:///")) {}
40
SetDefaultPrefix(const char * default_resolver_prefix)41 void SetDefaultPrefix(const char* default_resolver_prefix) {
42 GPR_ASSERT(default_resolver_prefix != nullptr);
43 GPR_ASSERT(*default_resolver_prefix != '\0');
44 default_prefix_.reset(gpr_strdup(default_resolver_prefix));
45 }
46
RegisterResolverFactory(std::unique_ptr<ResolverFactory> factory)47 void RegisterResolverFactory(std::unique_ptr<ResolverFactory> factory) {
48 for (size_t i = 0; i < factories_.size(); ++i) {
49 GPR_ASSERT(strcmp(factories_[i]->scheme(), factory->scheme()) != 0);
50 }
51 factories_.push_back(std::move(factory));
52 }
53
LookupResolverFactory(absl::string_view scheme) const54 ResolverFactory* LookupResolverFactory(absl::string_view scheme) const {
55 for (size_t i = 0; i < factories_.size(); ++i) {
56 if (scheme == factories_[i]->scheme()) {
57 return factories_[i].get();
58 }
59 }
60 return nullptr;
61 }
62
63 // Returns the factory for the scheme of \a target. If \a target does
64 // not parse as a URI, prepends \a default_prefix_ and tries again.
65 // If URI parsing is successful (in either attempt), sets \a uri to
66 // point to the parsed URI.
67 // If \a default_prefix_ needs to be prepended, sets \a canonical_target
68 // to the canonical target string.
FindResolverFactory(absl::string_view target,URI * uri,std::string * canonical_target) const69 ResolverFactory* FindResolverFactory(absl::string_view target, URI* uri,
70 std::string* canonical_target) const {
71 GPR_ASSERT(uri != nullptr);
72 absl::StatusOr<URI> tmp_uri = URI::Parse(target);
73 ResolverFactory* factory =
74 tmp_uri.ok() ? LookupResolverFactory(tmp_uri->scheme()) : nullptr;
75 if (factory != nullptr) {
76 *uri = *tmp_uri;
77 return factory;
78 }
79 *canonical_target = absl::StrCat(default_prefix_.get(), target);
80 absl::StatusOr<URI> tmp_uri2 = URI::Parse(*canonical_target);
81 factory =
82 tmp_uri2.ok() ? LookupResolverFactory(tmp_uri2->scheme()) : nullptr;
83 if (factory != nullptr) {
84 *uri = *tmp_uri2;
85 return factory;
86 }
87 if (!tmp_uri.ok() || !tmp_uri2.ok()) {
88 gpr_log(GPR_ERROR, "%s",
89 absl::StrFormat("Error parsing URI(s). '%s':%s; '%s':%s", target,
90 tmp_uri.status().ToString(), *canonical_target,
91 tmp_uri2.status().ToString())
92 .c_str());
93 return nullptr;
94 }
95 gpr_log(GPR_ERROR, "Don't know how to resolve '%s' or '%s'.",
96 std::string(target).c_str(), canonical_target->c_str());
97 return nullptr;
98 }
99
100 private:
101 // We currently support 10 factories without doing additional
102 // allocation. This number could be raised if there is a case where
103 // more factories are needed and the additional allocations are
104 // hurting performance (which is unlikely, since these allocations
105 // only occur at gRPC initialization time).
106 absl::InlinedVector<std::unique_ptr<ResolverFactory>, 10> factories_;
107 grpc_core::UniquePtr<char> default_prefix_;
108 };
109
110 static RegistryState* g_state = nullptr;
111
112 } // namespace
113
114 //
115 // ResolverRegistry::Builder
116 //
117
InitRegistry()118 void ResolverRegistry::Builder::InitRegistry() {
119 if (g_state == nullptr) g_state = new RegistryState();
120 }
121
ShutdownRegistry()122 void ResolverRegistry::Builder::ShutdownRegistry() {
123 delete g_state;
124 g_state = nullptr;
125 }
126
SetDefaultPrefix(const char * default_prefix)127 void ResolverRegistry::Builder::SetDefaultPrefix(const char* default_prefix) {
128 InitRegistry();
129 g_state->SetDefaultPrefix(default_prefix);
130 }
131
RegisterResolverFactory(std::unique_ptr<ResolverFactory> factory)132 void ResolverRegistry::Builder::RegisterResolverFactory(
133 std::unique_ptr<ResolverFactory> factory) {
134 InitRegistry();
135 g_state->RegisterResolverFactory(std::move(factory));
136 }
137
138 //
139 // ResolverRegistry
140 //
141
LookupResolverFactory(const char * scheme)142 ResolverFactory* ResolverRegistry::LookupResolverFactory(const char* scheme) {
143 GPR_ASSERT(g_state != nullptr);
144 return g_state->LookupResolverFactory(scheme);
145 }
146
IsValidTarget(absl::string_view target)147 bool ResolverRegistry::IsValidTarget(absl::string_view target) {
148 URI uri;
149 std::string canonical_target;
150 ResolverFactory* factory =
151 g_state->FindResolverFactory(target, &uri, &canonical_target);
152 return factory == nullptr ? false : factory->IsValidUri(uri);
153 }
154
CreateResolver(const char * target,const grpc_channel_args * args,grpc_pollset_set * pollset_set,std::shared_ptr<WorkSerializer> work_serializer,std::unique_ptr<Resolver::ResultHandler> result_handler)155 OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
156 const char* target, const grpc_channel_args* args,
157 grpc_pollset_set* pollset_set,
158 std::shared_ptr<WorkSerializer> work_serializer,
159 std::unique_ptr<Resolver::ResultHandler> result_handler) {
160 GPR_ASSERT(g_state != nullptr);
161 std::string canonical_target;
162 ResolverArgs resolver_args;
163 ResolverFactory* factory = g_state->FindResolverFactory(
164 target, &resolver_args.uri, &canonical_target);
165 resolver_args.args = args;
166 resolver_args.pollset_set = pollset_set;
167 resolver_args.work_serializer = std::move(work_serializer);
168 resolver_args.result_handler = std::move(result_handler);
169 OrphanablePtr<Resolver> resolver =
170 factory == nullptr ? nullptr
171 : factory->CreateResolver(std::move(resolver_args));
172 return resolver;
173 }
174
GetDefaultAuthority(absl::string_view target)175 std::string ResolverRegistry::GetDefaultAuthority(absl::string_view target) {
176 GPR_ASSERT(g_state != nullptr);
177 URI uri;
178 std::string canonical_target;
179 ResolverFactory* factory =
180 g_state->FindResolverFactory(target, &uri, &canonical_target);
181 std::string authority =
182 factory == nullptr ? "" : factory->GetDefaultAuthority(uri);
183 return authority;
184 }
185
AddDefaultPrefixIfNeeded(const char * target)186 grpc_core::UniquePtr<char> ResolverRegistry::AddDefaultPrefixIfNeeded(
187 const char* target) {
188 GPR_ASSERT(g_state != nullptr);
189 URI uri;
190 std::string canonical_target;
191 g_state->FindResolverFactory(target, &uri, &canonical_target);
192 return grpc_core::UniquePtr<char>(canonical_target.empty()
193 ? gpr_strdup(target)
194 : gpr_strdup(canonical_target.c_str()));
195 }
196
197 } // namespace grpc_core
198