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 : }
|