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