1 /*
2 *
3 * Copyright 2015, Google Inc.
4 * 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 // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
35
36 // Because rust's union implementation is unstable and possibly buggy
37 // (rust-lang/rust#32836),
38 // so we need to wrap the type and expose more safer interfaces.
39
40 #include <grpc/support/port_platform.h>
41
42 #include <grpc/byte_buffer_reader.h>
43 #include <grpc/grpc.h>
44 #include <grpc/slice.h>
45 #include <grpc/support/alloc.h>
46 #include <grpc/support/log.h>
47 #include <grpc/support/string_util.h>
48 #include <grpc/support/thd_id.h>
49
50 #ifdef GRPC_SYS_SECURE
51 #include <grpc/grpc_security.h>
52 #endif
53
54 #include <string.h>
55
56 #ifdef GPR_WINDOWS
57 #define GPR_EXPORT extern "C" __declspec(dllexport)
58 #define GPR_CALLTYPE __cdecl
59 #endif
60
61 #ifndef GPR_EXPORT
62 #define GPR_EXPORT extern "C"
63 #endif
64
65 #ifndef GPR_CALLTYPE
66 #define GPR_CALLTYPE
67 #endif
68
string_to_byte_buffer(const char * buffer,size_t len)69 grpc_byte_buffer* string_to_byte_buffer(const char* buffer, size_t len) {
70 grpc_slice slice = grpc_slice_from_copied_buffer(buffer, len);
71 grpc_byte_buffer* bb = grpc_raw_byte_buffer_create(&slice, 1);
72 grpc_slice_unref(slice);
73 return bb;
74 }
75
76 /*
77 * Helper to maintain lifetime of batch op inputs and store batch op outputs.
78 */
79 typedef struct grpcwrap_batch_context {
80 grpc_metadata_array send_initial_metadata;
81 grpc_byte_buffer* send_message;
82 struct {
83 grpc_metadata_array trailing_metadata;
84 } send_status_from_server;
85 grpc_metadata_array recv_initial_metadata;
86 grpc_byte_buffer* recv_message;
87 struct {
88 grpc_metadata_array trailing_metadata;
89 grpc_status_code status;
90 grpc_slice status_details;
91 const char* error_string;
92 } recv_status_on_client;
93 int recv_close_on_server_cancelled;
94 } grpcwrap_batch_context;
95
96 GPR_EXPORT grpcwrap_batch_context* GPR_CALLTYPE
grpcwrap_batch_context_create()97 grpcwrap_batch_context_create() {
98 auto* ctx =
99 (grpcwrap_batch_context*)gpr_malloc(sizeof(grpcwrap_batch_context));
100 memset(ctx, 0, sizeof(grpcwrap_batch_context));
101 return ctx;
102 }
103
104 typedef struct {
105 grpc_call* call;
106 grpc_call_details call_details;
107 grpc_metadata_array request_metadata;
108 } grpcwrap_request_call_context;
109
110 GPR_EXPORT grpcwrap_request_call_context* GPR_CALLTYPE
grpcwrap_request_call_context_create()111 grpcwrap_request_call_context_create() {
112 auto* ctx = (grpcwrap_request_call_context*)gpr_malloc(
113 sizeof(grpcwrap_request_call_context));
114 memset(ctx, 0, sizeof(grpcwrap_request_call_context));
115 return ctx;
116 }
117
118 /*
119 * Destroys array->metadata.
120 * The array pointer itself is not freed.
121 */
grpcwrap_metadata_array_destroy_metadata_only(grpc_metadata_array * array)122 GPR_EXPORT void grpcwrap_metadata_array_destroy_metadata_only(
123 grpc_metadata_array* array) {
124 gpr_free(array->metadata);
125 }
126
127 /*
128 * Destroys keys, values and array->metadata.
129 * The array pointer itself is not freed.
130 */
grpcwrap_metadata_array_destroy_metadata_including_entries(grpc_metadata_array * array)131 GPR_EXPORT void grpcwrap_metadata_array_destroy_metadata_including_entries(
132 grpc_metadata_array* array) {
133 size_t i;
134 if (array->metadata) {
135 for (i = 0; i < array->count; i++) {
136 grpc_slice_unref(array->metadata[i].key);
137 grpc_slice_unref(array->metadata[i].value);
138 }
139 }
140 gpr_free(array->metadata);
141 }
142
143 /*
144 * Fully destroys the metadata array.
145 */
146 GPR_EXPORT void GPR_CALLTYPE
grpcwrap_metadata_array_destroy_full(grpc_metadata_array * array)147 grpcwrap_metadata_array_destroy_full(grpc_metadata_array* array) {
148 if (!array) {
149 return;
150 }
151 grpcwrap_metadata_array_destroy_metadata_including_entries(array);
152 gpr_free(array);
153 }
154
155 /*
156 * Allocate metadata array with given capacity.
157 */
158 GPR_EXPORT void GPR_CALLTYPE
grpcwrap_metadata_array_init(grpc_metadata_array * array,size_t capacity)159 grpcwrap_metadata_array_init(grpc_metadata_array* array, size_t capacity) {
160 array->count = 0;
161 array->capacity = capacity;
162 if (!capacity) {
163 array->metadata = nullptr;
164 return;
165 }
166
167 auto* arr = (grpc_metadata*)gpr_malloc(sizeof(grpc_metadata) * capacity);
168 memset(arr, 0, sizeof(grpc_metadata) * capacity);
169 array->metadata = arr;
170 }
171
grpcwrap_metadata_array_add(grpc_metadata_array * array,const char * key,size_t key_length,const char * value,size_t value_length)172 GPR_EXPORT void GPR_CALLTYPE grpcwrap_metadata_array_add(
173 grpc_metadata_array* array, const char* key, size_t key_length,
174 const char* value, size_t value_length) {
175 GPR_ASSERT(array->count <= array->capacity);
176 size_t i = array->count;
177 if (i == array->capacity) {
178 array->capacity = array->capacity ? array->capacity * 2 : 4;
179 array->metadata = (grpc_metadata*)gpr_realloc(
180 array->metadata, array->capacity * sizeof(grpc_metadata));
181 memset(array->metadata + i, 0,
182 sizeof(grpc_metadata) * (array->capacity - i));
183 }
184 array->metadata[i].key = grpc_slice_from_copied_buffer(key, key_length);
185 array->metadata[i].value = grpc_slice_from_copied_buffer(value, value_length);
186 array->count++;
187 }
188
grpcwrap_metadata_array_get_key(const grpc_metadata_array * array,size_t index,size_t * key_length)189 GPR_EXPORT const char* GPR_CALLTYPE grpcwrap_metadata_array_get_key(
190 const grpc_metadata_array* array, size_t index, size_t* key_length) {
191 GPR_ASSERT(index < array->count);
192 *key_length = GRPC_SLICE_LENGTH(array->metadata[index].key);
193 return (char*)GRPC_SLICE_START_PTR(array->metadata[index].key);
194 }
195
grpcwrap_metadata_array_get_value(const grpc_metadata_array * array,size_t index,size_t * value_length)196 GPR_EXPORT const char* GPR_CALLTYPE grpcwrap_metadata_array_get_value(
197 const grpc_metadata_array* array, size_t index, size_t* value_length) {
198 GPR_ASSERT(index < array->count);
199 *value_length = GRPC_SLICE_LENGTH(array->metadata[index].value);
200 return (char*)GRPC_SLICE_START_PTR(array->metadata[index].value);
201 }
202
203 GPR_EXPORT void GPR_CALLTYPE
grpcwrap_metadata_array_cleanup(grpc_metadata_array * array)204 grpcwrap_metadata_array_cleanup(grpc_metadata_array* array) {
205 grpcwrap_metadata_array_destroy_metadata_including_entries(array);
206 }
207
208 GPR_EXPORT void GPR_CALLTYPE
grpcwrap_metadata_array_shrink_to_fit(grpc_metadata_array * array)209 grpcwrap_metadata_array_shrink_to_fit(grpc_metadata_array* array) {
210 GPR_ASSERT(array->count <= array->capacity);
211 if (array->count == array->capacity) {
212 return;
213 }
214 if (array->count) {
215 array->metadata = (grpc_metadata*)gpr_realloc(
216 array->metadata, array->count * sizeof(grpc_metadata));
217 array->capacity = array->count;
218 } else {
219 grpcwrap_metadata_array_cleanup(array);
220 array->capacity = 0;
221 array->metadata = nullptr;
222 }
223 }
224
225 /* Move contents of metadata array */
grpcwrap_metadata_array_move(grpc_metadata_array * dest,grpc_metadata_array * src)226 GPR_EXPORT void grpcwrap_metadata_array_move(grpc_metadata_array* dest,
227 grpc_metadata_array* src) {
228 if (!src) {
229 dest->capacity = 0;
230 dest->count = 0;
231 dest->metadata = nullptr;
232 return;
233 }
234
235 dest->capacity = src->capacity;
236 dest->count = src->count;
237 dest->metadata = src->metadata;
238
239 src->capacity = 0;
240 src->count = 0;
241 src->metadata = nullptr;
242 }
243
244 GPR_EXPORT void GPR_CALLTYPE
grpcwrap_batch_context_destroy(grpcwrap_batch_context * ctx)245 grpcwrap_batch_context_destroy(grpcwrap_batch_context* ctx) {
246 if (!ctx) {
247 return;
248 }
249 grpcwrap_metadata_array_destroy_metadata_including_entries(
250 &(ctx->send_initial_metadata));
251
252 grpc_byte_buffer_destroy(ctx->send_message);
253
254 grpcwrap_metadata_array_destroy_metadata_including_entries(
255 &(ctx->send_status_from_server.trailing_metadata));
256
257 grpcwrap_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata));
258
259 grpc_byte_buffer_destroy(ctx->recv_message);
260
261 grpcwrap_metadata_array_destroy_metadata_only(
262 &(ctx->recv_status_on_client.trailing_metadata));
263 grpc_slice_unref(ctx->recv_status_on_client.status_details);
264 gpr_free((void*)ctx->recv_status_on_client.error_string);
265
266 gpr_free(ctx);
267 }
268
269 GPR_EXPORT void GPR_CALLTYPE
grpcwrap_request_call_context_destroy(grpcwrap_request_call_context * ctx)270 grpcwrap_request_call_context_destroy(grpcwrap_request_call_context* ctx) {
271 if (!ctx) {
272 return;
273 }
274
275 if (ctx->call) {
276 grpc_call_unref(ctx->call);
277 }
278
279 grpc_call_details_destroy(&(ctx->call_details));
280 grpcwrap_metadata_array_destroy_metadata_only(&(ctx->request_metadata));
281
282 gpr_free(ctx);
283 }
284
grpcwrap_batch_context_take_recv_initial_metadata(grpcwrap_batch_context * ctx,grpc_metadata_array * res)285 GPR_EXPORT void GPR_CALLTYPE grpcwrap_batch_context_take_recv_initial_metadata(
286 grpcwrap_batch_context* ctx, grpc_metadata_array* res) {
287 grpcwrap_metadata_array_move(res, &(ctx->recv_initial_metadata));
288 }
289
290 GPR_EXPORT void GPR_CALLTYPE
grpcwrap_batch_context_take_recv_status_on_client_trailing_metadata(grpcwrap_batch_context * ctx,grpc_metadata_array * res)291 grpcwrap_batch_context_take_recv_status_on_client_trailing_metadata(
292 grpcwrap_batch_context* ctx, grpc_metadata_array* res) {
293 grpcwrap_metadata_array_move(res,
294 &(ctx->recv_status_on_client.trailing_metadata));
295 }
296
297 GPR_EXPORT const char* GPR_CALLTYPE
grpcwrap_slice_raw_offset(const grpc_slice * slice,size_t offset,size_t * len)298 grpcwrap_slice_raw_offset(const grpc_slice* slice, size_t offset, size_t* len) {
299 *len = GRPC_SLICE_LENGTH(*slice) - offset;
300 return (const char*)(GRPC_SLICE_START_PTR(*slice)) + offset;
301 }
302
303 GPR_EXPORT grpc_slice GPR_CALLTYPE
grpcwrap_slice_copy(const grpc_slice * slice)304 grpcwrap_slice_copy(const grpc_slice* slice) {
305 return grpc_slice_copy(*slice);
306 }
307
grpcwrap_slice_unref(const grpc_slice * slice)308 GPR_EXPORT void GPR_CALLTYPE grpcwrap_slice_unref(const grpc_slice* slice) {
309 grpc_slice_unref(*slice);
310 }
311
grpcwrap_slice_ref(const grpc_slice * slice)312 GPR_EXPORT grpc_slice GPR_CALLTYPE grpcwrap_slice_ref(const grpc_slice* slice) {
313 return grpc_slice_ref(*slice);
314 }
315
grpcwrap_slice_length(const grpc_slice * slice)316 GPR_EXPORT size_t GPR_CALLTYPE grpcwrap_slice_length(const grpc_slice* slice) {
317 return GRPC_SLICE_LENGTH(*slice);
318 }
319
320 GPR_EXPORT grpc_byte_buffer* GPR_CALLTYPE
grpcwrap_batch_context_take_recv_message(grpcwrap_batch_context * ctx)321 grpcwrap_batch_context_take_recv_message(grpcwrap_batch_context* ctx) {
322 grpc_byte_buffer* buf = nullptr;
323 if (ctx->recv_message) {
324 buf = ctx->recv_message;
325 ctx->recv_message = nullptr;
326 }
327 return buf;
328 }
329
330 GPR_EXPORT grpc_status_code GPR_CALLTYPE
grpcwrap_batch_context_recv_status_on_client_status(const grpcwrap_batch_context * ctx)331 grpcwrap_batch_context_recv_status_on_client_status(
332 const grpcwrap_batch_context* ctx) {
333 return ctx->recv_status_on_client.status;
334 }
335
336 GPR_EXPORT const char* GPR_CALLTYPE
grpcwrap_batch_context_recv_status_on_client_details(const grpcwrap_batch_context * ctx,size_t * details_length)337 grpcwrap_batch_context_recv_status_on_client_details(
338 const grpcwrap_batch_context* ctx, size_t* details_length) {
339 *details_length =
340 GRPC_SLICE_LENGTH(ctx->recv_status_on_client.status_details);
341 return (char*)GRPC_SLICE_START_PTR(ctx->recv_status_on_client.status_details);
342 }
343
344 GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
grpcwrap_batch_context_recv_status_on_client_trailing_metadata(const grpcwrap_batch_context * ctx)345 grpcwrap_batch_context_recv_status_on_client_trailing_metadata(
346 const grpcwrap_batch_context* ctx) {
347 return &(ctx->recv_status_on_client.trailing_metadata);
348 }
349
350 GPR_EXPORT const char* GPR_CALLTYPE
grpcwrap_batch_context_recv_status_on_client_error_string(const grpcwrap_batch_context * ctx)351 grpcwrap_batch_context_recv_status_on_client_error_string(
352 const grpcwrap_batch_context* ctx) {
353 return ctx->recv_status_on_client.error_string;
354 }
355
356 GPR_EXPORT grpc_call* GPR_CALLTYPE
grpcwrap_request_call_context_ref_call(grpcwrap_request_call_context * ctx)357 grpcwrap_request_call_context_ref_call(grpcwrap_request_call_context* ctx) {
358 grpc_call* call = ctx->call;
359 grpc_call_ref(call);
360 return call;
361 }
362
363 GPR_EXPORT grpc_call* GPR_CALLTYPE
grpcwrap_request_call_context_get_call(grpcwrap_request_call_context * ctx)364 grpcwrap_request_call_context_get_call(grpcwrap_request_call_context* ctx) {
365 return ctx->call;
366 }
367
grpcwrap_request_call_context_method(const grpcwrap_request_call_context * ctx,size_t * method_length)368 GPR_EXPORT const char* GPR_CALLTYPE grpcwrap_request_call_context_method(
369 const grpcwrap_request_call_context* ctx, size_t* method_length) {
370 *method_length = GRPC_SLICE_LENGTH(ctx->call_details.method);
371 return (char*)GRPC_SLICE_START_PTR(ctx->call_details.method);
372 }
373
grpcwrap_request_call_context_host(const grpcwrap_request_call_context * ctx,size_t * host_length)374 GPR_EXPORT const char* GPR_CALLTYPE grpcwrap_request_call_context_host(
375 const grpcwrap_request_call_context* ctx, size_t* host_length) {
376 *host_length = GRPC_SLICE_LENGTH(ctx->call_details.host);
377 return (char*)GRPC_SLICE_START_PTR(ctx->call_details.host);
378 }
379
grpcwrap_request_call_context_deadline(const grpcwrap_request_call_context * ctx)380 GPR_EXPORT gpr_timespec GPR_CALLTYPE grpcwrap_request_call_context_deadline(
381 const grpcwrap_request_call_context* ctx) {
382 return ctx->call_details.deadline;
383 }
384
385 GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
grpcwrap_request_call_context_metadata_array(const grpcwrap_request_call_context * ctx)386 grpcwrap_request_call_context_metadata_array(
387 const grpcwrap_request_call_context* ctx) {
388 return &(ctx->request_metadata);
389 }
390
391 GPR_EXPORT int32_t GPR_CALLTYPE
grpcwrap_batch_context_recv_close_on_server_cancelled(const grpcwrap_batch_context * ctx)392 grpcwrap_batch_context_recv_close_on_server_cancelled(
393 const grpcwrap_batch_context* ctx) {
394 return (int32_t)ctx->recv_close_on_server_cancelled;
395 }
396
397 /* Channel */
398
grpcwrap_channel_create_call(grpc_channel * channel,grpc_call * parent_call,uint32_t propagation_mask,grpc_completion_queue * cq,const char * method,size_t method_len,const char * host,size_t host_len,gpr_timespec deadline)399 GPR_EXPORT grpc_call* GPR_CALLTYPE grpcwrap_channel_create_call(
400 grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
401 grpc_completion_queue* cq, const char* method, size_t method_len,
402 const char* host, size_t host_len, gpr_timespec deadline) {
403 grpc_slice method_slice = grpc_slice_from_copied_buffer(method, method_len);
404 grpc_slice* host_slice_ptr = nullptr;
405 grpc_slice host_slice;
406 if (host != nullptr) {
407 host_slice = grpc_slice_from_copied_buffer(host, host_len);
408 host_slice_ptr = &host_slice;
409 } else {
410 // to silent msvc false warning
411 host_slice = grpc_empty_slice();
412 }
413 grpc_call* ret =
414 grpc_channel_create_call(channel, parent_call, propagation_mask, cq,
415 method_slice, host_slice_ptr, deadline, nullptr);
416 grpc_slice_unref(method_slice);
417 if (host != nullptr) {
418 grpc_slice_unref(host_slice);
419 }
420 return ret;
421 }
422
423 /* Channel args */
424
425 GPR_EXPORT grpc_channel_args* GPR_CALLTYPE
grpcwrap_channel_args_create(size_t num_args)426 grpcwrap_channel_args_create(size_t num_args) {
427 auto* args = (grpc_channel_args*)gpr_malloc(sizeof(grpc_channel_args));
428 memset(args, 0, sizeof(grpc_channel_args));
429
430 args->num_args = num_args;
431 args->args = (grpc_arg*)gpr_malloc(sizeof(grpc_arg) * num_args);
432 memset(args->args, 0, sizeof(grpc_arg) * num_args);
433 return args;
434 }
435
grpcwrap_channel_args_set_string(grpc_channel_args * args,size_t index,const char * key,const char * value)436 GPR_EXPORT void GPR_CALLTYPE grpcwrap_channel_args_set_string(
437 grpc_channel_args* args, size_t index, const char* key, const char* value) {
438 GPR_ASSERT(args);
439 GPR_ASSERT(index < args->num_args);
440 args->args[index].type = GRPC_ARG_STRING;
441 args->args[index].key = gpr_strdup(key);
442 args->args[index].value.string = gpr_strdup(value);
443 }
444
grpcwrap_channel_args_set_integer(grpc_channel_args * args,size_t index,const char * key,int value)445 GPR_EXPORT void GPR_CALLTYPE grpcwrap_channel_args_set_integer(
446 grpc_channel_args* args, size_t index, const char* key, int value) {
447 GPR_ASSERT(args);
448 GPR_ASSERT(index < args->num_args);
449 args->args[index].type = GRPC_ARG_INTEGER;
450 args->args[index].key = gpr_strdup(key);
451 args->args[index].value.integer = value;
452 }
453
grpcwrap_channel_args_set_pointer_vtable(grpc_channel_args * args,size_t index,const char * key,void * value,const grpc_arg_pointer_vtable * vtable)454 GPR_EXPORT void GPR_CALLTYPE grpcwrap_channel_args_set_pointer_vtable(
455 grpc_channel_args* args, size_t index, const char* key, void* value,
456 const grpc_arg_pointer_vtable* vtable) {
457 GPR_ASSERT(args);
458 GPR_ASSERT(index < args->num_args);
459 args->args[index].type = GRPC_ARG_POINTER;
460 args->args[index].key = gpr_strdup(key);
461 args->args[index].value.pointer.p = vtable->copy(value);
462 args->args[index].value.pointer.vtable = vtable;
463 }
464
465 GPR_EXPORT void GPR_CALLTYPE
grpcwrap_channel_args_destroy(grpc_channel_args * args)466 grpcwrap_channel_args_destroy(grpc_channel_args* args) {
467 size_t i;
468 if (args) {
469 for (i = 0; i < args->num_args; i++) {
470 gpr_free(args->args[i].key);
471 if (args->args[i].type == GRPC_ARG_STRING) {
472 gpr_free(args->args[i].value.string);
473 }
474 if (args->args[i].type == GRPC_ARG_POINTER) {
475 args->args[i].value.pointer.vtable->destroy(
476 args->args[i].value.pointer.p);
477 }
478 }
479 gpr_free(args->args);
480 gpr_free(args);
481 }
482 }
483
484 /* Call */
485
grpcwrap_call_start_unary(grpc_call * call,grpcwrap_batch_context * ctx,grpc_slice * send_buffer,uint32_t write_flags,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags,void * tag)486 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_start_unary(
487 grpc_call* call, grpcwrap_batch_context* ctx, grpc_slice* send_buffer,
488 uint32_t write_flags, grpc_metadata_array* initial_metadata,
489 uint32_t initial_metadata_flags, void* tag) {
490 /* TODO: don't use magic number */
491 grpc_op ops[6];
492 memset(ops, 0, sizeof(ops));
493 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
494 grpcwrap_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata);
495 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
496 ops[0].data.send_initial_metadata.metadata =
497 ctx->send_initial_metadata.metadata;
498 ops[0].flags = initial_metadata_flags;
499 ops[0].reserved = nullptr;
500
501 ops[1].op = GRPC_OP_SEND_MESSAGE;
502 ctx->send_message = grpc_raw_byte_buffer_create(send_buffer, 1);
503 ops[1].data.send_message.send_message = ctx->send_message;
504 ops[1].flags = write_flags;
505 ops[1].reserved = nullptr;
506
507 ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
508 ops[2].flags = 0;
509 ops[2].reserved = nullptr;
510
511 ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
512 ops[3].data.recv_initial_metadata.recv_initial_metadata =
513 &(ctx->recv_initial_metadata);
514 ops[3].flags = 0;
515 ops[3].reserved = nullptr;
516
517 ops[4].op = GRPC_OP_RECV_MESSAGE;
518 ops[4].data.recv_message.recv_message = &(ctx->recv_message);
519 ops[4].flags = 0;
520 ops[4].reserved = nullptr;
521
522 ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
523 ops[5].data.recv_status_on_client.trailing_metadata =
524 &(ctx->recv_status_on_client.trailing_metadata);
525 ops[5].data.recv_status_on_client.status =
526 &(ctx->recv_status_on_client.status);
527 ops[5].data.recv_status_on_client.status_details =
528 &(ctx->recv_status_on_client.status_details);
529 ops[5].data.recv_status_on_client.error_string =
530 &(ctx->recv_status_on_client.error_string);
531 ops[5].flags = 0;
532 ops[5].reserved = nullptr;
533
534 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
535 nullptr);
536 }
537
grpcwrap_call_start_client_streaming(grpc_call * call,grpcwrap_batch_context * ctx,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags,void * tag)538 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_start_client_streaming(
539 grpc_call* call, grpcwrap_batch_context* ctx,
540 grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags,
541 void* tag) {
542 /* TODO: don't use magic number */
543 grpc_op ops[4];
544 memset(ops, 0, sizeof(ops));
545 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
546 grpcwrap_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata);
547 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
548 ops[0].data.send_initial_metadata.metadata =
549 ctx->send_initial_metadata.metadata;
550 ops[0].flags = initial_metadata_flags;
551 ops[0].reserved = nullptr;
552
553 ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
554 ops[1].data.recv_initial_metadata.recv_initial_metadata =
555 &(ctx->recv_initial_metadata);
556 ops[1].flags = 0;
557 ops[1].reserved = nullptr;
558
559 ops[2].op = GRPC_OP_RECV_MESSAGE;
560 ops[2].data.recv_message.recv_message = &(ctx->recv_message);
561 ops[2].flags = 0;
562 ops[2].reserved = nullptr;
563
564 ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
565 ops[3].data.recv_status_on_client.trailing_metadata =
566 &(ctx->recv_status_on_client.trailing_metadata);
567 ops[3].data.recv_status_on_client.status =
568 &(ctx->recv_status_on_client.status);
569 ops[3].data.recv_status_on_client.status_details =
570 &(ctx->recv_status_on_client.status_details);
571 ops[3].data.recv_status_on_client.error_string =
572 &(ctx->recv_status_on_client.error_string);
573 ops[3].flags = 0;
574 ops[3].reserved = nullptr;
575
576 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
577 nullptr);
578 }
579
grpcwrap_call_start_server_streaming(grpc_call * call,grpcwrap_batch_context * ctx,grpc_slice * send_buffer,uint32_t write_flags,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags,void * tag)580 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_start_server_streaming(
581 grpc_call* call, grpcwrap_batch_context* ctx, grpc_slice* send_buffer,
582 uint32_t write_flags, grpc_metadata_array* initial_metadata,
583 uint32_t initial_metadata_flags, void* tag) {
584 /* TODO: don't use magic number */
585 grpc_op ops[4];
586 memset(ops, 0, sizeof(ops));
587 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
588 grpcwrap_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata);
589 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
590 ops[0].data.send_initial_metadata.metadata =
591 ctx->send_initial_metadata.metadata;
592 ops[0].flags = initial_metadata_flags;
593 ops[0].reserved = nullptr;
594
595 ops[1].op = GRPC_OP_SEND_MESSAGE;
596 ctx->send_message = grpc_raw_byte_buffer_create(send_buffer, 1);
597 ops[1].data.send_message.send_message = ctx->send_message;
598 ops[1].flags = write_flags;
599 ops[1].reserved = nullptr;
600
601 ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
602 ops[2].flags = 0;
603 ops[2].reserved = nullptr;
604
605 ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
606 ops[3].data.recv_status_on_client.trailing_metadata =
607 &(ctx->recv_status_on_client.trailing_metadata);
608 ops[3].data.recv_status_on_client.status =
609 &(ctx->recv_status_on_client.status);
610 ops[3].data.recv_status_on_client.status_details =
611 &(ctx->recv_status_on_client.status_details);
612 ops[3].data.recv_status_on_client.error_string =
613 &(ctx->recv_status_on_client.error_string);
614 ops[3].flags = 0;
615 ops[3].reserved = nullptr;
616
617 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
618 nullptr);
619 }
620
grpcwrap_call_start_duplex_streaming(grpc_call * call,grpcwrap_batch_context * ctx,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags,void * tag)621 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_start_duplex_streaming(
622 grpc_call* call, grpcwrap_batch_context* ctx,
623 grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags,
624 void* tag) {
625 /* TODO: don't use magic number */
626 grpc_op ops[2];
627 memset(ops, 0, sizeof(ops));
628 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
629 grpcwrap_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata);
630 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
631 ops[0].data.send_initial_metadata.metadata =
632 ctx->send_initial_metadata.metadata;
633 ops[0].flags = initial_metadata_flags;
634 ops[0].reserved = nullptr;
635
636 ops[1].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
637 ops[1].data.recv_status_on_client.trailing_metadata =
638 &(ctx->recv_status_on_client.trailing_metadata);
639 ops[1].data.recv_status_on_client.status =
640 &(ctx->recv_status_on_client.status);
641 ops[1].data.recv_status_on_client.status_details =
642 &(ctx->recv_status_on_client.status_details);
643 ops[1].data.recv_status_on_client.error_string =
644 &(ctx->recv_status_on_client.error_string);
645 ops[1].flags = 0;
646 ops[1].reserved = nullptr;
647
648 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
649 nullptr);
650 }
651
grpcwrap_call_recv_initial_metadata(grpc_call * call,grpcwrap_batch_context * ctx,void * tag)652 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_recv_initial_metadata(
653 grpc_call* call, grpcwrap_batch_context* ctx, void* tag) {
654 /* TODO: don't use magic number */
655 grpc_op ops[1];
656 ops[0].op = GRPC_OP_RECV_INITIAL_METADATA;
657 ops[0].data.recv_initial_metadata.recv_initial_metadata =
658 &(ctx->recv_initial_metadata);
659 ops[0].flags = 0;
660 ops[0].reserved = nullptr;
661
662 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
663 nullptr);
664 }
665
grpcwrap_call_send_message(grpc_call * call,grpcwrap_batch_context * ctx,grpc_slice * send_buffer,uint32_t write_flags,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags,void * tag)666 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_send_message(
667 grpc_call* call, grpcwrap_batch_context* ctx, grpc_slice* send_buffer,
668 uint32_t write_flags, grpc_metadata_array* initial_metadata,
669 uint32_t initial_metadata_flags, void* tag) {
670 /* TODO: don't use magic number */
671 grpc_op ops[2];
672 memset(ops, 0, sizeof(ops));
673 size_t nops = 1;
674
675 ops[0].op = GRPC_OP_SEND_MESSAGE;
676 ctx->send_message = grpc_raw_byte_buffer_create(send_buffer, 1);
677 ops[0].data.send_message.send_message = ctx->send_message;
678 ops[0].flags = write_flags;
679 ops[0].reserved = nullptr;
680
681 if (initial_metadata) {
682 ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA;
683 grpcwrap_metadata_array_move(&(ctx->send_initial_metadata),
684 initial_metadata);
685 ops[nops].data.send_initial_metadata.count =
686 ctx->send_initial_metadata.count;
687 ops[nops].data.send_initial_metadata.metadata =
688 ctx->send_initial_metadata.metadata;
689 ops[nops].flags = initial_metadata_flags;
690 ops[nops].reserved = nullptr;
691 nops++;
692 }
693 return grpc_call_start_batch(call, ops, nops, tag, nullptr);
694 }
695
696 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcwrap_call_send_close_from_client(grpc_call * call,void * tag)697 grpcwrap_call_send_close_from_client(grpc_call* call, void* tag) {
698 /* TODO: don't use magic number */
699 grpc_op ops[1];
700 ops[0].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
701 ops[0].flags = 0;
702 ops[0].reserved = nullptr;
703
704 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
705 nullptr);
706 }
707
grpcwrap_call_send_status_from_server(grpc_call * call,grpcwrap_batch_context * ctx,grpc_status_code status_code,const char * status_details,size_t status_details_len,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags,grpc_metadata_array * trailing_metadata,grpc_slice * optional_send_buffer,uint32_t write_flags,void * tag)708 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_send_status_from_server(
709 grpc_call* call, grpcwrap_batch_context* ctx, grpc_status_code status_code,
710 const char* status_details, size_t status_details_len,
711 grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags,
712 grpc_metadata_array* trailing_metadata, grpc_slice* optional_send_buffer,
713 uint32_t write_flags, void* tag) {
714 /* TODO: don't use magic number */
715 grpc_op ops[3];
716 memset(ops, 0, sizeof(ops));
717 size_t nops = 1;
718
719 grpc_slice status_details_slice =
720 grpc_slice_from_copied_buffer(status_details, status_details_len);
721
722 ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
723 ops[0].data.send_status_from_server.status = status_code;
724 ops[0].data.send_status_from_server.status_details = &status_details_slice;
725 grpcwrap_metadata_array_move(
726 &(ctx->send_status_from_server.trailing_metadata), trailing_metadata);
727 ops[0].data.send_status_from_server.trailing_metadata_count =
728 ctx->send_status_from_server.trailing_metadata.count;
729 ops[0].data.send_status_from_server.trailing_metadata =
730 ctx->send_status_from_server.trailing_metadata.metadata;
731 ops[0].flags = 0;
732 ops[0].reserved = nullptr;
733
734 if (optional_send_buffer) {
735 ops[nops].op = GRPC_OP_SEND_MESSAGE;
736 ctx->send_message = grpc_raw_byte_buffer_create(optional_send_buffer, 1);
737 ops[nops].data.send_message.send_message = ctx->send_message;
738 ops[nops].flags = write_flags;
739 ops[nops].reserved = nullptr;
740 nops++;
741 }
742 if (initial_metadata) {
743 ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA;
744 grpcwrap_metadata_array_move(&(ctx->send_initial_metadata),
745 initial_metadata);
746 ops[nops].data.send_initial_metadata.count =
747 ctx->send_initial_metadata.count;
748 ops[nops].data.send_initial_metadata.metadata =
749 ctx->send_initial_metadata.metadata;
750 ops[nops].flags = initial_metadata_flags;
751 ops[nops].reserved = nullptr;
752 nops++;
753 }
754
755 grpc_call_error ret = grpc_call_start_batch(call, ops, nops, tag, nullptr);
756 grpc_slice_unref(status_details_slice);
757 return ret;
758 }
759
grpcwrap_call_recv_message(grpc_call * call,grpcwrap_batch_context * ctx,void * tag)760 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_recv_message(
761 grpc_call* call, grpcwrap_batch_context* ctx, void* tag) {
762 /* TODO: don't use magic number */
763 grpc_op ops[1];
764 ops[0].op = GRPC_OP_RECV_MESSAGE;
765 ops[0].data.recv_message.recv_message = &(ctx->recv_message);
766 ops[0].flags = 0;
767 ops[0].reserved = nullptr;
768 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
769 nullptr);
770 }
771
grpcwrap_call_start_serverside(grpc_call * call,grpcwrap_batch_context * ctx,void * tag)772 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_start_serverside(
773 grpc_call* call, grpcwrap_batch_context* ctx, void* tag) {
774 /* TODO: don't use magic number */
775 grpc_op ops[1];
776 ops[0].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
777 ops[0].data.recv_close_on_server.cancelled =
778 (&ctx->recv_close_on_server_cancelled);
779 ops[0].flags = 0;
780 ops[0].reserved = nullptr;
781
782 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
783 nullptr);
784 }
785
grpcwrap_call_send_initial_metadata(grpc_call * call,grpcwrap_batch_context * ctx,grpc_metadata_array * initial_metadata,void * tag)786 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcwrap_call_send_initial_metadata(
787 grpc_call* call, grpcwrap_batch_context* ctx,
788 grpc_metadata_array* initial_metadata, void* tag) {
789 /* TODO: don't use magic number */
790 grpc_op ops[1];
791 memset(ops, 0, sizeof(ops));
792 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
793 grpcwrap_metadata_array_move(&(ctx->send_initial_metadata), initial_metadata);
794 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
795 ops[0].data.send_initial_metadata.metadata =
796 ctx->send_initial_metadata.metadata;
797 ops[0].flags = 0;
798 ops[0].reserved = nullptr;
799
800 return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), tag,
801 nullptr);
802 }
803
804 /** Kick call's completion queue, it should be called after there is an event
805 ready to poll.
806 THREAD SAFETY: grpcwrap_call_kick_completion_queue is thread-safe
807 because it does not change the call's state. */
808 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcwrap_call_kick_completion_queue(grpc_call * call,void * tag)809 grpcwrap_call_kick_completion_queue(grpc_call* call, void* tag) {
810 // Empty batch grpc_op kicks call's completion queue immediately.
811 return grpc_call_start_batch(call, nullptr, 0, tag, nullptr);
812 }
813
814 /* Server */
815
816 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcwrap_server_request_call(grpc_server * server,grpc_completion_queue * cq,grpcwrap_request_call_context * ctx,void * tag)817 grpcwrap_server_request_call(grpc_server* server, grpc_completion_queue* cq,
818 grpcwrap_request_call_context* ctx, void* tag) {
819 return grpc_server_request_call(server, &(ctx->call), &(ctx->call_details),
820 &(ctx->request_metadata), cq, cq, tag);
821 }
822