grpc_csharp_ext.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  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(ctx->recv_status_on_client.status_details);
  252. }
  253. GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
  254. grpcsharp_batch_context_recv_status_on_client_trailing_metadata(
  255. const grpcsharp_batch_context* ctx) {
  256. return &(ctx->recv_status_on_client.trailing_metadata);
  257. }
  258. GPR_EXPORT grpc_call* GPR_CALLTYPE
  259. grpcsharp_request_call_context_call(const grpcsharp_request_call_context* ctx) {
  260. return ctx->call;
  261. }
  262. GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_request_call_context_method(
  263. const grpcsharp_request_call_context* ctx, size_t* method_length) {
  264. *method_length = GRPC_SLICE_LENGTH(ctx->call_details.method);
  265. return (char*)GRPC_SLICE_START_PTR(ctx->call_details.method);
  266. }
  267. GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_request_call_context_host(
  268. const grpcsharp_request_call_context* ctx, size_t* host_length) {
  269. *host_length = GRPC_SLICE_LENGTH(ctx->call_details.host);
  270. return (char*)GRPC_SLICE_START_PTR(ctx->call_details.host);
  271. }
  272. GPR_EXPORT gpr_timespec GPR_CALLTYPE grpcsharp_request_call_context_deadline(
  273. const grpcsharp_request_call_context* ctx) {
  274. return ctx->call_details.deadline;
  275. }
  276. GPR_EXPORT const grpc_metadata_array* GPR_CALLTYPE
  277. grpcsharp_request_call_context_request_metadata(
  278. const grpcsharp_request_call_context* ctx) {
  279. return &(ctx->request_metadata);
  280. }
  281. GPR_EXPORT int32_t GPR_CALLTYPE
  282. grpcsharp_batch_context_recv_close_on_server_cancelled(
  283. const grpcsharp_batch_context* ctx) {
  284. return (int32_t)ctx->recv_close_on_server_cancelled;
  285. }
  286. /* Init & shutdown */
  287. GPR_EXPORT void GPR_CALLTYPE grpcsharp_init(void) { grpc_init(); }
  288. GPR_EXPORT void GPR_CALLTYPE grpcsharp_shutdown(void) { grpc_shutdown(); }
  289. /* Completion queue */
  290. GPR_EXPORT grpc_completion_queue* GPR_CALLTYPE
  291. grpcsharp_completion_queue_create_async(void) {
  292. return grpc_completion_queue_create_for_next(NULL);
  293. }
  294. GPR_EXPORT grpc_completion_queue* GPR_CALLTYPE
  295. grpcsharp_completion_queue_create_sync(void) {
  296. return grpc_completion_queue_create_for_pluck(NULL);
  297. }
  298. GPR_EXPORT void GPR_CALLTYPE
  299. grpcsharp_completion_queue_shutdown(grpc_completion_queue* cq) {
  300. grpc_completion_queue_shutdown(cq);
  301. }
  302. GPR_EXPORT void GPR_CALLTYPE
  303. grpcsharp_completion_queue_destroy(grpc_completion_queue* cq) {
  304. grpc_completion_queue_destroy(cq);
  305. }
  306. GPR_EXPORT grpc_event GPR_CALLTYPE
  307. grpcsharp_completion_queue_next(grpc_completion_queue* cq) {
  308. return grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME),
  309. NULL);
  310. }
  311. GPR_EXPORT grpc_event GPR_CALLTYPE
  312. grpcsharp_completion_queue_pluck(grpc_completion_queue* cq, void* tag) {
  313. return grpc_completion_queue_pluck(cq, tag,
  314. gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
  315. }
  316. /* Channel */
  317. GPR_EXPORT grpc_channel* GPR_CALLTYPE
  318. grpcsharp_insecure_channel_create(const char* target,
  319. const grpc_channel_args* args) {
  320. return grpc_insecure_channel_create(target, args, NULL);
  321. }
  322. GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_destroy(grpc_channel* channel) {
  323. grpc_channel_destroy(channel);
  324. }
  325. GPR_EXPORT grpc_call* GPR_CALLTYPE grpcsharp_channel_create_call(
  326. grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask,
  327. grpc_completion_queue* cq, const char* method, const char* host,
  328. gpr_timespec deadline) {
  329. grpc_slice method_slice = grpc_slice_from_copied_string(method);
  330. grpc_slice* host_slice_ptr = NULL;
  331. grpc_slice host_slice;
  332. if (host != NULL) {
  333. host_slice = grpc_slice_from_copied_string(host);
  334. host_slice_ptr = &host_slice;
  335. }
  336. grpc_call* ret =
  337. grpc_channel_create_call(channel, parent_call, propagation_mask, cq,
  338. method_slice, host_slice_ptr, deadline, NULL);
  339. grpc_slice_unref(method_slice);
  340. if (host != NULL) {
  341. grpc_slice_unref(host_slice);
  342. }
  343. return ret;
  344. }
  345. GPR_EXPORT grpc_connectivity_state GPR_CALLTYPE
  346. grpcsharp_channel_check_connectivity_state(grpc_channel* channel,
  347. int32_t try_to_connect) {
  348. return grpc_channel_check_connectivity_state(channel, try_to_connect);
  349. }
  350. GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_watch_connectivity_state(
  351. grpc_channel* channel, grpc_connectivity_state last_observed_state,
  352. gpr_timespec deadline, grpc_completion_queue* cq,
  353. grpcsharp_batch_context* ctx) {
  354. grpc_channel_watch_connectivity_state(channel, last_observed_state, deadline,
  355. cq, ctx);
  356. }
  357. GPR_EXPORT char* GPR_CALLTYPE
  358. grpcsharp_channel_get_target(grpc_channel* channel) {
  359. return grpc_channel_get_target(channel);
  360. }
  361. /* Channel args */
  362. GPR_EXPORT grpc_channel_args* GPR_CALLTYPE
  363. grpcsharp_channel_args_create(size_t num_args) {
  364. grpc_channel_args* args =
  365. (grpc_channel_args*)gpr_malloc(sizeof(grpc_channel_args));
  366. memset(args, 0, sizeof(grpc_channel_args));
  367. args->num_args = num_args;
  368. args->args = (grpc_arg*)gpr_malloc(sizeof(grpc_arg) * num_args);
  369. memset(args->args, 0, sizeof(grpc_arg) * num_args);
  370. return args;
  371. }
  372. GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_set_string(
  373. grpc_channel_args* args, size_t index, const char* key, const char* value) {
  374. GPR_ASSERT(args);
  375. GPR_ASSERT(index < args->num_args);
  376. args->args[index].type = GRPC_ARG_STRING;
  377. args->args[index].key = gpr_strdup(key);
  378. args->args[index].value.string = gpr_strdup(value);
  379. }
  380. GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_args_set_integer(
  381. grpc_channel_args* args, size_t index, const char* key, int value) {
  382. GPR_ASSERT(args);
  383. GPR_ASSERT(index < args->num_args);
  384. args->args[index].type = GRPC_ARG_INTEGER;
  385. args->args[index].key = gpr_strdup(key);
  386. args->args[index].value.integer = value;
  387. }
  388. GPR_EXPORT void GPR_CALLTYPE
  389. grpcsharp_channel_args_destroy(grpc_channel_args* args) {
  390. size_t i;
  391. if (args) {
  392. for (i = 0; i < args->num_args; i++) {
  393. gpr_free(args->args[i].key);
  394. if (args->args[i].type == GRPC_ARG_STRING) {
  395. gpr_free(args->args[i].value.string);
  396. }
  397. }
  398. gpr_free(args->args);
  399. gpr_free(args);
  400. }
  401. }
  402. /* Timespec */
  403. GPR_EXPORT gpr_timespec GPR_CALLTYPE gprsharp_now(gpr_clock_type clock_type) {
  404. return gpr_now(clock_type);
  405. }
  406. GPR_EXPORT gpr_timespec GPR_CALLTYPE
  407. gprsharp_inf_future(gpr_clock_type clock_type) {
  408. return gpr_inf_future(clock_type);
  409. }
  410. GPR_EXPORT gpr_timespec GPR_CALLTYPE
  411. gprsharp_inf_past(gpr_clock_type clock_type) {
  412. return gpr_inf_past(clock_type);
  413. }
  414. GPR_EXPORT gpr_timespec GPR_CALLTYPE
  415. gprsharp_convert_clock_type(gpr_timespec t, gpr_clock_type target_clock) {
  416. return gpr_convert_clock_type(t, target_clock);
  417. }
  418. GPR_EXPORT int32_t GPR_CALLTYPE gprsharp_sizeof_timespec(void) {
  419. return sizeof(gpr_timespec);
  420. }
  421. /* Call */
  422. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel(grpc_call* call) {
  423. return grpc_call_cancel(call, NULL);
  424. }
  425. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_cancel_with_status(
  426. grpc_call* call, grpc_status_code status, const char* description) {
  427. return grpc_call_cancel_with_status(call, status, description, NULL);
  428. }
  429. GPR_EXPORT char* GPR_CALLTYPE grpcsharp_call_get_peer(grpc_call* call) {
  430. return grpc_call_get_peer(call);
  431. }
  432. GPR_EXPORT void GPR_CALLTYPE gprsharp_free(void* p) { gpr_free(p); }
  433. GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_destroy(grpc_call* call) {
  434. grpc_call_unref(call);
  435. }
  436. typedef grpc_call_error (*grpcsharp_call_start_batch_func)(grpc_call* call,
  437. const grpc_op* ops,
  438. size_t nops,
  439. void* tag,
  440. void* reserved);
  441. /* Only for testing */
  442. static grpc_call_error grpcsharp_call_start_batch_nop(grpc_call* call,
  443. const grpc_op* ops,
  444. size_t nops, void* tag,
  445. void* reserved) {
  446. return GRPC_CALL_OK;
  447. }
  448. static grpc_call_error grpcsharp_call_start_batch_default(grpc_call* call,
  449. const grpc_op* ops,
  450. size_t nops,
  451. void* tag,
  452. void* reserved) {
  453. return grpc_call_start_batch(call, ops, nops, tag, reserved);
  454. }
  455. static grpcsharp_call_start_batch_func g_call_start_batch_func =
  456. grpcsharp_call_start_batch_default;
  457. static grpc_call_error grpcsharp_call_start_batch(grpc_call* call,
  458. const grpc_op* ops,
  459. size_t nops, void* tag,
  460. void* reserved) {
  461. return g_call_start_batch_func(call, ops, nops, tag, reserved);
  462. }
  463. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(
  464. grpc_call* call, grpcsharp_batch_context* ctx, const char* send_buffer,
  465. size_t send_buffer_len, uint32_t write_flags,
  466. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  467. /* TODO: don't use magic number */
  468. grpc_op ops[6];
  469. memset(ops, 0, sizeof(ops));
  470. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  471. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  472. initial_metadata);
  473. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  474. ops[0].data.send_initial_metadata.metadata =
  475. ctx->send_initial_metadata.metadata;
  476. ops[0].flags = initial_metadata_flags;
  477. ops[0].reserved = NULL;
  478. ops[1].op = GRPC_OP_SEND_MESSAGE;
  479. ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
  480. ops[1].data.send_message.send_message = ctx->send_message;
  481. ops[1].flags = write_flags;
  482. ops[1].reserved = NULL;
  483. ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  484. ops[2].flags = 0;
  485. ops[2].reserved = NULL;
  486. ops[3].op = GRPC_OP_RECV_INITIAL_METADATA;
  487. ops[3].data.recv_initial_metadata.recv_initial_metadata =
  488. &(ctx->recv_initial_metadata);
  489. ops[3].flags = 0;
  490. ops[3].reserved = NULL;
  491. ops[4].op = GRPC_OP_RECV_MESSAGE;
  492. ops[4].data.recv_message.recv_message = &(ctx->recv_message);
  493. ops[4].flags = 0;
  494. ops[4].reserved = NULL;
  495. ops[5].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  496. ops[5].data.recv_status_on_client.trailing_metadata =
  497. &(ctx->recv_status_on_client.trailing_metadata);
  498. ops[5].data.recv_status_on_client.status =
  499. &(ctx->recv_status_on_client.status);
  500. ops[5].data.recv_status_on_client.status_details =
  501. &(ctx->recv_status_on_client.status_details);
  502. ops[5].flags = 0;
  503. ops[5].reserved = NULL;
  504. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  505. ctx, NULL);
  506. }
  507. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(
  508. grpc_call* call, grpcsharp_batch_context* ctx,
  509. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  510. /* TODO: don't use magic number */
  511. grpc_op ops[4];
  512. memset(ops, 0, sizeof(ops));
  513. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  514. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  515. initial_metadata);
  516. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  517. ops[0].data.send_initial_metadata.metadata =
  518. ctx->send_initial_metadata.metadata;
  519. ops[0].flags = initial_metadata_flags;
  520. ops[0].reserved = NULL;
  521. ops[1].op = GRPC_OP_RECV_INITIAL_METADATA;
  522. ops[1].data.recv_initial_metadata.recv_initial_metadata =
  523. &(ctx->recv_initial_metadata);
  524. ops[1].flags = 0;
  525. ops[1].reserved = NULL;
  526. ops[2].op = GRPC_OP_RECV_MESSAGE;
  527. ops[2].data.recv_message.recv_message = &(ctx->recv_message);
  528. ops[2].flags = 0;
  529. ops[2].reserved = NULL;
  530. ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  531. ops[3].data.recv_status_on_client.trailing_metadata =
  532. &(ctx->recv_status_on_client.trailing_metadata);
  533. ops[3].data.recv_status_on_client.status =
  534. &(ctx->recv_status_on_client.status);
  535. ops[3].data.recv_status_on_client.status_details =
  536. &(ctx->recv_status_on_client.status_details);
  537. ops[3].flags = 0;
  538. ops[3].reserved = NULL;
  539. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  540. ctx, NULL);
  541. }
  542. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming(
  543. grpc_call* call, grpcsharp_batch_context* ctx, const char* send_buffer,
  544. size_t send_buffer_len, uint32_t write_flags,
  545. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  546. /* TODO: don't use magic number */
  547. grpc_op ops[4];
  548. memset(ops, 0, sizeof(ops));
  549. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  550. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  551. initial_metadata);
  552. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  553. ops[0].data.send_initial_metadata.metadata =
  554. ctx->send_initial_metadata.metadata;
  555. ops[0].flags = initial_metadata_flags;
  556. ops[0].reserved = NULL;
  557. ops[1].op = GRPC_OP_SEND_MESSAGE;
  558. ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
  559. ops[1].data.send_message.send_message = ctx->send_message;
  560. ops[1].flags = write_flags;
  561. ops[1].reserved = NULL;
  562. ops[2].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  563. ops[2].flags = 0;
  564. ops[2].reserved = NULL;
  565. ops[3].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  566. ops[3].data.recv_status_on_client.trailing_metadata =
  567. &(ctx->recv_status_on_client.trailing_metadata);
  568. ops[3].data.recv_status_on_client.status =
  569. &(ctx->recv_status_on_client.status);
  570. ops[3].data.recv_status_on_client.status_details =
  571. &(ctx->recv_status_on_client.status_details);
  572. ops[3].flags = 0;
  573. ops[3].reserved = NULL;
  574. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  575. ctx, NULL);
  576. }
  577. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(
  578. grpc_call* call, grpcsharp_batch_context* ctx,
  579. grpc_metadata_array* initial_metadata, uint32_t initial_metadata_flags) {
  580. /* TODO: don't use magic number */
  581. grpc_op ops[2];
  582. memset(ops, 0, sizeof(ops));
  583. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  584. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  585. initial_metadata);
  586. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  587. ops[0].data.send_initial_metadata.metadata =
  588. ctx->send_initial_metadata.metadata;
  589. ops[0].flags = initial_metadata_flags;
  590. ops[0].reserved = NULL;
  591. ops[1].op = GRPC_OP_RECV_STATUS_ON_CLIENT;
  592. ops[1].data.recv_status_on_client.trailing_metadata =
  593. &(ctx->recv_status_on_client.trailing_metadata);
  594. ops[1].data.recv_status_on_client.status =
  595. &(ctx->recv_status_on_client.status);
  596. ops[1].data.recv_status_on_client.status_details =
  597. &(ctx->recv_status_on_client.status_details);
  598. ops[1].flags = 0;
  599. ops[1].reserved = NULL;
  600. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  601. ctx, NULL);
  602. }
  603. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_recv_initial_metadata(
  604. grpc_call* call, grpcsharp_batch_context* ctx) {
  605. /* TODO: don't use magic number */
  606. grpc_op ops[1];
  607. ops[0].op = GRPC_OP_RECV_INITIAL_METADATA;
  608. ops[0].data.recv_initial_metadata.recv_initial_metadata =
  609. &(ctx->recv_initial_metadata);
  610. ops[0].flags = 0;
  611. ops[0].reserved = NULL;
  612. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  613. ctx, NULL);
  614. }
  615. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_message(
  616. grpc_call* call, grpcsharp_batch_context* ctx, const char* send_buffer,
  617. size_t send_buffer_len, uint32_t write_flags,
  618. int32_t send_empty_initial_metadata) {
  619. /* TODO: don't use magic number */
  620. grpc_op ops[2];
  621. memset(ops, 0, sizeof(ops));
  622. size_t nops = send_empty_initial_metadata ? 2 : 1;
  623. ops[0].op = GRPC_OP_SEND_MESSAGE;
  624. ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len);
  625. ops[0].data.send_message.send_message = ctx->send_message;
  626. ops[0].flags = write_flags;
  627. ops[0].reserved = NULL;
  628. ops[1].op = GRPC_OP_SEND_INITIAL_METADATA;
  629. ops[1].flags = 0;
  630. ops[1].reserved = NULL;
  631. return grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
  632. }
  633. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_close_from_client(
  634. grpc_call* call, grpcsharp_batch_context* ctx) {
  635. /* TODO: don't use magic number */
  636. grpc_op ops[1];
  637. ops[0].op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
  638. ops[0].flags = 0;
  639. ops[0].reserved = NULL;
  640. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  641. ctx, NULL);
  642. }
  643. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
  644. grpc_call* call, grpcsharp_batch_context* ctx, grpc_status_code status_code,
  645. const char* status_details, size_t status_details_len,
  646. grpc_metadata_array* trailing_metadata, int32_t send_empty_initial_metadata,
  647. const char* optional_send_buffer, size_t optional_send_buffer_len,
  648. uint32_t write_flags) {
  649. /* TODO: don't use magic number */
  650. grpc_op ops[3];
  651. memset(ops, 0, sizeof(ops));
  652. size_t nops = 1;
  653. grpc_slice status_details_slice =
  654. grpc_slice_from_copied_buffer(status_details, status_details_len);
  655. ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
  656. ops[0].data.send_status_from_server.status = status_code;
  657. ops[0].data.send_status_from_server.status_details = &status_details_slice;
  658. grpcsharp_metadata_array_move(
  659. &(ctx->send_status_from_server.trailing_metadata), trailing_metadata);
  660. ops[0].data.send_status_from_server.trailing_metadata_count =
  661. ctx->send_status_from_server.trailing_metadata.count;
  662. ops[0].data.send_status_from_server.trailing_metadata =
  663. ctx->send_status_from_server.trailing_metadata.metadata;
  664. ops[0].flags = 0;
  665. ops[0].reserved = NULL;
  666. if (optional_send_buffer) {
  667. ops[nops].op = GRPC_OP_SEND_MESSAGE;
  668. ctx->send_message =
  669. string_to_byte_buffer(optional_send_buffer, optional_send_buffer_len);
  670. ops[nops].data.send_message.send_message = ctx->send_message;
  671. ops[nops].flags = write_flags;
  672. ops[nops].reserved = NULL;
  673. nops++;
  674. }
  675. if (send_empty_initial_metadata) {
  676. ops[nops].op = GRPC_OP_SEND_INITIAL_METADATA;
  677. ops[nops].flags = 0;
  678. ops[nops].reserved = NULL;
  679. nops++;
  680. }
  681. grpc_call_error ret = grpcsharp_call_start_batch(call, ops, nops, ctx, NULL);
  682. grpc_slice_unref(status_details_slice);
  683. return ret;
  684. }
  685. GPR_EXPORT grpc_call_error GPR_CALLTYPE
  686. grpcsharp_call_recv_message(grpc_call* call, grpcsharp_batch_context* ctx) {
  687. /* TODO: don't use magic number */
  688. grpc_op ops[1];
  689. ops[0].op = GRPC_OP_RECV_MESSAGE;
  690. ops[0].data.recv_message.recv_message = &(ctx->recv_message);
  691. ops[0].flags = 0;
  692. ops[0].reserved = NULL;
  693. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  694. ctx, NULL);
  695. }
  696. GPR_EXPORT grpc_call_error GPR_CALLTYPE
  697. grpcsharp_call_start_serverside(grpc_call* call, grpcsharp_batch_context* ctx) {
  698. /* TODO: don't use magic number */
  699. grpc_op ops[1];
  700. ops[0].op = GRPC_OP_RECV_CLOSE_ON_SERVER;
  701. ops[0].data.recv_close_on_server.cancelled =
  702. (&ctx->recv_close_on_server_cancelled);
  703. ops[0].flags = 0;
  704. ops[0].reserved = NULL;
  705. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  706. ctx, NULL);
  707. }
  708. GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_initial_metadata(
  709. grpc_call* call, grpcsharp_batch_context* ctx,
  710. grpc_metadata_array* initial_metadata) {
  711. /* TODO: don't use magic number */
  712. grpc_op ops[1];
  713. memset(ops, 0, sizeof(ops));
  714. ops[0].op = GRPC_OP_SEND_INITIAL_METADATA;
  715. grpcsharp_metadata_array_move(&(ctx->send_initial_metadata),
  716. initial_metadata);
  717. ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count;
  718. ops[0].data.send_initial_metadata.metadata =
  719. ctx->send_initial_metadata.metadata;
  720. ops[0].flags = 0;
  721. ops[0].reserved = NULL;
  722. return grpcsharp_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]),
  723. ctx, NULL);
  724. }
  725. GPR_EXPORT grpc_call_error GPR_CALLTYPE
  726. grpcsharp_call_set_credentials(grpc_call* call, grpc_call_credentials* creds) {
  727. return grpc_call_set_credentials(call, creds);
  728. }
  729. /* Server */
  730. GPR_EXPORT grpc_server* GPR_CALLTYPE
  731. grpcsharp_server_create(const grpc_channel_args* args) {
  732. return grpc_server_create(args, NULL);
  733. }
  734. GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_register_completion_queue(
  735. grpc_server* server, grpc_completion_queue* cq) {
  736. grpc_server_register_completion_queue(server, cq, NULL);
  737. }
  738. GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_insecure_http2_port(
  739. grpc_server* server, const char* addr) {
  740. return grpc_server_add_insecure_http2_port(server, addr);
  741. }
  742. GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_start(grpc_server* server) {
  743. grpc_server_start(server);
  744. }
  745. GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_shutdown_and_notify_callback(
  746. grpc_server* server, grpc_completion_queue* cq,
  747. grpcsharp_batch_context* ctx) {
  748. grpc_server_shutdown_and_notify(server, cq, ctx);
  749. }
  750. GPR_EXPORT void GPR_CALLTYPE
  751. grpcsharp_server_cancel_all_calls(grpc_server* server) {
  752. grpc_server_cancel_all_calls(server);
  753. }
  754. GPR_EXPORT void GPR_CALLTYPE grpcsharp_server_destroy(grpc_server* server) {
  755. grpc_server_destroy(server);
  756. }
  757. GPR_EXPORT grpc_call_error GPR_CALLTYPE
  758. grpcsharp_server_request_call(grpc_server* server, grpc_completion_queue* cq,
  759. grpcsharp_request_call_context* ctx) {
  760. return grpc_server_request_call(server, &(ctx->call), &(ctx->call_details),
  761. &(ctx->request_metadata), cq, cq, ctx);
  762. }
  763. /* Security */
  764. static char* default_pem_root_certs = NULL;
  765. static grpc_ssl_roots_override_result override_ssl_roots_handler(
  766. char** pem_root_certs) {
  767. if (!default_pem_root_certs) {
  768. *pem_root_certs = NULL;
  769. return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
  770. }
  771. *pem_root_certs = gpr_strdup(default_pem_root_certs);
  772. return GRPC_SSL_ROOTS_OVERRIDE_OK;
  773. }
  774. GPR_EXPORT void GPR_CALLTYPE
  775. grpcsharp_override_default_ssl_roots(const char* pem_root_certs) {
  776. /*
  777. * This currently wastes ~300kB of memory by keeping a copy of roots
  778. * in a static variable, but for desktop/server use, the overhead
  779. * is negligible. In the future, we might want to change the behavior
  780. * for mobile (e.g. Xamarin).
  781. */
  782. default_pem_root_certs = gpr_strdup(pem_root_certs);
  783. grpc_set_ssl_roots_override_callback(override_ssl_roots_handler);
  784. }
  785. GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE
  786. grpcsharp_ssl_credentials_create(const char* pem_root_certs,
  787. const char* key_cert_pair_cert_chain,
  788. const char* key_cert_pair_private_key) {
  789. grpc_ssl_pem_key_cert_pair key_cert_pair;
  790. if (key_cert_pair_cert_chain || key_cert_pair_private_key) {
  791. key_cert_pair.cert_chain = key_cert_pair_cert_chain;
  792. key_cert_pair.private_key = key_cert_pair_private_key;
  793. return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL);
  794. } else {
  795. GPR_ASSERT(!key_cert_pair_cert_chain);
  796. GPR_ASSERT(!key_cert_pair_private_key);
  797. return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL);
  798. }
  799. }
  800. GPR_EXPORT void GPR_CALLTYPE
  801. grpcsharp_channel_credentials_release(grpc_channel_credentials* creds) {
  802. grpc_channel_credentials_release(creds);
  803. }
  804. GPR_EXPORT void GPR_CALLTYPE
  805. grpcsharp_call_credentials_release(grpc_call_credentials* creds) {
  806. grpc_call_credentials_release(creds);
  807. }
  808. GPR_EXPORT grpc_channel* GPR_CALLTYPE grpcsharp_secure_channel_create(
  809. grpc_channel_credentials* creds, const char* target,
  810. const grpc_channel_args* args) {
  811. return grpc_secure_channel_create(creds, target, args, NULL);
  812. }
  813. GPR_EXPORT grpc_server_credentials* GPR_CALLTYPE
  814. grpcsharp_ssl_server_credentials_create(
  815. const char* pem_root_certs, const char** key_cert_pair_cert_chain_array,
  816. const char** key_cert_pair_private_key_array, size_t num_key_cert_pairs,
  817. int force_client_auth) {
  818. size_t i;
  819. grpc_server_credentials* creds;
  820. grpc_ssl_pem_key_cert_pair* key_cert_pairs =
  821. gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
  822. memset(key_cert_pairs, 0,
  823. sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
  824. for (i = 0; i < num_key_cert_pairs; i++) {
  825. if (key_cert_pair_cert_chain_array[i] ||
  826. key_cert_pair_private_key_array[i]) {
  827. key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i];
  828. key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
  829. }
  830. }
  831. creds = grpc_ssl_server_credentials_create_ex(
  832. pem_root_certs, key_cert_pairs, num_key_cert_pairs,
  833. force_client_auth
  834. ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
  835. : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE,
  836. NULL);
  837. gpr_free(key_cert_pairs);
  838. return creds;
  839. }
  840. GPR_EXPORT void GPR_CALLTYPE
  841. grpcsharp_server_credentials_release(grpc_server_credentials* creds) {
  842. grpc_server_credentials_release(creds);
  843. }
  844. GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_server_add_secure_http2_port(
  845. grpc_server* server, const char* addr, grpc_server_credentials* creds) {
  846. return grpc_server_add_secure_http2_port(server, addr, creds);
  847. }
  848. GPR_EXPORT grpc_channel_credentials* GPR_CALLTYPE
  849. grpcsharp_composite_channel_credentials_create(
  850. grpc_channel_credentials* channel_creds,
  851. grpc_call_credentials* call_creds) {
  852. return grpc_composite_channel_credentials_create(channel_creds, call_creds,
  853. NULL);
  854. }
  855. GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
  856. grpcsharp_composite_call_credentials_create(grpc_call_credentials* creds1,
  857. grpc_call_credentials* creds2) {
  858. return grpc_composite_call_credentials_create(creds1, creds2, NULL);
  859. }
  860. /* Metadata credentials plugin */
  861. GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
  862. grpc_credentials_plugin_metadata_cb cb, void* user_data,
  863. grpc_metadata_array* metadata, grpc_status_code status,
  864. const char* error_details) {
  865. if (metadata) {
  866. cb(user_data, metadata->metadata, metadata->count, status, error_details);
  867. } else {
  868. cb(user_data, NULL, 0, status, error_details);
  869. }
  870. }
  871. typedef void(GPR_CALLTYPE* grpcsharp_metadata_interceptor_func)(
  872. void* state, const char* service_url, const char* method_name,
  873. grpc_credentials_plugin_metadata_cb cb, void* user_data,
  874. int32_t is_destroy);
  875. static int grpcsharp_get_metadata_handler(
  876. void* state, grpc_auth_metadata_context context,
  877. grpc_credentials_plugin_metadata_cb cb, void* user_data,
  878. grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
  879. size_t* num_creds_md, grpc_status_code* status,
  880. const char** error_details) {
  881. grpcsharp_metadata_interceptor_func interceptor =
  882. (grpcsharp_metadata_interceptor_func)(intptr_t)state;
  883. interceptor(state, context.service_url, context.method_name, cb, user_data,
  884. 0);
  885. return 0; /* Asynchronous return. */
  886. }
  887. static void grpcsharp_metadata_credentials_destroy_handler(void* state) {
  888. grpcsharp_metadata_interceptor_func interceptor =
  889. (grpcsharp_metadata_interceptor_func)(intptr_t)state;
  890. interceptor(state, NULL, NULL, NULL, NULL, 1);
  891. }
  892. GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
  893. grpcsharp_metadata_credentials_create_from_plugin(
  894. grpcsharp_metadata_interceptor_func metadata_interceptor) {
  895. grpc_metadata_credentials_plugin plugin;
  896. plugin.get_metadata = grpcsharp_get_metadata_handler;
  897. plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
  898. plugin.state = (void*)(intptr_t)metadata_interceptor;
  899. plugin.type = "";
  900. return grpc_metadata_credentials_create_from_plugin(plugin, NULL);
  901. }
  902. /* Auth context */
  903. GPR_EXPORT grpc_auth_context* GPR_CALLTYPE
  904. grpcsharp_call_auth_context(grpc_call* call) {
  905. return grpc_call_auth_context(call);
  906. }
  907. GPR_EXPORT const char* GPR_CALLTYPE
  908. grpcsharp_auth_context_peer_identity_property_name(
  909. const grpc_auth_context* ctx) {
  910. return grpc_auth_context_peer_identity_property_name(ctx);
  911. }
  912. GPR_EXPORT grpc_auth_property_iterator GPR_CALLTYPE
  913. grpcsharp_auth_context_property_iterator(const grpc_auth_context* ctx) {
  914. return grpc_auth_context_property_iterator(ctx);
  915. }
  916. GPR_EXPORT const grpc_auth_property* GPR_CALLTYPE
  917. grpcsharp_auth_property_iterator_next(grpc_auth_property_iterator* it) {
  918. return grpc_auth_property_iterator_next(it);
  919. }
  920. GPR_EXPORT void GPR_CALLTYPE
  921. grpcsharp_auth_context_release(grpc_auth_context* ctx) {
  922. grpc_auth_context_release(ctx);
  923. }
  924. /* Logging */
  925. typedef void(GPR_CALLTYPE* grpcsharp_log_func)(const char* file, int32_t line,
  926. uint64_t thd_id,
  927. const char* severity_string,
  928. const char* msg);
  929. static grpcsharp_log_func log_func = NULL;
  930. /* Redirects gpr_log to log_func callback */
  931. static void grpcsharp_log_handler(gpr_log_func_args* args) {
  932. log_func(args->file, args->line, gpr_thd_currentid(),
  933. gpr_log_severity_string(args->severity), args->message);
  934. }
  935. GPR_EXPORT void GPR_CALLTYPE grpcsharp_redirect_log(grpcsharp_log_func func) {
  936. GPR_ASSERT(func);
  937. log_func = func;
  938. gpr_set_log_function(grpcsharp_log_handler);
  939. }
  940. typedef void(GPR_CALLTYPE* test_callback_funcptr)(int32_t success);
  941. /* Version info */
  942. GPR_EXPORT const char* GPR_CALLTYPE grpcsharp_version_string() {
  943. return grpc_version_string();
  944. }
  945. /* For testing */
  946. GPR_EXPORT void GPR_CALLTYPE
  947. grpcsharp_test_callback(test_callback_funcptr callback) {
  948. callback(1);
  949. }
  950. /* For testing */
  951. GPR_EXPORT void* GPR_CALLTYPE grpcsharp_test_nop(void* ptr) { return ptr; }
  952. /* For testing */
  953. GPR_EXPORT int32_t GPR_CALLTYPE grpcsharp_sizeof_grpc_event(void) {
  954. return sizeof(grpc_event);
  955. }
  956. /* Override a method for testing */
  957. GPR_EXPORT void GPR_CALLTYPE
  958. grpcsharp_test_override_method(const char* method_name, const char* variant) {
  959. if (strcmp("grpcsharp_call_start_batch", method_name) == 0) {
  960. if (strcmp("nop", variant) == 0) {
  961. g_call_start_batch_func = grpcsharp_call_start_batch_nop;
  962. } else {
  963. GPR_ASSERT(0);
  964. }
  965. } else {
  966. GPR_ASSERT(0);
  967. }
  968. }