diff options
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | Makefile | 86 | ||||
-rw-r--r-- | build.json | 12 | ||||
-rw-r--r-- | src/csharp/.gitignore | 2 | ||||
-rwxr-xr-x | src/csharp/README.md | 22 | ||||
-rw-r--r-- | src/csharp/ext/grpc_csharp_ext.c | 113 |
6 files changed, 238 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore index 6eb55b1202..9c9ae5abd4 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,11 @@ coverage # python compiled objects *.pyc +#eclipse project files +.cproject +.project +.settings + # cache for run_tests.py .run_tests_cache @@ -551,13 +551,13 @@ endif static: static_c static_cxx -static_c: libs/$(CONFIG)/libgpr.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgrpc_unsecure.a +static_c: libs/$(CONFIG)/libgpr.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgrpc_unsecure.a libs/$(CONFIG)/libgrpc_csharp_ext.a static_cxx: libs/$(CONFIG)/libgrpc++.a shared: shared_c shared_cxx -shared_c: libs/$(CONFIG)/libgpr.$(SHARED_EXT) libs/$(CONFIG)/libgrpc.$(SHARED_EXT) libs/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) +shared_c: libs/$(CONFIG)/libgpr.$(SHARED_EXT) libs/$(CONFIG)/libgrpc.$(SHARED_EXT) libs/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) libs/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) shared_cxx: libs/$(CONFIG)/libgrpc++.$(SHARED_EXT) @@ -1016,6 +1016,8 @@ ifeq ($(CONFIG),opt) $(Q) $(STRIP) libs/$(CONFIG)/libgrpc.a $(E) "[STRIP] Stripping libgrpc_unsecure.a" $(Q) $(STRIP) libs/$(CONFIG)/libgrpc_unsecure.a + $(E) "[STRIP] Stripping libgrpc_csharp_ext.a" + $(Q) $(STRIP) libs/$(CONFIG)/libgrpc_csharp_ext.a endif strip-static_cxx: static_cxx @@ -1032,6 +1034,8 @@ ifeq ($(CONFIG),opt) $(Q) $(STRIP) libs/$(CONFIG)/libgrpc.$(SHARED_EXT) $(E) "[STRIP] Stripping libgrpc_unsecure.so" $(Q) $(STRIP) libs/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) + $(E) "[STRIP] Stripping libgrpc_csharp_ext.so" + $(Q) $(STRIP) libs/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) endif strip-shared_cxx: shared_cxx @@ -1137,6 +1141,8 @@ install-static_c: static_c strip-static_c $(Q) $(INSTALL) libs/$(CONFIG)/libgrpc.a $(prefix)/lib/libgrpc.a $(E) "[INSTALL] Installing libgrpc_unsecure.a" $(Q) $(INSTALL) libs/$(CONFIG)/libgrpc_unsecure.a $(prefix)/lib/libgrpc_unsecure.a + $(E) "[INSTALL] Installing libgrpc_csharp_ext.a" + $(Q) $(INSTALL) libs/$(CONFIG)/libgrpc_csharp_ext.a $(prefix)/lib/libgrpc_csharp_ext.a install-static_cxx: static_cxx strip-static_cxx $(E) "[INSTALL] Installing libgrpc++.a" @@ -1176,6 +1182,17 @@ ifneq ($(SYSTEM),Darwin) $(Q) ln -sf libgrpc_unsecure.$(SHARED_EXT) $(prefix)/lib/libgrpc_unsecure.so endif endif +ifeq ($(SYSTEM),MINGW32) + $(E) "[INSTALL] Installing grpc_csharp_ext.$(SHARED_EXT)" + $(Q) $(INSTALL) libs/$(CONFIG)/grpc_csharp_ext.$(SHARED_EXT) $(prefix)/lib/grpc_csharp_ext.$(SHARED_EXT) + $(Q) $(INSTALL) libs/$(CONFIG)/libgrpc_csharp_ext-imp.a $(prefix)/lib/libgrpc_csharp_ext-imp.a +else + $(E) "[INSTALL] Installing libgrpc_csharp_ext.$(SHARED_EXT)" + $(Q) $(INSTALL) libs/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) $(prefix)/lib/libgrpc_csharp_ext.$(SHARED_EXT) +ifneq ($(SYSTEM),Darwin) + $(Q) ln -sf libgrpc_csharp_ext.$(SHARED_EXT) $(prefix)/lib/libgrpc_csharp_ext.so +endif +endif ifneq ($(SYSTEM),MINGW32) ifneq ($(SYSTEM),Darwin) $(Q) ldconfig @@ -2296,6 +2313,71 @@ objs/$(CONFIG)/examples/tips/publisher.o: gens/examples/tips/label.pb.cc objs/$(CONFIG)/examples/tips/subscriber.o: gens/examples/tips/label.pb.cc gens/examples/tips/empty.pb.cc gens/examples/tips/pubsub.pb.cc +LIBGRPC_CSHARP_EXT_SRC = \ + src/csharp/ext/grpc_csharp_ext.c \ + + +LIBGRPC_CSHARP_EXT_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CSHARP_EXT_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure libraries if you don't have OpenSSL with ALPN. + +libs/$(CONFIG)/libgrpc_csharp_ext.a: openssl_dep_error + +ifeq ($(SYSTEM),MINGW32) +libs/$(CONFIG)/grpc_csharp_ext.$(SHARED_EXT): openssl_dep_error +else +libs/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT): openssl_dep_error +endif + +else + +ifneq ($(OPENSSL_DEP),) +src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP) +endif + +libs/$(CONFIG)/libgrpc_csharp_ext.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(LIBGRPC_CSHARP_EXT_OBJS) + $(E) "[AR] Creating $@" + $(Q) mkdir -p `dirname $@` + $(Q) rm -f libs/$(CONFIG)/libgrpc_csharp_ext.a + $(Q) $(AR) rcs libs/$(CONFIG)/libgrpc_csharp_ext.a $(LIBGRPC_CSHARP_EXT_OBJS) +ifeq ($(SYSTEM),Darwin) + $(Q) ranlib libs/$(CONFIG)/libgrpc_csharp_ext.a +endif + + + +ifeq ($(SYSTEM),MINGW32) +libs/$(CONFIG)/grpc_csharp_ext.$(SHARED_EXT): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP)libs/$(CONFIG)/gpr.$(SHARED_EXT)libs/$(CONFIG)/grpc.$(SHARED_EXT) $(OPENSSL_DEP) + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) -Llibs/$(CONFIG) -shared -Wl,--output-def=libs/$(CONFIG)/grpc_csharp_ext.def -Wl,--out-implib=libs/$(CONFIG)/libgrpc_csharp_ext-imp.a -o libs/$(CONFIG)/grpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr-imp -lgrpc-imp +else +libs/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) libs/$(CONFIG)/libgpr.$(SHARED_EXT) libs/$(CONFIG)/libgrpc.$(SHARED_EXT) $(OPENSSL_DEP) + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` +ifeq ($(SYSTEM),Darwin) + $(Q) $(LD) $(LDFLAGS) -Llibs/$(CONFIG) -dynamiclib -o libs/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr -lgrpc +else + $(Q) $(LD) $(LDFLAGS) -Llibs/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.0 -o libs/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) $(LIBGRPC_CSHARP_EXT_OBJS) $(LDLIBS) $(LDLIBS_SECURE) $(OPENSSL_MERGE_LIBS) -lgpr -lgrpc + $(Q) ln -sf libgrpc_csharp_ext.$(SHARED_EXT) libs/$(CONFIG)/libgrpc_csharp_ext.so.0 + $(Q) ln -sf libgrpc_csharp_ext.$(SHARED_EXT) libs/$(CONFIG)/libgrpc_csharp_ext.so +endif +endif + + +endif + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(LIBGRPC_CSHARP_EXT_OBJS:.o=.dep) +endif +endif + +objs/$(CONFIG)/src/csharp/ext/grpc_csharp_ext.o: + + LIBEND2END_FIXTURE_CHTTP2_FAKE_SECURITY_SRC = \ test/core/end2end/fixtures/chttp2_fake_security.c \ diff --git a/build.json b/build.json index 6e20d617e3..478fa785cd 100644 --- a/build.json +++ b/build.json @@ -441,6 +441,18 @@ "grpc", "gpr" ] + }, + { + "name": "grpc_csharp_ext", + "build": "all", + "language": "c", + "deps": [ + "gpr", + "grpc" + ], + "src": [ + "src/csharp/ext/grpc_csharp_ext.c" + ] } ], "targets": [ diff --git a/src/csharp/.gitignore b/src/csharp/.gitignore new file mode 100644 index 0000000000..dbf38f34b7 --- /dev/null +++ b/src/csharp/.gitignore @@ -0,0 +1,2 @@ +*.userprefs +test-results diff --git a/src/csharp/README.md b/src/csharp/README.md new file mode 100755 index 0000000000..5b56303c14 --- /dev/null +++ b/src/csharp/README.md @@ -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, building gGRPC C core library under Windows + is in progress. +- 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#. + diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c new file mode 100644 index 0000000000..74d11c655b --- /dev/null +++ b/src/csharp/ext/grpc_csharp_ext.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; +} |