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