1 /*
2  *
3  * Copyright 2019 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 #include "src/core/ext/filters/client_channel/xds/xds_client.h"
23 
24 namespace grpc_core {
25 
26 TraceFlag grpc_xds_resolver_trace(false, "xds_resolver");
27 
28 namespace {
29 
30 //
31 // XdsResolver
32 //
33 
34 class XdsResolver : public Resolver {
35  public:
XdsResolver(ResolverArgs args)36   explicit XdsResolver(ResolverArgs args)
37       : Resolver(std::move(args.work_serializer),
38                  std::move(args.result_handler)),
39         args_(grpc_channel_args_copy(args.args)),
40         interested_parties_(args.pollset_set) {
41     char* path = args.uri->path;
42     if (path[0] == '/') ++path;
43     server_name_ = path;
44     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
45       gpr_log(GPR_INFO, "[xds_resolver %p] created for server name %s", this,
46               server_name_.c_str());
47     }
48   }
49 
~XdsResolver()50   ~XdsResolver() override {
51     grpc_channel_args_destroy(args_);
52     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
53       gpr_log(GPR_INFO, "[xds_resolver %p] destroyed", this);
54     }
55   }
56 
57   void StartLocked() override;
58 
ShutdownLocked()59   void ShutdownLocked() override {
60     if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
61       gpr_log(GPR_INFO, "[xds_resolver %p] shutting down", this);
62     }
63     xds_client_.reset();
64   }
65 
66  private:
67   class ServiceConfigWatcher : public XdsClient::ServiceConfigWatcherInterface {
68    public:
ServiceConfigWatcher(RefCountedPtr<XdsResolver> resolver)69     explicit ServiceConfigWatcher(RefCountedPtr<XdsResolver> resolver)
70         : resolver_(std::move(resolver)) {}
71     void OnServiceConfigChanged(
72         RefCountedPtr<ServiceConfig> service_config) override;
73     void OnError(grpc_error* error) override;
74     void OnResourceDoesNotExist() override;
75 
76    private:
77     RefCountedPtr<XdsResolver> resolver_;
78   };
79 
80   std::string server_name_;
81   const grpc_channel_args* args_;
82   grpc_pollset_set* interested_parties_;
83   OrphanablePtr<XdsClient> xds_client_;
84 };
85 
OnServiceConfigChanged(RefCountedPtr<ServiceConfig> service_config)86 void XdsResolver::ServiceConfigWatcher::OnServiceConfigChanged(
87     RefCountedPtr<ServiceConfig> service_config) {
88   if (resolver_->xds_client_ == nullptr) return;
89   if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
90     gpr_log(GPR_INFO, "[xds_resolver %p] received updated service config: %s",
91             resolver_.get(), service_config->json_string().c_str());
92   }
93   grpc_arg xds_client_arg = resolver_->xds_client_->MakeChannelArg();
94   Result result;
95   result.args =
96       grpc_channel_args_copy_and_add(resolver_->args_, &xds_client_arg, 1);
97   result.service_config = std::move(service_config);
98   resolver_->result_handler()->ReturnResult(std::move(result));
99 }
100 
OnError(grpc_error * error)101 void XdsResolver::ServiceConfigWatcher::OnError(grpc_error* error) {
102   if (resolver_->xds_client_ == nullptr) return;
103   gpr_log(GPR_ERROR, "[xds_resolver %p] received error: %s", resolver_.get(),
104           grpc_error_string(error));
105   grpc_arg xds_client_arg = resolver_->xds_client_->MakeChannelArg();
106   Result result;
107   result.args =
108       grpc_channel_args_copy_and_add(resolver_->args_, &xds_client_arg, 1);
109   result.service_config_error = error;
110   resolver_->result_handler()->ReturnResult(std::move(result));
111 }
112 
OnResourceDoesNotExist()113 void XdsResolver::ServiceConfigWatcher::OnResourceDoesNotExist() {
114   if (resolver_->xds_client_ == nullptr) return;
115   gpr_log(GPR_ERROR,
116           "[xds_resolver %p] LDS/RDS resource does not exist -- returning "
117           "empty service config",
118           resolver_.get());
119   Result result;
120   result.service_config =
121       ServiceConfig::Create("{}", &result.service_config_error);
122   GPR_ASSERT(result.service_config != nullptr);
123   result.args = grpc_channel_args_copy(resolver_->args_);
124   resolver_->result_handler()->ReturnResult(std::move(result));
125 }
126 
StartLocked()127 void XdsResolver::StartLocked() {
128   grpc_error* error = GRPC_ERROR_NONE;
129   xds_client_ = MakeOrphanable<XdsClient>(
130       work_serializer(), interested_parties_, server_name_,
131       absl::make_unique<ServiceConfigWatcher>(Ref()), *args_, &error);
132   if (error != GRPC_ERROR_NONE) {
133     gpr_log(GPR_ERROR,
134             "Failed to create xds client -- channel will remain in "
135             "TRANSIENT_FAILURE: %s",
136             grpc_error_string(error));
137     result_handler()->ReturnError(error);
138   }
139 }
140 
141 //
142 // Factory
143 //
144 
145 class XdsResolverFactory : public ResolverFactory {
146  public:
XdsResolverFactory(const char * scheme)147   explicit XdsResolverFactory(const char* scheme) : scheme_(scheme) {}
148 
IsValidUri(const grpc_uri * uri) const149   bool IsValidUri(const grpc_uri* uri) const override {
150     if (GPR_UNLIKELY(0 != strcmp(uri->authority, ""))) {
151       gpr_log(GPR_ERROR, "URI authority not supported");
152       return false;
153     }
154     return true;
155   }
156 
CreateResolver(ResolverArgs args) const157   OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
158     if (!IsValidUri(args.uri)) return nullptr;
159     return MakeOrphanable<XdsResolver>(std::move(args));
160   }
161 
scheme() const162   const char* scheme() const override { return scheme_; }
163 
164  private:
165   const char* scheme_;
166 };
167 
168 constexpr char kXdsScheme[] = "xds";
169 constexpr char kXdsExperimentalScheme[] = "xds-experimental";
170 
171 }  // namespace
172 
173 }  // namespace grpc_core
174 
grpc_resolver_xds_init()175 void grpc_resolver_xds_init() {
176   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
177       absl::make_unique<grpc_core::XdsResolverFactory>(grpc_core::kXdsScheme));
178   // TODO(roth): Remov this in the 1.31 release.
179   grpc_core::ResolverRegistry::Builder::RegisterResolverFactory(
180       absl::make_unique<grpc_core::XdsResolverFactory>(
181           grpc_core::kXdsExperimentalScheme));
182 }
183 
grpc_resolver_xds_shutdown()184 void grpc_resolver_xds_shutdown() {}
185