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/lib/surface/channel.h"
22 
23 #include <inttypes.h>
24 #include <string.h>
25 
26 #include <algorithm>
27 #include <atomic>
28 #include <functional>
29 #include <memory>
30 
31 #include "absl/status/status.h"
32 
33 #include <grpc/compression.h>
34 #include <grpc/grpc.h>
35 #include <grpc/support/alloc.h>
36 #include <grpc/support/log.h>
37 #include <grpc/support/time.h>
38 
39 #include "src/core/lib/channel/channel_args.h"
40 #include "src/core/lib/channel/channel_stack.h"
41 #include "src/core/lib/channel/channel_stack_builder_impl.h"
42 #include "src/core/lib/channel/channel_trace.h"
43 #include "src/core/lib/channel/channelz.h"
44 #include "src/core/lib/config/core_configuration.h"
45 #include "src/core/lib/debug/stats.h"
46 #include "src/core/lib/debug/stats_data.h"
47 #include "src/core/lib/debug/trace.h"
48 #include "src/core/lib/gpr/useful.h"
49 #include "src/core/lib/gprpp/manual_constructor.h"
50 #include "src/core/lib/gprpp/ref_counted_ptr.h"
51 #include "src/core/lib/iomgr/error.h"
52 #include "src/core/lib/iomgr/exec_ctx.h"
53 #include "src/core/lib/resource_quota/memory_quota.h"
54 #include "src/core/lib/resource_quota/resource_quota.h"
55 #include "src/core/lib/surface/api_trace.h"
56 #include "src/core/lib/surface/call.h"
57 #include "src/core/lib/surface/channel_init.h"
58 #include "src/core/lib/surface/channel_stack_type.h"
59 #include "src/core/lib/surface/init_internally.h"
60 #include "src/core/lib/transport/transport.h"
61 
62 // IWYU pragma: no_include <type_traits>
63 
64 namespace grpc_core {
65 
Channel(bool is_client,bool is_promising,std::string target,const ChannelArgs & channel_args,grpc_compression_options compression_options,RefCountedPtr<grpc_channel_stack> channel_stack)66 Channel::Channel(bool is_client, bool is_promising, std::string target,
67                  const ChannelArgs& channel_args,
68                  grpc_compression_options compression_options,
69                  RefCountedPtr<grpc_channel_stack> channel_stack)
70     : is_client_(is_client),
71       is_promising_(is_promising),
72       compression_options_(compression_options),
73       call_size_estimate_(channel_stack->call_stack_size +
74                           grpc_call_get_initial_size_estimate()),
75       channelz_node_(channel_args.GetObjectRef<channelz::ChannelNode>()),
76       allocator_(channel_args.GetObject<ResourceQuota>()
77                      ->memory_quota()
78                      ->CreateMemoryOwner(target)),
79       target_(std::move(target)),
80       channel_stack_(std::move(channel_stack)) {
81   // We need to make sure that grpc_shutdown() does not shut things down
82   // until after the channel is destroyed.  However, the channel may not
83   // actually be destroyed by the time grpc_channel_destroy() returns,
84   // since there may be other existing refs to the channel.  If those
85   // refs are held by things that are visible to the wrapped language
86   // (such as outstanding calls on the channel), then the wrapped
87   // language can be responsible for making sure that grpc_shutdown()
88   // does not run until after those refs are released.  However, the
89   // channel may also have refs to itself held internally for various
90   // things that need to be cleaned up at channel destruction (e.g.,
91   // LB policies, subchannels, etc), and because these refs are not
92   // visible to the wrapped language, it cannot be responsible for
93   // deferring grpc_shutdown() until after they are released.  To
94   // accommodate that, we call grpc_init() here and then call
95   // grpc_shutdown() when the channel is actually destroyed, thus
96   // ensuring that shutdown is deferred until that point.
97   InitInternally();
98   auto channelz_node = channelz_node_;
99   *channel_stack_->on_destroy = [channelz_node]() {
100     if (channelz_node != nullptr) {
101       channelz_node->AddTraceEvent(
102           channelz::ChannelTrace::Severity::Info,
103           grpc_slice_from_static_string("Channel destroyed"));
104     }
105     ShutdownInternally();
106   };
107 }
108 
CreateWithBuilder(ChannelStackBuilder * builder)109 absl::StatusOr<RefCountedPtr<Channel>> Channel::CreateWithBuilder(
110     ChannelStackBuilder* builder) {
111   auto channel_args = builder->channel_args();
112   if (builder->channel_stack_type() == GRPC_SERVER_CHANNEL) {
113     global_stats().IncrementServerChannelsCreated();
114   } else {
115     global_stats().IncrementClientChannelsCreated();
116   }
117   absl::StatusOr<RefCountedPtr<grpc_channel_stack>> r = builder->Build();
118   if (!r.ok()) {
119     auto status = r.status();
120     gpr_log(GPR_ERROR, "channel stack builder failed: %s",
121             status.ToString().c_str());
122     return status;
123   }
124 
125   grpc_compression_options compression_options;
126   grpc_compression_options_init(&compression_options);
127   auto default_level =
128       channel_args.GetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL);
129   if (default_level.has_value()) {
130     compression_options.default_level.is_set = true;
131     compression_options.default_level.level = Clamp(
132         static_cast<grpc_compression_level>(*default_level),
133         GRPC_COMPRESS_LEVEL_NONE,
134         static_cast<grpc_compression_level>(GRPC_COMPRESS_LEVEL_COUNT - 1));
135   }
136   auto default_algorithm =
137       channel_args.GetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM);
138   if (default_algorithm.has_value()) {
139     compression_options.default_algorithm.is_set = true;
140     compression_options.default_algorithm.algorithm =
141         Clamp(static_cast<grpc_compression_algorithm>(*default_algorithm),
142               GRPC_COMPRESS_NONE,
143               static_cast<grpc_compression_algorithm>(
144                   GRPC_COMPRESS_ALGORITHMS_COUNT - 1));
145   }
146   auto enabled_algorithms_bitset =
147       channel_args.GetInt(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET);
148   if (enabled_algorithms_bitset.has_value()) {
149     compression_options.enabled_algorithms_bitset =
150         *enabled_algorithms_bitset | 1 /* always support no compression */;
151   }
152 
153   return RefCountedPtr<Channel>(new Channel(
154       grpc_channel_stack_type_is_client(builder->channel_stack_type()),
155       builder->IsPromising(), std::string(builder->target()), channel_args,
156       compression_options, std::move(*r)));
157 }
158 
159 namespace {
160 
channelz_node_copy(void * p)161 void* channelz_node_copy(void* p) {
162   channelz::ChannelNode* node = static_cast<channelz::ChannelNode*>(p);
163   node->Ref().release();
164   return p;
165 }
channelz_node_destroy(void * p)166 void channelz_node_destroy(void* p) {
167   channelz::ChannelNode* node = static_cast<channelz::ChannelNode*>(p);
168   node->Unref();
169 }
channelz_node_cmp(void * p1,void * p2)170 int channelz_node_cmp(void* p1, void* p2) { return QsortCompare(p1, p2); }
171 const grpc_arg_pointer_vtable channelz_node_arg_vtable = {
172     channelz_node_copy, channelz_node_destroy, channelz_node_cmp};
173 }  // namespace
174 
Create(const char * target,ChannelArgs args,grpc_channel_stack_type channel_stack_type,grpc_transport * optional_transport)175 absl::StatusOr<RefCountedPtr<Channel>> Channel::Create(
176     const char* target, ChannelArgs args,
177     grpc_channel_stack_type channel_stack_type,
178     grpc_transport* optional_transport) {
179   if (!args.GetString(GRPC_ARG_DEFAULT_AUTHORITY).has_value()) {
180     auto ssl_override = args.GetString(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
181     if (ssl_override.has_value()) {
182       args = args.Set(GRPC_ARG_DEFAULT_AUTHORITY,
183                       std::string(ssl_override.value()));
184     }
185   }
186   if (grpc_channel_stack_type_is_client(channel_stack_type)) {
187     auto channel_args_mutator =
188         grpc_channel_args_get_client_channel_creation_mutator();
189     if (channel_args_mutator != nullptr) {
190       args = channel_args_mutator(target, args, channel_stack_type);
191     }
192   }
193   // We only need to do this for clients here. For servers, this will be
194   // done in src/core/lib/surface/server.cc.
195   if (grpc_channel_stack_type_is_client(channel_stack_type)) {
196     // Check whether channelz is enabled.
197     if (args.GetBool(GRPC_ARG_ENABLE_CHANNELZ)
198             .value_or(GRPC_ENABLE_CHANNELZ_DEFAULT)) {
199       // Get parameters needed to create the channelz node.
200       const size_t channel_tracer_max_memory = std::max(
201           0,
202           args.GetInt(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE)
203               .value_or(GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT));
204       const bool is_internal_channel =
205           args.GetBool(GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL).value_or(false);
206       // Create the channelz node.
207       std::string channelz_node_target{target == nullptr ? "unknown" : target};
208       RefCountedPtr<channelz::ChannelNode> channelz_node =
209           MakeRefCounted<channelz::ChannelNode>(channelz_node_target,
210                                                 channel_tracer_max_memory,
211                                                 is_internal_channel);
212       channelz_node->AddTraceEvent(
213           channelz::ChannelTrace::Severity::Info,
214           grpc_slice_from_static_string("Channel created"));
215       // Add channelz node to channel args.
216       // We remove the is_internal_channel arg, since we no longer need it.
217       args = args.Remove(GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL)
218                  .Set(GRPC_ARG_CHANNELZ_CHANNEL_NODE,
219                       ChannelArgs::Pointer(channelz_node.release(),
220                                            &channelz_node_arg_vtable));
221     }
222   }
223   ChannelStackBuilderImpl builder(
224       grpc_channel_stack_type_string(channel_stack_type), channel_stack_type,
225       args);
226   builder.SetTarget(target).SetTransport(optional_transport);
227   if (!CoreConfiguration::Get().channel_init().CreateStack(&builder)) {
228     return nullptr;
229   }
230   return CreateWithBuilder(&builder);
231 }
232 
UpdateCallSizeEstimate(size_t size)233 void Channel::UpdateCallSizeEstimate(size_t size) {
234   size_t cur = call_size_estimate_.load(std::memory_order_relaxed);
235   if (cur < size) {
236     // size grew: update estimate
237     call_size_estimate_.compare_exchange_weak(
238         cur, size, std::memory_order_relaxed, std::memory_order_relaxed);
239     // if we lose: never mind, something else will likely update soon enough
240   } else if (cur == size) {
241     // no change: holding pattern
242   } else if (cur > 0) {
243     // size shrank: decrease estimate
244     call_size_estimate_.compare_exchange_weak(
245         cur, std::min(cur - 1, (255 * cur + size) / 256),
246         std::memory_order_relaxed, std::memory_order_relaxed);
247     // if we lose: never mind, something else will likely update soon enough
248   }
249 }
250 
251 }  // namespace grpc_core
252 
grpc_channel_get_target(grpc_channel * channel)253 char* grpc_channel_get_target(grpc_channel* channel) {
254   GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
255   auto target = grpc_core::Channel::FromC(channel)->target();
256   char* buffer = static_cast<char*>(gpr_zalloc(target.size() + 1));
257   memcpy(buffer, target.data(), target.size());
258   return buffer;
259 }
260 
grpc_channel_get_info(grpc_channel * channel,const grpc_channel_info * channel_info)261 void grpc_channel_get_info(grpc_channel* channel,
262                            const grpc_channel_info* channel_info) {
263   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
264   grpc_core::ExecCtx exec_ctx;
265   grpc_channel_element* elem = grpc_channel_stack_element(
266       grpc_core::Channel::FromC(channel)->channel_stack(), 0);
267   elem->filter->get_channel_info(elem, channel_info);
268 }
269 
grpc_channel_reset_connect_backoff(grpc_channel * channel)270 void grpc_channel_reset_connect_backoff(grpc_channel* channel) {
271   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
272   grpc_core::ExecCtx exec_ctx;
273   GRPC_API_TRACE("grpc_channel_reset_connect_backoff(channel=%p)", 1,
274                  (channel));
275   grpc_transport_op* op = grpc_make_transport_op(nullptr);
276   op->reset_connect_backoff = true;
277   grpc_channel_element* elem = grpc_channel_stack_element(
278       grpc_core::Channel::FromC(channel)->channel_stack(), 0);
279   elem->filter->start_transport_op(elem, op);
280 }
281 
grpc_channel_create_call_internal(grpc_channel * c_channel,grpc_call * parent_call,uint32_t propagation_mask,grpc_completion_queue * cq,grpc_pollset_set * pollset_set_alternative,grpc_core::Slice path,absl::optional<grpc_core::Slice> authority,grpc_core::Timestamp deadline)282 static grpc_call* grpc_channel_create_call_internal(
283     grpc_channel* c_channel, grpc_call* parent_call, uint32_t propagation_mask,
284     grpc_completion_queue* cq, grpc_pollset_set* pollset_set_alternative,
285     grpc_core::Slice path, absl::optional<grpc_core::Slice> authority,
286     grpc_core::Timestamp deadline) {
287   auto channel = grpc_core::Channel::FromC(c_channel)->Ref();
288   GPR_ASSERT(channel->is_client());
289   GPR_ASSERT(!(cq != nullptr && pollset_set_alternative != nullptr));
290 
291   grpc_call_create_args args;
292   args.channel = std::move(channel);
293   args.server = nullptr;
294   args.parent = parent_call;
295   args.propagation_mask = propagation_mask;
296   args.cq = cq;
297   args.pollset_set_alternative = pollset_set_alternative;
298   args.server_transport_data = nullptr;
299   args.path = std::move(path);
300   args.authority = std::move(authority);
301   args.send_deadline = deadline;
302 
303   grpc_call* call;
304   GRPC_LOG_IF_ERROR("call_create", grpc_call_create(&args, &call));
305   return call;
306 }
307 
grpc_channel_create_call(grpc_channel * channel,grpc_call * parent_call,uint32_t propagation_mask,grpc_completion_queue * completion_queue,grpc_slice method,const grpc_slice * host,gpr_timespec deadline,void * reserved)308 grpc_call* grpc_channel_create_call(grpc_channel* channel,
309                                     grpc_call* parent_call,
310                                     uint32_t propagation_mask,
311                                     grpc_completion_queue* completion_queue,
312                                     grpc_slice method, const grpc_slice* host,
313                                     gpr_timespec deadline, void* reserved) {
314   GPR_ASSERT(!reserved);
315   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
316   grpc_core::ExecCtx exec_ctx;
317   grpc_call* call = grpc_channel_create_call_internal(
318       channel, parent_call, propagation_mask, completion_queue, nullptr,
319       grpc_core::Slice(grpc_core::CSliceRef(method)),
320       host != nullptr
321           ? absl::optional<grpc_core::Slice>(grpc_core::CSliceRef(*host))
322           : absl::nullopt,
323       grpc_core::Timestamp::FromTimespecRoundUp(deadline));
324 
325   return call;
326 }
327 
grpc_channel_create_pollset_set_call(grpc_channel * channel,grpc_call * parent_call,uint32_t propagation_mask,grpc_pollset_set * pollset_set,const grpc_slice & method,const grpc_slice * host,grpc_core::Timestamp deadline,void * reserved)328 grpc_call* grpc_channel_create_pollset_set_call(
329     grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
330     grpc_pollset_set* pollset_set, const grpc_slice& method,
331     const grpc_slice* host, grpc_core::Timestamp deadline, void* reserved) {
332   GPR_ASSERT(!reserved);
333   return grpc_channel_create_call_internal(
334       channel, parent_call, propagation_mask, nullptr, pollset_set,
335       grpc_core::Slice(method),
336       host != nullptr
337           ? absl::optional<grpc_core::Slice>(grpc_core::CSliceRef(*host))
338           : absl::nullopt,
339       deadline);
340 }
341 
342 namespace grpc_core {
343 
RegisteredCall(const char * method_arg,const char * host_arg)344 RegisteredCall::RegisteredCall(const char* method_arg, const char* host_arg) {
345   path = Slice::FromCopiedString(method_arg);
346   if (host_arg != nullptr && host_arg[0] != 0) {
347     authority = Slice::FromCopiedString(host_arg);
348   }
349 }
350 
RegisteredCall(const RegisteredCall & other)351 RegisteredCall::RegisteredCall(const RegisteredCall& other)
352     : path(other.path.Ref()) {
353   if (other.authority.has_value()) {
354     authority = other.authority->Ref();
355   }
356 }
357 
~RegisteredCall()358 RegisteredCall::~RegisteredCall() {}
359 
360 }  // namespace grpc_core
361 
grpc_channel_register_call(grpc_channel * channel,const char * method,const char * host,void * reserved)362 void* grpc_channel_register_call(grpc_channel* channel, const char* method,
363                                  const char* host, void* reserved) {
364   GRPC_API_TRACE(
365       "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
366       4, (channel, method, host, reserved));
367   GPR_ASSERT(!reserved);
368   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
369   grpc_core::ExecCtx exec_ctx;
370   return grpc_core::Channel::FromC(channel)->RegisterCall(method, host);
371 }
372 
373 namespace grpc_core {
374 
RegisterCall(const char * method,const char * host)375 RegisteredCall* Channel::RegisterCall(const char* method, const char* host) {
376   MutexLock lock(&registration_table_.mu);
377   registration_table_.method_registration_attempts++;
378   auto key = std::make_pair(std::string(host != nullptr ? host : ""),
379                             std::string(method != nullptr ? method : ""));
380   auto rc_posn = registration_table_.map.find(key);
381   if (rc_posn != registration_table_.map.end()) {
382     return &rc_posn->second;
383   }
384   auto insertion_result = registration_table_.map.insert(
385       {std::move(key), RegisteredCall(method, host)});
386   return &insertion_result.first->second;
387 }
388 
389 }  // namespace grpc_core
390 
grpc_channel_create_registered_call(grpc_channel * channel,grpc_call * parent_call,uint32_t propagation_mask,grpc_completion_queue * completion_queue,void * registered_call_handle,gpr_timespec deadline,void * reserved)391 grpc_call* grpc_channel_create_registered_call(
392     grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
393     grpc_completion_queue* completion_queue, void* registered_call_handle,
394     gpr_timespec deadline, void* reserved) {
395   grpc_core::RegisteredCall* rc =
396       static_cast<grpc_core::RegisteredCall*>(registered_call_handle);
397   GRPC_API_TRACE(
398       "grpc_channel_create_registered_call("
399       "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
400       "registered_call_handle=%p, "
401       "deadline=gpr_timespec { tv_sec: %" PRId64
402       ", tv_nsec: %d, clock_type: %d }, "
403       "reserved=%p)",
404       9,
405       (channel, parent_call, (unsigned)propagation_mask, completion_queue,
406        registered_call_handle, deadline.tv_sec, deadline.tv_nsec,
407        (int)deadline.clock_type, reserved));
408   GPR_ASSERT(!reserved);
409   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
410   grpc_core::ExecCtx exec_ctx;
411   grpc_call* call = grpc_channel_create_call_internal(
412       channel, parent_call, propagation_mask, completion_queue, nullptr,
413       rc->path.Ref(),
414       rc->authority.has_value()
415           ? absl::optional<grpc_core::Slice>(rc->authority->Ref())
416           : absl::nullopt,
417       grpc_core::Timestamp::FromTimespecRoundUp(deadline));
418 
419   return call;
420 }
421 
grpc_channel_destroy_internal(grpc_channel * c_channel)422 void grpc_channel_destroy_internal(grpc_channel* c_channel) {
423   grpc_core::RefCountedPtr<grpc_core::Channel> channel(
424       grpc_core::Channel::FromC(c_channel));
425   grpc_transport_op* op = grpc_make_transport_op(nullptr);
426   grpc_channel_element* elem;
427   GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (c_channel));
428   op->disconnect_with_error = GRPC_ERROR_CREATE("Channel Destroyed");
429   elem = grpc_channel_stack_element(channel->channel_stack(), 0);
430   elem->filter->start_transport_op(elem, op);
431 }
432 
grpc_channel_destroy(grpc_channel * channel)433 void grpc_channel_destroy(grpc_channel* channel) {
434   grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
435   grpc_core::ExecCtx exec_ctx;
436   grpc_channel_destroy_internal(channel);
437 }
438