blob: a173fadc43c63f624eb65388b2319a3e6802798d [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * 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
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * 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.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080016 *
17 */
murgatroid999030c812016-09-16 13:25:08 -070018
David Garcia Quintasf74a49e2015-06-18 17:22:45 -070019#include <assert.h>
Craig Tillerc7e1a2a2015-11-02 14:17:32 -080020#include <limits.h>
David Garcia Quintasf74a49e2015-06-18 17:22:45 -070021#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25#include <grpc/compression.h>
murgatroid99c3910ca2016-01-06 13:14:23 -080026#include <grpc/grpc.h>
Craig Tiller0f310802016-10-26 16:25:56 -070027#include <grpc/slice.h>
David Garcia Quintasf74a49e2015-06-18 17:22:45 -070028#include <grpc/support/alloc.h>
29#include <grpc/support/log.h>
30#include <grpc/support/string_util.h>
David Garcia Quintase091af82015-07-15 21:37:02 -070031#include <grpc/support/useful.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080032
Craig Tiller9533d042016-03-25 17:11:06 -070033#include "src/core/lib/channel/channel_stack.h"
34#include "src/core/lib/compression/algorithm_metadata.h"
35#include "src/core/lib/iomgr/timer.h"
36#include "src/core/lib/profiling/timers.h"
Craig Tillera59c16c2016-10-31 07:25:01 -070037#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -070038#include "src/core/lib/slice/slice_string_helpers.h"
Craig Tillere7a17022017-03-13 10:20:38 -070039#include "src/core/lib/support/arena.h"
Craig Tiller9533d042016-03-25 17:11:06 -070040#include "src/core/lib/support/string.h"
41#include "src/core/lib/surface/api_trace.h"
42#include "src/core/lib/surface/call.h"
43#include "src/core/lib/surface/channel.h"
44#include "src/core/lib/surface/completion_queue.h"
Craig Tillerf2b5b7e2017-01-10 08:28:59 -080045#include "src/core/lib/surface/validate_metadata.h"
Craig Tiller732351f2016-12-13 16:40:38 -080046#include "src/core/lib/transport/error_utils.h"
David Garcia Quintas73dcbda2016-04-23 00:17:05 -070047#include "src/core/lib/transport/metadata.h"
Craig Tiller9533d042016-03-25 17:11:06 -070048#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas73dcbda2016-04-23 00:17:05 -070049#include "src/core/lib/transport/transport.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080050
Craig Tillerc7e1a2a2015-11-02 14:17:32 -080051/** The maximum number of concurrent batches possible.
Craig Tiller1b011672015-07-10 10:41:44 -070052 Based upon the maximum number of individually queueable ops in the batch
Craig Tiller94903892016-10-11 15:43:35 -070053 api:
Craig Tiller1b011672015-07-10 10:41:44 -070054 - initial metadata send
55 - message send
56 - status/close send (depending on client/server)
57 - initial metadata recv
58 - message recv
59 - status/close recv (depending on client/server) */
Craig Tillerc7e1a2a2015-11-02 14:17:32 -080060#define MAX_CONCURRENT_BATCHES 6
Craig Tiller1b011672015-07-10 10:41:44 -070061
Craig Tillerc7e1a2a2015-11-02 14:17:32 -080062#define MAX_SEND_EXTRA_METADATA_COUNT 3
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080063
Craig Tillerdaceea82015-02-02 16:15:53 -080064/* Status data for a request can come from several sources; this
65 enumerates them all, and acts as a priority sorting for which
66 status to return to the application - earlier entries override
67 later ones */
Craig Tillera82950e2015-09-22 12:33:20 -070068typedef enum {
Craig Tillerdaceea82015-02-02 16:15:53 -080069 /* Status came from the application layer overriding whatever
70 the wire says */
Craig Tiller68752722015-01-29 14:59:54 -080071 STATUS_FROM_API_OVERRIDE = 0,
Craig Tillerdaceea82015-02-02 16:15:53 -080072 /* Status came from 'the wire' - or somewhere below the surface
73 layer */
Craig Tiller68752722015-01-29 14:59:54 -080074 STATUS_FROM_WIRE,
Craig Tiller2dc32ea2017-01-31 15:32:34 -080075 /* Status was created by some internal channel stack operation: must come via
76 add_batch_error */
Craig Tiller2aa03df2016-03-16 08:24:55 -070077 STATUS_FROM_CORE,
Craig Tiller2dc32ea2017-01-31 15:32:34 -080078 /* Status was created by some surface error */
79 STATUS_FROM_SURFACE,
Craig Tilleraea081f2015-06-11 14:19:33 -070080 /* Status came from the server sending status */
81 STATUS_FROM_SERVER_STATUS,
Craig Tiller68752722015-01-29 14:59:54 -080082 STATUS_SOURCE_COUNT
83} status_source;
84
Craig Tillera82950e2015-09-22 12:33:20 -070085typedef struct {
Craig Tiller841a99d2016-12-12 16:58:57 -080086 bool is_set;
87 grpc_error *error;
Craig Tiller68752722015-01-29 14:59:54 -080088} received_status;
89
Craig Tiller4bab9462017-02-22 08:56:02 -080090static gpr_atm pack_received_status(received_status r) {
91 return r.is_set ? (1 | (gpr_atm)r.error) : 0;
92}
93
94static received_status unpack_received_status(gpr_atm atm) {
95 return (atm & 1) == 0
96 ? (received_status){.is_set = false, .error = GRPC_ERROR_NONE}
97 : (received_status){.is_set = true,
98 .error = (grpc_error *)(atm & ~(gpr_atm)1)};
99}
100
yang-g23f777d2017-02-22 23:32:26 -0800101#define MAX_ERRORS_PER_BATCH 4
Craig Tiller94903892016-10-11 15:43:35 -0700102
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800103typedef struct batch_control {
104 grpc_call *call;
Craig Tillere198b712017-03-31 15:29:33 -0700105 /* Share memory for cq_completion and notify_tag as they are never needed
106 simultaneously. Each byte used in this data structure count as six bytes
Craig Tiller7a8232d2017-04-03 10:59:42 -0700107 per call, so any savings we can make are worthwhile,
108
109 We use notify_tag to determine whether or not to send notification to the
110 completion queue. Once we've made that determination, we can reuse the
111 memory for cq_completion. */
Craig Tillerea54b8c2017-03-01 16:58:28 -0800112 union {
113 grpc_cq_completion cq_completion;
114 struct {
Craig Tillere198b712017-03-31 15:29:33 -0700115 /* Any given op indicates completion by either (a) calling a closure or
116 (b) sending a notification on the call's completion queue. If
117 \a is_closure is true, \a tag indicates a closure to be invoked;
118 otherwise, \a tag indicates the tag to be used in the notification to
119 be sent to the completion queue. */
Craig Tillerea54b8c2017-03-01 16:58:28 -0800120 void *tag;
121 bool is_closure;
122 } notify_tag;
123 } completion_data;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800124 grpc_closure finish_batch;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800125 gpr_refcount steps_to_complete;
Craig Tiller94903892016-10-11 15:43:35 -0700126
127 grpc_error *errors[MAX_ERRORS_PER_BATCH];
128 gpr_atm num_errors;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800129
Craig Tillera0f3abd2017-03-31 15:42:16 -0700130 grpc_transport_stream_op_batch op;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800131} batch_control;
132
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700133typedef struct {
134 gpr_mu child_list_mu;
135 grpc_call *first_child;
136} parent_call;
137
138typedef struct {
139 grpc_call *parent;
140 /** siblings: children of the same parent form a list, and this list is
141 protected under
142 parent->mu */
143 grpc_call *sibling_next;
144 grpc_call *sibling_prev;
145} child_call;
146
Craig Tillera82950e2015-09-22 12:33:20 -0700147struct grpc_call {
Craig Tillerdd36b152017-03-31 08:27:28 -0700148 gpr_refcount ext_ref;
Craig Tillere7a17022017-03-13 10:20:38 -0700149 gpr_arena *arena;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800150 grpc_completion_queue *cq;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700151 grpc_polling_entity pollent;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800152 grpc_channel *channel;
Mark D. Roth3d883412016-11-07 13:42:54 -0800153 gpr_timespec start_time;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700154 /* parent_call* */ gpr_atm parent_call_atm;
155 child_call *child_call;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800156
Craig Tillere5d683c2015-02-03 16:37:36 -0800157 /* client or server call */
Craig Tiller1cbf5762016-04-22 16:02:55 -0700158 bool is_client;
Craig Tillerdd36b152017-03-31 08:27:28 -0700159 /** has grpc_call_unref been called */
Craig Tiller1cbf5762016-04-22 16:02:55 -0700160 bool destroy_called;
Craig Tillerc7df0df2015-08-03 08:06:50 -0700161 /** flag indicating that cancellation is inherited */
Craig Tiller1cbf5762016-04-22 16:02:55 -0700162 bool cancellation_is_inherited;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800163 /** which ops are in-flight */
Craig Tiller1cbf5762016-04-22 16:02:55 -0700164 bool sent_initial_metadata;
165 bool sending_message;
166 bool sent_final_op;
167 bool received_initial_metadata;
168 bool receiving_message;
169 bool requested_final_op;
Craig Tillerb597dcf2017-03-09 07:02:11 -0800170 gpr_atm any_ops_sent_atm;
171 gpr_atm received_final_op_atm;
yang-g0b6ad7d2015-06-25 14:39:01 -0700172
Craig Tillera44cbfc2016-02-03 16:02:49 -0800173 /* have we received initial metadata */
174 bool has_initial_md_been_received;
175
Craig Tillerb58de722017-03-29 14:15:12 -0700176 batch_control *active_batches[MAX_CONCURRENT_BATCHES];
Craig Tillera0f3abd2017-03-31 15:42:16 -0700177 grpc_transport_stream_op_batch_payload stream_op_payload;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800178
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800179 /* first idx: is_receiving, second idx: is_trailing */
180 grpc_metadata_batch metadata_batch[2][2];
Craig Tillerebf94bf2015-02-05 08:48:46 -0800181
Craig Tillere5d683c2015-02-03 16:37:36 -0800182 /* Buffered read metadata waiting to be returned to the application.
183 Element 0 is initial metadata, element 1 is trailing metadata. */
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800184 grpc_metadata_array *buffered_metadata[2];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800185
Craig Tiller4bab9462017-02-22 08:56:02 -0800186 /* Packed received call statuses from various sources */
187 gpr_atm status[STATUS_SOURCE_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800188
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700189 /* Call data useful used for reporting. Only valid after the call has
190 * completed */
191 grpc_call_final_info final_info;
Craig Tiller466129e2016-03-09 14:43:18 -0800192
David Garcia Quintas749367f2016-05-17 19:15:24 -0700193 /* Compression algorithm for *incoming* data */
194 grpc_compression_algorithm incoming_compression_algorithm;
David Garcia Quintase091af82015-07-15 21:37:02 -0700195 /* Supported encodings (compression algorithms), a bitset */
Craig Tiller7536af02015-12-22 13:49:30 -0800196 uint32_t encodings_accepted_by_peer;
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700197
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700198 /* Contexts for various subsystems (security, tracing, ...). */
Julien Boeuf83b02972015-05-20 22:50:34 -0700199 grpc_call_context_element context[GRPC_CONTEXT_COUNT];
Craig Tiller935cf422015-05-01 14:10:46 -0700200
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800201 /* for the client, extra metadata is initial metadata; for the
202 server, it's trailing metadata */
203 grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT];
204 int send_extra_metadata_count;
Craig Tiller6902ad22015-04-16 08:01:49 -0700205 gpr_timespec send_deadline;
206
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800207 grpc_slice_buffer_stream sending_stream;
Craig Tiller94903892016-10-11 15:43:35 -0700208
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800209 grpc_byte_stream *receiving_stream;
210 grpc_byte_buffer **receiving_buffer;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700211 grpc_slice receiving_slice;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800212 grpc_closure receiving_slice_ready;
213 grpc_closure receiving_stream_ready;
Craig Tillera44cbfc2016-02-03 16:02:49 -0800214 grpc_closure receiving_initial_metadata_ready;
Craig Tiller7536af02015-12-22 13:49:30 -0800215 uint32_t test_only_last_message_flags;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800216
Craig Tillere7a17022017-03-13 10:20:38 -0700217 grpc_closure release_call;
218
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800219 union {
220 struct {
221 grpc_status_code *status;
Craig Tiller68208fe2016-11-14 14:35:02 -0800222 grpc_slice *status_details;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800223 } client;
224 struct {
225 int *cancelled;
226 } server;
227 } final_op;
Craig Tillera44cbfc2016-02-03 16:02:49 -0800228
Craig Tiller8a677802016-04-22 15:07:53 -0700229 void *saved_receiving_stream_ready_bctlp;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800230};
231
ncteisen7712c7c2017-07-12 23:11:27 -0700232grpc_tracer_flag grpc_call_error_trace =
233 GRPC_TRACER_INITIALIZER(false, "call_error");
234grpc_tracer_flag grpc_compression_trace =
235 GRPC_TRACER_INITIALIZER(false, "compression");
Craig Tiller58b30cd2017-01-31 17:07:36 -0800236
Craig Tiller87d5b192015-04-16 14:37:57 -0700237#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800238#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
239#define CALL_ELEM_FROM_CALL(call, idx) \
240 grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
241#define CALL_FROM_TOP_ELEM(top_elem) \
242 CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem))
243
Craig Tillera82950e2015-09-22 12:33:20 -0700244static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
Craig Tillera0f3abd2017-03-31 15:42:16 -0700245 grpc_transport_stream_op_batch *op);
Craig Tiller2dc32ea2017-01-31 15:32:34 -0800246static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
247 status_source source, grpc_status_code status,
248 const char *description);
Craig Tiller255edaa2016-12-13 09:04:55 -0800249static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
Craig Tiller2dc32ea2017-01-31 15:32:34 -0800250 status_source source, grpc_error *error);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800251static void destroy_call(grpc_exec_ctx *exec_ctx, void *call_stack,
Craig Tillerc027e772016-05-03 16:27:00 -0700252 grpc_error *error);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800253static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
Craig Tillerc027e772016-05-03 16:27:00 -0700254 grpc_error *error);
Craig Tiller841a99d2016-12-12 16:58:57 -0800255static void get_final_status(grpc_call *call,
256 void (*set_value)(grpc_status_code code,
257 void *user_data),
258 void *set_value_user_data, grpc_slice *details);
259static void set_status_value_directly(grpc_status_code status, void *dest);
260static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
261 status_source source, grpc_error *error);
262static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl);
263static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl);
264static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
yang-g23f777d2017-02-22 23:32:26 -0800265 grpc_error *error, bool has_cancelled);
Craig Tillerbac41422015-05-29 16:32:28 -0700266
Craig Tillerf4484cd2017-02-01 08:28:40 -0800267static void add_init_error(grpc_error **composite, grpc_error *new) {
268 if (new == GRPC_ERROR_NONE) return;
269 if (*composite == GRPC_ERROR_NONE)
ncteisen4b36a3d2017-03-13 19:08:06 -0700270 *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Call creation failed");
Craig Tillerf4484cd2017-02-01 08:28:40 -0800271 *composite = grpc_error_add_child(*composite, new);
272}
273
Craig Tiller58450912017-03-16 09:42:43 -0700274void *grpc_call_arena_alloc(grpc_call *call, size_t size) {
275 return gpr_arena_alloc(call->arena, size);
276}
277
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700278static parent_call *get_or_create_parent_call(grpc_call *call) {
279 parent_call *p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm);
280 if (p == NULL) {
281 p = gpr_arena_alloc(call->arena, sizeof(*p));
282 gpr_mu_init(&p->child_list_mu);
283 if (!gpr_atm_rel_cas(&call->parent_call_atm, (gpr_atm)NULL, (gpr_atm)p)) {
284 gpr_mu_destroy(&p->child_list_mu);
285 p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm);
286 }
287 }
288 return p;
289}
290
291static parent_call *get_parent_call(grpc_call *call) {
292 return (parent_call *)gpr_atm_acq_load(&call->parent_call_atm);
293}
294
Craig Tillera59c16c2016-10-31 07:25:01 -0700295grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
296 const grpc_call_create_args *args,
Craig Tiller8e214652016-08-19 09:54:31 -0700297 grpc_call **out_call) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800298 size_t i, j;
Craig Tillerf4484cd2017-02-01 08:28:40 -0800299 grpc_error *error = GRPC_ERROR_NONE;
Craig Tiller8e214652016-08-19 09:54:31 -0700300 grpc_channel_stack *channel_stack =
301 grpc_channel_get_channel_stack(args->channel);
Craig Tiller1f41b6b2015-10-09 15:07:02 -0700302 grpc_call *call;
Craig Tiller0ba432d2015-10-09 16:57:11 -0700303 GPR_TIMER_BEGIN("grpc_call_create", 0);
Craig Tillera6bec8f2017-03-14 08:26:04 -0700304 gpr_arena *arena =
305 gpr_arena_create(grpc_channel_get_call_size_estimate(args->channel));
Craig Tillere7a17022017-03-13 10:20:38 -0700306 call = gpr_arena_alloc(arena,
307 sizeof(grpc_call) + channel_stack->call_stack_size);
Craig Tillerdd36b152017-03-31 08:27:28 -0700308 gpr_ref_init(&call->ext_ref, 1);
Craig Tillere7a17022017-03-13 10:20:38 -0700309 call->arena = arena;
Craig Tiller0eaed722016-09-21 10:44:18 -0700310 *out_call = call;
Craig Tiller8e214652016-08-19 09:54:31 -0700311 call->channel = args->channel;
312 call->cq = args->cq;
Mark D. Roth3d883412016-11-07 13:42:54 -0800313 call->start_time = gpr_now(GPR_CLOCK_MONOTONIC);
David Garcia Quintas46123372016-05-09 15:28:42 -0700314 /* Always support no compression */
315 GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
Craig Tiller8e214652016-08-19 09:54:31 -0700316 call->is_client = args->server_transport_data == NULL;
Craig Tillerea54b8c2017-03-01 16:58:28 -0800317 call->stream_op_payload.context = call->context;
Craig Tiller4eecdde2016-11-14 08:21:17 -0800318 grpc_slice path = grpc_empty_slice();
Craig Tillera82950e2015-09-22 12:33:20 -0700319 if (call->is_client) {
Craig Tiller8e214652016-08-19 09:54:31 -0700320 GPR_ASSERT(args->add_initial_metadata_count <
321 MAX_SEND_EXTRA_METADATA_COUNT);
322 for (i = 0; i < args->add_initial_metadata_count; i++) {
323 call->send_extra_metadata[i].md = args->add_initial_metadata[i];
Craig Tiller3b05e1d2016-11-21 13:46:31 -0800324 if (grpc_slice_eq(GRPC_MDKEY(args->add_initial_metadata[i]),
325 GRPC_MDSTR_PATH)) {
Craig Tiller0160de92016-11-18 08:46:46 -0800326 path = grpc_slice_ref_internal(
327 GRPC_MDVALUE(args->add_initial_metadata[i]));
Mark D. Rothaa850a72016-09-26 13:38:02 -0700328 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800329 }
Craig Tiller8e214652016-08-19 09:54:31 -0700330 call->send_extra_metadata_count = (int)args->add_initial_metadata_count;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800331 } else {
Craig Tiller8e214652016-08-19 09:54:31 -0700332 GPR_ASSERT(args->add_initial_metadata_count == 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800333 call->send_extra_metadata_count = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700334 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800335 for (i = 0; i < 2; i++) {
336 for (j = 0; j < 2; j++) {
337 call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
338 }
Craig Tillera82950e2015-09-22 12:33:20 -0700339 }
Craig Tillerca3451d2016-09-29 10:27:44 -0700340 gpr_timespec send_deadline =
Craig Tiller8e214652016-08-19 09:54:31 -0700341 gpr_convert_clock_type(args->send_deadline, GPR_CLOCK_MONOTONIC);
Mark D. Rothf28763c2016-09-14 15:18:40 -0700342
Craig Tillerbea92ba2017-04-19 08:33:31 -0700343 bool immediately_cancel = false;
344
Craig Tiller8e214652016-08-19 09:54:31 -0700345 if (args->parent_call != NULL) {
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700346 child_call *cc = call->child_call =
347 gpr_arena_alloc(arena, sizeof(child_call));
348 call->child_call->parent = args->parent_call;
349
Craig Tiller8e214652016-08-19 09:54:31 -0700350 GRPC_CALL_INTERNAL_REF(args->parent_call, "child");
Craig Tillera82950e2015-09-22 12:33:20 -0700351 GPR_ASSERT(call->is_client);
Craig Tiller8e214652016-08-19 09:54:31 -0700352 GPR_ASSERT(!args->parent_call->is_client);
Craig Tillera82950e2015-09-22 12:33:20 -0700353
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700354 parent_call *pc = get_or_create_parent_call(args->parent_call);
355
356 gpr_mu_lock(&pc->child_list_mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700357
Craig Tiller8e214652016-08-19 09:54:31 -0700358 if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) {
Craig Tillera82950e2015-09-22 12:33:20 -0700359 send_deadline = gpr_time_min(
360 gpr_convert_clock_type(send_deadline,
Craig Tiller8e214652016-08-19 09:54:31 -0700361 args->parent_call->send_deadline.clock_type),
362 args->parent_call->send_deadline);
Craig Tillerc7df0df2015-08-03 08:06:50 -0700363 }
Craig Tillera82950e2015-09-22 12:33:20 -0700364 /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with
365 * GRPC_PROPAGATE_STATS_CONTEXT */
366 /* TODO(ctiller): This should change to use the appropriate census start_op
367 * call. */
Craig Tiller8e214652016-08-19 09:54:31 -0700368 if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) {
Craig Tiller239af8b2017-02-01 10:21:42 -0800369 if (0 == (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT)) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700370 add_init_error(&error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
371 "Census tracing propagation requested "
372 "without Census context propagation"));
Craig Tiller239af8b2017-02-01 10:21:42 -0800373 }
Craig Tiller8e214652016-08-19 09:54:31 -0700374 grpc_call_context_set(
375 call, GRPC_CONTEXT_TRACING,
376 args->parent_call->context[GRPC_CONTEXT_TRACING].value, NULL);
Craig Tillerf20d3072017-02-01 10:39:26 -0800377 } else if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700378 add_init_error(&error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
379 "Census context propagation requested "
380 "without Census tracing propagation"));
Craig Tiller45724b32015-09-22 10:42:19 -0700381 }
Craig Tiller8e214652016-08-19 09:54:31 -0700382 if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
Craig Tillera82950e2015-09-22 12:33:20 -0700383 call->cancellation_is_inherited = 1;
Craig Tiller123c72b2017-03-10 07:33:27 -0800384 if (gpr_atm_acq_load(&args->parent_call->received_final_op_atm)) {
Craig Tillerbea92ba2017-04-19 08:33:31 -0700385 immediately_cancel = true;
Craig Tiller123c72b2017-03-10 07:33:27 -0800386 }
Craig Tiller45724b32015-09-22 10:42:19 -0700387 }
Craig Tillera82950e2015-09-22 12:33:20 -0700388
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700389 if (pc->first_child == NULL) {
390 pc->first_child = call;
391 cc->sibling_next = cc->sibling_prev = call;
Craig Tillera82950e2015-09-22 12:33:20 -0700392 } else {
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700393 cc->sibling_next = pc->first_child;
394 cc->sibling_prev = pc->first_child->child_call->sibling_prev;
395 cc->sibling_next->child_call->sibling_prev =
396 cc->sibling_prev->child_call->sibling_next = call;
Craig Tillera82950e2015-09-22 12:33:20 -0700397 }
398
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700399 gpr_mu_unlock(&pc->child_list_mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700400 }
Mark D. Rothf28763c2016-09-14 15:18:40 -0700401
Mark D. Roth14c072c2016-08-26 08:31:34 -0700402 call->send_deadline = send_deadline;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700403
Craig Tillerca3451d2016-09-29 10:27:44 -0700404 GRPC_CHANNEL_INTERNAL_REF(args->channel, "call");
Craig Tillerdd36b152017-03-31 08:27:28 -0700405 /* initial refcount dropped by grpc_call_unref */
Craig Tillerd426cac2017-03-13 12:30:45 -0700406 grpc_call_element_args call_args = {
407 .call_stack = CALL_STACK_FROM_CALL(call),
408 .server_transport_data = args->server_transport_data,
409 .context = call->context,
410 .path = path,
411 .start_time = call->start_time,
412 .deadline = send_deadline,
413 .arena = call->arena};
Craig Tillerf4484cd2017-02-01 08:28:40 -0800414 add_init_error(&error, grpc_call_stack_init(exec_ctx, channel_stack, 1,
Craig Tillerd426cac2017-03-13 12:30:45 -0700415 destroy_call, call, &call_args));
Mark D. Rothf28763c2016-09-14 15:18:40 -0700416 if (error != GRPC_ERROR_NONE) {
Craig Tiller58b30cd2017-01-31 17:07:36 -0800417 cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
418 GRPC_ERROR_REF(error));
Craig Tillera82950e2015-09-22 12:33:20 -0700419 }
Craig Tillerbea92ba2017-04-19 08:33:31 -0700420 if (immediately_cancel) {
421 cancel_with_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE,
422 GRPC_ERROR_CANCELLED);
423 }
Craig Tillerca3451d2016-09-29 10:27:44 -0700424 if (args->cq != NULL) {
Mark D. Rothf28763c2016-09-14 15:18:40 -0700425 GPR_ASSERT(
Craig Tillerca3451d2016-09-29 10:27:44 -0700426 args->pollset_set_alternative == NULL &&
Mark D. Rothf28763c2016-09-14 15:18:40 -0700427 "Only one of 'cq' and 'pollset_set_alternative' should be non-NULL.");
Craig Tillerca3451d2016-09-29 10:27:44 -0700428 GRPC_CQ_INTERNAL_REF(args->cq, "bind");
Mark D. Rothf28763c2016-09-14 15:18:40 -0700429 call->pollent =
Craig Tillerca3451d2016-09-29 10:27:44 -0700430 grpc_polling_entity_create_from_pollset(grpc_cq_pollset(args->cq));
Mark D. Rothf28763c2016-09-14 15:18:40 -0700431 }
Craig Tillerca3451d2016-09-29 10:27:44 -0700432 if (args->pollset_set_alternative != NULL) {
433 call->pollent = grpc_polling_entity_create_from_pollset_set(
434 args->pollset_set_alternative);
Mark D. Rothf28763c2016-09-14 15:18:40 -0700435 }
436 if (!grpc_polling_entity_is_empty(&call->pollent)) {
437 grpc_call_stack_set_pollset_or_pollset_set(
Craig Tillera59c16c2016-10-31 07:25:01 -0700438 exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent);
Mark D. Rothf28763c2016-09-14 15:18:40 -0700439 }
440
Craig Tiller4eecdde2016-11-14 08:21:17 -0800441 grpc_slice_unref_internal(exec_ctx, path);
Mark D. Rothaa850a72016-09-26 13:38:02 -0700442
Craig Tiller0ba432d2015-10-09 16:57:11 -0700443 GPR_TIMER_END("grpc_call_create", 0);
Craig Tiller8e214652016-08-19 09:54:31 -0700444 return error;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800445}
446
Craig Tillera82950e2015-09-22 12:33:20 -0700447void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call,
448 grpc_completion_queue *cq) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800449 GPR_ASSERT(cq);
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700450
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700451 if (grpc_polling_entity_pollset_set(&call->pollent) != NULL) {
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700452 gpr_log(GPR_ERROR, "A pollset_set is already registered for this call.");
453 abort();
454 }
Craig Tiller166e2502015-02-03 20:14:41 -0800455 call->cq = cq;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800456 GRPC_CQ_INTERNAL_REF(cq, "bind");
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700457 call->pollent = grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq));
David Garcia Quintas4afce7e2016-04-18 16:25:17 -0700458 grpc_call_stack_set_pollset_or_pollset_set(
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700459 exec_ctx, CALL_STACK_FROM_CALL(call), &call->pollent);
Craig Tiller166e2502015-02-03 20:14:41 -0800460}
461
ncteisen9c43fc02017-06-08 16:06:23 -0700462#ifndef NDEBUG
Craig Tiller7b435612015-11-24 08:15:05 -0800463#define REF_REASON reason
464#define REF_ARG , const char *reason
Craig Tiller4df412b2015-04-28 07:57:54 -0700465#else
Craig Tiller7b435612015-11-24 08:15:05 -0800466#define REF_REASON ""
467#define REF_ARG
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800468#endif
Craig Tiller7b435612015-11-24 08:15:05 -0800469void grpc_call_internal_ref(grpc_call *c REF_ARG) {
470 GRPC_CALL_STACK_REF(CALL_STACK_FROM_CALL(c), REF_REASON);
471}
472void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
473 GRPC_CALL_STACK_UNREF(exec_ctx, CALL_STACK_FROM_CALL(c), REF_REASON);
474}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800475
Craig Tillere7a17022017-03-13 10:20:38 -0700476static void release_call(grpc_exec_ctx *exec_ctx, void *call,
477 grpc_error *error) {
478 grpc_call *c = call;
Craig Tiller51006fe2017-03-15 08:07:02 -0700479 grpc_channel *channel = c->channel;
Craig Tillerdbad3702017-03-15 08:21:19 -0700480 grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena));
Craig Tiller51006fe2017-03-15 08:07:02 -0700481 GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call");
Craig Tillere7a17022017-03-13 10:20:38 -0700482}
483
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700484static void set_status_value_directly(grpc_status_code status, void *dest);
Craig Tillerc027e772016-05-03 16:27:00 -0700485static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
486 grpc_error *error) {
Craig Tiller566316f2015-02-02 15:25:32 -0800487 size_t i;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800488 int ii;
Craig Tilleraef25da2015-01-29 17:19:45 -0800489 grpc_call *c = call;
Craig Tiller0ba432d2015-10-09 16:57:11 -0700490 GPR_TIMER_BEGIN("destroy_call", 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800491 for (i = 0; i < 2; i++) {
492 grpc_metadata_batch_destroy(
Craig Tillera59c16c2016-10-31 07:25:01 -0700493 exec_ctx, &c->metadata_batch[1 /* is_receiving */][i /* is_initial */]);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800494 }
495 if (c->receiving_stream != NULL) {
Craig Tiller3b66ab92015-12-09 19:42:22 -0800496 grpc_byte_stream_destroy(exec_ctx, c->receiving_stream);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800497 }
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700498 parent_call *pc = get_parent_call(c);
499 if (pc != NULL) {
500 gpr_mu_destroy(&pc->child_list_mu);
501 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800502 for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
Craig Tillera59c16c2016-10-31 07:25:01 -0700503 GRPC_MDELEM_UNREF(exec_ctx, c->send_extra_metadata[ii].md);
Craig Tillera82950e2015-09-22 12:33:20 -0700504 }
505 for (i = 0; i < GRPC_CONTEXT_COUNT; i++) {
506 if (c->context[i].destroy) {
507 c->context[i].destroy(c->context[i].value);
Craig Tiller935cf422015-05-01 14:10:46 -0700508 }
Craig Tillera82950e2015-09-22 12:33:20 -0700509 }
Craig Tillera82950e2015-09-22 12:33:20 -0700510 if (c->cq) {
Craig Tillerf8401102017-04-17 09:47:28 -0700511 GRPC_CQ_INTERNAL_UNREF(exec_ctx, c->cq, "bind");
Craig Tillera82950e2015-09-22 12:33:20 -0700512 }
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700513
Craig Tiller841a99d2016-12-12 16:58:57 -0800514 get_final_status(call, set_status_value_directly, &c->final_info.final_status,
515 NULL);
Mark D. Roth3d883412016-11-07 13:42:54 -0800516 c->final_info.stats.latency =
517 gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700518
Craig Tiller841a99d2016-12-12 16:58:57 -0800519 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800520 GRPC_ERROR_UNREF(
Craig Tillerb597dcf2017-03-09 07:02:11 -0800521 unpack_received_status(gpr_atm_acq_load(&c->status[i])).error);
Craig Tiller841a99d2016-12-12 16:58:57 -0800522 }
523
Craig Tillere7a17022017-03-13 10:20:38 -0700524 grpc_call_stack_destroy(exec_ctx, CALL_STACK_FROM_CALL(c), &c->final_info,
ncteisen969b46e2017-06-08 14:57:11 -0700525 GRPC_CLOSURE_INIT(&c->release_call, release_call, c,
Craig Tillere7a17022017-03-13 10:20:38 -0700526 grpc_schedule_on_exec_ctx));
Craig Tiller0ba432d2015-10-09 16:57:11 -0700527 GPR_TIMER_END("destroy_call", 0);
Craig Tillera4541102015-01-29 11:46:11 -0800528}
529
Craig Tillerdd36b152017-03-31 08:27:28 -0700530void grpc_call_ref(grpc_call *c) { gpr_ref(&c->ext_ref); }
531
532void grpc_call_unref(grpc_call *c) {
533 if (!gpr_unref(&c->ext_ref)) return;
534
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700535 child_call *cc = c->child_call;
Craig Tiller841a99d2016-12-12 16:58:57 -0800536 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tillerb8d3a312015-06-19 17:27:53 -0700537
Craig Tillerdd36b152017-03-31 08:27:28 -0700538 GPR_TIMER_BEGIN("grpc_call_unref", 0);
539 GRPC_API_TRACE("grpc_call_unref(c=%p)", 1, (c));
Craig Tiller841a99d2016-12-12 16:58:57 -0800540
Craig Tiller9fd9a442017-04-05 16:52:34 -0700541 if (cc) {
542 parent_call *pc = get_parent_call(cc->parent);
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700543 gpr_mu_lock(&pc->child_list_mu);
544 if (c == pc->first_child) {
545 pc->first_child = cc->sibling_next;
546 if (c == pc->first_child) {
547 pc->first_child = NULL;
Craig Tiller841a99d2016-12-12 16:58:57 -0800548 }
Craig Tiller841a99d2016-12-12 16:58:57 -0800549 }
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700550 cc->sibling_prev->child_call->sibling_next = cc->sibling_next;
551 cc->sibling_next->child_call->sibling_prev = cc->sibling_prev;
552 gpr_mu_unlock(&pc->child_list_mu);
553 GRPC_CALL_INTERNAL_UNREF(&exec_ctx, cc->parent, "child");
Craig Tiller841a99d2016-12-12 16:58:57 -0800554 }
555
Craig Tiller841a99d2016-12-12 16:58:57 -0800556 GPR_ASSERT(!c->destroy_called);
557 c->destroy_called = 1;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700558 bool cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) != 0 &&
559 gpr_atm_acq_load(&c->received_final_op_atm) == 0;
Craig Tiller37cbc3f2017-02-16 14:54:55 -0800560 if (cancel) {
561 cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
562 GRPC_ERROR_CANCELLED);
563 }
Craig Tiller841a99d2016-12-12 16:58:57 -0800564 GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
565 grpc_exec_ctx_finish(&exec_ctx);
Craig Tillerdd36b152017-03-31 08:27:28 -0700566 GPR_TIMER_END("grpc_call_unref", 0);
Craig Tillerf0f70a82016-06-23 13:55:06 -0700567}
Craig Tiller30547562015-02-05 17:04:51 -0800568
Craig Tiller841a99d2016-12-12 16:58:57 -0800569grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
570 GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved));
571 GPR_ASSERT(!reserved);
Craig Tiller37cbc3f2017-02-16 14:54:55 -0800572 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
573 cancel_with_error(&exec_ctx, call, STATUS_FROM_API_OVERRIDE,
574 GRPC_ERROR_CANCELLED);
575 grpc_exec_ctx_finish(&exec_ctx);
576 return GRPC_CALL_OK;
Craig Tiller841a99d2016-12-12 16:58:57 -0800577}
578
579static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
Craig Tillera0f3abd2017-03-31 15:42:16 -0700580 grpc_transport_stream_op_batch *op) {
Craig Tiller841a99d2016-12-12 16:58:57 -0800581 grpc_call_element *elem;
582
583 GPR_TIMER_BEGIN("execute_op", 0);
584 elem = CALL_ELEM_FROM_CALL(call, 0);
Craig Tillera0f3abd2017-03-31 15:42:16 -0700585 elem->filter->start_transport_stream_op_batch(exec_ctx, elem, op);
Craig Tiller841a99d2016-12-12 16:58:57 -0800586 GPR_TIMER_END("execute_op", 0);
587}
588
589char *grpc_call_get_peer(grpc_call *call) {
590 grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
591 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
592 char *result;
593 GRPC_API_TRACE("grpc_call_get_peer(%p)", 1, (call));
594 result = elem->filter->get_peer(&exec_ctx, elem);
595 if (result == NULL) {
596 result = grpc_channel_get_target(call->channel);
597 }
598 if (result == NULL) {
599 result = gpr_strdup("unknown");
600 }
601 grpc_exec_ctx_finish(&exec_ctx);
602 return result;
603}
604
605grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
606 return CALL_FROM_TOP_ELEM(elem);
607}
608
609/*******************************************************************************
610 * CANCELLATION
611 */
612
613grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
614 grpc_status_code status,
615 const char *description,
616 void *reserved) {
Craig Tiller841a99d2016-12-12 16:58:57 -0800617 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
618 GRPC_API_TRACE(
619 "grpc_call_cancel_with_status("
620 "c=%p, status=%d, description=%s, reserved=%p)",
621 4, (c, (int)status, description, reserved));
622 GPR_ASSERT(reserved == NULL);
Craig Tiller2dc32ea2017-01-31 15:32:34 -0800623 cancel_with_status(&exec_ctx, c, STATUS_FROM_API_OVERRIDE, status,
624 description);
Craig Tiller841a99d2016-12-12 16:58:57 -0800625 grpc_exec_ctx_finish(&exec_ctx);
Craig Tiller2dc32ea2017-01-31 15:32:34 -0800626 return GRPC_CALL_OK;
Craig Tiller841a99d2016-12-12 16:58:57 -0800627}
628
Craig Tillerc5b90df2017-03-10 16:11:08 -0800629static void done_termination(grpc_exec_ctx *exec_ctx, void *call,
Craig Tiller841a99d2016-12-12 16:58:57 -0800630 grpc_error *error) {
Craig Tillerc5b90df2017-03-10 16:11:08 -0800631 GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "termination");
Craig Tiller841a99d2016-12-12 16:58:57 -0800632}
633
Craig Tiller255edaa2016-12-13 09:04:55 -0800634static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
Craig Tiller2dc32ea2017-01-31 15:32:34 -0800635 status_source source, grpc_error *error) {
Craig Tillerc5b90df2017-03-10 16:11:08 -0800636 GRPC_CALL_INTERNAL_REF(c, "termination");
Craig Tiller2dc32ea2017-01-31 15:32:34 -0800637 set_status_from_error(exec_ctx, c, source, GRPC_ERROR_REF(error));
Craig Tillera0f3abd2017-03-31 15:42:16 -0700638 grpc_transport_stream_op_batch *op = grpc_make_transport_stream_op(
ncteisen969b46e2017-06-08 14:57:11 -0700639 GRPC_CLOSURE_CREATE(done_termination, c, grpc_schedule_on_exec_ctx));
Craig Tiller22b182b2017-03-16 10:56:58 -0700640 op->cancel_stream = true;
641 op->payload->cancel_stream.cancel_error = error;
Craig Tillerc5b90df2017-03-10 16:11:08 -0800642 execute_op(exec_ctx, c, op);
Craig Tiller255edaa2016-12-13 09:04:55 -0800643}
644
Craig Tiller841a99d2016-12-12 16:58:57 -0800645static grpc_error *error_from_status(grpc_status_code status,
646 const char *description) {
647 return grpc_error_set_int(
ncteisen4b36a3d2017-03-13 19:08:06 -0700648 grpc_error_set_str(GRPC_ERROR_CREATE_FROM_COPIED_STRING(description),
649 GRPC_ERROR_STR_GRPC_MESSAGE,
650 grpc_slice_from_copied_string(description)),
Craig Tiller841a99d2016-12-12 16:58:57 -0800651 GRPC_ERROR_INT_GRPC_STATUS, status);
652}
653
Craig Tiller2dc32ea2017-01-31 15:32:34 -0800654static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
655 status_source source, grpc_status_code status,
656 const char *description) {
657 cancel_with_error(exec_ctx, c, source,
658 error_from_status(status, description));
Craig Tiller841a99d2016-12-12 16:58:57 -0800659}
660
661/*******************************************************************************
662 * FINAL STATUS CODE MANIPULATION
663 */
664
Craig Tiller58b30cd2017-01-31 17:07:36 -0800665static bool get_final_status_from(
Craig Tiller4bab9462017-02-22 08:56:02 -0800666 grpc_call *call, grpc_error *error, bool allow_ok_status,
Craig Tiller58b30cd2017-01-31 17:07:36 -0800667 void (*set_value)(grpc_status_code code, void *user_data),
668 void *set_value_user_data, grpc_slice *details) {
Craig Tiller737b6252017-01-09 15:25:15 -0800669 grpc_status_code code;
ncteiseneb2b1152017-03-28 15:27:27 -0700670 grpc_slice slice = grpc_empty_slice();
ncteisenbbb38012017-03-10 14:58:43 -0800671 grpc_error_get_status(error, call->send_deadline, &code, &slice, NULL);
Craig Tiller58b30cd2017-01-31 17:07:36 -0800672 if (code == GRPC_STATUS_OK && !allow_ok_status) {
673 return false;
674 }
Craig Tiller737b6252017-01-09 15:25:15 -0800675
676 set_value(code, set_value_user_data);
677 if (details != NULL) {
ncteisenbbb38012017-03-10 14:58:43 -0800678 *details = grpc_slice_ref_internal(slice);
Craig Tiller737b6252017-01-09 15:25:15 -0800679 }
Craig Tiller58b30cd2017-01-31 17:07:36 -0800680 return true;
Craig Tiller737b6252017-01-09 15:25:15 -0800681}
682
Craig Tiller841a99d2016-12-12 16:58:57 -0800683static void get_final_status(grpc_call *call,
684 void (*set_value)(grpc_status_code code,
685 void *user_data),
686 void *set_value_user_data, grpc_slice *details) {
687 int i;
Craig Tiller4bab9462017-02-22 08:56:02 -0800688 received_status status[STATUS_SOURCE_COUNT];
689 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
690 status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
691 }
Craig Tiller84f75d42017-05-03 13:06:35 -0700692 if (GRPC_TRACER_ON(grpc_call_error_trace)) {
Craig Tiller58b30cd2017-01-31 17:07:36 -0800693 gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
694 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800695 if (status[i].is_set) {
696 gpr_log(GPR_DEBUG, " %d: %s", i, grpc_error_string(status[i].error));
Craig Tiller58b30cd2017-01-31 17:07:36 -0800697 }
Craig Tiller841a99d2016-12-12 16:58:57 -0800698 }
699 }
Craig Tiller58b30cd2017-01-31 17:07:36 -0800700 /* first search through ignoring "OK" statuses: if something went wrong,
701 * ensure we report it */
702 for (int allow_ok_status = 0; allow_ok_status < 2; allow_ok_status++) {
703 /* search for the best status we can present: ideally the error we use has a
704 clearly defined grpc-status, and we'll prefer that. */
705 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800706 if (status[i].is_set &&
707 grpc_error_has_clear_grpc_status(status[i].error)) {
708 if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
Craig Tiller58b30cd2017-01-31 17:07:36 -0800709 set_value, set_value_user_data, details)) {
710 return;
711 }
712 }
713 }
714 /* If no clearly defined status exists, search for 'anything' */
715 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800716 if (status[i].is_set) {
717 if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
Craig Tiller58b30cd2017-01-31 17:07:36 -0800718 set_value, set_value_user_data, details)) {
719 return;
720 }
721 }
Craig Tiller737b6252017-01-09 15:25:15 -0800722 }
723 }
724 /* If nothing exists, set some default */
Craig Tiller841a99d2016-12-12 16:58:57 -0800725 if (call->is_client) {
726 set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
Craig Tillerbe1b9a72016-06-24 13:22:11 -0700727 } else {
Craig Tiller841a99d2016-12-12 16:58:57 -0800728 set_value(GRPC_STATUS_OK, set_value_user_data);
Craig Tillerf0f70a82016-06-23 13:55:06 -0700729 }
Craig Tillerf0f70a82016-06-23 13:55:06 -0700730}
731
Craig Tillera59c16c2016-10-31 07:25:01 -0700732static void set_status_from_error(grpc_exec_ctx *exec_ctx, grpc_call *call,
733 status_source source, grpc_error *error) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800734 if (!gpr_atm_rel_cas(&call->status[source],
735 pack_received_status((received_status){
736 .is_set = false, .error = GRPC_ERROR_NONE}),
737 pack_received_status((received_status){
738 .is_set = true, .error = error}))) {
Craig Tiller841a99d2016-12-12 16:58:57 -0800739 GRPC_ERROR_UNREF(error);
Craig Tiller841a99d2016-12-12 16:58:57 -0800740 }
Craig Tiller68752722015-01-29 14:59:54 -0800741}
742
Craig Tiller841a99d2016-12-12 16:58:57 -0800743/*******************************************************************************
744 * COMPRESSION
745 */
746
David Garcia Quintasac094472016-05-18 20:25:57 -0700747static void set_incoming_compression_algorithm(
748 grpc_call *call, grpc_compression_algorithm algo) {
David Garcia Quintas303d3082016-05-05 18:25:34 -0700749 GPR_ASSERT(algo < GRPC_COMPRESS_ALGORITHMS_COUNT);
David Garcia Quintas749367f2016-05-17 19:15:24 -0700750 call->incoming_compression_algorithm = algo;
David Garcia Quintasdb94b272015-06-15 18:37:01 -0700751}
752
David Garcia Quintas0c331882015-10-08 14:51:54 -0700753grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
David Garcia Quintas64824be2015-10-06 19:45:36 -0700754 grpc_call *call) {
755 grpc_compression_algorithm algorithm;
David Garcia Quintas749367f2016-05-17 19:15:24 -0700756 algorithm = call->incoming_compression_algorithm;
David Garcia Quintas64824be2015-10-06 19:45:36 -0700757 return algorithm;
David Garcia Quintas7c0d9142015-07-23 04:58:20 -0700758}
759
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700760static grpc_compression_algorithm compression_algorithm_for_level_locked(
761 grpc_call *call, grpc_compression_level level) {
David Garcia Quintasac094472016-05-18 20:25:57 -0700762 return grpc_compression_algorithm_for_level(level,
763 call->encodings_accepted_by_peer);
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700764}
765
Craig Tiller7536af02015-12-22 13:49:30 -0800766uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
767 uint32_t flags;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800768 flags = call->test_only_last_message_flags;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800769 return flags;
770}
771
Craig Tiller3ff27542015-10-09 15:39:44 -0700772static void destroy_encodings_accepted_by_peer(void *p) { return; }
773
Craig Tillera59c16c2016-10-31 07:25:01 -0700774static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
Craig Tiller0160de92016-11-18 08:46:46 -0800775 grpc_call *call, grpc_mdelem mdel) {
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700776 size_t i;
777 grpc_compression_algorithm algorithm;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700778 grpc_slice_buffer accept_encoding_parts;
779 grpc_slice accept_encoding_slice;
Craig Tiller3ff27542015-10-09 15:39:44 -0700780 void *accepted_user_data;
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700781
Craig Tiller3ff27542015-10-09 15:39:44 -0700782 accepted_user_data =
783 grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
784 if (accepted_user_data != NULL) {
785 call->encodings_accepted_by_peer =
Craig Tiller7536af02015-12-22 13:49:30 -0800786 (uint32_t)(((uintptr_t)accepted_user_data) - 1);
Craig Tiller3ff27542015-10-09 15:39:44 -0700787 return;
788 }
789
Craig Tiller0160de92016-11-18 08:46:46 -0800790 accept_encoding_slice = GRPC_MDVALUE(mdel);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700791 grpc_slice_buffer_init(&accept_encoding_parts);
792 grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700793
David Garcia Quintase091af82015-07-15 21:37:02 -0700794 /* No need to zero call->encodings_accepted_by_peer: grpc_call_create already
795 * zeroes the whole grpc_call */
David Garcia Quintasb1866bd2015-07-08 22:37:01 -0700796 /* Always support no compression */
Craig Tillera82950e2015-09-22 12:33:20 -0700797 GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
798 for (i = 0; i < accept_encoding_parts.count; i++) {
Craig Tiller68208fe2016-11-14 14:35:02 -0800799 grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
800 if (grpc_compression_algorithm_parse(accept_encoding_entry_slice,
801 &algorithm)) {
Craig Tillera82950e2015-09-22 12:33:20 -0700802 GPR_BITSET(&call->encodings_accepted_by_peer, algorithm);
803 } else {
804 char *accept_encoding_entry_str =
Craig Tillerb4aa70e2016-12-09 09:40:11 -0800805 grpc_slice_to_c_string(accept_encoding_entry_slice);
Craig Tillera82950e2015-09-22 12:33:20 -0700806 gpr_log(GPR_ERROR,
807 "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
808 accept_encoding_entry_str);
809 gpr_free(accept_encoding_entry_str);
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700810 }
Craig Tillera82950e2015-09-22 12:33:20 -0700811 }
Craig Tiller3ff27542015-10-09 15:39:44 -0700812
Craig Tillera59c16c2016-10-31 07:25:01 -0700813 grpc_slice_buffer_destroy_internal(exec_ctx, &accept_encoding_parts);
Craig Tiller3ff27542015-10-09 15:39:44 -0700814
815 grpc_mdelem_set_user_data(
816 mdel, destroy_encodings_accepted_by_peer,
Craig Tiller7536af02015-12-22 13:49:30 -0800817 (void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700818}
819
Craig Tiller7536af02015-12-22 13:49:30 -0800820uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
821 uint32_t encodings_accepted_by_peer;
David Garcia Quintas0c331882015-10-08 14:51:54 -0700822 encodings_accepted_by_peer = call->encodings_accepted_by_peer;
David Garcia Quintas0c331882015-10-08 14:51:54 -0700823 return encodings_accepted_by_peer;
Craig Tiller68752722015-01-29 14:59:54 -0800824}
825
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800826static grpc_linked_mdelem *linked_from_md(grpc_metadata *md) {
827 return (grpc_linked_mdelem *)&md->internal_data;
Craig Tillerc12fee62015-02-03 11:55:50 -0800828}
829
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700830static grpc_metadata *get_md_elem(grpc_metadata *metadata,
831 grpc_metadata *additional_metadata, int i,
832 int count) {
833 grpc_metadata *res =
834 i < count ? &metadata[i] : &additional_metadata[i - count];
835 GPR_ASSERT(res);
836 return res;
837}
838
Craig Tillera59c16c2016-10-31 07:25:01 -0700839static int prepare_application_metadata(
840 grpc_exec_ctx *exec_ctx, grpc_call *call, int count,
841 grpc_metadata *metadata, int is_trailing, int prepend_extra_metadata,
842 grpc_metadata *additional_metadata, int additional_metadata_count) {
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700843 int total_count = count + additional_metadata_count;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800844 int i;
845 grpc_metadata_batch *batch =
846 &call->metadata_batch[0 /* is_receiving */][is_trailing];
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700847 for (i = 0; i < total_count; i++) {
848 const grpc_metadata *md =
849 get_md_elem(metadata, additional_metadata, i, count);
Craig Tillerb42445c2016-04-22 13:11:44 -0700850 grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
851 GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
Craig Tillerf2b5b7e2017-01-10 08:28:59 -0800852 if (!GRPC_LOG_IF_ERROR("validate_metadata",
853 grpc_validate_header_key_is_legal(md->key))) {
Craig Tillerb42445c2016-04-22 13:11:44 -0700854 break;
Craig Tillerdf2d9222016-11-18 16:38:57 -0800855 } else if (!grpc_is_binary_header(md->key) &&
Craig Tillerf2b5b7e2017-01-10 08:28:59 -0800856 !GRPC_LOG_IF_ERROR(
857 "validate_metadata",
858 grpc_validate_header_nonbin_value_is_legal(md->value))) {
Craig Tillerb42445c2016-04-22 13:11:44 -0700859 break;
860 }
Craig Tiller1282a672016-11-18 14:57:53 -0800861 l->md = grpc_mdelem_from_grpc_metadata(exec_ctx, (grpc_metadata *)md);
Craig Tillerb42445c2016-04-22 13:11:44 -0700862 }
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700863 if (i != total_count) {
Craig Tiller5ae3ffb2016-11-18 14:58:32 -0800864 for (int j = 0; j < i; j++) {
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700865 const grpc_metadata *md =
866 get_md_elem(metadata, additional_metadata, j, count);
Craig Tillerb42445c2016-04-22 13:11:44 -0700867 grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
Craig Tillera59c16c2016-10-31 07:25:01 -0700868 GRPC_MDELEM_UNREF(exec_ctx, l->md);
Craig Tillerb42445c2016-04-22 13:11:44 -0700869 }
870 return 0;
871 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800872 if (prepend_extra_metadata) {
873 if (call->send_extra_metadata_count == 0) {
874 prepend_extra_metadata = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700875 } else {
Craig Tiller09608182016-11-22 15:43:56 -0800876 for (i = 0; i < call->send_extra_metadata_count; i++) {
877 GRPC_LOG_IF_ERROR("prepare_application_metadata",
878 grpc_metadata_batch_link_tail(
Craig Tiller9277aa72017-01-11 14:15:38 -0800879 exec_ctx, batch, &call->send_extra_metadata[i]));
Craig Tillera82950e2015-09-22 12:33:20 -0700880 }
Craig Tiller629b0ed2015-04-22 11:14:26 -0700881 }
Craig Tillera82950e2015-09-22 12:33:20 -0700882 }
Craig Tiller09608182016-11-22 15:43:56 -0800883 for (i = 0; i < total_count; i++) {
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700884 grpc_metadata *md = get_md_elem(metadata, additional_metadata, i, count);
Craig Tiller9277aa72017-01-11 14:15:38 -0800885 GRPC_LOG_IF_ERROR(
886 "prepare_application_metadata",
887 grpc_metadata_batch_link_tail(exec_ctx, batch, linked_from_md(md)));
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800888 }
Craig Tiller09608182016-11-22 15:43:56 -0800889 call->send_extra_metadata_count = 0;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800890
Craig Tillerb96d0012015-05-06 15:33:23 -0700891 return 1;
892}
893
Craig Tiller566316f2015-02-02 15:25:32 -0800894/* we offset status by a small amount when storing it into transport metadata
895 as metadata cannot store a 0 value (which is used as OK for grpc_status_codes
896 */
897#define STATUS_OFFSET 1
Craig Tillera82950e2015-09-22 12:33:20 -0700898static void destroy_status(void *ignored) {}
Craig Tiller566316f2015-02-02 15:25:32 -0800899
Craig Tiller0160de92016-11-18 08:46:46 -0800900static uint32_t decode_status(grpc_mdelem md) {
Craig Tiller7536af02015-12-22 13:49:30 -0800901 uint32_t status;
Craig Tillerebdef9d2015-11-19 17:09:49 -0800902 void *user_data;
Craig Tiller0160de92016-11-18 08:46:46 -0800903 if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) return 0;
904 if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_1)) return 1;
905 if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_2)) return 2;
Craig Tillerebdef9d2015-11-19 17:09:49 -0800906 user_data = grpc_mdelem_get_user_data(md, destroy_status);
907 if (user_data != NULL) {
Craig Tiller7536af02015-12-22 13:49:30 -0800908 status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET;
Craig Tillera82950e2015-09-22 12:33:20 -0700909 } else {
Craig Tiller0160de92016-11-18 08:46:46 -0800910 if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(md), &status)) {
Craig Tillera82950e2015-09-22 12:33:20 -0700911 status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
Craig Tiller566316f2015-02-02 15:25:32 -0800912 }
Craig Tillera82950e2015-09-22 12:33:20 -0700913 grpc_mdelem_set_user_data(md, destroy_status,
Craig Tiller7536af02015-12-22 13:49:30 -0800914 (void *)(intptr_t)(status + STATUS_OFFSET));
Craig Tillera82950e2015-09-22 12:33:20 -0700915 }
Craig Tiller566316f2015-02-02 15:25:32 -0800916 return status;
917}
918
Craig Tiller0160de92016-11-18 08:46:46 -0800919static grpc_compression_algorithm decode_compression(grpc_mdelem md) {
Craig Tillerebdef9d2015-11-19 17:09:49 -0800920 grpc_compression_algorithm algorithm =
Craig Tiller0160de92016-11-18 08:46:46 -0800921 grpc_compression_algorithm_from_slice(GRPC_MDVALUE(md));
Craig Tillerebdef9d2015-11-19 17:09:49 -0800922 if (algorithm == GRPC_COMPRESS_ALGORITHMS_COUNT) {
Craig Tillerb4aa70e2016-12-09 09:40:11 -0800923 char *md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
David Garcia Quintas303d3082016-05-05 18:25:34 -0700924 gpr_log(GPR_ERROR,
925 "Invalid incoming compression algorithm: '%s'. Interpreting "
926 "incoming data as uncompressed.",
927 md_c_str);
Craig Tiller68208fe2016-11-14 14:35:02 -0800928 gpr_free(md_c_str);
David Garcia Quintas303d3082016-05-05 18:25:34 -0700929 return GRPC_COMPRESS_NONE;
Craig Tillera82950e2015-09-22 12:33:20 -0700930 }
David Garcia Quintasfc0fa332015-06-25 18:11:07 -0700931 return algorithm;
David Garcia Quintasdb94b272015-06-15 18:37:01 -0700932}
933
Craig Tillera7d37a32016-11-22 14:37:16 -0800934static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
935 int is_trailing) {
Craig Tiller09608182016-11-22 15:43:56 -0800936 if (b->list.count == 0) return;
Craig Tillera7d37a32016-11-22 14:37:16 -0800937 GPR_TIMER_BEGIN("publish_app_metadata", 0);
Craig Tiller566316f2015-02-02 15:25:32 -0800938 grpc_metadata_array *dest;
939 grpc_metadata *mdusr;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800940 dest = call->buffered_metadata[is_trailing];
Craig Tillerb0f3bca2016-11-22 14:54:10 -0800941 if (dest->count + b->list.count > dest->capacity) {
942 dest->capacity =
943 GPR_MAX(dest->capacity + b->list.count, dest->capacity * 3 / 2);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800944 dest->metadata =
945 gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
946 }
Craig Tillera7d37a32016-11-22 14:37:16 -0800947 for (grpc_linked_mdelem *l = b->list.head; l != NULL; l = l->next) {
948 mdusr = &dest->metadata[dest->count++];
Craig Tillercf0a2022016-11-23 11:36:21 -0800949 /* we pass back borrowed slices that are valid whilst the call is valid */
950 mdusr->key = GRPC_MDKEY(l->md);
951 mdusr->value = GRPC_MDVALUE(l->md);
Craig Tillera7d37a32016-11-22 14:37:16 -0800952 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800953 GPR_TIMER_END("publish_app_metadata", 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800954}
Craig Tiller566316f2015-02-02 15:25:32 -0800955
Craig Tillera7d37a32016-11-22 14:37:16 -0800956static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
957 grpc_metadata_batch *b) {
Craig Tillera7d37a32016-11-22 14:37:16 -0800958 if (b->idx.named.grpc_encoding != NULL) {
David Garcia Quintas749367f2016-05-17 19:15:24 -0700959 GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
Craig Tillera7d37a32016-11-22 14:37:16 -0800960 set_incoming_compression_algorithm(
961 call, decode_compression(b->idx.named.grpc_encoding->md));
David Garcia Quintas749367f2016-05-17 19:15:24 -0700962 GPR_TIMER_END("incoming_compression_algorithm", 0);
Craig Tillerde7b4672016-11-23 11:13:46 -0800963 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding);
Craig Tillera82950e2015-09-22 12:33:20 -0700964 }
Craig Tillera7d37a32016-11-22 14:37:16 -0800965 if (b->idx.named.grpc_accept_encoding != NULL) {
966 GPR_TIMER_BEGIN("encodings_accepted_by_peer", 0);
967 set_encodings_accepted_by_peer(exec_ctx, call,
968 b->idx.named.grpc_accept_encoding->md);
Craig Tillerde7b4672016-11-23 11:13:46 -0800969 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding);
Craig Tillera7d37a32016-11-22 14:37:16 -0800970 GPR_TIMER_END("encodings_accepted_by_peer", 0);
971 }
Craig Tillera7d37a32016-11-22 14:37:16 -0800972 publish_app_metadata(call, b, false);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800973}
Craig Tiller6902ad22015-04-16 08:01:49 -0700974
Craig Tillera7d37a32016-11-22 14:37:16 -0800975static void recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args,
976 grpc_metadata_batch *b) {
Craig Tillerc5866662016-11-16 15:25:00 -0800977 grpc_call *call = args;
Mark D. Rothbd3b93b2017-06-22 10:53:01 -0700978 if (b->idx.named.grpc_status != NULL) {
979 uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
980 grpc_error *error =
981 status_code == GRPC_STATUS_OK
982 ? GRPC_ERROR_NONE
983 : grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
984 "Error received from peer"),
985 GRPC_ERROR_INT_GRPC_STATUS,
986 (intptr_t)status_code);
987 if (b->idx.named.grpc_message != NULL) {
988 error = grpc_error_set_str(
989 error, GRPC_ERROR_STR_GRPC_MESSAGE,
990 grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md)));
991 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_message);
992 } else if (error != GRPC_ERROR_NONE) {
993 error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
994 grpc_empty_slice());
995 }
996 set_status_from_error(exec_ctx, call, STATUS_FROM_WIRE, error);
997 grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_status);
998 }
Craig Tillera7d37a32016-11-22 14:37:16 -0800999 publish_app_metadata(call, b, true);
Craig Tiller629b0ed2015-04-22 11:14:26 -07001000}
Craig Tiller8b282cb2015-04-17 14:57:44 -07001001
Craig Tillera82950e2015-09-22 12:33:20 -07001002grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) {
1003 return CALL_STACK_FROM_CALL(call);
Craig Tiller566316f2015-02-02 15:25:32 -08001004}
1005
Craig Tiller255edaa2016-12-13 09:04:55 -08001006/*******************************************************************************
Craig Tillerfb189f82015-02-03 12:07:07 -08001007 * BATCH API IMPLEMENTATION
1008 */
1009
Craig Tillera82950e2015-09-22 12:33:20 -07001010static void set_status_value_directly(grpc_status_code status, void *dest) {
1011 *(grpc_status_code *)dest = status;
Craig Tillerfb189f82015-02-03 12:07:07 -08001012}
1013
Craig Tillera82950e2015-09-22 12:33:20 -07001014static void set_cancelled_value(grpc_status_code status, void *dest) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001015 *(int *)dest = (status != GRPC_STATUS_OK);
Craig Tiller166e2502015-02-03 20:14:41 -08001016}
Craig Tillerfb189f82015-02-03 12:07:07 -08001017
Craig Tillerc6549762016-03-09 17:10:43 -08001018static bool are_write_flags_valid(uint32_t flags) {
David Garcia Quintas1d5aca52015-06-14 14:42:04 -07001019 /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */
Craig Tiller7536af02015-12-22 13:49:30 -08001020 const uint32_t allowed_write_positions =
Craig Tillera82950e2015-09-22 12:33:20 -07001021 (GRPC_WRITE_USED_MASK | GRPC_WRITE_INTERNAL_USED_MASK);
Craig Tiller7536af02015-12-22 13:49:30 -08001022 const uint32_t invalid_positions = ~allowed_write_positions;
David Garcia Quintas1d5aca52015-06-14 14:42:04 -07001023 return !(flags & invalid_positions);
1024}
1025
Craig Tillerc6549762016-03-09 17:10:43 -08001026static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) {
1027 /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */
1028 uint32_t invalid_positions = ~GRPC_INITIAL_METADATA_USED_MASK;
1029 if (!is_client) {
1030 invalid_positions |= GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST;
1031 }
1032 return !(flags & invalid_positions);
1033}
1034
Craig Tiller2a11ad12017-02-08 17:09:02 -08001035static int batch_slot_for_op(grpc_op_type type) {
1036 switch (type) {
1037 case GRPC_OP_SEND_INITIAL_METADATA:
1038 return 0;
1039 case GRPC_OP_SEND_MESSAGE:
1040 return 1;
1041 case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
1042 case GRPC_OP_SEND_STATUS_FROM_SERVER:
1043 return 2;
1044 case GRPC_OP_RECV_INITIAL_METADATA:
1045 return 3;
1046 case GRPC_OP_RECV_MESSAGE:
1047 return 4;
1048 case GRPC_OP_RECV_CLOSE_ON_SERVER:
1049 case GRPC_OP_RECV_STATUS_ON_CLIENT:
1050 return 5;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001051 }
Craig Tillerc869da02017-02-08 17:11:17 -08001052 GPR_UNREACHABLE_CODE(return 123456789);
Craig Tiller2a11ad12017-02-08 17:09:02 -08001053}
Craig Tiller89d33792017-02-08 16:39:16 -08001054
1055static batch_control *allocate_batch_control(grpc_call *call,
1056 const grpc_op *ops,
1057 size_t num_ops) {
1058 int slot = batch_slot_for_op(ops[0].op);
Craig Tillerb58de722017-03-29 14:15:12 -07001059 batch_control **pslot = &call->active_batches[slot];
1060 if (*pslot == NULL) {
1061 *pslot = gpr_arena_alloc(call->arena, sizeof(batch_control));
1062 }
1063 batch_control *bctl = *pslot;
Craig Tiller5e5ef302017-02-09 08:46:49 -08001064 if (bctl->call != NULL) {
1065 return NULL;
1066 }
1067 memset(bctl, 0, sizeof(*bctl));
1068 bctl->call = call;
Craig Tiller3fddcb42017-03-10 11:01:48 -08001069 bctl->op.payload = &call->stream_op_payload;
Craig Tiller5e5ef302017-02-09 08:46:49 -08001070 return bctl;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001071}
1072
1073static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
1074 grpc_cq_completion *storage) {
1075 batch_control *bctl = user_data;
1076 grpc_call *call = bctl->call;
Craig Tiller5e5ef302017-02-09 08:46:49 -08001077 bctl->call = NULL;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001078 GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
1079}
1080
Craig Tiller94903892016-10-11 15:43:35 -07001081static grpc_error *consolidate_batch_errors(batch_control *bctl) {
Craig Tillerb597dcf2017-03-09 07:02:11 -08001082 size_t n = (size_t)gpr_atm_acq_load(&bctl->num_errors);
Craig Tiller94903892016-10-11 15:43:35 -07001083 if (n == 0) {
1084 return GRPC_ERROR_NONE;
1085 } else if (n == 1) {
Craig Tillera78da602017-01-27 08:16:23 -08001086 /* Skip creating a composite error in the case that only one error was
1087 logged */
Craig Tillerad980e32017-01-23 07:46:25 -08001088 grpc_error *e = bctl->errors[0];
1089 bctl->errors[0] = NULL;
1090 return e;
Craig Tiller94903892016-10-11 15:43:35 -07001091 } else {
ncteisen4b36a3d2017-03-13 19:08:06 -07001092 grpc_error *error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1093 "Call batch failed", bctl->errors, n);
Craig Tiller1c4775c2017-01-06 16:07:45 -08001094 for (size_t i = 0; i < n; i++) {
1095 GRPC_ERROR_UNREF(bctl->errors[i]);
Craig Tillerad980e32017-01-23 07:46:25 -08001096 bctl->errors[i] = NULL;
Craig Tiller1c4775c2017-01-06 16:07:45 -08001097 }
1098 return error;
Craig Tiller94903892016-10-11 15:43:35 -07001099 }
1100}
1101
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001102static void post_batch_completion(grpc_exec_ctx *exec_ctx,
1103 batch_control *bctl) {
Craig Tiller94903892016-10-11 15:43:35 -07001104 grpc_call *next_child_call;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001105 grpc_call *call = bctl->call;
Craig Tiller94903892016-10-11 15:43:35 -07001106 grpc_error *error = consolidate_batch_errors(bctl);
1107
Craig Tillerea54b8c2017-03-01 16:58:28 -08001108 if (bctl->op.send_initial_metadata) {
Craig Tiller94903892016-10-11 15:43:35 -07001109 grpc_metadata_batch_destroy(
1110 exec_ctx,
1111 &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
1112 }
Craig Tillerea54b8c2017-03-01 16:58:28 -08001113 if (bctl->op.send_message) {
Craig Tillerf927ad12017-01-06 15:27:31 -08001114 call->sending_message = false;
1115 }
Craig Tillerea54b8c2017-03-01 16:58:28 -08001116 if (bctl->op.send_trailing_metadata) {
Craig Tiller94903892016-10-11 15:43:35 -07001117 grpc_metadata_batch_destroy(
1118 exec_ctx,
1119 &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
1120 }
Craig Tillerea54b8c2017-03-01 16:58:28 -08001121 if (bctl->op.recv_trailing_metadata) {
Craig Tiller94903892016-10-11 15:43:35 -07001122 grpc_metadata_batch *md =
1123 &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
1124 recv_trailing_filter(exec_ctx, call, md);
1125
Craig Tiller94903892016-10-11 15:43:35 -07001126 /* propagate cancellation to any interested children */
Craig Tillerb18c8ba2017-03-13 15:51:37 -07001127 gpr_atm_rel_store(&call->received_final_op_atm, 1);
Craig Tiller1c10a7b2017-03-29 14:35:16 -07001128 parent_call *pc = get_parent_call(call);
1129 if (pc != NULL) {
1130 grpc_call *child;
1131 gpr_mu_lock(&pc->child_list_mu);
1132 child = pc->first_child;
1133 if (child != NULL) {
1134 do {
1135 next_child_call = child->child_call->sibling_next;
1136 if (child->cancellation_is_inherited) {
1137 GRPC_CALL_INTERNAL_REF(child, "propagate_cancel");
1138 cancel_with_error(exec_ctx, child, STATUS_FROM_API_OVERRIDE,
1139 GRPC_ERROR_CANCELLED);
1140 GRPC_CALL_INTERNAL_UNREF(exec_ctx, child, "propagate_cancel");
1141 }
1142 child = next_child_call;
1143 } while (child != pc->first_child);
1144 }
1145 gpr_mu_unlock(&pc->child_list_mu);
Craig Tiller94903892016-10-11 15:43:35 -07001146 }
1147
1148 if (call->is_client) {
1149 get_final_status(call, set_status_value_directly,
Craig Tiller841a99d2016-12-12 16:58:57 -08001150 call->final_op.client.status,
1151 call->final_op.client.status_details);
Craig Tiller94903892016-10-11 15:43:35 -07001152 } else {
1153 get_final_status(call, set_cancelled_value,
Craig Tiller841a99d2016-12-12 16:58:57 -08001154 call->final_op.server.cancelled, NULL);
Craig Tiller94903892016-10-11 15:43:35 -07001155 }
1156
Craig Tiller02b87cd2016-09-02 09:50:08 -07001157 GRPC_ERROR_UNREF(error);
1158 error = GRPC_ERROR_NONE;
1159 }
Craig Tiller94903892016-10-11 15:43:35 -07001160
Craig Tillerea54b8c2017-03-01 16:58:28 -08001161 if (bctl->completion_data.notify_tag.is_closure) {
Craig Tillerb08fa492016-05-10 14:56:05 -07001162 /* unrefs bctl->error */
Craig Tiller2db5bda2017-02-09 10:30:55 -08001163 bctl->call = NULL;
ncteisen969b46e2017-06-08 14:57:11 -07001164 GRPC_CLOSURE_RUN(exec_ctx, bctl->completion_data.notify_tag.tag, error);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001165 GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
1166 } else {
Craig Tillerb08fa492016-05-10 14:56:05 -07001167 /* unrefs bctl->error */
Craig Tiller9c1ec542017-03-02 08:42:54 -08001168 grpc_cq_end_op(
1169 exec_ctx, bctl->call->cq, bctl->completion_data.notify_tag.tag, error,
1170 finish_batch_completion, bctl, &bctl->completion_data.cq_completion);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001171 }
1172}
1173
Craig Tillerd04dc4d2017-01-09 14:40:28 -08001174static void finish_batch_step(grpc_exec_ctx *exec_ctx, batch_control *bctl) {
Craig Tiller065b1392017-01-09 14:05:07 -08001175 if (gpr_unref(&bctl->steps_to_complete)) {
1176 post_batch_completion(exec_ctx, bctl);
1177 }
1178}
1179
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001180static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
1181 batch_control *bctl) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001182 grpc_error *error;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001183 grpc_call *call = bctl->call;
1184 for (;;) {
1185 size_t remaining = call->receiving_stream->length -
1186 (*call->receiving_buffer)->data.raw.slice_buffer.length;
1187 if (remaining == 0) {
1188 call->receiving_message = 0;
Craig Tiller3b66ab92015-12-09 19:42:22 -08001189 grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001190 call->receiving_stream = NULL;
Craig Tillerd04dc4d2017-01-09 14:40:28 -08001191 finish_batch_step(exec_ctx, bctl);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001192 return;
1193 }
Muxi Yan29723ee2017-04-12 20:24:42 -07001194 if (grpc_byte_stream_next(exec_ctx, call->receiving_stream, remaining,
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001195 &call->receiving_slice_ready)) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001196 error = grpc_byte_stream_pull(exec_ctx, call->receiving_stream,
1197 &call->receiving_slice);
1198 if (error == GRPC_ERROR_NONE) {
1199 grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
1200 call->receiving_slice);
1201 } else {
1202 grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
1203 call->receiving_stream = NULL;
1204 grpc_byte_buffer_destroy(*call->receiving_buffer);
1205 *call->receiving_buffer = NULL;
1206 call->receiving_message = 0;
1207 finish_batch_step(exec_ctx, bctl);
1208 return;
1209 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001210 } else {
1211 return;
1212 }
1213 }
1214}
1215
1216static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
Craig Tillerc027e772016-05-03 16:27:00 -07001217 grpc_error *error) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001218 batch_control *bctl = bctlp;
1219 grpc_call *call = bctl->call;
Muxi Yan29723ee2017-04-12 20:24:42 -07001220 grpc_byte_stream *bs = call->receiving_stream;
1221 bool release_error = false;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001222
Craig Tillerc027e772016-05-03 16:27:00 -07001223 if (error == GRPC_ERROR_NONE) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001224 grpc_slice slice;
1225 error = grpc_byte_stream_pull(exec_ctx, bs, &slice);
1226 if (error == GRPC_ERROR_NONE) {
1227 grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
1228 slice);
1229 continue_receiving_slices(exec_ctx, bctl);
1230 } else {
1231 /* Error returned by grpc_byte_stream_pull needs to be released manually
1232 */
1233 release_error = true;
1234 }
1235 }
1236
1237 if (error != GRPC_ERROR_NONE) {
Craig Tiller84f75d42017-05-03 13:06:35 -07001238 if (GRPC_TRACER_ON(grpc_trace_operation_failures)) {
Craig Tillera286b042016-06-13 15:20:39 +00001239 GRPC_LOG_IF_ERROR("receiving_slice_ready", GRPC_ERROR_REF(error));
1240 }
Craig Tillere1b8c2b2015-12-16 19:27:52 -08001241 grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
Craig Tiller38edec62015-12-14 15:01:29 -08001242 call->receiving_stream = NULL;
1243 grpc_byte_buffer_destroy(*call->receiving_buffer);
1244 *call->receiving_buffer = NULL;
Muxi Yan29723ee2017-04-12 20:24:42 -07001245 call->receiving_message = 0;
Craig Tillerd04dc4d2017-01-09 14:40:28 -08001246 finish_batch_step(exec_ctx, bctl);
Muxi Yan29723ee2017-04-12 20:24:42 -07001247 if (release_error) {
1248 GRPC_ERROR_UNREF(error);
1249 }
Craig Tiller38edec62015-12-14 15:01:29 -08001250 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001251}
1252
Mark D. Roth274c8ed2016-10-04 09:21:42 -07001253static void process_data_after_md(grpc_exec_ctx *exec_ctx,
1254 batch_control *bctl) {
Craig Tillera44cbfc2016-02-03 16:02:49 -08001255 grpc_call *call = bctl->call;
1256 if (call->receiving_stream == NULL) {
1257 *call->receiving_buffer = NULL;
1258 call->receiving_message = 0;
Craig Tillerd04dc4d2017-01-09 14:40:28 -08001259 finish_batch_step(exec_ctx, bctl);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001260 } else {
1261 call->test_only_last_message_flags = call->receiving_stream->flags;
1262 if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) &&
David Garcia Quintas749367f2016-05-17 19:15:24 -07001263 (call->incoming_compression_algorithm > GRPC_COMPRESS_NONE)) {
Craig Tillera44cbfc2016-02-03 16:02:49 -08001264 *call->receiving_buffer = grpc_raw_compressed_byte_buffer_create(
David Garcia Quintas749367f2016-05-17 19:15:24 -07001265 NULL, 0, call->incoming_compression_algorithm);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001266 } else {
1267 *call->receiving_buffer = grpc_raw_byte_buffer_create(NULL, 0);
1268 }
ncteisen969b46e2017-06-08 14:57:11 -07001269 GRPC_CLOSURE_INIT(&call->receiving_slice_ready, receiving_slice_ready, bctl,
Craig Tiller91031da2016-12-28 15:44:25 -08001270 grpc_schedule_on_exec_ctx);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001271 continue_receiving_slices(exec_ctx, bctl);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001272 }
1273}
1274
1275static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
Craig Tillerc027e772016-05-03 16:27:00 -07001276 grpc_error *error) {
Craig Tillera44cbfc2016-02-03 16:02:49 -08001277 batch_control *bctl = bctlp;
1278 grpc_call *call = bctl->call;
Mark D. Roth274c8ed2016-10-04 09:21:42 -07001279 if (error != GRPC_ERROR_NONE) {
yang-g23f777d2017-02-22 23:32:26 -08001280 if (call->receiving_stream != NULL) {
1281 grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
1282 call->receiving_stream = NULL;
1283 }
1284 add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), true);
Craig Tiller58b30cd2017-01-31 17:07:36 -08001285 cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
1286 GRPC_ERROR_REF(error));
Mark D. Roth274c8ed2016-10-04 09:21:42 -07001287 }
Craig Tiller065b1392017-01-09 14:05:07 -08001288 if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
Craig Tiller52cf8712016-04-23 22:54:21 -07001289 call->receiving_stream == NULL) {
Mark D. Roth274c8ed2016-10-04 09:21:42 -07001290 process_data_after_md(exec_ctx, bctlp);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001291 } else {
Craig Tiller8a677802016-04-22 15:07:53 -07001292 call->saved_receiving_stream_ready_bctlp = bctlp;
Craig Tillera44cbfc2016-02-03 16:02:49 -08001293 }
1294}
1295
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001296static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
1297 batch_control *bctl) {
1298 grpc_call *call = bctl->call;
David Garcia Quintasac094472016-05-18 20:25:57 -07001299 /* validate call->incoming_compression_algorithm */
1300 if (call->incoming_compression_algorithm != GRPC_COMPRESS_NONE) {
1301 const grpc_compression_algorithm algo =
1302 call->incoming_compression_algorithm;
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001303 char *error_msg = NULL;
1304 const grpc_compression_options compression_options =
David Garcia Quintasac094472016-05-18 20:25:57 -07001305 grpc_channel_compression_options(call->channel);
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001306 /* check if algorithm is known */
1307 if (algo >= GRPC_COMPRESS_ALGORITHMS_COUNT) {
1308 gpr_asprintf(&error_msg, "Invalid compression algorithm value '%d'.",
1309 algo);
Yuchen Zeng64c0e8d2016-06-10 11:19:51 -07001310 gpr_log(GPR_ERROR, "%s", error_msg);
Craig Tiller2dc32ea2017-01-31 15:32:34 -08001311 cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
1312 GRPC_STATUS_UNIMPLEMENTED, error_msg);
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001313 } else if (grpc_compression_options_is_algorithm_enabled(
1314 &compression_options, algo) == 0) {
1315 /* check if algorithm is supported by current channel config */
David Garcia Quintas1ff168a2016-06-30 10:25:04 -07001316 char *algo_name = NULL;
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001317 grpc_compression_algorithm_name(algo, &algo_name);
1318 gpr_asprintf(&error_msg, "Compression algorithm '%s' is disabled.",
1319 algo_name);
Yuchen Zeng64c0e8d2016-06-10 11:19:51 -07001320 gpr_log(GPR_ERROR, "%s", error_msg);
Craig Tiller2dc32ea2017-01-31 15:32:34 -08001321 cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
1322 GRPC_STATUS_UNIMPLEMENTED, error_msg);
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001323 } else {
David Garcia Quintasac094472016-05-18 20:25:57 -07001324 call->incoming_compression_algorithm = algo;
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001325 }
1326 gpr_free(error_msg);
1327 }
David Garcia Quintasf1945f22016-05-18 10:53:14 -07001328
1329 /* make sure the received grpc-encoding is amongst the ones listed in
1330 * grpc-accept-encoding */
1331 GPR_ASSERT(call->encodings_accepted_by_peer != 0);
1332 if (!GPR_BITGET(call->encodings_accepted_by_peer,
David Garcia Quintasac094472016-05-18 20:25:57 -07001333 call->incoming_compression_algorithm)) {
Craig Tiller84f75d42017-05-03 13:06:35 -07001334 if (GRPC_TRACER_ON(grpc_compression_trace)) {
David Garcia Quintas1ff168a2016-06-30 10:25:04 -07001335 char *algo_name = NULL;
David Garcia Quintasac094472016-05-18 20:25:57 -07001336 grpc_compression_algorithm_name(call->incoming_compression_algorithm,
1337 &algo_name);
David Garcia Quintasf1945f22016-05-18 10:53:14 -07001338 gpr_log(GPR_ERROR,
1339 "Compression algorithm (grpc-encoding = '%s') not present in "
1340 "the bitset of accepted encodings (grpc-accept-encodings: "
1341 "'0x%x')",
1342 algo_name, call->encodings_accepted_by_peer);
1343 }
1344 }
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001345}
1346
Craig Tiller3ba16e42016-12-08 16:46:18 -08001347static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
yang-g23f777d2017-02-22 23:32:26 -08001348 grpc_error *error, bool has_cancelled) {
Craig Tiller452422e2016-09-01 15:54:56 -07001349 if (error == GRPC_ERROR_NONE) return;
Craig Tillerb597dcf2017-03-09 07:02:11 -08001350 int idx = (int)gpr_atm_full_fetch_add(&bctl->num_errors, 1);
yang-g23f777d2017-02-22 23:32:26 -08001351 if (idx == 0 && !has_cancelled) {
Craig Tiller2dc32ea2017-01-31 15:32:34 -08001352 cancel_with_error(exec_ctx, bctl->call, STATUS_FROM_CORE,
1353 GRPC_ERROR_REF(error));
1354 }
Craig Tiller94903892016-10-11 15:43:35 -07001355 bctl->errors[idx] = error;
Craig Tiller452422e2016-09-01 15:54:56 -07001356}
1357
Craig Tillera44cbfc2016-02-03 16:02:49 -08001358static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
Craig Tillerc027e772016-05-03 16:27:00 -07001359 void *bctlp, grpc_error *error) {
Craig Tillera44cbfc2016-02-03 16:02:49 -08001360 batch_control *bctl = bctlp;
1361 grpc_call *call = bctl->call;
1362
yang-g23f777d2017-02-22 23:32:26 -08001363 add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
Craig Tiller452422e2016-09-01 15:54:56 -07001364 if (error == GRPC_ERROR_NONE) {
Craig Tillerc48ca712016-04-04 13:42:04 -07001365 grpc_metadata_batch *md =
1366 &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
Craig Tillera7d37a32016-11-22 14:37:16 -08001367 recv_initial_filter(exec_ctx, call, md);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001368
Craig Tillera7d37a32016-11-22 14:37:16 -08001369 /* TODO(ctiller): this could be moved into recv_initial_filter now */
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001370 GPR_TIMER_BEGIN("validate_filtered_metadata", 0);
1371 validate_filtered_metadata(exec_ctx, bctl);
1372 GPR_TIMER_END("validate_filtered_metadata", 0);
David Garcia Quintas46123372016-05-09 15:28:42 -07001373
Craig Tillerc48ca712016-04-04 13:42:04 -07001374 if (gpr_time_cmp(md->deadline, gpr_inf_future(md->deadline.clock_type)) !=
1375 0 &&
1376 !call->is_client) {
Mark D. Rothf28763c2016-09-14 15:18:40 -07001377 call->send_deadline =
1378 gpr_convert_clock_type(md->deadline, GPR_CLOCK_MONOTONIC);
Craig Tillerc48ca712016-04-04 13:42:04 -07001379 }
Craig Tillera44cbfc2016-02-03 16:02:49 -08001380 }
1381
Craig Tillerc48ca712016-04-04 13:42:04 -07001382 call->has_initial_md_been_received = true;
Craig Tiller8a677802016-04-22 15:07:53 -07001383 if (call->saved_receiving_stream_ready_bctlp != NULL) {
ncteisen969b46e2017-06-08 14:57:11 -07001384 grpc_closure *saved_rsr_closure = GRPC_CLOSURE_CREATE(
Craig Tiller91031da2016-12-28 15:44:25 -08001385 receiving_stream_ready, call->saved_receiving_stream_ready_bctlp,
1386 grpc_schedule_on_exec_ctx);
Craig Tiller8a677802016-04-22 15:07:53 -07001387 call->saved_receiving_stream_ready_bctlp = NULL;
ncteisen969b46e2017-06-08 14:57:11 -07001388 GRPC_CLOSURE_RUN(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error));
Craig Tillera44cbfc2016-02-03 16:02:49 -08001389 }
1390
Craig Tillerd04dc4d2017-01-09 14:40:28 -08001391 finish_batch_step(exec_ctx, bctl);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001392}
1393
Craig Tillerc027e772016-05-03 16:27:00 -07001394static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
1395 grpc_error *error) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001396 batch_control *bctl = bctlp;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001397
yang-g23f777d2017-02-22 23:32:26 -08001398 add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
Craig Tillerd04dc4d2017-01-09 14:40:28 -08001399 finish_batch_step(exec_ctx, bctl);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001400}
1401
Craig Tiller89d33792017-02-08 16:39:16 -08001402static void free_no_op_completion(grpc_exec_ctx *exec_ctx, void *p,
1403 grpc_cq_completion *completion) {
1404 gpr_free(completion);
1405}
1406
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001407static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1408 grpc_call *call, const grpc_op *ops,
1409 size_t nops, void *notify_tag,
1410 int is_notify_tag_closure) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001411 size_t i;
Craig Tillerfb189f82015-02-03 12:07:07 -08001412 const grpc_op *op;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001413 batch_control *bctl;
1414 int num_completion_callbacks_needed = 1;
1415 grpc_call_error error = GRPC_CALL_OK;
Craig Tiller9928d392015-08-18 09:40:24 -07001416
Vitaly Bukae60003d2016-08-01 19:34:51 -07001417 // sent_initial_metadata guards against variable reuse.
1418 grpc_metadata compression_md;
1419
Craig Tiller0ba432d2015-10-09 16:57:11 -07001420 GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001421 GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
Masood Malekghassemi76c3d742015-08-19 18:22:53 -07001422
Craig Tillera82950e2015-09-22 12:33:20 -07001423 if (nops == 0) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001424 if (!is_notify_tag_closure) {
yang-g0eaf7de2017-07-05 16:50:51 -07001425 GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag) == 0);
Craig Tiller89d33792017-02-08 16:39:16 -08001426 grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
1427 free_no_op_completion, NULL,
1428 gpr_malloc(sizeof(grpc_cq_completion)));
Craig Tiller2db5bda2017-02-09 10:30:55 -08001429 } else {
ncteisen969b46e2017-06-08 14:57:11 -07001430 GRPC_CLOSURE_SCHED(exec_ctx, notify_tag, GRPC_ERROR_NONE);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001431 }
Craig Tillerea50b902015-12-15 07:05:25 -08001432 error = GRPC_CALL_OK;
1433 goto done;
Craig Tillera82950e2015-09-22 12:33:20 -07001434 }
1435
Craig Tiller89d33792017-02-08 16:39:16 -08001436 bctl = allocate_batch_control(call, ops, nops);
Craig Tiller5e5ef302017-02-09 08:46:49 -08001437 if (bctl == NULL) {
1438 return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1439 }
Craig Tillerea54b8c2017-03-01 16:58:28 -08001440 bctl->completion_data.notify_tag.tag = notify_tag;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001441 bctl->completion_data.notify_tag.is_closure =
1442 (uint8_t)(is_notify_tag_closure != 0);
Craig Tillera82950e2015-09-22 12:33:20 -07001443
Craig Tillera0f3abd2017-03-31 15:42:16 -07001444 grpc_transport_stream_op_batch *stream_op = &bctl->op;
1445 grpc_transport_stream_op_batch_payload *stream_op_payload =
Craig Tiller9c1ec542017-03-02 08:42:54 -08001446 &call->stream_op_payload;
Craig Tillera82950e2015-09-22 12:33:20 -07001447
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001448 /* rewrite batch ops into a transport op */
1449 for (i = 0; i < nops; i++) {
1450 op = &ops[i];
Craig Tillera82950e2015-09-22 12:33:20 -07001451 if (op->reserved != NULL) {
Craig Tiller3ffd8222015-09-21 08:21:57 -07001452 error = GRPC_CALL_ERROR;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001453 goto done_with_error;
Craig Tiller3ffd8222015-09-21 08:21:57 -07001454 }
Craig Tillera82950e2015-09-22 12:33:20 -07001455 switch (op->op) {
1456 case GRPC_OP_SEND_INITIAL_METADATA:
1457 /* Flag validation: currently allow no flags */
Craig Tillerc6549762016-03-09 17:10:43 -08001458 if (!are_initial_metadata_flags_valid(op->flags, call->is_client)) {
Craig Tillera82950e2015-09-22 12:33:20 -07001459 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001460 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001461 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001462 if (call->sent_initial_metadata) {
1463 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1464 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001465 }
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001466 /* process compression level */
Vitaly Bukae60003d2016-08-01 19:34:51 -07001467 memset(&compression_md, 0, sizeof(compression_md));
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001468 size_t additional_metadata_count = 0;
David Garcia Quintas749367f2016-05-17 19:15:24 -07001469 grpc_compression_level effective_compression_level;
1470 bool level_set = false;
1471 if (op->data.send_initial_metadata.maybe_compression_level.is_set) {
David Garcia Quintas749367f2016-05-17 19:15:24 -07001472 effective_compression_level =
David Garcia Quintas8ba42be2016-06-07 17:30:20 -07001473 op->data.send_initial_metadata.maybe_compression_level.level;
David Garcia Quintas749367f2016-05-17 19:15:24 -07001474 level_set = true;
1475 } else {
David Garcia Quintasac094472016-05-18 20:25:57 -07001476 const grpc_compression_options copts =
1477 grpc_channel_compression_options(call->channel);
1478 level_set = copts.default_level.is_set;
1479 if (level_set) {
1480 effective_compression_level = copts.default_level.level;
1481 }
David Garcia Quintas749367f2016-05-17 19:15:24 -07001482 }
David Garcia Quintas3e4f49f2016-05-18 23:59:02 -07001483 if (level_set && !call->is_client) {
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001484 const grpc_compression_algorithm calgo =
1485 compression_algorithm_for_level_locked(
David Garcia Quintas749367f2016-05-17 19:15:24 -07001486 call, effective_compression_level);
David Garcia Quintas3e4f49f2016-05-18 23:59:02 -07001487 // the following will be picked up by the compress filter and used as
1488 // the call's compression algorithm.
Craig Tiller68208fe2016-11-14 14:35:02 -08001489 compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
1490 compression_md.value = grpc_compression_algorithm_slice(calgo);
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001491 additional_metadata_count++;
1492 }
1493
1494 if (op->data.send_initial_metadata.count + additional_metadata_count >
1495 INT_MAX) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001496 error = GRPC_CALL_ERROR_INVALID_METADATA;
1497 goto done_with_error;
1498 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001499 stream_op->send_initial_metadata = true;
Craig Tillerea54b8c2017-03-01 16:58:28 -08001500 call->sent_initial_metadata = true;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001501 if (!prepare_application_metadata(
Craig Tillera59c16c2016-10-31 07:25:01 -07001502 exec_ctx, call, (int)op->data.send_initial_metadata.count,
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001503 op->data.send_initial_metadata.metadata, 0, call->is_client,
1504 &compression_md, (int)additional_metadata_count)) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001505 error = GRPC_CALL_ERROR_INVALID_METADATA;
1506 goto done_with_error;
1507 }
1508 /* TODO(ctiller): just make these the same variable? */
Craig Tiller095a2202017-05-17 09:02:44 -07001509 if (call->is_client) {
1510 call->metadata_batch[0][0].deadline = call->send_deadline;
1511 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001512 stream_op_payload->send_initial_metadata.send_initial_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001513 &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */];
Craig Tiller9c1ec542017-03-02 08:42:54 -08001514 stream_op_payload->send_initial_metadata.send_initial_metadata_flags =
1515 op->flags;
Craig Tillera82950e2015-09-22 12:33:20 -07001516 break;
1517 case GRPC_OP_SEND_MESSAGE:
1518 if (!are_write_flags_valid(op->flags)) {
1519 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001520 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001521 }
Mark D. Roth448c1f02017-01-25 10:44:30 -08001522 if (op->data.send_message.send_message == NULL) {
Craig Tillera82950e2015-09-22 12:33:20 -07001523 error = GRPC_CALL_ERROR_INVALID_MESSAGE;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001524 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001525 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001526 if (call->sending_message) {
1527 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1528 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001529 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001530 stream_op->send_message = true;
Craig Tillerea54b8c2017-03-01 16:58:28 -08001531 call->sending_message = true;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001532 grpc_slice_buffer_stream_init(
1533 &call->sending_stream,
Mark D. Roth448c1f02017-01-25 10:44:30 -08001534 &op->data.send_message.send_message->data.raw.slice_buffer,
1535 op->flags);
Lizan Zhou61f09732016-10-26 14:09:52 -07001536 /* If the outgoing buffer is already compressed, mark it as so in the
1537 flags. These will be picked up by the compression filter and further
1538 (wasteful) attempts at compression skipped. */
Mark D. Roth9d76dbe2017-01-25 15:02:56 -08001539 if (op->data.send_message.send_message->data.raw.compression >
1540 GRPC_COMPRESS_NONE) {
Lizan Zhou61f09732016-10-26 14:09:52 -07001541 call->sending_stream.base.flags |= GRPC_WRITE_INTERNAL_COMPRESS;
1542 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001543 stream_op_payload->send_message.send_message =
1544 &call->sending_stream.base;
Craig Tillera82950e2015-09-22 12:33:20 -07001545 break;
1546 case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
1547 /* Flag validation: currently allow no flags */
1548 if (op->flags != 0) {
1549 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001550 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001551 }
1552 if (!call->is_client) {
1553 error = GRPC_CALL_ERROR_NOT_ON_SERVER;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001554 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001555 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001556 if (call->sent_final_op) {
1557 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1558 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001559 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001560 stream_op->send_trailing_metadata = true;
Craig Tillere198b712017-03-31 15:29:33 -07001561 call->sent_final_op = true;
Craig Tiller2d43fbf2017-03-13 16:10:05 -07001562 stream_op_payload->send_trailing_metadata.send_trailing_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001563 &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
Craig Tillera82950e2015-09-22 12:33:20 -07001564 break;
1565 case GRPC_OP_SEND_STATUS_FROM_SERVER:
1566 /* Flag validation: currently allow no flags */
1567 if (op->flags != 0) {
1568 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001569 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001570 }
1571 if (call->is_client) {
1572 error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001573 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001574 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001575 if (call->sent_final_op) {
1576 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1577 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001578 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001579 if (op->data.send_status_from_server.trailing_metadata_count >
1580 INT_MAX) {
1581 error = GRPC_CALL_ERROR_INVALID_METADATA;
1582 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001583 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001584 stream_op->send_trailing_metadata = true;
Craig Tillere198b712017-03-31 15:29:33 -07001585 call->sent_final_op = true;
Craig Tiller93727aa2017-02-06 13:05:39 -08001586 GPR_ASSERT(call->send_extra_metadata_count == 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001587 call->send_extra_metadata_count = 1;
1588 call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
Craig Tillera59c16c2016-10-31 07:25:01 -07001589 exec_ctx, call->channel, op->data.send_status_from_server.status);
Craig Tiller841a99d2016-12-12 16:58:57 -08001590 {
1591 grpc_error *override_error = GRPC_ERROR_NONE;
1592 if (op->data.send_status_from_server.status != GRPC_STATUS_OK) {
ncteisen4b36a3d2017-03-13 19:08:06 -07001593 override_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1594 "Error from server send status");
Craig Tiller841a99d2016-12-12 16:58:57 -08001595 }
1596 if (op->data.send_status_from_server.status_details != NULL) {
1597 call->send_extra_metadata[1].md = grpc_mdelem_from_slices(
1598 exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
1599 grpc_slice_ref_internal(
1600 *op->data.send_status_from_server.status_details));
1601 call->send_extra_metadata_count++;
1602 char *msg = grpc_slice_to_c_string(
1603 GRPC_MDVALUE(call->send_extra_metadata[1].md));
ncteisen4b36a3d2017-03-13 19:08:06 -07001604 override_error =
1605 grpc_error_set_str(override_error, GRPC_ERROR_STR_GRPC_MESSAGE,
1606 grpc_slice_from_copied_string(msg));
Craig Tiller841a99d2016-12-12 16:58:57 -08001607 gpr_free(msg);
1608 }
1609 set_status_from_error(exec_ctx, call, STATUS_FROM_API_OVERRIDE,
1610 override_error);
Craig Tiller69a1f662016-09-28 10:24:21 -07001611 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001612 if (!prepare_application_metadata(
Craig Tillera59c16c2016-10-31 07:25:01 -07001613 exec_ctx, call,
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001614 (int)op->data.send_status_from_server.trailing_metadata_count,
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001615 op->data.send_status_from_server.trailing_metadata, 1, 1, NULL,
1616 0)) {
Craig Tiller93727aa2017-02-06 13:05:39 -08001617 for (int n = 0; n < call->send_extra_metadata_count; n++) {
1618 GRPC_MDELEM_UNREF(exec_ctx, call->send_extra_metadata[n].md);
1619 }
1620 call->send_extra_metadata_count = 0;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001621 error = GRPC_CALL_ERROR_INVALID_METADATA;
1622 goto done_with_error;
1623 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001624 stream_op_payload->send_trailing_metadata.send_trailing_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001625 &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
Craig Tillera82950e2015-09-22 12:33:20 -07001626 break;
1627 case GRPC_OP_RECV_INITIAL_METADATA:
1628 /* Flag validation: currently allow no flags */
1629 if (op->flags != 0) {
1630 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001631 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001632 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001633 if (call->received_initial_metadata) {
1634 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1635 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001636 }
Craig Tillere198b712017-03-31 15:29:33 -07001637 call->received_initial_metadata = true;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001638 call->buffered_metadata[0] =
1639 op->data.recv_initial_metadata.recv_initial_metadata;
ncteisen969b46e2017-06-08 14:57:11 -07001640 GRPC_CLOSURE_INIT(&call->receiving_initial_metadata_ready,
Craig Tiller91031da2016-12-28 15:44:25 -08001641 receiving_initial_metadata_ready, bctl,
1642 grpc_schedule_on_exec_ctx);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001643 stream_op->recv_initial_metadata = true;
1644 stream_op_payload->recv_initial_metadata.recv_initial_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001645 &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
Craig Tiller9c1ec542017-03-02 08:42:54 -08001646 stream_op_payload->recv_initial_metadata.recv_initial_metadata_ready =
Craig Tillera44cbfc2016-02-03 16:02:49 -08001647 &call->receiving_initial_metadata_ready;
1648 num_completion_callbacks_needed++;
Craig Tillera82950e2015-09-22 12:33:20 -07001649 break;
1650 case GRPC_OP_RECV_MESSAGE:
1651 /* Flag validation: currently allow no flags */
1652 if (op->flags != 0) {
1653 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001654 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001655 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001656 if (call->receiving_message) {
1657 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
yang-g48f3a712015-12-07 11:23:50 -08001658 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001659 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001660 call->receiving_message = true;
1661 stream_op->recv_message = true;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001662 call->receiving_buffer = op->data.recv_message.recv_message;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001663 stream_op_payload->recv_message.recv_message = &call->receiving_stream;
ncteisen969b46e2017-06-08 14:57:11 -07001664 GRPC_CLOSURE_INIT(&call->receiving_stream_ready, receiving_stream_ready,
Craig Tiller91031da2016-12-28 15:44:25 -08001665 bctl, grpc_schedule_on_exec_ctx);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001666 stream_op_payload->recv_message.recv_message_ready =
1667 &call->receiving_stream_ready;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001668 num_completion_callbacks_needed++;
Craig Tillera82950e2015-09-22 12:33:20 -07001669 break;
1670 case GRPC_OP_RECV_STATUS_ON_CLIENT:
1671 /* Flag validation: currently allow no flags */
1672 if (op->flags != 0) {
1673 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001674 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001675 }
1676 if (!call->is_client) {
1677 error = GRPC_CALL_ERROR_NOT_ON_SERVER;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001678 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001679 }
Craig Tiller1cbf5762016-04-22 16:02:55 -07001680 if (call->requested_final_op) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001681 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1682 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001683 }
Craig Tillere198b712017-03-31 15:29:33 -07001684 call->requested_final_op = true;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001685 call->buffered_metadata[1] =
Craig Tillera82950e2015-09-22 12:33:20 -07001686 op->data.recv_status_on_client.trailing_metadata;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001687 call->final_op.client.status = op->data.recv_status_on_client.status;
1688 call->final_op.client.status_details =
1689 op->data.recv_status_on_client.status_details;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001690 stream_op->recv_trailing_metadata = true;
1691 stream_op->collect_stats = true;
1692 stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001693 &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
Craig Tiller9c1ec542017-03-02 08:42:54 -08001694 stream_op_payload->collect_stats.collect_stats =
David Garcia Quintas5dde14c2016-07-28 17:29:27 -07001695 &call->final_info.stats.transport_stream_stats;
Craig Tillera82950e2015-09-22 12:33:20 -07001696 break;
1697 case GRPC_OP_RECV_CLOSE_ON_SERVER:
1698 /* Flag validation: currently allow no flags */
1699 if (op->flags != 0) {
1700 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001701 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001702 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001703 if (call->is_client) {
1704 error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
1705 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001706 }
Craig Tiller1cbf5762016-04-22 16:02:55 -07001707 if (call->requested_final_op) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001708 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1709 goto done_with_error;
1710 }
Craig Tillere198b712017-03-31 15:29:33 -07001711 call->requested_final_op = true;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001712 call->final_op.server.cancelled =
Craig Tillera82950e2015-09-22 12:33:20 -07001713 op->data.recv_close_on_server.cancelled;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001714 stream_op->recv_trailing_metadata = true;
1715 stream_op->collect_stats = true;
1716 stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001717 &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
Craig Tiller9c1ec542017-03-02 08:42:54 -08001718 stream_op_payload->collect_stats.collect_stats =
David Garcia Quintas5dde14c2016-07-28 17:29:27 -07001719 &call->final_info.stats.transport_stream_stats;
Craig Tillera82950e2015-09-22 12:33:20 -07001720 break;
Craig Tillerfb189f82015-02-03 12:07:07 -08001721 }
Craig Tillera82950e2015-09-22 12:33:20 -07001722 }
Craig Tillerfb189f82015-02-03 12:07:07 -08001723
Craig Tillera82950e2015-09-22 12:33:20 -07001724 GRPC_CALL_INTERNAL_REF(call, "completion");
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001725 if (!is_notify_tag_closure) {
yang-g0eaf7de2017-07-05 16:50:51 -07001726 GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag) == 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001727 }
1728 gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
Craig Tillerfb189f82015-02-03 12:07:07 -08001729
ncteisen969b46e2017-06-08 14:57:11 -07001730 GRPC_CLOSURE_INIT(&bctl->finish_batch, finish_batch, bctl,
Craig Tiller91031da2016-12-28 15:44:25 -08001731 grpc_schedule_on_exec_ctx);
Craig Tiller6e7b45e2016-07-08 17:25:49 -07001732 stream_op->on_complete = &bctl->finish_batch;
Craig Tillerb597dcf2017-03-09 07:02:11 -08001733 gpr_atm_rel_store(&call->any_ops_sent_atm, 1);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001734
Craig Tiller6e7b45e2016-07-08 17:25:49 -07001735 execute_op(exec_ctx, call, stream_op);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001736
Craig Tiller3ffd8222015-09-21 08:21:57 -07001737done:
Craig Tiller0ba432d2015-10-09 16:57:11 -07001738 GPR_TIMER_END("grpc_call_start_batch", 0);
Craig Tiller3ffd8222015-09-21 08:21:57 -07001739 return error;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001740
1741done_with_error:
1742 /* reverse any mutations that occured */
Craig Tiller9c1ec542017-03-02 08:42:54 -08001743 if (stream_op->send_initial_metadata) {
Craig Tillere198b712017-03-31 15:29:33 -07001744 call->sent_initial_metadata = false;
Craig Tillera59c16c2016-10-31 07:25:01 -07001745 grpc_metadata_batch_clear(exec_ctx, &call->metadata_batch[0][0]);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001746 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001747 if (stream_op->send_message) {
Craig Tillere198b712017-03-31 15:29:33 -07001748 call->sending_message = false;
Craig Tiller3b66ab92015-12-09 19:42:22 -08001749 grpc_byte_stream_destroy(exec_ctx, &call->sending_stream.base);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001750 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001751 if (stream_op->send_trailing_metadata) {
Craig Tillere198b712017-03-31 15:29:33 -07001752 call->sent_final_op = false;
Craig Tillera59c16c2016-10-31 07:25:01 -07001753 grpc_metadata_batch_clear(exec_ctx, &call->metadata_batch[0][1]);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001754 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001755 if (stream_op->recv_initial_metadata) {
Craig Tillere198b712017-03-31 15:29:33 -07001756 call->received_initial_metadata = false;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001757 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001758 if (stream_op->recv_message) {
Craig Tillere198b712017-03-31 15:29:33 -07001759 call->receiving_message = false;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001760 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001761 if (stream_op->recv_trailing_metadata) {
Craig Tillere198b712017-03-31 15:29:33 -07001762 call->requested_final_op = false;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001763 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001764 goto done;
1765}
1766
1767grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
1768 size_t nops, void *tag, void *reserved) {
1769 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
1770 grpc_call_error err;
1771
1772 GRPC_API_TRACE(
David Garcia Quintas46123372016-05-09 15:28:42 -07001773 "grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, "
1774 "reserved=%p)",
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001775 5, (call, ops, (unsigned long)nops, tag, reserved));
1776
1777 if (reserved != NULL) {
1778 err = GRPC_CALL_ERROR;
1779 } else {
1780 err = call_start_batch(&exec_ctx, call, ops, nops, tag, 0);
1781 }
1782
1783 grpc_exec_ctx_finish(&exec_ctx);
1784 return err;
1785}
1786
1787grpc_call_error grpc_call_start_batch_and_execute(grpc_exec_ctx *exec_ctx,
1788 grpc_call *call,
1789 const grpc_op *ops,
1790 size_t nops,
1791 grpc_closure *closure) {
1792 return call_start_batch(exec_ctx, call, ops, nops, closure, 1);
Craig Tillerfb189f82015-02-03 12:07:07 -08001793}
Craig Tiller935cf422015-05-01 14:10:46 -07001794
Craig Tillera82950e2015-09-22 12:33:20 -07001795void grpc_call_context_set(grpc_call *call, grpc_context_index elem,
1796 void *value, void (*destroy)(void *value)) {
1797 if (call->context[elem].destroy) {
1798 call->context[elem].destroy(call->context[elem].value);
1799 }
Julien Boeuf83b02972015-05-20 22:50:34 -07001800 call->context[elem].value = value;
1801 call->context[elem].destroy = destroy;
Craig Tiller935cf422015-05-01 14:10:46 -07001802}
1803
Craig Tillera82950e2015-09-22 12:33:20 -07001804void *grpc_call_context_get(grpc_call *call, grpc_context_index elem) {
Julien Boeuf83b02972015-05-20 22:50:34 -07001805 return call->context[elem].value;
Craig Tiller935cf422015-05-01 14:10:46 -07001806}
Julien Boeuf9f218dd2015-04-23 10:24:02 -07001807
Craig Tiller7536af02015-12-22 13:49:30 -08001808uint8_t grpc_call_is_client(grpc_call *call) { return call->is_client; }
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -07001809
1810grpc_compression_algorithm grpc_call_compression_for_level(
1811 grpc_call *call, grpc_compression_level level) {
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001812 grpc_compression_algorithm algo =
1813 compression_algorithm_for_level_locked(call, level);
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001814 return algo;
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -07001815}
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07001816
1817const char *grpc_call_error_to_string(grpc_call_error error) {
1818 switch (error) {
1819 case GRPC_CALL_ERROR:
1820 return "GRPC_CALL_ERROR";
1821 case GRPC_CALL_ERROR_ALREADY_ACCEPTED:
1822 return "GRPC_CALL_ERROR_ALREADY_ACCEPTED";
1823 case GRPC_CALL_ERROR_ALREADY_FINISHED:
1824 return "GRPC_CALL_ERROR_ALREADY_FINISHED";
1825 case GRPC_CALL_ERROR_ALREADY_INVOKED:
1826 return "GRPC_CALL_ERROR_ALREADY_INVOKED";
1827 case GRPC_CALL_ERROR_BATCH_TOO_BIG:
1828 return "GRPC_CALL_ERROR_BATCH_TOO_BIG";
1829 case GRPC_CALL_ERROR_INVALID_FLAGS:
1830 return "GRPC_CALL_ERROR_INVALID_FLAGS";
1831 case GRPC_CALL_ERROR_INVALID_MESSAGE:
1832 return "GRPC_CALL_ERROR_INVALID_MESSAGE";
1833 case GRPC_CALL_ERROR_INVALID_METADATA:
1834 return "GRPC_CALL_ERROR_INVALID_METADATA";
1835 case GRPC_CALL_ERROR_NOT_INVOKED:
1836 return "GRPC_CALL_ERROR_NOT_INVOKED";
1837 case GRPC_CALL_ERROR_NOT_ON_CLIENT:
1838 return "GRPC_CALL_ERROR_NOT_ON_CLIENT";
1839 case GRPC_CALL_ERROR_NOT_ON_SERVER:
1840 return "GRPC_CALL_ERROR_NOT_ON_SERVER";
1841 case GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE:
1842 return "GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE";
1843 case GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH:
1844 return "GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH";
1845 case GRPC_CALL_ERROR_TOO_MANY_OPERATIONS:
1846 return "GRPC_CALL_ERROR_TOO_MANY_OPERATIONS";
yang-g0eaf7de2017-07-05 16:50:51 -07001847 case GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN:
1848 return "GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN";
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07001849 case GRPC_CALL_OK:
1850 return "GRPC_CALL_OK";
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07001851 }
Yuchen Zengf02bada2016-04-19 14:12:27 -07001852 GPR_UNREACHABLE_CODE(return "GRPC_CALL_ERROR_UNKNOW");
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07001853}