grpc_csharp_ext.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288
  1. /*
  2. *
  3. * Copyright 2015 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include <grpc/byte_buffer_reader.h>
  19. #include <grpc/grpc.h>
  20. #include <grpc/grpc_security.h>
  21. #include <grpc/slice.h>
  22. #include <grpc/support/alloc.h>
  23. #include <grpc/support/log.h>
  24. #include <grpc/support/port_platform.h>
  25. #include <grpc/support/string_util.h>
  26. #include <grpc/support/thd_id.h>
  27. #include <string.h>
  28. #ifdef GPR_WINDOWS
  29. #define GPR_EXPORT __declspec(dllexport)
  30. #define GPR_CALLTYPE __stdcall
  31. #endif
  32. #ifndef GPR_EXPORT
  33. #define GPR_EXPORT
  34. #endif
  35. #ifndef GPR_CALLTYPE
  36. #define GPR_CALLTYPE
  37. #endif
  38. static grpc_byte_buffer* grpcsharp_create_byte_buffer_from_stolen_slices(
  39. grpc_slice_buffer* slice_buffer) {
  40. grpc_byte_buffer* bb =
  41. (grpc_byte_buffer*)gpr_zalloc(sizeof(grpc_byte_buffer));
  42. bb->type = GRPC_BB_RAW;
  43. bb->data.raw.compression = GRPC_COMPRESS_NONE;
  44. grpc_slice_buffer_init(&bb->data.raw.slice_buffer);
  45. grpc_slice_buffer_swap(&bb->data.raw.slice_buffer, slice_buffer);
  46. return bb;
  47. }
  48. /*
  49. * Helper to maintain lifetime of batch op inputs and store batch op outputs.
  50. */
  51. typedef struct grpcsharp_batch_context {
  52. grpc_metadata_array send_initial_metadata;
  53. grpc_byte_buffer* send_message;
  54. struct {
  55. grpc_metadata_array trailing_metadata;
  56. } send_status_from_server;
  57. grpc_metadata_array recv_initial_metadata;
  58. grpc_byte_buffer* recv_message;
  59. grpc_byte_buffer_reader* recv_message_reader;
  60. struct {
  61. grpc_metadata_array trailing_metadata;
  62. grpc_status_code status;
  63. grpc_slice status_details;
  64. } recv_status_on_client;
  65. int recv_close_on_server_cancelled;
  66. /* reserve space for byte_buffer_reader */
  67. grpc_byte_buffer_reader reserved_recv_message_reader;
  68. } grpcsharp_batch_context;
  69. GPR_EXPORT grpcsharp_batch_context* GPR_CALLTYPE
  70. grpcsharp_batch_context_create() {
  71. grpcsharp_batch_context* ctx = gpr_malloc(sizeof(grpcsharp_batch_context));
  72. memset(ctx, 0, sizeof(grpcsharp_batch_context));
  73. return ctx;
  74. }
  75. typedef struct {
  76. grpc_call* call;
  77. grpc_call_details call_details;
  78. grpc_metadata_array request_metadata;
  79. } grpcsharp_request_call_context;
  80. GPR_EXPORT grpcsharp_request_call_context* GPR_CALLTYPE
  81. grpcsharp_request_call_context_create() {
  82. grpcsharp_request_call_context* ctx =
  83. gpr_malloc(sizeof(grpcsharp_request_call_context));
  84. memset(ctx, 0, sizeof(grpcsharp_request_call_context));
  85. return ctx;
  86. }
  87. /*
  88. * Destroys array->metadata.
  89. * The array pointer itself is not freed.
  90. */
  91. void grpcsharp_metadata_array_destroy_metadata_only(
  92. grpc_metadata_array* array) {
  93. gpr_free(array->metadata);
  94. }
  95. /*
  96. * Destroys keys, values and array->metadata.
  97. * The array pointer itself is not freed.
  98. */
  99. void grpcsharp_metadata_array_destroy_metadata_including_entries(
  100. grpc_metadata_array* array) {
  101. size_t i;
  102. if (array->metadata) {
  103. for (i = 0; i < array->count; i++) {
  104. grpc_slice_unref(array->metadata[i].key);
  105. grpc_slice_unref(array->metadata[i].value);
  106. }
  107. }
  108. gpr_free(array->metadata);
  109. }
  110. /*
  111. * Fully destroys the metadata array.
  112. */
  113. GPR_EXPORT void GPR_CALLTYPE
  114. grpcsharp_metadata_array_destroy_full(grpc_metadata_array* array) {
  115. if (!array) {
  116. return;
  117. }
  118. grpcsharp_metadata_array_destroy_metadata_including_entries(array);
  119. gpr_free(array);
  120. }
  121. /*
  122. * Creates an empty metadata array with given capacity.
  123. * Array can later be destroyed by grpc_metadata_array_destroy_full.
  124. */
  125. GPR_EXPORT grpc_metadata_array* GPR_CALLTYPE
  126. grpcsharp_metadata_array_create(size_t capacity) {
  127. grpc_metadata_array* array =
  128. (grpc_metadata_array*)gpr_malloc(sizeof(grpc_metadata_array));
  129. grpc_metadata_array_init(array);
  130. array->capacity = capacity;
  131. array->count = 0;
  132. if (capacity > 0) {
  133. array->metadata =
  134. (grpc_metadata*)gpr_malloc(sizeof(grpc_metadata) * capacity);
  135. memset(array->metadata, 0, sizeof(grpc_metadata) * capacity);
  136. } else {
  137. array->metadata = NULL;
  138. }
  139. return array;
  140. }
  141. GPR_EXPORT void GPR_CALLTYPE
  142. grpcsharp_metadata_array_add(grpc_metadata_array* array, const char* key,
  143. const char* value, size_t value_length) {
  144. size_t i = array->count;
  145. GPR_ASSERT(array->count < array->capacity);
  146. array->metadata[i].key = grpc_slice_from_copied_string(key);
  147. array->metadata[i].value = grpc_slice_from_copied_buffer(value, value_length);
  148. array->count++;
  149. }
  150. GPR_EXPORT intptr_t GPR_CALLTYPE
  151. grpcsharp_metadata_array_count(grpc_metadata_array* array) {
  152. return (intptr_t)array->count;
  153. }
  154. GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_metadata_array_get_key(
  155. grpc_metadata_array* array, size_t index, size_t* key_length) {
  156. GPR_ASSERT(index < array->count);
  157. *key_length = GRPC_SLICE_LENGTH(array->metadata[index].key);
  158. return (char*)GRPC_SLICE_START_PTR(array->metadata[index].key);
  159. }
  160. GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_metadata_array_get_value(
  161. grpc_metadata_array* array, size_t index, size_t* value_length) {
  162. GPR_ASSERT(index < array->count);
  163. *value_length = GRPC_SLICE_LENGTH(array->metadata[index].value);
  164. return (char*)GRPC_SLICE_START_PTR(array->metadata[index].value);
  165. }
  166. /* Move contents of metadata array */
  167. void grpcsharp_metadata_array_move(grpc_metadata_array* dest,
  168. grpc_metadata_array* src) {
  169. if (!src) {
  170. dest->capacity = 0;
  171. dest->count = 0;
  172. dest->metadata = NULL;
  173. return;
  174. }
  175. dest->capacity = src->capacity;
  176. dest->count = src->count;
  177. dest->metadata = src->metadata;
  178. src->capacity = 0;
  179. src->count = 0;
  180. src->metadata = NULL;
  181. }
  182. GPR_EXPORT void GPR_CALLTYPE
  183. grpcsharp_batch_context_reset(grpcsharp_batch_context* ctx) {
  184. grpcsharp_metadata_array_destroy_metadata_including_entries(
  185. &(ctx->send_initial_metadata));
  186. grpc_byte_buffer_destroy(ctx->send_message);
  187. grpcsharp_metadata_array_destroy_metadata_including_entries(
  188. &(ctx->send_status_from_server.trailing_metadata));
  189. grpcsharp_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata));
  190. if (ctx->recv_message_reader) {
  191. grpc_byte_buffer_reader_destroy(ctx->recv_message_reader);
  192. }
  193. grpc_byte_buffer_destroy(ctx->recv_message);
  194. grpcsharp_metadata_array_destroy_metadata_only(
  195. &(ctx->recv_status_on_client.trailing_metadata));
  196. grpc_slice_unref(ctx->recv_status_on_client.status_details);
  197. memset(ctx, 0, sizeof(grpcsharp_batch_context));
  198. }
  199. GPR_EXPORT void GPR_CALLTYPE
  200. grpcsharp_batch_context_destroy(grpcsharp_batch_context* ctx) {
  201. if (!ctx) {
  202. return;
  203. }
  204. grpcsharp_batch_context_reset(ctx);
  205. gpr_free(ctx);
  206. }
  207. GPR_EXPORT void GPR_CALLTYPE
  208. grpcsharp_request_call_context_reset(grpcsharp_request_call_context* ctx) {
  209. /* NOTE: ctx->server_rpc_new.call is not destroyed because callback handler is
  210. supposed
  211. to take its ownership. */
  212. grpc_call_details_destroy(&(ctx->call_details));
  213. grpcsharp_metadata_array_destroy_metadata_only(&(ctx->request_metadata));
  214. memset(ctx, 0, sizeof(grpcsharp_request_call_context));
  215. }
  216. GPR_EXPORT void GPR_CALLTYPE
  217. grpcsharp_request_call_context_destroy(grpcsharp_request_call_context* ctx) {
  218. if (!ctx) {
  219. return;
  220. }
  221. grpcsharp_request_call_context_reset(ctx);
  222. gpr_free(ctx);
  223. }
  224. GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
  225. grpcsharp_batch_context_recv_initial_metadata(
  226. const grpcsharp_batch_context* ctx) {
  227. return &(ctx->recv_initial_metadata);
  228. }
  229. GPR_EXPORT intptr_t GPR_CALLTYPE grpcsharp_batch_context_recv_message_length(
  230. const grpcsharp_batch_context* ctx) {
  231. grpc_byte_buffer_reader reader;
  232. if (!ctx->recv_message) {
  233. return -1;
  234. }
  235. GPR_ASSERT(grpc_byte_buffer_reader_init(&reader, ctx->recv_message));
  236. intptr_t result = (intptr_t)grpc_byte_buffer_length(reader.buffer_out);
  237. grpc_byte_buffer_reader_destroy(&reader);
  238. return result;
  239. }
  240. /*
  241. * Gets the next slice from recv_message byte buffer.
  242. * Returns 1 if a slice was get successfully, 0 if there are no more slices to
  243. * read. Set slice_len to the length of the slice and the slice_data_ptr to
  244. * point to slice's data. Caller must ensure that the byte buffer being read
  245. * from stays alive as long as the data of the slice are being accessed
  246. * (grpc_byte_buffer_reader_peek method is used internally)
  247. *
  248. * Remarks:
  249. * Slices can only be iterated once.
  250. * Initializes recv_message_buffer_reader if it was not initialized yet.
  251. */
  252. GPR_EXPORT int GPR_CALLTYPE
  253. grpcsharp_batch_context_recv_message_next_slice_peek(
  254. grpcsharp_batch_context* ctx, size_t* slice_len, uint8_t** slice_data_ptr) {
  255. *slice_len = 0;
  256. *slice_data_ptr = NULL;
  257. if (!ctx->recv_message) {
  258. return 0;
  259. }
  260. if (!ctx->recv_message_reader) {
  261. ctx->recv_message_reader = &ctx->reserved_recv_message_reader;
  262. GPR_ASSERT(grpc_byte_buffer_reader_init(ctx->recv_message_reader,
  263. ctx->recv_message));
  264. }
  265. grpc_slice* slice_ptr;
  266. if (!grpc_byte_buffer_reader_peek(ctx->recv_message_reader, &slice_ptr)) {
  267. return 0;
  268. }
  269. /* recv_message buffer must not be deleted before all the data is read */
  270. *slice_len = GRPC_SLICE_LENGTH(*slice_ptr);
  271. *slice_data_ptr = GRPC_SLICE_START_PTR(*slice_ptr);
  272. return 1;
  273. }
  274. GPR_EXPORT grpc_status_code GPR_CALLTYPE
  275. grpcsharp_batch_context_recv_status_on_client_status(
  276. const grpcsharp_batch_context* ctx) {
  277. return ctx->recv_status_on_client.status;
  278. }
  279. GPR_EXPORT const char* GPR_CALLTYPE
  280. grpcsharp_batch_context_recv_status_on_client_details(
  281. const grpcsharp_batch_context* ctx, size_t* details_length) {
  282. *details_length =
  283. GRPC_SLICE_LENGTH(ctx->recv_status_on_client.status_details);
  284. return (char*)GRPC_SLICE_START_PTR(ctx->recv_status_on_client.status_details);
  285. }
  286. GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
  287. grpcsharp_batch_context_recv_status_on_client_trailing_metadata(
  288. const grpcsharp_batch_context* ctx) {
  289. return &(ctx->recv_status_on_client.trailing_metadata);
  290. }
  291. GPR_EXPORT grpc_call* GPR_CALLTYPE
  292. grpcsharp_request_call_context_call(const grpcsharp_request_call_context* ctx) {
  293. return ctx->call;
  294. }
  295. GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_request_call_context_method(
  296. const grpcsharp_request_call_context* ctx, size_t* method_length) {
  297. *method_length = GRPC_SLICE_LENGTH(ctx->call_details.method);
  298. return (char*)GRPC_SLICE_START_PTR(ctx->call_details.method);
  299. }
  300. GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_request_call_context_host(
  301. const grpcsharp_request_call_context* ctx, size_t* host_length) {
  302. *host_length = GRPC_SLICE_LENGTH(ctx->call_details.host);
  303. return (char*)GRPC_SLICE_START_PTR(ctx->call_details.host);
  304. }
  305. GPR_EXPORT gpr_timespec GPR_CALLTYPE grpcsharp_request_call_context_deadline(
  306. const grpcsharp_request_call_context* ctx) {
  307. return ctx->call_details.deadline;
  308. }
  309. GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
  310. grpcsharp_request_call_context_request_metadata(
  311. const grpcsharp_request_call_context* ctx) {
  312. return &(ctx->request_metadata);
  313. }
  314. GPR_EXPORT int32_t GPR_CALLTYPE
  315. grpcsharp_batch_context_recv_close_on_server_cancelled(
  316. const grpcsharp_batch_context* ctx) {
  317. return (int32_t)ctx->recv_close_on_server_cancelled;
  318. }
  319. /* Init & shutdown */
  320. GPR_EXPORT void GPR_CALLTYPE grpcsharp_init(void) { grpc_init(); }
  321. GPR_EXPORT void GPR_CALLTYPE grpcsharp_shutdown(void) { grpc_shutdown(); }
  322. /* Completion queue */
  323. GPR_EXPORT grpc_completion_queue* GPR_CALLTYPE
  324. grpcsharp_completion_queue_create_async(void) {
  325. return grpc_completion_queue_create_for_next(NULL);
  326. }
  327. GPR_EXPORT grpc_completion_queue* GPR_CALLTYPE
  328. grpcsharp_completion_queue_create_sync(void) {
  329. return grpc_completion_queue_create_for_pluck(NULL);
  330. }
  331. GPR_EXPORT void GPR_CALLTYPE
  332. grpcsharp_completion_queue_shutdown(grpc_completion_queue* cq) {
  333. grpc_completion_queue_shutdown(cq);
  334. }
  335. GPR_EXPORT void GPR_CALLTYPE
  336. grpcsharp_completion_queue_destroy(grpc_completion_queue* cq) {
  337. grpc_completion_queue_destroy(cq);
  338. }
  339. GPR_EXPORT grpc_event GPR_CALLTYPE
  340. grpcsharp_completion_queue_next(grpc_completion_queue* cq) {
  341. return grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
  342. NULL);
  343. }
  344. GPR_EXPORT grpc_event GPR_CALLTYPE
  345. grpcsharp_completion_queue_pluck(grpc_completion_queue* cq, void* tag) {
  346. return grpc_completion_queue_pluck(cq, tag,
  347. gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
  348. }
  349. /* Channel */
  350. GPR_EXPORT grpc_channel* GPR_CALLTYPE
  351. grpcsharp_insecure_channel_create(const char* target,
  352. const grpc_channel_args* args) {
  353. return grpc_insecure_channel_create(target, args, NULL);
  354. }
  355. GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_destroy(grpc_channel* channel) {
  356. grpc_channel_destroy(channel);
  357. }
  358. GPR_EXPORT grpc_call* GPR_CALLTYPE grpcsharp_channel_create_call(
  359. grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
  360. grpc_completion_queue* cq, const char* method, const char* host,
  361. gpr_timespec deadline) {
  362. grpc_slice method_slice = grpc_slice_from_copied_string(method);
  363. grpc_slice* host_slice_ptr = NULL;
  364. grpc_slice host_slice;
  365. if (host != NULL) {
  366. host_slice = grpc_slice_from_copied_string(host);
  367. host_slice_ptr = &host_slice;
  368. }
  369. grpc_call* ret =
  370. grpc_channel_create_call(channel, parent_call, propagation_mask, cq,
  371. method_slice, host_slice_ptr, deadline, NULL);
  372. grpc_slice_unref(method_slice);
  373. if (host != NULL) {
  374. grpc_slice_unref(host_slice);
  375. }
  376. return ret;
  377. }
  378. GPR_EXPORT grpc_connectivity_state GPR_CALLTYPE
  379. grpcsharp_channel_check_connectivity_state(grpc_channel* channel,
  380. int32_t try_to_connect) {
  381. return grpc_channel_check_connectivity_state(channel, try_to_connect);
  382. }
  383. GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_watch_connectivity_state(
  384. grpc_channel* channel, grpc_connectivity_state last_observed_state,
  385. gpr_timespec deadline, grpc_completion_queue* cq,
  386. grpcsharp_batch_context* ctx) {
  387. grpc_channel_watch_connectivity_state(channel, last_observed_state, deadline,
  388. cq, ctx);
  389. }
  390. GPR_EXPORT char* GPR_CALLTYPE
  391. grpcsharp_channel_get_target(grpc_channel* channel) {
  392. return grpc_channel_get_target(channel);
  393. }
  394. /* Channel args */
  395. GPR_EXPORT grpc_channel_args* GPR_CALLTYPE
  396. grpcsharp_channel_args_create(size_t num_args) {
  397. grpc_channel_args* args =
  398. (grpc_channel_args*)gpr_malloc(sizeof(grpc_channel_args));
  399. memset(args, 0, sizeof(grpc_channel_args));
  400. args->num_args = num_args;
  401. args->args = (grpc_arg*)gpr_malloc(sizeof(grpc_arg) * num_args);
  402. memset(args->args, 0, sizeof(grpc_arg) * num_args);
  403. return args;
  404. }
  405. GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_set_string(
  406. grpc_channel_args* args, size_t index, const char* key, const char* value) {
  407. GPR_ASSERT(args);
  408. GPR_ASSERT(index < args->num_args);
  409. args->args[index].type = GRPC_ARG_STRING;
  410. args->args[index].key = gpr_strdup(key);
  411. args->args[index].value.string = gpr_strdup(value);
  412. }
  413. GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_set_integer(
  414. grpc_channel_args* args, size_t index, const char* key, int value) {
  415. GPR_ASSERT(args);
  416. GPR_ASSERT(index < args->num_args);
  417. args->args[index].type = GRPC_ARG_INTEGER;
  418. args->args[index].key = gpr_strdup(key);
  419. args->args[index].value.integer = value;
  420. }
  421. GPR_EXPORT void GPR_CALLTYPE
  422. grpcsharp_channel_args_destroy(grpc_channel_args* args) {
  423. size_t i;
  424. if (args) {
  425. for (i = 0; i < args->num_args; i++) {
  426. gpr_free(args->args[i].key);
  427. if (args->args[i].type == GRPC_ARG_STRING) {
  428. gpr_free(args->args[i].value.string);
  429. }
  430. }
  431. gpr_free(args->args);
  432. gpr_free(args);
  433. }
  434. }
  435. /* Timespec */
  436. GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(gpr_clock_type clock_type) {
  437. return gpr_now(clock_type);
  438. }
  439. GPR_EXPORT gpr_timespec GPR_CALLTYPE
  440. gprsharp_inf_future(gpr_clock_type clock_type) {
  441. return gpr_inf_future(clock_type);
  442. }
  443. GPR_EXPORT gpr_timespec GPR_CALLTYPE
  444. gprsharp_inf_past(gpr_clock_type clock_type) {
  445. return gpr_inf_past(clock_type);
  446. }
  447. GPR_EXPORT gpr_timespec GPR_CALLTYPE
  448. gprsharp_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock) {
  449. return gpr_convert_clock_type(t, target_clock);
  450. }
  451. GPR_EXPORT int32_t GPR_CALLTYPE gprsharp_sizeof_timespec(void) {
  452. return sizeof(gpr_timespec);
  453. }
  454. /* Call */
  455. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel(grpc_call* call) {
  456. return grpc_call_cancel(call, NULL);
  457. }
  458. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel_with_status(
  459. grpc_call* call, grpc_status_code status, const char* description) {
  460. return grpc_call_cancel_with_status(call, status, description, NULL);
  461. }
  462. GPR_EXPORT char* GPR_CALLTYPE grpcsharp_call_get_peer(grpc_call* call) {
  463. return grpc_call_get_peer(call);
  464. }
  465. GPR_EXPORT void GPR_CALLTYPE gprsharp_free(void* p) { gpr_free(p); }
  466. GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call* call) {
  467. grpc_call_unref(call);
  468. }
  469. typedef grpc_call_error (*grpcsharp_call_start_batch_func)(grpc_call* call,
  470. const grpc_op* ops,
  471. size_t nops,
  472. void* tag,
  473. void* reserved);
  474. /* Only for testing */
  475. static grpc_call_error grpcsharp_call_start_batch_nop(grpc_call* call,
  476. const grpc_op* ops,
  477. size_t nops, void* tag,
  478. void* reserved) {
  479. return GRPC_CALL_OK;
  480. }
  481. static grpc_call_error grpcsharp_call_start_batch_default(grpc_call* call,
  482. const grpc_op* ops,
  483. size_t nops,
  484. void* tag,
  485. void* reserved) {
  486. return grpc_call_start_batch(call, ops, nops, tag, reserved);
  487. }
  488. static grpcsharp_call_start_batch_func g_call_start_batch_func =
  489. grpcsharp_call_start_batch_default;
  490. static grpc_call_error grpcsharp_call_start_batch(grpc_call* call,
  491. const grpc_op* ops,
  492. size_t nops, void* tag,
  493. void* reserved) {
  494. return g_call_start_batch_func(call, ops, nops, tag, reserved);
  495. }
  496. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
  497. grpc_call* call, grpcsharp_batch_context* ctx,
  498. grpc_slice_buffer* send_buffer, uint32_t write_flags,
  499. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  500. /* TODO: don't use magic number */
  501. grpc_op ops[6];
  502. memset(ops, 0, sizeof(ops));
  503. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  504. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  505. initial_metadata);
  506. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  507. ops[0].data.send_initial_metadata.metadata =
  508. ctx->send_initial_metadata.metadata;
  509. ops[0].flags = initial_metadata_flags;
  510. ops[0].reserved = NULL;
  511. ops[1].op = GRPC_OP_SEND_MESSAGE;
  512. ctx->send_message =
  513. grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
  514. ops[1].data.send_message.send_message = ctx->send_message;
  515. ops[1].flags = write_flags;
  516. ops[1].reserved = NULL;
  517. ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  518. ops[2].flags = 0;
  519. ops[2].reserved = NULL;
  520. ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
  521. ops[3].data.recv_initial_metadata.recv_initial_metadata =
  522. &(ctx->recv_initial_metadata);
  523. ops[3].flags = 0;
  524. ops[3].reserved = NULL;
  525. ops[4].op = GRPC_OP_RECV_MESSAGE;
  526. ops[4].data.recv_message.recv_message = &(ctx->recv_message);
  527. ops[4].flags = 0;
  528. ops[4].reserved = NULL;
  529. ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  530. ops[5].data.recv_status_on_client.trailing_metadata =
  531. &(ctx->recv_status_on_client.trailing_metadata);
  532. ops[5].data.recv_status_on_client.status =
  533. &(ctx->recv_status_on_client.status);
  534. ops[5].data.recv_status_on_client.status_details =
  535. &(ctx->recv_status_on_client.status_details);
  536. ops[5].flags = 0;
  537. ops[5].reserved = NULL;
  538. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  539. ctx, NULL);
  540. }
  541. /* Only for testing. Shortcircuits the unary call logic and only echoes the
  542. message as if it was received from the server */
  543. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_test_call_start_unary_echo(
  544. grpc_call* call, grpcsharp_batch_context* ctx,
  545. grpc_slice_buffer* send_buffer, uint32_t write_flags,
  546. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  547. // prepare as if we were performing a normal RPC.
  548. grpc_byte_buffer* send_message =
  549. grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
  550. ctx->recv_message = send_message; // echo message sent by the client as if
  551. // received from server.
  552. ctx->recv_status_on_client.status = GRPC_STATUS_OK;
  553. ctx->recv_status_on_client.status_details = grpc_empty_slice();
  554. // echo initial metadata as if received from server (as trailing metadata)
  555. grpcsharp_metadata_array_move(&(ctx->recv_status_on_client.trailing_metadata),
  556. initial_metadata);
  557. return GRPC_CALL_OK;
  558. }
  559. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(
  560. grpc_call* call, grpcsharp_batch_context* ctx,
  561. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  562. /* TODO: don't use magic number */
  563. grpc_op ops[4];
  564. memset(ops, 0, sizeof(ops));
  565. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  566. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  567. initial_metadata);
  568. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  569. ops[0].data.send_initial_metadata.metadata =
  570. ctx->send_initial_metadata.metadata;
  571. ops[0].flags = initial_metadata_flags;
  572. ops[0].reserved = NULL;
  573. ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
  574. ops[1].data.recv_initial_metadata.recv_initial_metadata =
  575. &(ctx->recv_initial_metadata);
  576. ops[1].flags = 0;
  577. ops[1].reserved = NULL;
  578. ops[2].op = GRPC_OP_RECV_MESSAGE;
  579. ops[2].data.recv_message.recv_message = &(ctx->recv_message);
  580. ops[2].flags = 0;
  581. ops[2].reserved = NULL;
  582. ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  583. ops[3].data.recv_status_on_client.trailing_metadata =
  584. &(ctx->recv_status_on_client.trailing_metadata);
  585. ops[3].data.recv_status_on_client.status =
  586. &(ctx->recv_status_on_client.status);
  587. ops[3].data.recv_status_on_client.status_details =
  588. &(ctx->recv_status_on_client.status_details);
  589. ops[3].flags = 0;
  590. ops[3].reserved = NULL;
  591. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  592. ctx, NULL);
  593. }
  594. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
  595. grpc_call* call, grpcsharp_batch_context* ctx,
  596. grpc_slice_buffer* send_buffer, uint32_t write_flags,
  597. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  598. /* TODO: don't use magic number */
  599. grpc_op ops[4];
  600. memset(ops, 0, sizeof(ops));
  601. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  602. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  603. initial_metadata);
  604. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  605. ops[0].data.send_initial_metadata.metadata =
  606. ctx->send_initial_metadata.metadata;
  607. ops[0].flags = initial_metadata_flags;
  608. ops[0].reserved = NULL;
  609. ops[1].op = GRPC_OP_SEND_MESSAGE;
  610. ctx->send_message =
  611. grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
  612. ops[1].data.send_message.send_message = ctx->send_message;
  613. ops[1].flags = write_flags;
  614. ops[1].reserved = NULL;
  615. ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  616. ops[2].flags = 0;
  617. ops[2].reserved = NULL;
  618. ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  619. ops[3].data.recv_status_on_client.trailing_metadata =
  620. &(ctx->recv_status_on_client.trailing_metadata);
  621. ops[3].data.recv_status_on_client.status =
  622. &(ctx->recv_status_on_client.status);
  623. ops[3].data.recv_status_on_client.status_details =
  624. &(ctx->recv_status_on_client.status_details);
  625. ops[3].flags = 0;
  626. ops[3].reserved = NULL;
  627. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  628. ctx, NULL);
  629. }
  630. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(
  631. grpc_call* call, grpcsharp_batch_context* ctx,
  632. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  633. /* TODO: don't use magic number */
  634. grpc_op ops[2];
  635. memset(ops, 0, sizeof(ops));
  636. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  637. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  638. initial_metadata);
  639. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  640. ops[0].data.send_initial_metadata.metadata =
  641. ctx->send_initial_metadata.metadata;
  642. ops[0].flags = initial_metadata_flags;
  643. ops[0].reserved = NULL;
  644. ops[1].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  645. ops[1].data.recv_status_on_client.trailing_metadata =
  646. &(ctx->recv_status_on_client.trailing_metadata);
  647. ops[1].data.recv_status_on_client.status =
  648. &(ctx->recv_status_on_client.status);
  649. ops[1].data.recv_status_on_client.status_details =
  650. &(ctx->recv_status_on_client.status_details);
  651. ops[1].flags = 0;
  652. ops[1].reserved = NULL;
  653. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  654. ctx, NULL);
  655. }
  656. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata(
  657. grpc_call* call, grpcsharp_batch_context* ctx) {
  658. /* TODO: don't use magic number */
  659. grpc_op ops[1];
  660. ops[0].op = GRPC_OP_RECV_INITIAL_METADATA;
  661. ops[0].data.recv_initial_metadata.recv_initial_metadata =
  662. &(ctx->recv_initial_metadata);
  663. ops[0].flags = 0;
  664. ops[0].reserved = NULL;
  665. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  666. ctx, NULL);
  667. }
  668. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message(
  669. grpc_call* call, grpcsharp_batch_context* ctx,
  670. grpc_slice_buffer* send_buffer, uint32_t write_flags,
  671. int32_t send_empty_initial_metadata) {
  672. /* TODO: don't use magic number */
  673. grpc_op ops[2];
  674. memset(ops, 0, sizeof(ops));
  675. size_t nops = send_empty_initial_metadata ? 2 : 1;
  676. ops[0].op = GRPC_OP_SEND_MESSAGE;
  677. ctx->send_message =
  678. grpcsharp_create_byte_buffer_from_stolen_slices(send_buffer);
  679. ops[0].data.send_message.send_message = ctx->send_message;
  680. ops[0].flags = write_flags;
  681. ops[0].reserved = NULL;
  682. ops[1].op = GRPC_OP_SEND_INITIAL_METADATA;
  683. ops[1].flags = 0;
  684. ops[1].reserved = NULL;
  685. return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
  686. }
  687. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client(
  688. grpc_call* call, grpcsharp_batch_context* ctx) {
  689. /* TODO: don't use magic number */
  690. grpc_op ops[1];
  691. ops[0].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  692. ops[0].flags = 0;
  693. ops[0].reserved = NULL;
  694. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  695. ctx, NULL);
  696. }
  697. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
  698. grpc_call* call, grpcsharp_batch_context* ctx, grpc_status_code status_code,
  699. const char* status_details, size_t status_details_len,
  700. grpc_metadata_array* trailing_metadata, int32_t send_empty_initial_metadata,
  701. grpc_slice_buffer* optional_send_buffer, uint32_t write_flags) {
  702. /* TODO: don't use magic number */
  703. grpc_op ops[3];
  704. memset(ops, 0, sizeof(ops));
  705. size_t nops = 1;
  706. grpc_slice status_details_slice =
  707. grpc_slice_from_copied_buffer(status_details, status_details_len);
  708. ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
  709. ops[0].data.send_status_from_server.status = status_code;
  710. ops[0].data.send_status_from_server.status_details = &status_details_slice;
  711. grpcsharp_metadata_array_move(
  712. &(ctx->send_status_from_server.trailing_metadata), trailing_metadata);
  713. ops[0].data.send_status_from_server.trailing_metadata_count =
  714. ctx->send_status_from_server.trailing_metadata.count;
  715. ops[0].data.send_status_from_server.trailing_metadata =
  716. ctx->send_status_from_server.trailing_metadata.metadata;
  717. ops[0].flags = 0;
  718. ops[0].reserved = NULL;
  719. if (optional_send_buffer) {
  720. ops[nops].op = GRPC_OP_SEND_MESSAGE;
  721. ctx->send_message =
  722. grpcsharp_create_byte_buffer_from_stolen_slices(optional_send_buffer);
  723. ops[nops].data.send_message.send_message = ctx->send_message;
  724. ops[nops].flags = write_flags;
  725. ops[nops].reserved = NULL;
  726. nops++;
  727. }
  728. if (send_empty_initial_metadata) {
  729. ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA;
  730. ops[nops].flags = 0;
  731. ops[nops].reserved = NULL;
  732. nops++;
  733. }
  734. grpc_call_error ret = grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
  735. grpc_slice_unref(status_details_slice);
  736. return ret;
  737. }
  738. GPR_EXPORT grpc_call_error GPR_CALLTYPE
  739. grpcsharp_call_recv_message(grpc_call* call, grpcsharp_batch_context* ctx) {
  740. /* TODO: don't use magic number */
  741. grpc_op ops[1];
  742. ops[0].op = GRPC_OP_RECV_MESSAGE;
  743. ops[0].data.recv_message.recv_message = &(ctx->recv_message);
  744. ops[0].flags = 0;
  745. ops[0].reserved = NULL;
  746. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  747. ctx, NULL);
  748. }
  749. GPR_EXPORT grpc_call_error GPR_CALLTYPE
  750. grpcsharp_call_start_serverside(grpc_call* call, grpcsharp_batch_context* ctx) {
  751. /* TODO: don't use magic number */
  752. grpc_op ops[1];
  753. ops[0].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
  754. ops[0].data.recv_close_on_server.cancelled =
  755. (&ctx->recv_close_on_server_cancelled);
  756. ops[0].flags = 0;
  757. ops[0].reserved = NULL;
  758. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  759. ctx, NULL);
  760. }
  761. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata(
  762. grpc_call* call, grpcsharp_batch_context* ctx,
  763. grpc_metadata_array* initial_metadata) {
  764. /* TODO: don't use magic number */
  765. grpc_op ops[1];
  766. memset(ops, 0, sizeof(ops));
  767. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  768. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  769. initial_metadata);
  770. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  771. ops[0].data.send_initial_metadata.metadata =
  772. ctx->send_initial_metadata.metadata;
  773. ops[0].flags = 0;
  774. ops[0].reserved = NULL;
  775. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  776. ctx, NULL);
  777. }
  778. GPR_EXPORT grpc_call_error GPR_CALLTYPE
  779. grpcsharp_call_set_credentials(grpc_call* call, grpc_call_credentials* creds) {
  780. return grpc_call_set_credentials(call, creds);
  781. }
  782. /* Server */
  783. GPR_EXPORT grpc_server* GPR_CALLTYPE
  784. grpcsharp_server_create(const grpc_channel_args* args) {
  785. return grpc_server_create(args, NULL);
  786. }
  787. GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_register_completion_queue(
  788. grpc_server* server, grpc_completion_queue* cq) {
  789. grpc_server_register_completion_queue(server, cq, NULL);
  790. }
  791. GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_insecure_http2_port(
  792. grpc_server* server, const char* addr) {
  793. return grpc_server_add_insecure_http2_port(server, addr);
  794. }
  795. GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_start(grpc_server* server) {
  796. grpc_server_start(server);
  797. }
  798. GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_shutdown_and_notify_callback(
  799. grpc_server* server, grpc_completion_queue* cq,
  800. grpcsharp_batch_context* ctx) {
  801. grpc_server_shutdown_and_notify(server, cq, ctx);
  802. }
  803. GPR_EXPORT void GPR_CALLTYPE
  804. grpcsharp_server_cancel_all_calls(grpc_server* server) {
  805. grpc_server_cancel_all_calls(server);
  806. }
  807. GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_destroy(grpc_server* server) {
  808. grpc_server_destroy(server);
  809. }
  810. GPR_EXPORT grpc_call_error GPR_CALLTYPE
  811. grpcsharp_server_request_call(grpc_server* server, grpc_completion_queue* cq,
  812. grpcsharp_request_call_context* ctx) {
  813. return grpc_server_request_call(server, &(ctx->call), &(ctx->call_details),
  814. &(ctx->request_metadata), cq, cq, ctx);
  815. }
  816. /* Native callback dispatcher */
  817. typedef int(GPR_CALLTYPE* grpcsharp_native_callback_dispatcher_func)(
  818. void* tag, void* arg0, void* arg1, void* arg2, void* arg3, void* arg4,
  819. void* arg5);
  820. static grpcsharp_native_callback_dispatcher_func native_callback_dispatcher =
  821. NULL;
  822. GPR_EXPORT void GPR_CALLTYPE grpcsharp_native_callback_dispatcher_init(
  823. grpcsharp_native_callback_dispatcher_func func) {
  824. GPR_ASSERT(func);
  825. native_callback_dispatcher = func;
  826. }
  827. /* Security */
  828. static char* default_pem_root_certs = NULL;
  829. static grpc_ssl_roots_override_result override_ssl_roots_handler(
  830. char** pem_root_certs) {
  831. if (!default_pem_root_certs) {
  832. *pem_root_certs = NULL;
  833. return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
  834. }
  835. *pem_root_certs = gpr_strdup(default_pem_root_certs);
  836. return GRPC_SSL_ROOTS_OVERRIDE_OK;
  837. }
  838. GPR_EXPORT void GPR_CALLTYPE
  839. grpcsharp_override_default_ssl_roots(const char* pem_root_certs) {
  840. /*
  841. * This currently wastes ~300kB of memory by keeping a copy of roots
  842. * in a static variable, but for desktop/server use, the overhead
  843. * is negligible. In the future, we might want to change the behavior
  844. * for mobile (e.g. Xamarin).
  845. */
  846. default_pem_root_certs = gpr_strdup(pem_root_certs);
  847. grpc_set_ssl_roots_override_callback(override_ssl_roots_handler);
  848. }
  849. static void grpcsharp_verify_peer_destroy_handler(void* userdata) {
  850. native_callback_dispatcher(userdata, NULL, NULL, (void*)1, NULL, NULL, NULL);
  851. }
  852. static int grpcsharp_verify_peer_handler(const char* target_name,
  853. const char* peer_pem, void* userdata) {
  854. return native_callback_dispatcher(userdata, (void*)target_name,
  855. (void*)peer_pem, (void*)0, NULL, NULL,
  856. NULL);
  857. }
  858. GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE
  859. grpcsharp_ssl_credentials_create(const char* pem_root_certs,
  860. const char* key_cert_pair_cert_chain,
  861. const char* key_cert_pair_private_key,
  862. void* verify_peer_callback_tag) {
  863. grpc_ssl_pem_key_cert_pair key_cert_pair;
  864. verify_peer_options verify_options;
  865. grpc_ssl_pem_key_cert_pair* key_cert_pair_ptr = NULL;
  866. verify_peer_options* verify_options_ptr = NULL;
  867. if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
  868. memset(&key_cert_pair, 0, sizeof(key_cert_pair));
  869. key_cert_pair.cert_chain = key_cert_pair_cert_chain;
  870. key_cert_pair.private_key = key_cert_pair_private_key;
  871. key_cert_pair_ptr = &key_cert_pair;
  872. } else {
  873. GPR_ASSERT(!key_cert_pair_cert_chain);
  874. GPR_ASSERT(!key_cert_pair_private_key);
  875. }
  876. if (verify_peer_callback_tag != NULL) {
  877. memset(&verify_options, 0, sizeof(verify_peer_options));
  878. verify_options.verify_peer_callback_userdata = verify_peer_callback_tag;
  879. verify_options.verify_peer_destruct = grpcsharp_verify_peer_destroy_handler;
  880. verify_options.verify_peer_callback = grpcsharp_verify_peer_handler;
  881. verify_options_ptr = &verify_options;
  882. }
  883. return grpc_ssl_credentials_create(pem_root_certs, key_cert_pair_ptr,
  884. verify_options_ptr, NULL);
  885. }
  886. GPR_EXPORT void GPR_CALLTYPE
  887. grpcsharp_channel_credentials_release(grpc_channel_credentials* creds) {
  888. grpc_channel_credentials_release(creds);
  889. }
  890. GPR_EXPORT void GPR_CALLTYPE
  891. grpcsharp_call_credentials_release(grpc_call_credentials* creds) {
  892. grpc_call_credentials_release(creds);
  893. }
  894. GPR_EXPORT grpc_channel* GPR_CALLTYPE grpcsharp_secure_channel_create(
  895. grpc_channel_credentials* creds, const char* target,
  896. const grpc_channel_args* args) {
  897. return grpc_secure_channel_create(creds, target, args, NULL);
  898. }
  899. GPR_EXPORT grpc_server_credentials* GPR_CALLTYPE
  900. grpcsharp_ssl_server_credentials_create(
  901. const char* pem_root_certs, const char** key_cert_pair_cert_chain_array,
  902. const char** key_cert_pair_private_key_array, size_t num_key_cert_pairs,
  903. grpc_ssl_client_certificate_request_type client_request_type) {
  904. size_t i;
  905. grpc_server_credentials* creds;
  906. grpc_ssl_pem_key_cert_pair* key_cert_pairs =
  907. gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
  908. memset(key_cert_pairs, 0,
  909. sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
  910. for (i = 0; i < num_key_cert_pairs; i++) {
  911. if (key_cert_pair_cert_chain_array[i] ||
  912. key_cert_pair_private_key_array[i]) {
  913. key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i];
  914. key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
  915. }
  916. }
  917. creds = grpc_ssl_server_credentials_create_ex(pem_root_certs, key_cert_pairs,
  918. num_key_cert_pairs,
  919. client_request_type, NULL);
  920. gpr_free(key_cert_pairs);
  921. return creds;
  922. }
  923. GPR_EXPORT void GPR_CALLTYPE
  924. grpcsharp_server_credentials_release(grpc_server_credentials* creds) {
  925. grpc_server_credentials_release(creds);
  926. }
  927. GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_secure_http2_port(
  928. grpc_server* server, const char* addr, grpc_server_credentials* creds) {
  929. return grpc_server_add_secure_http2_port(server, addr, creds);
  930. }
  931. GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE
  932. grpcsharp_composite_channel_credentials_create(
  933. grpc_channel_credentials* channel_creds,
  934. grpc_call_credentials* call_creds) {
  935. return grpc_composite_channel_credentials_create(channel_creds, call_creds,
  936. NULL);
  937. }
  938. GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
  939. grpcsharp_composite_call_credentials_create(grpc_call_credentials* creds1,
  940. grpc_call_credentials* creds2) {
  941. return grpc_composite_call_credentials_create(creds1, creds2, NULL);
  942. }
  943. /* Metadata credentials plugin */
  944. GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
  945. grpc_credentials_plugin_metadata_cb cb, void* user_data,
  946. grpc_metadata_array* metadata, grpc_status_code status,
  947. const char* error_details) {
  948. if (metadata) {
  949. cb(user_data, metadata->metadata, metadata->count, status, error_details);
  950. } else {
  951. cb(user_data, NULL, 0, status, error_details);
  952. }
  953. }
  954. static int grpcsharp_get_metadata_handler(
  955. void* state, grpc_auth_metadata_context context,
  956. grpc_credentials_plugin_metadata_cb cb, void* user_data,
  957. grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
  958. size_t* num_creds_md, grpc_status_code* status,
  959. const char** error_details) {
  960. native_callback_dispatcher(state, (void*)context.service_url,
  961. (void*)context.method_name, cb, user_data,
  962. (void*)0, NULL);
  963. return 0; /* Asynchronous return. */
  964. }
  965. static void grpcsharp_metadata_credentials_destroy_handler(void* state) {
  966. native_callback_dispatcher(state, NULL, NULL, NULL, NULL, (void*)1, NULL);
  967. }
  968. GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
  969. grpcsharp_metadata_credentials_create_from_plugin(void* callback_tag) {
  970. grpc_metadata_credentials_plugin plugin;
  971. plugin.get_metadata = grpcsharp_get_metadata_handler;
  972. plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
  973. plugin.state = callback_tag;
  974. plugin.type = "";
  975. // TODO(yihuazhang): Expose min_security_level via the C# API so
  976. // that applications can decide what minimum security level their
  977. // plugins require.
  978. return grpc_metadata_credentials_create_from_plugin(
  979. plugin, GRPC_PRIVACY_AND_INTEGRITY, NULL);
  980. }
  981. /* Auth context */
  982. GPR_EXPORT grpc_auth_context* GPR_CALLTYPE
  983. grpcsharp_call_auth_context(grpc_call* call) {
  984. return grpc_call_auth_context(call);
  985. }
  986. GPR_EXPORT const char* GPR_CALLTYPE
  987. grpcsharp_auth_context_peer_identity_property_name(
  988. const grpc_auth_context* ctx) {
  989. return grpc_auth_context_peer_identity_property_name(ctx);
  990. }
  991. GPR_EXPORT grpc_auth_property_iterator GPR_CALLTYPE
  992. grpcsharp_auth_context_property_iterator(const grpc_auth_context* ctx) {
  993. return grpc_auth_context_property_iterator(ctx);
  994. }
  995. GPR_EXPORT const grpc_auth_property* GPR_CALLTYPE
  996. grpcsharp_auth_property_iterator_next(grpc_auth_property_iterator* it) {
  997. return grpc_auth_property_iterator_next(it);
  998. }
  999. GPR_EXPORT void GPR_CALLTYPE
  1000. grpcsharp_auth_context_release(grpc_auth_context* ctx) {
  1001. grpc_auth_context_release(ctx);
  1002. }
  1003. /* Logging */
  1004. typedef void(GPR_CALLTYPE* grpcsharp_log_func)(const char* file, int32_t line,
  1005. uint64_t thd_id,
  1006. const char* severity_string,
  1007. const char* msg);
  1008. static grpcsharp_log_func log_func = NULL;
  1009. /* Redirects gpr_log to log_func callback */
  1010. static void grpcsharp_log_handler(gpr_log_func_args* args) {
  1011. log_func(args->file, args->line, gpr_thd_currentid(),
  1012. gpr_log_severity_string(args->severity), args->message);
  1013. }
  1014. GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) {
  1015. GPR_ASSERT(func);
  1016. log_func = func;
  1017. gpr_set_log_function(grpcsharp_log_handler);
  1018. }
  1019. typedef void(GPR_CALLTYPE* test_callback_funcptr)(int32_t success);
  1020. /* Slice buffer functionality */
  1021. GPR_EXPORT grpc_slice_buffer* GPR_CALLTYPE grpcsharp_slice_buffer_create() {
  1022. grpc_slice_buffer* slice_buffer =
  1023. (grpc_slice_buffer*)gpr_malloc(sizeof(grpc_slice_buffer));
  1024. grpc_slice_buffer_init(slice_buffer);
  1025. return slice_buffer;
  1026. }
  1027. GPR_EXPORT void GPR_CALLTYPE
  1028. grpcsharp_slice_buffer_reset_and_unref(grpc_slice_buffer* buffer) {
  1029. grpc_slice_buffer_reset_and_unref(buffer);
  1030. }
  1031. GPR_EXPORT void GPR_CALLTYPE
  1032. grpcsharp_slice_buffer_destroy(grpc_slice_buffer* buffer) {
  1033. grpc_slice_buffer_destroy(buffer);
  1034. gpr_free(buffer);
  1035. }
  1036. GPR_EXPORT size_t GPR_CALLTYPE
  1037. grpcsharp_slice_buffer_slice_count(grpc_slice_buffer* buffer) {
  1038. return buffer->count;
  1039. }
  1040. GPR_EXPORT void GPR_CALLTYPE
  1041. grpcsharp_slice_buffer_slice_peek(grpc_slice_buffer* buffer, size_t index,
  1042. size_t* slice_len, uint8_t** slice_data_ptr) {
  1043. GPR_ASSERT(buffer->count > index);
  1044. grpc_slice* slice_ptr = &buffer->slices[index];
  1045. *slice_len = GRPC_SLICE_LENGTH(*slice_ptr);
  1046. *slice_data_ptr = GRPC_SLICE_START_PTR(*slice_ptr);
  1047. }
  1048. GPR_EXPORT void* GPR_CALLTYPE grpcsharp_slice_buffer_adjust_tail_space(
  1049. grpc_slice_buffer* buffer, size_t available_tail_space,
  1050. size_t requested_tail_space) {
  1051. if (available_tail_space == requested_tail_space) {
  1052. // nothing to do
  1053. } else if (available_tail_space >= requested_tail_space) {
  1054. grpc_slice_buffer_trim_end(
  1055. buffer, available_tail_space - requested_tail_space, NULL);
  1056. } else {
  1057. if (available_tail_space > 0) {
  1058. grpc_slice_buffer_trim_end(buffer, available_tail_space, NULL);
  1059. }
  1060. grpc_slice new_slice = grpc_slice_malloc(requested_tail_space);
  1061. // grpc_slice_buffer_add_indexed always adds as a new slice entry into the
  1062. // sb (which is suboptimal in some cases) but it doesn't have the problem of
  1063. // sometimes splitting the continguous new_slice across two different slices
  1064. // (like grpc_slice_buffer_add would)
  1065. grpc_slice_buffer_add_indexed(buffer, new_slice);
  1066. }
  1067. if (buffer->count == 0) {
  1068. return NULL;
  1069. }
  1070. grpc_slice* last_slice = &(buffer->slices[buffer->count - 1]);
  1071. return GRPC_SLICE_END_PTR(*last_slice) - requested_tail_space;
  1072. }
  1073. /* Version info */
  1074. GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_version_string() {
  1075. return grpc_version_string();
  1076. }
  1077. /* For testing */
  1078. GPR_EXPORT void GPR_CALLTYPE
  1079. grpcsharp_test_callback(test_callback_funcptr callback) {
  1080. callback(1);
  1081. }
  1082. /* For testing */
  1083. GPR_EXPORT void* GPR_CALLTYPE grpcsharp_test_nop(void* ptr) { return ptr; }
  1084. /* For testing */
  1085. GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) {
  1086. return sizeof(grpc_event);
  1087. }
  1088. /* Override a method for testing */
  1089. GPR_EXPORT void GPR_CALLTYPE
  1090. grpcsharp_test_override_method(const char* method_name, const char* variant) {
  1091. if (strcmp("grpcsharp_call_start_batch", method_name) == 0) {
  1092. if (strcmp("nop", variant) == 0) {
  1093. g_call_start_batch_func = grpcsharp_call_start_batch_nop;
  1094. } else {
  1095. GPR_ASSERT(0);
  1096. }
  1097. } else {
  1098. GPR_ASSERT(0);
  1099. }
  1100. }