1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <grpc/byte_buffer_reader.h>
20 #include <grpc/grpc.h>
21 #include <grpc/grpc_security.h>
22 #include <grpc/slice.h>
23 #include <grpc/support/alloc.h>
24 #include <grpc/support/log.h>
25 #include <grpc/support/port_platform.h>
26 #include <grpc/support/string_util.h>
27 #include <grpc/support/thd_id.h>
28
29 #include <string.h>
30
31 #ifdef GPR_WINDOWS
32 #define GPR_EXPORT __declspec(dllexport)
33 #define GPR_CALLTYPE __stdcall
34 #endif
35
36 #ifndef GPR_EXPORT
37 #define GPR_EXPORT
38 #endif
39
40 #ifndef GPR_CALLTYPE
41 #define GPR_CALLTYPE
42 #endif
43
grpcsharp_create_byte_buffer_from_stolen_slices(grpc_slice_buffer * slice_buffer)44 static grpc_byte_buffer* grpcsharp_create_byte_buffer_from_stolen_slices(
45 grpc_slice_buffer* slice_buffer) {
46 grpc_byte_buffer* bb =
47 (grpc_byte_buffer*)gpr_zalloc(sizeof(grpc_byte_buffer));
48 bb->type = GRPC_BB_RAW;
49 bb->data.raw.compression = GRPC_COMPRESS_NONE;
50 grpc_slice_buffer_init(&bb->data.raw.slice_buffer);
51
52 grpc_slice_buffer_swap(&bb->data.raw.slice_buffer, slice_buffer);
53 return bb;
54 }
55
56 /*
57 * Helper to maintain lifetime of batch op inputs and store batch op outputs.
58 */
59 typedef struct grpcsharp_batch_context {
60 grpc_metadata_array send_initial_metadata;
61 grpc_byte_buffer* send_message;
62 struct {
63 grpc_metadata_array trailing_metadata;
64 } send_status_from_server;
65 grpc_metadata_array recv_initial_metadata;
66 grpc_byte_buffer* recv_message;
67 grpc_byte_buffer_reader* recv_message_reader;
68 struct {
69 grpc_metadata_array trailing_metadata;
70 grpc_status_code status;
71 grpc_slice status_details;
72 const char* error_string;
73 } recv_status_on_client;
74 int recv_close_on_server_cancelled;
75
76 /* reserve space for byte_buffer_reader */
77 grpc_byte_buffer_reader reserved_recv_message_reader;
78 } grpcsharp_batch_context;
79
80 GPR_EXPORT grpcsharp_batch_context* GPR_CALLTYPE
grpcsharp_batch_context_create()81 grpcsharp_batch_context_create() {
82 grpcsharp_batch_context* ctx = gpr_malloc(sizeof(grpcsharp_batch_context));
83 memset(ctx, 0, sizeof(grpcsharp_batch_context));
84 return ctx;
85 }
86
87 typedef struct {
88 grpc_call* call;
89 grpc_call_details call_details;
90 grpc_metadata_array request_metadata;
91 } grpcsharp_request_call_context;
92
93 GPR_EXPORT grpcsharp_request_call_context* GPR_CALLTYPE
grpcsharp_request_call_context_create()94 grpcsharp_request_call_context_create() {
95 grpcsharp_request_call_context* ctx =
96 gpr_malloc(sizeof(grpcsharp_request_call_context));
97 memset(ctx, 0, sizeof(grpcsharp_request_call_context));
98 return ctx;
99 }
100
101 /*
102 * Destroys array->metadata.
103 * The array pointer itself is not freed.
104 */
grpcsharp_metadata_array_destroy_metadata_only(grpc_metadata_array * array)105 void grpcsharp_metadata_array_destroy_metadata_only(
106 grpc_metadata_array* array) {
107 gpr_free(array->metadata);
108 }
109
110 /*
111 * Destroys keys, values and array->metadata.
112 * The array pointer itself is not freed.
113 */
grpcsharp_metadata_array_destroy_metadata_including_entries(grpc_metadata_array * array)114 void grpcsharp_metadata_array_destroy_metadata_including_entries(
115 grpc_metadata_array* array) {
116 size_t i;
117 if (array->metadata) {
118 for (i = 0; i < array->count; i++) {
119 grpc_slice_unref(array->metadata[i].key);
120 grpc_slice_unref(array->metadata[i].value);
121 }
122 }
123 gpr_free(array->metadata);
124 }
125
126 /*
127 * Fully destroys the metadata array.
128 */
129 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_metadata_array_destroy_full(grpc_metadata_array * array)130 grpcsharp_metadata_array_destroy_full(grpc_metadata_array* array) {
131 if (!array) {
132 return;
133 }
134 grpcsharp_metadata_array_destroy_metadata_including_entries(array);
135 gpr_free(array);
136 }
137
138 /*
139 * Creates an empty metadata array with given capacity.
140 * Array can later be destroyed by grpc_metadata_array_destroy_full.
141 */
142 GPR_EXPORT grpc_metadata_array* GPR_CALLTYPE
grpcsharp_metadata_array_create(size_t capacity)143 grpcsharp_metadata_array_create(size_t capacity) {
144 grpc_metadata_array* array =
145 (grpc_metadata_array*)gpr_malloc(sizeof(grpc_metadata_array));
146 grpc_metadata_array_init(array);
147 array->capacity = capacity;
148 array->count = 0;
149 if (capacity > 0) {
150 array->metadata =
151 (grpc_metadata*)gpr_malloc(sizeof(grpc_metadata) * capacity);
152 memset(array->metadata, 0, sizeof(grpc_metadata) * capacity);
153 } else {
154 array->metadata = NULL;
155 }
156 return array;
157 }
158
159 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_metadata_array_add(grpc_metadata_array * array,const char * key,const char * value,size_t value_length)160 grpcsharp_metadata_array_add(grpc_metadata_array* array, const char* key,
161 const char* value, size_t value_length) {
162 size_t i = array->count;
163 GPR_ASSERT(array->count < array->capacity);
164 array->metadata[i].key = grpc_slice_from_copied_string(key);
165 array->metadata[i].value = grpc_slice_from_copied_buffer(value, value_length);
166 array->count++;
167 }
168
169 GPR_EXPORT intptr_t GPR_CALLTYPE
grpcsharp_metadata_array_count(grpc_metadata_array * array)170 grpcsharp_metadata_array_count(grpc_metadata_array* array) {
171 return (intptr_t)array->count;
172 }
173
grpcsharp_metadata_array_get_key(grpc_metadata_array * array,size_t index,size_t * key_length)174 GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_metadata_array_get_key(
175 grpc_metadata_array* array, size_t index, size_t* key_length) {
176 GPR_ASSERT(index < array->count);
177 *key_length = GRPC_SLICE_LENGTH(array->metadata[index].key);
178 return (char*)GRPC_SLICE_START_PTR(array->metadata[index].key);
179 }
180
grpcsharp_metadata_array_get_value(grpc_metadata_array * array,size_t index,size_t * value_length)181 GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_metadata_array_get_value(
182 grpc_metadata_array* array, size_t index, size_t* value_length) {
183 GPR_ASSERT(index < array->count);
184 *value_length = GRPC_SLICE_LENGTH(array->metadata[index].value);
185 return (char*)GRPC_SLICE_START_PTR(array->metadata[index].value);
186 }
187
188 /* Move contents of metadata array */
grpcsharp_metadata_array_move(grpc_metadata_array * dest,grpc_metadata_array * src)189 void grpcsharp_metadata_array_move(grpc_metadata_array* dest,
190 grpc_metadata_array* src) {
191 if (!src) {
192 dest->capacity = 0;
193 dest->count = 0;
194 dest->metadata = NULL;
195 return;
196 }
197
198 dest->capacity = src->capacity;
199 dest->count = src->count;
200 dest->metadata = src->metadata;
201
202 src->capacity = 0;
203 src->count = 0;
204 src->metadata = NULL;
205 }
206
207 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_batch_context_reset(grpcsharp_batch_context * ctx)208 grpcsharp_batch_context_reset(grpcsharp_batch_context* ctx) {
209 grpcsharp_metadata_array_destroy_metadata_including_entries(
210 &(ctx->send_initial_metadata));
211
212 grpc_byte_buffer_destroy(ctx->send_message);
213
214 grpcsharp_metadata_array_destroy_metadata_including_entries(
215 &(ctx->send_status_from_server.trailing_metadata));
216
217 grpcsharp_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata));
218
219 if (ctx->recv_message_reader) {
220 grpc_byte_buffer_reader_destroy(ctx->recv_message_reader);
221 }
222 grpc_byte_buffer_destroy(ctx->recv_message);
223
224 grpcsharp_metadata_array_destroy_metadata_only(
225 &(ctx->recv_status_on_client.trailing_metadata));
226 grpc_slice_unref(ctx->recv_status_on_client.status_details);
227 gpr_free((void*)ctx->recv_status_on_client.error_string);
228 memset(ctx, 0, sizeof(grpcsharp_batch_context));
229 }
230
231 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_batch_context_destroy(grpcsharp_batch_context * ctx)232 grpcsharp_batch_context_destroy(grpcsharp_batch_context* ctx) {
233 if (!ctx) {
234 return;
235 }
236 grpcsharp_batch_context_reset(ctx);
237 gpr_free(ctx);
238 }
239
240 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_request_call_context_reset(grpcsharp_request_call_context * ctx)241 grpcsharp_request_call_context_reset(grpcsharp_request_call_context* ctx) {
242 /* NOTE: ctx->server_rpc_new.call is not destroyed because callback handler is
243 supposed
244 to take its ownership. */
245
246 grpc_call_details_destroy(&(ctx->call_details));
247 grpcsharp_metadata_array_destroy_metadata_only(&(ctx->request_metadata));
248 memset(ctx, 0, sizeof(grpcsharp_request_call_context));
249 }
250
251 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_request_call_context_destroy(grpcsharp_request_call_context * ctx)252 grpcsharp_request_call_context_destroy(grpcsharp_request_call_context* ctx) {
253 if (!ctx) {
254 return;
255 }
256 grpcsharp_request_call_context_reset(ctx);
257 gpr_free(ctx);
258 }
259
260 GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
grpcsharp_batch_context_recv_initial_metadata(const grpcsharp_batch_context * ctx)261 grpcsharp_batch_context_recv_initial_metadata(
262 const grpcsharp_batch_context* ctx) {
263 return &(ctx->recv_initial_metadata);
264 }
265
grpcsharp_batch_context_recv_message_length(const grpcsharp_batch_context * ctx)266 GPR_EXPORT intptr_t GPR_CALLTYPE grpcsharp_batch_context_recv_message_length(
267 const grpcsharp_batch_context* ctx) {
268 grpc_byte_buffer_reader reader;
269 if (!ctx->recv_message) {
270 return -1;
271 }
272
273 GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, ctx->recv_message));
274 intptr_t result = (intptr_t)grpc_byte_buffer_length(reader.buffer_out);
275 grpc_byte_buffer_reader_destroy(&reader);
276
277 return result;
278 }
279
280 /*
281 * Gets the next slice from recv_message byte buffer.
282 * Returns 1 if a slice was get successfully, 0 if there are no more slices to
283 * read. Set slice_len to the length of the slice and the slice_data_ptr to
284 * point to slice's data. Caller must ensure that the byte buffer being read
285 * from stays alive as long as the data of the slice are being accessed
286 * (grpc_byte_buffer_reader_peek method is used internally)
287 *
288 * Remarks:
289 * Slices can only be iterated once.
290 * Initializes recv_message_buffer_reader if it was not initialized yet.
291 */
292 GPR_EXPORT int GPR_CALLTYPE
grpcsharp_batch_context_recv_message_next_slice_peek(grpcsharp_batch_context * ctx,size_t * slice_len,uint8_t ** slice_data_ptr)293 grpcsharp_batch_context_recv_message_next_slice_peek(
294 grpcsharp_batch_context* ctx, size_t* slice_len, uint8_t** slice_data_ptr) {
295 *slice_len = 0;
296 *slice_data_ptr = NULL;
297
298 if (!ctx->recv_message) {
299 return 0;
300 }
301
302 if (!ctx->recv_message_reader) {
303 ctx->recv_message_reader = &ctx->reserved_recv_message_reader;
304 GPR_ASSERT(grpc_byte_buffer_reader_init(ctx->recv_message_reader,
305 ctx->recv_message));
306 }
307
308 grpc_slice* slice_ptr;
309 if (!grpc_byte_buffer_reader_peek(ctx->recv_message_reader, &slice_ptr)) {
310 return 0;
311 }
312
313 /* recv_message buffer must not be deleted before all the data is read */
314 *slice_len = GRPC_SLICE_LENGTH(*slice_ptr);
315 *slice_data_ptr = GRPC_SLICE_START_PTR(*slice_ptr);
316 return 1;
317 }
318
319 GPR_EXPORT grpc_status_code GPR_CALLTYPE
grpcsharp_batch_context_recv_status_on_client_status(const grpcsharp_batch_context * ctx)320 grpcsharp_batch_context_recv_status_on_client_status(
321 const grpcsharp_batch_context* ctx) {
322 return ctx->recv_status_on_client.status;
323 }
324
325 GPR_EXPORT const char* GPR_CALLTYPE
grpcsharp_batch_context_recv_status_on_client_details(const grpcsharp_batch_context * ctx,size_t * details_length)326 grpcsharp_batch_context_recv_status_on_client_details(
327 const grpcsharp_batch_context* ctx, size_t* details_length) {
328 *details_length =
329 GRPC_SLICE_LENGTH(ctx->recv_status_on_client.status_details);
330 return (char*)GRPC_SLICE_START_PTR(ctx->recv_status_on_client.status_details);
331 }
332
333 GPR_EXPORT const char* GPR_CALLTYPE
grpcsharp_batch_context_recv_status_on_client_error_string(const grpcsharp_batch_context * ctx)334 grpcsharp_batch_context_recv_status_on_client_error_string(
335 const grpcsharp_batch_context* ctx) {
336 return ctx->recv_status_on_client.error_string;
337 }
338
339 GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
grpcsharp_batch_context_recv_status_on_client_trailing_metadata(const grpcsharp_batch_context * ctx)340 grpcsharp_batch_context_recv_status_on_client_trailing_metadata(
341 const grpcsharp_batch_context* ctx) {
342 return &(ctx->recv_status_on_client.trailing_metadata);
343 }
344
345 GPR_EXPORT grpc_call* GPR_CALLTYPE
grpcsharp_request_call_context_call(const grpcsharp_request_call_context * ctx)346 grpcsharp_request_call_context_call(const grpcsharp_request_call_context* ctx) {
347 return ctx->call;
348 }
349
grpcsharp_request_call_context_method(const grpcsharp_request_call_context * ctx,size_t * method_length)350 GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_request_call_context_method(
351 const grpcsharp_request_call_context* ctx, size_t* method_length) {
352 *method_length = GRPC_SLICE_LENGTH(ctx->call_details.method);
353 return (char*)GRPC_SLICE_START_PTR(ctx->call_details.method);
354 }
355
grpcsharp_request_call_context_host(const grpcsharp_request_call_context * ctx,size_t * host_length)356 GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_request_call_context_host(
357 const grpcsharp_request_call_context* ctx, size_t* host_length) {
358 *host_length = GRPC_SLICE_LENGTH(ctx->call_details.host);
359 return (char*)GRPC_SLICE_START_PTR(ctx->call_details.host);
360 }
361
grpcsharp_request_call_context_deadline(const grpcsharp_request_call_context * ctx)362 GPR_EXPORT gpr_timespec GPR_CALLTYPE grpcsharp_request_call_context_deadline(
363 const grpcsharp_request_call_context* ctx) {
364 return ctx->call_details.deadline;
365 }
366
367 GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
grpcsharp_request_call_context_request_metadata(const grpcsharp_request_call_context * ctx)368 grpcsharp_request_call_context_request_metadata(
369 const grpcsharp_request_call_context* ctx) {
370 return &(ctx->request_metadata);
371 }
372
373 GPR_EXPORT int32_t GPR_CALLTYPE
grpcsharp_batch_context_recv_close_on_server_cancelled(const grpcsharp_batch_context * ctx)374 grpcsharp_batch_context_recv_close_on_server_cancelled(
375 const grpcsharp_batch_context* ctx) {
376 return (int32_t)ctx->recv_close_on_server_cancelled;
377 }
378
379 /* Init & shutdown */
380
grpcsharp_init(void)381 GPR_EXPORT void GPR_CALLTYPE grpcsharp_init(void) { grpc_init(); }
382
grpcsharp_shutdown(void)383 GPR_EXPORT void GPR_CALLTYPE grpcsharp_shutdown(void) { grpc_shutdown(); }
384
385 /* Completion queue */
386
387 GPR_EXPORT grpc_completion_queue* GPR_CALLTYPE
grpcsharp_completion_queue_create_async(void)388 grpcsharp_completion_queue_create_async(void) {
389 return grpc_completion_queue_create_for_next(NULL);
390 }
391
392 GPR_EXPORT grpc_completion_queue* GPR_CALLTYPE
grpcsharp_completion_queue_create_sync(void)393 grpcsharp_completion_queue_create_sync(void) {
394 return grpc_completion_queue_create_for_pluck(NULL);
395 }
396
397 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_completion_queue_shutdown(grpc_completion_queue * cq)398 grpcsharp_completion_queue_shutdown(grpc_completion_queue* cq) {
399 grpc_completion_queue_shutdown(cq);
400 }
401
402 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_completion_queue_destroy(grpc_completion_queue * cq)403 grpcsharp_completion_queue_destroy(grpc_completion_queue* cq) {
404 grpc_completion_queue_destroy(cq);
405 }
406
407 GPR_EXPORT grpc_event GPR_CALLTYPE
grpcsharp_completion_queue_next(grpc_completion_queue * cq)408 grpcsharp_completion_queue_next(grpc_completion_queue* cq) {
409 return grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
410 NULL);
411 }
412
413 GPR_EXPORT grpc_event GPR_CALLTYPE
grpcsharp_completion_queue_pluck(grpc_completion_queue * cq,void * tag)414 grpcsharp_completion_queue_pluck(grpc_completion_queue* cq, void* tag) {
415 return grpc_completion_queue_pluck(cq, tag,
416 gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
417 }
418
419 /* Channel */
420
421 GPR_EXPORT grpc_channel* GPR_CALLTYPE
422
grpcsharp_insecure_channel_create(const char * target,const grpc_channel_args * args)423 grpcsharp_insecure_channel_create(const char* target,
424 const grpc_channel_args* args) {
425 return grpc_insecure_channel_create(target, args, NULL);
426 }
427
grpcsharp_channel_destroy(grpc_channel * channel)428 GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_destroy(grpc_channel* channel) {
429 grpc_channel_destroy(channel);
430 }
431
grpcsharp_channel_create_call(grpc_channel * channel,grpc_call * parent_call,uint32_t propagation_mask,grpc_completion_queue * cq,const char * method,const char * host,gpr_timespec deadline)432 GPR_EXPORT grpc_call* GPR_CALLTYPE grpcsharp_channel_create_call(
433 grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
434 grpc_completion_queue* cq, const char* method, const char* host,
435 gpr_timespec deadline) {
436 grpc_slice method_slice = grpc_slice_from_copied_string(method);
437 grpc_slice* host_slice_ptr = NULL;
438 grpc_slice host_slice;
439 if (host != NULL) {
440 host_slice = grpc_slice_from_copied_string(host);
441 host_slice_ptr = &host_slice;
442 }
443 grpc_call* ret =
444 grpc_channel_create_call(channel, parent_call, propagation_mask, cq,
445 method_slice, host_slice_ptr, deadline, NULL);
446 grpc_slice_unref(method_slice);
447 if (host != NULL) {
448 grpc_slice_unref(host_slice);
449 }
450 return ret;
451 }
452
453 GPR_EXPORT grpc_connectivity_state GPR_CALLTYPE
grpcsharp_channel_check_connectivity_state(grpc_channel * channel,int32_t try_to_connect)454 grpcsharp_channel_check_connectivity_state(grpc_channel* channel,
455 int32_t try_to_connect) {
456 return grpc_channel_check_connectivity_state(channel, try_to_connect);
457 }
458
grpcsharp_channel_watch_connectivity_state(grpc_channel * channel,grpc_connectivity_state last_observed_state,gpr_timespec deadline,grpc_completion_queue * cq,grpcsharp_batch_context * ctx)459 GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_watch_connectivity_state(
460 grpc_channel* channel, grpc_connectivity_state last_observed_state,
461 gpr_timespec deadline, grpc_completion_queue* cq,
462 grpcsharp_batch_context* ctx) {
463 grpc_channel_watch_connectivity_state(channel, last_observed_state, deadline,
464 cq, ctx);
465 }
466
467 GPR_EXPORT char* GPR_CALLTYPE
grpcsharp_channel_get_target(grpc_channel * channel)468 grpcsharp_channel_get_target(grpc_channel* channel) {
469 return grpc_channel_get_target(channel);
470 }
471
472 /* Channel args */
473
474 GPR_EXPORT grpc_channel_args* GPR_CALLTYPE
grpcsharp_channel_args_create(size_t num_args)475 grpcsharp_channel_args_create(size_t num_args) {
476 grpc_channel_args* args =
477 (grpc_channel_args*)gpr_malloc(sizeof(grpc_channel_args));
478 memset(args, 0, sizeof(grpc_channel_args));
479
480 args->num_args = num_args;
481 args->args = (grpc_arg*)gpr_malloc(sizeof(grpc_arg) * num_args);
482 memset(args->args, 0, sizeof(grpc_arg) * num_args);
483 return args;
484 }
485
grpcsharp_channel_args_set_string(grpc_channel_args * args,size_t index,const char * key,const char * value)486 GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_set_string(
487 grpc_channel_args* args, size_t index, const char* key, const char* value) {
488 GPR_ASSERT(args);
489 GPR_ASSERT(index < args->num_args);
490 args->args[index].type = GRPC_ARG_STRING;
491 args->args[index].key = gpr_strdup(key);
492 args->args[index].value.string = gpr_strdup(value);
493 }
494
grpcsharp_channel_args_set_integer(grpc_channel_args * args,size_t index,const char * key,int value)495 GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_set_integer(
496 grpc_channel_args* args, size_t index, const char* key, int value) {
497 GPR_ASSERT(args);
498 GPR_ASSERT(index < args->num_args);
499 args->args[index].type = GRPC_ARG_INTEGER;
500 args->args[index].key = gpr_strdup(key);
501 args->args[index].value.integer = value;
502 }
503
504 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_channel_args_destroy(grpc_channel_args * args)505 grpcsharp_channel_args_destroy(grpc_channel_args* args) {
506 size_t i;
507 if (args) {
508 for (i = 0; i < args->num_args; i++) {
509 gpr_free(args->args[i].key);
510 if (args->args[i].type == GRPC_ARG_STRING) {
511 gpr_free(args->args[i].value.string);
512 }
513 }
514 gpr_free(args->args);
515 gpr_free(args);
516 }
517 }
518
519 /* Timespec */
520
gprsharp_now(gpr_clock_type clock_type)521 GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(gpr_clock_type clock_type) {
522 return gpr_now(clock_type);
523 }
524
525 GPR_EXPORT gpr_timespec GPR_CALLTYPE
gprsharp_inf_future(gpr_clock_type clock_type)526 gprsharp_inf_future(gpr_clock_type clock_type) {
527 return gpr_inf_future(clock_type);
528 }
529
530 GPR_EXPORT gpr_timespec GPR_CALLTYPE
gprsharp_inf_past(gpr_clock_type clock_type)531 gprsharp_inf_past(gpr_clock_type clock_type) {
532 return gpr_inf_past(clock_type);
533 }
534
535 GPR_EXPORT gpr_timespec GPR_CALLTYPE
gprsharp_convert_clock_type(gpr_timespec t,gpr_clock_type target_clock)536 gprsharp_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock) {
537 return gpr_convert_clock_type(t, target_clock);
538 }
539
gprsharp_sizeof_timespec(void)540 GPR_EXPORT int32_t GPR_CALLTYPE gprsharp_sizeof_timespec(void) {
541 return sizeof(gpr_timespec);
542 }
543
544 /* Call */
545
grpcsharp_call_cancel(grpc_call * call)546 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel(grpc_call* call) {
547 return grpc_call_cancel(call, NULL);
548 }
549
grpcsharp_call_cancel_with_status(grpc_call * call,grpc_status_code status,const char * description)550 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel_with_status(
551 grpc_call* call, grpc_status_code status, const char* description) {
552 return grpc_call_cancel_with_status(call, status, description, NULL);
553 }
554
grpcsharp_call_get_peer(grpc_call * call)555 GPR_EXPORT char* GPR_CALLTYPE grpcsharp_call_get_peer(grpc_call* call) {
556 return grpc_call_get_peer(call);
557 }
558
gprsharp_free(void * p)559 GPR_EXPORT void GPR_CALLTYPE gprsharp_free(void* p) { gpr_free(p); }
560
grpcsharp_call_destroy(grpc_call * call)561 GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call* call) {
562 grpc_call_unref(call);
563 }
564
565 typedef grpc_call_error (*grpcsharp_call_start_batch_func)(grpc_call* call,
566 const grpc_op* ops,
567 size_t nops,
568 void* tag,
569 void* reserved);
570
571 /* Only for testing */
grpcsharp_call_start_batch_nop(grpc_call * call,const grpc_op * ops,size_t nops,void * tag,void * reserved)572 static grpc_call_error grpcsharp_call_start_batch_nop(grpc_call* call,
573 const grpc_op* ops,
574 size_t nops, void* tag,
575 void* reserved) {
576 (void)call;
577 (void)ops;
578 (void)nops;
579 (void)tag;
580 (void)reserved;
581 return GRPC_CALL_OK;
582 }
583
grpcsharp_call_start_batch_default(grpc_call * call,const grpc_op * ops,size_t nops,void * tag,void * reserved)584 static grpc_call_error grpcsharp_call_start_batch_default(grpc_call* call,
585 const grpc_op* ops,
586 size_t nops,
587 void* tag,
588 void* reserved) {
589 return grpc_call_start_batch(call, ops, nops, tag, reserved);
590 }
591
592 static grpcsharp_call_start_batch_func g_call_start_batch_func =
593 grpcsharp_call_start_batch_default;
594
grpcsharp_call_start_batch(grpc_call * call,const grpc_op * ops,size_t nops,void * tag,void * reserved)595 static grpc_call_error grpcsharp_call_start_batch(grpc_call* call,
596 const grpc_op* ops,
597 size_t nops, void* tag,
598 void* reserved) {
599 return g_call_start_batch_func(call, ops, nops, tag, reserved);
600 }
601
grpcsharp_call_start_unary(grpc_call * call,grpcsharp_batch_context * ctx,grpc_slice_buffer * send_buffer,uint32_t write_flags,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags)602 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
603 grpc_call* call, grpcsharp_batch_context* ctx,
604 grpc_slice_buffer* send_buffer, uint32_t write_flags,
605 grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
606 /* TODO: don't use magic number */
607 grpc_op ops[6];
608 memset(ops, 0, sizeof(ops));
609 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
610 grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
611 initial_metadata);
612 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
613 ops[0].data.send_initial_metadata.metadata =
614 ctx->send_initial_metadata.metadata;
615 ops[0].flags = initial_metadata_flags;
616 ops[0].reserved = NULL;
617
618 ops[1].op = GRPC_OP_SEND_MESSAGE;
619 ctx->send_message =
620 grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
621 ops[1].data.send_message.send_message = ctx->send_message;
622 ops[1].flags = write_flags;
623 ops[1].reserved = NULL;
624
625 ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
626 ops[2].flags = 0;
627 ops[2].reserved = NULL;
628
629 ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
630 ops[3].data.recv_initial_metadata.recv_initial_metadata =
631 &(ctx->recv_initial_metadata);
632 ops[3].flags = 0;
633 ops[3].reserved = NULL;
634
635 ops[4].op = GRPC_OP_RECV_MESSAGE;
636 ops[4].data.recv_message.recv_message = &(ctx->recv_message);
637 ops[4].flags = 0;
638 ops[4].reserved = NULL;
639
640 ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
641 ops[5].data.recv_status_on_client.trailing_metadata =
642 &(ctx->recv_status_on_client.trailing_metadata);
643 ops[5].data.recv_status_on_client.status =
644 &(ctx->recv_status_on_client.status);
645 ops[5].data.recv_status_on_client.status_details =
646 &(ctx->recv_status_on_client.status_details);
647 ops[5].data.recv_status_on_client.error_string =
648 &(ctx->recv_status_on_client.error_string);
649 ops[5].flags = 0;
650 ops[5].reserved = NULL;
651
652 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
653 ctx, NULL);
654 }
655
656 /* Only for testing. Shortcircuits the unary call logic and only echoes the
657 message as if it was received from the server */
grpcsharp_test_call_start_unary_echo(grpc_call * call,grpcsharp_batch_context * ctx,grpc_slice_buffer * send_buffer,uint32_t write_flags,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags)658 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_test_call_start_unary_echo(
659 grpc_call* call, grpcsharp_batch_context* ctx,
660 grpc_slice_buffer* send_buffer, uint32_t write_flags,
661 grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
662 (void)call;
663 (void)write_flags;
664 (void)initial_metadata_flags;
665 // prepare as if we were performing a normal RPC.
666 grpc_byte_buffer* send_message =
667 grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
668
669 ctx->recv_message = send_message; // echo message sent by the client as if
670 // received from server.
671 ctx->recv_status_on_client.status = GRPC_STATUS_OK;
672 ctx->recv_status_on_client.status_details = grpc_empty_slice();
673 ctx->recv_status_on_client.error_string = NULL;
674 // echo initial metadata as if received from server (as trailing metadata)
675 grpcsharp_metadata_array_move(&(ctx->recv_status_on_client.trailing_metadata),
676 initial_metadata);
677 return GRPC_CALL_OK;
678 }
679
grpcsharp_call_start_client_streaming(grpc_call * call,grpcsharp_batch_context * ctx,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags)680 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(
681 grpc_call* call, grpcsharp_batch_context* ctx,
682 grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
683 /* TODO: don't use magic number */
684 grpc_op ops[4];
685 memset(ops, 0, sizeof(ops));
686 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
687 grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
688 initial_metadata);
689 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
690 ops[0].data.send_initial_metadata.metadata =
691 ctx->send_initial_metadata.metadata;
692 ops[0].flags = initial_metadata_flags;
693 ops[0].reserved = NULL;
694
695 ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
696 ops[1].data.recv_initial_metadata.recv_initial_metadata =
697 &(ctx->recv_initial_metadata);
698 ops[1].flags = 0;
699 ops[1].reserved = NULL;
700
701 ops[2].op = GRPC_OP_RECV_MESSAGE;
702 ops[2].data.recv_message.recv_message = &(ctx->recv_message);
703 ops[2].flags = 0;
704 ops[2].reserved = NULL;
705
706 ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
707 ops[3].data.recv_status_on_client.trailing_metadata =
708 &(ctx->recv_status_on_client.trailing_metadata);
709 ops[3].data.recv_status_on_client.status =
710 &(ctx->recv_status_on_client.status);
711 ops[3].data.recv_status_on_client.status_details =
712 &(ctx->recv_status_on_client.status_details);
713 ops[3].data.recv_status_on_client.error_string =
714 &(ctx->recv_status_on_client.error_string);
715 ops[3].flags = 0;
716 ops[3].reserved = NULL;
717
718 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
719 ctx, NULL);
720 }
721
grpcsharp_call_start_server_streaming(grpc_call * call,grpcsharp_batch_context * ctx,grpc_slice_buffer * send_buffer,uint32_t write_flags,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags)722 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
723 grpc_call* call, grpcsharp_batch_context* ctx,
724 grpc_slice_buffer* send_buffer, uint32_t write_flags,
725 grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
726 /* TODO: don't use magic number */
727 grpc_op ops[4];
728 memset(ops, 0, sizeof(ops));
729 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
730 grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
731 initial_metadata);
732 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
733 ops[0].data.send_initial_metadata.metadata =
734 ctx->send_initial_metadata.metadata;
735 ops[0].flags = initial_metadata_flags;
736 ops[0].reserved = NULL;
737
738 ops[1].op = GRPC_OP_SEND_MESSAGE;
739 ctx->send_message =
740 grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
741 ops[1].data.send_message.send_message = ctx->send_message;
742 ops[1].flags = write_flags;
743 ops[1].reserved = NULL;
744
745 ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
746 ops[2].flags = 0;
747 ops[2].reserved = NULL;
748
749 ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
750 ops[3].data.recv_status_on_client.trailing_metadata =
751 &(ctx->recv_status_on_client.trailing_metadata);
752 ops[3].data.recv_status_on_client.status =
753 &(ctx->recv_status_on_client.status);
754 ops[3].data.recv_status_on_client.status_details =
755 &(ctx->recv_status_on_client.status_details);
756 ops[3].data.recv_status_on_client.error_string =
757 &(ctx->recv_status_on_client.error_string);
758 ops[3].flags = 0;
759 ops[3].reserved = NULL;
760
761 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
762 ctx, NULL);
763 }
764
grpcsharp_call_start_duplex_streaming(grpc_call * call,grpcsharp_batch_context * ctx,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags)765 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(
766 grpc_call* call, grpcsharp_batch_context* ctx,
767 grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
768 /* TODO: don't use magic number */
769 grpc_op ops[2];
770 memset(ops, 0, sizeof(ops));
771 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
772 grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
773 initial_metadata);
774 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
775 ops[0].data.send_initial_metadata.metadata =
776 ctx->send_initial_metadata.metadata;
777 ops[0].flags = initial_metadata_flags;
778 ops[0].reserved = NULL;
779
780 ops[1].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
781 ops[1].data.recv_status_on_client.trailing_metadata =
782 &(ctx->recv_status_on_client.trailing_metadata);
783 ops[1].data.recv_status_on_client.status =
784 &(ctx->recv_status_on_client.status);
785 ops[1].data.recv_status_on_client.status_details =
786 &(ctx->recv_status_on_client.status_details);
787 ops[1].data.recv_status_on_client.error_string =
788 &(ctx->recv_status_on_client.error_string);
789 ops[1].flags = 0;
790 ops[1].reserved = NULL;
791
792 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
793 ctx, NULL);
794 }
795
grpcsharp_call_recv_initial_metadata(grpc_call * call,grpcsharp_batch_context * ctx)796 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata(
797 grpc_call* call, grpcsharp_batch_context* ctx) {
798 /* TODO: don't use magic number */
799 grpc_op ops[1];
800 ops[0].op = GRPC_OP_RECV_INITIAL_METADATA;
801 ops[0].data.recv_initial_metadata.recv_initial_metadata =
802 &(ctx->recv_initial_metadata);
803 ops[0].flags = 0;
804 ops[0].reserved = NULL;
805
806 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
807 ctx, NULL);
808 }
809
grpcsharp_call_send_message(grpc_call * call,grpcsharp_batch_context * ctx,grpc_slice_buffer * send_buffer,uint32_t write_flags,int32_t send_empty_initial_metadata)810 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message(
811 grpc_call* call, grpcsharp_batch_context* ctx,
812 grpc_slice_buffer* send_buffer, uint32_t write_flags,
813 int32_t send_empty_initial_metadata) {
814 /* TODO: don't use magic number */
815 grpc_op ops[2];
816 memset(ops, 0, sizeof(ops));
817 size_t nops = send_empty_initial_metadata ? 2 : 1;
818 ops[0].op = GRPC_OP_SEND_MESSAGE;
819 ctx->send_message =
820 grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
821 ops[0].data.send_message.send_message = ctx->send_message;
822 ops[0].flags = write_flags;
823 ops[0].reserved = NULL;
824 ops[1].op = GRPC_OP_SEND_INITIAL_METADATA;
825 ops[1].flags = 0;
826 ops[1].reserved = NULL;
827
828 return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
829 }
830
grpcsharp_call_send_close_from_client(grpc_call * call,grpcsharp_batch_context * ctx)831 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client(
832 grpc_call* call, grpcsharp_batch_context* ctx) {
833 /* TODO: don't use magic number */
834 grpc_op ops[1];
835 ops[0].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
836 ops[0].flags = 0;
837 ops[0].reserved = NULL;
838
839 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
840 ctx, NULL);
841 }
842
grpcsharp_call_send_status_from_server(grpc_call * call,grpcsharp_batch_context * ctx,grpc_status_code status_code,const char * status_details,size_t status_details_len,grpc_metadata_array * trailing_metadata,int32_t send_empty_initial_metadata,grpc_slice_buffer * optional_send_buffer,uint32_t write_flags)843 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
844 grpc_call* call, grpcsharp_batch_context* ctx, grpc_status_code status_code,
845 const char* status_details, size_t status_details_len,
846 grpc_metadata_array* trailing_metadata, int32_t send_empty_initial_metadata,
847 grpc_slice_buffer* optional_send_buffer, uint32_t write_flags) {
848 /* TODO: don't use magic number */
849 grpc_op ops[3];
850 memset(ops, 0, sizeof(ops));
851 size_t nops = 1;
852 grpc_slice status_details_slice =
853 grpc_slice_from_copied_buffer(status_details, status_details_len);
854 ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
855 ops[0].data.send_status_from_server.status = status_code;
856 ops[0].data.send_status_from_server.status_details = &status_details_slice;
857 grpcsharp_metadata_array_move(
858 &(ctx->send_status_from_server.trailing_metadata), trailing_metadata);
859 ops[0].data.send_status_from_server.trailing_metadata_count =
860 ctx->send_status_from_server.trailing_metadata.count;
861 ops[0].data.send_status_from_server.trailing_metadata =
862 ctx->send_status_from_server.trailing_metadata.metadata;
863 ops[0].flags = 0;
864 ops[0].reserved = NULL;
865 if (optional_send_buffer) {
866 ops[nops].op = GRPC_OP_SEND_MESSAGE;
867 ctx->send_message =
868 grpcsharp_create_byte_buffer_from_stolen_slices(optional_send_buffer);
869 ops[nops].data.send_message.send_message = ctx->send_message;
870 ops[nops].flags = write_flags;
871 ops[nops].reserved = NULL;
872 nops++;
873 }
874 if (send_empty_initial_metadata) {
875 ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA;
876 ops[nops].flags = 0;
877 ops[nops].reserved = NULL;
878 nops++;
879 }
880 grpc_call_error ret = grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
881 grpc_slice_unref(status_details_slice);
882 return ret;
883 }
884
885 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_recv_message(grpc_call * call,grpcsharp_batch_context * ctx)886 grpcsharp_call_recv_message(grpc_call* call, grpcsharp_batch_context* ctx) {
887 /* TODO: don't use magic number */
888 grpc_op ops[1];
889 ops[0].op = GRPC_OP_RECV_MESSAGE;
890 ops[0].data.recv_message.recv_message = &(ctx->recv_message);
891 ops[0].flags = 0;
892 ops[0].reserved = NULL;
893 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
894 ctx, NULL);
895 }
896
897 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_serverside(grpc_call * call,grpcsharp_batch_context * ctx)898 grpcsharp_call_start_serverside(grpc_call* call, grpcsharp_batch_context* ctx) {
899 /* TODO: don't use magic number */
900 grpc_op ops[1];
901 ops[0].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
902 ops[0].data.recv_close_on_server.cancelled =
903 (&ctx->recv_close_on_server_cancelled);
904 ops[0].flags = 0;
905 ops[0].reserved = NULL;
906
907 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
908 ctx, NULL);
909 }
910
grpcsharp_call_send_initial_metadata(grpc_call * call,grpcsharp_batch_context * ctx,grpc_metadata_array * initial_metadata)911 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata(
912 grpc_call* call, grpcsharp_batch_context* ctx,
913 grpc_metadata_array* initial_metadata) {
914 /* TODO: don't use magic number */
915 grpc_op ops[1];
916 memset(ops, 0, sizeof(ops));
917 ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
918 grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
919 initial_metadata);
920 ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
921 ops[0].data.send_initial_metadata.metadata =
922 ctx->send_initial_metadata.metadata;
923 ops[0].flags = 0;
924 ops[0].reserved = NULL;
925
926 return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
927 ctx, NULL);
928 }
929
930 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_set_credentials(grpc_call * call,grpc_call_credentials * creds)931 grpcsharp_call_set_credentials(grpc_call* call, grpc_call_credentials* creds) {
932 return grpc_call_set_credentials(call, creds);
933 }
934
935 /* Server */
936
937 GPR_EXPORT grpc_server* GPR_CALLTYPE
grpcsharp_server_create(const grpc_channel_args * args)938 grpcsharp_server_create(const grpc_channel_args* args) {
939 return grpc_server_create(args, NULL);
940 }
941
grpcsharp_server_register_completion_queue(grpc_server * server,grpc_completion_queue * cq)942 GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_register_completion_queue(
943 grpc_server* server, grpc_completion_queue* cq) {
944 grpc_server_register_completion_queue(server, cq, NULL);
945 }
946
grpcsharp_server_add_insecure_http2_port(grpc_server * server,const char * addr)947 GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_insecure_http2_port(
948 grpc_server* server, const char* addr) {
949 return grpc_server_add_insecure_http2_port(server, addr);
950 }
951
grpcsharp_server_start(grpc_server * server)952 GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_start(grpc_server* server) {
953 grpc_server_start(server);
954 }
955
grpcsharp_server_shutdown_and_notify_callback(grpc_server * server,grpc_completion_queue * cq,grpcsharp_batch_context * ctx)956 GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_shutdown_and_notify_callback(
957 grpc_server* server, grpc_completion_queue* cq,
958 grpcsharp_batch_context* ctx) {
959 grpc_server_shutdown_and_notify(server, cq, ctx);
960 }
961
962 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_server_cancel_all_calls(grpc_server * server)963 grpcsharp_server_cancel_all_calls(grpc_server* server) {
964 grpc_server_cancel_all_calls(server);
965 }
966
grpcsharp_server_destroy(grpc_server * server)967 GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_destroy(grpc_server* server) {
968 grpc_server_destroy(server);
969 }
970
971 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_server_request_call(grpc_server * server,grpc_completion_queue * cq,grpcsharp_request_call_context * ctx)972 grpcsharp_server_request_call(grpc_server* server, grpc_completion_queue* cq,
973 grpcsharp_request_call_context* ctx) {
974 return grpc_server_request_call(server, &(ctx->call), &(ctx->call_details),
975 &(ctx->request_metadata), cq, cq, ctx);
976 }
977
978 /* Native callback dispatcher */
979
980 typedef int(GPR_CALLTYPE* grpcsharp_native_callback_dispatcher_func)(
981 void* tag, void* arg0, void* arg1, void* arg2, void* arg3, void* arg4,
982 void* arg5);
983
984 static grpcsharp_native_callback_dispatcher_func native_callback_dispatcher =
985 NULL;
986
grpcsharp_native_callback_dispatcher_init(grpcsharp_native_callback_dispatcher_func func)987 GPR_EXPORT void GPR_CALLTYPE grpcsharp_native_callback_dispatcher_init(
988 grpcsharp_native_callback_dispatcher_func func) {
989 GPR_ASSERT(func);
990 native_callback_dispatcher = func;
991 }
992
993 /* Security */
994
995 static char* default_pem_root_certs = NULL;
996
override_ssl_roots_handler(char ** pem_root_certs)997 static grpc_ssl_roots_override_result override_ssl_roots_handler(
998 char** pem_root_certs) {
999 if (!default_pem_root_certs) {
1000 *pem_root_certs = NULL;
1001 return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
1002 }
1003 *pem_root_certs = gpr_strdup(default_pem_root_certs);
1004 return GRPC_SSL_ROOTS_OVERRIDE_OK;
1005 }
1006
1007 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_override_default_ssl_roots(const char * pem_root_certs)1008 grpcsharp_override_default_ssl_roots(const char* pem_root_certs) {
1009 /*
1010 * This currently wastes ~300kB of memory by keeping a copy of roots
1011 * in a static variable, but for desktop/server use, the overhead
1012 * is negligible. In the future, we might want to change the behavior
1013 * for mobile (e.g. Xamarin).
1014 */
1015 default_pem_root_certs = gpr_strdup(pem_root_certs);
1016 grpc_set_ssl_roots_override_callback(override_ssl_roots_handler);
1017 }
1018
grpcsharp_verify_peer_destroy_handler(void * userdata)1019 static void grpcsharp_verify_peer_destroy_handler(void* userdata) {
1020 native_callback_dispatcher(userdata, NULL, NULL, (void*)1, NULL, NULL, NULL);
1021 }
1022
grpcsharp_verify_peer_handler(const char * target_name,const char * peer_pem,void * userdata)1023 static int grpcsharp_verify_peer_handler(const char* target_name,
1024 const char* peer_pem, void* userdata) {
1025 return native_callback_dispatcher(userdata, (void*)target_name,
1026 (void*)peer_pem, (void*)0, NULL, NULL,
1027 NULL);
1028 }
1029
1030 GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE
grpcsharp_ssl_credentials_create(const char * pem_root_certs,const char * key_cert_pair_cert_chain,const char * key_cert_pair_private_key,void * verify_peer_callback_tag)1031 grpcsharp_ssl_credentials_create(const char* pem_root_certs,
1032 const char* key_cert_pair_cert_chain,
1033 const char* key_cert_pair_private_key,
1034 void* verify_peer_callback_tag) {
1035 grpc_ssl_pem_key_cert_pair key_cert_pair;
1036 verify_peer_options verify_options;
1037 grpc_ssl_pem_key_cert_pair* key_cert_pair_ptr = NULL;
1038 verify_peer_options* verify_options_ptr = NULL;
1039
1040 if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
1041 memset(&key_cert_pair, 0, sizeof(key_cert_pair));
1042 key_cert_pair.cert_chain = key_cert_pair_cert_chain;
1043 key_cert_pair.private_key = key_cert_pair_private_key;
1044 key_cert_pair_ptr = &key_cert_pair;
1045 } else {
1046 GPR_ASSERT(!key_cert_pair_cert_chain);
1047 GPR_ASSERT(!key_cert_pair_private_key);
1048 }
1049
1050 if (verify_peer_callback_tag != NULL) {
1051 memset(&verify_options, 0, sizeof(verify_peer_options));
1052 verify_options.verify_peer_callback_userdata = verify_peer_callback_tag;
1053 verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler;
1054 verify_options.verify_peer_callback = grpcsharp_verify_peer_handler;
1055 verify_options_ptr = &verify_options;
1056 }
1057
1058 return grpc_ssl_credentials_create(pem_root_certs, key_cert_pair_ptr,
1059 verify_options_ptr, NULL);
1060 }
1061
1062 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_channel_credentials_release(grpc_channel_credentials * creds)1063 grpcsharp_channel_credentials_release(grpc_channel_credentials* creds) {
1064 grpc_channel_credentials_release(creds);
1065 }
1066
1067 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_call_credentials_release(grpc_call_credentials * creds)1068 grpcsharp_call_credentials_release(grpc_call_credentials* creds) {
1069 grpc_call_credentials_release(creds);
1070 }
1071
grpcsharp_secure_channel_create(grpc_channel_credentials * creds,const char * target,const grpc_channel_args * args)1072 GPR_EXPORT grpc_channel* GPR_CALLTYPE grpcsharp_secure_channel_create(
1073 grpc_channel_credentials* creds, const char* target,
1074 const grpc_channel_args* args) {
1075 return grpc_secure_channel_create(creds, target, args, NULL);
1076 }
1077
1078 GPR_EXPORT grpc_server_credentials* GPR_CALLTYPE
grpcsharp_ssl_server_credentials_create(const char * pem_root_certs,const char ** key_cert_pair_cert_chain_array,const char ** key_cert_pair_private_key_array,size_t num_key_cert_pairs,grpc_ssl_client_certificate_request_type client_request_type)1079 grpcsharp_ssl_server_credentials_create(
1080 const char* pem_root_certs, const char** key_cert_pair_cert_chain_array,
1081 const char** key_cert_pair_private_key_array, size_t num_key_cert_pairs,
1082 grpc_ssl_client_certificate_request_type client_request_type) {
1083 size_t i;
1084 grpc_server_credentials* creds;
1085 grpc_ssl_pem_key_cert_pair* key_cert_pairs =
1086 gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
1087 memset(key_cert_pairs, 0,
1088 sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
1089
1090 for (i = 0; i < num_key_cert_pairs; i++) {
1091 if (key_cert_pair_cert_chain_array[i] ||
1092 key_cert_pair_private_key_array[i]) {
1093 key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i];
1094 key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
1095 }
1096 }
1097 creds = grpc_ssl_server_credentials_create_ex(pem_root_certs, key_cert_pairs,
1098 num_key_cert_pairs,
1099 client_request_type, NULL);
1100 gpr_free(key_cert_pairs);
1101 return creds;
1102 }
1103
1104 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_server_credentials_release(grpc_server_credentials * creds)1105 grpcsharp_server_credentials_release(grpc_server_credentials* creds) {
1106 grpc_server_credentials_release(creds);
1107 }
1108
grpcsharp_server_add_secure_http2_port(grpc_server * server,const char * addr,grpc_server_credentials * creds)1109 GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_secure_http2_port(
1110 grpc_server* server, const char* addr, grpc_server_credentials* creds) {
1111 return grpc_server_add_secure_http2_port(server, addr, creds);
1112 }
1113
1114 GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE
grpcsharp_composite_channel_credentials_create(grpc_channel_credentials * channel_creds,grpc_call_credentials * call_creds)1115 grpcsharp_composite_channel_credentials_create(
1116 grpc_channel_credentials* channel_creds,
1117 grpc_call_credentials* call_creds) {
1118 return grpc_composite_channel_credentials_create(channel_creds, call_creds,
1119 NULL);
1120 }
1121
1122 GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
grpcsharp_composite_call_credentials_create(grpc_call_credentials * creds1,grpc_call_credentials * creds2)1123 grpcsharp_composite_call_credentials_create(grpc_call_credentials* creds1,
1124 grpc_call_credentials* creds2) {
1125 return grpc_composite_call_credentials_create(creds1, creds2, NULL);
1126 }
1127
1128 /* Metadata credentials plugin */
1129
grpcsharp_metadata_credentials_notify_from_plugin(grpc_credentials_plugin_metadata_cb cb,void * user_data,grpc_metadata_array * metadata,grpc_status_code status,const char * error_details)1130 GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
1131 grpc_credentials_plugin_metadata_cb cb, void* user_data,
1132 grpc_metadata_array* metadata, grpc_status_code status,
1133 const char* error_details) {
1134 if (metadata) {
1135 cb(user_data, metadata->metadata, metadata->count, status, error_details);
1136 } else {
1137 cb(user_data, NULL, 0, status, error_details);
1138 }
1139 }
1140
grpcsharp_get_metadata_handler(void * state,grpc_auth_metadata_context context,grpc_credentials_plugin_metadata_cb cb,void * user_data,grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],size_t * num_creds_md,grpc_status_code * status,const char ** error_details)1141 static int grpcsharp_get_metadata_handler(
1142 void* state, grpc_auth_metadata_context context,
1143 grpc_credentials_plugin_metadata_cb cb, void* user_data,
1144 grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
1145 size_t* num_creds_md, grpc_status_code* status,
1146 const char** error_details) {
1147 (void)creds_md;
1148 (void)num_creds_md;
1149 (void)status;
1150 (void)error_details;
1151 // the "context" object and its contents are only guaranteed to live until
1152 // this handler returns (which could result in use-after-free for async
1153 // handling of the callback), so the C# counterpart of this handler
1154 // must make a copy of the "service_url" and "method_name" strings before
1155 // it returns if it wants to uses these strings.
1156 native_callback_dispatcher(state, (void*)context.service_url,
1157 (void*)context.method_name, cb, user_data,
1158 (void*)0, NULL);
1159 return 0; /* Asynchronous return. */
1160 }
1161
grpcsharp_metadata_credentials_destroy_handler(void * state)1162 static void grpcsharp_metadata_credentials_destroy_handler(void* state) {
1163 native_callback_dispatcher(state, NULL, NULL, NULL, NULL, (void*)1, NULL);
1164 }
1165
1166 GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
grpcsharp_metadata_credentials_create_from_plugin(void * callback_tag)1167 grpcsharp_metadata_credentials_create_from_plugin(void* callback_tag) {
1168 grpc_metadata_credentials_plugin plugin;
1169 plugin.get_metadata = grpcsharp_get_metadata_handler;
1170 plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
1171 plugin.state = callback_tag;
1172 plugin.type = "";
1173 // TODO(yihuazhang): Expose min_security_level via the C# API so
1174 // that applications can decide what minimum security level their
1175 // plugins require.
1176 return grpc_metadata_credentials_create_from_plugin(
1177 plugin, GRPC_PRIVACY_AND_INTEGRITY, NULL);
1178 }
1179
1180 /* Auth context */
1181
1182 GPR_EXPORT grpc_auth_context* GPR_CALLTYPE
grpcsharp_call_auth_context(grpc_call * call)1183 grpcsharp_call_auth_context(grpc_call* call) {
1184 return grpc_call_auth_context(call);
1185 }
1186
1187 GPR_EXPORT const char* GPR_CALLTYPE
grpcsharp_auth_context_peer_identity_property_name(const grpc_auth_context * ctx)1188 grpcsharp_auth_context_peer_identity_property_name(
1189 const grpc_auth_context* ctx) {
1190 return grpc_auth_context_peer_identity_property_name(ctx);
1191 }
1192
1193 GPR_EXPORT grpc_auth_property_iterator GPR_CALLTYPE
grpcsharp_auth_context_property_iterator(const grpc_auth_context * ctx)1194 grpcsharp_auth_context_property_iterator(const grpc_auth_context* ctx) {
1195 return grpc_auth_context_property_iterator(ctx);
1196 }
1197
1198 GPR_EXPORT const grpc_auth_property* GPR_CALLTYPE
grpcsharp_auth_property_iterator_next(grpc_auth_property_iterator * it)1199 grpcsharp_auth_property_iterator_next(grpc_auth_property_iterator* it) {
1200 return grpc_auth_property_iterator_next(it);
1201 }
1202
1203 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_auth_context_release(grpc_auth_context * ctx)1204 grpcsharp_auth_context_release(grpc_auth_context* ctx) {
1205 grpc_auth_context_release(ctx);
1206 }
1207
1208 /* Logging */
1209
1210 typedef void(GPR_CALLTYPE* grpcsharp_log_func)(const char* file, int32_t line,
1211 uint64_t thd_id,
1212 const char* severity_string,
1213 const char* msg);
1214 static grpcsharp_log_func log_func = NULL;
1215
1216 /* Redirects gpr_log to log_func callback */
grpcsharp_log_handler(gpr_log_func_args * args)1217 static void grpcsharp_log_handler(gpr_log_func_args* args) {
1218 log_func(args->file, args->line, gpr_thd_currentid(),
1219 gpr_log_severity_string(args->severity), args->message);
1220 }
1221
grpcsharp_redirect_log(grpcsharp_log_func func)1222 GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) {
1223 GPR_ASSERT(func);
1224 log_func = func;
1225 gpr_set_log_function(grpcsharp_log_handler);
1226 }
1227
1228 typedef void(GPR_CALLTYPE* test_callback_funcptr)(int32_t success);
1229
1230 /* Slice buffer functionality */
grpcsharp_slice_buffer_create()1231 GPR_EXPORT grpc_slice_buffer* GPR_CALLTYPE grpcsharp_slice_buffer_create() {
1232 grpc_slice_buffer* slice_buffer =
1233 (grpc_slice_buffer*)gpr_malloc(sizeof(grpc_slice_buffer));
1234 grpc_slice_buffer_init(slice_buffer);
1235 return slice_buffer;
1236 }
1237
1238 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_slice_buffer_reset_and_unref(grpc_slice_buffer * buffer)1239 grpcsharp_slice_buffer_reset_and_unref(grpc_slice_buffer* buffer) {
1240 grpc_slice_buffer_reset_and_unref(buffer);
1241 }
1242
1243 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_slice_buffer_destroy(grpc_slice_buffer * buffer)1244 grpcsharp_slice_buffer_destroy(grpc_slice_buffer* buffer) {
1245 grpc_slice_buffer_destroy(buffer);
1246 gpr_free(buffer);
1247 }
1248
1249 GPR_EXPORT size_t GPR_CALLTYPE
grpcsharp_slice_buffer_slice_count(grpc_slice_buffer * buffer)1250 grpcsharp_slice_buffer_slice_count(grpc_slice_buffer* buffer) {
1251 return buffer->count;
1252 }
1253
1254 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_slice_buffer_slice_peek(grpc_slice_buffer * buffer,size_t index,size_t * slice_len,uint8_t ** slice_data_ptr)1255 grpcsharp_slice_buffer_slice_peek(grpc_slice_buffer* buffer, size_t index,
1256 size_t* slice_len, uint8_t** slice_data_ptr) {
1257 GPR_ASSERT(buffer->count > index);
1258 grpc_slice* slice_ptr = &buffer->slices[index];
1259 *slice_len = GRPC_SLICE_LENGTH(*slice_ptr);
1260 *slice_data_ptr = GRPC_SLICE_START_PTR(*slice_ptr);
1261 }
1262
grpcsharp_slice_buffer_adjust_tail_space(grpc_slice_buffer * buffer,size_t available_tail_space,size_t requested_tail_space)1263 GPR_EXPORT void* GPR_CALLTYPE grpcsharp_slice_buffer_adjust_tail_space(
1264 grpc_slice_buffer* buffer, size_t available_tail_space,
1265 size_t requested_tail_space) {
1266 if (available_tail_space == requested_tail_space) {
1267 // nothing to do
1268 } else if (available_tail_space >= requested_tail_space) {
1269 grpc_slice_buffer_trim_end(
1270 buffer, available_tail_space - requested_tail_space, NULL);
1271 } else {
1272 if (available_tail_space > 0) {
1273 grpc_slice_buffer_trim_end(buffer, available_tail_space, NULL);
1274 }
1275
1276 grpc_slice new_slice = grpc_slice_malloc(requested_tail_space);
1277 // grpc_slice_buffer_add_indexed always adds as a new slice entry into the
1278 // sb (which is suboptimal in some cases) but it doesn't have the problem of
1279 // sometimes splitting the continguous new_slice across two different slices
1280 // (like grpc_slice_buffer_add would)
1281 grpc_slice_buffer_add_indexed(buffer, new_slice);
1282 }
1283
1284 if (buffer->count == 0) {
1285 return NULL;
1286 }
1287 grpc_slice* last_slice = &(buffer->slices[buffer->count - 1]);
1288 return GRPC_SLICE_END_PTR(*last_slice) - requested_tail_space;
1289 }
1290
1291 /* Version info */
grpcsharp_version_string()1292 GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_version_string() {
1293 return grpc_version_string();
1294 }
1295
1296 /* For testing */
1297 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_test_callback(test_callback_funcptr callback)1298 grpcsharp_test_callback(test_callback_funcptr callback) {
1299 callback(1);
1300 }
1301
1302 /* For testing */
grpcsharp_test_nop(void * ptr)1303 GPR_EXPORT void* GPR_CALLTYPE grpcsharp_test_nop(void* ptr) { return ptr; }
1304
1305 /* For testing */
grpcsharp_sizeof_grpc_event(void)1306 GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) {
1307 return sizeof(grpc_event);
1308 }
1309
1310 /* Override a method for testing */
1311 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_test_override_method(const char * method_name,const char * variant)1312 grpcsharp_test_override_method(const char* method_name, const char* variant) {
1313 if (strcmp("grpcsharp_call_start_batch", method_name) == 0) {
1314 if (strcmp("nop", variant) == 0) {
1315 g_call_start_batch_func = grpcsharp_call_start_batch_nop;
1316 } else {
1317 GPR_ASSERT(0);
1318 }
1319 } else {
1320 GPR_ASSERT(0);
1321 }
1322 }
1323