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   return GRPC_CALL_OK;
577 }
578 
grpcsharp_call_start_batch_default(grpc_call * call,const grpc_op * ops,size_t nops,void * tag,void * reserved)579 static grpc_call_error grpcsharp_call_start_batch_default(grpc_call* call,
580                                                           const grpc_op* ops,
581                                                           size_t nops,
582                                                           void* tag,
583                                                           void* reserved) {
584   return grpc_call_start_batch(call, ops, nops, tag, reserved);
585 }
586 
587 static grpcsharp_call_start_batch_func g_call_start_batch_func =
588     grpcsharp_call_start_batch_default;
589 
grpcsharp_call_start_batch(grpc_call * call,const grpc_op * ops,size_t nops,void * tag,void * reserved)590 static grpc_call_error grpcsharp_call_start_batch(grpc_call* call,
591                                                   const grpc_op* ops,
592                                                   size_t nops, void* tag,
593                                                   void* reserved) {
594   return g_call_start_batch_func(call, ops, nops, tag, reserved);
595 }
596 
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)597 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
598     grpc_call* call, grpcsharp_batch_context* ctx,
599     grpc_slice_buffer* send_buffer, uint32_t write_flags,
600     grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
601   /* TODO: don't use magic number */
602   grpc_op ops[6];
603   memset(ops, 0, sizeof(ops));
604   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
605   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
606                                 initial_metadata);
607   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
608   ops[0].data.send_initial_metadata.metadata =
609       ctx->send_initial_metadata.metadata;
610   ops[0].flags = initial_metadata_flags;
611   ops[0].reserved = NULL;
612 
613   ops[1].op = GRPC_OP_SEND_MESSAGE;
614   ctx->send_message =
615       grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
616   ops[1].data.send_message.send_message = ctx->send_message;
617   ops[1].flags = write_flags;
618   ops[1].reserved = NULL;
619 
620   ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
621   ops[2].flags = 0;
622   ops[2].reserved = NULL;
623 
624   ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
625   ops[3].data.recv_initial_metadata.recv_initial_metadata =
626       &(ctx->recv_initial_metadata);
627   ops[3].flags = 0;
628   ops[3].reserved = NULL;
629 
630   ops[4].op = GRPC_OP_RECV_MESSAGE;
631   ops[4].data.recv_message.recv_message = &(ctx->recv_message);
632   ops[4].flags = 0;
633   ops[4].reserved = NULL;
634 
635   ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
636   ops[5].data.recv_status_on_client.trailing_metadata =
637       &(ctx->recv_status_on_client.trailing_metadata);
638   ops[5].data.recv_status_on_client.status =
639       &(ctx->recv_status_on_client.status);
640   ops[5].data.recv_status_on_client.status_details =
641       &(ctx->recv_status_on_client.status_details);
642   ops[5].data.recv_status_on_client.error_string =
643       &(ctx->recv_status_on_client.error_string);
644   ops[5].flags = 0;
645   ops[5].reserved = NULL;
646 
647   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
648                                     ctx, NULL);
649 }
650 
651 /* Only for testing. Shortcircuits the unary call logic and only echoes the
652    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)653 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_test_call_start_unary_echo(
654     grpc_call* call, grpcsharp_batch_context* ctx,
655     grpc_slice_buffer* send_buffer, uint32_t write_flags,
656     grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
657   // prepare as if we were performing a normal RPC.
658   grpc_byte_buffer* send_message =
659       grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
660 
661   ctx->recv_message = send_message;  // echo message sent by the client as if
662                                      // received from server.
663   ctx->recv_status_on_client.status = GRPC_STATUS_OK;
664   ctx->recv_status_on_client.status_details = grpc_empty_slice();
665   ctx->recv_status_on_client.error_string = NULL;
666   // echo initial metadata as if received from server (as trailing metadata)
667   grpcsharp_metadata_array_move(&(ctx->recv_status_on_client.trailing_metadata),
668                                 initial_metadata);
669   return GRPC_CALL_OK;
670 }
671 
grpcsharp_call_start_client_streaming(grpc_call * call,grpcsharp_batch_context * ctx,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags)672 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(
673     grpc_call* call, grpcsharp_batch_context* ctx,
674     grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
675   /* TODO: don't use magic number */
676   grpc_op ops[4];
677   memset(ops, 0, sizeof(ops));
678   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
679   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
680                                 initial_metadata);
681   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
682   ops[0].data.send_initial_metadata.metadata =
683       ctx->send_initial_metadata.metadata;
684   ops[0].flags = initial_metadata_flags;
685   ops[0].reserved = NULL;
686 
687   ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
688   ops[1].data.recv_initial_metadata.recv_initial_metadata =
689       &(ctx->recv_initial_metadata);
690   ops[1].flags = 0;
691   ops[1].reserved = NULL;
692 
693   ops[2].op = GRPC_OP_RECV_MESSAGE;
694   ops[2].data.recv_message.recv_message = &(ctx->recv_message);
695   ops[2].flags = 0;
696   ops[2].reserved = NULL;
697 
698   ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
699   ops[3].data.recv_status_on_client.trailing_metadata =
700       &(ctx->recv_status_on_client.trailing_metadata);
701   ops[3].data.recv_status_on_client.status =
702       &(ctx->recv_status_on_client.status);
703   ops[3].data.recv_status_on_client.status_details =
704       &(ctx->recv_status_on_client.status_details);
705   ops[3].data.recv_status_on_client.error_string =
706       &(ctx->recv_status_on_client.error_string);
707   ops[3].flags = 0;
708   ops[3].reserved = NULL;
709 
710   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
711                                     ctx, NULL);
712 }
713 
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)714 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
715     grpc_call* call, grpcsharp_batch_context* ctx,
716     grpc_slice_buffer* send_buffer, uint32_t write_flags,
717     grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
718   /* TODO: don't use magic number */
719   grpc_op ops[4];
720   memset(ops, 0, sizeof(ops));
721   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
722   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
723                                 initial_metadata);
724   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
725   ops[0].data.send_initial_metadata.metadata =
726       ctx->send_initial_metadata.metadata;
727   ops[0].flags = initial_metadata_flags;
728   ops[0].reserved = NULL;
729 
730   ops[1].op = GRPC_OP_SEND_MESSAGE;
731   ctx->send_message =
732       grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
733   ops[1].data.send_message.send_message = ctx->send_message;
734   ops[1].flags = write_flags;
735   ops[1].reserved = NULL;
736 
737   ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
738   ops[2].flags = 0;
739   ops[2].reserved = NULL;
740 
741   ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
742   ops[3].data.recv_status_on_client.trailing_metadata =
743       &(ctx->recv_status_on_client.trailing_metadata);
744   ops[3].data.recv_status_on_client.status =
745       &(ctx->recv_status_on_client.status);
746   ops[3].data.recv_status_on_client.status_details =
747       &(ctx->recv_status_on_client.status_details);
748   ops[3].data.recv_status_on_client.error_string =
749       &(ctx->recv_status_on_client.error_string);
750   ops[3].flags = 0;
751   ops[3].reserved = NULL;
752 
753   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
754                                     ctx, NULL);
755 }
756 
grpcsharp_call_start_duplex_streaming(grpc_call * call,grpcsharp_batch_context * ctx,grpc_metadata_array * initial_metadata,uint32_t initial_metadata_flags)757 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(
758     grpc_call* call, grpcsharp_batch_context* ctx,
759     grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
760   /* TODO: don't use magic number */
761   grpc_op ops[2];
762   memset(ops, 0, sizeof(ops));
763   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
764   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
765                                 initial_metadata);
766   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
767   ops[0].data.send_initial_metadata.metadata =
768       ctx->send_initial_metadata.metadata;
769   ops[0].flags = initial_metadata_flags;
770   ops[0].reserved = NULL;
771 
772   ops[1].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
773   ops[1].data.recv_status_on_client.trailing_metadata =
774       &(ctx->recv_status_on_client.trailing_metadata);
775   ops[1].data.recv_status_on_client.status =
776       &(ctx->recv_status_on_client.status);
777   ops[1].data.recv_status_on_client.status_details =
778       &(ctx->recv_status_on_client.status_details);
779   ops[1].data.recv_status_on_client.error_string =
780       &(ctx->recv_status_on_client.error_string);
781   ops[1].flags = 0;
782   ops[1].reserved = NULL;
783 
784   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
785                                     ctx, NULL);
786 }
787 
grpcsharp_call_recv_initial_metadata(grpc_call * call,grpcsharp_batch_context * ctx)788 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata(
789     grpc_call* call, grpcsharp_batch_context* ctx) {
790   /* TODO: don't use magic number */
791   grpc_op ops[1];
792   ops[0].op = GRPC_OP_RECV_INITIAL_METADATA;
793   ops[0].data.recv_initial_metadata.recv_initial_metadata =
794       &(ctx->recv_initial_metadata);
795   ops[0].flags = 0;
796   ops[0].reserved = NULL;
797 
798   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
799                                     ctx, NULL);
800 }
801 
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)802 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message(
803     grpc_call* call, grpcsharp_batch_context* ctx,
804     grpc_slice_buffer* send_buffer, uint32_t write_flags,
805     int32_t send_empty_initial_metadata) {
806   /* TODO: don't use magic number */
807   grpc_op ops[2];
808   memset(ops, 0, sizeof(ops));
809   size_t nops = send_empty_initial_metadata ? 2 : 1;
810   ops[0].op = GRPC_OP_SEND_MESSAGE;
811   ctx->send_message =
812       grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
813   ops[0].data.send_message.send_message = ctx->send_message;
814   ops[0].flags = write_flags;
815   ops[0].reserved = NULL;
816   ops[1].op = GRPC_OP_SEND_INITIAL_METADATA;
817   ops[1].flags = 0;
818   ops[1].reserved = NULL;
819 
820   return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
821 }
822 
grpcsharp_call_send_close_from_client(grpc_call * call,grpcsharp_batch_context * ctx)823 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client(
824     grpc_call* call, grpcsharp_batch_context* ctx) {
825   /* TODO: don't use magic number */
826   grpc_op ops[1];
827   ops[0].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
828   ops[0].flags = 0;
829   ops[0].reserved = NULL;
830 
831   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
832                                     ctx, NULL);
833 }
834 
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)835 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
836     grpc_call* call, grpcsharp_batch_context* ctx, grpc_status_code status_code,
837     const char* status_details, size_t status_details_len,
838     grpc_metadata_array* trailing_metadata, int32_t send_empty_initial_metadata,
839     grpc_slice_buffer* optional_send_buffer, uint32_t write_flags) {
840   /* TODO: don't use magic number */
841   grpc_op ops[3];
842   memset(ops, 0, sizeof(ops));
843   size_t nops = 1;
844   grpc_slice status_details_slice =
845       grpc_slice_from_copied_buffer(status_details, status_details_len);
846   ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
847   ops[0].data.send_status_from_server.status = status_code;
848   ops[0].data.send_status_from_server.status_details = &status_details_slice;
849   grpcsharp_metadata_array_move(
850       &(ctx->send_status_from_server.trailing_metadata), trailing_metadata);
851   ops[0].data.send_status_from_server.trailing_metadata_count =
852       ctx->send_status_from_server.trailing_metadata.count;
853   ops[0].data.send_status_from_server.trailing_metadata =
854       ctx->send_status_from_server.trailing_metadata.metadata;
855   ops[0].flags = 0;
856   ops[0].reserved = NULL;
857   if (optional_send_buffer) {
858     ops[nops].op = GRPC_OP_SEND_MESSAGE;
859     ctx->send_message =
860         grpcsharp_create_byte_buffer_from_stolen_slices(optional_send_buffer);
861     ops[nops].data.send_message.send_message = ctx->send_message;
862     ops[nops].flags = write_flags;
863     ops[nops].reserved = NULL;
864     nops++;
865   }
866   if (send_empty_initial_metadata) {
867     ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA;
868     ops[nops].flags = 0;
869     ops[nops].reserved = NULL;
870     nops++;
871   }
872   grpc_call_error ret = grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
873   grpc_slice_unref(status_details_slice);
874   return ret;
875 }
876 
877 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_recv_message(grpc_call * call,grpcsharp_batch_context * ctx)878 grpcsharp_call_recv_message(grpc_call* call, grpcsharp_batch_context* ctx) {
879   /* TODO: don't use magic number */
880   grpc_op ops[1];
881   ops[0].op = GRPC_OP_RECV_MESSAGE;
882   ops[0].data.recv_message.recv_message = &(ctx->recv_message);
883   ops[0].flags = 0;
884   ops[0].reserved = NULL;
885   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
886                                     ctx, NULL);
887 }
888 
889 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_start_serverside(grpc_call * call,grpcsharp_batch_context * ctx)890 grpcsharp_call_start_serverside(grpc_call* call, grpcsharp_batch_context* ctx) {
891   /* TODO: don't use magic number */
892   grpc_op ops[1];
893   ops[0].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
894   ops[0].data.recv_close_on_server.cancelled =
895       (&ctx->recv_close_on_server_cancelled);
896   ops[0].flags = 0;
897   ops[0].reserved = NULL;
898 
899   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
900                                     ctx, NULL);
901 }
902 
grpcsharp_call_send_initial_metadata(grpc_call * call,grpcsharp_batch_context * ctx,grpc_metadata_array * initial_metadata)903 GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata(
904     grpc_call* call, grpcsharp_batch_context* ctx,
905     grpc_metadata_array* initial_metadata) {
906   /* TODO: don't use magic number */
907   grpc_op ops[1];
908   memset(ops, 0, sizeof(ops));
909   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
910   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
911                                 initial_metadata);
912   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
913   ops[0].data.send_initial_metadata.metadata =
914       ctx->send_initial_metadata.metadata;
915   ops[0].flags = 0;
916   ops[0].reserved = NULL;
917 
918   return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
919                                     ctx, NULL);
920 }
921 
922 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_call_set_credentials(grpc_call * call,grpc_call_credentials * creds)923 grpcsharp_call_set_credentials(grpc_call* call, grpc_call_credentials* creds) {
924   return grpc_call_set_credentials(call, creds);
925 }
926 
927 /* Server */
928 
929 GPR_EXPORT grpc_server* GPR_CALLTYPE
grpcsharp_server_create(const grpc_channel_args * args)930 grpcsharp_server_create(const grpc_channel_args* args) {
931   return grpc_server_create(args, NULL);
932 }
933 
grpcsharp_server_register_completion_queue(grpc_server * server,grpc_completion_queue * cq)934 GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_register_completion_queue(
935     grpc_server* server, grpc_completion_queue* cq) {
936   grpc_server_register_completion_queue(server, cq, NULL);
937 }
938 
grpcsharp_server_add_insecure_http2_port(grpc_server * server,const char * addr)939 GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_insecure_http2_port(
940     grpc_server* server, const char* addr) {
941   return grpc_server_add_insecure_http2_port(server, addr);
942 }
943 
grpcsharp_server_start(grpc_server * server)944 GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_start(grpc_server* server) {
945   grpc_server_start(server);
946 }
947 
grpcsharp_server_shutdown_and_notify_callback(grpc_server * server,grpc_completion_queue * cq,grpcsharp_batch_context * ctx)948 GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_shutdown_and_notify_callback(
949     grpc_server* server, grpc_completion_queue* cq,
950     grpcsharp_batch_context* ctx) {
951   grpc_server_shutdown_and_notify(server, cq, ctx);
952 }
953 
954 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_server_cancel_all_calls(grpc_server * server)955 grpcsharp_server_cancel_all_calls(grpc_server* server) {
956   grpc_server_cancel_all_calls(server);
957 }
958 
grpcsharp_server_destroy(grpc_server * server)959 GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_destroy(grpc_server* server) {
960   grpc_server_destroy(server);
961 }
962 
963 GPR_EXPORT grpc_call_error GPR_CALLTYPE
grpcsharp_server_request_call(grpc_server * server,grpc_completion_queue * cq,grpcsharp_request_call_context * ctx)964 grpcsharp_server_request_call(grpc_server* server, grpc_completion_queue* cq,
965                               grpcsharp_request_call_context* ctx) {
966   return grpc_server_request_call(server, &(ctx->call), &(ctx->call_details),
967                                   &(ctx->request_metadata), cq, cq, ctx);
968 }
969 
970 /* Native callback dispatcher */
971 
972 typedef int(GPR_CALLTYPE* grpcsharp_native_callback_dispatcher_func)(
973     void* tag, void* arg0, void* arg1, void* arg2, void* arg3, void* arg4,
974     void* arg5);
975 
976 static grpcsharp_native_callback_dispatcher_func native_callback_dispatcher =
977     NULL;
978 
grpcsharp_native_callback_dispatcher_init(grpcsharp_native_callback_dispatcher_func func)979 GPR_EXPORT void GPR_CALLTYPE grpcsharp_native_callback_dispatcher_init(
980     grpcsharp_native_callback_dispatcher_func func) {
981   GPR_ASSERT(func);
982   native_callback_dispatcher = func;
983 }
984 
985 /* Security */
986 
987 static char* default_pem_root_certs = NULL;
988 
override_ssl_roots_handler(char ** pem_root_certs)989 static grpc_ssl_roots_override_result override_ssl_roots_handler(
990     char** pem_root_certs) {
991   if (!default_pem_root_certs) {
992     *pem_root_certs = NULL;
993     return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
994   }
995   *pem_root_certs = gpr_strdup(default_pem_root_certs);
996   return GRPC_SSL_ROOTS_OVERRIDE_OK;
997 }
998 
999 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_override_default_ssl_roots(const char * pem_root_certs)1000 grpcsharp_override_default_ssl_roots(const char* pem_root_certs) {
1001   /*
1002    * This currently wastes ~300kB of memory by keeping a copy of roots
1003    * in a static variable, but for desktop/server use, the overhead
1004    * is negligible. In the future, we might want to change the behavior
1005    * for mobile (e.g. Xamarin).
1006    */
1007   default_pem_root_certs = gpr_strdup(pem_root_certs);
1008   grpc_set_ssl_roots_override_callback(override_ssl_roots_handler);
1009 }
1010 
grpcsharp_verify_peer_destroy_handler(void * userdata)1011 static void grpcsharp_verify_peer_destroy_handler(void* userdata) {
1012   native_callback_dispatcher(userdata, NULL, NULL, (void*)1, NULL, NULL, NULL);
1013 }
1014 
grpcsharp_verify_peer_handler(const char * target_name,const char * peer_pem,void * userdata)1015 static int grpcsharp_verify_peer_handler(const char* target_name,
1016                                          const char* peer_pem, void* userdata) {
1017   return native_callback_dispatcher(userdata, (void*)target_name,
1018                                     (void*)peer_pem, (void*)0, NULL, NULL,
1019                                     NULL);
1020 }
1021 
1022 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)1023 grpcsharp_ssl_credentials_create(const char* pem_root_certs,
1024                                  const char* key_cert_pair_cert_chain,
1025                                  const char* key_cert_pair_private_key,
1026                                  void* verify_peer_callback_tag) {
1027   grpc_ssl_pem_key_cert_pair key_cert_pair;
1028   verify_peer_options verify_options;
1029   grpc_ssl_pem_key_cert_pair* key_cert_pair_ptr = NULL;
1030   verify_peer_options* verify_options_ptr = NULL;
1031 
1032   if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
1033     memset(&key_cert_pair, 0, sizeof(key_cert_pair));
1034     key_cert_pair.cert_chain = key_cert_pair_cert_chain;
1035     key_cert_pair.private_key = key_cert_pair_private_key;
1036     key_cert_pair_ptr = &key_cert_pair;
1037   } else {
1038     GPR_ASSERT(!key_cert_pair_cert_chain);
1039     GPR_ASSERT(!key_cert_pair_private_key);
1040   }
1041 
1042   if (verify_peer_callback_tag != NULL) {
1043     memset(&verify_options, 0, sizeof(verify_peer_options));
1044     verify_options.verify_peer_callback_userdata = verify_peer_callback_tag;
1045     verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler;
1046     verify_options.verify_peer_callback = grpcsharp_verify_peer_handler;
1047     verify_options_ptr = &verify_options;
1048   }
1049 
1050   return grpc_ssl_credentials_create(pem_root_certs, key_cert_pair_ptr,
1051                                      verify_options_ptr, NULL);
1052 }
1053 
1054 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_channel_credentials_release(grpc_channel_credentials * creds)1055 grpcsharp_channel_credentials_release(grpc_channel_credentials* creds) {
1056   grpc_channel_credentials_release(creds);
1057 }
1058 
1059 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_call_credentials_release(grpc_call_credentials * creds)1060 grpcsharp_call_credentials_release(grpc_call_credentials* creds) {
1061   grpc_call_credentials_release(creds);
1062 }
1063 
grpcsharp_secure_channel_create(grpc_channel_credentials * creds,const char * target,const grpc_channel_args * args)1064 GPR_EXPORT grpc_channel* GPR_CALLTYPE grpcsharp_secure_channel_create(
1065     grpc_channel_credentials* creds, const char* target,
1066     const grpc_channel_args* args) {
1067   return grpc_secure_channel_create(creds, target, args, NULL);
1068 }
1069 
1070 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)1071 grpcsharp_ssl_server_credentials_create(
1072     const char* pem_root_certs, const char** key_cert_pair_cert_chain_array,
1073     const char** key_cert_pair_private_key_array, size_t num_key_cert_pairs,
1074     grpc_ssl_client_certificate_request_type client_request_type) {
1075   size_t i;
1076   grpc_server_credentials* creds;
1077   grpc_ssl_pem_key_cert_pair* key_cert_pairs =
1078       gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
1079   memset(key_cert_pairs, 0,
1080          sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
1081 
1082   for (i = 0; i < num_key_cert_pairs; i++) {
1083     if (key_cert_pair_cert_chain_array[i] ||
1084         key_cert_pair_private_key_array[i]) {
1085       key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i];
1086       key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
1087     }
1088   }
1089   creds = grpc_ssl_server_credentials_create_ex(pem_root_certs, key_cert_pairs,
1090                                                 num_key_cert_pairs,
1091                                                 client_request_type, NULL);
1092   gpr_free(key_cert_pairs);
1093   return creds;
1094 }
1095 
1096 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_server_credentials_release(grpc_server_credentials * creds)1097 grpcsharp_server_credentials_release(grpc_server_credentials* creds) {
1098   grpc_server_credentials_release(creds);
1099 }
1100 
grpcsharp_server_add_secure_http2_port(grpc_server * server,const char * addr,grpc_server_credentials * creds)1101 GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_secure_http2_port(
1102     grpc_server* server, const char* addr, grpc_server_credentials* creds) {
1103   return grpc_server_add_secure_http2_port(server, addr, creds);
1104 }
1105 
1106 GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE
grpcsharp_composite_channel_credentials_create(grpc_channel_credentials * channel_creds,grpc_call_credentials * call_creds)1107 grpcsharp_composite_channel_credentials_create(
1108     grpc_channel_credentials* channel_creds,
1109     grpc_call_credentials* call_creds) {
1110   return grpc_composite_channel_credentials_create(channel_creds, call_creds,
1111                                                    NULL);
1112 }
1113 
1114 GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
grpcsharp_composite_call_credentials_create(grpc_call_credentials * creds1,grpc_call_credentials * creds2)1115 grpcsharp_composite_call_credentials_create(grpc_call_credentials* creds1,
1116                                             grpc_call_credentials* creds2) {
1117   return grpc_composite_call_credentials_create(creds1, creds2, NULL);
1118 }
1119 
1120 /* Metadata credentials plugin */
1121 
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)1122 GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
1123     grpc_credentials_plugin_metadata_cb cb, void* user_data,
1124     grpc_metadata_array* metadata, grpc_status_code status,
1125     const char* error_details) {
1126   if (metadata) {
1127     cb(user_data, metadata->metadata, metadata->count, status, error_details);
1128   } else {
1129     cb(user_data, NULL, 0, status, error_details);
1130   }
1131 }
1132 
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)1133 static int grpcsharp_get_metadata_handler(
1134     void* state, grpc_auth_metadata_context context,
1135     grpc_credentials_plugin_metadata_cb cb, void* user_data,
1136     grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
1137     size_t* num_creds_md, grpc_status_code* status,
1138     const char** error_details) {
1139   // the "context" object and its contents are only guaranteed to live until
1140   // this handler returns (which could result in use-after-free for async
1141   // handling of the callback), so the C# counterpart of this handler
1142   // must make a copy of the "service_url" and "method_name" strings before
1143   // it returns if it wants to uses these strings.
1144   native_callback_dispatcher(state, (void*)context.service_url,
1145                              (void*)context.method_name, cb, user_data,
1146                              (void*)0, NULL);
1147   return 0; /* Asynchronous return. */
1148 }
1149 
grpcsharp_metadata_credentials_destroy_handler(void * state)1150 static void grpcsharp_metadata_credentials_destroy_handler(void* state) {
1151   native_callback_dispatcher(state, NULL, NULL, NULL, NULL, (void*)1, NULL);
1152 }
1153 
1154 GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
grpcsharp_metadata_credentials_create_from_plugin(void * callback_tag)1155 grpcsharp_metadata_credentials_create_from_plugin(void* callback_tag) {
1156   grpc_metadata_credentials_plugin plugin;
1157   plugin.get_metadata = grpcsharp_get_metadata_handler;
1158   plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
1159   plugin.state = callback_tag;
1160   plugin.type = "";
1161   // TODO(yihuazhang): Expose min_security_level via the C# API so
1162   // that applications can decide what minimum security level their
1163   // plugins require.
1164   return grpc_metadata_credentials_create_from_plugin(
1165       plugin, GRPC_PRIVACY_AND_INTEGRITY, NULL);
1166 }
1167 
1168 /* Auth context */
1169 
1170 GPR_EXPORT grpc_auth_context* GPR_CALLTYPE
grpcsharp_call_auth_context(grpc_call * call)1171 grpcsharp_call_auth_context(grpc_call* call) {
1172   return grpc_call_auth_context(call);
1173 }
1174 
1175 GPR_EXPORT const char* GPR_CALLTYPE
grpcsharp_auth_context_peer_identity_property_name(const grpc_auth_context * ctx)1176 grpcsharp_auth_context_peer_identity_property_name(
1177     const grpc_auth_context* ctx) {
1178   return grpc_auth_context_peer_identity_property_name(ctx);
1179 }
1180 
1181 GPR_EXPORT grpc_auth_property_iterator GPR_CALLTYPE
grpcsharp_auth_context_property_iterator(const grpc_auth_context * ctx)1182 grpcsharp_auth_context_property_iterator(const grpc_auth_context* ctx) {
1183   return grpc_auth_context_property_iterator(ctx);
1184 }
1185 
1186 GPR_EXPORT const grpc_auth_property* GPR_CALLTYPE
grpcsharp_auth_property_iterator_next(grpc_auth_property_iterator * it)1187 grpcsharp_auth_property_iterator_next(grpc_auth_property_iterator* it) {
1188   return grpc_auth_property_iterator_next(it);
1189 }
1190 
1191 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_auth_context_release(grpc_auth_context * ctx)1192 grpcsharp_auth_context_release(grpc_auth_context* ctx) {
1193   grpc_auth_context_release(ctx);
1194 }
1195 
1196 /* Logging */
1197 
1198 typedef void(GPR_CALLTYPE* grpcsharp_log_func)(const char* file, int32_t line,
1199                                                uint64_t thd_id,
1200                                                const char* severity_string,
1201                                                const char* msg);
1202 static grpcsharp_log_func log_func = NULL;
1203 
1204 /* Redirects gpr_log to log_func callback */
grpcsharp_log_handler(gpr_log_func_args * args)1205 static void grpcsharp_log_handler(gpr_log_func_args* args) {
1206   log_func(args->file, args->line, gpr_thd_currentid(),
1207            gpr_log_severity_string(args->severity), args->message);
1208 }
1209 
grpcsharp_redirect_log(grpcsharp_log_func func)1210 GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) {
1211   GPR_ASSERT(func);
1212   log_func = func;
1213   gpr_set_log_function(grpcsharp_log_handler);
1214 }
1215 
1216 typedef void(GPR_CALLTYPE* test_callback_funcptr)(int32_t success);
1217 
1218 /* Slice buffer functionality */
grpcsharp_slice_buffer_create()1219 GPR_EXPORT grpc_slice_buffer* GPR_CALLTYPE grpcsharp_slice_buffer_create() {
1220   grpc_slice_buffer* slice_buffer =
1221       (grpc_slice_buffer*)gpr_malloc(sizeof(grpc_slice_buffer));
1222   grpc_slice_buffer_init(slice_buffer);
1223   return slice_buffer;
1224 }
1225 
1226 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_slice_buffer_reset_and_unref(grpc_slice_buffer * buffer)1227 grpcsharp_slice_buffer_reset_and_unref(grpc_slice_buffer* buffer) {
1228   grpc_slice_buffer_reset_and_unref(buffer);
1229 }
1230 
1231 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_slice_buffer_destroy(grpc_slice_buffer * buffer)1232 grpcsharp_slice_buffer_destroy(grpc_slice_buffer* buffer) {
1233   grpc_slice_buffer_destroy(buffer);
1234   gpr_free(buffer);
1235 }
1236 
1237 GPR_EXPORT size_t GPR_CALLTYPE
grpcsharp_slice_buffer_slice_count(grpc_slice_buffer * buffer)1238 grpcsharp_slice_buffer_slice_count(grpc_slice_buffer* buffer) {
1239   return buffer->count;
1240 }
1241 
1242 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)1243 grpcsharp_slice_buffer_slice_peek(grpc_slice_buffer* buffer, size_t index,
1244                                   size_t* slice_len, uint8_t** slice_data_ptr) {
1245   GPR_ASSERT(buffer->count > index);
1246   grpc_slice* slice_ptr = &buffer->slices[index];
1247   *slice_len = GRPC_SLICE_LENGTH(*slice_ptr);
1248   *slice_data_ptr = GRPC_SLICE_START_PTR(*slice_ptr);
1249 }
1250 
grpcsharp_slice_buffer_adjust_tail_space(grpc_slice_buffer * buffer,size_t available_tail_space,size_t requested_tail_space)1251 GPR_EXPORT void* GPR_CALLTYPE grpcsharp_slice_buffer_adjust_tail_space(
1252     grpc_slice_buffer* buffer, size_t available_tail_space,
1253     size_t requested_tail_space) {
1254   if (available_tail_space == requested_tail_space) {
1255     // nothing to do
1256   } else if (available_tail_space >= requested_tail_space) {
1257     grpc_slice_buffer_trim_end(
1258         buffer, available_tail_space - requested_tail_space, NULL);
1259   } else {
1260     if (available_tail_space > 0) {
1261       grpc_slice_buffer_trim_end(buffer, available_tail_space, NULL);
1262     }
1263 
1264     grpc_slice new_slice = grpc_slice_malloc(requested_tail_space);
1265     // grpc_slice_buffer_add_indexed always adds as a new slice entry into the
1266     // sb (which is suboptimal in some cases) but it doesn't have the problem of
1267     // sometimes splitting the continguous new_slice across two different slices
1268     // (like grpc_slice_buffer_add would)
1269     grpc_slice_buffer_add_indexed(buffer, new_slice);
1270   }
1271 
1272   if (buffer->count == 0) {
1273     return NULL;
1274   }
1275   grpc_slice* last_slice = &(buffer->slices[buffer->count - 1]);
1276   return GRPC_SLICE_END_PTR(*last_slice) - requested_tail_space;
1277 }
1278 
1279 /* Version info */
grpcsharp_version_string()1280 GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_version_string() {
1281   return grpc_version_string();
1282 }
1283 
1284 /* For testing */
1285 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_test_callback(test_callback_funcptr callback)1286 grpcsharp_test_callback(test_callback_funcptr callback) {
1287   callback(1);
1288 }
1289 
1290 /* For testing */
grpcsharp_test_nop(void * ptr)1291 GPR_EXPORT void* GPR_CALLTYPE grpcsharp_test_nop(void* ptr) { return ptr; }
1292 
1293 /* For testing */
grpcsharp_sizeof_grpc_event(void)1294 GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) {
1295   return sizeof(grpc_event);
1296 }
1297 
1298 /* Override a method for testing */
1299 GPR_EXPORT void GPR_CALLTYPE
grpcsharp_test_override_method(const char * method_name,const char * variant)1300 grpcsharp_test_override_method(const char* method_name, const char* variant) {
1301   if (strcmp("grpcsharp_call_start_batch", method_name) == 0) {
1302     if (strcmp("nop", variant) == 0) {
1303       g_call_start_batch_func = grpcsharp_call_start_batch_nop;
1304     } else {
1305       GPR_ASSERT(0);
1306     }
1307   } else {
1308     GPR_ASSERT(0);
1309   }
1310 }
1311