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 <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27 #include <grpc/support/string_util.h>
28
29 namespace grpc_core {
30
31 namespace {
32
33 class RegistryState {
34 public:
RegistryState()35 RegistryState() : default_prefix_(gpr_strdup("dns:///")) {}
36
SetDefaultPrefix(const char * default_resolver_prefix)37 void SetDefaultPrefix(const char* default_resolver_prefix) {
38 GPR_ASSERT(default_resolver_prefix != nullptr);
39 GPR_ASSERT(*default_resolver_prefix != '\0');
40 default_prefix_.reset(gpr_strdup(default_resolver_prefix));
41 }
42
RegisterResolverFactory(UniquePtr<ResolverFactory> factory)43 void RegisterResolverFactory(UniquePtr<ResolverFactory> factory) {
44 for (size_t i = 0; i < factories_.size(); ++i) {
45 GPR_ASSERT(strcmp(factories_[i]->scheme(), factory->scheme()) != 0);
46 }
47 factories_.push_back(std::move(factory));
48 }
49
LookupResolverFactory(const char * scheme) const50 ResolverFactory* LookupResolverFactory(const char* scheme) const {
51 for (size_t i = 0; i < factories_.size(); ++i) {
52 if (strcmp(scheme, factories_[i]->scheme()) == 0) {
53 return factories_[i].get();
54 }
55 }
56 return nullptr;
57 }
58
59 // Returns the factory for the scheme of \a target. If \a target does
60 // not parse as a URI, prepends \a default_prefix_ and tries again.
61 // If URI parsing is successful (in either attempt), sets \a uri to
62 // point to the parsed URI.
63 // If \a default_prefix_ needs to be prepended, sets \a canonical_target
64 // to the canonical target string.
FindResolverFactory(const char * target,grpc_uri ** uri,char ** canonical_target) const65 ResolverFactory* FindResolverFactory(const char* target, grpc_uri** uri,
66 char** canonical_target) const {
67 GPR_ASSERT(uri != nullptr);
68 *uri = grpc_uri_parse(target, 1);
69 ResolverFactory* factory =
70 *uri == nullptr ? nullptr : LookupResolverFactory((*uri)->scheme);
71 if (factory == nullptr) {
72 grpc_uri_destroy(*uri);
73 gpr_asprintf(canonical_target, "%s%s", default_prefix_.get(), target);
74 *uri = grpc_uri_parse(*canonical_target, 1);
75 factory =
76 *uri == nullptr ? nullptr : LookupResolverFactory((*uri)->scheme);
77 if (factory == nullptr) {
78 grpc_uri_destroy(grpc_uri_parse(target, 0));
79 grpc_uri_destroy(grpc_uri_parse(*canonical_target, 0));
80 gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", target,
81 *canonical_target);
82 }
83 }
84 return factory;
85 }
86
87 private:
88 // We currently support 10 factories without doing additional
89 // allocation. This number could be raised if there is a case where
90 // more factories are needed and the additional allocations are
91 // hurting performance (which is unlikely, since these allocations
92 // only occur at gRPC initialization time).
93 InlinedVector<UniquePtr<ResolverFactory>, 10> factories_;
94 UniquePtr<char> default_prefix_;
95 };
96
97 static RegistryState* g_state = nullptr;
98
99 } // namespace
100
101 //
102 // ResolverRegistry::Builder
103 //
104
InitRegistry()105 void ResolverRegistry::Builder::InitRegistry() {
106 if (g_state == nullptr) g_state = New<RegistryState>();
107 }
108
ShutdownRegistry()109 void ResolverRegistry::Builder::ShutdownRegistry() {
110 Delete(g_state);
111 g_state = nullptr;
112 }
113
SetDefaultPrefix(const char * default_resolver_prefix)114 void ResolverRegistry::Builder::SetDefaultPrefix(
115 const char* default_resolver_prefix) {
116 InitRegistry();
117 g_state->SetDefaultPrefix(default_resolver_prefix);
118 }
119
RegisterResolverFactory(UniquePtr<ResolverFactory> factory)120 void ResolverRegistry::Builder::RegisterResolverFactory(
121 UniquePtr<ResolverFactory> factory) {
122 InitRegistry();
123 g_state->RegisterResolverFactory(std::move(factory));
124 }
125
126 //
127 // ResolverRegistry
128 //
129
LookupResolverFactory(const char * scheme)130 ResolverFactory* ResolverRegistry::LookupResolverFactory(const char* scheme) {
131 GPR_ASSERT(g_state != nullptr);
132 return g_state->LookupResolverFactory(scheme);
133 }
134
CreateResolver(const char * target,const grpc_channel_args * args,grpc_pollset_set * pollset_set,grpc_combiner * combiner)135 OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
136 const char* target, const grpc_channel_args* args,
137 grpc_pollset_set* pollset_set, grpc_combiner* combiner) {
138 GPR_ASSERT(g_state != nullptr);
139 grpc_uri* uri = nullptr;
140 char* canonical_target = nullptr;
141 ResolverFactory* factory =
142 g_state->FindResolverFactory(target, &uri, &canonical_target);
143 ResolverArgs resolver_args;
144 resolver_args.uri = uri;
145 resolver_args.args = args;
146 resolver_args.pollset_set = pollset_set;
147 resolver_args.combiner = combiner;
148 OrphanablePtr<Resolver> resolver =
149 factory == nullptr ? nullptr : factory->CreateResolver(resolver_args);
150 grpc_uri_destroy(uri);
151 gpr_free(canonical_target);
152 return resolver;
153 }
154
GetDefaultAuthority(const char * target)155 UniquePtr<char> ResolverRegistry::GetDefaultAuthority(const char* target) {
156 GPR_ASSERT(g_state != nullptr);
157 grpc_uri* uri = nullptr;
158 char* canonical_target = nullptr;
159 ResolverFactory* factory =
160 g_state->FindResolverFactory(target, &uri, &canonical_target);
161 UniquePtr<char> authority =
162 factory == nullptr ? nullptr : factory->GetDefaultAuthority(uri);
163 grpc_uri_destroy(uri);
164 gpr_free(canonical_target);
165 return authority;
166 }
167
AddDefaultPrefixIfNeeded(const char * target)168 UniquePtr<char> ResolverRegistry::AddDefaultPrefixIfNeeded(const char* target) {
169 GPR_ASSERT(g_state != nullptr);
170 grpc_uri* uri = nullptr;
171 char* canonical_target = nullptr;
172 g_state->FindResolverFactory(target, &uri, &canonical_target);
173 grpc_uri_destroy(uri);
174 return UniquePtr<char>(canonical_target == nullptr ? gpr_strdup(target)
175 : canonical_target);
176 }
177
178 } // namespace grpc_core
179