blob: a7b932b46dfa49c47115fbc187249c7f6b35ce38 [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>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080031
Craig Tiller9533d042016-03-25 17:11:06 -070032#include "src/core/lib/channel/channel_stack.h"
33#include "src/core/lib/compression/algorithm_metadata.h"
Craig Tiller28086682017-07-18 14:22:19 -070034#include "src/core/lib/debug/stats.h"
Mark D. Rothdbdf4952018-01-18 11:21:12 -080035#include "src/core/lib/gpr/arena.h"
36#include "src/core/lib/gpr/string.h"
Vijay Paid4d0a302018-01-25 13:24:03 -080037#include "src/core/lib/gpr/useful.h"
Craig Tiller9533d042016-03-25 17:11:06 -070038#include "src/core/lib/iomgr/timer.h"
39#include "src/core/lib/profiling/timers.h"
Craig Tillera59c16c2016-10-31 07:25:01 -070040#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -070041#include "src/core/lib/slice/slice_string_helpers.h"
Craig Tiller9533d042016-03-25 17:11:06 -070042#include "src/core/lib/surface/api_trace.h"
43#include "src/core/lib/surface/call.h"
Yash Tibrewal1c9b5842017-09-21 15:49:55 -070044#include "src/core/lib/surface/call_test_only.h"
Craig Tiller9533d042016-03-25 17:11:06 -070045#include "src/core/lib/surface/channel.h"
46#include "src/core/lib/surface/completion_queue.h"
Craig Tillerf2b5b7e2017-01-10 08:28:59 -080047#include "src/core/lib/surface/validate_metadata.h"
Craig Tiller732351f2016-12-13 16:40:38 -080048#include "src/core/lib/transport/error_utils.h"
David Garcia Quintas73dcbda2016-04-23 00:17:05 -070049#include "src/core/lib/transport/metadata.h"
Craig Tiller9533d042016-03-25 17:11:06 -070050#include "src/core/lib/transport/static_metadata.h"
David Garcia Quintas73dcbda2016-04-23 00:17:05 -070051#include "src/core/lib/transport/transport.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052
Craig Tillerc7e1a2a2015-11-02 14:17:32 -080053/** The maximum number of concurrent batches possible.
Craig Tiller1b011672015-07-10 10:41:44 -070054 Based upon the maximum number of individually queueable ops in the batch
Craig Tiller94903892016-10-11 15:43:35 -070055 api:
Craig Tiller1b011672015-07-10 10:41:44 -070056 - initial metadata send
57 - message send
58 - status/close send (depending on client/server)
59 - initial metadata recv
60 - message recv
61 - status/close recv (depending on client/server) */
Craig Tillerc7e1a2a2015-11-02 14:17:32 -080062#define MAX_CONCURRENT_BATCHES 6
Craig Tiller1b011672015-07-10 10:41:44 -070063
Craig Tillerc7e1a2a2015-11-02 14:17:32 -080064#define MAX_SEND_EXTRA_METADATA_COUNT 3
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080065
Craig Tillerdaceea82015-02-02 16:15:53 -080066/* Status data for a request can come from several sources; this
67 enumerates them all, and acts as a priority sorting for which
68 status to return to the application - earlier entries override
69 later ones */
Craig Tillera82950e2015-09-22 12:33:20 -070070typedef enum {
Craig Tillerdaceea82015-02-02 16:15:53 -080071 /* Status came from the application layer overriding whatever
72 the wire says */
Craig Tiller68752722015-01-29 14:59:54 -080073 STATUS_FROM_API_OVERRIDE = 0,
Craig Tillerdaceea82015-02-02 16:15:53 -080074 /* Status came from 'the wire' - or somewhere below the surface
75 layer */
Craig Tiller68752722015-01-29 14:59:54 -080076 STATUS_FROM_WIRE,
Craig Tiller2dc32ea2017-01-31 15:32:34 -080077 /* Status was created by some internal channel stack operation: must come via
78 add_batch_error */
Craig Tiller2aa03df2016-03-16 08:24:55 -070079 STATUS_FROM_CORE,
Craig Tiller2dc32ea2017-01-31 15:32:34 -080080 /* Status was created by some surface error */
81 STATUS_FROM_SURFACE,
Craig Tilleraea081f2015-06-11 14:19:33 -070082 /* Status came from the server sending status */
83 STATUS_FROM_SERVER_STATUS,
Craig Tiller68752722015-01-29 14:59:54 -080084 STATUS_SOURCE_COUNT
85} status_source;
86
Craig Tillera82950e2015-09-22 12:33:20 -070087typedef struct {
Craig Tiller841a99d2016-12-12 16:58:57 -080088 bool is_set;
Muxi Yan38fcd0c2017-12-06 18:52:18 -080089 grpc_error* error;
Craig Tiller68752722015-01-29 14:59:54 -080090} received_status;
91
Craig Tiller4bab9462017-02-22 08:56:02 -080092static gpr_atm pack_received_status(received_status r) {
93 return r.is_set ? (1 | (gpr_atm)r.error) : 0;
94}
95
96static received_status unpack_received_status(gpr_atm atm) {
Yash Tibrewald8b84a22017-09-25 13:38:03 -070097 if ((atm & 1) == 0) {
98 return {false, GRPC_ERROR_NONE};
99 } else {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800100 return {true, (grpc_error*)(atm & ~(gpr_atm)1)};
Yash Tibrewald8b84a22017-09-25 13:38:03 -0700101 }
Craig Tiller4bab9462017-02-22 08:56:02 -0800102}
103
yang-g23f777d2017-02-22 23:32:26 -0800104#define MAX_ERRORS_PER_BATCH 4
Craig Tiller94903892016-10-11 15:43:35 -0700105
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800106typedef struct batch_control {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800107 grpc_call* call;
Craig Tillere198b712017-03-31 15:29:33 -0700108 /* Share memory for cq_completion and notify_tag as they are never needed
109 simultaneously. Each byte used in this data structure count as six bytes
Craig Tiller7a8232d2017-04-03 10:59:42 -0700110 per call, so any savings we can make are worthwhile,
111
112 We use notify_tag to determine whether or not to send notification to the
113 completion queue. Once we've made that determination, we can reuse the
114 memory for cq_completion. */
Craig Tillerea54b8c2017-03-01 16:58:28 -0800115 union {
116 grpc_cq_completion cq_completion;
117 struct {
Craig Tillere198b712017-03-31 15:29:33 -0700118 /* Any given op indicates completion by either (a) calling a closure or
119 (b) sending a notification on the call's completion queue. If
120 \a is_closure is true, \a tag indicates a closure to be invoked;
121 otherwise, \a tag indicates the tag to be used in the notification to
122 be sent to the completion queue. */
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800123 void* tag;
Craig Tillerea54b8c2017-03-01 16:58:28 -0800124 bool is_closure;
125 } notify_tag;
126 } completion_data;
Mark D. Roth764cf042017-09-01 09:00:06 -0700127 grpc_closure start_batch;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800128 grpc_closure finish_batch;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800129 gpr_refcount steps_to_complete;
Craig Tiller94903892016-10-11 15:43:35 -0700130
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800131 grpc_error* errors[MAX_ERRORS_PER_BATCH];
Craig Tiller94903892016-10-11 15:43:35 -0700132 gpr_atm num_errors;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800133
Craig Tillera0f3abd2017-03-31 15:42:16 -0700134 grpc_transport_stream_op_batch op;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800135} batch_control;
136
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700137typedef struct {
138 gpr_mu child_list_mu;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800139 grpc_call* first_child;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700140} parent_call;
141
142typedef struct {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800143 grpc_call* parent;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700144 /** siblings: children of the same parent form a list, and this list is
145 protected under
146 parent->mu */
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800147 grpc_call* sibling_next;
148 grpc_call* sibling_prev;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700149} child_call;
150
Yuchen Zeng6eb505b2017-08-25 16:05:29 -0700151#define RECV_NONE ((gpr_atm)0)
152#define RECV_INITIAL_METADATA_FIRST ((gpr_atm)1)
153
Craig Tillera82950e2015-09-22 12:33:20 -0700154struct grpc_call {
Craig Tillerdd36b152017-03-31 08:27:28 -0700155 gpr_refcount ext_ref;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800156 gpr_arena* arena;
Mark D. Roth764cf042017-09-01 09:00:06 -0700157 grpc_call_combiner call_combiner;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800158 grpc_completion_queue* cq;
David Garcia Quintas2a50dfe2016-05-31 15:09:12 -0700159 grpc_polling_entity pollent;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800160 grpc_channel* channel;
Mark D. Roth3d883412016-11-07 13:42:54 -0800161 gpr_timespec start_time;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700162 /* parent_call* */ gpr_atm parent_call_atm;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800163 child_call* child;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800164
Craig Tillere5d683c2015-02-03 16:37:36 -0800165 /* client or server call */
Craig Tiller1cbf5762016-04-22 16:02:55 -0700166 bool is_client;
Craig Tillerdd36b152017-03-31 08:27:28 -0700167 /** has grpc_call_unref been called */
Craig Tiller1cbf5762016-04-22 16:02:55 -0700168 bool destroy_called;
Craig Tillerc7df0df2015-08-03 08:06:50 -0700169 /** flag indicating that cancellation is inherited */
Craig Tiller1cbf5762016-04-22 16:02:55 -0700170 bool cancellation_is_inherited;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800171 /** which ops are in-flight */
Craig Tiller1cbf5762016-04-22 16:02:55 -0700172 bool sent_initial_metadata;
173 bool sending_message;
174 bool sent_final_op;
175 bool received_initial_metadata;
176 bool receiving_message;
177 bool requested_final_op;
Craig Tillerb597dcf2017-03-09 07:02:11 -0800178 gpr_atm any_ops_sent_atm;
179 gpr_atm received_final_op_atm;
yang-g0b6ad7d2015-06-25 14:39:01 -0700180
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800181 batch_control* active_batches[MAX_CONCURRENT_BATCHES];
Craig Tillera0f3abd2017-03-31 15:42:16 -0700182 grpc_transport_stream_op_batch_payload stream_op_payload;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800183
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800184 /* first idx: is_receiving, second idx: is_trailing */
185 grpc_metadata_batch metadata_batch[2][2];
Craig Tillerebf94bf2015-02-05 08:48:46 -0800186
Craig Tillere5d683c2015-02-03 16:37:36 -0800187 /* Buffered read metadata waiting to be returned to the application.
188 Element 0 is initial metadata, element 1 is trailing metadata. */
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800189 grpc_metadata_array* buffered_metadata[2];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800190
Mark D. Roth764cf042017-09-01 09:00:06 -0700191 grpc_metadata compression_md;
192
193 // A char* indicating the peer name.
194 gpr_atm peer_string;
195
Craig Tiller4bab9462017-02-22 08:56:02 -0800196 /* Packed received call statuses from various sources */
197 gpr_atm status[STATUS_SOURCE_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800198
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700199 /* Call data useful used for reporting. Only valid after the call has
200 * completed */
201 grpc_call_final_info final_info;
Craig Tiller466129e2016-03-09 14:43:18 -0800202
David Garcia Quintas749367f2016-05-17 19:15:24 -0700203 /* Compression algorithm for *incoming* data */
Muxi Yane6d888d2017-09-14 09:42:56 -0700204 grpc_message_compression_algorithm incoming_message_compression_algorithm;
Muxi Yan68a0fd52017-07-21 09:26:04 -0700205 /* Stream compression algorithm for *incoming* data */
206 grpc_stream_compression_algorithm incoming_stream_compression_algorithm;
David Garcia Quintase091af82015-07-15 21:37:02 -0700207 /* Supported encodings (compression algorithms), a bitset */
Craig Tiller7536af02015-12-22 13:49:30 -0800208 uint32_t encodings_accepted_by_peer;
Muxi Yan68a0fd52017-07-21 09:26:04 -0700209 /* Supported stream encodings (stream compression algorithms), a bitset */
210 uint32_t stream_encodings_accepted_by_peer;
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700211
Julien Boeufc6f8d0a2015-05-11 22:40:02 -0700212 /* Contexts for various subsystems (security, tracing, ...). */
Julien Boeuf83b02972015-05-20 22:50:34 -0700213 grpc_call_context_element context[GRPC_CONTEXT_COUNT];
Craig Tiller935cf422015-05-01 14:10:46 -0700214
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800215 /* for the client, extra metadata is initial metadata; for the
216 server, it's trailing metadata */
217 grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT];
218 int send_extra_metadata_count;
Craig Tiller89c14282017-07-19 15:32:27 -0700219 grpc_millis send_deadline;
Craig Tiller6902ad22015-04-16 08:01:49 -0700220
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800221 grpc_slice_buffer_stream sending_stream;
Craig Tiller94903892016-10-11 15:43:35 -0700222
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800223 grpc_byte_stream* receiving_stream;
224 grpc_byte_buffer** receiving_buffer;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700225 grpc_slice receiving_slice;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800226 grpc_closure receiving_slice_ready;
227 grpc_closure receiving_stream_ready;
Craig Tillera44cbfc2016-02-03 16:02:49 -0800228 grpc_closure receiving_initial_metadata_ready;
Craig Tiller7536af02015-12-22 13:49:30 -0800229 uint32_t test_only_last_message_flags;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800230
Craig Tillere7a17022017-03-13 10:20:38 -0700231 grpc_closure release_call;
232
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800233 union {
234 struct {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800235 grpc_status_code* status;
236 grpc_slice* status_details;
ncteisen40737d62017-11-13 08:02:35 -0800237 const char** error_string;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800238 } client;
239 struct {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800240 int* cancelled;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800241 } server;
242 } final_op;
Craig Tillera44cbfc2016-02-03 16:02:49 -0800243
Yuchen Zeng6eb505b2017-08-25 16:05:29 -0700244 /* recv_state can contain one of the following values:
245 RECV_NONE : : no initial metadata and messages received
246 RECV_INITIAL_METADATA_FIRST : received initial metadata first
247 a batch_control* : received messages first
248
249 +------1------RECV_NONE------3-----+
250 | |
251 | |
252 v v
253 RECV_INITIAL_METADATA_FIRST receiving_stream_ready_bctlp
254 | ^ | ^
255 | | | |
256 +-----2-----+ +-----4-----+
257
258 For 1, 4: See receiving_initial_metadata_ready() function
259 For 2, 3: See receiving_stream_ready() function */
260 gpr_atm recv_state;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800261};
262
Craig Tiller694580f2017-10-18 14:48:14 -0700263grpc_core::TraceFlag grpc_call_error_trace(false, "call_error");
264grpc_core::TraceFlag grpc_compression_trace(false, "compression");
Craig Tiller58b30cd2017-01-31 17:07:36 -0800265
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800266#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack*)((call) + 1))
267#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call*)(call_stack)) - 1)
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800268#define CALL_ELEM_FROM_CALL(call, idx) \
269 grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
270#define CALL_FROM_TOP_ELEM(top_elem) \
271 CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem))
272
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800273static void execute_batch(grpc_call* call, grpc_transport_stream_op_batch* op,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800274 grpc_closure* start_batch_closure);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800275static void cancel_with_status(grpc_call* c, status_source source,
276 grpc_status_code status,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800277 const char* description);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800278static void cancel_with_error(grpc_call* c, status_source source,
279 grpc_error* error);
280static void destroy_call(void* call_stack, grpc_error* error);
281static void receiving_slice_ready(void* bctlp, grpc_error* error);
282static void get_final_status(
283 grpc_call* call, void (*set_value)(grpc_status_code code, void* user_data),
284 void* set_value_user_data, grpc_slice* details, const char** error_string);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800285static void set_status_value_directly(grpc_status_code status, void* dest);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800286static void set_status_from_error(grpc_call* call, status_source source,
287 grpc_error* error);
288static void process_data_after_md(batch_control* bctl);
289static void post_batch_completion(batch_control* bctl);
290static void add_batch_error(batch_control* bctl, grpc_error* error,
291 bool has_cancelled);
Craig Tillerbac41422015-05-29 16:32:28 -0700292
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800293static void add_init_error(grpc_error** composite, grpc_error* new_err) {
Yash Tibrewal52778c42017-09-11 15:00:11 -0700294 if (new_err == GRPC_ERROR_NONE) return;
Craig Tillerf4484cd2017-02-01 08:28:40 -0800295 if (*composite == GRPC_ERROR_NONE)
ncteisen4b36a3d2017-03-13 19:08:06 -0700296 *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Call creation failed");
Yash Tibrewal52778c42017-09-11 15:00:11 -0700297 *composite = grpc_error_add_child(*composite, new_err);
Craig Tillerf4484cd2017-02-01 08:28:40 -0800298}
299
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800300void* grpc_call_arena_alloc(grpc_call* call, size_t size) {
Craig Tiller58450912017-03-16 09:42:43 -0700301 return gpr_arena_alloc(call->arena, size);
302}
303
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800304static parent_call* get_or_create_parent_call(grpc_call* call) {
305 parent_call* p = (parent_call*)gpr_atm_acq_load(&call->parent_call_atm);
Craig Tiller4782d922017-11-10 09:53:21 -0800306 if (p == nullptr) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800307 p = (parent_call*)gpr_arena_alloc(call->arena, sizeof(*p));
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700308 gpr_mu_init(&p->child_list_mu);
Muxi Yan60430062017-12-06 22:29:12 -0800309 if (!gpr_atm_rel_cas(&call->parent_call_atm, (gpr_atm) nullptr,
310 (gpr_atm)p)) {
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700311 gpr_mu_destroy(&p->child_list_mu);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800312 p = (parent_call*)gpr_atm_acq_load(&call->parent_call_atm);
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700313 }
314 }
315 return p;
316}
317
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800318static parent_call* get_parent_call(grpc_call* call) {
319 return (parent_call*)gpr_atm_acq_load(&call->parent_call_atm);
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700320}
321
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800322grpc_error* grpc_call_create(const grpc_call_create_args* args,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800323 grpc_call** out_call) {
yang-gce1cfea2018-01-31 15:59:50 -0800324 GPR_TIMER_SCOPE("grpc_call_create", 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800325 size_t i, j;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800326 grpc_error* error = GRPC_ERROR_NONE;
327 grpc_channel_stack* channel_stack =
Craig Tiller8e214652016-08-19 09:54:31 -0700328 grpc_channel_get_channel_stack(args->channel);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800329 grpc_call* call;
Craig Tiller0ff222a2017-09-01 09:41:43 -0700330 size_t initial_size = grpc_channel_get_call_size_estimate(args->channel);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800331 GRPC_STATS_INC_CALL_INITIAL_SIZE(initial_size);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800332 gpr_arena* arena = gpr_arena_create(initial_size);
333 call = (grpc_call*)gpr_arena_alloc(
Yash Tibrewalca3c1c02017-09-07 22:47:16 -0700334 arena, sizeof(grpc_call) + channel_stack->call_stack_size);
Craig Tillerdd36b152017-03-31 08:27:28 -0700335 gpr_ref_init(&call->ext_ref, 1);
Craig Tillere7a17022017-03-13 10:20:38 -0700336 call->arena = arena;
Mark D. Roth764cf042017-09-01 09:00:06 -0700337 grpc_call_combiner_init(&call->call_combiner);
Craig Tiller0eaed722016-09-21 10:44:18 -0700338 *out_call = call;
Craig Tiller8e214652016-08-19 09:54:31 -0700339 call->channel = args->channel;
340 call->cq = args->cq;
Mark D. Roth3d883412016-11-07 13:42:54 -0800341 call->start_time = gpr_now(GPR_CLOCK_MONOTONIC);
David Garcia Quintas46123372016-05-09 15:28:42 -0700342 /* Always support no compression */
Muxi Yane6d888d2017-09-14 09:42:56 -0700343 GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_MESSAGE_COMPRESS_NONE);
Craig Tiller4782d922017-11-10 09:53:21 -0800344 call->is_client = args->server_transport_data == nullptr;
Craig Tiller28086682017-07-18 14:22:19 -0700345 if (call->is_client) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800346 GRPC_STATS_INC_CLIENT_CALLS_CREATED();
Craig Tiller28086682017-07-18 14:22:19 -0700347 } else {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800348 GRPC_STATS_INC_SERVER_CALLS_CREATED();
Craig Tiller28086682017-07-18 14:22:19 -0700349 }
Craig Tillerea54b8c2017-03-01 16:58:28 -0800350 call->stream_op_payload.context = call->context;
Craig Tiller4eecdde2016-11-14 08:21:17 -0800351 grpc_slice path = grpc_empty_slice();
Craig Tillera82950e2015-09-22 12:33:20 -0700352 if (call->is_client) {
Craig Tiller8e214652016-08-19 09:54:31 -0700353 GPR_ASSERT(args->add_initial_metadata_count <
354 MAX_SEND_EXTRA_METADATA_COUNT);
355 for (i = 0; i < args->add_initial_metadata_count; i++) {
356 call->send_extra_metadata[i].md = args->add_initial_metadata[i];
Craig Tiller3b05e1d2016-11-21 13:46:31 -0800357 if (grpc_slice_eq(GRPC_MDKEY(args->add_initial_metadata[i]),
358 GRPC_MDSTR_PATH)) {
Craig Tiller0160de92016-11-18 08:46:46 -0800359 path = grpc_slice_ref_internal(
360 GRPC_MDVALUE(args->add_initial_metadata[i]));
Mark D. Rothaa850a72016-09-26 13:38:02 -0700361 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800362 }
Craig Tiller8e214652016-08-19 09:54:31 -0700363 call->send_extra_metadata_count = (int)args->add_initial_metadata_count;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800364 } else {
Craig Tiller8e214652016-08-19 09:54:31 -0700365 GPR_ASSERT(args->add_initial_metadata_count == 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800366 call->send_extra_metadata_count = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700367 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800368 for (i = 0; i < 2; i++) {
369 for (j = 0; j < 2; j++) {
Craig Tiller89c14282017-07-19 15:32:27 -0700370 call->metadata_batch[i][j].deadline = GRPC_MILLIS_INF_FUTURE;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800371 }
Craig Tillera82950e2015-09-22 12:33:20 -0700372 }
Craig Tiller89c14282017-07-19 15:32:27 -0700373 grpc_millis send_deadline = args->send_deadline;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700374
Craig Tillerbea92ba2017-04-19 08:33:31 -0700375 bool immediately_cancel = false;
376
Craig Tiller4782d922017-11-10 09:53:21 -0800377 if (args->parent != nullptr) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800378 child_call* cc = call->child =
379 (child_call*)gpr_arena_alloc(arena, sizeof(child_call));
Yash Tibrewalb2a54ac2017-09-13 10:18:07 -0700380 call->child->parent = args->parent;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700381
Yash Tibrewalb2a54ac2017-09-13 10:18:07 -0700382 GRPC_CALL_INTERNAL_REF(args->parent, "child");
Craig Tillera82950e2015-09-22 12:33:20 -0700383 GPR_ASSERT(call->is_client);
Yash Tibrewalb2a54ac2017-09-13 10:18:07 -0700384 GPR_ASSERT(!args->parent->is_client);
Craig Tillera82950e2015-09-22 12:33:20 -0700385
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800386 parent_call* pc = get_or_create_parent_call(args->parent);
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700387
388 gpr_mu_lock(&pc->child_list_mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700389
Craig Tiller8e214652016-08-19 09:54:31 -0700390 if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) {
Craig Tiller50448be2017-09-18 13:56:51 -0700391 send_deadline = GPR_MIN(send_deadline, args->parent->send_deadline);
Craig Tillerc7df0df2015-08-03 08:06:50 -0700392 }
Craig Tillera82950e2015-09-22 12:33:20 -0700393 /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with
394 * GRPC_PROPAGATE_STATS_CONTEXT */
395 /* TODO(ctiller): This should change to use the appropriate census start_op
396 * call. */
Craig Tiller8e214652016-08-19 09:54:31 -0700397 if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) {
Craig Tiller239af8b2017-02-01 10:21:42 -0800398 if (0 == (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT)) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700399 add_init_error(&error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
400 "Census tracing propagation requested "
401 "without Census context propagation"));
Craig Tiller239af8b2017-02-01 10:21:42 -0800402 }
Yash Tibrewalb2a54ac2017-09-13 10:18:07 -0700403 grpc_call_context_set(call, GRPC_CONTEXT_TRACING,
404 args->parent->context[GRPC_CONTEXT_TRACING].value,
Craig Tiller4782d922017-11-10 09:53:21 -0800405 nullptr);
Craig Tillerf20d3072017-02-01 10:39:26 -0800406 } else if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT) {
ncteisen4b36a3d2017-03-13 19:08:06 -0700407 add_init_error(&error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
408 "Census context propagation requested "
409 "without Census tracing propagation"));
Craig Tiller45724b32015-09-22 10:42:19 -0700410 }
Craig Tiller8e214652016-08-19 09:54:31 -0700411 if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
Craig Tillera82950e2015-09-22 12:33:20 -0700412 call->cancellation_is_inherited = 1;
Yash Tibrewalb2a54ac2017-09-13 10:18:07 -0700413 if (gpr_atm_acq_load(&args->parent->received_final_op_atm)) {
Craig Tillerbea92ba2017-04-19 08:33:31 -0700414 immediately_cancel = true;
Craig Tiller123c72b2017-03-10 07:33:27 -0800415 }
Craig Tiller45724b32015-09-22 10:42:19 -0700416 }
Craig Tillera82950e2015-09-22 12:33:20 -0700417
Craig Tiller4782d922017-11-10 09:53:21 -0800418 if (pc->first_child == nullptr) {
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700419 pc->first_child = call;
420 cc->sibling_next = cc->sibling_prev = call;
Craig Tillera82950e2015-09-22 12:33:20 -0700421 } else {
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700422 cc->sibling_next = pc->first_child;
Yash Tibrewalb2a54ac2017-09-13 10:18:07 -0700423 cc->sibling_prev = pc->first_child->child->sibling_prev;
424 cc->sibling_next->child->sibling_prev =
425 cc->sibling_prev->child->sibling_next = call;
Craig Tillera82950e2015-09-22 12:33:20 -0700426 }
427
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700428 gpr_mu_unlock(&pc->child_list_mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700429 }
Mark D. Rothf28763c2016-09-14 15:18:40 -0700430
Mark D. Roth14c072c2016-08-26 08:31:34 -0700431 call->send_deadline = send_deadline;
Mark D. Rothf28763c2016-09-14 15:18:40 -0700432
Craig Tillerca3451d2016-09-29 10:27:44 -0700433 GRPC_CHANNEL_INTERNAL_REF(args->channel, "call");
Craig Tillerdd36b152017-03-31 08:27:28 -0700434 /* initial refcount dropped by grpc_call_unref */
Yash Tibrewald8b84a22017-09-25 13:38:03 -0700435 grpc_call_element_args call_args = {CALL_STACK_FROM_CALL(call),
436 args->server_transport_data,
437 call->context,
438 path,
439 call->start_time,
440 send_deadline,
441 call->arena,
442 &call->call_combiner};
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800443 add_init_error(&error, grpc_call_stack_init(channel_stack, 1, destroy_call,
444 call, &call_args));
Mark D. Rothf28763c2016-09-14 15:18:40 -0700445 if (error != GRPC_ERROR_NONE) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800446 cancel_with_error(call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error));
Craig Tillera82950e2015-09-22 12:33:20 -0700447 }
Craig Tillerbea92ba2017-04-19 08:33:31 -0700448 if (immediately_cancel) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800449 cancel_with_error(call, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED);
Craig Tillerbea92ba2017-04-19 08:33:31 -0700450 }
Craig Tiller4782d922017-11-10 09:53:21 -0800451 if (args->cq != nullptr) {
Muxi Yan60430062017-12-06 22:29:12 -0800452 GPR_ASSERT(args->pollset_set_alternative == nullptr &&
453 "Only one of 'cq' and 'pollset_set_alternative' should be "
454 "non-nullptr.");
Craig Tillerca3451d2016-09-29 10:27:44 -0700455 GRPC_CQ_INTERNAL_REF(args->cq, "bind");
Mark D. Rothf28763c2016-09-14 15:18:40 -0700456 call->pollent =
Craig Tillerca3451d2016-09-29 10:27:44 -0700457 grpc_polling_entity_create_from_pollset(grpc_cq_pollset(args->cq));
Mark D. Rothf28763c2016-09-14 15:18:40 -0700458 }
Craig Tiller4782d922017-11-10 09:53:21 -0800459 if (args->pollset_set_alternative != nullptr) {
Craig Tillerca3451d2016-09-29 10:27:44 -0700460 call->pollent = grpc_polling_entity_create_from_pollset_set(
461 args->pollset_set_alternative);
Mark D. Rothf28763c2016-09-14 15:18:40 -0700462 }
463 if (!grpc_polling_entity_is_empty(&call->pollent)) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800464 grpc_call_stack_set_pollset_or_pollset_set(CALL_STACK_FROM_CALL(call),
465 &call->pollent);
Mark D. Rothf28763c2016-09-14 15:18:40 -0700466 }
467
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800468 grpc_slice_unref_internal(path);
Mark D. Rothaa850a72016-09-26 13:38:02 -0700469
Craig Tiller8e214652016-08-19 09:54:31 -0700470 return error;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800471}
472
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800473void grpc_call_set_completion_queue(grpc_call* call,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800474 grpc_completion_queue* cq) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800475 GPR_ASSERT(cq);
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700476
Craig Tiller4782d922017-11-10 09:53:21 -0800477 if (grpc_polling_entity_pollset_set(&call->pollent) != nullptr) {
David Garcia Quintasf72eb972016-05-03 18:28:09 -0700478 gpr_log(GPR_ERROR, "A pollset_set is already registered for this call.");
479 abort();
480 }
Craig Tiller166e2502015-02-03 20:14:41 -0800481 call->cq = cq;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800482 GRPC_CQ_INTERNAL_REF(cq, "bind");
David Garcia Quintasc4d51122016-06-06 14:56:02 -0700483 call->pollent = grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq));
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800484 grpc_call_stack_set_pollset_or_pollset_set(CALL_STACK_FROM_CALL(call),
485 &call->pollent);
Craig Tiller166e2502015-02-03 20:14:41 -0800486}
487
ncteisen9c43fc02017-06-08 16:06:23 -0700488#ifndef NDEBUG
Craig Tiller7b435612015-11-24 08:15:05 -0800489#define REF_REASON reason
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800490#define REF_ARG , const char* reason
Craig Tiller4df412b2015-04-28 07:57:54 -0700491#else
Craig Tiller7b435612015-11-24 08:15:05 -0800492#define REF_REASON ""
493#define REF_ARG
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800494#endif
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800495void grpc_call_internal_ref(grpc_call* c REF_ARG) {
Craig Tiller7b435612015-11-24 08:15:05 -0800496 GRPC_CALL_STACK_REF(CALL_STACK_FROM_CALL(c), REF_REASON);
497}
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800498void grpc_call_internal_unref(grpc_call* c REF_ARG) {
499 GRPC_CALL_STACK_UNREF(CALL_STACK_FROM_CALL(c), REF_REASON);
Craig Tiller7b435612015-11-24 08:15:05 -0800500}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800501
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800502static void release_call(void* call, grpc_error* error) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800503 grpc_call* c = (grpc_call*)call;
504 grpc_channel* channel = c->channel;
Mark D. Roth764cf042017-09-01 09:00:06 -0700505 grpc_call_combiner_destroy(&c->call_combiner);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800506 gpr_free((char*)c->peer_string);
Craig Tillerdbad3702017-03-15 08:21:19 -0700507 grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena));
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800508 GRPC_CHANNEL_INTERNAL_UNREF(channel, "call");
Craig Tillere7a17022017-03-13 10:20:38 -0700509}
510
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800511static void set_status_value_directly(grpc_status_code status, void* dest);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800512static void destroy_call(void* call, grpc_error* error) {
yang-gce1cfea2018-01-31 15:59:50 -0800513 GPR_TIMER_SCOPE("destroy_call", 0);
Craig Tiller566316f2015-02-02 15:25:32 -0800514 size_t i;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800515 int ii;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800516 grpc_call* c = (grpc_call*)call;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800517 for (i = 0; i < 2; i++) {
518 grpc_metadata_batch_destroy(
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800519 &c->metadata_batch[1 /* is_receiving */][i /* is_initial */]);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800520 }
Craig Tiller4782d922017-11-10 09:53:21 -0800521 if (c->receiving_stream != nullptr) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800522 grpc_byte_stream_destroy(c->receiving_stream);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800523 }
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800524 parent_call* pc = get_parent_call(c);
Craig Tiller4782d922017-11-10 09:53:21 -0800525 if (pc != nullptr) {
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700526 gpr_mu_destroy(&pc->child_list_mu);
527 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800528 for (ii = 0; ii < c->send_extra_metadata_count; ii++) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800529 GRPC_MDELEM_UNREF(c->send_extra_metadata[ii].md);
Craig Tillera82950e2015-09-22 12:33:20 -0700530 }
531 for (i = 0; i < GRPC_CONTEXT_COUNT; i++) {
532 if (c->context[i].destroy) {
533 c->context[i].destroy(c->context[i].value);
Craig Tiller935cf422015-05-01 14:10:46 -0700534 }
Craig Tillera82950e2015-09-22 12:33:20 -0700535 }
Craig Tillera82950e2015-09-22 12:33:20 -0700536 if (c->cq) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800537 GRPC_CQ_INTERNAL_UNREF(c->cq, "bind");
Craig Tillera82950e2015-09-22 12:33:20 -0700538 }
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700539
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800540 get_final_status(c, set_status_value_directly, &c->final_info.final_status,
541 nullptr, c->final_info.error_string);
Mark D. Roth3d883412016-11-07 13:42:54 -0800542 c->final_info.stats.latency =
543 gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
David Garcia Quintas01c4d992016-07-07 20:11:27 -0700544
Craig Tiller841a99d2016-12-12 16:58:57 -0800545 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800546 GRPC_ERROR_UNREF(
Craig Tillerb597dcf2017-03-09 07:02:11 -0800547 unpack_received_status(gpr_atm_acq_load(&c->status[i])).error);
Craig Tiller841a99d2016-12-12 16:58:57 -0800548 }
549
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800550 grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c), &c->final_info,
ncteisen969b46e2017-06-08 14:57:11 -0700551 GRPC_CLOSURE_INIT(&c->release_call, release_call, c,
Craig Tillere7a17022017-03-13 10:20:38 -0700552 grpc_schedule_on_exec_ctx));
Craig Tillera4541102015-01-29 11:46:11 -0800553}
554
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800555void grpc_call_ref(grpc_call* c) { gpr_ref(&c->ext_ref); }
Craig Tillerdd36b152017-03-31 08:27:28 -0700556
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800557void grpc_call_unref(grpc_call* c) {
Craig Tillerdd36b152017-03-31 08:27:28 -0700558 if (!gpr_unref(&c->ext_ref)) return;
559
yang-gce1cfea2018-01-31 15:59:50 -0800560 GPR_TIMER_SCOPE("grpc_call_unref", 0);
561
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800562 child_call* cc = c->child;
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800563 grpc_core::ExecCtx exec_ctx;
Craig Tillerb8d3a312015-06-19 17:27:53 -0700564
Craig Tillerdd36b152017-03-31 08:27:28 -0700565 GRPC_API_TRACE("grpc_call_unref(c=%p)", 1, (c));
Craig Tiller841a99d2016-12-12 16:58:57 -0800566
Craig Tiller9fd9a442017-04-05 16:52:34 -0700567 if (cc) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800568 parent_call* pc = get_parent_call(cc->parent);
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700569 gpr_mu_lock(&pc->child_list_mu);
570 if (c == pc->first_child) {
571 pc->first_child = cc->sibling_next;
572 if (c == pc->first_child) {
Craig Tiller4782d922017-11-10 09:53:21 -0800573 pc->first_child = nullptr;
Craig Tiller841a99d2016-12-12 16:58:57 -0800574 }
Craig Tiller841a99d2016-12-12 16:58:57 -0800575 }
Yash Tibrewalb2a54ac2017-09-13 10:18:07 -0700576 cc->sibling_prev->child->sibling_next = cc->sibling_next;
577 cc->sibling_next->child->sibling_prev = cc->sibling_prev;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700578 gpr_mu_unlock(&pc->child_list_mu);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800579 GRPC_CALL_INTERNAL_UNREF(cc->parent, "child");
Craig Tiller841a99d2016-12-12 16:58:57 -0800580 }
581
Craig Tiller841a99d2016-12-12 16:58:57 -0800582 GPR_ASSERT(!c->destroy_called);
583 c->destroy_called = 1;
Craig Tiller1c10a7b2017-03-29 14:35:16 -0700584 bool cancel = gpr_atm_acq_load(&c->any_ops_sent_atm) != 0 &&
585 gpr_atm_acq_load(&c->received_final_op_atm) == 0;
Craig Tiller37cbc3f2017-02-16 14:54:55 -0800586 if (cancel) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800587 cancel_with_error(c, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED);
Mark D. Roth180c6b12017-09-05 13:46:41 -0700588 } else {
589 // Unset the call combiner cancellation closure. This has the
590 // effect of scheduling the previously set cancellation closure, if
591 // any, so that it can release any internal references it may be
592 // holding to the call stack.
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800593 grpc_call_combiner_set_notify_on_cancel(&c->call_combiner, nullptr);
Craig Tiller37cbc3f2017-02-16 14:54:55 -0800594 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800595 GRPC_CALL_INTERNAL_UNREF(c, "destroy");
Craig Tillerf0f70a82016-06-23 13:55:06 -0700596}
Craig Tiller30547562015-02-05 17:04:51 -0800597
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800598grpc_call_error grpc_call_cancel(grpc_call* call, void* reserved) {
Craig Tiller841a99d2016-12-12 16:58:57 -0800599 GRPC_API_TRACE("grpc_call_cancel(call=%p, reserved=%p)", 2, (call, reserved));
600 GPR_ASSERT(!reserved);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800601 grpc_core::ExecCtx exec_ctx;
602 cancel_with_error(call, STATUS_FROM_API_OVERRIDE, GRPC_ERROR_CANCELLED);
603
Craig Tiller37cbc3f2017-02-16 14:54:55 -0800604 return GRPC_CALL_OK;
Craig Tiller841a99d2016-12-12 16:58:57 -0800605}
606
Mark D. Roth764cf042017-09-01 09:00:06 -0700607// This is called via the call combiner to start sending a batch down
608// the filter stack.
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800609static void execute_batch_in_call_combiner(void* arg, grpc_error* ignored) {
yang-gce1cfea2018-01-31 15:59:50 -0800610 GPR_TIMER_SCOPE("execute_batch", 0);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800611 grpc_transport_stream_op_batch* batch = (grpc_transport_stream_op_batch*)arg;
612 grpc_call* call = (grpc_call*)batch->handler_private.extra_arg;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800613 grpc_call_element* elem = CALL_ELEM_FROM_CALL(call, 0);
Mark D. Roth764cf042017-09-01 09:00:06 -0700614 GRPC_CALL_LOG_OP(GPR_INFO, elem, batch);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800615 elem->filter->start_transport_stream_op_batch(elem, batch);
Mark D. Roth764cf042017-09-01 09:00:06 -0700616}
Craig Tiller841a99d2016-12-12 16:58:57 -0800617
Mark D. Roth764cf042017-09-01 09:00:06 -0700618// start_batch_closure points to a caller-allocated closure to be used
619// for entering the call combiner.
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800620static void execute_batch(grpc_call* call,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800621 grpc_transport_stream_op_batch* batch,
622 grpc_closure* start_batch_closure) {
Mark D. Roth764cf042017-09-01 09:00:06 -0700623 batch->handler_private.extra_arg = call;
624 GRPC_CLOSURE_INIT(start_batch_closure, execute_batch_in_call_combiner, batch,
625 grpc_schedule_on_exec_ctx);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800626 GRPC_CALL_COMBINER_START(&call->call_combiner, start_batch_closure,
Mark D. Roth764cf042017-09-01 09:00:06 -0700627 GRPC_ERROR_NONE, "executing batch");
Craig Tiller841a99d2016-12-12 16:58:57 -0800628}
629
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800630char* grpc_call_get_peer(grpc_call* call) {
631 char* peer_string = (char*)gpr_atm_acq_load(&call->peer_string);
Craig Tiller4782d922017-11-10 09:53:21 -0800632 if (peer_string != nullptr) return gpr_strdup(peer_string);
Mark D. Roth764cf042017-09-01 09:00:06 -0700633 peer_string = grpc_channel_get_target(call->channel);
Craig Tiller4782d922017-11-10 09:53:21 -0800634 if (peer_string != nullptr) return peer_string;
Mark D. Roth764cf042017-09-01 09:00:06 -0700635 return gpr_strdup("unknown");
Craig Tiller841a99d2016-12-12 16:58:57 -0800636}
637
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800638grpc_call* grpc_call_from_top_element(grpc_call_element* elem) {
Craig Tiller841a99d2016-12-12 16:58:57 -0800639 return CALL_FROM_TOP_ELEM(elem);
640}
641
642/*******************************************************************************
643 * CANCELLATION
644 */
645
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800646grpc_call_error grpc_call_cancel_with_status(grpc_call* c,
Craig Tiller841a99d2016-12-12 16:58:57 -0800647 grpc_status_code status,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800648 const char* description,
649 void* reserved) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800650 grpc_core::ExecCtx exec_ctx;
Craig Tiller841a99d2016-12-12 16:58:57 -0800651 GRPC_API_TRACE(
652 "grpc_call_cancel_with_status("
653 "c=%p, status=%d, description=%s, reserved=%p)",
654 4, (c, (int)status, description, reserved));
Craig Tiller4782d922017-11-10 09:53:21 -0800655 GPR_ASSERT(reserved == nullptr);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800656 cancel_with_status(c, STATUS_FROM_API_OVERRIDE, status, description);
657
Craig Tiller2dc32ea2017-01-31 15:32:34 -0800658 return GRPC_CALL_OK;
Craig Tiller841a99d2016-12-12 16:58:57 -0800659}
660
Mark D. Roth764cf042017-09-01 09:00:06 -0700661typedef struct {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800662 grpc_call* call;
Mark D. Roth764cf042017-09-01 09:00:06 -0700663 grpc_closure start_batch;
664 grpc_closure finish_batch;
665} cancel_state;
666
667// The on_complete callback used when sending a cancel_stream batch down
668// the filter stack. Yields the call combiner when the batch is done.
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800669static void done_termination(void* arg, grpc_error* error) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800670 cancel_state* state = (cancel_state*)arg;
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800671 GRPC_CALL_COMBINER_STOP(&state->call->call_combiner,
Mark D. Roth764cf042017-09-01 09:00:06 -0700672 "on_complete for cancel_stream op");
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800673 GRPC_CALL_INTERNAL_UNREF(state->call, "termination");
Mark D. Roth764cf042017-09-01 09:00:06 -0700674 gpr_free(state);
Craig Tiller841a99d2016-12-12 16:58:57 -0800675}
676
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800677static void cancel_with_error(grpc_call* c, status_source source,
678 grpc_error* error) {
Craig Tillerc5b90df2017-03-10 16:11:08 -0800679 GRPC_CALL_INTERNAL_REF(c, "termination");
Mark D. Roth764cf042017-09-01 09:00:06 -0700680 // Inform the call combiner of the cancellation, so that it can cancel
681 // any in-flight asynchronous actions that may be holding the call
682 // combiner. This ensures that the cancel_stream batch can be sent
683 // down the filter stack in a timely manner.
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800684 grpc_call_combiner_cancel(&c->call_combiner, GRPC_ERROR_REF(error));
685 set_status_from_error(c, source, GRPC_ERROR_REF(error));
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800686 cancel_state* state = (cancel_state*)gpr_malloc(sizeof(*state));
Mark D. Roth764cf042017-09-01 09:00:06 -0700687 state->call = c;
688 GRPC_CLOSURE_INIT(&state->finish_batch, done_termination, state,
689 grpc_schedule_on_exec_ctx);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800690 grpc_transport_stream_op_batch* op =
Mark D. Roth764cf042017-09-01 09:00:06 -0700691 grpc_make_transport_stream_op(&state->finish_batch);
Craig Tiller22b182b2017-03-16 10:56:58 -0700692 op->cancel_stream = true;
693 op->payload->cancel_stream.cancel_error = error;
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800694 execute_batch(c, op, &state->start_batch);
Craig Tiller255edaa2016-12-13 09:04:55 -0800695}
696
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800697static grpc_error* error_from_status(grpc_status_code status,
698 const char* description) {
Alexander Polcyn088e85c2017-07-28 14:53:20 -0700699 // copying 'description' is needed to ensure the grpc_call_cancel_with_status
700 // guarantee that can be short-lived.
Craig Tiller841a99d2016-12-12 16:58:57 -0800701 return grpc_error_set_int(
ncteisen4b36a3d2017-03-13 19:08:06 -0700702 grpc_error_set_str(GRPC_ERROR_CREATE_FROM_COPIED_STRING(description),
703 GRPC_ERROR_STR_GRPC_MESSAGE,
704 grpc_slice_from_copied_string(description)),
Craig Tiller841a99d2016-12-12 16:58:57 -0800705 GRPC_ERROR_INT_GRPC_STATUS, status);
706}
707
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800708static void cancel_with_status(grpc_call* c, status_source source,
709 grpc_status_code status,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800710 const char* description) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800711 cancel_with_error(c, source, error_from_status(status, description));
Craig Tiller841a99d2016-12-12 16:58:57 -0800712}
713
714/*******************************************************************************
715 * FINAL STATUS CODE MANIPULATION
716 */
717
Yash Tibrewal0ee75742017-10-13 16:07:13 -0700718static bool get_final_status_from(
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800719 grpc_call* call, grpc_error* error, bool allow_ok_status,
Yash Tibrewal4e9265c2017-11-09 17:46:29 -0800720 void (*set_value)(grpc_status_code code, void* user_data),
ncteisen40737d62017-11-13 08:02:35 -0800721 void* set_value_user_data, grpc_slice* details, const char** error_string) {
Craig Tiller737b6252017-01-09 15:25:15 -0800722 grpc_status_code code;
ncteiseneb2b1152017-03-28 15:27:27 -0700723 grpc_slice slice = grpc_empty_slice();
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800724 grpc_error_get_status(error, call->send_deadline, &code, &slice, nullptr,
725 error_string);
Craig Tiller58b30cd2017-01-31 17:07:36 -0800726 if (code == GRPC_STATUS_OK && !allow_ok_status) {
727 return false;
728 }
Craig Tiller737b6252017-01-09 15:25:15 -0800729
730 set_value(code, set_value_user_data);
Craig Tiller4782d922017-11-10 09:53:21 -0800731 if (details != nullptr) {
ncteisenbbb38012017-03-10 14:58:43 -0800732 *details = grpc_slice_ref_internal(slice);
Craig Tiller737b6252017-01-09 15:25:15 -0800733 }
Craig Tiller58b30cd2017-01-31 17:07:36 -0800734 return true;
Craig Tiller737b6252017-01-09 15:25:15 -0800735}
736
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800737static void get_final_status(
738 grpc_call* call, void (*set_value)(grpc_status_code code, void* user_data),
739 void* set_value_user_data, grpc_slice* details, const char** error_string) {
Craig Tiller841a99d2016-12-12 16:58:57 -0800740 int i;
Craig Tiller4bab9462017-02-22 08:56:02 -0800741 received_status status[STATUS_SOURCE_COUNT];
742 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
743 status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
744 }
Craig Tiller6014e8a2017-10-16 13:50:29 -0700745 if (grpc_call_error_trace.enabled()) {
Craig Tiller58b30cd2017-01-31 17:07:36 -0800746 gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
747 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800748 if (status[i].is_set) {
749 gpr_log(GPR_DEBUG, " %d: %s", i, grpc_error_string(status[i].error));
Craig Tiller58b30cd2017-01-31 17:07:36 -0800750 }
Craig Tiller841a99d2016-12-12 16:58:57 -0800751 }
752 }
Craig Tiller58b30cd2017-01-31 17:07:36 -0800753 /* first search through ignoring "OK" statuses: if something went wrong,
754 * ensure we report it */
755 for (int allow_ok_status = 0; allow_ok_status < 2; allow_ok_status++) {
756 /* search for the best status we can present: ideally the error we use has a
757 clearly defined grpc-status, and we'll prefer that. */
758 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800759 if (status[i].is_set &&
760 grpc_error_has_clear_grpc_status(status[i].error)) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800761 if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
762 set_value, set_value_user_data, details,
763 error_string)) {
Craig Tiller58b30cd2017-01-31 17:07:36 -0800764 return;
765 }
766 }
767 }
768 /* If no clearly defined status exists, search for 'anything' */
769 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800770 if (status[i].is_set) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800771 if (get_final_status_from(call, status[i].error, allow_ok_status != 0,
772 set_value, set_value_user_data, details,
773 error_string)) {
Craig Tiller58b30cd2017-01-31 17:07:36 -0800774 return;
775 }
776 }
Craig Tiller737b6252017-01-09 15:25:15 -0800777 }
778 }
779 /* If nothing exists, set some default */
Craig Tiller841a99d2016-12-12 16:58:57 -0800780 if (call->is_client) {
781 set_value(GRPC_STATUS_UNKNOWN, set_value_user_data);
Craig Tillerbe1b9a72016-06-24 13:22:11 -0700782 } else {
Craig Tiller841a99d2016-12-12 16:58:57 -0800783 set_value(GRPC_STATUS_OK, set_value_user_data);
Craig Tillerf0f70a82016-06-23 13:55:06 -0700784 }
Craig Tillerf0f70a82016-06-23 13:55:06 -0700785}
786
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800787static void set_status_from_error(grpc_call* call, status_source source,
788 grpc_error* error) {
Craig Tiller4bab9462017-02-22 08:56:02 -0800789 if (!gpr_atm_rel_cas(&call->status[source],
Yash Tibrewal37fdb732017-09-25 16:45:02 -0700790 pack_received_status({false, GRPC_ERROR_NONE}),
791 pack_received_status({true, error}))) {
Craig Tiller841a99d2016-12-12 16:58:57 -0800792 GRPC_ERROR_UNREF(error);
Craig Tiller841a99d2016-12-12 16:58:57 -0800793 }
Craig Tiller68752722015-01-29 14:59:54 -0800794}
795
Craig Tiller841a99d2016-12-12 16:58:57 -0800796/*******************************************************************************
797 * COMPRESSION
798 */
799
Muxi Yane6d888d2017-09-14 09:42:56 -0700800static void set_incoming_message_compression_algorithm(
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800801 grpc_call* call, grpc_message_compression_algorithm algo) {
Muxi Yane6d888d2017-09-14 09:42:56 -0700802 GPR_ASSERT(algo < GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT);
803 call->incoming_message_compression_algorithm = algo;
David Garcia Quintasdb94b272015-06-15 18:37:01 -0700804}
805
Muxi Yan68a0fd52017-07-21 09:26:04 -0700806static void set_incoming_stream_compression_algorithm(
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800807 grpc_call* call, grpc_stream_compression_algorithm algo) {
Muxi Yan68a0fd52017-07-21 09:26:04 -0700808 GPR_ASSERT(algo < GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT);
809 call->incoming_stream_compression_algorithm = algo;
810}
811
Muxi Yan68ee7ce2017-09-25 12:38:35 -0700812grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800813 grpc_call* call) {
Muxi Yane6d888d2017-09-14 09:42:56 -0700814 grpc_compression_algorithm algorithm = GRPC_COMPRESS_NONE;
815 grpc_compression_algorithm_from_message_stream_compression_algorithm(
816 &algorithm, call->incoming_message_compression_algorithm,
817 call->incoming_stream_compression_algorithm);
David Garcia Quintas64824be2015-10-06 19:45:36 -0700818 return algorithm;
David Garcia Quintas7c0d9142015-07-23 04:58:20 -0700819}
820
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700821static grpc_compression_algorithm compression_algorithm_for_level_locked(
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800822 grpc_call* call, grpc_compression_level level) {
David Garcia Quintasac094472016-05-18 20:25:57 -0700823 return grpc_compression_algorithm_for_level(level,
824 call->encodings_accepted_by_peer);
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700825}
826
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800827uint32_t grpc_call_test_only_get_message_flags(grpc_call* call) {
Craig Tiller7536af02015-12-22 13:49:30 -0800828 uint32_t flags;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800829 flags = call->test_only_last_message_flags;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800830 return flags;
831}
832
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800833static void destroy_encodings_accepted_by_peer(void* p) { return; }
Craig Tiller3ff27542015-10-09 15:39:44 -0700834
Muxi Yan99024d62017-12-08 14:02:18 -0800835static void set_encodings_accepted_by_peer(grpc_call* call, grpc_mdelem mdel,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800836 uint32_t* encodings_accepted_by_peer,
Muxi Yane6d888d2017-09-14 09:42:56 -0700837 bool stream_encoding) {
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700838 size_t i;
Muxi Yane6d888d2017-09-14 09:42:56 -0700839 uint32_t algorithm;
Craig Tillerd41a4a72016-10-26 16:16:06 -0700840 grpc_slice_buffer accept_encoding_parts;
841 grpc_slice accept_encoding_slice;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800842 void* accepted_user_data;
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700843
Craig Tiller3ff27542015-10-09 15:39:44 -0700844 accepted_user_data =
845 grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
Craig Tiller4782d922017-11-10 09:53:21 -0800846 if (accepted_user_data != nullptr) {
Muxi Yane6d888d2017-09-14 09:42:56 -0700847 *encodings_accepted_by_peer =
Craig Tiller7536af02015-12-22 13:49:30 -0800848 (uint32_t)(((uintptr_t)accepted_user_data) - 1);
Craig Tiller3ff27542015-10-09 15:39:44 -0700849 return;
850 }
851
Muxi Yane6d888d2017-09-14 09:42:56 -0700852 *encodings_accepted_by_peer = 0;
853
Craig Tiller0160de92016-11-18 08:46:46 -0800854 accept_encoding_slice = GRPC_MDVALUE(mdel);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700855 grpc_slice_buffer_init(&accept_encoding_parts);
Muxi Yan68ee7ce2017-09-25 12:38:35 -0700856 grpc_slice_split_without_space(accept_encoding_slice, ",",
857 &accept_encoding_parts);
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700858
Muxi Yane6d888d2017-09-14 09:42:56 -0700859 GPR_BITSET(encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700860 for (i = 0; i < accept_encoding_parts.count; i++) {
Muxi Yane6d888d2017-09-14 09:42:56 -0700861 int r;
Craig Tiller68208fe2016-11-14 14:35:02 -0800862 grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
Muxi Yane6d888d2017-09-14 09:42:56 -0700863 if (!stream_encoding) {
864 r = grpc_message_compression_algorithm_parse(
865 accept_encoding_entry_slice,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800866 (grpc_message_compression_algorithm*)&algorithm);
Muxi Yane6d888d2017-09-14 09:42:56 -0700867 } else {
868 r = grpc_stream_compression_algorithm_parse(
869 accept_encoding_entry_slice,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800870 (grpc_stream_compression_algorithm*)&algorithm);
Muxi Yane6d888d2017-09-14 09:42:56 -0700871 }
872 if (r) {
873 GPR_BITSET(encodings_accepted_by_peer, algorithm);
Craig Tillera82950e2015-09-22 12:33:20 -0700874 } else {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800875 char* accept_encoding_entry_str =
Craig Tillerb4aa70e2016-12-09 09:40:11 -0800876 grpc_slice_to_c_string(accept_encoding_entry_slice);
Craig Tillera82950e2015-09-22 12:33:20 -0700877 gpr_log(GPR_ERROR,
878 "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
879 accept_encoding_entry_str);
880 gpr_free(accept_encoding_entry_str);
David Garcia Quintasb8edf7e2015-07-08 20:18:57 -0700881 }
Craig Tillera82950e2015-09-22 12:33:20 -0700882 }
Craig Tiller3ff27542015-10-09 15:39:44 -0700883
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800884 grpc_slice_buffer_destroy_internal(&accept_encoding_parts);
Craig Tiller3ff27542015-10-09 15:39:44 -0700885
886 grpc_mdelem_set_user_data(
887 mdel, destroy_encodings_accepted_by_peer,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800888 (void*)(((uintptr_t)(*encodings_accepted_by_peer)) + 1));
Muxi Yan68a0fd52017-07-21 09:26:04 -0700889}
890
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800891uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call* call) {
Craig Tiller7536af02015-12-22 13:49:30 -0800892 uint32_t encodings_accepted_by_peer;
David Garcia Quintas0c331882015-10-08 14:51:54 -0700893 encodings_accepted_by_peer = call->encodings_accepted_by_peer;
David Garcia Quintas0c331882015-10-08 14:51:54 -0700894 return encodings_accepted_by_peer;
Craig Tiller68752722015-01-29 14:59:54 -0800895}
896
Muxi Yan68a0fd52017-07-21 09:26:04 -0700897grpc_stream_compression_algorithm
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800898grpc_call_test_only_get_incoming_stream_encodings(grpc_call* call) {
Muxi Yan68a0fd52017-07-21 09:26:04 -0700899 return call->incoming_stream_compression_algorithm;
900}
901
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800902static grpc_linked_mdelem* linked_from_md(const grpc_metadata* md) {
903 return (grpc_linked_mdelem*)&md->internal_data;
Craig Tillerc12fee62015-02-03 11:55:50 -0800904}
905
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800906static grpc_metadata* get_md_elem(grpc_metadata* metadata,
907 grpc_metadata* additional_metadata, int i,
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700908 int count) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800909 grpc_metadata* res =
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700910 i < count ? &metadata[i] : &additional_metadata[i - count];
911 GPR_ASSERT(res);
912 return res;
913}
914
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800915static int prepare_application_metadata(grpc_call* call, int count,
916 grpc_metadata* metadata,
917 int is_trailing,
918 int prepend_extra_metadata,
919 grpc_metadata* additional_metadata,
920 int additional_metadata_count) {
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700921 int total_count = count + additional_metadata_count;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800922 int i;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800923 grpc_metadata_batch* batch =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800924 &call->metadata_batch[0 /* is_receiving */][is_trailing];
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700925 for (i = 0; i < total_count; i++) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800926 const grpc_metadata* md =
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700927 get_md_elem(metadata, additional_metadata, i, count);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800928 grpc_linked_mdelem* l = linked_from_md(md);
Craig Tillerb42445c2016-04-22 13:11:44 -0700929 GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
Craig Tillerf2b5b7e2017-01-10 08:28:59 -0800930 if (!GRPC_LOG_IF_ERROR("validate_metadata",
931 grpc_validate_header_key_is_legal(md->key))) {
Craig Tillerb42445c2016-04-22 13:11:44 -0700932 break;
Craig Tillerdf2d9222016-11-18 16:38:57 -0800933 } else if (!grpc_is_binary_header(md->key) &&
Craig Tillerf2b5b7e2017-01-10 08:28:59 -0800934 !GRPC_LOG_IF_ERROR(
935 "validate_metadata",
936 grpc_validate_header_nonbin_value_is_legal(md->value))) {
Craig Tillerb42445c2016-04-22 13:11:44 -0700937 break;
938 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800939 l->md = grpc_mdelem_from_grpc_metadata((grpc_metadata*)md);
Craig Tillerb42445c2016-04-22 13:11:44 -0700940 }
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700941 if (i != total_count) {
Craig Tiller5ae3ffb2016-11-18 14:58:32 -0800942 for (int j = 0; j < i; j++) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800943 const grpc_metadata* md =
David Garcia Quintasa301eaa2016-05-06 16:59:03 -0700944 get_md_elem(metadata, additional_metadata, j, count);
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800945 grpc_linked_mdelem* l = linked_from_md(md);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800946 GRPC_MDELEM_UNREF(l->md);
Craig Tillerb42445c2016-04-22 13:11:44 -0700947 }
948 return 0;
949 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800950 if (prepend_extra_metadata) {
951 if (call->send_extra_metadata_count == 0) {
952 prepend_extra_metadata = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700953 } else {
Craig Tiller09608182016-11-22 15:43:56 -0800954 for (i = 0; i < call->send_extra_metadata_count; i++) {
955 GRPC_LOG_IF_ERROR("prepare_application_metadata",
956 grpc_metadata_batch_link_tail(
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800957 batch, &call->send_extra_metadata[i]));
Craig Tillera82950e2015-09-22 12:33:20 -0700958 }
Craig Tiller629b0ed2015-04-22 11:14:26 -0700959 }
Craig Tillera82950e2015-09-22 12:33:20 -0700960 }
Craig Tiller09608182016-11-22 15:43:56 -0800961 for (i = 0; i < total_count; i++) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800962 grpc_metadata* md = get_md_elem(metadata, additional_metadata, i, count);
963 grpc_linked_mdelem* l = linked_from_md(md);
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800964 grpc_error* error = grpc_metadata_batch_link_tail(batch, l);
Noah Eisene6432bf2017-07-31 16:37:15 -0700965 if (error != GRPC_ERROR_NONE) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -0800966 GRPC_MDELEM_UNREF(l->md);
Noah Eisene6432bf2017-07-31 16:37:15 -0700967 }
968 GRPC_LOG_IF_ERROR("prepare_application_metadata", error);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800969 }
Craig Tiller09608182016-11-22 15:43:56 -0800970 call->send_extra_metadata_count = 0;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -0800971
Craig Tillerb96d0012015-05-06 15:33:23 -0700972 return 1;
973}
974
Craig Tiller566316f2015-02-02 15:25:32 -0800975/* we offset status by a small amount when storing it into transport metadata
976 as metadata cannot store a 0 value (which is used as OK for grpc_status_codes
977 */
978#define STATUS_OFFSET 1
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800979static void destroy_status(void* ignored) {}
Craig Tiller566316f2015-02-02 15:25:32 -0800980
Craig Tiller0160de92016-11-18 08:46:46 -0800981static uint32_t decode_status(grpc_mdelem md) {
Craig Tiller7536af02015-12-22 13:49:30 -0800982 uint32_t status;
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800983 void* user_data;
Craig Tiller0160de92016-11-18 08:46:46 -0800984 if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) return 0;
985 if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_1)) return 1;
986 if (grpc_mdelem_eq(md, GRPC_MDELEM_GRPC_STATUS_2)) return 2;
Craig Tillerebdef9d2015-11-19 17:09:49 -0800987 user_data = grpc_mdelem_get_user_data(md, destroy_status);
Craig Tiller4782d922017-11-10 09:53:21 -0800988 if (user_data != nullptr) {
Craig Tiller7536af02015-12-22 13:49:30 -0800989 status = ((uint32_t)(intptr_t)user_data) - STATUS_OFFSET;
Craig Tillera82950e2015-09-22 12:33:20 -0700990 } else {
Craig Tiller0160de92016-11-18 08:46:46 -0800991 if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(md), &status)) {
Craig Tillera82950e2015-09-22 12:33:20 -0700992 status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
Craig Tiller566316f2015-02-02 15:25:32 -0800993 }
Craig Tillera82950e2015-09-22 12:33:20 -0700994 grpc_mdelem_set_user_data(md, destroy_status,
Muxi Yan38fcd0c2017-12-06 18:52:18 -0800995 (void*)(intptr_t)(status + STATUS_OFFSET));
Craig Tillera82950e2015-09-22 12:33:20 -0700996 }
Craig Tiller566316f2015-02-02 15:25:32 -0800997 return status;
998}
999
Muxi Yan68ee7ce2017-09-25 12:38:35 -07001000static grpc_message_compression_algorithm decode_message_compression(
1001 grpc_mdelem md) {
Muxi Yane6d888d2017-09-14 09:42:56 -07001002 grpc_message_compression_algorithm algorithm =
1003 grpc_message_compression_algorithm_from_slice(GRPC_MDVALUE(md));
1004 if (algorithm == GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001005 char* md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
David Garcia Quintas303d3082016-05-05 18:25:34 -07001006 gpr_log(GPR_ERROR,
Muxi Yane6d888d2017-09-14 09:42:56 -07001007 "Invalid incoming message compression algorithm: '%s'. "
1008 "Interpreting incoming data as uncompressed.",
David Garcia Quintas303d3082016-05-05 18:25:34 -07001009 md_c_str);
Craig Tiller68208fe2016-11-14 14:35:02 -08001010 gpr_free(md_c_str);
Muxi Yane6d888d2017-09-14 09:42:56 -07001011 return GRPC_MESSAGE_COMPRESS_NONE;
Craig Tillera82950e2015-09-22 12:33:20 -07001012 }
David Garcia Quintasfc0fa332015-06-25 18:11:07 -07001013 return algorithm;
David Garcia Quintasdb94b272015-06-15 18:37:01 -07001014}
1015
Muxi Yan68a0fd52017-07-21 09:26:04 -07001016static grpc_stream_compression_algorithm decode_stream_compression(
1017 grpc_mdelem md) {
1018 grpc_stream_compression_algorithm algorithm =
1019 grpc_stream_compression_algorithm_from_slice(GRPC_MDVALUE(md));
1020 if (algorithm == GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001021 char* md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
Muxi Yan68a0fd52017-07-21 09:26:04 -07001022 gpr_log(GPR_ERROR,
1023 "Invalid incoming stream compression algorithm: '%s'. Interpreting "
1024 "incoming data as uncompressed.",
1025 md_c_str);
1026 gpr_free(md_c_str);
1027 return GRPC_STREAM_COMPRESS_NONE;
1028 }
1029 return algorithm;
1030}
1031
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001032static void publish_app_metadata(grpc_call* call, grpc_metadata_batch* b,
Craig Tillera7d37a32016-11-22 14:37:16 -08001033 int is_trailing) {
Craig Tiller09608182016-11-22 15:43:56 -08001034 if (b->list.count == 0) return;
Ken Payson1dc08332018-01-25 16:52:51 -08001035 if (is_trailing && call->buffered_metadata[1] == nullptr) return;
yang-gce1cfea2018-01-31 15:59:50 -08001036 GPR_TIMER_SCOPE("publish_app_metadata", 0);
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001037 grpc_metadata_array* dest;
1038 grpc_metadata* mdusr;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001039 dest = call->buffered_metadata[is_trailing];
Craig Tillerb0f3bca2016-11-22 14:54:10 -08001040 if (dest->count + b->list.count > dest->capacity) {
1041 dest->capacity =
1042 GPR_MAX(dest->capacity + b->list.count, dest->capacity * 3 / 2);
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001043 dest->metadata = (grpc_metadata*)gpr_realloc(
Yash Tibrewalca3c1c02017-09-07 22:47:16 -07001044 dest->metadata, sizeof(grpc_metadata) * dest->capacity);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001045 }
Craig Tiller4782d922017-11-10 09:53:21 -08001046 for (grpc_linked_mdelem* l = b->list.head; l != nullptr; l = l->next) {
Craig Tillera7d37a32016-11-22 14:37:16 -08001047 mdusr = &dest->metadata[dest->count++];
Craig Tillercf0a2022016-11-23 11:36:21 -08001048 /* we pass back borrowed slices that are valid whilst the call is valid */
1049 mdusr->key = GRPC_MDKEY(l->md);
1050 mdusr->value = GRPC_MDVALUE(l->md);
Craig Tillera7d37a32016-11-22 14:37:16 -08001051 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001052}
Craig Tiller566316f2015-02-02 15:25:32 -08001053
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001054static void recv_initial_filter(grpc_call* call, grpc_metadata_batch* b) {
Craig Tiller4782d922017-11-10 09:53:21 -08001055 if (b->idx.named.content_encoding != nullptr) {
yang-gce1cfea2018-01-31 15:59:50 -08001056 GPR_TIMER_SCOPE("incoming_stream_compression_algorithm", 0);
Muxi Yan68a0fd52017-07-21 09:26:04 -07001057 set_incoming_stream_compression_algorithm(
1058 call, decode_stream_compression(b->idx.named.content_encoding->md));
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001059 grpc_metadata_batch_remove(b, b->idx.named.content_encoding);
Muxi Yane6d888d2017-09-14 09:42:56 -07001060 }
Muxi Yan67454d72017-12-06 22:09:36 -08001061 if (b->idx.named.grpc_encoding != nullptr) {
yang-gce1cfea2018-01-31 15:59:50 -08001062 GPR_TIMER_SCOPE("incoming_message_compression_algorithm", 0);
Muxi Yane6d888d2017-09-14 09:42:56 -07001063 set_incoming_message_compression_algorithm(
1064 call, decode_message_compression(b->idx.named.grpc_encoding->md));
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001065 grpc_metadata_batch_remove(b, b->idx.named.grpc_encoding);
Craig Tillera82950e2015-09-22 12:33:20 -07001066 }
Muxi Yane6d888d2017-09-14 09:42:56 -07001067 uint32_t message_encodings_accepted_by_peer = 1u;
1068 uint32_t stream_encodings_accepted_by_peer = 1u;
Craig Tiller4782d922017-11-10 09:53:21 -08001069 if (b->idx.named.grpc_accept_encoding != nullptr) {
yang-gce1cfea2018-01-31 15:59:50 -08001070 GPR_TIMER_SCOPE("encodings_accepted_by_peer", 0);
Muxi Yan99024d62017-12-08 14:02:18 -08001071 set_encodings_accepted_by_peer(call, b->idx.named.grpc_accept_encoding->md,
Muxi Yane6d888d2017-09-14 09:42:56 -07001072 &message_encodings_accepted_by_peer, false);
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001073 grpc_metadata_batch_remove(b, b->idx.named.grpc_accept_encoding);
Craig Tillera7d37a32016-11-22 14:37:16 -08001074 }
Craig Tiller4782d922017-11-10 09:53:21 -08001075 if (b->idx.named.accept_encoding != nullptr) {
yang-gce1cfea2018-01-31 15:59:50 -08001076 GPR_TIMER_SCOPE("stream_encodings_accepted_by_peer", 0);
Muxi Yan99024d62017-12-08 14:02:18 -08001077 set_encodings_accepted_by_peer(call, b->idx.named.accept_encoding->md,
Muxi Yane6d888d2017-09-14 09:42:56 -07001078 &stream_encodings_accepted_by_peer, true);
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001079 grpc_metadata_batch_remove(b, b->idx.named.accept_encoding);
Muxi Yan68a0fd52017-07-21 09:26:04 -07001080 }
Muxi Yane6d888d2017-09-14 09:42:56 -07001081 call->encodings_accepted_by_peer =
1082 grpc_compression_bitset_from_message_stream_compression_bitset(
1083 message_encodings_accepted_by_peer,
1084 stream_encodings_accepted_by_peer);
Craig Tillera7d37a32016-11-22 14:37:16 -08001085 publish_app_metadata(call, b, false);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001086}
Craig Tiller6902ad22015-04-16 08:01:49 -07001087
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001088static void recv_trailing_filter(void* args, grpc_metadata_batch* b) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001089 grpc_call* call = (grpc_call*)args;
Craig Tiller4782d922017-11-10 09:53:21 -08001090 if (b->idx.named.grpc_status != nullptr) {
Mark D. Rothbd3b93b2017-06-22 10:53:01 -07001091 uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001092 grpc_error* error =
Mark D. Rothbd3b93b2017-06-22 10:53:01 -07001093 status_code == GRPC_STATUS_OK
1094 ? GRPC_ERROR_NONE
1095 : grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1096 "Error received from peer"),
1097 GRPC_ERROR_INT_GRPC_STATUS,
1098 (intptr_t)status_code);
Craig Tiller4782d922017-11-10 09:53:21 -08001099 if (b->idx.named.grpc_message != nullptr) {
Mark D. Rothbd3b93b2017-06-22 10:53:01 -07001100 error = grpc_error_set_str(
1101 error, GRPC_ERROR_STR_GRPC_MESSAGE,
1102 grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_message->md)));
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001103 grpc_metadata_batch_remove(b, b->idx.named.grpc_message);
Mark D. Rothbd3b93b2017-06-22 10:53:01 -07001104 } else if (error != GRPC_ERROR_NONE) {
1105 error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE,
1106 grpc_empty_slice());
1107 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001108 set_status_from_error(call, STATUS_FROM_WIRE, error);
1109 grpc_metadata_batch_remove(b, b->idx.named.grpc_status);
Mark D. Rothbd3b93b2017-06-22 10:53:01 -07001110 }
Craig Tillera7d37a32016-11-22 14:37:16 -08001111 publish_app_metadata(call, b, true);
Craig Tiller629b0ed2015-04-22 11:14:26 -07001112}
Craig Tiller8b282cb2015-04-17 14:57:44 -07001113
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001114grpc_call_stack* grpc_call_get_call_stack(grpc_call* call) {
Craig Tillera82950e2015-09-22 12:33:20 -07001115 return CALL_STACK_FROM_CALL(call);
Craig Tiller566316f2015-02-02 15:25:32 -08001116}
1117
Craig Tiller255edaa2016-12-13 09:04:55 -08001118/*******************************************************************************
Craig Tillerfb189f82015-02-03 12:07:07 -08001119 * BATCH API IMPLEMENTATION
1120 */
1121
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001122static void set_status_value_directly(grpc_status_code status, void* dest) {
1123 *(grpc_status_code*)dest = status;
Craig Tillerfb189f82015-02-03 12:07:07 -08001124}
1125
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001126static void set_cancelled_value(grpc_status_code status, void* dest) {
1127 *(int*)dest = (status != GRPC_STATUS_OK);
Craig Tiller166e2502015-02-03 20:14:41 -08001128}
Craig Tillerfb189f82015-02-03 12:07:07 -08001129
Craig Tillerc6549762016-03-09 17:10:43 -08001130static bool are_write_flags_valid(uint32_t flags) {
David Garcia Quintas1d5aca52015-06-14 14:42:04 -07001131 /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */
Craig Tiller7536af02015-12-22 13:49:30 -08001132 const uint32_t allowed_write_positions =
Craig Tillera82950e2015-09-22 12:33:20 -07001133 (GRPC_WRITE_USED_MASK | GRPC_WRITE_INTERNAL_USED_MASK);
Craig Tiller7536af02015-12-22 13:49:30 -08001134 const uint32_t invalid_positions = ~allowed_write_positions;
David Garcia Quintas1d5aca52015-06-14 14:42:04 -07001135 return !(flags & invalid_positions);
1136}
1137
Craig Tillerc6549762016-03-09 17:10:43 -08001138static bool are_initial_metadata_flags_valid(uint32_t flags, bool is_client) {
1139 /* check that only bits in GRPC_WRITE_(INTERNAL?)_USED_MASK are set */
1140 uint32_t invalid_positions = ~GRPC_INITIAL_METADATA_USED_MASK;
1141 if (!is_client) {
1142 invalid_positions |= GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST;
1143 }
1144 return !(flags & invalid_positions);
1145}
1146
Craig Tiller2a11ad12017-02-08 17:09:02 -08001147static int batch_slot_for_op(grpc_op_type type) {
1148 switch (type) {
1149 case GRPC_OP_SEND_INITIAL_METADATA:
1150 return 0;
1151 case GRPC_OP_SEND_MESSAGE:
1152 return 1;
1153 case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
1154 case GRPC_OP_SEND_STATUS_FROM_SERVER:
1155 return 2;
1156 case GRPC_OP_RECV_INITIAL_METADATA:
1157 return 3;
1158 case GRPC_OP_RECV_MESSAGE:
1159 return 4;
1160 case GRPC_OP_RECV_CLOSE_ON_SERVER:
1161 case GRPC_OP_RECV_STATUS_ON_CLIENT:
1162 return 5;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001163 }
Craig Tillerc869da02017-02-08 17:11:17 -08001164 GPR_UNREACHABLE_CODE(return 123456789);
Craig Tiller2a11ad12017-02-08 17:09:02 -08001165}
Craig Tiller89d33792017-02-08 16:39:16 -08001166
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001167static batch_control* allocate_batch_control(grpc_call* call,
1168 const grpc_op* ops,
Craig Tiller89d33792017-02-08 16:39:16 -08001169 size_t num_ops) {
1170 int slot = batch_slot_for_op(ops[0].op);
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001171 batch_control** pslot = &call->active_batches[slot];
Craig Tiller4782d922017-11-10 09:53:21 -08001172 if (*pslot == nullptr) {
Yash Tibrewalca3c1c02017-09-07 22:47:16 -07001173 *pslot =
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001174 (batch_control*)gpr_arena_alloc(call->arena, sizeof(batch_control));
Craig Tillerb58de722017-03-29 14:15:12 -07001175 }
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001176 batch_control* bctl = *pslot;
Craig Tiller4782d922017-11-10 09:53:21 -08001177 if (bctl->call != nullptr) {
1178 return nullptr;
Craig Tiller5e5ef302017-02-09 08:46:49 -08001179 }
1180 memset(bctl, 0, sizeof(*bctl));
1181 bctl->call = call;
Craig Tiller3fddcb42017-03-10 11:01:48 -08001182 bctl->op.payload = &call->stream_op_payload;
Craig Tiller5e5ef302017-02-09 08:46:49 -08001183 return bctl;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001184}
1185
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001186static void finish_batch_completion(void* user_data,
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001187 grpc_cq_completion* storage) {
1188 batch_control* bctl = (batch_control*)user_data;
1189 grpc_call* call = bctl->call;
Craig Tiller4782d922017-11-10 09:53:21 -08001190 bctl->call = nullptr;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001191 GRPC_CALL_INTERNAL_UNREF(call, "completion");
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001192}
1193
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001194static grpc_error* consolidate_batch_errors(batch_control* bctl) {
Craig Tillerb597dcf2017-03-09 07:02:11 -08001195 size_t n = (size_t)gpr_atm_acq_load(&bctl->num_errors);
Craig Tiller94903892016-10-11 15:43:35 -07001196 if (n == 0) {
1197 return GRPC_ERROR_NONE;
1198 } else if (n == 1) {
Craig Tillera78da602017-01-27 08:16:23 -08001199 /* Skip creating a composite error in the case that only one error was
1200 logged */
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001201 grpc_error* e = bctl->errors[0];
Craig Tiller4782d922017-11-10 09:53:21 -08001202 bctl->errors[0] = nullptr;
Craig Tillerad980e32017-01-23 07:46:25 -08001203 return e;
Craig Tiller94903892016-10-11 15:43:35 -07001204 } else {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001205 grpc_error* error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
ncteisen4b36a3d2017-03-13 19:08:06 -07001206 "Call batch failed", bctl->errors, n);
Craig Tiller1c4775c2017-01-06 16:07:45 -08001207 for (size_t i = 0; i < n; i++) {
1208 GRPC_ERROR_UNREF(bctl->errors[i]);
Craig Tiller4782d922017-11-10 09:53:21 -08001209 bctl->errors[i] = nullptr;
Craig Tiller1c4775c2017-01-06 16:07:45 -08001210 }
1211 return error;
Craig Tiller94903892016-10-11 15:43:35 -07001212 }
1213}
1214
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001215static void post_batch_completion(batch_control* bctl) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001216 grpc_call* next_child_call;
1217 grpc_call* call = bctl->call;
1218 grpc_error* error = consolidate_batch_errors(bctl);
Craig Tiller94903892016-10-11 15:43:35 -07001219
Craig Tillerea54b8c2017-03-01 16:58:28 -08001220 if (bctl->op.send_initial_metadata) {
Craig Tiller94903892016-10-11 15:43:35 -07001221 grpc_metadata_batch_destroy(
Muxi Yan99024d62017-12-08 14:02:18 -08001222
Craig Tiller94903892016-10-11 15:43:35 -07001223 &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
1224 }
Craig Tillerea54b8c2017-03-01 16:58:28 -08001225 if (bctl->op.send_message) {
Craig Tillerf927ad12017-01-06 15:27:31 -08001226 call->sending_message = false;
1227 }
Craig Tillerea54b8c2017-03-01 16:58:28 -08001228 if (bctl->op.send_trailing_metadata) {
Craig Tiller94903892016-10-11 15:43:35 -07001229 grpc_metadata_batch_destroy(
Muxi Yan99024d62017-12-08 14:02:18 -08001230
Craig Tiller94903892016-10-11 15:43:35 -07001231 &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */]);
1232 }
Craig Tillerea54b8c2017-03-01 16:58:28 -08001233 if (bctl->op.recv_trailing_metadata) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001234 grpc_metadata_batch* md =
Craig Tiller94903892016-10-11 15:43:35 -07001235 &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001236 recv_trailing_filter(call, md);
Craig Tiller94903892016-10-11 15:43:35 -07001237
Craig Tiller94903892016-10-11 15:43:35 -07001238 /* propagate cancellation to any interested children */
Craig Tillerb18c8ba2017-03-13 15:51:37 -07001239 gpr_atm_rel_store(&call->received_final_op_atm, 1);
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001240 parent_call* pc = get_parent_call(call);
Craig Tiller4782d922017-11-10 09:53:21 -08001241 if (pc != nullptr) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001242 grpc_call* child;
Craig Tiller1c10a7b2017-03-29 14:35:16 -07001243 gpr_mu_lock(&pc->child_list_mu);
1244 child = pc->first_child;
Craig Tiller4782d922017-11-10 09:53:21 -08001245 if (child != nullptr) {
Craig Tiller1c10a7b2017-03-29 14:35:16 -07001246 do {
Yash Tibrewalb2a54ac2017-09-13 10:18:07 -07001247 next_child_call = child->child->sibling_next;
Craig Tiller1c10a7b2017-03-29 14:35:16 -07001248 if (child->cancellation_is_inherited) {
1249 GRPC_CALL_INTERNAL_REF(child, "propagate_cancel");
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001250 cancel_with_error(child, STATUS_FROM_API_OVERRIDE,
Craig Tiller1c10a7b2017-03-29 14:35:16 -07001251 GRPC_ERROR_CANCELLED);
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001252 GRPC_CALL_INTERNAL_UNREF(child, "propagate_cancel");
Craig Tiller1c10a7b2017-03-29 14:35:16 -07001253 }
1254 child = next_child_call;
1255 } while (child != pc->first_child);
1256 }
1257 gpr_mu_unlock(&pc->child_list_mu);
Craig Tiller94903892016-10-11 15:43:35 -07001258 }
1259
1260 if (call->is_client) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001261 get_final_status(call, set_status_value_directly,
Craig Tiller841a99d2016-12-12 16:58:57 -08001262 call->final_op.client.status,
ncteisen40737d62017-11-13 08:02:35 -08001263 call->final_op.client.status_details,
1264 call->final_op.client.error_string);
Craig Tiller94903892016-10-11 15:43:35 -07001265 } else {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001266 get_final_status(call, set_cancelled_value,
ncteisendf817f32017-11-15 16:48:19 -08001267 call->final_op.server.cancelled, nullptr, nullptr);
Craig Tiller94903892016-10-11 15:43:35 -07001268 }
1269
Craig Tiller02b87cd2016-09-02 09:50:08 -07001270 GRPC_ERROR_UNREF(error);
1271 error = GRPC_ERROR_NONE;
1272 }
Craig Tillerf6343042017-09-20 11:11:58 -07001273 if (error != GRPC_ERROR_NONE && bctl->op.recv_message &&
Craig Tiller4782d922017-11-10 09:53:21 -08001274 *call->receiving_buffer != nullptr) {
Craig Tillerf6343042017-09-20 11:11:58 -07001275 grpc_byte_buffer_destroy(*call->receiving_buffer);
Craig Tiller4782d922017-11-10 09:53:21 -08001276 *call->receiving_buffer = nullptr;
Craig Tillerf6343042017-09-20 11:11:58 -07001277 }
Craig Tiller94903892016-10-11 15:43:35 -07001278
Craig Tillerea54b8c2017-03-01 16:58:28 -08001279 if (bctl->completion_data.notify_tag.is_closure) {
Craig Tillerb08fa492016-05-10 14:56:05 -07001280 /* unrefs bctl->error */
Craig Tiller4782d922017-11-10 09:53:21 -08001281 bctl->call = nullptr;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001282 GRPC_CLOSURE_RUN((grpc_closure*)bctl->completion_data.notify_tag.tag,
1283 error);
1284 GRPC_CALL_INTERNAL_UNREF(call, "completion");
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001285 } else {
Craig Tillerb08fa492016-05-10 14:56:05 -07001286 /* unrefs bctl->error */
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001287 grpc_cq_end_op(bctl->call->cq, bctl->completion_data.notify_tag.tag, error,
1288 finish_batch_completion, bctl,
1289 &bctl->completion_data.cq_completion);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001290 }
1291}
1292
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001293static void finish_batch_step(batch_control* bctl) {
Craig Tiller065b1392017-01-09 14:05:07 -08001294 if (gpr_unref(&bctl->steps_to_complete)) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001295 post_batch_completion(bctl);
Craig Tiller065b1392017-01-09 14:05:07 -08001296 }
1297}
1298
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001299static void continue_receiving_slices(batch_control* bctl) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001300 grpc_error* error;
1301 grpc_call* call = bctl->call;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001302 for (;;) {
1303 size_t remaining = call->receiving_stream->length -
1304 (*call->receiving_buffer)->data.raw.slice_buffer.length;
1305 if (remaining == 0) {
1306 call->receiving_message = 0;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001307 grpc_byte_stream_destroy(call->receiving_stream);
Craig Tiller4782d922017-11-10 09:53:21 -08001308 call->receiving_stream = nullptr;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001309 finish_batch_step(bctl);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001310 return;
1311 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001312 if (grpc_byte_stream_next(call->receiving_stream, remaining,
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001313 &call->receiving_slice_ready)) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001314 error =
1315 grpc_byte_stream_pull(call->receiving_stream, &call->receiving_slice);
Muxi Yan29723ee2017-04-12 20:24:42 -07001316 if (error == GRPC_ERROR_NONE) {
1317 grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
1318 call->receiving_slice);
1319 } else {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001320 grpc_byte_stream_destroy(call->receiving_stream);
Craig Tiller4782d922017-11-10 09:53:21 -08001321 call->receiving_stream = nullptr;
Muxi Yan29723ee2017-04-12 20:24:42 -07001322 grpc_byte_buffer_destroy(*call->receiving_buffer);
Craig Tiller4782d922017-11-10 09:53:21 -08001323 *call->receiving_buffer = nullptr;
Muxi Yan29723ee2017-04-12 20:24:42 -07001324 call->receiving_message = 0;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001325 finish_batch_step(bctl);
Muxi Yan29723ee2017-04-12 20:24:42 -07001326 return;
1327 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001328 } else {
1329 return;
1330 }
1331 }
1332}
1333
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001334static void receiving_slice_ready(void* bctlp, grpc_error* error) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001335 batch_control* bctl = (batch_control*)bctlp;
1336 grpc_call* call = bctl->call;
1337 grpc_byte_stream* bs = call->receiving_stream;
Muxi Yan29723ee2017-04-12 20:24:42 -07001338 bool release_error = false;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001339
Craig Tillerc027e772016-05-03 16:27:00 -07001340 if (error == GRPC_ERROR_NONE) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001341 grpc_slice slice;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001342 error = grpc_byte_stream_pull(bs, &slice);
Muxi Yan29723ee2017-04-12 20:24:42 -07001343 if (error == GRPC_ERROR_NONE) {
1344 grpc_slice_buffer_add(&(*call->receiving_buffer)->data.raw.slice_buffer,
1345 slice);
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001346 continue_receiving_slices(bctl);
Muxi Yan29723ee2017-04-12 20:24:42 -07001347 } else {
1348 /* Error returned by grpc_byte_stream_pull needs to be released manually
1349 */
1350 release_error = true;
1351 }
1352 }
1353
1354 if (error != GRPC_ERROR_NONE) {
Craig Tiller6014e8a2017-10-16 13:50:29 -07001355 if (grpc_trace_operation_failures.enabled()) {
Craig Tillera286b042016-06-13 15:20:39 +00001356 GRPC_LOG_IF_ERROR("receiving_slice_ready", GRPC_ERROR_REF(error));
1357 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001358 grpc_byte_stream_destroy(call->receiving_stream);
Craig Tiller4782d922017-11-10 09:53:21 -08001359 call->receiving_stream = nullptr;
Craig Tiller38edec62015-12-14 15:01:29 -08001360 grpc_byte_buffer_destroy(*call->receiving_buffer);
Craig Tiller4782d922017-11-10 09:53:21 -08001361 *call->receiving_buffer = nullptr;
Muxi Yan29723ee2017-04-12 20:24:42 -07001362 call->receiving_message = 0;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001363 finish_batch_step(bctl);
Muxi Yan29723ee2017-04-12 20:24:42 -07001364 if (release_error) {
1365 GRPC_ERROR_UNREF(error);
1366 }
Craig Tiller38edec62015-12-14 15:01:29 -08001367 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001368}
1369
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001370static void process_data_after_md(batch_control* bctl) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001371 grpc_call* call = bctl->call;
Craig Tiller4782d922017-11-10 09:53:21 -08001372 if (call->receiving_stream == nullptr) {
1373 *call->receiving_buffer = nullptr;
Craig Tillera44cbfc2016-02-03 16:02:49 -08001374 call->receiving_message = 0;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001375 finish_batch_step(bctl);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001376 } else {
1377 call->test_only_last_message_flags = call->receiving_stream->flags;
1378 if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) &&
Muxi Yan68ee7ce2017-09-25 12:38:35 -07001379 (call->incoming_message_compression_algorithm >
1380 GRPC_MESSAGE_COMPRESS_NONE)) {
Muxi Yane6d888d2017-09-14 09:42:56 -07001381 grpc_compression_algorithm algo;
Muxi Yan68ee7ce2017-09-25 12:38:35 -07001382 GPR_ASSERT(
1383 grpc_compression_algorithm_from_message_stream_compression_algorithm(
Muxi Yan03fc8572017-10-06 18:47:09 -07001384 &algo, call->incoming_message_compression_algorithm,
1385 (grpc_stream_compression_algorithm)0));
Muxi Yan68ee7ce2017-09-25 12:38:35 -07001386 *call->receiving_buffer =
Muxi Yan67454d72017-12-06 22:09:36 -08001387 grpc_raw_compressed_byte_buffer_create(nullptr, 0, algo);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001388 } else {
Craig Tiller4782d922017-11-10 09:53:21 -08001389 *call->receiving_buffer = grpc_raw_byte_buffer_create(nullptr, 0);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001390 }
ncteisen969b46e2017-06-08 14:57:11 -07001391 GRPC_CLOSURE_INIT(&call->receiving_slice_ready, receiving_slice_ready, bctl,
Craig Tiller91031da2016-12-28 15:44:25 -08001392 grpc_schedule_on_exec_ctx);
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001393 continue_receiving_slices(bctl);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001394 }
1395}
1396
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001397static void receiving_stream_ready(void* bctlp, grpc_error* error) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001398 batch_control* bctl = (batch_control*)bctlp;
1399 grpc_call* call = bctl->call;
Mark D. Roth274c8ed2016-10-04 09:21:42 -07001400 if (error != GRPC_ERROR_NONE) {
Craig Tiller4782d922017-11-10 09:53:21 -08001401 if (call->receiving_stream != nullptr) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001402 grpc_byte_stream_destroy(call->receiving_stream);
Craig Tiller4782d922017-11-10 09:53:21 -08001403 call->receiving_stream = nullptr;
yang-g23f777d2017-02-22 23:32:26 -08001404 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001405 add_batch_error(bctl, GRPC_ERROR_REF(error), true);
1406 cancel_with_error(call, STATUS_FROM_SURFACE, GRPC_ERROR_REF(error));
Mark D. Roth274c8ed2016-10-04 09:21:42 -07001407 }
Yuchen Zeng6eb505b2017-08-25 16:05:29 -07001408 /* If recv_state is RECV_NONE, we will save the batch_control
Yuchen Zenge40e2592017-08-15 15:50:49 -07001409 * object with rel_cas, and will not use it after the cas. Its corresponding
1410 * acq_load is in receiving_initial_metadata_ready() */
Craig Tiller4782d922017-11-10 09:53:21 -08001411 if (error != GRPC_ERROR_NONE || call->receiving_stream == nullptr ||
Yuchen Zeng6eb505b2017-08-25 16:05:29 -07001412 !gpr_atm_rel_cas(&call->recv_state, RECV_NONE, (gpr_atm)bctlp)) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001413 process_data_after_md(bctl);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001414 }
1415}
1416
Mark D. Roth764cf042017-09-01 09:00:06 -07001417// The recv_message_ready callback used when sending a batch containing
1418// a recv_message op down the filter stack. Yields the call combiner
1419// before processing the received message.
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001420static void receiving_stream_ready_in_call_combiner(void* bctlp,
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001421 grpc_error* error) {
1422 batch_control* bctl = (batch_control*)bctlp;
1423 grpc_call* call = bctl->call;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001424 GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_message_ready");
1425 receiving_stream_ready(bctlp, error);
Mark D. Roth764cf042017-09-01 09:00:06 -07001426}
1427
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001428static void validate_filtered_metadata(batch_control* bctl) {
Muxi Yane6d888d2017-09-14 09:42:56 -07001429 grpc_compression_algorithm compression_algorithm;
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001430 grpc_call* call = bctl->call;
Muxi Yan68a0fd52017-07-21 09:26:04 -07001431 if (call->incoming_stream_compression_algorithm !=
Muxi Yane6d888d2017-09-14 09:42:56 -07001432 GRPC_STREAM_COMPRESS_NONE &&
Muxi Yan68ee7ce2017-09-25 12:38:35 -07001433 call->incoming_message_compression_algorithm !=
1434 GRPC_MESSAGE_COMPRESS_NONE) {
Craig Tiller4782d922017-11-10 09:53:21 -08001435 char* error_msg = nullptr;
Muxi Yane6d888d2017-09-14 09:42:56 -07001436 gpr_asprintf(&error_msg,
1437 "Incoming stream has both stream compression (%d) and message "
1438 "compression (%d).",
1439 call->incoming_stream_compression_algorithm,
1440 call->incoming_message_compression_algorithm);
1441 gpr_log(GPR_ERROR, "%s", error_msg);
Muxi Yan99024d62017-12-08 14:02:18 -08001442 cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_INTERNAL,
1443 error_msg);
Muxi Yan68a0fd52017-07-21 09:26:04 -07001444 gpr_free(error_msg);
Muxi Yane6d888d2017-09-14 09:42:56 -07001445 } else if (
1446 grpc_compression_algorithm_from_message_stream_compression_algorithm(
1447 &compression_algorithm, call->incoming_message_compression_algorithm,
1448 call->incoming_stream_compression_algorithm) == 0) {
Muxi Yan67454d72017-12-06 22:09:36 -08001449 char* error_msg = nullptr;
Muxi Yane6d888d2017-09-14 09:42:56 -07001450 gpr_asprintf(&error_msg,
1451 "Error in incoming message compression (%d) or stream "
1452 "compression (%d).",
1453 call->incoming_stream_compression_algorithm,
1454 call->incoming_message_compression_algorithm);
Muxi Yan99024d62017-12-08 14:02:18 -08001455 cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_INTERNAL,
1456 error_msg);
Muxi Yane6d888d2017-09-14 09:42:56 -07001457 gpr_free(error_msg);
1458 } else {
Craig Tiller4782d922017-11-10 09:53:21 -08001459 char* error_msg = nullptr;
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001460 const grpc_compression_options compression_options =
David Garcia Quintasac094472016-05-18 20:25:57 -07001461 grpc_channel_compression_options(call->channel);
Muxi Yane6d888d2017-09-14 09:42:56 -07001462 if (compression_algorithm >= GRPC_COMPRESS_ALGORITHMS_COUNT) {
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001463 gpr_asprintf(&error_msg, "Invalid compression algorithm value '%d'.",
Muxi Yane6d888d2017-09-14 09:42:56 -07001464 compression_algorithm);
Yuchen Zeng64c0e8d2016-06-10 11:19:51 -07001465 gpr_log(GPR_ERROR, "%s", error_msg);
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001466 cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_UNIMPLEMENTED,
1467 error_msg);
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001468 } else if (grpc_compression_options_is_algorithm_enabled(
Muxi Yane6d888d2017-09-14 09:42:56 -07001469 &compression_options, compression_algorithm) == 0) {
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001470 /* check if algorithm is supported by current channel config */
Craig Tiller4782d922017-11-10 09:53:21 -08001471 const char* algo_name = nullptr;
Muxi Yane6d888d2017-09-14 09:42:56 -07001472 grpc_compression_algorithm_name(compression_algorithm, &algo_name);
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001473 gpr_asprintf(&error_msg, "Compression algorithm '%s' is disabled.",
1474 algo_name);
Yuchen Zeng64c0e8d2016-06-10 11:19:51 -07001475 gpr_log(GPR_ERROR, "%s", error_msg);
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001476 cancel_with_status(call, STATUS_FROM_SURFACE, GRPC_STATUS_UNIMPLEMENTED,
1477 error_msg);
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001478 }
1479 gpr_free(error_msg);
David Garcia Quintasf1945f22016-05-18 10:53:14 -07001480
Muxi Yan68a0fd52017-07-21 09:26:04 -07001481 GPR_ASSERT(call->encodings_accepted_by_peer != 0);
Muxi Yane6d888d2017-09-14 09:42:56 -07001482 if (!GPR_BITGET(call->encodings_accepted_by_peer, compression_algorithm)) {
Craig Tiller6014e8a2017-10-16 13:50:29 -07001483 if (grpc_compression_trace.enabled()) {
Craig Tiller4782d922017-11-10 09:53:21 -08001484 const char* algo_name = nullptr;
Muxi Yane6d888d2017-09-14 09:42:56 -07001485 grpc_compression_algorithm_name(compression_algorithm, &algo_name);
Muxi Yan68a0fd52017-07-21 09:26:04 -07001486 gpr_log(GPR_ERROR,
Muxi Yane6d888d2017-09-14 09:42:56 -07001487 "Compression algorithm ('%s') not present in the bitset of "
1488 "accepted encodings ('0x%x')",
Muxi Yan68a0fd52017-07-21 09:26:04 -07001489 algo_name, call->encodings_accepted_by_peer);
1490 }
David Garcia Quintasf1945f22016-05-18 10:53:14 -07001491 }
1492 }
David Garcia Quintas3e71f772016-05-18 10:14:32 -07001493}
1494
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001495static void add_batch_error(batch_control* bctl, grpc_error* error,
1496 bool has_cancelled) {
Craig Tiller452422e2016-09-01 15:54:56 -07001497 if (error == GRPC_ERROR_NONE) return;
Craig Tillerb597dcf2017-03-09 07:02:11 -08001498 int idx = (int)gpr_atm_full_fetch_add(&bctl->num_errors, 1);
yang-g23f777d2017-02-22 23:32:26 -08001499 if (idx == 0 && !has_cancelled) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001500 cancel_with_error(bctl->call, STATUS_FROM_CORE, GRPC_ERROR_REF(error));
Craig Tiller2dc32ea2017-01-31 15:32:34 -08001501 }
Craig Tiller94903892016-10-11 15:43:35 -07001502 bctl->errors[idx] = error;
Craig Tiller452422e2016-09-01 15:54:56 -07001503}
1504
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001505static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001506 batch_control* bctl = (batch_control*)bctlp;
1507 grpc_call* call = bctl->call;
Craig Tillera44cbfc2016-02-03 16:02:49 -08001508
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001509 GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_initial_metadata_ready");
Mark D. Roth764cf042017-09-01 09:00:06 -07001510
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001511 add_batch_error(bctl, GRPC_ERROR_REF(error), false);
Craig Tiller452422e2016-09-01 15:54:56 -07001512 if (error == GRPC_ERROR_NONE) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001513 grpc_metadata_batch* md =
Craig Tillerc48ca712016-04-04 13:42:04 -07001514 &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001515 recv_initial_filter(call, md);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001516
Craig Tillera7d37a32016-11-22 14:37:16 -08001517 /* TODO(ctiller): this could be moved into recv_initial_filter now */
yang-gce1cfea2018-01-31 15:59:50 -08001518 GPR_TIMER_SCOPE("validate_filtered_metadata", 0);
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001519 validate_filtered_metadata(bctl);
David Garcia Quintas46123372016-05-09 15:28:42 -07001520
Craig Tiller89c14282017-07-19 15:32:27 -07001521 if (md->deadline != GRPC_MILLIS_INF_FUTURE && !call->is_client) {
1522 call->send_deadline = md->deadline;
Craig Tillerc48ca712016-04-04 13:42:04 -07001523 }
Craig Tillera44cbfc2016-02-03 16:02:49 -08001524 }
1525
Craig Tiller4782d922017-11-10 09:53:21 -08001526 grpc_closure* saved_rsr_closure = nullptr;
Yuchen Zeng0ce19a22017-08-15 14:24:00 -07001527 while (true) {
Yuchen Zeng6eb505b2017-08-25 16:05:29 -07001528 gpr_atm rsr_bctlp = gpr_atm_acq_load(&call->recv_state);
Yuchen Zeng0ce19a22017-08-15 14:24:00 -07001529 /* Should only receive initial metadata once */
1530 GPR_ASSERT(rsr_bctlp != 1);
1531 if (rsr_bctlp == 0) {
Yuchen Zenge40e2592017-08-15 15:50:49 -07001532 /* We haven't seen initial metadata and messages before, thus initial
1533 * metadata is received first.
1534 * no_barrier_cas is used, as this function won't access the batch_control
1535 * object saved by receiving_stream_ready() if the initial metadata is
1536 * received first. */
Yuchen Zeng6eb505b2017-08-25 16:05:29 -07001537 if (gpr_atm_no_barrier_cas(&call->recv_state, RECV_NONE,
1538 RECV_INITIAL_METADATA_FIRST)) {
Yuchen Zeng0ce19a22017-08-15 14:24:00 -07001539 break;
1540 }
1541 } else {
1542 /* Already received messages */
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001543 saved_rsr_closure =
1544 GRPC_CLOSURE_CREATE(receiving_stream_ready, (batch_control*)rsr_bctlp,
1545 grpc_schedule_on_exec_ctx);
Yuchen Zeng6eb505b2017-08-25 16:05:29 -07001546 /* No need to modify recv_state */
Yuchen Zeng0ce19a22017-08-15 14:24:00 -07001547 break;
1548 }
1549 }
Craig Tiller4782d922017-11-10 09:53:21 -08001550 if (saved_rsr_closure != nullptr) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001551 GRPC_CLOSURE_RUN(saved_rsr_closure, GRPC_ERROR_REF(error));
Craig Tillera44cbfc2016-02-03 16:02:49 -08001552 }
1553
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001554 finish_batch_step(bctl);
Craig Tillera44cbfc2016-02-03 16:02:49 -08001555}
1556
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001557static void finish_batch(void* bctlp, grpc_error* error) {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001558 batch_control* bctl = (batch_control*)bctlp;
1559 grpc_call* call = bctl->call;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001560 GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete");
1561 add_batch_error(bctl, GRPC_ERROR_REF(error), false);
1562 finish_batch_step(bctl);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001563}
1564
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001565static void free_no_op_completion(void* p, grpc_cq_completion* completion) {
Craig Tiller89d33792017-02-08 16:39:16 -08001566 gpr_free(completion);
1567}
1568
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001569static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001570 size_t nops, void* notify_tag,
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001571 int is_notify_tag_closure) {
yang-gce1cfea2018-01-31 15:59:50 -08001572 GPR_TIMER_SCOPE("grpc_call_start_batch", 0);
1573
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001574 size_t i;
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001575 const grpc_op* op;
1576 batch_control* bctl;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001577 int num_completion_callbacks_needed = 1;
1578 grpc_call_error error = GRPC_CALL_OK;
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001579 grpc_transport_stream_op_batch* stream_op;
1580 grpc_transport_stream_op_batch_payload* stream_op_payload;
Craig Tiller9928d392015-08-18 09:40:24 -07001581
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001582 GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
Masood Malekghassemi76c3d742015-08-19 18:22:53 -07001583
Craig Tillera82950e2015-09-22 12:33:20 -07001584 if (nops == 0) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001585 if (!is_notify_tag_closure) {
yang-g7d6b9142017-07-13 11:48:56 -07001586 GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag));
Yash Tibrewal52778c42017-09-11 15:00:11 -07001587 grpc_cq_end_op(
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001588 call->cq, notify_tag, GRPC_ERROR_NONE, free_no_op_completion, nullptr,
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001589 (grpc_cq_completion*)gpr_malloc(sizeof(grpc_cq_completion)));
Craig Tiller2db5bda2017-02-09 10:30:55 -08001590 } else {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001591 GRPC_CLOSURE_SCHED((grpc_closure*)notify_tag, GRPC_ERROR_NONE);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001592 }
Craig Tillerea50b902015-12-15 07:05:25 -08001593 error = GRPC_CALL_OK;
1594 goto done;
Craig Tillera82950e2015-09-22 12:33:20 -07001595 }
1596
Craig Tiller89d33792017-02-08 16:39:16 -08001597 bctl = allocate_batch_control(call, ops, nops);
Craig Tiller4782d922017-11-10 09:53:21 -08001598 if (bctl == nullptr) {
Craig Tiller5e5ef302017-02-09 08:46:49 -08001599 return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1600 }
Craig Tillerea54b8c2017-03-01 16:58:28 -08001601 bctl->completion_data.notify_tag.tag = notify_tag;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001602 bctl->completion_data.notify_tag.is_closure =
1603 (uint8_t)(is_notify_tag_closure != 0);
Craig Tillera82950e2015-09-22 12:33:20 -07001604
Yash Tibrewal533d1182017-09-18 10:48:22 -07001605 stream_op = &bctl->op;
1606 stream_op_payload = &call->stream_op_payload;
Craig Tillera82950e2015-09-22 12:33:20 -07001607
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001608 /* rewrite batch ops into a transport op */
1609 for (i = 0; i < nops; i++) {
1610 op = &ops[i];
Craig Tiller4782d922017-11-10 09:53:21 -08001611 if (op->reserved != nullptr) {
Craig Tiller3ffd8222015-09-21 08:21:57 -07001612 error = GRPC_CALL_ERROR;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001613 goto done_with_error;
Craig Tiller3ffd8222015-09-21 08:21:57 -07001614 }
Craig Tillera82950e2015-09-22 12:33:20 -07001615 switch (op->op) {
Yash Tibrewal533d1182017-09-18 10:48:22 -07001616 case GRPC_OP_SEND_INITIAL_METADATA: {
Craig Tillera82950e2015-09-22 12:33:20 -07001617 /* Flag validation: currently allow no flags */
Craig Tillerc6549762016-03-09 17:10:43 -08001618 if (!are_initial_metadata_flags_valid(op->flags, call->is_client)) {
Craig Tillera82950e2015-09-22 12:33:20 -07001619 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001620 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001621 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001622 if (call->sent_initial_metadata) {
1623 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1624 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001625 }
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001626 /* process compression level */
Mark D. Roth764cf042017-09-01 09:00:06 -07001627 memset(&call->compression_md, 0, sizeof(call->compression_md));
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001628 size_t additional_metadata_count = 0;
Muxi Yandf174cc2017-07-26 16:01:48 -07001629 grpc_compression_level effective_compression_level =
1630 GRPC_COMPRESS_LEVEL_NONE;
David Garcia Quintas749367f2016-05-17 19:15:24 -07001631 bool level_set = false;
Muxi Yane6d888d2017-09-14 09:42:56 -07001632 if (op->data.send_initial_metadata.maybe_compression_level.is_set) {
David Garcia Quintas749367f2016-05-17 19:15:24 -07001633 effective_compression_level =
David Garcia Quintas8ba42be2016-06-07 17:30:20 -07001634 op->data.send_initial_metadata.maybe_compression_level.level;
David Garcia Quintas749367f2016-05-17 19:15:24 -07001635 level_set = true;
1636 } else {
David Garcia Quintasac094472016-05-18 20:25:57 -07001637 const grpc_compression_options copts =
1638 grpc_channel_compression_options(call->channel);
Muxi Yane6d888d2017-09-14 09:42:56 -07001639 if (copts.default_level.is_set) {
Muxi Yan68a0fd52017-07-21 09:26:04 -07001640 level_set = true;
David Garcia Quintasac094472016-05-18 20:25:57 -07001641 effective_compression_level = copts.default_level.level;
1642 }
David Garcia Quintas749367f2016-05-17 19:15:24 -07001643 }
David Garcia Quintas3e4f49f2016-05-18 23:59:02 -07001644 if (level_set && !call->is_client) {
Muxi Yane6d888d2017-09-14 09:42:56 -07001645 const grpc_compression_algorithm calgo =
1646 compression_algorithm_for_level_locked(
1647 call, effective_compression_level);
1648 /* the following will be picked up by the compress filter and used
1649 * as the call's compression algorithm. */
1650 call->compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
1651 call->compression_md.value = grpc_compression_algorithm_slice(calgo);
1652 additional_metadata_count++;
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001653 }
1654
1655 if (op->data.send_initial_metadata.count + additional_metadata_count >
1656 INT_MAX) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001657 error = GRPC_CALL_ERROR_INVALID_METADATA;
1658 goto done_with_error;
1659 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001660 stream_op->send_initial_metadata = true;
Craig Tillerea54b8c2017-03-01 16:58:28 -08001661 call->sent_initial_metadata = true;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001662 if (!prepare_application_metadata(
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001663 call, (int)op->data.send_initial_metadata.count,
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001664 op->data.send_initial_metadata.metadata, 0, call->is_client,
Mark D. Roth764cf042017-09-01 09:00:06 -07001665 &call->compression_md, (int)additional_metadata_count)) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001666 error = GRPC_CALL_ERROR_INVALID_METADATA;
1667 goto done_with_error;
1668 }
1669 /* TODO(ctiller): just make these the same variable? */
Craig Tiller095a2202017-05-17 09:02:44 -07001670 if (call->is_client) {
1671 call->metadata_batch[0][0].deadline = call->send_deadline;
1672 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001673 stream_op_payload->send_initial_metadata.send_initial_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001674 &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */];
Craig Tiller9c1ec542017-03-02 08:42:54 -08001675 stream_op_payload->send_initial_metadata.send_initial_metadata_flags =
1676 op->flags;
Mark D. Roth764cf042017-09-01 09:00:06 -07001677 if (call->is_client) {
1678 stream_op_payload->send_initial_metadata.peer_string =
1679 &call->peer_string;
1680 }
Craig Tillera82950e2015-09-22 12:33:20 -07001681 break;
Yash Tibrewal533d1182017-09-18 10:48:22 -07001682 }
1683 case GRPC_OP_SEND_MESSAGE: {
Craig Tillera82950e2015-09-22 12:33:20 -07001684 if (!are_write_flags_valid(op->flags)) {
1685 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001686 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001687 }
Craig Tiller4782d922017-11-10 09:53:21 -08001688 if (op->data.send_message.send_message == nullptr) {
Craig Tillera82950e2015-09-22 12:33:20 -07001689 error = GRPC_CALL_ERROR_INVALID_MESSAGE;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001690 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001691 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001692 if (call->sending_message) {
1693 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1694 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001695 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001696 stream_op->send_message = true;
Craig Tillerea54b8c2017-03-01 16:58:28 -08001697 call->sending_message = true;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001698 grpc_slice_buffer_stream_init(
1699 &call->sending_stream,
Mark D. Roth448c1f02017-01-25 10:44:30 -08001700 &op->data.send_message.send_message->data.raw.slice_buffer,
1701 op->flags);
Lizan Zhou61f09732016-10-26 14:09:52 -07001702 /* If the outgoing buffer is already compressed, mark it as so in the
1703 flags. These will be picked up by the compression filter and further
1704 (wasteful) attempts at compression skipped. */
Mark D. Roth9d76dbe2017-01-25 15:02:56 -08001705 if (op->data.send_message.send_message->data.raw.compression >
1706 GRPC_COMPRESS_NONE) {
Lizan Zhou61f09732016-10-26 14:09:52 -07001707 call->sending_stream.base.flags |= GRPC_WRITE_INTERNAL_COMPRESS;
1708 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001709 stream_op_payload->send_message.send_message =
1710 &call->sending_stream.base;
Craig Tillera82950e2015-09-22 12:33:20 -07001711 break;
Yash Tibrewal533d1182017-09-18 10:48:22 -07001712 }
1713 case GRPC_OP_SEND_CLOSE_FROM_CLIENT: {
Craig Tillera82950e2015-09-22 12:33:20 -07001714 /* Flag validation: currently allow no flags */
1715 if (op->flags != 0) {
1716 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001717 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001718 }
1719 if (!call->is_client) {
1720 error = GRPC_CALL_ERROR_NOT_ON_SERVER;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001721 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001722 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001723 if (call->sent_final_op) {
1724 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1725 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001726 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001727 stream_op->send_trailing_metadata = true;
Craig Tillere198b712017-03-31 15:29:33 -07001728 call->sent_final_op = true;
Craig Tiller2d43fbf2017-03-13 16:10:05 -07001729 stream_op_payload->send_trailing_metadata.send_trailing_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001730 &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
Craig Tillera82950e2015-09-22 12:33:20 -07001731 break;
Yash Tibrewal533d1182017-09-18 10:48:22 -07001732 }
1733 case GRPC_OP_SEND_STATUS_FROM_SERVER: {
Craig Tillera82950e2015-09-22 12:33:20 -07001734 /* Flag validation: currently allow no flags */
1735 if (op->flags != 0) {
1736 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001737 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001738 }
1739 if (call->is_client) {
1740 error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001741 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001742 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001743 if (call->sent_final_op) {
1744 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1745 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001746 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001747 if (op->data.send_status_from_server.trailing_metadata_count >
1748 INT_MAX) {
1749 error = GRPC_CALL_ERROR_INVALID_METADATA;
1750 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001751 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001752 stream_op->send_trailing_metadata = true;
Craig Tillere198b712017-03-31 15:29:33 -07001753 call->sent_final_op = true;
Craig Tiller93727aa2017-02-06 13:05:39 -08001754 GPR_ASSERT(call->send_extra_metadata_count == 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001755 call->send_extra_metadata_count = 1;
1756 call->send_extra_metadata[0].md = grpc_channel_get_reffed_status_elem(
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001757 call->channel, op->data.send_status_from_server.status);
Craig Tiller841a99d2016-12-12 16:58:57 -08001758 {
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001759 grpc_error* override_error = GRPC_ERROR_NONE;
Craig Tiller841a99d2016-12-12 16:58:57 -08001760 if (op->data.send_status_from_server.status != GRPC_STATUS_OK) {
Ken Paysonb3532972018-01-11 20:25:30 -08001761 override_error =
1762 error_from_status(op->data.send_status_from_server.status,
1763 "Returned non-ok status");
Craig Tiller841a99d2016-12-12 16:58:57 -08001764 }
Craig Tiller4782d922017-11-10 09:53:21 -08001765 if (op->data.send_status_from_server.status_details != nullptr) {
Craig Tiller841a99d2016-12-12 16:58:57 -08001766 call->send_extra_metadata[1].md = grpc_mdelem_from_slices(
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001767 GRPC_MDSTR_GRPC_MESSAGE,
Craig Tiller841a99d2016-12-12 16:58:57 -08001768 grpc_slice_ref_internal(
1769 *op->data.send_status_from_server.status_details));
1770 call->send_extra_metadata_count++;
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001771 char* msg = grpc_slice_to_c_string(
Craig Tiller841a99d2016-12-12 16:58:57 -08001772 GRPC_MDVALUE(call->send_extra_metadata[1].md));
ncteisen4b36a3d2017-03-13 19:08:06 -07001773 override_error =
1774 grpc_error_set_str(override_error, GRPC_ERROR_STR_GRPC_MESSAGE,
1775 grpc_slice_from_copied_string(msg));
Craig Tiller841a99d2016-12-12 16:58:57 -08001776 gpr_free(msg);
1777 }
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001778 set_status_from_error(call, STATUS_FROM_API_OVERRIDE, override_error);
Craig Tiller69a1f662016-09-28 10:24:21 -07001779 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001780 if (!prepare_application_metadata(
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001781 call,
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001782 (int)op->data.send_status_from_server.trailing_metadata_count,
Craig Tillerbe98d242017-11-10 15:26:57 -08001783 op->data.send_status_from_server.trailing_metadata, 1, 1,
1784 nullptr, 0)) {
Craig Tiller93727aa2017-02-06 13:05:39 -08001785 for (int n = 0; n < call->send_extra_metadata_count; n++) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001786 GRPC_MDELEM_UNREF(call->send_extra_metadata[n].md);
Craig Tiller93727aa2017-02-06 13:05:39 -08001787 }
1788 call->send_extra_metadata_count = 0;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001789 error = GRPC_CALL_ERROR_INVALID_METADATA;
1790 goto done_with_error;
1791 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001792 stream_op_payload->send_trailing_metadata.send_trailing_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001793 &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
Craig Tillera82950e2015-09-22 12:33:20 -07001794 break;
Yash Tibrewal533d1182017-09-18 10:48:22 -07001795 }
1796 case GRPC_OP_RECV_INITIAL_METADATA: {
Craig Tillera82950e2015-09-22 12:33:20 -07001797 /* Flag validation: currently allow no flags */
1798 if (op->flags != 0) {
1799 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001800 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001801 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001802 if (call->received_initial_metadata) {
1803 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1804 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001805 }
Craig Tillere198b712017-03-31 15:29:33 -07001806 call->received_initial_metadata = true;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001807 call->buffered_metadata[0] =
1808 op->data.recv_initial_metadata.recv_initial_metadata;
ncteisen969b46e2017-06-08 14:57:11 -07001809 GRPC_CLOSURE_INIT(&call->receiving_initial_metadata_ready,
Craig Tiller91031da2016-12-28 15:44:25 -08001810 receiving_initial_metadata_ready, bctl,
1811 grpc_schedule_on_exec_ctx);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001812 stream_op->recv_initial_metadata = true;
1813 stream_op_payload->recv_initial_metadata.recv_initial_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001814 &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
Craig Tiller9c1ec542017-03-02 08:42:54 -08001815 stream_op_payload->recv_initial_metadata.recv_initial_metadata_ready =
Craig Tillera44cbfc2016-02-03 16:02:49 -08001816 &call->receiving_initial_metadata_ready;
Mark D. Roth764cf042017-09-01 09:00:06 -07001817 if (!call->is_client) {
1818 stream_op_payload->recv_initial_metadata.peer_string =
1819 &call->peer_string;
1820 }
Craig Tillera44cbfc2016-02-03 16:02:49 -08001821 num_completion_callbacks_needed++;
Craig Tillera82950e2015-09-22 12:33:20 -07001822 break;
Yash Tibrewal533d1182017-09-18 10:48:22 -07001823 }
1824 case GRPC_OP_RECV_MESSAGE: {
Craig Tillera82950e2015-09-22 12:33:20 -07001825 /* Flag validation: currently allow no flags */
1826 if (op->flags != 0) {
1827 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001828 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001829 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001830 if (call->receiving_message) {
1831 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
yang-g48f3a712015-12-07 11:23:50 -08001832 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001833 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001834 call->receiving_message = true;
1835 stream_op->recv_message = true;
Mark D. Roth448c1f02017-01-25 10:44:30 -08001836 call->receiving_buffer = op->data.recv_message.recv_message;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001837 stream_op_payload->recv_message.recv_message = &call->receiving_stream;
Mark D. Roth764cf042017-09-01 09:00:06 -07001838 GRPC_CLOSURE_INIT(&call->receiving_stream_ready,
1839 receiving_stream_ready_in_call_combiner, bctl,
1840 grpc_schedule_on_exec_ctx);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001841 stream_op_payload->recv_message.recv_message_ready =
1842 &call->receiving_stream_ready;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001843 num_completion_callbacks_needed++;
Craig Tillera82950e2015-09-22 12:33:20 -07001844 break;
Yash Tibrewal533d1182017-09-18 10:48:22 -07001845 }
1846 case GRPC_OP_RECV_STATUS_ON_CLIENT: {
Craig Tillera82950e2015-09-22 12:33:20 -07001847 /* Flag validation: currently allow no flags */
1848 if (op->flags != 0) {
1849 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001850 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001851 }
1852 if (!call->is_client) {
1853 error = GRPC_CALL_ERROR_NOT_ON_SERVER;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001854 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001855 }
Craig Tiller1cbf5762016-04-22 16:02:55 -07001856 if (call->requested_final_op) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001857 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1858 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001859 }
Craig Tillere198b712017-03-31 15:29:33 -07001860 call->requested_final_op = true;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001861 call->buffered_metadata[1] =
Craig Tillera82950e2015-09-22 12:33:20 -07001862 op->data.recv_status_on_client.trailing_metadata;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001863 call->final_op.client.status = op->data.recv_status_on_client.status;
1864 call->final_op.client.status_details =
1865 op->data.recv_status_on_client.status_details;
ncteisen40737d62017-11-13 08:02:35 -08001866 call->final_op.client.error_string =
1867 op->data.recv_status_on_client.error_string;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001868 stream_op->recv_trailing_metadata = true;
1869 stream_op->collect_stats = true;
1870 stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001871 &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
Craig Tiller9c1ec542017-03-02 08:42:54 -08001872 stream_op_payload->collect_stats.collect_stats =
David Garcia Quintas5dde14c2016-07-28 17:29:27 -07001873 &call->final_info.stats.transport_stream_stats;
Craig Tillera82950e2015-09-22 12:33:20 -07001874 break;
Yash Tibrewal533d1182017-09-18 10:48:22 -07001875 }
1876 case GRPC_OP_RECV_CLOSE_ON_SERVER: {
Craig Tillera82950e2015-09-22 12:33:20 -07001877 /* Flag validation: currently allow no flags */
1878 if (op->flags != 0) {
1879 error = GRPC_CALL_ERROR_INVALID_FLAGS;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001880 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001881 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001882 if (call->is_client) {
1883 error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
1884 goto done_with_error;
Craig Tillera82950e2015-09-22 12:33:20 -07001885 }
Craig Tiller1cbf5762016-04-22 16:02:55 -07001886 if (call->requested_final_op) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001887 error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
1888 goto done_with_error;
1889 }
Craig Tillere198b712017-03-31 15:29:33 -07001890 call->requested_final_op = true;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001891 call->final_op.server.cancelled =
Craig Tillera82950e2015-09-22 12:33:20 -07001892 op->data.recv_close_on_server.cancelled;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001893 stream_op->recv_trailing_metadata = true;
1894 stream_op->collect_stats = true;
1895 stream_op_payload->recv_trailing_metadata.recv_trailing_metadata =
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001896 &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
Craig Tiller9c1ec542017-03-02 08:42:54 -08001897 stream_op_payload->collect_stats.collect_stats =
David Garcia Quintas5dde14c2016-07-28 17:29:27 -07001898 &call->final_info.stats.transport_stream_stats;
Craig Tillera82950e2015-09-22 12:33:20 -07001899 break;
Yash Tibrewal533d1182017-09-18 10:48:22 -07001900 }
Craig Tillerfb189f82015-02-03 12:07:07 -08001901 }
Craig Tillera82950e2015-09-22 12:33:20 -07001902 }
Craig Tillerfb189f82015-02-03 12:07:07 -08001903
Craig Tillera82950e2015-09-22 12:33:20 -07001904 GRPC_CALL_INTERNAL_REF(call, "completion");
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001905 if (!is_notify_tag_closure) {
yang-g7d6b9142017-07-13 11:48:56 -07001906 GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag));
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001907 }
1908 gpr_ref_init(&bctl->steps_to_complete, num_completion_callbacks_needed);
Craig Tillerfb189f82015-02-03 12:07:07 -08001909
ncteisen969b46e2017-06-08 14:57:11 -07001910 GRPC_CLOSURE_INIT(&bctl->finish_batch, finish_batch, bctl,
Craig Tiller91031da2016-12-28 15:44:25 -08001911 grpc_schedule_on_exec_ctx);
Craig Tiller6e7b45e2016-07-08 17:25:49 -07001912 stream_op->on_complete = &bctl->finish_batch;
Craig Tillerb597dcf2017-03-09 07:02:11 -08001913 gpr_atm_rel_store(&call->any_ops_sent_atm, 1);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001914
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001915 execute_batch(call, stream_op, &bctl->start_batch);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001916
Craig Tiller3ffd8222015-09-21 08:21:57 -07001917done:
Craig Tiller3ffd8222015-09-21 08:21:57 -07001918 return error;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001919
1920done_with_error:
1921 /* reverse any mutations that occured */
Craig Tiller9c1ec542017-03-02 08:42:54 -08001922 if (stream_op->send_initial_metadata) {
Craig Tillere198b712017-03-31 15:29:33 -07001923 call->sent_initial_metadata = false;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001924 grpc_metadata_batch_clear(&call->metadata_batch[0][0]);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001925 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001926 if (stream_op->send_message) {
Craig Tillere198b712017-03-31 15:29:33 -07001927 call->sending_message = false;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001928 grpc_byte_stream_destroy(&call->sending_stream.base);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001929 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001930 if (stream_op->send_trailing_metadata) {
Craig Tillere198b712017-03-31 15:29:33 -07001931 call->sent_final_op = false;
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001932 grpc_metadata_batch_clear(&call->metadata_batch[0][1]);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001933 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001934 if (stream_op->recv_initial_metadata) {
Craig Tillere198b712017-03-31 15:29:33 -07001935 call->received_initial_metadata = false;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001936 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001937 if (stream_op->recv_message) {
Craig Tillere198b712017-03-31 15:29:33 -07001938 call->receiving_message = false;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001939 }
Craig Tiller9c1ec542017-03-02 08:42:54 -08001940 if (stream_op->recv_trailing_metadata) {
Craig Tillere198b712017-03-31 15:29:33 -07001941 call->requested_final_op = false;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001942 }
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001943 goto done;
1944}
1945
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001946grpc_call_error grpc_call_start_batch(grpc_call* call, const grpc_op* ops,
1947 size_t nops, void* tag, void* reserved) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001948 grpc_core::ExecCtx exec_ctx;
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001949 grpc_call_error err;
1950
1951 GRPC_API_TRACE(
David Garcia Quintas46123372016-05-09 15:28:42 -07001952 "grpc_call_start_batch(call=%p, ops=%p, nops=%lu, tag=%p, "
1953 "reserved=%p)",
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001954 5, (call, ops, (unsigned long)nops, tag, reserved));
1955
Craig Tiller4782d922017-11-10 09:53:21 -08001956 if (reserved != nullptr) {
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001957 err = GRPC_CALL_ERROR;
1958 } else {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001959 err = call_start_batch(call, ops, nops, tag, 0);
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001960 }
1961
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001962 return err;
1963}
1964
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001965grpc_call_error grpc_call_start_batch_and_execute(grpc_call* call,
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001966 const grpc_op* ops,
Craig Tillerc7e1a2a2015-11-02 14:17:32 -08001967 size_t nops,
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001968 grpc_closure* closure) {
Yash Tibrewal8cf14702017-12-06 09:47:54 -08001969 return call_start_batch(call, ops, nops, closure, 1);
Craig Tillerfb189f82015-02-03 12:07:07 -08001970}
Craig Tiller935cf422015-05-01 14:10:46 -07001971
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001972void grpc_call_context_set(grpc_call* call, grpc_context_index elem,
1973 void* value, void (*destroy)(void* value)) {
Craig Tillera82950e2015-09-22 12:33:20 -07001974 if (call->context[elem].destroy) {
1975 call->context[elem].destroy(call->context[elem].value);
1976 }
Julien Boeuf83b02972015-05-20 22:50:34 -07001977 call->context[elem].value = value;
1978 call->context[elem].destroy = destroy;
Craig Tiller935cf422015-05-01 14:10:46 -07001979}
1980
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001981void* grpc_call_context_get(grpc_call* call, grpc_context_index elem) {
Julien Boeuf83b02972015-05-20 22:50:34 -07001982 return call->context[elem].value;
Craig Tiller935cf422015-05-01 14:10:46 -07001983}
Julien Boeuf9f218dd2015-04-23 10:24:02 -07001984
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001985uint8_t grpc_call_is_client(grpc_call* call) { return call->is_client; }
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -07001986
1987grpc_compression_algorithm grpc_call_compression_for_level(
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001988 grpc_call* call, grpc_compression_level level) {
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001989 grpc_compression_algorithm algo =
1990 compression_algorithm_for_level_locked(call, level);
David Garcia Quintasa301eaa2016-05-06 16:59:03 -07001991 return algo;
David Garcia Quintas13c2f6e2016-03-17 22:51:52 -07001992}
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07001993
Muxi Yan38fcd0c2017-12-06 18:52:18 -08001994const char* grpc_call_error_to_string(grpc_call_error error) {
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07001995 switch (error) {
1996 case GRPC_CALL_ERROR:
1997 return "GRPC_CALL_ERROR";
1998 case GRPC_CALL_ERROR_ALREADY_ACCEPTED:
1999 return "GRPC_CALL_ERROR_ALREADY_ACCEPTED";
2000 case GRPC_CALL_ERROR_ALREADY_FINISHED:
2001 return "GRPC_CALL_ERROR_ALREADY_FINISHED";
2002 case GRPC_CALL_ERROR_ALREADY_INVOKED:
2003 return "GRPC_CALL_ERROR_ALREADY_INVOKED";
2004 case GRPC_CALL_ERROR_BATCH_TOO_BIG:
2005 return "GRPC_CALL_ERROR_BATCH_TOO_BIG";
2006 case GRPC_CALL_ERROR_INVALID_FLAGS:
2007 return "GRPC_CALL_ERROR_INVALID_FLAGS";
2008 case GRPC_CALL_ERROR_INVALID_MESSAGE:
2009 return "GRPC_CALL_ERROR_INVALID_MESSAGE";
2010 case GRPC_CALL_ERROR_INVALID_METADATA:
2011 return "GRPC_CALL_ERROR_INVALID_METADATA";
2012 case GRPC_CALL_ERROR_NOT_INVOKED:
2013 return "GRPC_CALL_ERROR_NOT_INVOKED";
2014 case GRPC_CALL_ERROR_NOT_ON_CLIENT:
2015 return "GRPC_CALL_ERROR_NOT_ON_CLIENT";
2016 case GRPC_CALL_ERROR_NOT_ON_SERVER:
2017 return "GRPC_CALL_ERROR_NOT_ON_SERVER";
2018 case GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE:
2019 return "GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE";
2020 case GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH:
2021 return "GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH";
2022 case GRPC_CALL_ERROR_TOO_MANY_OPERATIONS:
2023 return "GRPC_CALL_ERROR_TOO_MANY_OPERATIONS";
yang-g0eaf7de2017-07-05 16:50:51 -07002024 case GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN:
2025 return "GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN";
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07002026 case GRPC_CALL_OK:
2027 return "GRPC_CALL_OK";
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07002028 }
Yuchen Zengf02bada2016-04-19 14:12:27 -07002029 GPR_UNREACHABLE_CODE(return "GRPC_CALL_ERROR_UNKNOW");
Yuchen Zeng2e7d9572016-04-15 17:29:57 -07002030}