grpc_csharp_ext.c 38 KB

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