parent
922d8a69a4
commit
94c365326a
6 changed files with 238 additions and 2 deletions
@ -0,0 +1,2 @@ |
|||||||
|
*.userprefs |
||||||
|
test-results |
@ -0,0 +1,22 @@ |
|||||||
|
gRPC C# |
||||||
|
======= |
||||||
|
|
||||||
|
A C# implementation of gRPC, Google's RPC library. |
||||||
|
|
||||||
|
EXPERIMENTAL ONLY |
||||||
|
----------------- |
||||||
|
|
||||||
|
**This gRPC C# implementation is work-in-progress and is not expected to work yet.** |
||||||
|
|
||||||
|
- The implementation is a wrapper around gRPC C core library |
||||||
|
- Code only runs under mono currently, because there have been issues building |
||||||
|
the gRPC C core library under Windows. |
||||||
|
- It is very possible that some parts of the code will be heavily refactored or |
||||||
|
completely rewritten. |
||||||
|
|
||||||
|
CONTENTS |
||||||
|
-------- |
||||||
|
|
||||||
|
- ext: |
||||||
|
The extension library that wraps C API to be more digestible by C#. |
||||||
|
|
@ -0,0 +1,113 @@ |
|||||||
|
#include <grpc/grpc.h> |
||||||
|
#include <grpc/support/log.h> |
||||||
|
#include <grpc/support/slice.h> |
||||||
|
|
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
grpc_byte_buffer *string_to_byte_buffer(const char *buffer, size_t len) { |
||||||
|
gpr_slice slice = gpr_slice_from_copied_buffer(buffer, len); |
||||||
|
grpc_byte_buffer *bb = grpc_byte_buffer_create(&slice, 1); |
||||||
|
gpr_slice_unref(slice); |
||||||
|
return bb; |
||||||
|
} |
||||||
|
|
||||||
|
void grpc_call_start_write_from_copied_buffer(grpc_call *call, |
||||||
|
const char *buffer, size_t len, |
||||||
|
void *tag, gpr_uint32 flags) { |
||||||
|
grpc_byte_buffer *byte_buffer = string_to_byte_buffer(buffer, len); |
||||||
|
GPR_ASSERT(grpc_call_start_write_old(call, byte_buffer, tag, flags) == |
||||||
|
GRPC_CALL_OK); |
||||||
|
grpc_byte_buffer_destroy(byte_buffer); |
||||||
|
} |
||||||
|
|
||||||
|
grpc_completion_type grpc_event_type(const grpc_event *event) { |
||||||
|
return event->type; |
||||||
|
} |
||||||
|
|
||||||
|
grpc_op_error grpc_event_write_accepted(const grpc_event *event) { |
||||||
|
GPR_ASSERT(event->type == GRPC_WRITE_ACCEPTED); |
||||||
|
return event->data.invoke_accepted; |
||||||
|
} |
||||||
|
|
||||||
|
grpc_op_error grpc_event_finish_accepted(const grpc_event *event) { |
||||||
|
GPR_ASSERT(event->type == GRPC_FINISH_ACCEPTED); |
||||||
|
return event->data.finish_accepted; |
||||||
|
} |
||||||
|
|
||||||
|
grpc_status_code grpc_event_finished_status(const grpc_event *event) { |
||||||
|
GPR_ASSERT(event->type == GRPC_FINISHED); |
||||||
|
return event->data.finished.status; |
||||||
|
} |
||||||
|
|
||||||
|
const char *grpc_event_finished_details(const grpc_event *event) { |
||||||
|
GPR_ASSERT(event->type == GRPC_FINISHED); |
||||||
|
return event->data.finished.details; |
||||||
|
} |
||||||
|
|
||||||
|
gpr_intptr grpc_event_read_length(const grpc_event *event) { |
||||||
|
GPR_ASSERT(event->type == GRPC_READ); |
||||||
|
if (!event->data.read) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
return grpc_byte_buffer_length(event->data.read); |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
* Copies data from read event to a buffer. Fatal error occurs if |
||||||
|
* buffer is too small. |
||||||
|
*/ |
||||||
|
void grpc_event_read_copy_to_buffer(const grpc_event *event, char *buffer, |
||||||
|
size_t buffer_len) { |
||||||
|
grpc_byte_buffer_reader *reader; |
||||||
|
gpr_slice slice; |
||||||
|
size_t offset = 0; |
||||||
|
|
||||||
|
GPR_ASSERT(event->type == GRPC_READ); |
||||||
|
reader = grpc_byte_buffer_reader_create(event->data.read); |
||||||
|
|
||||||
|
GPR_ASSERT(event->data.read); |
||||||
|
while (grpc_byte_buffer_reader_next(reader, &slice)) { |
||||||
|
size_t len = GPR_SLICE_LENGTH(slice); |
||||||
|
GPR_ASSERT(offset + len <= buffer_len); |
||||||
|
memcpy(buffer + offset, GPR_SLICE_START_PTR(slice), |
||||||
|
GPR_SLICE_LENGTH(slice)); |
||||||
|
offset += len; |
||||||
|
gpr_slice_unref(slice); |
||||||
|
} |
||||||
|
grpc_byte_buffer_reader_destroy(reader); |
||||||
|
} |
||||||
|
|
||||||
|
grpc_call *grpc_event_call(const grpc_event *event) { |
||||||
|
/* we only allow this for newly incoming server calls. */ |
||||||
|
GPR_ASSERT(event->type == GRPC_SERVER_RPC_NEW); |
||||||
|
return event->call; |
||||||
|
} |
||||||
|
|
||||||
|
const char *grpc_event_server_rpc_new_method(const grpc_event *event) { |
||||||
|
GPR_ASSERT(event->type == GRPC_SERVER_RPC_NEW); |
||||||
|
return event->data.server_rpc_new.method; |
||||||
|
} |
||||||
|
|
||||||
|
grpc_completion_type grpc_completion_queue_next_with_callback( |
||||||
|
grpc_completion_queue *cq) { |
||||||
|
grpc_event *ev; |
||||||
|
grpc_completion_type t; |
||||||
|
void (*callback)(grpc_event *); |
||||||
|
|
||||||
|
ev = grpc_completion_queue_next(cq, gpr_inf_future); |
||||||
|
t = ev->type; |
||||||
|
if (ev->tag) { |
||||||
|
/* call the callback in ev->tag */ |
||||||
|
/* C forbids to cast object pointers to function pointers, so
|
||||||
|
* we cast to intptr first. |
||||||
|
*/ |
||||||
|
callback = (void (*)(grpc_event *))(gpr_intptr)ev->tag; |
||||||
|
(*callback)(ev); |
||||||
|
} |
||||||
|
grpc_event_finish(ev); |
||||||
|
|
||||||
|
/* return completion type to allow some handling for events that have no
|
||||||
|
* tag - such as GRPC_QUEUE_SHUTDOWN |
||||||
|
*/ |
||||||
|
return t; |
||||||
|
} |
Loading…
Reference in new issue