blob: f358eb546a9b0550b5483b7a01aa13e2fbe2fa3b [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include "src/core/surface/call.h"
35#include "src/core/channel/channel_stack.h"
ctiller18b49ab2014-12-09 14:39:16 -080036#include "src/core/iomgr/alarm.h"
Craig Tiller485d7762015-01-23 12:54:05 -080037#include "src/core/support/string.h"
Craig Tiller1e0d4c42015-01-30 16:17:29 -080038#include "src/core/surface/byte_buffer_queue.h"
ctiller18b49ab2014-12-09 14:39:16 -080039#include "src/core/surface/channel.h"
40#include "src/core/surface/completion_queue.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080041#include <grpc/support/alloc.h>
42#include <grpc/support/log.h>
Craig Tiller6902ad22015-04-16 08:01:49 -070043#include <assert.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080044
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48
Craig Tiller566316f2015-02-02 15:25:32 -080049typedef struct legacy_state legacy_state;
50static void destroy_legacy_state(legacy_state *ls);
Craig Tillercce17ac2015-01-20 09:29:28 -080051
Craig Tiller8eb9d472015-01-27 17:00:03 -080052typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state;
53
54typedef enum {
55 SEND_NOTHING,
56 SEND_INITIAL_METADATA,
Craig Tiller7bd9b992015-02-04 08:38:02 -080057 SEND_BUFFERED_INITIAL_METADATA,
Craig Tiller8eb9d472015-01-27 17:00:03 -080058 SEND_MESSAGE,
Craig Tiller7bd9b992015-02-04 08:38:02 -080059 SEND_BUFFERED_MESSAGE,
Craig Tiller1c141902015-01-31 08:51:54 -080060 SEND_TRAILING_METADATA_AND_FINISH,
Craig Tiller8eb9d472015-01-27 17:00:03 -080061 SEND_FINISH
62} send_action;
63
64typedef struct {
65 grpc_ioreq_completion_func on_complete;
66 void *user_data;
67 grpc_op_error status;
68} completed_request;
69
Craig Tillerc12fee62015-02-03 11:55:50 -080070/* See request_set in grpc_call below for a description */
Craig Tiller6902ad22015-04-16 08:01:49 -070071#define REQSET_EMPTY 'X'
72#define REQSET_DONE 'Y'
73
74#define MAX_SEND_INITIAL_METADATA_COUNT 3
Craig Tiller1e0d4c42015-01-30 16:17:29 -080075
Craig Tillerc18c56e2015-02-02 15:59:13 -080076typedef struct {
Craig Tillerdaceea82015-02-02 16:15:53 -080077 /* Overall status of the operation: starts OK, may degrade to
78 non-OK */
Craig Tiller1e0d4c42015-01-30 16:17:29 -080079 grpc_op_error status;
Craig Tillerdaceea82015-02-02 16:15:53 -080080 /* Completion function to call at the end of the operation */
Craig Tillercce17ac2015-01-20 09:29:28 -080081 grpc_ioreq_completion_func on_complete;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080082 void *user_data;
Craig Tillerd642dcf2015-02-03 20:39:09 -080083 /* a bit mask of which request ops are needed (1u << opid) */
Craig Tiller58ce3f02015-04-22 07:54:24 -070084 gpr_uint16 need_mask;
Craig Tillerdaceea82015-02-02 16:15:53 -080085 /* a bit mask of which request ops are now completed */
Craig Tiller58ce3f02015-04-22 07:54:24 -070086 gpr_uint16 complete_mask;
Craig Tillerc18c56e2015-02-02 15:59:13 -080087} reqinfo_master;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080088
Craig Tillerdaceea82015-02-02 16:15:53 -080089/* Status data for a request can come from several sources; this
90 enumerates them all, and acts as a priority sorting for which
91 status to return to the application - earlier entries override
92 later ones */
Craig Tiller68752722015-01-29 14:59:54 -080093typedef enum {
Craig Tillerdaceea82015-02-02 16:15:53 -080094 /* Status came from the application layer overriding whatever
95 the wire says */
Craig Tiller68752722015-01-29 14:59:54 -080096 STATUS_FROM_API_OVERRIDE = 0,
Craig Tiller8b282cb2015-04-17 14:57:44 -070097 /* Status was created by some internal channel stack operation */
98 STATUS_FROM_CORE,
Craig Tillerdaceea82015-02-02 16:15:53 -080099 /* Status came from 'the wire' - or somewhere below the surface
100 layer */
Craig Tiller68752722015-01-29 14:59:54 -0800101 STATUS_FROM_WIRE,
Craig Tiller68752722015-01-29 14:59:54 -0800102 STATUS_SOURCE_COUNT
103} status_source;
104
105typedef struct {
Craig Tillerdaceea82015-02-02 16:15:53 -0800106 gpr_uint8 is_set;
Craig Tiller68752722015-01-29 14:59:54 -0800107 grpc_status_code code;
108 grpc_mdstr *details;
109} received_status;
110
Craig Tillerdaceea82015-02-02 16:15:53 -0800111/* How far through the GRPC stream have we read? */
112typedef enum {
113 /* We are still waiting for initial metadata to complete */
Craig Tillerc12fee62015-02-03 11:55:50 -0800114 READ_STATE_INITIAL = 0,
Craig Tillerdaceea82015-02-02 16:15:53 -0800115 /* We have gotten initial metadata, and are reading either
116 messages or trailing metadata */
117 READ_STATE_GOT_INITIAL_METADATA,
118 /* The stream is closed for reading */
119 READ_STATE_READ_CLOSED,
120 /* The stream is closed for reading & writing */
121 READ_STATE_STREAM_CLOSED
122} read_state;
123
Craig Tillerc12fee62015-02-03 11:55:50 -0800124typedef enum {
125 WRITE_STATE_INITIAL = 0,
126 WRITE_STATE_STARTED,
127 WRITE_STATE_WRITE_CLOSED
128} write_state;
129
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800130struct grpc_call {
131 grpc_completion_queue *cq;
132 grpc_channel *channel;
133 grpc_mdctx *metadata_context;
Craig Tillercce17ac2015-01-20 09:29:28 -0800134 /* TODO(ctiller): share with cq if possible? */
135 gpr_mu mu;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800136
Craig Tillere5d683c2015-02-03 16:37:36 -0800137 /* how far through the stream have we read? */
Craig Tillerdaceea82015-02-02 16:15:53 -0800138 read_state read_state;
Craig Tillere5d683c2015-02-03 16:37:36 -0800139 /* how far through the stream have we written? */
Craig Tillerc12fee62015-02-03 11:55:50 -0800140 write_state write_state;
Craig Tillere5d683c2015-02-03 16:37:36 -0800141 /* client or server call */
142 gpr_uint8 is_client;
143 /* is the alarm set */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800144 gpr_uint8 have_alarm;
Craig Tillere5d683c2015-02-03 16:37:36 -0800145 /* are we currently performing a send operation */
Craig Tiller8eb9d472015-01-27 17:00:03 -0800146 gpr_uint8 sending;
Craig Tiller629b0ed2015-04-22 11:14:26 -0700147 /* are we currently performing a recv operation */
148 gpr_uint8 receiving;
Craig Tiller991ca9f2015-03-03 09:59:22 -0800149 /* are we currently completing requests */
150 gpr_uint8 completing;
Craig Tillere5d683c2015-02-03 16:37:36 -0800151 /* pairs with completed_requests */
Craig Tiller8eb9d472015-01-27 17:00:03 -0800152 gpr_uint8 num_completed_requests;
Craig Tiller629b0ed2015-04-22 11:14:26 -0700153 /* are we currently reading a message? */
154 gpr_uint8 reading_message;
Craig Tiller83f88d92015-04-21 16:02:05 -0700155 /* flags with bits corresponding to write states allowing us to determine
156 what was sent */
Craig Tiller58ce3f02015-04-22 07:54:24 -0700157 gpr_uint16 last_send_contains;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800158
Craig Tillere5d683c2015-02-03 16:37:36 -0800159 /* Active ioreqs.
160 request_set and request_data contain one element per active ioreq
161 operation.
Craig Tillerebf94bf2015-02-05 08:48:46 -0800162
Craig Tillere5d683c2015-02-03 16:37:36 -0800163 request_set[op] is an integer specifying a set of operations to which
164 the request belongs:
Craig Tillerebf94bf2015-02-05 08:48:46 -0800165 - if it is < GRPC_IOREQ_OP_COUNT, then this operation is pending
Craig Tillere5d683c2015-02-03 16:37:36 -0800166 completion, and the integer represents to which group of operations
167 the ioreq belongs. Each group is represented by one master, and the
168 integer in request_set is an index into masters to find the master
169 data.
170 - if it is REQSET_EMPTY, the ioreq op is inactive and available to be
171 started
172 - finally, if request_set[op] is REQSET_DONE, then the operation is
173 complete and unavailable to be started again
Craig Tillerebf94bf2015-02-05 08:48:46 -0800174
Craig Tillere5d683c2015-02-03 16:37:36 -0800175 request_data[op] is the request data as supplied by the initiator of
176 a request, and is valid iff request_set[op] <= GRPC_IOREQ_OP_COUNT.
177 The set fields are as per the request type specified by op.
178
Craig Tillerd6731622015-02-03 22:44:13 -0800179 Finally, one element of masters is set per active _set_ of ioreq
Craig Tillere5d683c2015-02-03 16:37:36 -0800180 operations. It describes work left outstanding, result status, and
181 what work to perform upon operation completion. As one ioreq of each
182 op type can be active at once, by convention we choose the first element
Craig Tillerd6731622015-02-03 22:44:13 -0800183 of the group to be the master -- ie the master of in-progress operation
184 op is masters[request_set[op]]. This allows constant time allocation
Craig Tillere5d683c2015-02-03 16:37:36 -0800185 and a strong upper bound of a count of masters to be calculated. */
Craig Tillerc12fee62015-02-03 11:55:50 -0800186 gpr_uint8 request_set[GRPC_IOREQ_OP_COUNT];
187 grpc_ioreq_data request_data[GRPC_IOREQ_OP_COUNT];
Craig Tillerc18c56e2015-02-02 15:59:13 -0800188 reqinfo_master masters[GRPC_IOREQ_OP_COUNT];
Craig Tillere5d683c2015-02-03 16:37:36 -0800189
190 /* Dynamic array of ioreq's that have completed: the count of
191 elements is queued in num_completed_requests.
192 This list is built up under lock(), and flushed entirely during
193 unlock().
194 We know the upper bound of the number of elements as we can only
195 have one ioreq of each type active at once. */
Craig Tiller8eb9d472015-01-27 17:00:03 -0800196 completed_request completed_requests[GRPC_IOREQ_OP_COUNT];
Craig Tillere5d683c2015-02-03 16:37:36 -0800197 /* Incoming buffer of messages */
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800198 grpc_byte_buffer_queue incoming_queue;
Craig Tillere5d683c2015-02-03 16:37:36 -0800199 /* Buffered read metadata waiting to be returned to the application.
200 Element 0 is initial metadata, element 1 is trailing metadata. */
Craig Tillerc12fee62015-02-03 11:55:50 -0800201 grpc_metadata_array buffered_metadata[2];
Craig Tillere5d683c2015-02-03 16:37:36 -0800202 /* All metadata received - unreffed at once at the end of the call */
Craig Tiller3a4749f2015-01-30 07:51:45 -0800203 grpc_mdelem **owned_metadata;
204 size_t owned_metadata_count;
205 size_t owned_metadata_capacity;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800206
Craig Tillere5d683c2015-02-03 16:37:36 -0800207 /* Received call statuses from various sources */
Craig Tiller68752722015-01-29 14:59:54 -0800208 received_status status[STATUS_SOURCE_COUNT];
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800209
Craig Tillere5d683c2015-02-03 16:37:36 -0800210 /* Deadline alarm - if have_alarm is non-zero */
Craig Tillercce17ac2015-01-20 09:29:28 -0800211 grpc_alarm alarm;
212
Craig Tillere5d683c2015-02-03 16:37:36 -0800213 /* Call refcount - to keep the call alive during asynchronous operations */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800214 gpr_refcount internal_refcount;
Craig Tillercce17ac2015-01-20 09:29:28 -0800215
Craig Tiller6902ad22015-04-16 08:01:49 -0700216 grpc_linked_mdelem send_initial_metadata[MAX_SEND_INITIAL_METADATA_COUNT];
217 grpc_linked_mdelem status_link;
218 grpc_linked_mdelem details_link;
219 size_t send_initial_metadata_count;
220 gpr_timespec send_deadline;
221
Craig Tiller83f88d92015-04-21 16:02:05 -0700222 grpc_stream_op_buffer send_ops;
223 grpc_stream_op_buffer recv_ops;
224 grpc_stream_state recv_state;
225
Craig Tiller629b0ed2015-04-22 11:14:26 -0700226 gpr_slice_buffer incoming_message;
227 gpr_uint32 incoming_message_length;
228
Craig Tillerebf94bf2015-02-05 08:48:46 -0800229 /* Data that the legacy api needs to track. To be deleted at some point
Craig Tillere5d683c2015-02-03 16:37:36 -0800230 soon */
Craig Tillercce17ac2015-01-20 09:29:28 -0800231 legacy_state *legacy_state;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800232};
233
Craig Tiller87d5b192015-04-16 14:37:57 -0700234#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800235#define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1)
236#define CALL_ELEM_FROM_CALL(call, idx) \
237 grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx)
238#define CALL_FROM_TOP_ELEM(top_elem) \
239 CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem))
240
Craig Tillercce17ac2015-01-20 09:29:28 -0800241#define SWAP(type, x, y) \
242 do { \
243 type temp = x; \
244 x = y; \
245 y = temp; \
246 } while (0)
247
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800248static void do_nothing(void *ignored, grpc_op_error also_ignored) {}
Craig Tiller6902ad22015-04-16 08:01:49 -0700249static void set_deadline_alarm(grpc_call *call, gpr_timespec deadline);
Craig Tiller83f88d92015-04-21 16:02:05 -0700250static void call_on_done_recv(void *call, int success);
251static void call_on_done_send(void *call, int success);
252static int fill_send_ops(grpc_call *call, grpc_transport_op *op);
253static void execute_op(grpc_call *call, grpc_transport_op *op);
Craig Tiller629b0ed2015-04-22 11:14:26 -0700254static void recv_metadata(grpc_call *call, grpc_metadata_batch *metadata);
255static void finish_read_ops(grpc_call *call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800256
Craig Tillerfb189f82015-02-03 12:07:07 -0800257grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
Craig Tiller87d5b192015-04-16 14:37:57 -0700258 const void *server_transport_data,
259 grpc_mdelem **add_initial_metadata,
260 size_t add_initial_metadata_count,
261 gpr_timespec send_deadline) {
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800262 size_t i;
Craig Tiller7e8489a2015-04-23 12:41:16 -0700263 grpc_transport_op initial_op;
264 grpc_transport_op *initial_op_ptr = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800265 grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel);
266 grpc_call *call =
267 gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size);
Craig Tillercce17ac2015-01-20 09:29:28 -0800268 memset(call, 0, sizeof(grpc_call));
269 gpr_mu_init(&call->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800270 call->channel = channel;
Craig Tillerfb189f82015-02-03 12:07:07 -0800271 call->cq = cq;
Craig Tillercce17ac2015-01-20 09:29:28 -0800272 call->is_client = server_transport_data == NULL;
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800273 for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) {
Craig Tillerc12fee62015-02-03 11:55:50 -0800274 call->request_set[i] = REQSET_EMPTY;
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800275 }
Craig Tiller23aa6c42015-01-27 17:16:12 -0800276 if (call->is_client) {
Craig Tillerc12fee62015-02-03 11:55:50 -0800277 call->request_set[GRPC_IOREQ_SEND_TRAILING_METADATA] = REQSET_DONE;
278 call->request_set[GRPC_IOREQ_SEND_STATUS] = REQSET_DONE;
Craig Tiller23aa6c42015-01-27 17:16:12 -0800279 }
Craig Tiller6902ad22015-04-16 08:01:49 -0700280 GPR_ASSERT(add_initial_metadata_count < MAX_SEND_INITIAL_METADATA_COUNT);
281 for (i = 0; i < add_initial_metadata_count; i++) {
282 call->send_initial_metadata[i].md = add_initial_metadata[i];
283 }
284 call->send_initial_metadata_count = add_initial_metadata_count;
285 call->send_deadline = send_deadline;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800286 grpc_channel_internal_ref(channel);
287 call->metadata_context = grpc_channel_get_metadata_context(channel);
Craig Tillerfbf5be22015-04-22 16:17:09 -0700288 grpc_sopb_init(&call->send_ops);
289 grpc_sopb_init(&call->recv_ops);
Craig Tillerfa4f9942015-04-23 15:22:09 -0700290 gpr_slice_buffer_init(&call->incoming_message);
Craig Tiller9c71b6f2015-04-24 16:02:00 -0700291 /* dropped in destroy */
292 gpr_ref_init(&call->internal_refcount, 1);
Craig Tiller7e8489a2015-04-23 12:41:16 -0700293 /* server hack: start reads immediately so we can get initial metadata.
294 TODO(ctiller): figure out a cleaner solution */
295 if (!call->is_client) {
296 memset(&initial_op, 0, sizeof(initial_op));
297 initial_op.recv_ops = &call->recv_ops;
298 initial_op.recv_state = &call->recv_state;
299 initial_op.on_done_recv = call_on_done_recv;
300 initial_op.recv_user_data = call;
301 call->receiving = 1;
Craig Tiller4df412b2015-04-28 07:57:54 -0700302 GRPC_CALL_INTERNAL_REF(call, "receiving");
Craig Tiller7e8489a2015-04-23 12:41:16 -0700303 initial_op_ptr = &initial_op;
304 }
305 grpc_call_stack_init(channel_stack, server_transport_data, initial_op_ptr,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800306 CALL_STACK_FROM_CALL(call));
Craig Tiller6902ad22015-04-16 08:01:49 -0700307 if (gpr_time_cmp(send_deadline, gpr_inf_future) != 0) {
308 set_deadline_alarm(call, send_deadline);
309 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800310 return call;
311}
312
Craig Tiller166e2502015-02-03 20:14:41 -0800313void grpc_call_set_completion_queue(grpc_call *call,
314 grpc_completion_queue *cq) {
315 call->cq = cq;
316}
317
Craig Tiller24be0f72015-02-10 14:04:22 -0800318grpc_completion_queue *grpc_call_get_completion_queue(grpc_call *call) {
319 return call->cq;
320}
321
Craig Tiller4df412b2015-04-28 07:57:54 -0700322#ifdef GRPC_CALL_REF_COUNT_DEBUG
323void grpc_call_internal_ref(grpc_call *c, const char *reason) {
324 gpr_log(GPR_DEBUG, "CALL: ref %p %d -> %d [%s]", c,
325 c->internal_refcount.count, c->internal_refcount.count + 1, reason);
326#else
327void grpc_call_internal_ref(grpc_call *c) {
328#endif
329 gpr_ref(&c->internal_refcount);
330}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800331
Craig Tilleraef25da2015-01-29 17:19:45 -0800332static void destroy_call(void *call, int ignored_success) {
Craig Tiller566316f2015-02-02 15:25:32 -0800333 size_t i;
Craig Tilleraef25da2015-01-29 17:19:45 -0800334 grpc_call *c = call;
Craig Tillera4541102015-01-29 11:46:11 -0800335 grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c));
336 grpc_channel_internal_unref(c->channel);
337 gpr_mu_destroy(&c->mu);
Craig Tiller68752722015-01-29 14:59:54 -0800338 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
339 if (c->status[i].details) {
340 grpc_mdstr_unref(c->status[i].details);
341 }
Craig Tillera4541102015-01-29 11:46:11 -0800342 }
Craig Tiller3a4749f2015-01-30 07:51:45 -0800343 for (i = 0; i < c->owned_metadata_count; i++) {
344 grpc_mdelem_unref(c->owned_metadata[i]);
345 }
346 gpr_free(c->owned_metadata);
Craig Tillerc12fee62015-02-03 11:55:50 -0800347 for (i = 0; i < GPR_ARRAY_SIZE(c->buffered_metadata); i++) {
348 gpr_free(c->buffered_metadata[i].metadata);
349 }
Craig Tillereb40a532015-04-17 16:46:20 -0700350 for (i = 0; i < c->send_initial_metadata_count; i++) {
351 grpc_mdelem_unref(c->send_initial_metadata[i].md);
352 }
Craig Tillerb56ca8d2015-04-24 17:16:22 -0700353 grpc_sopb_destroy(&c->send_ops);
354 grpc_sopb_destroy(&c->recv_ops);
Craig Tillera4541102015-01-29 11:46:11 -0800355 if (c->legacy_state) {
Craig Tiller566316f2015-02-02 15:25:32 -0800356 destroy_legacy_state(c->legacy_state);
Craig Tillera4541102015-01-29 11:46:11 -0800357 }
Craig Tiller37bbead2015-02-05 08:43:49 -0800358 grpc_bbq_destroy(&c->incoming_queue);
Craig Tillerfa4f9942015-04-23 15:22:09 -0700359 gpr_slice_buffer_destroy(&c->incoming_message);
Craig Tillera4541102015-01-29 11:46:11 -0800360 gpr_free(c);
361}
362
Craig Tiller4df412b2015-04-28 07:57:54 -0700363#ifdef GRPC_CALL_REF_COUNT_DEBUG
364void grpc_call_internal_unref(grpc_call *c, const char *reason,
365 int allow_immediate_deletion) {
366 gpr_log(GPR_DEBUG, "CALL: unref %p %d -> %d [%s]", c,
367 c->internal_refcount.count, c->internal_refcount.count - 1, reason);
368#else
Craig Tiller64bc3fd2015-04-24 17:07:12 -0700369void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) {
Craig Tiller4df412b2015-04-28 07:57:54 -0700370#endif
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800371 if (gpr_unref(&c->internal_refcount)) {
Craig Tilleraef25da2015-01-29 17:19:45 -0800372 if (allow_immediate_deletion) {
373 destroy_call(c, 1);
374 } else {
375 grpc_iomgr_add_callback(destroy_call, c);
376 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800377 }
378}
379
Craig Tiller928fbc82015-01-29 15:06:42 -0800380static void set_status_code(grpc_call *call, status_source source,
381 gpr_uint32 status) {
Craig Tiller8b976d02015-02-05 21:41:23 -0800382 int flush;
383
Craig Tillerdaceea82015-02-02 16:15:53 -0800384 call->status[source].is_set = 1;
Craig Tiller68752722015-01-29 14:59:54 -0800385 call->status[source].code = status;
Craig Tiller30547562015-02-05 17:04:51 -0800386
Craig Tiller8b976d02015-02-05 21:41:23 -0800387 if (call->is_client) {
388 flush = status == GRPC_STATUS_CANCELLED;
389 } else {
390 flush = status != GRPC_STATUS_OK;
391 }
392
393 if (flush && !grpc_bbq_empty(&call->incoming_queue)) {
Craig Tiller30547562015-02-05 17:04:51 -0800394 grpc_bbq_flush(&call->incoming_queue);
395 }
Craig Tiller68752722015-01-29 14:59:54 -0800396}
397
Craig Tiller928fbc82015-01-29 15:06:42 -0800398static void set_status_details(grpc_call *call, status_source source,
399 grpc_mdstr *status) {
Craig Tiller68752722015-01-29 14:59:54 -0800400 if (call->status[source].details != NULL) {
401 grpc_mdstr_unref(call->status[source].details);
402 }
403 call->status[source].details = status;
404}
405
Craig Tillercce17ac2015-01-20 09:29:28 -0800406static grpc_call_error bind_cq(grpc_call *call, grpc_completion_queue *cq) {
407 if (call->cq) return GRPC_CALL_ERROR_ALREADY_INVOKED;
408 call->cq = cq;
409 return GRPC_CALL_OK;
410}
411
Craig Tillerc12fee62015-02-03 11:55:50 -0800412static int is_op_live(grpc_call *call, grpc_ioreq_op op) {
413 gpr_uint8 set = call->request_set[op];
414 reqinfo_master *master;
415 if (set >= GRPC_IOREQ_OP_COUNT) return 0;
416 master = &call->masters[set];
Craig Tillerd642dcf2015-02-03 20:39:09 -0800417 return (master->complete_mask & (1u << op)) == 0;
Craig Tillerc12fee62015-02-03 11:55:50 -0800418}
419
Craig Tiller8eb9d472015-01-27 17:00:03 -0800420static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); }
Craig Tillercce17ac2015-01-20 09:29:28 -0800421
Craig Tiller629b0ed2015-04-22 11:14:26 -0700422static int need_more_data(grpc_call *call) {
423 return is_op_live(call, GRPC_IOREQ_RECV_INITIAL_METADATA) ||
Craig Tiller10b9cb52015-04-28 10:00:15 -0700424 (is_op_live(call, GRPC_IOREQ_RECV_MESSAGE) && grpc_bbq_empty(&call->incoming_queue)) ||
Craig Tiller629b0ed2015-04-22 11:14:26 -0700425 is_op_live(call, GRPC_IOREQ_RECV_TRAILING_METADATA) ||
426 is_op_live(call, GRPC_IOREQ_RECV_STATUS) ||
427 is_op_live(call, GRPC_IOREQ_RECV_STATUS_DETAILS) ||
Craig Tiller4df412b2015-04-28 07:57:54 -0700428 (is_op_live(call, GRPC_IOREQ_RECV_CLOSE) &&
429 grpc_bbq_empty(&call->incoming_queue)) ||
430 (call->write_state == WRITE_STATE_INITIAL && !call->is_client &&
Craig Tiller10b9cb52015-04-28 10:00:15 -0700431 call->read_state < READ_STATE_GOT_INITIAL_METADATA);
Craig Tiller629b0ed2015-04-22 11:14:26 -0700432}
433
Craig Tiller8eb9d472015-01-27 17:00:03 -0800434static void unlock(grpc_call *call) {
Craig Tiller83f88d92015-04-21 16:02:05 -0700435 grpc_transport_op op;
Craig Tiller8eb9d472015-01-27 17:00:03 -0800436 completed_request completed_requests[GRPC_IOREQ_OP_COUNT];
Craig Tiller991ca9f2015-03-03 09:59:22 -0800437 int completing_requests = 0;
Craig Tiller83f88d92015-04-21 16:02:05 -0700438 int start_op = 0;
Craig Tiller8eb9d472015-01-27 17:00:03 -0800439 int i;
440
Craig Tiller83f88d92015-04-21 16:02:05 -0700441 memset(&op, 0, sizeof(op));
442
Craig Tiller1a727fd2015-04-24 13:21:22 -0700443 if (!call->receiving && need_more_data(call)) {
Craig Tiller83f88d92015-04-21 16:02:05 -0700444 op.recv_ops = &call->recv_ops;
445 op.recv_state = &call->recv_state;
446 op.on_done_recv = call_on_done_recv;
447 op.recv_user_data = call;
Craig Tiller629b0ed2015-04-22 11:14:26 -0700448 call->receiving = 1;
Craig Tiller4df412b2015-04-28 07:57:54 -0700449 GRPC_CALL_INTERNAL_REF(call, "receiving");
Craig Tiller83f88d92015-04-21 16:02:05 -0700450 start_op = 1;
451 }
452
453 if (!call->sending) {
454 if (fill_send_ops(call, &op)) {
455 call->sending = 1;
Craig Tiller4df412b2015-04-28 07:57:54 -0700456 GRPC_CALL_INTERNAL_REF(call, "sending");
Craig Tiller83f88d92015-04-21 16:02:05 -0700457 start_op = 1;
458 }
Craig Tillercffbcb72015-01-29 23:16:33 -0800459 }
Craig Tiller2e103572015-01-29 14:12:07 -0800460
Craig Tiller991ca9f2015-03-03 09:59:22 -0800461 if (!call->completing && call->num_completed_requests != 0) {
462 completing_requests = call->num_completed_requests;
Craig Tiller8eb9d472015-01-27 17:00:03 -0800463 memcpy(completed_requests, call->completed_requests,
464 sizeof(completed_requests));
465 call->num_completed_requests = 0;
Craig Tiller991ca9f2015-03-03 09:59:22 -0800466 call->completing = 1;
Craig Tiller4df412b2015-04-28 07:57:54 -0700467 GRPC_CALL_INTERNAL_REF(call, "completing");
Craig Tiller8eb9d472015-01-27 17:00:03 -0800468 }
469
Craig Tiller8eb9d472015-01-27 17:00:03 -0800470 gpr_mu_unlock(&call->mu);
471
Craig Tiller83f88d92015-04-21 16:02:05 -0700472 if (start_op) {
473 execute_op(call, &op);
Craig Tiller8eb9d472015-01-27 17:00:03 -0800474 }
475
Craig Tiller991ca9f2015-03-03 09:59:22 -0800476 if (completing_requests > 0) {
477 for (i = 0; i < completing_requests; i++) {
478 completed_requests[i].on_complete(call, completed_requests[i].status,
479 completed_requests[i].user_data);
480 }
481 lock(call);
482 call->completing = 0;
483 unlock(call);
Craig Tiller4df412b2015-04-28 07:57:54 -0700484 GRPC_CALL_INTERNAL_UNREF(call, "completing", 0);
Craig Tiller8eb9d472015-01-27 17:00:03 -0800485 }
486}
Craig Tillercce17ac2015-01-20 09:29:28 -0800487
Craig Tillerfb189f82015-02-03 12:07:07 -0800488static void get_final_status(grpc_call *call, grpc_ioreq_data out) {
Craig Tiller68752722015-01-29 14:59:54 -0800489 int i;
490 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
Craig Tillerdaceea82015-02-02 16:15:53 -0800491 if (call->status[i].is_set) {
Craig Tillerfb189f82015-02-03 12:07:07 -0800492 out.recv_status.set_value(call->status[i].code,
493 out.recv_status.user_data);
494 return;
495 }
496 }
Craig Tillerde343162015-02-09 23:37:22 -0800497 if (call->is_client) {
498 out.recv_status.set_value(GRPC_STATUS_UNKNOWN, out.recv_status.user_data);
499 } else {
500 out.recv_status.set_value(GRPC_STATUS_OK, out.recv_status.user_data);
501 }
Craig Tillerfb189f82015-02-03 12:07:07 -0800502}
503
504static void get_final_details(grpc_call *call, grpc_ioreq_data out) {
505 int i;
506 for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
507 if (call->status[i].is_set) {
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800508 if (call->status[i].details) {
509 gpr_slice details = call->status[i].details->slice;
510 size_t len = GPR_SLICE_LENGTH(details);
Craig Tillerfb189f82015-02-03 12:07:07 -0800511 if (len + 1 > *out.recv_status_details.details_capacity) {
512 *out.recv_status_details.details_capacity = GPR_MAX(
513 len + 1, *out.recv_status_details.details_capacity * 3 / 2);
514 *out.recv_status_details.details =
515 gpr_realloc(*out.recv_status_details.details,
516 *out.recv_status_details.details_capacity);
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800517 }
Craig Tillerfb189f82015-02-03 12:07:07 -0800518 memcpy(*out.recv_status_details.details, GPR_SLICE_START_PTR(details),
519 len);
520 (*out.recv_status_details.details)[len] = 0;
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800521 } else {
522 goto no_details;
523 }
Craig Tiller68752722015-01-29 14:59:54 -0800524 return;
525 }
526 }
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800527
528no_details:
Craig Tillerfb189f82015-02-03 12:07:07 -0800529 if (0 == *out.recv_status_details.details_capacity) {
530 *out.recv_status_details.details_capacity = 8;
531 *out.recv_status_details.details =
532 gpr_malloc(*out.recv_status_details.details_capacity);
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800533 }
Craig Tillerfb189f82015-02-03 12:07:07 -0800534 **out.recv_status_details.details = 0;
Craig Tiller68752722015-01-29 14:59:54 -0800535}
536
Craig Tillerc12fee62015-02-03 11:55:50 -0800537static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
538 grpc_op_error status) {
539 completed_request *cr;
540 gpr_uint8 master_set = call->request_set[op];
541 reqinfo_master *master;
542 size_t i;
543 /* ioreq is live: we need to do something */
544 master = &call->masters[master_set];
Craig Tillerd642dcf2015-02-03 20:39:09 -0800545 master->complete_mask |= 1u << op;
Craig Tillerc12fee62015-02-03 11:55:50 -0800546 if (status != GRPC_OP_OK) {
547 master->status = status;
Craig Tillerc12fee62015-02-03 11:55:50 -0800548 }
549 if (master->complete_mask == master->need_mask) {
550 for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) {
551 if (call->request_set[i] != master_set) {
552 continue;
553 }
554 call->request_set[i] = REQSET_DONE;
555 switch ((grpc_ioreq_op)i) {
556 case GRPC_IOREQ_RECV_MESSAGE:
557 case GRPC_IOREQ_SEND_MESSAGE:
558 if (master->status == GRPC_OP_OK) {
559 call->request_set[i] = REQSET_EMPTY;
560 } else {
561 call->write_state = WRITE_STATE_WRITE_CLOSED;
562 }
563 break;
564 case GRPC_IOREQ_RECV_CLOSE:
565 case GRPC_IOREQ_SEND_INITIAL_METADATA:
566 case GRPC_IOREQ_SEND_TRAILING_METADATA:
567 case GRPC_IOREQ_SEND_STATUS:
568 case GRPC_IOREQ_SEND_CLOSE:
569 break;
570 case GRPC_IOREQ_RECV_STATUS:
Craig Tillerfb189f82015-02-03 12:07:07 -0800571 get_final_status(call, call->request_data[GRPC_IOREQ_RECV_STATUS]);
572 break;
573 case GRPC_IOREQ_RECV_STATUS_DETAILS:
574 get_final_details(call,
575 call->request_data[GRPC_IOREQ_RECV_STATUS_DETAILS]);
Craig Tillerc12fee62015-02-03 11:55:50 -0800576 break;
577 case GRPC_IOREQ_RECV_INITIAL_METADATA:
578 SWAP(grpc_metadata_array, call->buffered_metadata[0],
579 *call->request_data[GRPC_IOREQ_RECV_INITIAL_METADATA]
580 .recv_metadata);
581 break;
582 case GRPC_IOREQ_RECV_TRAILING_METADATA:
583 SWAP(grpc_metadata_array, call->buffered_metadata[1],
584 *call->request_data[GRPC_IOREQ_RECV_TRAILING_METADATA]
585 .recv_metadata);
586 break;
587 case GRPC_IOREQ_OP_COUNT:
588 abort();
589 break;
590 }
591 }
592 cr = &call->completed_requests[call->num_completed_requests++];
593 cr->status = master->status;
594 cr->on_complete = master->on_complete;
595 cr->user_data = master->user_data;
596 }
597}
598
Craig Tillercce17ac2015-01-20 09:29:28 -0800599static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op,
600 grpc_op_error status) {
Craig Tillerc12fee62015-02-03 11:55:50 -0800601 if (is_op_live(call, op)) {
602 finish_live_ioreq_op(call, op, status);
Craig Tillercce17ac2015-01-20 09:29:28 -0800603 }
604}
605
Craig Tiller58ce3f02015-04-22 07:54:24 -0700606static void call_on_done_send(void *pc, int success) {
607 grpc_call *call = pc;
608 grpc_op_error error = success ? GRPC_OP_OK : GRPC_OP_ERROR;
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800609 lock(call);
Craig Tiller58ce3f02015-04-22 07:54:24 -0700610 if (call->last_send_contains & (1 << GRPC_IOREQ_SEND_INITIAL_METADATA)) {
611 finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, error);
612 }
613 if (call->last_send_contains & (1 << GRPC_IOREQ_SEND_MESSAGE)) {
614 finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGE, error);
615 }
616 if (call->last_send_contains & (1 << GRPC_IOREQ_SEND_CLOSE)) {
Craig Tiller6e84aba2015-04-23 15:08:17 -0700617 finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, error);
618 finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, error);
Craig Tiller48b9fde2015-04-24 08:04:59 -0700619 finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_OK);
Craig Tiller58ce3f02015-04-22 07:54:24 -0700620 }
Craig Tiller3928c7a2015-04-23 16:00:47 -0700621 call->last_send_contains = 0;
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800622 call->sending = 0;
623 unlock(call);
Craig Tiller4df412b2015-04-28 07:57:54 -0700624 GRPC_CALL_INTERNAL_UNREF(call, "sending", 0);
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800625}
626
Craig Tiller629b0ed2015-04-22 11:14:26 -0700627static void finish_message(grpc_call *call) {
628 /* TODO(ctiller): this could be a lot faster if coded directly */
629 grpc_byte_buffer *byte_buffer = grpc_byte_buffer_create(
630 call->incoming_message.slices, call->incoming_message.count);
631 gpr_slice_buffer_reset_and_unref(&call->incoming_message);
632
633 grpc_bbq_push(&call->incoming_queue, byte_buffer);
634
635 GPR_ASSERT(call->incoming_message.count == 0);
636 call->reading_message = 0;
637}
638
639static int begin_message(grpc_call *call, grpc_begin_message msg) {
640 /* can't begin a message when we're still reading a message */
641 if (call->reading_message) {
642 char *message = NULL;
643 gpr_asprintf(
644 &message, "Message terminated early; read %d bytes, expected %d",
645 (int)call->incoming_message.length, (int)call->incoming_message_length);
646 grpc_call_cancel_with_status(call, GRPC_STATUS_INVALID_ARGUMENT, message);
647 gpr_free(message);
648 return 0;
649 }
650 /* stash away parameters, and prepare for incoming slices */
651 if (msg.length > grpc_channel_get_max_message_length(call->channel)) {
652 char *message = NULL;
653 gpr_asprintf(
654 &message,
655 "Maximum message length of %d exceeded by a message of length %d",
656 grpc_channel_get_max_message_length(call->channel), msg.length);
657 grpc_call_cancel_with_status(call, GRPC_STATUS_INVALID_ARGUMENT, message);
658 gpr_free(message);
659 return 0;
660 } else if (msg.length > 0) {
661 call->reading_message = 1;
662 call->incoming_message_length = msg.length;
663 return 1;
664 } else {
665 finish_message(call);
666 return 1;
667 }
668}
669
670static int add_slice_to_message(grpc_call *call, gpr_slice slice) {
671 if (GPR_SLICE_LENGTH(slice) == 0) {
672 gpr_slice_unref(slice);
673 return 1;
674 }
675 /* we have to be reading a message to know what to do here */
676 if (!call->reading_message) {
677 grpc_call_cancel_with_status(
678 call, GRPC_STATUS_INVALID_ARGUMENT,
679 "Received payload data while not reading a message");
680 return 0;
681 }
682 /* append the slice to the incoming buffer */
683 gpr_slice_buffer_add(&call->incoming_message, slice);
684 if (call->incoming_message.length > call->incoming_message_length) {
685 /* if we got too many bytes, complain */
686 char *message = NULL;
687 gpr_asprintf(
688 &message, "Receiving message overflow; read %d bytes, expected %d",
689 (int)call->incoming_message.length, (int)call->incoming_message_length);
690 grpc_call_cancel_with_status(call, GRPC_STATUS_INVALID_ARGUMENT, message);
691 gpr_free(message);
692 return 0;
693 } else if (call->incoming_message.length == call->incoming_message_length) {
694 finish_message(call);
695 return 1;
696 } else {
697 return 1;
698 }
699}
700
701static void call_on_done_recv(void *pc, int success) {
702 grpc_call *call = pc;
703 size_t i;
Craig Tiller629b0ed2015-04-22 11:14:26 -0700704 lock(call);
Craig Tiller6e84aba2015-04-23 15:08:17 -0700705 call->receiving = 0;
Craig Tiller48b9fde2015-04-24 08:04:59 -0700706 if (success) {
707 for (i = 0; success && i < call->recv_ops.nops; i++) {
708 grpc_stream_op *op = &call->recv_ops.ops[i];
709 switch (op->type) {
710 case GRPC_NO_OP:
711 break;
712 case GRPC_OP_METADATA:
713 recv_metadata(call, &op->data.metadata);
714 break;
715 case GRPC_OP_BEGIN_MESSAGE:
716 success = begin_message(call, op->data.begin_message);
717 break;
718 case GRPC_OP_SLICE:
719 success = add_slice_to_message(call, op->data.slice);
720 break;
721 }
Craig Tiller629b0ed2015-04-22 11:14:26 -0700722 }
Craig Tiller48b9fde2015-04-24 08:04:59 -0700723 if (call->recv_state == GRPC_STREAM_RECV_CLOSED) {
724 GPR_ASSERT(call->read_state <= READ_STATE_READ_CLOSED);
725 call->read_state = READ_STATE_READ_CLOSED;
726 }
727 if (call->recv_state == GRPC_STREAM_CLOSED) {
728 GPR_ASSERT(call->read_state <= READ_STATE_STREAM_CLOSED);
729 call->read_state = READ_STATE_STREAM_CLOSED;
Craig Tiller48b9fde2015-04-24 08:04:59 -0700730 }
731 finish_read_ops(call);
732 } else {
733 finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_ERROR);
734 finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_ERROR);
735 finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_ERROR);
736 finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_ERROR);
737 finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_ERROR);
738 finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS_DETAILS, GRPC_OP_ERROR);
Craig Tiller629b0ed2015-04-22 11:14:26 -0700739 }
Craig Tillerc1f75602015-04-24 11:44:53 -0700740 call->recv_ops.nops = 0;
Craig Tiller629b0ed2015-04-22 11:14:26 -0700741 unlock(call);
742
Craig Tiller4df412b2015-04-28 07:57:54 -0700743 GRPC_CALL_INTERNAL_UNREF(call, "receiving", 0);
Craig Tiller629b0ed2015-04-22 11:14:26 -0700744}
745
Craig Tiller83f88d92015-04-21 16:02:05 -0700746static grpc_mdelem_list chain_metadata_from_app(grpc_call *call, size_t count,
747 grpc_metadata *metadata) {
748 size_t i;
749 grpc_mdelem_list out;
750 if (count == 0) {
751 out.head = out.tail = NULL;
752 return out;
753 }
754 for (i = 0; i < count; i++) {
755 grpc_metadata *md = &metadata[i];
756 grpc_metadata *next_md = (i == count - 1) ? NULL : &metadata[i + 1];
757 grpc_metadata *prev_md = (i == 0) ? NULL : &metadata[i - 1];
758 grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
Craig Tillerd2b11fa2015-04-21 13:45:19 -0700759 GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
Craig Tiller83f88d92015-04-21 16:02:05 -0700760 l->md = grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key,
761 (const gpr_uint8 *)md->value,
762 md->value_length);
763 l->next = next_md ? (grpc_linked_mdelem *)&next_md->internal_data : NULL;
764 l->prev = prev_md ? (grpc_linked_mdelem *)&prev_md->internal_data : NULL;
765 }
766 out.head = (grpc_linked_mdelem *)&(metadata[0].internal_data);
767 out.tail = (grpc_linked_mdelem *)&(metadata[count - 1].internal_data);
768 return out;
769}
770
Craig Tiller629b0ed2015-04-22 11:14:26 -0700771/* Copy the contents of a byte buffer into stream ops */
772static void copy_byte_buffer_to_stream_ops(grpc_byte_buffer *byte_buffer,
773 grpc_stream_op_buffer *sopb) {
774 size_t i;
775
776 switch (byte_buffer->type) {
777 case GRPC_BB_SLICE_BUFFER:
778 for (i = 0; i < byte_buffer->data.slice_buffer.count; i++) {
779 gpr_slice slice = byte_buffer->data.slice_buffer.slices[i];
780 gpr_slice_ref(slice);
781 grpc_sopb_add_slice(sopb, slice);
782 }
783 break;
784 }
785}
786
Craig Tiller83f88d92015-04-21 16:02:05 -0700787static int fill_send_ops(grpc_call *call, grpc_transport_op *op) {
788 grpc_ioreq_data data;
789 grpc_metadata_batch mdb;
790 size_t i;
Craig Tiller58ce3f02015-04-22 07:54:24 -0700791 char status_str[GPR_LTOA_MIN_BUFSIZE];
Craig Tiller83f88d92015-04-21 16:02:05 -0700792 GPR_ASSERT(op->send_ops == NULL);
793
794 switch (call->write_state) {
795 case WRITE_STATE_INITIAL:
796 if (!is_op_live(call, GRPC_IOREQ_SEND_INITIAL_METADATA)) {
797 break;
798 }
799 data = call->request_data[GRPC_IOREQ_SEND_INITIAL_METADATA];
Craig Tiller629b0ed2015-04-22 11:14:26 -0700800 mdb.list = chain_metadata_from_app(call, data.send_metadata.count,
801 data.send_metadata.metadata);
Craig Tiller83f88d92015-04-21 16:02:05 -0700802 mdb.garbage.head = mdb.garbage.tail = NULL;
803 mdb.deadline = call->send_deadline;
804 for (i = 0; i < call->send_initial_metadata_count; i++) {
Craig Tiller629b0ed2015-04-22 11:14:26 -0700805 grpc_metadata_batch_link_head(&mdb, &call->send_initial_metadata[i]);
Craig Tiller83f88d92015-04-21 16:02:05 -0700806 }
807 grpc_sopb_add_metadata(&call->send_ops, mdb);
808 op->send_ops = &call->send_ops;
809 op->bind_pollset = grpc_cq_pollset(call->cq);
Craig Tiller58ce3f02015-04-22 07:54:24 -0700810 call->last_send_contains |= 1 << GRPC_IOREQ_SEND_INITIAL_METADATA;
811 call->write_state = WRITE_STATE_STARTED;
Craig Tillerc1f75602015-04-24 11:44:53 -0700812 call->send_initial_metadata_count = 0;
Craig Tiller629b0ed2015-04-22 11:14:26 -0700813 /* fall through intended */
Craig Tiller83f88d92015-04-21 16:02:05 -0700814 case WRITE_STATE_STARTED:
815 if (is_op_live(call, GRPC_IOREQ_SEND_MESSAGE)) {
816 data = call->request_data[GRPC_IOREQ_SEND_MESSAGE];
Craig Tiller629b0ed2015-04-22 11:14:26 -0700817 grpc_sopb_add_begin_message(
818 &call->send_ops, grpc_byte_buffer_length(data.send_message), 0);
819 copy_byte_buffer_to_stream_ops(data.send_message, &call->send_ops);
Craig Tiller58ce3f02015-04-22 07:54:24 -0700820 op->send_ops = &call->send_ops;
821 call->last_send_contains |= 1 << GRPC_IOREQ_SEND_MESSAGE;
822 }
823 if (is_op_live(call, GRPC_IOREQ_SEND_CLOSE)) {
824 op->is_last_send = 1;
825 op->send_ops = &call->send_ops;
826 call->last_send_contains |= 1 << GRPC_IOREQ_SEND_CLOSE;
827 call->write_state = WRITE_STATE_WRITE_CLOSED;
828 if (!call->is_client) {
829 /* send trailing metadata */
830 data = call->request_data[GRPC_IOREQ_SEND_TRAILING_METADATA];
Craig Tiller629b0ed2015-04-22 11:14:26 -0700831 mdb.list = chain_metadata_from_app(call, data.send_metadata.count,
832 data.send_metadata.metadata);
Craig Tiller58ce3f02015-04-22 07:54:24 -0700833 mdb.garbage.head = mdb.garbage.tail = NULL;
Craig Tillerd393f102015-04-23 16:11:51 -0700834 mdb.deadline = gpr_inf_future;
Craig Tiller58ce3f02015-04-22 07:54:24 -0700835 /* send status */
836 /* TODO(ctiller): cache common status values */
837 data = call->request_data[GRPC_IOREQ_SEND_STATUS];
838 gpr_ltoa(data.send_status.code, status_str);
839 grpc_metadata_batch_add_tail(
840 &mdb, &call->status_link,
841 grpc_mdelem_from_metadata_strings(
842 call->metadata_context,
843 grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)),
844 grpc_mdstr_from_string(call->metadata_context, status_str)));
845 if (data.send_status.details) {
846 grpc_metadata_batch_add_tail(
847 &mdb, &call->details_link,
848 grpc_mdelem_from_metadata_strings(
849 call->metadata_context,
Craig Tiller629b0ed2015-04-22 11:14:26 -0700850 grpc_mdstr_ref(
851 grpc_channel_get_message_string(call->channel)),
Craig Tiller58ce3f02015-04-22 07:54:24 -0700852 grpc_mdstr_from_string(call->metadata_context,
853 data.send_status.details)));
854 }
Craig Tiller7e8489a2015-04-23 12:41:16 -0700855 grpc_sopb_add_metadata(&call->send_ops, mdb);
Craig Tillerde648622015-02-05 09:32:10 -0800856 }
Craig Tillerc12fee62015-02-03 11:55:50 -0800857 }
Craig Tiller58ce3f02015-04-22 07:54:24 -0700858 break;
Craig Tillerc12fee62015-02-03 11:55:50 -0800859 case WRITE_STATE_WRITE_CLOSED:
Craig Tiller8eb9d472015-01-27 17:00:03 -0800860 break;
Craig Tiller62ac1552015-01-27 15:41:44 -0800861 }
Craig Tiller58ce3f02015-04-22 07:54:24 -0700862 if (op->send_ops) {
863 op->on_done_send = call_on_done_send;
864 op->send_user_data = call;
865 }
866 return op->send_ops != NULL;
Craig Tillercce17ac2015-01-20 09:29:28 -0800867}
868
869static grpc_call_error start_ioreq_error(grpc_call *call,
870 gpr_uint32 mutated_ops,
871 grpc_call_error ret) {
872 size_t i;
873 for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) {
Craig Tillerd642dcf2015-02-03 20:39:09 -0800874 if (mutated_ops & (1u << i)) {
Craig Tillerc12fee62015-02-03 11:55:50 -0800875 call->request_set[i] = REQSET_EMPTY;
Craig Tillercce17ac2015-01-20 09:29:28 -0800876 }
877 }
Craig Tillercce17ac2015-01-20 09:29:28 -0800878 return ret;
879}
880
Craig Tillerc12fee62015-02-03 11:55:50 -0800881static void finish_read_ops(grpc_call *call) {
882 int empty;
883
884 if (is_op_live(call, GRPC_IOREQ_RECV_MESSAGE)) {
885 empty =
886 (NULL == (*call->request_data[GRPC_IOREQ_RECV_MESSAGE].recv_message =
887 grpc_bbq_pop(&call->incoming_queue)));
888 if (!empty) {
889 finish_live_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK);
890 empty = grpc_bbq_empty(&call->incoming_queue);
891 }
892 } else {
893 empty = grpc_bbq_empty(&call->incoming_queue);
894 }
895
896 switch (call->read_state) {
897 case READ_STATE_STREAM_CLOSED:
898 if (empty) {
899 finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK);
900 }
901 /* fallthrough */
902 case READ_STATE_READ_CLOSED:
903 if (empty) {
904 finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK);
905 }
906 finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK);
Craig Tillerfb189f82015-02-03 12:07:07 -0800907 finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS_DETAILS, GRPC_OP_OK);
Craig Tillerc12fee62015-02-03 11:55:50 -0800908 finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK);
909 /* fallthrough */
910 case READ_STATE_GOT_INITIAL_METADATA:
911 finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK);
912 /* fallthrough */
913 case READ_STATE_INITIAL:
914 /* do nothing */
915 break;
916 }
917}
918
919static void early_out_write_ops(grpc_call *call) {
920 switch (call->write_state) {
921 case WRITE_STATE_WRITE_CLOSED:
922 finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGE, GRPC_OP_ERROR);
923 finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_ERROR);
924 finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_ERROR);
925 finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_OK);
926 /* fallthrough */
927 case WRITE_STATE_STARTED:
928 finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_ERROR);
929 /* fallthrough */
930 case WRITE_STATE_INITIAL:
931 /* do nothing */
932 break;
933 }
934}
935
Craig Tiller8eb9d472015-01-27 17:00:03 -0800936static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
937 size_t nreqs,
938 grpc_ioreq_completion_func completion,
Craig Tiller9cc61412015-02-02 14:02:52 -0800939 void *user_data) {
Craig Tillercce17ac2015-01-20 09:29:28 -0800940 size_t i;
941 gpr_uint32 have_ops = 0;
Craig Tillercce17ac2015-01-20 09:29:28 -0800942 grpc_ioreq_op op;
Craig Tillerc18c56e2015-02-02 15:59:13 -0800943 reqinfo_master *master;
Craig Tillercce17ac2015-01-20 09:29:28 -0800944 grpc_ioreq_data data;
Craig Tiller1e0d4c42015-01-30 16:17:29 -0800945 gpr_uint8 set;
946
947 if (nreqs == 0) {
948 return GRPC_CALL_OK;
949 }
950
951 set = reqs[0].op;
Craig Tillercce17ac2015-01-20 09:29:28 -0800952
953 for (i = 0; i < nreqs; i++) {
954 op = reqs[i].op;
Craig Tillerc12fee62015-02-03 11:55:50 -0800955 if (call->request_set[op] < GRPC_IOREQ_OP_COUNT) {
Craig Tillercce17ac2015-01-20 09:29:28 -0800956 return start_ioreq_error(call, have_ops,
957 GRPC_CALL_ERROR_TOO_MANY_OPERATIONS);
Craig Tillerc12fee62015-02-03 11:55:50 -0800958 } else if (call->request_set[op] == REQSET_DONE) {
Craig Tiller1c141902015-01-31 08:51:54 -0800959 return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_ALREADY_INVOKED);
Craig Tillercce17ac2015-01-20 09:29:28 -0800960 }
Craig Tillerd642dcf2015-02-03 20:39:09 -0800961 have_ops |= 1u << op;
Craig Tillercce17ac2015-01-20 09:29:28 -0800962 data = reqs[i].data;
963
Craig Tillerc12fee62015-02-03 11:55:50 -0800964 call->request_data[op] = data;
965 call->request_set[op] = set;
Craig Tillercce17ac2015-01-20 09:29:28 -0800966 }
967
Craig Tillerc18c56e2015-02-02 15:59:13 -0800968 master = &call->masters[set];
969 master->status = GRPC_OP_OK;
Craig Tillercce17ac2015-01-20 09:29:28 -0800970 master->need_mask = have_ops;
Craig Tiller1b409442015-01-29 14:36:17 -0800971 master->complete_mask = 0;
Craig Tillercce17ac2015-01-20 09:29:28 -0800972 master->on_complete = completion;
973 master->user_data = user_data;
974
Craig Tillerc12fee62015-02-03 11:55:50 -0800975 finish_read_ops(call);
976 early_out_write_ops(call);
977
Craig Tillercce17ac2015-01-20 09:29:28 -0800978 return GRPC_CALL_OK;
979}
980
Craig Tillercce17ac2015-01-20 09:29:28 -0800981grpc_call_error grpc_call_start_ioreq_and_call_back(
982 grpc_call *call, const grpc_ioreq *reqs, size_t nreqs,
983 grpc_ioreq_completion_func on_complete, void *user_data) {
Craig Tiller8eb9d472015-01-27 17:00:03 -0800984 grpc_call_error err;
985 lock(call);
Craig Tiller9cc61412015-02-02 14:02:52 -0800986 err = start_ioreq(call, reqs, nreqs, on_complete, user_data);
Craig Tiller8eb9d472015-01-27 17:00:03 -0800987 unlock(call);
988 return err;
Craig Tillercce17ac2015-01-20 09:29:28 -0800989}
990
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800991void grpc_call_destroy(grpc_call *c) {
ctillerc6d61c42014-12-15 14:52:08 -0800992 int cancel;
Craig Tiller9724de82015-01-28 17:06:29 -0800993 lock(c);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800994 if (c->have_alarm) {
ctiller18b49ab2014-12-09 14:39:16 -0800995 grpc_alarm_cancel(&c->alarm);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800996 c->have_alarm = 0;
997 }
Craig Tillerdaceea82015-02-02 16:15:53 -0800998 cancel = c->read_state != READ_STATE_STREAM_CLOSED;
Craig Tiller9724de82015-01-28 17:06:29 -0800999 unlock(c);
ctillerc6d61c42014-12-15 14:52:08 -08001000 if (cancel) grpc_call_cancel(c);
Craig Tiller4df412b2015-04-28 07:57:54 -07001001 GRPC_CALL_INTERNAL_UNREF(c, "destroy", 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001002}
1003
Craig Tiller58ce3f02015-04-22 07:54:24 -07001004grpc_call_error grpc_call_cancel(grpc_call *call) {
Craig Tiller48b9fde2015-04-24 08:04:59 -07001005 return grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED, "Cancelled");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001006}
1007
Craig Tiller6046dc32015-01-14 12:55:45 -08001008grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
1009 grpc_status_code status,
1010 const char *description) {
Craig Tiller48b9fde2015-04-24 08:04:59 -07001011 grpc_transport_op op;
Craig Tiller6046dc32015-01-14 12:55:45 -08001012 grpc_mdstr *details =
1013 description ? grpc_mdstr_from_string(c->metadata_context, description)
1014 : NULL;
Craig Tiller48b9fde2015-04-24 08:04:59 -07001015 memset(&op, 0, sizeof(op));
1016 op.cancel_with_status = status;
1017
Craig Tiller9724de82015-01-28 17:06:29 -08001018 lock(c);
Craig Tiller68752722015-01-29 14:59:54 -08001019 set_status_code(c, STATUS_FROM_API_OVERRIDE, status);
1020 set_status_details(c, STATUS_FROM_API_OVERRIDE, details);
Craig Tiller9724de82015-01-28 17:06:29 -08001021 unlock(c);
Craig Tiller48b9fde2015-04-24 08:04:59 -07001022
1023 execute_op(c, &op);
1024
1025 return GRPC_CALL_OK;
Craig Tillerd248c242015-01-14 11:49:12 -08001026}
1027
Craig Tiller58ce3f02015-04-22 07:54:24 -07001028static void execute_op(grpc_call *call, grpc_transport_op *op) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001029 grpc_call_element *elem;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001030 elem = CALL_ELEM_FROM_CALL(call, 0);
Craig Tiller58ce3f02015-04-22 07:54:24 -07001031 elem->filter->start_transport_op(elem, op);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001032}
1033
Craig Tiller566316f2015-02-02 15:25:32 -08001034grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
1035 return CALL_FROM_TOP_ELEM(elem);
1036}
1037
1038static void call_alarm(void *arg, int success) {
1039 grpc_call *call = arg;
1040 if (success) {
1041 if (call->is_client) {
1042 grpc_call_cancel_with_status(call, GRPC_STATUS_DEADLINE_EXCEEDED,
1043 "Deadline Exceeded");
1044 } else {
1045 grpc_call_cancel(call);
1046 }
1047 }
Craig Tiller4df412b2015-04-28 07:57:54 -07001048 GRPC_CALL_INTERNAL_UNREF(call, "alarm", 1);
Craig Tiller566316f2015-02-02 15:25:32 -08001049}
1050
Craig Tiller6902ad22015-04-16 08:01:49 -07001051static void set_deadline_alarm(grpc_call *call, gpr_timespec deadline) {
Craig Tiller566316f2015-02-02 15:25:32 -08001052 if (call->have_alarm) {
1053 gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice");
Craig Tillerfa4f9942015-04-23 15:22:09 -07001054 assert(0);
Craig Tiller7e8489a2015-04-23 12:41:16 -07001055 return;
Craig Tiller566316f2015-02-02 15:25:32 -08001056 }
Craig Tiller4df412b2015-04-28 07:57:54 -07001057 GRPC_CALL_INTERNAL_REF(call, "alarm");
Craig Tiller566316f2015-02-02 15:25:32 -08001058 call->have_alarm = 1;
1059 grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now());
1060}
1061
Craig Tiller566316f2015-02-02 15:25:32 -08001062/* we offset status by a small amount when storing it into transport metadata
1063 as metadata cannot store a 0 value (which is used as OK for grpc_status_codes
1064 */
1065#define STATUS_OFFSET 1
1066static void destroy_status(void *ignored) {}
1067
1068static gpr_uint32 decode_status(grpc_mdelem *md) {
1069 gpr_uint32 status;
1070 void *user_data = grpc_mdelem_get_user_data(md, destroy_status);
1071 if (user_data) {
Craig Tiller87d5b192015-04-16 14:37:57 -07001072 status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET;
Craig Tiller566316f2015-02-02 15:25:32 -08001073 } else {
1074 if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value),
1075 GPR_SLICE_LENGTH(md->value->slice),
1076 &status)) {
1077 status = GRPC_STATUS_UNKNOWN; /* could not parse status code */
1078 }
1079 grpc_mdelem_set_user_data(md, destroy_status,
1080 (void *)(gpr_intptr)(status + STATUS_OFFSET));
1081 }
1082 return status;
1083}
1084
Craig Tiller629b0ed2015-04-22 11:14:26 -07001085static void recv_metadata(grpc_call *call, grpc_metadata_batch *md) {
Craig Tiller6902ad22015-04-16 08:01:49 -07001086 grpc_linked_mdelem *l;
Craig Tiller566316f2015-02-02 15:25:32 -08001087 grpc_metadata_array *dest;
1088 grpc_metadata *mdusr;
Craig Tiller6902ad22015-04-16 08:01:49 -07001089 int is_trailing;
Craig Tiller8b282cb2015-04-17 14:57:44 -07001090 grpc_mdctx *mdctx = call->metadata_context;
Craig Tiller566316f2015-02-02 15:25:32 -08001091
Craig Tiller6902ad22015-04-16 08:01:49 -07001092 is_trailing = call->read_state >= READ_STATE_GOT_INITIAL_METADATA;
Craig Tiller48b02ec2015-04-21 13:58:36 -07001093 for (l = md->list.head; l != NULL; l = l->next) {
Craig Tiller6902ad22015-04-16 08:01:49 -07001094 grpc_mdelem *md = l->md;
1095 grpc_mdstr *key = md->key;
1096 if (key == grpc_channel_get_status_string(call->channel)) {
1097 set_status_code(call, STATUS_FROM_WIRE, decode_status(md));
Craig Tiller6902ad22015-04-16 08:01:49 -07001098 } else if (key == grpc_channel_get_message_string(call->channel)) {
1099 set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value));
Craig Tiller6902ad22015-04-16 08:01:49 -07001100 } else {
1101 dest = &call->buffered_metadata[is_trailing];
1102 if (dest->count == dest->capacity) {
1103 dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2);
1104 dest->metadata =
1105 gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
1106 }
1107 mdusr = &dest->metadata[dest->count++];
1108 mdusr->key = grpc_mdstr_as_c_string(md->key);
1109 mdusr->value = grpc_mdstr_as_c_string(md->value);
1110 mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice);
1111 if (call->owned_metadata_count == call->owned_metadata_capacity) {
Craig Tiller87d5b192015-04-16 14:37:57 -07001112 call->owned_metadata_capacity =
1113 GPR_MAX(call->owned_metadata_capacity + 8,
1114 call->owned_metadata_capacity * 2);
Craig Tiller6902ad22015-04-16 08:01:49 -07001115 call->owned_metadata =
1116 gpr_realloc(call->owned_metadata,
1117 sizeof(grpc_mdelem *) * call->owned_metadata_capacity);
1118 }
1119 call->owned_metadata[call->owned_metadata_count++] = md;
Craig Tiller8b282cb2015-04-17 14:57:44 -07001120 l->md = 0;
Craig Tiller566316f2015-02-02 15:25:32 -08001121 }
Craig Tiller6902ad22015-04-16 08:01:49 -07001122 }
1123 if (gpr_time_cmp(md->deadline, gpr_inf_future) != 0) {
1124 set_deadline_alarm(call, md->deadline);
1125 }
1126 if (!is_trailing) {
Craig Tiller629b0ed2015-04-22 11:14:26 -07001127 call->read_state = READ_STATE_GOT_INITIAL_METADATA;
Craig Tiller566316f2015-02-02 15:25:32 -08001128 }
Craig Tiller6902ad22015-04-16 08:01:49 -07001129
Craig Tiller8b282cb2015-04-17 14:57:44 -07001130 grpc_mdctx_lock(mdctx);
1131 for (l = md->list.head; l; l = l->next) {
1132 if (l->md) grpc_mdctx_locked_mdelem_unref(mdctx, l->md);
1133 }
1134 for (l = md->garbage.head; l; l = l->next) {
1135 grpc_mdctx_locked_mdelem_unref(mdctx, l->md);
1136 }
1137 grpc_mdctx_unlock(mdctx);
Craig Tiller629b0ed2015-04-22 11:14:26 -07001138}
Craig Tiller8b282cb2015-04-17 14:57:44 -07001139
Craig Tiller566316f2015-02-02 15:25:32 -08001140grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) {
1141 return CALL_STACK_FROM_CALL(call);
1142}
1143
1144/*
Craig Tillerfb189f82015-02-03 12:07:07 -08001145 * BATCH API IMPLEMENTATION
1146 */
1147
1148static void set_status_value_directly(grpc_status_code status, void *dest) {
1149 *(grpc_status_code *)dest = status;
1150}
1151
1152static void set_cancelled_value(grpc_status_code status, void *dest) {
1153 *(grpc_status_code *)dest = (status != GRPC_STATUS_OK);
1154}
1155
Craig Tiller166e2502015-02-03 20:14:41 -08001156static void finish_batch(grpc_call *call, grpc_op_error result, void *tag) {
1157 grpc_cq_end_op_complete(call->cq, tag, call, do_nothing, NULL, GRPC_OP_OK);
1158}
Craig Tillerfb189f82015-02-03 12:07:07 -08001159
1160grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
1161 size_t nops, void *tag) {
1162 grpc_ioreq reqs[GRPC_IOREQ_OP_COUNT];
1163 size_t in;
1164 size_t out;
1165 const grpc_op *op;
1166 grpc_ioreq *req;
1167
murgatroid99d47946b2015-03-09 14:27:07 -07001168 GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, tag);
1169
murgatroid99a8c21e82015-02-12 13:55:53 -08001170 if (nops == 0) {
1171 grpc_cq_begin_op(call->cq, call, GRPC_OP_COMPLETE);
1172 grpc_cq_end_op_complete(call->cq, tag, call, do_nothing, NULL, GRPC_OP_OK);
1173 return GRPC_CALL_OK;
1174 }
1175
Craig Tillerfb189f82015-02-03 12:07:07 -08001176 /* rewrite batch ops into ioreq ops */
1177 for (in = 0, out = 0; in < nops; in++) {
1178 op = &ops[in];
1179 switch (op->op) {
1180 case GRPC_OP_SEND_INITIAL_METADATA:
1181 req = &reqs[out++];
1182 req->op = GRPC_IOREQ_SEND_INITIAL_METADATA;
1183 req->data.send_metadata.count = op->data.send_initial_metadata.count;
1184 req->data.send_metadata.metadata =
1185 op->data.send_initial_metadata.metadata;
1186 break;
1187 case GRPC_OP_SEND_MESSAGE:
1188 req = &reqs[out++];
1189 req->op = GRPC_IOREQ_SEND_MESSAGE;
1190 req->data.send_message = op->data.send_message;
1191 break;
1192 case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
1193 if (!call->is_client) {
1194 return GRPC_CALL_ERROR_NOT_ON_SERVER;
1195 }
1196 req = &reqs[out++];
1197 req->op = GRPC_IOREQ_SEND_CLOSE;
1198 break;
1199 case GRPC_OP_SEND_STATUS_FROM_SERVER:
1200 if (call->is_client) {
1201 return GRPC_CALL_ERROR_NOT_ON_CLIENT;
1202 }
1203 req = &reqs[out++];
1204 req->op = GRPC_IOREQ_SEND_TRAILING_METADATA;
1205 req->data.send_metadata.count =
1206 op->data.send_status_from_server.trailing_metadata_count;
1207 req->data.send_metadata.metadata =
1208 op->data.send_status_from_server.trailing_metadata;
1209 req = &reqs[out++];
1210 req->op = GRPC_IOREQ_SEND_STATUS;
1211 req->data.send_status.code = op->data.send_status_from_server.status;
1212 req->data.send_status.details =
1213 op->data.send_status_from_server.status_details;
1214 req = &reqs[out++];
1215 req->op = GRPC_IOREQ_SEND_CLOSE;
1216 break;
1217 case GRPC_OP_RECV_INITIAL_METADATA:
1218 if (!call->is_client) {
1219 return GRPC_CALL_ERROR_NOT_ON_SERVER;
1220 }
1221 req = &reqs[out++];
1222 req->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
1223 req->data.recv_metadata = op->data.recv_initial_metadata;
1224 break;
1225 case GRPC_OP_RECV_MESSAGE:
1226 req = &reqs[out++];
1227 req->op = GRPC_IOREQ_RECV_MESSAGE;
1228 req->data.recv_message = op->data.recv_message;
1229 break;
1230 case GRPC_OP_RECV_STATUS_ON_CLIENT:
1231 if (!call->is_client) {
1232 return GRPC_CALL_ERROR_NOT_ON_SERVER;
1233 }
1234 req = &reqs[out++];
1235 req->op = GRPC_IOREQ_RECV_STATUS;
1236 req->data.recv_status.set_value = set_status_value_directly;
1237 req->data.recv_status.user_data = op->data.recv_status_on_client.status;
1238 req = &reqs[out++];
1239 req->op = GRPC_IOREQ_RECV_STATUS_DETAILS;
1240 req->data.recv_status_details.details =
1241 op->data.recv_status_on_client.status_details;
1242 req->data.recv_status_details.details_capacity =
1243 op->data.recv_status_on_client.status_details_capacity;
1244 req = &reqs[out++];
1245 req->op = GRPC_IOREQ_RECV_TRAILING_METADATA;
1246 req->data.recv_metadata =
1247 op->data.recv_status_on_client.trailing_metadata;
1248 req = &reqs[out++];
1249 req->op = GRPC_IOREQ_RECV_CLOSE;
1250 break;
1251 case GRPC_OP_RECV_CLOSE_ON_SERVER:
1252 req = &reqs[out++];
1253 req->op = GRPC_IOREQ_RECV_STATUS;
1254 req->data.recv_status.set_value = set_cancelled_value;
1255 req->data.recv_status.user_data =
1256 op->data.recv_close_on_server.cancelled;
1257 req = &reqs[out++];
1258 req->op = GRPC_IOREQ_RECV_CLOSE;
1259 break;
1260 }
1261 }
1262
1263 grpc_cq_begin_op(call->cq, call, GRPC_OP_COMPLETE);
1264
1265 return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_batch,
1266 tag);
1267}
1268
1269/*
Craig Tiller566316f2015-02-02 15:25:32 -08001270 * LEGACY API IMPLEMENTATION
1271 * All this code will disappear as soon as wrappings are updated
1272 */
1273
1274struct legacy_state {
1275 gpr_uint8 md_out_buffer;
1276 size_t md_out_count[2];
1277 size_t md_out_capacity[2];
1278 grpc_metadata *md_out[2];
1279 grpc_byte_buffer *msg_out;
1280
1281 /* input buffers */
1282 grpc_metadata_array initial_md_in;
1283 grpc_metadata_array trailing_md_in;
1284
1285 size_t details_capacity;
1286 char *details;
1287 grpc_status_code status;
1288
Craig Tiller37bbead2015-02-05 08:43:49 -08001289 char *send_details;
1290
Craig Tiller566316f2015-02-02 15:25:32 -08001291 size_t msg_in_read_idx;
1292 grpc_byte_buffer *msg_in;
1293
1294 void *finished_tag;
1295};
1296
1297static legacy_state *get_legacy_state(grpc_call *call) {
1298 if (call->legacy_state == NULL) {
1299 call->legacy_state = gpr_malloc(sizeof(legacy_state));
1300 memset(call->legacy_state, 0, sizeof(legacy_state));
1301 }
1302 return call->legacy_state;
1303}
1304
1305static void destroy_legacy_state(legacy_state *ls) {
1306 size_t i, j;
1307 for (i = 0; i < 2; i++) {
1308 for (j = 0; j < ls->md_out_count[i]; j++) {
Craig Tiller4f972732015-02-05 12:40:20 -08001309 gpr_free((char *)ls->md_out[i][j].key);
1310 gpr_free((char *)ls->md_out[i][j].value);
Craig Tiller566316f2015-02-02 15:25:32 -08001311 }
1312 gpr_free(ls->md_out[i]);
1313 }
1314 gpr_free(ls->initial_md_in.metadata);
1315 gpr_free(ls->trailing_md_in.metadata);
Craig Tillerea3697b2015-02-05 08:40:18 -08001316 gpr_free(ls->details);
Craig Tiller37bbead2015-02-05 08:43:49 -08001317 gpr_free(ls->send_details);
Craig Tiller566316f2015-02-02 15:25:32 -08001318 gpr_free(ls);
1319}
1320
Craig Tiller40d2a432015-02-02 15:29:14 -08001321grpc_call_error grpc_call_add_metadata_old(grpc_call *call,
1322 grpc_metadata *metadata,
1323 gpr_uint32 flags) {
Craig Tiller62ac1552015-01-27 15:41:44 -08001324 legacy_state *ls;
1325 grpc_metadata *mdout;
1326
Craig Tiller8eb9d472015-01-27 17:00:03 -08001327 lock(call);
Craig Tiller62ac1552015-01-27 15:41:44 -08001328 ls = get_legacy_state(call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001329
Craig Tiller1c141902015-01-31 08:51:54 -08001330 if (ls->md_out_count[ls->md_out_buffer] ==
1331 ls->md_out_capacity[ls->md_out_buffer]) {
Craig Tillerc689ca32015-01-30 10:59:52 -08001332 ls->md_out_capacity[ls->md_out_buffer] =
Craig Tiller1c141902015-01-31 08:51:54 -08001333 GPR_MAX(ls->md_out_capacity[ls->md_out_buffer] * 3 / 2,
1334 ls->md_out_capacity[ls->md_out_buffer] + 8);
1335 ls->md_out[ls->md_out_buffer] = gpr_realloc(
1336 ls->md_out[ls->md_out_buffer],
1337 sizeof(grpc_metadata) * ls->md_out_capacity[ls->md_out_buffer]);
Craig Tillercce17ac2015-01-20 09:29:28 -08001338 }
Craig Tillerc689ca32015-01-30 10:59:52 -08001339 mdout = &ls->md_out[ls->md_out_buffer][ls->md_out_count[ls->md_out_buffer]++];
Craig Tiller62ac1552015-01-27 15:41:44 -08001340 mdout->key = gpr_strdup(metadata->key);
1341 mdout->value = gpr_malloc(metadata->value_length);
1342 mdout->value_length = metadata->value_length;
Craig Tiller4f972732015-02-05 12:40:20 -08001343 memcpy((char *)mdout->value, metadata->value, metadata->value_length);
klempnerc463f742014-12-19 13:03:35 -08001344
Craig Tiller8eb9d472015-01-27 17:00:03 -08001345 unlock(call);
Craig Tiller62ac1552015-01-27 15:41:44 -08001346
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001347 return GRPC_CALL_OK;
1348}
1349
Craig Tiller50524cc2015-01-29 23:00:00 -08001350static void finish_status(grpc_call *call, grpc_op_error status,
1351 void *ignored) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001352 legacy_state *ls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001353
Craig Tiller8eb9d472015-01-27 17:00:03 -08001354 lock(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001355 ls = get_legacy_state(call);
Craig Tiller7a9d7922015-01-31 09:35:20 -08001356 grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL,
1357 ls->status, ls->details, ls->trailing_md_in.metadata,
1358 ls->trailing_md_in.count);
Craig Tiller8eb9d472015-01-27 17:00:03 -08001359 unlock(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001360}
Craig Tiller80fa15c2015-01-13 16:10:49 -08001361
Craig Tillercce17ac2015-01-20 09:29:28 -08001362static void finish_recv_metadata(grpc_call *call, grpc_op_error status,
1363 void *tag) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001364 legacy_state *ls;
1365
Craig Tiller8eb9d472015-01-27 17:00:03 -08001366 lock(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001367 ls = get_legacy_state(call);
1368 if (status == GRPC_OP_OK) {
1369 grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL,
Craig Tiller1c141902015-01-31 08:51:54 -08001370 ls->initial_md_in.count,
1371 ls->initial_md_in.metadata);
Craig Tillercce17ac2015-01-20 09:29:28 -08001372
Craig Tiller62ac1552015-01-27 15:41:44 -08001373 } else {
1374 grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, 0,
1375 NULL);
1376 }
Craig Tiller8eb9d472015-01-27 17:00:03 -08001377 unlock(call);
Craig Tiller62ac1552015-01-27 15:41:44 -08001378}
1379
Craig Tiller50524cc2015-01-29 23:00:00 -08001380static void finish_send_metadata(grpc_call *call, grpc_op_error status,
1381 void *tag) {}
Craig Tiller80fa15c2015-01-13 16:10:49 -08001382
Craig Tiller40d2a432015-02-02 15:29:14 -08001383grpc_call_error grpc_call_invoke_old(grpc_call *call, grpc_completion_queue *cq,
1384 void *metadata_read_tag,
1385 void *finished_tag, gpr_uint32 flags) {
Craig Tillerfb189f82015-02-03 12:07:07 -08001386 grpc_ioreq reqs[4];
Craig Tillerfa8f4012015-01-29 16:16:58 -08001387 legacy_state *ls;
Craig Tillercce17ac2015-01-20 09:29:28 -08001388 grpc_call_error err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001389
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001390 grpc_cq_begin_op(cq, call, GRPC_CLIENT_METADATA_READ);
Craig Tillercce17ac2015-01-20 09:29:28 -08001391 grpc_cq_begin_op(cq, call, GRPC_FINISHED);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001392
Craig Tiller8eb9d472015-01-27 17:00:03 -08001393 lock(call);
Craig Tillerfa8f4012015-01-29 16:16:58 -08001394 ls = get_legacy_state(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001395 err = bind_cq(call, cq);
Craig Tillerfa8f4012015-01-29 16:16:58 -08001396 if (err != GRPC_CALL_OK) goto done;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001397
Craig Tiller50524cc2015-01-29 23:00:00 -08001398 ls->finished_tag = finished_tag;
1399
Craig Tillerfa8f4012015-01-29 16:16:58 -08001400 reqs[0].op = GRPC_IOREQ_SEND_INITIAL_METADATA;
Craig Tillerc689ca32015-01-30 10:59:52 -08001401 reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer];
1402 reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer];
1403 ls->md_out_buffer++;
Craig Tiller9cc61412015-02-02 14:02:52 -08001404 err = start_ioreq(call, reqs, 1, finish_send_metadata, NULL);
Craig Tillerfa8f4012015-01-29 16:16:58 -08001405 if (err != GRPC_CALL_OK) goto done;
Craig Tiller9724de82015-01-28 17:06:29 -08001406
Craig Tillerfa8f4012015-01-29 16:16:58 -08001407 reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA;
Craig Tiller03d5bf72015-01-30 12:01:30 -08001408 reqs[0].data.recv_metadata = &ls->initial_md_in;
Craig Tiller9cc61412015-02-02 14:02:52 -08001409 err = start_ioreq(call, reqs, 1, finish_recv_metadata, metadata_read_tag);
Craig Tillerfa8f4012015-01-29 16:16:58 -08001410 if (err != GRPC_CALL_OK) goto done;
1411
1412 reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA;
Craig Tiller03d5bf72015-01-30 12:01:30 -08001413 reqs[0].data.recv_metadata = &ls->trailing_md_in;
Craig Tillerfa8f4012015-01-29 16:16:58 -08001414 reqs[1].op = GRPC_IOREQ_RECV_STATUS;
Craig Tillerfb189f82015-02-03 12:07:07 -08001415 reqs[1].data.recv_status.user_data = &ls->status;
1416 reqs[1].data.recv_status.set_value = set_status_value_directly;
1417 reqs[2].op = GRPC_IOREQ_RECV_STATUS_DETAILS;
1418 reqs[2].data.recv_status_details.details = &ls->details;
1419 reqs[2].data.recv_status_details.details_capacity = &ls->details_capacity;
1420 reqs[3].op = GRPC_IOREQ_RECV_CLOSE;
1421 err = start_ioreq(call, reqs, 4, finish_status, NULL);
Craig Tillerfa8f4012015-01-29 16:16:58 -08001422 if (err != GRPC_CALL_OK) goto done;
1423
1424done:
Craig Tiller8eb9d472015-01-27 17:00:03 -08001425 unlock(call);
1426 return err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001427}
1428
Craig Tiller40d2a432015-02-02 15:29:14 -08001429grpc_call_error grpc_call_server_accept_old(grpc_call *call,
1430 grpc_completion_queue *cq,
1431 void *finished_tag) {
Craig Tiller05140d02015-01-30 16:43:40 -08001432 grpc_ioreq reqs[2];
Craig Tiller8eb9d472015-01-27 17:00:03 -08001433 grpc_call_error err;
Craig Tiller05140d02015-01-30 16:43:40 -08001434 legacy_state *ls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001435
1436 /* inform the completion queue of an incoming operation (corresponding to
1437 finished_tag) */
1438 grpc_cq_begin_op(cq, call, GRPC_FINISHED);
1439
Craig Tiller8884d7f2015-01-29 10:46:45 -08001440 lock(call);
Craig Tiller05140d02015-01-30 16:43:40 -08001441 ls = get_legacy_state(call);
1442
Craig Tiller8eb9d472015-01-27 17:00:03 -08001443 err = bind_cq(call, cq);
Craig Tiller970781b2015-02-08 14:38:31 -08001444 if (err != GRPC_CALL_OK) {
1445 unlock(call);
1446 return err;
1447 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001448
Craig Tiller05140d02015-01-30 16:43:40 -08001449 ls->finished_tag = finished_tag;
Craig Tiller50524cc2015-01-29 23:00:00 -08001450
Craig Tiller05140d02015-01-30 16:43:40 -08001451 reqs[0].op = GRPC_IOREQ_RECV_STATUS;
Craig Tillerfb189f82015-02-03 12:07:07 -08001452 reqs[0].data.recv_status.user_data = &ls->status;
1453 reqs[0].data.recv_status.set_value = set_status_value_directly;
Craig Tiller05140d02015-01-30 16:43:40 -08001454 reqs[1].op = GRPC_IOREQ_RECV_CLOSE;
Craig Tiller9cc61412015-02-02 14:02:52 -08001455 err = start_ioreq(call, reqs, 2, finish_status, NULL);
Craig Tiller8eb9d472015-01-27 17:00:03 -08001456 unlock(call);
1457 return err;
nnoble0c475f02014-12-05 15:37:39 -08001458}
1459
Craig Tillerabcf6522015-01-28 15:44:24 -08001460static void finish_send_initial_metadata(grpc_call *call, grpc_op_error status,
1461 void *tag) {}
Craig Tiller39fd4282015-01-28 09:12:31 -08001462
Craig Tiller40d2a432015-02-02 15:29:14 -08001463grpc_call_error grpc_call_server_end_initial_metadata_old(grpc_call *call,
1464 gpr_uint32 flags) {
Craig Tiller39fd4282015-01-28 09:12:31 -08001465 grpc_ioreq req;
1466 grpc_call_error err;
1467 legacy_state *ls;
1468
1469 lock(call);
1470 ls = get_legacy_state(call);
1471 req.op = GRPC_IOREQ_SEND_INITIAL_METADATA;
Craig Tillerc689ca32015-01-30 10:59:52 -08001472 req.data.send_metadata.count = ls->md_out_count[ls->md_out_buffer];
1473 req.data.send_metadata.metadata = ls->md_out[ls->md_out_buffer];
Craig Tiller9cc61412015-02-02 14:02:52 -08001474 err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL);
Craig Tiller39fd4282015-01-28 09:12:31 -08001475 unlock(call);
Craig Tillerabcf6522015-01-28 15:44:24 -08001476
Craig Tiller39fd4282015-01-28 09:12:31 -08001477 return err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001478}
1479
Craig Tiller68f55a02015-01-30 07:54:48 -08001480static void finish_read_event(void *p, grpc_op_error error) {
Craig Tiller8f4f6e22015-01-31 20:01:37 -08001481 if (p) grpc_byte_buffer_destroy(p);
Craig Tiller68f55a02015-01-30 07:54:48 -08001482}
1483
Craig Tillercce17ac2015-01-20 09:29:28 -08001484static void finish_read(grpc_call *call, grpc_op_error error, void *tag) {
1485 legacy_state *ls;
Craig Tiller05140d02015-01-30 16:43:40 -08001486 grpc_byte_buffer *msg;
Craig Tiller8eb9d472015-01-27 17:00:03 -08001487 lock(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001488 ls = get_legacy_state(call);
Craig Tiller05140d02015-01-30 16:43:40 -08001489 msg = ls->msg_in;
1490 grpc_cq_end_read(call->cq, tag, call, finish_read_event, msg, msg);
Craig Tiller8eb9d472015-01-27 17:00:03 -08001491 unlock(call);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001492}
1493
Craig Tiller40d2a432015-02-02 15:29:14 -08001494grpc_call_error grpc_call_start_read_old(grpc_call *call, void *tag) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001495 legacy_state *ls;
1496 grpc_ioreq req;
Craig Tiller8eb9d472015-01-27 17:00:03 -08001497 grpc_call_error err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001498
1499 grpc_cq_begin_op(call->cq, call, GRPC_READ);
1500
Craig Tiller8eb9d472015-01-27 17:00:03 -08001501 lock(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001502 ls = get_legacy_state(call);
Craig Tiller05140d02015-01-30 16:43:40 -08001503 req.op = GRPC_IOREQ_RECV_MESSAGE;
1504 req.data.recv_message = &ls->msg_in;
Craig Tiller9cc61412015-02-02 14:02:52 -08001505 err = start_ioreq(call, &req, 1, finish_read, tag);
Craig Tiller8eb9d472015-01-27 17:00:03 -08001506 unlock(call);
1507 return err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001508}
1509
Craig Tillercce17ac2015-01-20 09:29:28 -08001510static void finish_write(grpc_call *call, grpc_op_error status, void *tag) {
Craig Tillera4541102015-01-29 11:46:11 -08001511 lock(call);
1512 grpc_byte_buffer_destroy(get_legacy_state(call)->msg_out);
1513 unlock(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001514 grpc_cq_end_write_accepted(call->cq, tag, call, do_nothing, NULL, status);
1515}
1516
Craig Tiller40d2a432015-02-02 15:29:14 -08001517grpc_call_error grpc_call_start_write_old(grpc_call *call,
1518 grpc_byte_buffer *byte_buffer,
1519 void *tag, gpr_uint32 flags) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001520 grpc_ioreq req;
1521 legacy_state *ls;
Craig Tiller8eb9d472015-01-27 17:00:03 -08001522 grpc_call_error err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001523
1524 grpc_cq_begin_op(call->cq, call, GRPC_WRITE_ACCEPTED);
1525
Craig Tiller8eb9d472015-01-27 17:00:03 -08001526 lock(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001527 ls = get_legacy_state(call);
Craig Tillera4541102015-01-29 11:46:11 -08001528 ls->msg_out = grpc_byte_buffer_copy(byte_buffer);
Craig Tiller05140d02015-01-30 16:43:40 -08001529 req.op = GRPC_IOREQ_SEND_MESSAGE;
1530 req.data.send_message = ls->msg_out;
Craig Tiller9cc61412015-02-02 14:02:52 -08001531 err = start_ioreq(call, &req, 1, finish_write, tag);
Craig Tiller8eb9d472015-01-27 17:00:03 -08001532 unlock(call);
1533
1534 return err;
Craig Tillercce17ac2015-01-20 09:29:28 -08001535}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001536
Craig Tillercce17ac2015-01-20 09:29:28 -08001537static void finish_finish(grpc_call *call, grpc_op_error status, void *tag) {
1538 grpc_cq_end_finish_accepted(call->cq, tag, call, do_nothing, NULL, status);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001539}
1540
Craig Tiller40d2a432015-02-02 15:29:14 -08001541grpc_call_error grpc_call_writes_done_old(grpc_call *call, void *tag) {
Craig Tillercce17ac2015-01-20 09:29:28 -08001542 grpc_ioreq req;
Craig Tiller8eb9d472015-01-27 17:00:03 -08001543 grpc_call_error err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001544 grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED);
1545
Craig Tiller8eb9d472015-01-27 17:00:03 -08001546 lock(call);
Craig Tillercce17ac2015-01-20 09:29:28 -08001547 req.op = GRPC_IOREQ_SEND_CLOSE;
Craig Tiller9cc61412015-02-02 14:02:52 -08001548 err = start_ioreq(call, &req, 1, finish_finish, tag);
Craig Tiller8eb9d472015-01-27 17:00:03 -08001549 unlock(call);
1550
1551 return err;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001552}
1553
Craig Tiller40d2a432015-02-02 15:29:14 -08001554grpc_call_error grpc_call_start_write_status_old(grpc_call *call,
1555 grpc_status_code status,
1556 const char *details,
1557 void *tag) {
Craig Tiller05140d02015-01-30 16:43:40 -08001558 grpc_ioreq reqs[3];
Craig Tiller8eb9d472015-01-27 17:00:03 -08001559 grpc_call_error err;
Craig Tillerfa8f4012015-01-29 16:16:58 -08001560 legacy_state *ls;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001561 grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED);
1562
Craig Tiller8eb9d472015-01-27 17:00:03 -08001563 lock(call);
Craig Tillerfa8f4012015-01-29 16:16:58 -08001564 ls = get_legacy_state(call);
Craig Tillerf31d14c2015-01-28 09:26:42 -08001565 reqs[0].op = GRPC_IOREQ_SEND_TRAILING_METADATA;
Craig Tillerc689ca32015-01-30 10:59:52 -08001566 reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer];
1567 reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer];
Craig Tiller1c141902015-01-31 08:51:54 -08001568 reqs[1].op = GRPC_IOREQ_SEND_STATUS;
Craig Tiller05140d02015-01-30 16:43:40 -08001569 reqs[1].data.send_status.code = status;
Craig Tiller37bbead2015-02-05 08:43:49 -08001570 reqs[1].data.send_status.details = ls->send_details = gpr_strdup(details);
Craig Tiller1c141902015-01-31 08:51:54 -08001571 reqs[2].op = GRPC_IOREQ_SEND_CLOSE;
Craig Tiller9cc61412015-02-02 14:02:52 -08001572 err = start_ioreq(call, reqs, 3, finish_finish, tag);
Craig Tiller8eb9d472015-01-27 17:00:03 -08001573 unlock(call);
1574
1575 return err;
Craig Tiller190d3602015-02-18 09:23:38 -08001576}