• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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