• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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