LCOV - code coverage report
Current view: top level - csharp/ext - grpc_csharp_ext.c (source / functions) Hit Total Coverage
Test: tmp.CaZ6RjdVn2 Lines: 456 465 98.1 %
Date: 2015-12-10 22:15:08 Functions: 88 90 97.8 %

          Line data    Source code
       1             : /*
       2             :  *
       3             :  * Copyright 2015, Google Inc.
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions are
       8             :  * met:
       9             :  *
      10             :  *     * Redistributions of source code must retain the above copyright
      11             :  * notice, this list of conditions and the following disclaimer.
      12             :  *     * Redistributions in binary form must reproduce the above
      13             :  * copyright notice, this list of conditions and the following disclaimer
      14             :  * in the documentation and/or other materials provided with the
      15             :  * distribution.
      16             :  *     * Neither the name of Google Inc. nor the names of its
      17             :  * contributors may be used to endorse or promote products derived from
      18             :  * this software without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             :  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             :  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             :  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             :  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             :  *
      32             :  */
      33             : 
      34             : #include "src/core/support/string.h"
      35             : 
      36             : #include <grpc/byte_buffer_reader.h>
      37             : #include <grpc/support/port_platform.h>
      38             : #include <grpc/support/alloc.h>
      39             : #include <grpc/support/log.h>
      40             : #include <grpc/support/slice.h>
      41             : #include <grpc/support/string_util.h>
      42             : #include <grpc/support/thd.h>
      43             : #include <grpc/grpc.h>
      44             : #include <grpc/grpc_security.h>
      45             : 
      46             : #include <string.h>
      47             : 
      48             : #ifdef GPR_WIN32
      49             : #define GPR_EXPORT __declspec(dllexport)
      50             : #define GPR_CALLTYPE __stdcall
      51             : #endif
      52             : 
      53             : #ifndef GPR_EXPORT
      54             : #define GPR_EXPORT
      55             : #endif
      56             : 
      57             : #ifndef GPR_CALLTYPE
      58             : #define GPR_CALLTYPE
      59             : #endif
      60             : 
      61         154 : grpc_byte_buffer *string_to_byte_buffer(const char *buffer, size_t len) {
      62         154 :   gpr_slice slice = gpr_slice_from_copied_buffer(buffer, len);
      63         154 :   grpc_byte_buffer *bb = grpc_raw_byte_buffer_create(&slice, 1);
      64         154 :   gpr_slice_unref(slice);
      65         154 :   return bb;
      66             : }
      67             : 
      68             : /*
      69             :  * Helper to maintain lifetime of batch op inputs and store batch op outputs.
      70             :  */
      71             : typedef struct grpcsharp_batch_context {
      72             :   grpc_metadata_array send_initial_metadata;
      73             :   grpc_byte_buffer *send_message;
      74             :   struct {
      75             :     grpc_metadata_array trailing_metadata;
      76             :     char *status_details;
      77             :   } send_status_from_server;
      78             :   grpc_metadata_array recv_initial_metadata;
      79             :   grpc_byte_buffer *recv_message;
      80             :   struct {
      81             :     grpc_metadata_array trailing_metadata;
      82             :     grpc_status_code status;
      83             :     char *status_details;
      84             :     size_t status_details_capacity;
      85             :   } recv_status_on_client;
      86             :   int recv_close_on_server_cancelled;
      87             :   struct {
      88             :     grpc_call *call;
      89             :     grpc_call_details call_details;
      90             :     grpc_metadata_array request_metadata;
      91             :   } server_rpc_new;
      92             : } grpcsharp_batch_context;
      93             : 
      94         690 : GPR_EXPORT grpcsharp_batch_context *GPR_CALLTYPE grpcsharp_batch_context_create() {
      95         690 :   grpcsharp_batch_context *ctx = gpr_malloc(sizeof(grpcsharp_batch_context));
      96         690 :   memset(ctx, 0, sizeof(grpcsharp_batch_context));
      97         690 :   return ctx;
      98             : }
      99             : 
     100             : /*
     101             :  * Destroys array->metadata.
     102             :  * The array pointer itself is not freed.
     103             :  */
     104        2070 : void grpcsharp_metadata_array_destroy_metadata_only(
     105             :     grpc_metadata_array *array) {
     106        2070 :   gpr_free(array->metadata);
     107        2070 : }
     108             : 
     109             : /*
     110             :  * Destroys keys, values and array->metadata.
     111             :  * The array pointer itself is not freed.
     112             :  */
     113        1523 : void grpcsharp_metadata_array_destroy_metadata_including_entries(
     114             :     grpc_metadata_array *array) {
     115             :   size_t i;
     116        1523 :   if (array->metadata) {
     117          40 :     for (i = 0; i < array->count; i++) {
     118          23 :       gpr_free((void *)array->metadata[i].key);
     119          23 :       gpr_free((void *)array->metadata[i].value);
     120             :     }
     121             :   }
     122        1523 :   gpr_free(array->metadata);
     123        1523 : }
     124             : 
     125             : /*
     126             :  * Fully destroys the metadata array.
     127             :  */
     128             : GPR_EXPORT void GPR_CALLTYPE
     129         143 : grpcsharp_metadata_array_destroy_full(grpc_metadata_array *array) {
     130         143 :   if (!array) {
     131         143 :     return;
     132             :   }
     133         143 :   grpcsharp_metadata_array_destroy_metadata_including_entries(array);
     134         143 :   gpr_free(array);
     135             : }
     136             : 
     137             : /*
     138             :  * Creates an empty metadata array with given capacity.
     139             :  * Array can later be destroyed by grpc_metadata_array_destroy_full.
     140             :  */
     141             : GPR_EXPORT grpc_metadata_array *GPR_CALLTYPE
     142         143 : grpcsharp_metadata_array_create(size_t capacity) {
     143         143 :   grpc_metadata_array *array =
     144             :       (grpc_metadata_array *)gpr_malloc(sizeof(grpc_metadata_array));
     145         143 :   grpc_metadata_array_init(array);
     146         143 :   array->capacity = capacity;
     147         143 :   array->count = 0;
     148         143 :   if (capacity > 0) {
     149          17 :     array->metadata =
     150          17 :         (grpc_metadata *)gpr_malloc(sizeof(grpc_metadata) * capacity);
     151          17 :     memset(array->metadata, 0, sizeof(grpc_metadata) * capacity);
     152             :   } else {
     153         126 :     array->metadata = NULL;
     154             :   }
     155         143 :   return array;
     156             : }
     157             : 
     158             : GPR_EXPORT void GPR_CALLTYPE
     159          23 : grpcsharp_metadata_array_add(grpc_metadata_array *array, const char *key,
     160             :                              const char *value, size_t value_length) {
     161          23 :   size_t i = array->count;
     162          23 :   GPR_ASSERT(array->count < array->capacity);
     163          23 :   array->metadata[i].key = gpr_strdup(key);
     164          23 :   array->metadata[i].value = (char *)gpr_malloc(value_length);
     165          23 :   memcpy((void *)array->metadata[i].value, value, value_length);
     166          23 :   array->metadata[i].value_length = value_length;
     167          23 :   array->count++;
     168          23 : }
     169             : 
     170             : GPR_EXPORT gpr_intptr GPR_CALLTYPE
     171         209 : grpcsharp_metadata_array_count(grpc_metadata_array *array) {
     172         209 :   return (gpr_intptr)array->count;
     173             : }
     174             : 
     175             : GPR_EXPORT const char *GPR_CALLTYPE
     176          89 : grpcsharp_metadata_array_get_key(grpc_metadata_array *array, size_t index) {
     177          89 :   GPR_ASSERT(index < array->count);
     178          89 :   return array->metadata[index].key;
     179             : }
     180             : 
     181             : GPR_EXPORT const char *GPR_CALLTYPE
     182          89 : grpcsharp_metadata_array_get_value(grpc_metadata_array *array, size_t index) {
     183          89 :   GPR_ASSERT(index < array->count);
     184          89 :   return array->metadata[index].value;
     185             : }
     186             : 
     187          89 : GPR_EXPORT gpr_intptr GPR_CALLTYPE grpcsharp_metadata_array_get_value_length(
     188             :     grpc_metadata_array *array, size_t index) {
     189          89 :   GPR_ASSERT(index < array->count);
     190          89 :   return (gpr_intptr)array->metadata[index].value_length;
     191             : }
     192             : 
     193             : /* Move contents of metadata array */
     194         137 : void grpcsharp_metadata_array_move(grpc_metadata_array *dest,
     195             :                                    grpc_metadata_array *src) {
     196         137 :   if (!src) {
     197           0 :     dest->capacity = 0;
     198           0 :     dest->count = 0;
     199           0 :     dest->metadata = NULL;
     200         137 :     return;
     201             :   }
     202             : 
     203         137 :   dest->capacity = src->capacity;
     204         137 :   dest->count = src->count;
     205         137 :   dest->metadata = src->metadata;
     206             : 
     207         137 :   src->capacity = 0;
     208         137 :   src->count = 0;
     209         137 :   src->metadata = NULL;
     210             : }
     211             : 
     212         690 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) {
     213         690 :   if (!ctx) {
     214         690 :     return;
     215             :   }
     216         690 :   grpcsharp_metadata_array_destroy_metadata_including_entries(
     217             :       &(ctx->send_initial_metadata));
     218             : 
     219         690 :   grpc_byte_buffer_destroy(ctx->send_message);
     220             : 
     221         690 :   grpcsharp_metadata_array_destroy_metadata_including_entries(
     222             :       &(ctx->send_status_from_server.trailing_metadata));
     223         690 :   gpr_free(ctx->send_status_from_server.status_details);
     224             : 
     225         690 :   grpcsharp_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata));
     226             : 
     227         690 :   grpc_byte_buffer_destroy(ctx->recv_message);
     228             : 
     229         690 :   grpcsharp_metadata_array_destroy_metadata_only(
     230             :       &(ctx->recv_status_on_client.trailing_metadata));
     231         690 :   gpr_free((void *)ctx->recv_status_on_client.status_details);
     232             : 
     233             :   /* NOTE: ctx->server_rpc_new.call is not destroyed because callback handler is
     234             :      supposed
     235             :      to take its ownership. */
     236             : 
     237         690 :   grpc_call_details_destroy(&(ctx->server_rpc_new.call_details));
     238         690 :   grpcsharp_metadata_array_destroy_metadata_only(
     239             :       &(ctx->server_rpc_new.request_metadata));
     240             : 
     241         690 :   gpr_free(ctx);
     242             : }
     243             : 
     244             : GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE
     245          70 : grpcsharp_batch_context_recv_initial_metadata(
     246             :     const grpcsharp_batch_context *ctx) {
     247          70 :   return &(ctx->recv_initial_metadata);
     248             : }
     249             : 
     250         238 : GPR_EXPORT gpr_intptr GPR_CALLTYPE grpcsharp_batch_context_recv_message_length(
     251             :     const grpcsharp_batch_context *ctx) {
     252         238 :   if (!ctx->recv_message) {
     253          87 :     return -1;
     254             :   }
     255         151 :   return (gpr_intptr)grpc_byte_buffer_length(ctx->recv_message);
     256             : }
     257             : 
     258             : /*
     259             :  * Copies data from recv_message to a buffer. Fatal error occurs if
     260             :  * buffer is too small.
     261             :  */
     262         151 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_batch_context_recv_message_to_buffer(
     263             :     const grpcsharp_batch_context *ctx, char *buffer, size_t buffer_len) {
     264             :   grpc_byte_buffer_reader reader;
     265             :   gpr_slice slice;
     266         151 :   size_t offset = 0;
     267             : 
     268         151 :   grpc_byte_buffer_reader_init(&reader, ctx->recv_message);
     269             : 
     270         784 :   while (grpc_byte_buffer_reader_next(&reader, &slice)) {
     271         482 :     size_t len = GPR_SLICE_LENGTH(slice);
     272         482 :     GPR_ASSERT(offset + len <= buffer_len);
     273         589 :     memcpy(buffer + offset, GPR_SLICE_START_PTR(slice),
     274         589 :            GPR_SLICE_LENGTH(slice));
     275         482 :     offset += len;
     276         482 :     gpr_slice_unref(slice);
     277             :   }
     278         151 : }
     279             : 
     280             : GPR_EXPORT grpc_status_code GPR_CALLTYPE
     281          70 : grpcsharp_batch_context_recv_status_on_client_status(
     282             :     const grpcsharp_batch_context *ctx) {
     283          70 :   return ctx->recv_status_on_client.status;
     284             : }
     285             : 
     286             : GPR_EXPORT const char *GPR_CALLTYPE
     287          70 : grpcsharp_batch_context_recv_status_on_client_details(
     288             :     const grpcsharp_batch_context *ctx) {
     289          70 :   return ctx->recv_status_on_client.status_details;
     290             : }
     291             : 
     292             : GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE
     293          70 : grpcsharp_batch_context_recv_status_on_client_trailing_metadata(
     294             :     const grpcsharp_batch_context *ctx) {
     295          70 :   return &(ctx->recv_status_on_client.trailing_metadata);
     296             : }
     297             : 
     298          68 : GPR_EXPORT grpc_call *GPR_CALLTYPE grpcsharp_batch_context_server_rpc_new_call(
     299             :     const grpcsharp_batch_context *ctx) {
     300          68 :   return ctx->server_rpc_new.call;
     301             : }
     302             : 
     303             : GPR_EXPORT const char *GPR_CALLTYPE
     304          68 : grpcsharp_batch_context_server_rpc_new_method(
     305             :     const grpcsharp_batch_context *ctx) {
     306          68 :   return ctx->server_rpc_new.call_details.method;
     307             : }
     308             : 
     309          68 : GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_batch_context_server_rpc_new_host(
     310             :     const grpcsharp_batch_context *ctx) {
     311          68 :   return ctx->server_rpc_new.call_details.host;
     312             : }
     313             : 
     314             : GPR_EXPORT gpr_timespec GPR_CALLTYPE
     315          68 : grpcsharp_batch_context_server_rpc_new_deadline(
     316             :     const grpcsharp_batch_context *ctx) {
     317          68 :   return ctx->server_rpc_new.call_details.deadline;
     318             : }
     319             : 
     320             : GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE
     321          68 : grpcsharp_batch_context_server_rpc_new_request_metadata(
     322             :     const grpcsharp_batch_context *ctx) {
     323          68 :   return &(ctx->server_rpc_new.request_metadata);
     324             : }
     325             : 
     326             : GPR_EXPORT gpr_int32 GPR_CALLTYPE
     327          68 : grpcsharp_batch_context_recv_close_on_server_cancelled(
     328             :     const grpcsharp_batch_context *ctx) {
     329          68 :   return (gpr_int32) ctx->recv_close_on_server_cancelled;
     330             : }
     331             : 
     332             : /* Init & shutdown */
     333             : 
     334         153 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_init(void) { grpc_init(); }
     335             : 
     336         149 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_shutdown(void) { grpc_shutdown(); }
     337             : 
     338             : /* Completion queue */
     339             : 
     340             : GPR_EXPORT grpc_completion_queue *GPR_CALLTYPE
     341         111 : grpcsharp_completion_queue_create(void) {
     342         111 :   return grpc_completion_queue_create(NULL);
     343             : }
     344             : 
     345             : GPR_EXPORT void GPR_CALLTYPE
     346          59 : grpcsharp_completion_queue_shutdown(grpc_completion_queue *cq) {
     347          59 :   grpc_completion_queue_shutdown(cq);
     348          59 : }
     349             : 
     350             : GPR_EXPORT void GPR_CALLTYPE
     351         111 : grpcsharp_completion_queue_destroy(grpc_completion_queue *cq) {
     352         111 :   grpc_completion_queue_destroy(cq);
     353         111 : }
     354             : 
     355             : GPR_EXPORT grpc_event GPR_CALLTYPE
     356         893 : grpcsharp_completion_queue_next(grpc_completion_queue *cq) {
     357         893 :   return grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
     358             :                                     NULL);
     359             : }
     360             : 
     361             : GPR_EXPORT grpc_event GPR_CALLTYPE
     362          30 : grpcsharp_completion_queue_pluck(grpc_completion_queue *cq, void *tag) {
     363          30 :   return grpc_completion_queue_pluck(cq, tag,
     364             :                                      gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
     365             : }
     366             : 
     367             : /* Channel */
     368             : 
     369             : GPR_EXPORT grpc_channel *GPR_CALLTYPE
     370             : 
     371          46 : grpcsharp_insecure_channel_create(const char *target, const grpc_channel_args *args) {
     372          46 :   return grpc_insecure_channel_create(target, args, NULL);
     373             : }
     374             : 
     375          47 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_destroy(grpc_channel *channel) {
     376          47 :   grpc_channel_destroy(channel);
     377          47 : }
     378             : 
     379             : GPR_EXPORT grpc_call *GPR_CALLTYPE
     380          71 : grpcsharp_channel_create_call(grpc_channel *channel, grpc_call *parent_call,
     381             :                               gpr_uint32 propagation_mask,
     382             :                               grpc_completion_queue *cq,
     383             :                               const char *method, const char *host,
     384             :                               gpr_timespec deadline) {
     385          71 :   return grpc_channel_create_call(channel, parent_call, propagation_mask, cq,
     386             :                                   method, host, deadline, NULL);
     387             : }
     388             : 
     389             : GPR_EXPORT grpc_connectivity_state GPR_CALLTYPE
     390           9 : grpcsharp_channel_check_connectivity_state(grpc_channel *channel, gpr_int32 try_to_connect) {
     391           9 :   return grpc_channel_check_connectivity_state(channel, try_to_connect);
     392             : }
     393             : 
     394           3 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_watch_connectivity_state(
     395             :     grpc_channel *channel, grpc_connectivity_state last_observed_state,
     396             :     gpr_timespec deadline, grpc_completion_queue *cq, grpcsharp_batch_context *ctx) {
     397           3 :   grpc_channel_watch_connectivity_state(channel, last_observed_state,
     398             :                                         deadline, cq, ctx);
     399           3 : }
     400             : 
     401           1 : GPR_EXPORT char *GPR_CALLTYPE grpcsharp_channel_get_target(grpc_channel *channel) {
     402           1 :   return grpc_channel_get_target(channel);
     403             : }
     404             : 
     405             : /* Channel args */
     406             : 
     407             : GPR_EXPORT grpc_channel_args *GPR_CALLTYPE
     408          53 : grpcsharp_channel_args_create(size_t num_args) {
     409          53 :   grpc_channel_args *args =
     410             :       (grpc_channel_args *)gpr_malloc(sizeof(grpc_channel_args));
     411          53 :   memset(args, 0, sizeof(grpc_channel_args));
     412             : 
     413          53 :   args->num_args = num_args;
     414          53 :   args->args = (grpc_arg *)gpr_malloc(sizeof(grpc_arg) * num_args);
     415          53 :   memset(args->args, 0, sizeof(grpc_arg) * num_args);
     416          53 :   return args;
     417             : }
     418             : 
     419             : GPR_EXPORT void GPR_CALLTYPE
     420          56 : grpcsharp_channel_args_set_string(grpc_channel_args *args, size_t index,
     421             :                                   const char *key, const char *value) {
     422          56 :   GPR_ASSERT(args);
     423          56 :   GPR_ASSERT(index < args->num_args);
     424          56 :   args->args[index].type = GRPC_ARG_STRING;
     425          56 :   args->args[index].key = gpr_strdup(key);
     426          56 :   args->args[index].value.string = gpr_strdup(value);
     427          56 : }
     428             : 
     429             : GPR_EXPORT void GPR_CALLTYPE
     430           3 : grpcsharp_channel_args_set_integer(grpc_channel_args *args, size_t index,
     431             :                                   const char *key, int value) {
     432           3 :   GPR_ASSERT(args);
     433           3 :   GPR_ASSERT(index < args->num_args);
     434           3 :   args->args[index].type = GRPC_ARG_INTEGER;
     435           3 :   args->args[index].key = gpr_strdup(key);
     436           3 :   args->args[index].value.integer = value;
     437           3 : }
     438             : 
     439             : GPR_EXPORT void GPR_CALLTYPE
     440          53 : grpcsharp_channel_args_destroy(grpc_channel_args *args) {
     441             :   size_t i;
     442          53 :   if (args) {
     443         117 :     for (i = 0; i < args->num_args; i++) {
     444          64 :       gpr_free(args->args[i].key);
     445          64 :       if (args->args[i].type == GRPC_ARG_STRING) {
     446          61 :         gpr_free(args->args[i].value.string);
     447             :       }
     448             :     }
     449          53 :     gpr_free(args->args);
     450          53 :     gpr_free(args);
     451             :   }
     452          53 : }
     453             : 
     454             : /* Timespec */
     455             : 
     456           2 : GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(gpr_clock_type clock_type) {
     457           2 :   return gpr_now(clock_type);
     458             : }
     459             : 
     460         150 : GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_future(gpr_clock_type clock_type) {
     461         150 :   return gpr_inf_future(clock_type);
     462             : }
     463             : 
     464          27 : GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_inf_past(gpr_clock_type clock_type) {
     465          27 :   return gpr_inf_past(clock_type);
     466             : }
     467             : 
     468          66 : GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock) {
     469          66 :   return gpr_convert_clock_type(t, target_clock);
     470             : }
     471             : 
     472           1 : GPR_EXPORT gpr_int32 GPR_CALLTYPE gprsharp_sizeof_timespec(void) {
     473           1 :   return sizeof(gpr_timespec);
     474             : }
     475             : 
     476             : /* Call */
     477             : 
     478          26 : GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel(grpc_call *call) {
     479          26 :   return grpc_call_cancel(call, NULL);
     480             : }
     481             : 
     482             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     483           1 : grpcsharp_call_cancel_with_status(grpc_call *call, grpc_status_code status,
     484             :                                   const char *description) {
     485           1 :   return grpc_call_cancel_with_status(call, status, description, NULL);
     486             : }
     487             : 
     488          66 : GPR_EXPORT char *GPR_CALLTYPE grpcsharp_call_get_peer(grpc_call *call) {
     489          66 :   return grpc_call_get_peer(call);
     490             : }
     491             : 
     492          67 : GPR_EXPORT void GPR_CALLTYPE gprsharp_free(void *p) {
     493          67 :   gpr_free(p);
     494          67 : }
     495             : 
     496         139 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call *call) {
     497         139 :   grpc_call_destroy(call);
     498         139 : }
     499             : 
     500             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     501          42 : grpcsharp_call_start_unary(grpc_call *call, grpcsharp_batch_context *ctx,
     502             :                            const char *send_buffer, size_t send_buffer_len,
     503             :                            grpc_metadata_array *initial_metadata, gpr_uint32 write_flags) {
     504             :   /* TODO: don't use magic number */
     505             :   grpc_op ops[6];
     506          42 :   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
     507          42 :   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
     508             :                                 initial_metadata);
     509          42 :   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
     510          42 :   ops[0].data.send_initial_metadata.metadata =
     511          42 :       ctx->send_initial_metadata.metadata;
     512          42 :   ops[0].flags = 0;
     513          42 :   ops[0].reserved = NULL;
     514             : 
     515          42 :   ops[1].op = GRPC_OP_SEND_MESSAGE;
     516          42 :   ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
     517          42 :   ops[1].data.send_message = ctx->send_message;
     518          42 :   ops[1].flags = write_flags;
     519          42 :   ops[1].reserved = NULL;
     520             : 
     521          42 :   ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
     522          42 :   ops[2].flags = 0;
     523          42 :   ops[2].reserved = NULL;
     524             : 
     525          42 :   ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
     526          42 :   ops[3].data.recv_initial_metadata = &(ctx->recv_initial_metadata);
     527          42 :   ops[3].flags = 0;
     528          42 :   ops[3].reserved = NULL;
     529             : 
     530          42 :   ops[4].op = GRPC_OP_RECV_MESSAGE;
     531          42 :   ops[4].data.recv_message = &(ctx->recv_message);
     532          42 :   ops[4].flags = 0;
     533          42 :   ops[4].reserved = NULL;
     534             : 
     535          42 :   ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
     536          42 :   ops[5].data.recv_status_on_client.trailing_metadata =
     537          42 :       &(ctx->recv_status_on_client.trailing_metadata);
     538          42 :   ops[5].data.recv_status_on_client.status =
     539          42 :       &(ctx->recv_status_on_client.status);
     540             :   /* not using preallocation for status_details */
     541          42 :   ops[5].data.recv_status_on_client.status_details =
     542          42 :       &(ctx->recv_status_on_client.status_details);
     543          42 :   ops[5].data.recv_status_on_client.status_details_capacity =
     544          42 :       &(ctx->recv_status_on_client.status_details_capacity);
     545          42 :   ops[5].flags = 0;
     546          42 :   ops[5].reserved = NULL;
     547             : 
     548          42 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     549             :                                NULL);
     550             : }
     551             : 
     552             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     553          11 : grpcsharp_call_start_client_streaming(grpc_call *call,
     554             :                                       grpcsharp_batch_context *ctx,
     555             :                                       grpc_metadata_array *initial_metadata) {
     556             :   /* TODO: don't use magic number */
     557             :   grpc_op ops[4];
     558          11 :   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
     559          11 :   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
     560             :                                 initial_metadata);
     561          11 :   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
     562          11 :   ops[0].data.send_initial_metadata.metadata =
     563          11 :       ctx->send_initial_metadata.metadata;
     564          11 :   ops[0].flags = 0;
     565          11 :   ops[0].reserved = NULL;
     566             : 
     567          11 :   ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
     568          11 :   ops[1].data.recv_initial_metadata = &(ctx->recv_initial_metadata);
     569          11 :   ops[1].flags = 0;
     570          11 :   ops[1].reserved = NULL;
     571             : 
     572          11 :   ops[2].op = GRPC_OP_RECV_MESSAGE;
     573          11 :   ops[2].data.recv_message = &(ctx->recv_message);
     574          11 :   ops[2].flags = 0;
     575          11 :   ops[2].reserved = NULL;
     576             : 
     577          11 :   ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
     578          11 :   ops[3].data.recv_status_on_client.trailing_metadata =
     579          11 :       &(ctx->recv_status_on_client.trailing_metadata);
     580          11 :   ops[3].data.recv_status_on_client.status =
     581          11 :       &(ctx->recv_status_on_client.status);
     582             :   /* not using preallocation for status_details */
     583          11 :   ops[3].data.recv_status_on_client.status_details =
     584          11 :       &(ctx->recv_status_on_client.status_details);
     585          11 :   ops[3].data.recv_status_on_client.status_details_capacity =
     586          11 :       &(ctx->recv_status_on_client.status_details_capacity);
     587          11 :   ops[3].flags = 0;
     588          11 :   ops[3].reserved = NULL;
     589             : 
     590          11 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     591             :                                NULL);
     592             : }
     593             : 
     594           7 : GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
     595             :     grpc_call *call, grpcsharp_batch_context *ctx, const char *send_buffer,
     596             :     size_t send_buffer_len, grpc_metadata_array *initial_metadata, gpr_uint32 write_flags) {
     597             :   /* TODO: don't use magic number */
     598             :   grpc_op ops[4];
     599           7 :   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
     600           7 :   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
     601             :                                 initial_metadata);
     602           7 :   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
     603           7 :   ops[0].data.send_initial_metadata.metadata =
     604           7 :       ctx->send_initial_metadata.metadata;
     605           7 :   ops[0].flags = 0;
     606           7 :   ops[0].reserved = NULL;
     607             : 
     608           7 :   ops[1].op = GRPC_OP_SEND_MESSAGE;
     609           7 :   ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
     610           7 :   ops[1].data.send_message = ctx->send_message;
     611           7 :   ops[1].flags = write_flags;
     612           7 :   ops[1].reserved = NULL;
     613             : 
     614           7 :   ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
     615           7 :   ops[2].flags = 0;
     616           7 :   ops[2].reserved = NULL;
     617             : 
     618           7 :   ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
     619           7 :   ops[3].data.recv_status_on_client.trailing_metadata =
     620           7 :       &(ctx->recv_status_on_client.trailing_metadata);
     621           7 :   ops[3].data.recv_status_on_client.status =
     622           7 :       &(ctx->recv_status_on_client.status);
     623             :   /* not using preallocation for status_details */
     624           7 :   ops[3].data.recv_status_on_client.status_details =
     625           7 :       &(ctx->recv_status_on_client.status_details);
     626           7 :   ops[3].data.recv_status_on_client.status_details_capacity =
     627           7 :       &(ctx->recv_status_on_client.status_details_capacity);
     628           7 :   ops[3].flags = 0;
     629           7 :   ops[3].reserved = NULL;
     630             : 
     631           7 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     632             :                                NULL);
     633             : }
     634             : 
     635             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     636          10 : grpcsharp_call_start_duplex_streaming(grpc_call *call,
     637             :                                       grpcsharp_batch_context *ctx,
     638             :                                       grpc_metadata_array *initial_metadata) {
     639             :   /* TODO: don't use magic number */
     640             :   grpc_op ops[2];
     641          10 :   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
     642          10 :   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
     643             :                                 initial_metadata);
     644          10 :   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
     645          10 :   ops[0].data.send_initial_metadata.metadata =
     646          10 :       ctx->send_initial_metadata.metadata;
     647          10 :   ops[0].flags = 0;
     648          10 :   ops[0].reserved = NULL;
     649             : 
     650          10 :   ops[1].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
     651          10 :   ops[1].data.recv_status_on_client.trailing_metadata =
     652          10 :       &(ctx->recv_status_on_client.trailing_metadata);
     653          10 :   ops[1].data.recv_status_on_client.status =
     654          10 :       &(ctx->recv_status_on_client.status);
     655             :   /* not using preallocation for status_details */
     656          10 :   ops[1].data.recv_status_on_client.status_details =
     657          10 :       &(ctx->recv_status_on_client.status_details);
     658          10 :   ops[1].data.recv_status_on_client.status_details_capacity =
     659          10 :       &(ctx->recv_status_on_client.status_details_capacity);
     660          10 :   ops[1].flags = 0;
     661          10 :   ops[1].reserved = NULL;
     662             : 
     663          10 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     664             :                                NULL);
     665             : }
     666             : 
     667          17 : GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata(
     668             :   grpc_call *call, grpcsharp_batch_context *ctx) {
     669             :   /* TODO: don't use magic number */
     670             :   grpc_op ops[1];
     671          17 :   ops[0].op = GRPC_OP_RECV_INITIAL_METADATA;
     672          17 :   ops[0].data.recv_initial_metadata = &(ctx->recv_initial_metadata);
     673          17 :   ops[0].flags = 0;
     674          17 :   ops[0].reserved = NULL;
     675             : 
     676          17 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     677             :     NULL);
     678             : }
     679             : 
     680             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     681         105 : grpcsharp_call_send_message(grpc_call *call, grpcsharp_batch_context *ctx,
     682             :                             const char *send_buffer, size_t send_buffer_len,
     683             :                             gpr_uint32 write_flags,
     684             :                             gpr_int32 send_empty_initial_metadata) {
     685             :   /* TODO: don't use magic number */
     686             :   grpc_op ops[2];
     687         105 :   size_t nops = send_empty_initial_metadata ? 2 : 1;
     688         105 :   ops[0].op = GRPC_OP_SEND_MESSAGE;
     689         105 :   ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
     690         105 :   ops[0].data.send_message = ctx->send_message;
     691         105 :   ops[0].flags = write_flags;
     692         105 :   ops[0].reserved = NULL;
     693         105 :   ops[1].op = GRPC_OP_SEND_INITIAL_METADATA;
     694         105 :   ops[1].data.send_initial_metadata.count = 0;
     695         105 :   ops[1].data.send_initial_metadata.metadata = NULL;
     696         105 :   ops[1].flags = 0;
     697         105 :   ops[1].reserved = NULL;
     698             : 
     699         105 :   return grpc_call_start_batch(call, ops, nops, ctx, NULL);
     700             : }
     701             : 
     702             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     703          15 : grpcsharp_call_send_close_from_client(grpc_call *call,
     704             :                                       grpcsharp_batch_context *ctx) {
     705             :   /* TODO: don't use magic number */
     706             :   grpc_op ops[1];
     707          15 :   ops[0].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
     708          15 :   ops[0].flags = 0;
     709          15 :   ops[0].reserved = NULL;
     710             : 
     711          15 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     712             :                                NULL);
     713             : }
     714             : 
     715          59 : GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
     716             :     grpc_call *call, grpcsharp_batch_context *ctx, grpc_status_code status_code,
     717             :     const char *status_details, grpc_metadata_array *trailing_metadata,
     718             :     gpr_int32 send_empty_initial_metadata) {
     719             :   /* TODO: don't use magic number */
     720             :   grpc_op ops[2];
     721          59 :   size_t nops = send_empty_initial_metadata ? 2 : 1;
     722          59 :   ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
     723          59 :   ops[0].data.send_status_from_server.status = status_code;
     724          59 :   ops[0].data.send_status_from_server.status_details =
     725          59 :       gpr_strdup(status_details);
     726          59 :   grpcsharp_metadata_array_move(
     727             :       &(ctx->send_status_from_server.trailing_metadata), trailing_metadata);
     728          59 :   ops[0].data.send_status_from_server.trailing_metadata_count =
     729          59 :       ctx->send_status_from_server.trailing_metadata.count;
     730          59 :   ops[0].data.send_status_from_server.trailing_metadata =
     731          59 :       ctx->send_status_from_server.trailing_metadata.metadata;
     732          59 :   ops[0].flags = 0;
     733          59 :   ops[0].reserved = NULL;
     734          59 :   ops[1].op = GRPC_OP_SEND_INITIAL_METADATA;
     735          59 :   ops[1].data.send_initial_metadata.count = 0;
     736          59 :   ops[1].data.send_initial_metadata.metadata = NULL;
     737          59 :   ops[1].flags = 0;
     738          59 :   ops[1].reserved = NULL;
     739             : 
     740          59 :   return grpc_call_start_batch(call, ops, nops, ctx, NULL);
     741             : }
     742             : 
     743             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     744         185 : grpcsharp_call_recv_message(grpc_call *call, grpcsharp_batch_context *ctx) {
     745             :   /* TODO: don't use magic number */
     746             :   grpc_op ops[1];
     747         185 :   ops[0].op = GRPC_OP_RECV_MESSAGE;
     748         185 :   ops[0].data.recv_message = &(ctx->recv_message);
     749         185 :   ops[0].flags = 0;
     750         185 :   ops[0].reserved = NULL;
     751         185 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     752             :                                NULL);
     753             : }
     754             : 
     755             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     756          68 : grpcsharp_call_start_serverside(grpc_call *call, grpcsharp_batch_context *ctx) {
     757             :   /* TODO: don't use magic number */
     758             :   grpc_op ops[1];
     759          68 :   ops[0].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
     760          68 :   ops[0].data.recv_close_on_server.cancelled =
     761          68 :       (&ctx->recv_close_on_server_cancelled);
     762          68 :   ops[0].flags = 0;
     763          68 :   ops[0].reserved = NULL;
     764             : 
     765          68 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     766             :                                NULL);
     767             : }
     768             : 
     769             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     770           8 : grpcsharp_call_send_initial_metadata(grpc_call *call,
     771             :                                      grpcsharp_batch_context *ctx,
     772             :                                      grpc_metadata_array *initial_metadata) {
     773             :   /* TODO: don't use magic number */
     774             :   grpc_op ops[1];
     775           8 :   ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
     776           8 :   grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
     777             :                                 initial_metadata);
     778           8 :   ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
     779           8 :   ops[0].data.send_initial_metadata.metadata =
     780           8 :       ctx->send_initial_metadata.metadata;
     781           8 :   ops[0].flags = 0;
     782           8 :   ops[0].reserved = NULL;
     783             : 
     784           8 :   return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx,
     785             :                                NULL);
     786             : }
     787             : 
     788           0 : GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_set_credentials(
     789             :     grpc_call *call,
     790             :     grpc_call_credentials *creds) {
     791           0 :   return grpc_call_set_credentials(call, creds);
     792             : }
     793             : 
     794             : /* Server */
     795             : 
     796             : GPR_EXPORT grpc_server *GPR_CALLTYPE
     797          46 : grpcsharp_server_create(grpc_completion_queue *cq,
     798             :                         const grpc_channel_args *args) {
     799          46 :   grpc_server *server = grpc_server_create(args, NULL);
     800          46 :   grpc_server_register_completion_queue(server, cq, NULL);
     801          46 :   return server;
     802             : }
     803             : 
     804             : GPR_EXPORT gpr_int32 GPR_CALLTYPE
     805          43 : grpcsharp_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
     806          43 :   return grpc_server_add_insecure_http2_port(server, addr);
     807             : }
     808             : 
     809          46 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_start(grpc_server *server) {
     810          46 :   grpc_server_start(server);
     811          46 : }
     812             : 
     813             : GPR_EXPORT void GPR_CALLTYPE
     814          46 : grpcsharp_server_shutdown_and_notify_callback(grpc_server *server,
     815             :                                               grpc_completion_queue *cq,
     816             :                                               grpcsharp_batch_context *ctx) {
     817          46 :   grpc_server_shutdown_and_notify(server, cq, ctx);
     818          46 : }
     819             : 
     820           0 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_cancel_all_calls(grpc_server *server) {
     821           0 :   grpc_server_cancel_all_calls(server);
     822           0 : }
     823             : 
     824          44 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_destroy(grpc_server *server) {
     825          44 :   grpc_server_destroy(server);
     826          44 : }
     827             : 
     828             : GPR_EXPORT grpc_call_error GPR_CALLTYPE
     829         114 : grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq,
     830             :                               grpcsharp_batch_context *ctx) {
     831         114 :   return grpc_server_request_call(
     832             :       server, &(ctx->server_rpc_new.call), &(ctx->server_rpc_new.call_details),
     833             :       &(ctx->server_rpc_new.request_metadata), cq, cq, ctx);
     834             : }
     835             : 
     836             : /* Security */
     837             : 
     838             : GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE
     839           3 : grpcsharp_ssl_credentials_create(const char *pem_root_certs,
     840             :                                  const char *key_cert_pair_cert_chain,
     841             :                                  const char *key_cert_pair_private_key) {
     842             :   grpc_ssl_pem_key_cert_pair key_cert_pair;
     843           3 :   if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
     844           1 :     key_cert_pair.cert_chain = key_cert_pair_cert_chain;
     845           1 :     key_cert_pair.private_key = key_cert_pair_private_key;
     846           1 :     return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL);
     847             :   } else {
     848           2 :     GPR_ASSERT(!key_cert_pair_cert_chain);
     849           2 :     GPR_ASSERT(!key_cert_pair_private_key);
     850           2 :     return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL);
     851             :   }
     852             : }
     853             : 
     854           4 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_credentials_release(
     855             :     grpc_channel_credentials *creds) {
     856           4 :   grpc_channel_credentials_release(creds);
     857           4 : }
     858             : 
     859           4 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_credentials_release(
     860             :     grpc_call_credentials *creds) {
     861           4 :   grpc_call_credentials_release(creds);
     862           4 : }
     863             : 
     864             : GPR_EXPORT grpc_channel *GPR_CALLTYPE
     865           3 : grpcsharp_secure_channel_create(grpc_channel_credentials *creds,
     866             :                                 const char *target,
     867             :                                 const grpc_channel_args *args) {
     868           3 :   return grpc_secure_channel_create(creds, target, args, NULL);
     869             : }
     870             : 
     871             : GPR_EXPORT grpc_server_credentials *GPR_CALLTYPE
     872           3 : grpcsharp_ssl_server_credentials_create(
     873             :     const char *pem_root_certs, const char **key_cert_pair_cert_chain_array,
     874             :     const char **key_cert_pair_private_key_array, size_t num_key_cert_pairs,
     875             :     int force_client_auth) {
     876             :   size_t i;
     877             :   grpc_server_credentials *creds;
     878           3 :   grpc_ssl_pem_key_cert_pair *key_cert_pairs =
     879           3 :       gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
     880           3 :   memset(key_cert_pairs, 0,
     881             :          sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
     882             : 
     883           6 :   for (i = 0; i < num_key_cert_pairs; i++) {
     884           3 :     if (key_cert_pair_cert_chain_array[i] ||
     885           0 :         key_cert_pair_private_key_array[i]) {
     886           3 :       key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i];
     887           3 :       key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
     888             :     }
     889             :   }
     890           3 :   creds = grpc_ssl_server_credentials_create(pem_root_certs, key_cert_pairs,
     891             :                                              num_key_cert_pairs,
     892             :                                              force_client_auth, NULL);
     893           3 :   gpr_free(key_cert_pairs);
     894           3 :   return creds;
     895             : }
     896             : 
     897           3 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_credentials_release(
     898             :     grpc_server_credentials *creds) {
     899           3 :   grpc_server_credentials_release(creds);
     900           3 : }
     901             : 
     902             : GPR_EXPORT gpr_int32 GPR_CALLTYPE
     903           3 : grpcsharp_server_add_secure_http2_port(grpc_server *server, const char *addr,
     904             :                                        grpc_server_credentials *creds) {
     905           3 :   return grpc_server_add_secure_http2_port(server, addr, creds);
     906             : }
     907             : 
     908           1 : GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE grpcsharp_composite_channel_credentials_create(
     909             :   grpc_channel_credentials *channel_creds,
     910             :   grpc_call_credentials *call_creds) {
     911           1 :   return grpc_composite_channel_credentials_create(channel_creds, call_creds, NULL);
     912             : }
     913             : 
     914           1 : GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_composite_call_credentials_create(
     915             :   grpc_call_credentials *creds1,
     916             :   grpc_call_credentials *creds2) {
     917           1 :   return grpc_composite_call_credentials_create(creds1, creds2, NULL);
     918             : }
     919             : 
     920             : /* Metadata credentials plugin */
     921             : 
     922           1 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
     923             :     grpc_credentials_plugin_metadata_cb cb,
     924             :     void *user_data, grpc_metadata_array *metadata,
     925             :   grpc_status_code status, const char *error_details) {
     926           1 :   cb(user_data, metadata->metadata, metadata->count, status, error_details);
     927           1 : }
     928             : 
     929             : typedef void(GPR_CALLTYPE *grpcsharp_metadata_interceptor_func)(
     930             :   void *state, const char *service_url, const char *method_name,
     931             :   grpc_credentials_plugin_metadata_cb cb,
     932             :   void *user_data, gpr_int32 is_destroy);
     933             : 
     934           1 : static void grpcsharp_get_metadata_handler(
     935             :     void *state, grpc_auth_metadata_context context,
     936             :     grpc_credentials_plugin_metadata_cb cb, void *user_data) {
     937           1 :   grpcsharp_metadata_interceptor_func interceptor =
     938             :       (grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
     939           1 :   interceptor(state, context.service_url, context.method_name, cb, user_data, 0);
     940           1 : }
     941             : 
     942           3 : static void grpcsharp_metadata_credentials_destroy_handler(void *state) {
     943           3 :   grpcsharp_metadata_interceptor_func interceptor =
     944             :       (grpcsharp_metadata_interceptor_func)(gpr_intptr)state;
     945           3 :   interceptor(state, NULL, NULL, NULL, NULL, 1);
     946           3 : }
     947             : 
     948           3 : GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_metadata_credentials_create_from_plugin(
     949             :   grpcsharp_metadata_interceptor_func metadata_interceptor) {
     950             :   grpc_metadata_credentials_plugin plugin;
     951           3 :   plugin.get_metadata = grpcsharp_get_metadata_handler;
     952           3 :   plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
     953           3 :   plugin.state = (void*)(gpr_intptr)metadata_interceptor;
     954           3 :   plugin.type = "";
     955           3 :   return grpc_metadata_credentials_create_from_plugin(plugin, NULL);
     956             : }
     957             : 
     958             : /* Logging */
     959             : 
     960             : typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, gpr_int32 line,
     961             :                                                gpr_uint64 thd_id,
     962             :                                                const char *severity_string,
     963             :                                                const char *msg);
     964             : static grpcsharp_log_func log_func = NULL;
     965             : 
     966             : /* Redirects gpr_log to log_func callback */
     967        5775 : static void grpcsharp_log_handler(gpr_log_func_args *args) {
     968        5775 :   log_func(args->file, args->line, gpr_thd_currentid(),
     969             :            gpr_log_severity_string(args->severity), args->message);
     970        5774 : }
     971             : 
     972           4 : GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) {
     973           4 :   GPR_ASSERT(func);
     974           4 :   log_func = func;
     975           4 :   gpr_set_log_function(grpcsharp_log_handler);
     976           4 : }
     977             : 
     978             : typedef void(GPR_CALLTYPE *test_callback_funcptr)(gpr_int32 success);
     979             : 
     980             : /* Version info */
     981           1 : GPR_EXPORT const char *GPR_CALLTYPE grpcsharp_version_string() {
     982           1 :   return grpc_version_string();
     983             : }
     984             : 
     985             : /* For testing */
     986             : GPR_EXPORT void GPR_CALLTYPE
     987    11020000 : grpcsharp_test_callback(test_callback_funcptr callback) {
     988    11020000 :   callback(1);
     989    11020000 : }
     990             : 
     991             : /* For testing */
     992   101000000 : GPR_EXPORT void *GPR_CALLTYPE grpcsharp_test_nop(void *ptr) { return ptr; }
     993             : 
     994             : /* For testing */
     995           1 : GPR_EXPORT gpr_int32 GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) {
     996           1 :   return sizeof(grpc_event);
     997             : }

Generated by: LCOV version 1.11