Imported Upstream version 1.22.0
[platform/upstream/grpc.git] / src / core / lib / surface / channel.cc
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 <limits.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <grpc/compression.h>
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.h>
31 #include <grpc/support/string_util.h>
32
33 #include "src/core/lib/channel/channel_args.h"
34 #include "src/core/lib/channel/channel_trace.h"
35 #include "src/core/lib/channel/channelz.h"
36 #include "src/core/lib/channel/channelz_registry.h"
37 #include "src/core/lib/debug/stats.h"
38 #include "src/core/lib/gpr/string.h"
39 #include "src/core/lib/gprpp/manual_constructor.h"
40 #include "src/core/lib/gprpp/memory.h"
41 #include "src/core/lib/gprpp/ref_counted_ptr.h"
42 #include "src/core/lib/iomgr/iomgr.h"
43 #include "src/core/lib/iomgr/resource_quota.h"
44 #include "src/core/lib/slice/slice_internal.h"
45 #include "src/core/lib/surface/api_trace.h"
46 #include "src/core/lib/surface/call.h"
47 #include "src/core/lib/surface/channel_init.h"
48 #include "src/core/lib/transport/static_metadata.h"
49
50 /** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS.
51  *  Avoids needing to take a metadata context lock for sending status
52  *  if the status code is <= NUM_CACHED_STATUS_ELEMS.
53  *  Sized to allow the most commonly used codes to fit in
54  *  (OK, Cancelled, Unknown). */
55 #define NUM_CACHED_STATUS_ELEMS 3
56
57 typedef struct registered_call {
58   grpc_mdelem path;
59   grpc_mdelem authority;
60   struct registered_call* next;
61 } registered_call;
62
63 static void destroy_channel(void* arg, grpc_error* error);
64
65 grpc_channel* grpc_channel_create_with_builder(
66     grpc_channel_stack_builder* builder,
67     grpc_channel_stack_type channel_stack_type) {
68   char* target = gpr_strdup(grpc_channel_stack_builder_get_target(builder));
69   grpc_channel_args* args = grpc_channel_args_copy(
70       grpc_channel_stack_builder_get_channel_arguments(builder));
71   grpc_resource_user* resource_user =
72       grpc_channel_stack_builder_get_resource_user(builder);
73   grpc_channel* channel;
74   if (channel_stack_type == GRPC_SERVER_CHANNEL) {
75     GRPC_STATS_INC_SERVER_CHANNELS_CREATED();
76   } else {
77     GRPC_STATS_INC_CLIENT_CHANNELS_CREATED();
78   }
79   grpc_error* error = grpc_channel_stack_builder_finish(
80       builder, sizeof(grpc_channel), 1, destroy_channel, nullptr,
81       reinterpret_cast<void**>(&channel));
82   if (error != GRPC_ERROR_NONE) {
83     gpr_log(GPR_ERROR, "channel stack builder failed: %s",
84             grpc_error_string(error));
85     GRPC_ERROR_UNREF(error);
86     gpr_free(target);
87     grpc_channel_args_destroy(args);
88     return channel;
89   }
90   channel->target = target;
91   channel->resource_user = resource_user;
92   channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type);
93   gpr_mu_init(&channel->registered_call_mu);
94   channel->registered_calls = nullptr;
95
96   gpr_atm_no_barrier_store(
97       &channel->call_size_estimate,
98       (gpr_atm)CHANNEL_STACK_FROM_CHANNEL(channel)->call_stack_size +
99           grpc_call_get_initial_size_estimate());
100
101   grpc_compression_options_init(&channel->compression_options);
102   for (size_t i = 0; i < args->num_args; i++) {
103     if (0 ==
104         strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) {
105       channel->compression_options.default_level.is_set = true;
106       channel->compression_options.default_level.level =
107           static_cast<grpc_compression_level>(grpc_channel_arg_get_integer(
108               &args->args[i],
109               {GRPC_COMPRESS_LEVEL_NONE, GRPC_COMPRESS_LEVEL_NONE,
110                GRPC_COMPRESS_LEVEL_COUNT - 1}));
111     } else if (0 == strcmp(args->args[i].key,
112                            GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM)) {
113       channel->compression_options.default_algorithm.is_set = true;
114       channel->compression_options.default_algorithm.algorithm =
115           static_cast<grpc_compression_algorithm>(grpc_channel_arg_get_integer(
116               &args->args[i], {GRPC_COMPRESS_NONE, GRPC_COMPRESS_NONE,
117                                GRPC_COMPRESS_ALGORITHMS_COUNT - 1}));
118     } else if (0 ==
119                strcmp(args->args[i].key,
120                       GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET)) {
121       channel->compression_options.enabled_algorithms_bitset =
122           static_cast<uint32_t>(args->args[i].value.integer) |
123           0x1; /* always support no compression */
124     } else if (0 == strcmp(args->args[i].key, GRPC_ARG_CHANNELZ_CHANNEL_NODE)) {
125       GPR_ASSERT(args->args[i].type == GRPC_ARG_POINTER);
126       GPR_ASSERT(args->args[i].value.pointer.p != nullptr);
127       channel->channelz_node = static_cast<grpc_core::channelz::ChannelNode*>(
128                                    args->args[i].value.pointer.p)
129                                    ->Ref();
130     }
131   }
132
133   grpc_channel_args_destroy(args);
134   return channel;
135 }
136
137 static grpc_core::UniquePtr<char> get_default_authority(
138     const grpc_channel_args* input_args) {
139   bool has_default_authority = false;
140   char* ssl_override = nullptr;
141   grpc_core::UniquePtr<char> default_authority;
142   const size_t num_args = input_args != nullptr ? input_args->num_args : 0;
143   for (size_t i = 0; i < num_args; ++i) {
144     if (0 == strcmp(input_args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
145       has_default_authority = true;
146     } else if (0 == strcmp(input_args->args[i].key,
147                            GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
148       ssl_override = grpc_channel_arg_get_string(&input_args->args[i]);
149     }
150   }
151   if (!has_default_authority && ssl_override != nullptr) {
152     default_authority.reset(gpr_strdup(ssl_override));
153   }
154   return default_authority;
155 }
156
157 static grpc_channel_args* build_channel_args(
158     const grpc_channel_args* input_args, char* default_authority) {
159   grpc_arg new_args[1];
160   size_t num_new_args = 0;
161   if (default_authority != nullptr) {
162     new_args[num_new_args++] = grpc_channel_arg_string_create(
163         const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), default_authority);
164   }
165   return grpc_channel_args_copy_and_add(input_args, new_args, num_new_args);
166 }
167
168 namespace {
169
170 void* channelz_node_copy(void* p) {
171   grpc_core::channelz::ChannelNode* node =
172       static_cast<grpc_core::channelz::ChannelNode*>(p);
173   node->Ref().release();
174   return p;
175 }
176 void channelz_node_destroy(void* p) {
177   grpc_core::channelz::ChannelNode* node =
178       static_cast<grpc_core::channelz::ChannelNode*>(p);
179   node->Unref();
180 }
181 int channelz_node_cmp(void* p1, void* p2) { return GPR_ICMP(p1, p2); }
182 const grpc_arg_pointer_vtable channelz_node_arg_vtable = {
183     channelz_node_copy, channelz_node_destroy, channelz_node_cmp};
184
185 void CreateChannelzNode(grpc_channel_stack_builder* builder) {
186   const grpc_channel_args* args =
187       grpc_channel_stack_builder_get_channel_arguments(builder);
188   // Check whether channelz is enabled.
189   const bool channelz_enabled = grpc_channel_arg_get_bool(
190       grpc_channel_args_find(args, GRPC_ARG_ENABLE_CHANNELZ),
191       GRPC_ENABLE_CHANNELZ_DEFAULT);
192   if (!channelz_enabled) return;
193   // Get parameters needed to create the channelz node.
194   const size_t channel_tracer_max_memory = grpc_channel_arg_get_integer(
195       grpc_channel_args_find(args,
196                              GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE),
197       {GRPC_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE_DEFAULT, 0, INT_MAX});
198   const intptr_t channelz_parent_uuid =
199       grpc_core::channelz::GetParentUuidFromArgs(*args);
200   // Create the channelz node.
201   grpc_core::RefCountedPtr<grpc_core::channelz::ChannelNode> channelz_node =
202       grpc_core::MakeRefCounted<grpc_core::channelz::ChannelNode>(
203           grpc_core::UniquePtr<char>(
204               gpr_strdup(grpc_channel_stack_builder_get_target(builder))),
205           channel_tracer_max_memory, channelz_parent_uuid);
206   channelz_node->AddTraceEvent(
207       grpc_core::channelz::ChannelTrace::Severity::Info,
208       grpc_slice_from_static_string("Channel created"));
209   // Update parent channel node, if any.
210   if (channelz_parent_uuid > 0) {
211     grpc_core::RefCountedPtr<grpc_core::channelz::BaseNode> parent_node =
212         grpc_core::channelz::ChannelzRegistry::Get(channelz_parent_uuid);
213     if (parent_node != nullptr) {
214       grpc_core::channelz::ChannelNode* parent =
215           static_cast<grpc_core::channelz::ChannelNode*>(parent_node.get());
216       parent->AddChildChannel(channelz_node->uuid());
217     }
218   }
219   // Add channelz node to channel args.
220   // We remove the arg for the parent uuid, since we no longer need it.
221   grpc_arg new_arg = grpc_channel_arg_pointer_create(
222       const_cast<char*>(GRPC_ARG_CHANNELZ_CHANNEL_NODE), channelz_node.get(),
223       &channelz_node_arg_vtable);
224   const char* args_to_remove[] = {GRPC_ARG_CHANNELZ_PARENT_UUID};
225   grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
226       args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), &new_arg, 1);
227   grpc_channel_stack_builder_set_channel_arguments(builder, new_args);
228   grpc_channel_args_destroy(new_args);
229 }
230
231 }  // namespace
232
233 grpc_channel* grpc_channel_create(const char* target,
234                                   const grpc_channel_args* input_args,
235                                   grpc_channel_stack_type channel_stack_type,
236                                   grpc_transport* optional_transport,
237                                   grpc_resource_user* resource_user) {
238   grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
239   const grpc_core::UniquePtr<char> default_authority =
240       get_default_authority(input_args);
241   grpc_channel_args* args =
242       build_channel_args(input_args, default_authority.get());
243   grpc_channel_stack_builder_set_channel_arguments(builder, args);
244   grpc_channel_args_destroy(args);
245   grpc_channel_stack_builder_set_target(builder, target);
246   grpc_channel_stack_builder_set_transport(builder, optional_transport);
247   grpc_channel_stack_builder_set_resource_user(builder, resource_user);
248   if (!grpc_channel_init_create_stack(builder, channel_stack_type)) {
249     grpc_channel_stack_builder_destroy(builder);
250     if (resource_user != nullptr) {
251       grpc_resource_user_free(resource_user, GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
252     }
253     return nullptr;
254   }
255   // We only need to do this for clients here. For servers, this will be
256   // done in src/core/lib/surface/server.cc.
257   if (grpc_channel_stack_type_is_client(channel_stack_type)) {
258     CreateChannelzNode(builder);
259   }
260   return grpc_channel_create_with_builder(builder, channel_stack_type);
261 }
262
263 size_t grpc_channel_get_call_size_estimate(grpc_channel* channel) {
264 #define ROUND_UP_SIZE 256
265   /* We round up our current estimate to the NEXT value of ROUND_UP_SIZE.
266      This ensures:
267       1. a consistent size allocation when our estimate is drifting slowly
268          (which is common) - which tends to help most allocators reuse memory
269       2. a small amount of allowed growth over the estimate without hitting
270          the arena size doubling case, reducing overall memory usage */
271   return (static_cast<size_t>(
272               gpr_atm_no_barrier_load(&channel->call_size_estimate)) +
273           2 * ROUND_UP_SIZE) &
274          ~static_cast<size_t>(ROUND_UP_SIZE - 1);
275 }
276
277 void grpc_channel_update_call_size_estimate(grpc_channel* channel,
278                                             size_t size) {
279   size_t cur = static_cast<size_t>(
280       gpr_atm_no_barrier_load(&channel->call_size_estimate));
281   if (cur < size) {
282     /* size grew: update estimate */
283     gpr_atm_no_barrier_cas(&channel->call_size_estimate,
284                            static_cast<gpr_atm>(cur),
285                            static_cast<gpr_atm>(size));
286     /* if we lose: never mind, something else will likely update soon enough */
287   } else if (cur == size) {
288     /* no change: holding pattern */
289   } else if (cur > 0) {
290     /* size shrank: decrease estimate */
291     gpr_atm_no_barrier_cas(
292         &channel->call_size_estimate, static_cast<gpr_atm>(cur),
293         static_cast<gpr_atm>(GPR_MIN(cur - 1, (255 * cur + size) / 256)));
294     /* if we lose: never mind, something else will likely update soon enough */
295   }
296 }
297
298 char* grpc_channel_get_target(grpc_channel* channel) {
299   GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel));
300   return gpr_strdup(channel->target);
301 }
302
303 void grpc_channel_get_info(grpc_channel* channel,
304                            const grpc_channel_info* channel_info) {
305   grpc_core::ExecCtx exec_ctx;
306   grpc_channel_element* elem =
307       grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
308   elem->filter->get_channel_info(elem, channel_info);
309 }
310
311 void grpc_channel_reset_connect_backoff(grpc_channel* channel) {
312   grpc_core::ExecCtx exec_ctx;
313   GRPC_API_TRACE("grpc_channel_reset_connect_backoff(channel=%p)", 1,
314                  (channel));
315   grpc_transport_op* op = grpc_make_transport_op(nullptr);
316   op->reset_connect_backoff = true;
317   grpc_channel_element* elem =
318       grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
319   elem->filter->start_transport_op(elem, op);
320 }
321
322 static grpc_call* grpc_channel_create_call_internal(
323     grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
324     grpc_completion_queue* cq, grpc_pollset_set* pollset_set_alternative,
325     grpc_mdelem path_mdelem, grpc_mdelem authority_mdelem,
326     grpc_millis deadline) {
327   grpc_mdelem send_metadata[2];
328   size_t num_metadata = 0;
329
330   GPR_ASSERT(channel->is_client);
331   GPR_ASSERT(!(cq != nullptr && pollset_set_alternative != nullptr));
332
333   send_metadata[num_metadata++] = path_mdelem;
334   if (!GRPC_MDISNULL(authority_mdelem)) {
335     send_metadata[num_metadata++] = authority_mdelem;
336   }
337
338   grpc_call_create_args args;
339   args.channel = channel;
340   args.server = nullptr;
341   args.parent = parent_call;
342   args.propagation_mask = propagation_mask;
343   args.cq = cq;
344   args.pollset_set_alternative = pollset_set_alternative;
345   args.server_transport_data = nullptr;
346   args.add_initial_metadata = send_metadata;
347   args.add_initial_metadata_count = num_metadata;
348   args.send_deadline = deadline;
349
350   grpc_call* call;
351   GRPC_LOG_IF_ERROR("call_create", grpc_call_create(&args, &call));
352   return call;
353 }
354
355 grpc_call* grpc_channel_create_call(grpc_channel* channel,
356                                     grpc_call* parent_call,
357                                     uint32_t propagation_mask,
358                                     grpc_completion_queue* cq,
359                                     grpc_slice method, const grpc_slice* host,
360                                     gpr_timespec deadline, void* reserved) {
361   GPR_ASSERT(!reserved);
362   grpc_core::ExecCtx exec_ctx;
363   grpc_call* call = grpc_channel_create_call_internal(
364       channel, parent_call, propagation_mask, cq, nullptr,
365       grpc_mdelem_create(GRPC_MDSTR_PATH, method, nullptr),
366       host != nullptr ? grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, *host, nullptr)
367                       : GRPC_MDNULL,
368       grpc_timespec_to_millis_round_up(deadline));
369
370   return call;
371 }
372
373 grpc_call* grpc_channel_create_pollset_set_call(
374     grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
375     grpc_pollset_set* pollset_set, const grpc_slice& method,
376     const grpc_slice* host, grpc_millis deadline, void* reserved) {
377   GPR_ASSERT(!reserved);
378   return grpc_channel_create_call_internal(
379       channel, parent_call, propagation_mask, nullptr, pollset_set,
380       grpc_mdelem_create(GRPC_MDSTR_PATH, method, nullptr),
381       host != nullptr ? grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, *host, nullptr)
382                       : GRPC_MDNULL,
383       deadline);
384 }
385
386 void* grpc_channel_register_call(grpc_channel* channel, const char* method,
387                                  const char* host, void* reserved) {
388   registered_call* rc =
389       static_cast<registered_call*>(gpr_malloc(sizeof(registered_call)));
390   GRPC_API_TRACE(
391       "grpc_channel_register_call(channel=%p, method=%s, host=%s, reserved=%p)",
392       4, (channel, method, host, reserved));
393   GPR_ASSERT(!reserved);
394   grpc_core::ExecCtx exec_ctx;
395
396   rc->path = grpc_mdelem_from_slices(
397       GRPC_MDSTR_PATH,
398       grpc_slice_intern(grpc_slice_from_static_string(method)));
399   rc->authority =
400       host ? grpc_mdelem_from_slices(
401                  GRPC_MDSTR_AUTHORITY,
402                  grpc_slice_intern(grpc_slice_from_static_string(host)))
403            : GRPC_MDNULL;
404   gpr_mu_lock(&channel->registered_call_mu);
405   rc->next = channel->registered_calls;
406   channel->registered_calls = rc;
407   gpr_mu_unlock(&channel->registered_call_mu);
408
409   return rc;
410 }
411
412 grpc_call* grpc_channel_create_registered_call(
413     grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
414     grpc_completion_queue* completion_queue, void* registered_call_handle,
415     gpr_timespec deadline, void* reserved) {
416   registered_call* rc = static_cast<registered_call*>(registered_call_handle);
417   GRPC_API_TRACE(
418       "grpc_channel_create_registered_call("
419       "channel=%p, parent_call=%p, propagation_mask=%x, completion_queue=%p, "
420       "registered_call_handle=%p, "
421       "deadline=gpr_timespec { tv_sec: %" PRId64
422       ", tv_nsec: %d, clock_type: %d }, "
423       "reserved=%p)",
424       9,
425       (channel, parent_call, (unsigned)propagation_mask, completion_queue,
426        registered_call_handle, deadline.tv_sec, deadline.tv_nsec,
427        (int)deadline.clock_type, reserved));
428   GPR_ASSERT(!reserved);
429   grpc_core::ExecCtx exec_ctx;
430   grpc_call* call = grpc_channel_create_call_internal(
431       channel, parent_call, propagation_mask, completion_queue, nullptr,
432       GRPC_MDELEM_REF(rc->path), GRPC_MDELEM_REF(rc->authority),
433       grpc_timespec_to_millis_round_up(deadline));
434
435   return call;
436 }
437
438 static void destroy_channel(void* arg, grpc_error* error) {
439   grpc_channel* channel = static_cast<grpc_channel*>(arg);
440   if (channel->channelz_node != nullptr) {
441     if (channel->channelz_node->parent_uuid() > 0) {
442       grpc_core::RefCountedPtr<grpc_core::channelz::BaseNode> parent_node =
443           grpc_core::channelz::ChannelzRegistry::Get(
444               channel->channelz_node->parent_uuid());
445       if (parent_node != nullptr) {
446         grpc_core::channelz::ChannelNode* parent =
447             static_cast<grpc_core::channelz::ChannelNode*>(parent_node.get());
448         parent->RemoveChildChannel(channel->channelz_node->uuid());
449       }
450     }
451     channel->channelz_node->AddTraceEvent(
452         grpc_core::channelz::ChannelTrace::Severity::Info,
453         grpc_slice_from_static_string("Channel destroyed"));
454     channel->channelz_node.reset();
455   }
456   grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel));
457   while (channel->registered_calls) {
458     registered_call* rc = channel->registered_calls;
459     channel->registered_calls = rc->next;
460     GRPC_MDELEM_UNREF(rc->path);
461     GRPC_MDELEM_UNREF(rc->authority);
462     gpr_free(rc);
463   }
464   if (channel->resource_user != nullptr) {
465     grpc_resource_user_free(channel->resource_user,
466                             GRPC_RESOURCE_QUOTA_CHANNEL_SIZE);
467   }
468   gpr_mu_destroy(&channel->registered_call_mu);
469   gpr_free(channel->target);
470   gpr_free(channel);
471 }
472
473 void grpc_channel_destroy(grpc_channel* channel) {
474   grpc_transport_op* op = grpc_make_transport_op(nullptr);
475   grpc_channel_element* elem;
476   grpc_core::ExecCtx exec_ctx;
477   GRPC_API_TRACE("grpc_channel_destroy(channel=%p)", 1, (channel));
478   op->disconnect_with_error =
479       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel Destroyed");
480   elem = grpc_channel_stack_element(CHANNEL_STACK_FROM_CHANNEL(channel), 0);
481   elem->filter->start_transport_op(elem, op);
482
483   GRPC_CHANNEL_INTERNAL_UNREF(channel, "channel");
484 }
485
486 grpc_mdelem grpc_channel_get_reffed_status_elem_slowpath(grpc_channel* channel,
487                                                          int i) {
488   char tmp[GPR_LTOA_MIN_BUFSIZE];
489   gpr_ltoa(i, tmp);
490   return grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_STATUS,
491                                  grpc_slice_from_copied_string(tmp));
492 }