Merge branch 'master' of github.com:grpc/grpc into lb_pollset_propagation

pull/6190/head
David Garcia Quintas 9 years ago
commit 12e111c692
  1. 2
      .gitignore
  2. 19
      BUILD
  3. 177
      Makefile
  4. 2
      binding.gyp
  5. 41
      build.yaml
  6. 2
      config.m4
  7. 2
      examples/cpp/helloworld/Makefile
  8. 2
      examples/cpp/route_guide/Makefile
  9. 20
      examples/node/greeter_client.js
  10. 12
      examples/node/greeter_server.js
  11. 39
      examples/node/helloworld_grpc_pb.js
  12. 332
      examples/node/helloworld_pb.js
  13. 1
      examples/node/package.json
  14. 2
      gRPC.podspec
  15. 6
      grpc.gemspec
  16. 39
      include/grpc/impl/codegen/port_platform.h
  17. 25
      package.json
  18. 25
      package.xml
  19. 5
      requirements.txt
  20. 14
      src/compiler/config.h
  21. 35
      src/compiler/cpp_generator.cc
  22. 17
      src/compiler/cpp_generator.h
  23. 33
      src/compiler/cpp_plugin.cc
  24. 32
      src/compiler/csharp_generator.cc
  25. 4
      src/compiler/csharp_generator.h
  26. 24
      src/compiler/csharp_plugin.cc
  27. 119
      src/compiler/generator_helpers.h
  28. 277
      src/compiler/node_generator.cc
  29. 49
      src/compiler/node_generator.h
  30. 50
      src/compiler/node_generator_helpers.h
  31. 77
      src/compiler/node_plugin.cc
  32. 24
      src/core/ext/client_config/client_channel.c
  33. 7
      src/core/ext/client_config/subchannel.c
  34. 6
      src/core/ext/client_config/subchannel_call_holder.c
  35. 14
      src/core/ext/resolver/dns/native/dns_resolver.c
  36. 6
      src/core/ext/resolver/zookeeper/zookeeper_resolver.c
  37. 4
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  38. 2
      src/core/ext/transport/chttp2/transport/hpack_parser.c
  39. 10
      src/core/lib/channel/compress_filter.c
  40. 13
      src/core/lib/channel/http_server_filter.c
  41. 2
      src/core/lib/http/httpcli.c
  42. 35
      src/core/lib/http/parser.c
  43. 1
      src/core/lib/http/parser.h
  44. 6
      src/core/lib/iomgr/closure.c
  45. 3
      src/core/lib/iomgr/closure.h
  46. 2
      src/core/lib/iomgr/exec_ctx.h
  47. 3
      src/core/lib/iomgr/resolve_address.h
  48. 9
      src/core/lib/iomgr/resolve_address_posix.c
  49. 9
      src/core/lib/iomgr/resolve_address_windows.c
  50. 23
      src/core/lib/iomgr/tcp_client_posix.c
  51. 28
      src/core/lib/iomgr/tcp_server_windows.c
  52. 16
      src/core/lib/iomgr/tcp_windows.c
  53. 15
      src/core/lib/iomgr/timer.c
  54. 44
      src/core/lib/support/env_win32.c
  55. 4
      src/core/lib/support/log_linux.c
  56. 18
      src/core/lib/support/log_win32.c
  57. 94
      src/core/lib/support/string_util_win32.c
  58. 32
      src/core/lib/support/string_win32.c
  59. 10
      src/core/lib/support/time_posix.c
  60. 4
      src/core/lib/support/time_win32.c
  61. 73
      src/core/lib/support/tmpfile_msys.c
  62. 4
      src/core/lib/support/tmpfile_posix.c
  63. 4
      src/core/lib/support/tmpfile_win32.c
  64. 93
      src/core/lib/surface/call.c
  65. 3
      src/core/lib/surface/lame_client.c
  66. 2
      src/core/lib/surface/validate_metadata.c
  67. 21
      src/core/lib/transport/metadata.c
  68. 1
      src/core/lib/transport/metadata.h
  69. 3
      src/csharp/Grpc.Core/Version.cs
  70. 11
      src/csharp/Grpc.Core/VersionInfo.cs
  71. 18
      src/csharp/Grpc.Examples/MathGrpc.cs
  72. 18
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  73. 3
      src/csharp/Grpc.IntegrationTesting.StressClient/.gitignore
  74. 60
      src/csharp/Grpc.IntegrationTesting.StressClient/Grpc.IntegrationTesting.StressClient.csproj
  75. 26
      src/csharp/Grpc.IntegrationTesting.StressClient/Program.cs
  76. 11
      src/csharp/Grpc.IntegrationTesting.StressClient/Properties/AssemblyInfo.cs
  77. 3
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  78. 3
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  79. 452
      src/csharp/Grpc.IntegrationTesting/Metrics.cs
  80. 152
      src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
  81. 36
      src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
  82. 318
      src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
  83. 54
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  84. 8
      src/csharp/Grpc.sln
  85. 6
      src/csharp/buildall.bat
  86. 2
      src/csharp/generate_proto_csharp.sh
  87. 2
      src/node/.gitignore
  88. 1
      src/node/.jshintignore
  89. 28
      src/node/.jshintrc
  90. 3
      src/node/src/client.js
  91. 99
      src/node/test/math/math_grpc_pb.js
  92. 866
      src/node/test/math/math_pb.js
  93. 40
      src/node/test/math/math_server.js
  94. 37
      src/node/test/math/node_modules/grpc.js
  95. 43
      src/node/test/math_client_test.js
  96. 75
      src/proto/grpc/testing/compiler_test.proto
  97. 1
      src/python/.gitignore
  98. 34
      src/python/grpcio/commands.py
  99. 2
      src/python/grpcio/grpc_core_dependencies.py
  100. 2
      src/python/grpcio/tests/interop/_insecure_interop_test.py
  101. Some files were not shown because too many files have changed in this diff Show More

2
.gitignore vendored

@ -14,7 +14,7 @@ dist/
*.egg *.egg
# Node installation output # Node installation output
node_modules/ ^node_modules
src/node/extension_binary/ src/node/extension_binary/
# gcov coverage data # gcov coverage data

19
BUILD

@ -84,6 +84,7 @@ cc_library(
"src/core/lib/support/stack_lockfree.c", "src/core/lib/support/stack_lockfree.c",
"src/core/lib/support/string.c", "src/core/lib/support/string.c",
"src/core/lib/support/string_posix.c", "src/core/lib/support/string_posix.c",
"src/core/lib/support/string_util_win32.c",
"src/core/lib/support/string_win32.c", "src/core/lib/support/string_win32.c",
"src/core/lib/support/subprocess_posix.c", "src/core/lib/support/subprocess_posix.c",
"src/core/lib/support/subprocess_windows.c", "src/core/lib/support/subprocess_windows.c",
@ -98,6 +99,7 @@ cc_library(
"src/core/lib/support/time_precise.c", "src/core/lib/support/time_precise.c",
"src/core/lib/support/time_win32.c", "src/core/lib/support/time_win32.c",
"src/core/lib/support/tls_pthread.c", "src/core/lib/support/tls_pthread.c",
"src/core/lib/support/tmpfile_msys.c",
"src/core/lib/support/tmpfile_posix.c", "src/core/lib/support/tmpfile_posix.c",
"src/core/lib/support/tmpfile_win32.c", "src/core/lib/support/tmpfile_win32.c",
"src/core/lib/support/wrap_memcpy.c", "src/core/lib/support/wrap_memcpy.c",
@ -1140,6 +1142,8 @@ cc_library(
"src/compiler/csharp_generator.h", "src/compiler/csharp_generator.h",
"src/compiler/csharp_generator_helpers.h", "src/compiler/csharp_generator_helpers.h",
"src/compiler/generator_helpers.h", "src/compiler/generator_helpers.h",
"src/compiler/node_generator.h",
"src/compiler/node_generator_helpers.h",
"src/compiler/objective_c_generator.h", "src/compiler/objective_c_generator.h",
"src/compiler/objective_c_generator_helpers.h", "src/compiler/objective_c_generator_helpers.h",
"src/compiler/python_generator.h", "src/compiler/python_generator.h",
@ -1149,6 +1153,7 @@ cc_library(
"src/compiler/ruby_generator_string-inl.h", "src/compiler/ruby_generator_string-inl.h",
"src/compiler/cpp_generator.cc", "src/compiler/cpp_generator.cc",
"src/compiler/csharp_generator.cc", "src/compiler/csharp_generator.cc",
"src/compiler/node_generator.cc",
"src/compiler/objective_c_generator.cc", "src/compiler/objective_c_generator.cc",
"src/compiler/python_generator.cc", "src/compiler/python_generator.cc",
"src/compiler/ruby_generator.cc", "src/compiler/ruby_generator.cc",
@ -1220,6 +1225,7 @@ objc_library(
"src/core/lib/support/stack_lockfree.c", "src/core/lib/support/stack_lockfree.c",
"src/core/lib/support/string.c", "src/core/lib/support/string.c",
"src/core/lib/support/string_posix.c", "src/core/lib/support/string_posix.c",
"src/core/lib/support/string_util_win32.c",
"src/core/lib/support/string_win32.c", "src/core/lib/support/string_win32.c",
"src/core/lib/support/subprocess_posix.c", "src/core/lib/support/subprocess_posix.c",
"src/core/lib/support/subprocess_windows.c", "src/core/lib/support/subprocess_windows.c",
@ -1234,6 +1240,7 @@ objc_library(
"src/core/lib/support/time_precise.c", "src/core/lib/support/time_precise.c",
"src/core/lib/support/time_win32.c", "src/core/lib/support/time_win32.c",
"src/core/lib/support/tls_pthread.c", "src/core/lib/support/tls_pthread.c",
"src/core/lib/support/tmpfile_msys.c",
"src/core/lib/support/tmpfile_posix.c", "src/core/lib/support/tmpfile_posix.c",
"src/core/lib/support/tmpfile_win32.c", "src/core/lib/support/tmpfile_win32.c",
"src/core/lib/support/wrap_memcpy.c", "src/core/lib/support/wrap_memcpy.c",
@ -1672,6 +1679,18 @@ cc_binary(
) )
cc_binary(
name = "grpc_node_plugin",
srcs = [
"src/compiler/node_plugin.cc",
],
deps = [
"//external:protobuf_compiler",
":grpc_plugin_support",
],
)
cc_binary( cc_binary(
name = "grpc_objective_c_plugin", name = "grpc_objective_c_plugin",
srcs = [ srcs = [

@ -779,7 +779,7 @@ endif
.SECONDARY = %.pb.h %.pb.cc .SECONDARY = %.pb.h %.pb.cc
PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin PROTOC_PLUGINS = $(BINDIR)/$(CONFIG)/grpc_cpp_plugin $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(BINDIR)/$(CONFIG)/grpc_node_plugin $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(BINDIR)/$(CONFIG)/grpc_python_plugin $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
ifeq ($(DEP_MISSING),) ifeq ($(DEP_MISSING),)
all: static shared plugins all: static shared plugins
dep_error: dep_error:
@ -881,6 +881,7 @@ alarm_test: $(BINDIR)/$(CONFIG)/alarm_test
algorithm_test: $(BINDIR)/$(CONFIG)/algorithm_test algorithm_test: $(BINDIR)/$(CONFIG)/algorithm_test
alloc_test: $(BINDIR)/$(CONFIG)/alloc_test alloc_test: $(BINDIR)/$(CONFIG)/alloc_test
alpn_test: $(BINDIR)/$(CONFIG)/alpn_test alpn_test: $(BINDIR)/$(CONFIG)/alpn_test
api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer
bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
census_context_test: $(BINDIR)/$(CONFIG)/census_context_test census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
@ -1009,9 +1010,11 @@ cxx_time_test: $(BINDIR)/$(CONFIG)/cxx_time_test
end2end_test: $(BINDIR)/$(CONFIG)/end2end_test end2end_test: $(BINDIR)/$(CONFIG)/end2end_test
generic_async_streaming_ping_pong_test: $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test generic_async_streaming_ping_pong_test: $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test
generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test
golden_file_test: $(BINDIR)/$(CONFIG)/golden_file_test
grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli
grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin grpc_cpp_plugin: $(BINDIR)/$(CONFIG)/grpc_cpp_plugin
grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin grpc_csharp_plugin: $(BINDIR)/$(CONFIG)/grpc_csharp_plugin
grpc_node_plugin: $(BINDIR)/$(CONFIG)/grpc_node_plugin
grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin
grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin
grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
@ -1119,6 +1122,7 @@ h2_sockpair_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_nosec_test
h2_sockpair+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test h2_sockpair+trace_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test
h2_sockpair_1byte_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test h2_sockpair_1byte_nosec_test: $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test
h2_uds_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_nosec_test h2_uds_nosec_test: $(BINDIR)/$(CONFIG)/h2_uds_nosec_test
api_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry
client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry
hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry
http_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry http_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry
@ -1347,6 +1351,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test \ $(BINDIR)/$(CONFIG)/h2_sockpair+trace_nosec_test \
$(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test \ $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test \
$(BINDIR)/$(CONFIG)/h2_uds_nosec_test \ $(BINDIR)/$(CONFIG)/h2_uds_nosec_test \
$(BINDIR)/$(CONFIG)/api_fuzzer_one_entry \
$(BINDIR)/$(CONFIG)/client_fuzzer_one_entry \ $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry \
$(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry \ $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry \
$(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry \ $(BINDIR)/$(CONFIG)/http_fuzzer_test_one_entry \
@ -1377,6 +1382,7 @@ buildtests_cxx: buildtests_zookeeper privatelibs_cxx \
$(BINDIR)/$(CONFIG)/end2end_test \ $(BINDIR)/$(CONFIG)/end2end_test \
$(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test \ $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test \
$(BINDIR)/$(CONFIG)/generic_end2end_test \ $(BINDIR)/$(CONFIG)/generic_end2end_test \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_cli \ $(BINDIR)/$(CONFIG)/grpc_cli \
$(BINDIR)/$(CONFIG)/grpclb_api_test \ $(BINDIR)/$(CONFIG)/grpclb_api_test \
$(BINDIR)/$(CONFIG)/hybrid_end2end_test \ $(BINDIR)/$(CONFIG)/hybrid_end2end_test \
@ -1708,6 +1714,8 @@ test_cxx: test_zookeeper buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test || ( echo test generic_async_streaming_ping_pong_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/generic_async_streaming_ping_pong_test || ( echo test generic_async_streaming_ping_pong_test failed ; exit 1 )
$(E) "[RUN] Testing generic_end2end_test" $(E) "[RUN] Testing generic_end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing golden_file_test"
$(Q) $(BINDIR)/$(CONFIG)/golden_file_test || ( echo test golden_file_test failed ; exit 1 )
$(E) "[RUN] Testing grpclb_api_test" $(E) "[RUN] Testing grpclb_api_test"
$(Q) $(BINDIR)/$(CONFIG)/grpclb_api_test || ( echo test grpclb_api_test failed ; exit 1 ) $(Q) $(BINDIR)/$(CONFIG)/grpclb_api_test || ( echo test grpclb_api_test failed ; exit 1 )
$(E) "[RUN] Testing hybrid_end2end_test" $(E) "[RUN] Testing hybrid_end2end_test"
@ -1876,6 +1884,21 @@ $(GENDIR)/src/proto/grpc/lb/v0/load_balancer.grpc.pb.cc: src/proto/grpc/lb/v0/lo
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $< $(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif endif
ifeq ($(NO_PROTOC),true)
$(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc: protoc_dep_error
$(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: protoc_dep_error
else
$(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc: src/proto/grpc/testing/compiler_test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[PROTOC] Generating protobuf CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --cpp_out=$(GENDIR) $<
$(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: src/proto/grpc/testing/compiler_test.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS)
$(E) "[GRPC] Generating gRPC's protobuf service CC file from $<"
$(Q) mkdir -p `dirname $@`
$(Q) $(PROTOC) --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(BINDIR)/$(CONFIG)/grpc_cpp_plugin $<
endif
ifeq ($(NO_PROTOC),true) ifeq ($(NO_PROTOC),true)
$(GENDIR)/src/proto/grpc/testing/control.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/control.pb.cc: protoc_dep_error
$(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc: protoc_dep_error $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc: protoc_dep_error
@ -2242,6 +2265,8 @@ else
$(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) -d $(prefix)/bin
$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(prefix)/bin/grpc_csharp_plugin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_csharp_plugin $(prefix)/bin/grpc_csharp_plugin
$(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) -d $(prefix)/bin
$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_node_plugin $(prefix)/bin/grpc_node_plugin
$(Q) $(INSTALL) -d $(prefix)/bin
$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(prefix)/bin/grpc_objective_c_plugin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin $(prefix)/bin/grpc_objective_c_plugin
$(Q) $(INSTALL) -d $(prefix)/bin $(Q) $(INSTALL) -d $(prefix)/bin
$(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin $(Q) $(INSTALL) $(BINDIR)/$(CONFIG)/grpc_python_plugin $(prefix)/bin/grpc_python_plugin
@ -2325,6 +2350,7 @@ LIBGPR_SRC = \
src/core/lib/support/stack_lockfree.c \ src/core/lib/support/stack_lockfree.c \
src/core/lib/support/string.c \ src/core/lib/support/string.c \
src/core/lib/support/string_posix.c \ src/core/lib/support/string_posix.c \
src/core/lib/support/string_util_win32.c \
src/core/lib/support/string_win32.c \ src/core/lib/support/string_win32.c \
src/core/lib/support/subprocess_posix.c \ src/core/lib/support/subprocess_posix.c \
src/core/lib/support/subprocess_windows.c \ src/core/lib/support/subprocess_windows.c \
@ -2339,6 +2365,7 @@ LIBGPR_SRC = \
src/core/lib/support/time_precise.c \ src/core/lib/support/time_precise.c \
src/core/lib/support/time_win32.c \ src/core/lib/support/time_win32.c \
src/core/lib/support/tls_pthread.c \ src/core/lib/support/tls_pthread.c \
src/core/lib/support/tmpfile_msys.c \
src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_posix.c \
src/core/lib/support/tmpfile_win32.c \ src/core/lib/support/tmpfile_win32.c \
src/core/lib/support/wrap_memcpy.c \ src/core/lib/support/wrap_memcpy.c \
@ -2712,6 +2739,7 @@ LIBGRPC_TEST_UTIL_SRC = \
test/core/util/memory_counters.c \ test/core/util/memory_counters.c \
test/core/util/mock_endpoint.c \ test/core/util/mock_endpoint.c \
test/core/util/parse_hexstring.c \ test/core/util/parse_hexstring.c \
test/core/util/passthru_endpoint.c \
test/core/util/port_posix.c \ test/core/util/port_posix.c \
test/core/util/port_server_client.c \ test/core/util/port_server_client.c \
test/core/util/port_windows.c \ test/core/util/port_windows.c \
@ -2761,6 +2789,7 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
test/core/util/memory_counters.c \ test/core/util/memory_counters.c \
test/core/util/mock_endpoint.c \ test/core/util/mock_endpoint.c \
test/core/util/parse_hexstring.c \ test/core/util/parse_hexstring.c \
test/core/util/passthru_endpoint.c \
test/core/util/port_posix.c \ test/core/util/port_posix.c \
test/core/util/port_server_client.c \ test/core/util/port_server_client.c \
test/core/util/port_windows.c \ test/core/util/port_windows.c \
@ -3608,6 +3637,7 @@ endif
LIBGRPC_PLUGIN_SUPPORT_SRC = \ LIBGRPC_PLUGIN_SUPPORT_SRC = \
src/compiler/cpp_generator.cc \ src/compiler/cpp_generator.cc \
src/compiler/csharp_generator.cc \ src/compiler/csharp_generator.cc \
src/compiler/node_generator.cc \
src/compiler/objective_c_generator.cc \ src/compiler/objective_c_generator.cc \
src/compiler/python_generator.cc \ src/compiler/python_generator.cc \
src/compiler/ruby_generator.cc \ src/compiler/ruby_generator.cc \
@ -6054,6 +6084,38 @@ endif
endif endif
API_FUZZER_SRC = \
test/core/end2end/fuzzers/api_fuzzer.c \
API_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(API_FUZZER_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/api_fuzzer: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/api_fuzzer: $(API_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(API_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/api_fuzzer
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/api_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_api_fuzzer: $(API_FUZZER_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(API_FUZZER_OBJS:.o=.dep)
endif
endif
BIN_ENCODER_TEST_SRC = \ BIN_ENCODER_TEST_SRC = \
test/core/transport/chttp2/bin_encoder_test.c \ test/core/transport/chttp2/bin_encoder_test.c \
@ -10405,6 +10467,53 @@ endif
endif endif
GOLDEN_FILE_TEST_SRC = \
$(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc \
test/cpp/codegen/golden_file_test.cc \
GOLDEN_FILE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GOLDEN_FILE_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/golden_file_test: openssl_dep_error
else
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/golden_file_test: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/golden_file_test: $(PROTOBUF_DEP) $(GOLDEN_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LDXX) $(LDFLAGS) $(GOLDEN_FILE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/golden_file_test
endif
endif
$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/compiler_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/cpp/codegen/golden_file_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_golden_file_test: $(GOLDEN_FILE_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(GOLDEN_FILE_TEST_OBJS:.o=.dep)
endif
endif
$(OBJDIR)/$(CONFIG)/test/cpp/codegen/golden_file_test.o: $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc
GRPC_CLI_SRC = \ GRPC_CLI_SRC = \
test/cpp/util/grpc_cli.cc \ test/cpp/util/grpc_cli.cc \
@ -10510,6 +10619,37 @@ ifneq ($(NO_DEPS),true)
endif endif
GRPC_NODE_PLUGIN_SRC = \
src/compiler/node_plugin.cc \
GRPC_NODE_PLUGIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_NODE_PLUGIN_SRC))))
ifeq ($(NO_PROTOBUF),true)
# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
$(BINDIR)/$(CONFIG)/grpc_node_plugin: protobuf_dep_error
else
$(BINDIR)/$(CONFIG)/grpc_node_plugin: $(PROTOBUF_DEP) $(GRPC_NODE_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a
$(E) "[HOSTLD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(HOST_LDXX) $(HOST_LDFLAGS) $(GRPC_NODE_PLUGIN_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a $(HOST_LDLIBSXX) $(HOST_LDLIBS_PROTOC) $(HOST_LDLIBS) $(HOST_LDLIBS_PROTOC) -o $(BINDIR)/$(CONFIG)/grpc_node_plugin
endif
$(OBJDIR)/$(CONFIG)/src/compiler/node_plugin.o: $(LIBDIR)/$(CONFIG)/libgrpc_plugin_support.a
deps_grpc_node_plugin: $(GRPC_NODE_PLUGIN_OBJS:.o=.dep)
ifneq ($(NO_DEPS),true)
-include $(GRPC_NODE_PLUGIN_OBJS:.o=.dep)
endif
GRPC_OBJECTIVE_C_PLUGIN_SRC = \ GRPC_OBJECTIVE_C_PLUGIN_SRC = \
src/compiler/objective_c_plugin.cc \ src/compiler/objective_c_plugin.cc \
@ -13850,6 +13990,41 @@ ifneq ($(NO_DEPS),true)
endif endif
API_FUZZER_ONE_ENTRY_SRC = \
test/core/end2end/fuzzers/api_fuzzer.c \
test/core/util/one_corpus_entry_fuzzer.c \
API_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(API_FUZZER_ONE_ENTRY_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/api_fuzzer_one_entry: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/api_fuzzer_one_entry: $(API_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(API_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry
endif
$(OBJDIR)/$(CONFIG)/test/core/end2end/fuzzers/api_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_api_fuzzer_one_entry: $(API_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(API_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
endif
endif
CLIENT_FUZZER_ONE_ENTRY_SRC = \ CLIENT_FUZZER_ONE_ENTRY_SRC = \
test/core/end2end/fuzzers/client_fuzzer.c \ test/core/end2end/fuzzers/client_fuzzer.c \
test/core/util/one_corpus_entry_fuzzer.c \ test/core/util/one_corpus_entry_fuzzer.c \

@ -522,6 +522,7 @@
'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/stack_lockfree.c',
'src/core/lib/support/string.c', 'src/core/lib/support/string.c',
'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_posix.c',
'src/core/lib/support/string_util_win32.c',
'src/core/lib/support/string_win32.c', 'src/core/lib/support/string_win32.c',
'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_posix.c',
'src/core/lib/support/subprocess_windows.c', 'src/core/lib/support/subprocess_windows.c',
@ -536,6 +537,7 @@
'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_precise.c',
'src/core/lib/support/time_win32.c', 'src/core/lib/support/time_win32.c',
'src/core/lib/support/tls_pthread.c', 'src/core/lib/support/tls_pthread.c',
'src/core/lib/support/tmpfile_msys.c',
'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_posix.c',
'src/core/lib/support/tmpfile_win32.c', 'src/core/lib/support/tmpfile_win32.c',
'src/core/lib/support/wrap_memcpy.c', 'src/core/lib/support/wrap_memcpy.c',

@ -103,6 +103,7 @@ filegroups:
- src/core/lib/support/stack_lockfree.c - src/core/lib/support/stack_lockfree.c
- src/core/lib/support/string.c - src/core/lib/support/string.c
- src/core/lib/support/string_posix.c - src/core/lib/support/string_posix.c
- src/core/lib/support/string_util_win32.c
- src/core/lib/support/string_win32.c - src/core/lib/support/string_win32.c
- src/core/lib/support/subprocess_posix.c - src/core/lib/support/subprocess_posix.c
- src/core/lib/support/subprocess_windows.c - src/core/lib/support/subprocess_windows.c
@ -117,6 +118,7 @@ filegroups:
- src/core/lib/support/time_precise.c - src/core/lib/support/time_precise.c
- src/core/lib/support/time_win32.c - src/core/lib/support/time_win32.c
- src/core/lib/support/tls_pthread.c - src/core/lib/support/tls_pthread.c
- src/core/lib/support/tmpfile_msys.c
- src/core/lib/support/tmpfile_posix.c - src/core/lib/support/tmpfile_posix.c
- src/core/lib/support/tmpfile_win32.c - src/core/lib/support/tmpfile_win32.c
- src/core/lib/support/wrap_memcpy.c - src/core/lib/support/wrap_memcpy.c
@ -451,6 +453,7 @@ filegroups:
- test/core/util/memory_counters.h - test/core/util/memory_counters.h
- test/core/util/mock_endpoint.h - test/core/util/mock_endpoint.h
- test/core/util/parse_hexstring.h - test/core/util/parse_hexstring.h
- test/core/util/passthru_endpoint.h
- test/core/util/port.h - test/core/util/port.h
- test/core/util/port_server_client.h - test/core/util/port_server_client.h
- test/core/util/slice_splitter.h - test/core/util/slice_splitter.h
@ -462,6 +465,7 @@ filegroups:
- test/core/util/memory_counters.c - test/core/util/memory_counters.c
- test/core/util/mock_endpoint.c - test/core/util/mock_endpoint.c
- test/core/util/parse_hexstring.c - test/core/util/parse_hexstring.c
- test/core/util/passthru_endpoint.c
- test/core/util/port_posix.c - test/core/util/port_posix.c
- test/core/util/port_server_client.c - test/core/util/port_server_client.c
- test/core/util/port_windows.c - test/core/util/port_windows.c
@ -946,6 +950,8 @@ libs:
- src/compiler/csharp_generator.h - src/compiler/csharp_generator.h
- src/compiler/csharp_generator_helpers.h - src/compiler/csharp_generator_helpers.h
- src/compiler/generator_helpers.h - src/compiler/generator_helpers.h
- src/compiler/node_generator.h
- src/compiler/node_generator_helpers.h
- src/compiler/objective_c_generator.h - src/compiler/objective_c_generator.h
- src/compiler/objective_c_generator_helpers.h - src/compiler/objective_c_generator_helpers.h
- src/compiler/python_generator.h - src/compiler/python_generator.h
@ -956,6 +962,7 @@ libs:
src: src:
- src/compiler/cpp_generator.cc - src/compiler/cpp_generator.cc
- src/compiler/csharp_generator.cc - src/compiler/csharp_generator.cc
- src/compiler/node_generator.cc
- src/compiler/objective_c_generator.cc - src/compiler/objective_c_generator.cc
- src/compiler/python_generator.cc - src/compiler/python_generator.cc
- src/compiler/ruby_generator.cc - src/compiler/ruby_generator.cc
@ -1126,6 +1133,20 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: api_fuzzer
build: fuzzer
language: c
src:
- test/core/end2end/fuzzers/api_fuzzer.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
corpus_dirs:
- test/core/end2end/fuzzers/api_fuzzer_corpus
dict: test/core/end2end/fuzzers/api_fuzzer.dictionary
maxlen: 2048
- name: bin_encoder_test - name: bin_encoder_test
build: test build: test
language: c language: c
@ -2542,6 +2563,17 @@ targets:
- grpc - grpc
- gpr_test_util - gpr_test_util
- gpr - gpr
- name: golden_file_test
gtest: true
build: test
language: c++
src:
- src/proto/grpc/testing/compiler_test.proto
- test/cpp/codegen/golden_file_test.cc
deps:
- grpc++
- grpc
- gpr
- name: grpc_cli - name: grpc_cli
build: test build: test
run: false run: false
@ -2576,6 +2608,15 @@ targets:
secure: false secure: false
vs_config_type: Application vs_config_type: Application
vs_project_guid: '{3C813052-A49A-4662-B90A-1ADBEC7EE453}' vs_project_guid: '{3C813052-A49A-4662-B90A-1ADBEC7EE453}'
- name: grpc_node_plugin
build: protoc
language: c++
src:
- src/compiler/node_plugin.cc
deps:
- grpc_plugin_support
secure: false
vs_config_type: Application
- name: grpc_objective_c_plugin - name: grpc_objective_c_plugin
build: protoc build: protoc
language: c++ language: c++

@ -63,6 +63,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/support/stack_lockfree.c \ src/core/lib/support/stack_lockfree.c \
src/core/lib/support/string.c \ src/core/lib/support/string.c \
src/core/lib/support/string_posix.c \ src/core/lib/support/string_posix.c \
src/core/lib/support/string_util_win32.c \
src/core/lib/support/string_win32.c \ src/core/lib/support/string_win32.c \
src/core/lib/support/subprocess_posix.c \ src/core/lib/support/subprocess_posix.c \
src/core/lib/support/subprocess_windows.c \ src/core/lib/support/subprocess_windows.c \
@ -77,6 +78,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/support/time_precise.c \ src/core/lib/support/time_precise.c \
src/core/lib/support/time_win32.c \ src/core/lib/support/time_win32.c \
src/core/lib/support/tls_pthread.c \ src/core/lib/support/tls_pthread.c \
src/core/lib/support/tmpfile_msys.c \
src/core/lib/support/tmpfile_posix.c \ src/core/lib/support/tmpfile_posix.c \
src/core/lib/support/tmpfile_win32.c \ src/core/lib/support/tmpfile_win32.c \
src/core/lib/support/wrap_memcpy.c \ src/core/lib/support/wrap_memcpy.c \

@ -32,7 +32,7 @@
CXX = g++ CXX = g++
CPPFLAGS += -I/usr/local/include -pthread CPPFLAGS += -I/usr/local/include -pthread
CXXFLAGS += -std=c++11 CXXFLAGS += -std=c++11
LDFLAGS += -L/usr/local/lib -lgrpc++_unsecure -lgrpc -lprotobuf -lpthread -ldl LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` -lprotobuf -lpthread -ldl
PROTOC = protoc PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)` GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`

@ -32,7 +32,7 @@
CXX = g++ CXX = g++
CPPFLAGS += -I/usr/local/include -pthread CPPFLAGS += -I/usr/local/include -pthread
CXXFLAGS += -std=c++11 CXXFLAGS += -std=c++11
LDFLAGS += -L/usr/local/lib -lgrpc++_unsecure -lgrpc -lprotobuf -lpthread -ldl LDFLAGS += -L/usr/local/lib `pkg-config --libs grpc++` -lprotobuf -lpthread -ldl
PROTOC = protoc PROTOC = protoc
GRPC_CPP_PLUGIN = grpc_cpp_plugin GRPC_CPP_PLUGIN = grpc_cpp_plugin
GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)` GRPC_CPP_PLUGIN_PATH ?= `which $(GRPC_CPP_PLUGIN)`

@ -31,13 +31,13 @@
* *
*/ */
var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
var grpc = require('grpc'); var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
var hello_messages = require('./helloworld_pb');
var hello_service = require('./helloworld_grpc_pb');
function main() { function main() {
var client = new hello_proto.Greeter('localhost:50051', var client = new hello_service.GreeterClient('localhost:50051',
grpc.credentials.createInsecure()); grpc.credentials.createInsecure());
var user; var user;
if (process.argv.length >= 3) { if (process.argv.length >= 3) {
@ -45,8 +45,16 @@ function main() {
} else { } else {
user = 'world'; user = 'world';
} }
client.sayHello({name: user}, function(err, response) {
console.log('Greeting:', response.message); var request = new hello_messages.HelloRequest();
request.setName(user);
client.sayHello(request, function(err, response) {
if (err) {
debugger;
throw err;
}
console.log('Greeting:', response.getMessage());
}); });
} }

@ -31,16 +31,18 @@
* *
*/ */
var PROTO_PATH = __dirname + '/../protos/helloworld.proto';
var grpc = require('grpc'); var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
var hello_messages = require('./helloworld_pb');
var hello_service = require('./helloworld_grpc_pb');
/** /**
* Implements the SayHello RPC method. * Implements the SayHello RPC method.
*/ */
function sayHello(call, callback) { function sayHello(call, callback) {
callback(null, {message: 'Hello ' + call.request.name}); var reply = new hello_messages.HelloReply();
reply.setMessage("Hello " + call.request.getName());
callback(null, reply);
} }
/** /**
@ -49,7 +51,7 @@ function sayHello(call, callback) {
*/ */
function main() { function main() {
var server = new grpc.Server(); var server = new grpc.Server();
server.addProtoService(hello_proto.Greeter.service, {sayHello: sayHello}); server.addService(hello_service.GreeterService, {sayHello: sayHello});
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
server.start(); server.start();
} }

@ -0,0 +1,39 @@
// GENERATED CODE -- DO NOT EDIT!
var grpc = require('grpc');
var helloworld_pb = require('./helloworld_pb.js');
function serialize_HelloReply(arg) {
if (!(arg instanceof helloworld_pb.HelloReply)) {
throw new Error('Expected argument of type HelloReply');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloReply(buffer_arg) {
return helloworld_pb.HelloReply.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_HelloRequest(arg) {
if (!(arg instanceof helloworld_pb.HelloRequest)) {
throw new Error('Expected argument of type HelloRequest');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_HelloRequest(buffer_arg) {
return helloworld_pb.HelloRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
var GreeterService = exports.GreeterService = {
sayHello: {
path: '/helloworld.Greeter/SayHello',
requestStream: false,
responseStream: false,
requestType: helloworld_pb.HelloRequest,
responseType: helloworld_pb.HelloReply,
requestSerialize: serialize_HelloRequest,
requestDeserialize: deserialize_HelloRequest,
responseSerialize: serialize_HelloReply,
responseDeserialize: deserialize_HelloReply,
},
};
exports.GreeterClient = grpc.makeGenericClientConstructor(GreeterService);

@ -0,0 +1,332 @@
/**
* @fileoverview
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();
goog.exportSymbol('proto.helloworld.HelloReply', null, global);
goog.exportSymbol('proto.helloworld.HelloRequest', null, global);
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.helloworld.HelloRequest = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.helloworld.HelloRequest, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.helloworld.HelloRequest.displayName = 'proto.helloworld.HelloRequest';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.helloworld.HelloRequest.prototype.toObject = function(opt_includeInstance) {
return proto.helloworld.HelloRequest.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.helloworld.HelloRequest} msg The msg instance to transform.
* @return {!Object}
*/
proto.helloworld.HelloRequest.toObject = function(includeInstance, msg) {
var f, obj = {
name: msg.getName()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.helloworld.HelloRequest}
*/
proto.helloworld.HelloRequest.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.helloworld.HelloRequest;
return proto.helloworld.HelloRequest.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.helloworld.HelloRequest} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.helloworld.HelloRequest}
*/
proto.helloworld.HelloRequest.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setName(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.helloworld.HelloRequest} message
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloRequest.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.helloworld.HelloRequest.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloRequest.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getName();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.helloworld.HelloRequest} The clone.
*/
proto.helloworld.HelloRequest.prototype.cloneMessage = function() {
return /** @type {!proto.helloworld.HelloRequest} */ (jspb.Message.cloneMessage(this));
};
/**
* optional string name = 1;
* @return {string}
*/
proto.helloworld.HelloRequest.prototype.getName = function() {
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
};
/** @param {string} value */
proto.helloworld.HelloRequest.prototype.setName = function(value) {
jspb.Message.setField(this, 1, value);
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.helloworld.HelloReply = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.helloworld.HelloReply, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.helloworld.HelloReply.displayName = 'proto.helloworld.HelloReply';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.helloworld.HelloReply.prototype.toObject = function(opt_includeInstance) {
return proto.helloworld.HelloReply.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.helloworld.HelloReply} msg The msg instance to transform.
* @return {!Object}
*/
proto.helloworld.HelloReply.toObject = function(includeInstance, msg) {
var f, obj = {
message: msg.getMessage()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.helloworld.HelloReply}
*/
proto.helloworld.HelloReply.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.helloworld.HelloReply;
return proto.helloworld.HelloReply.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.helloworld.HelloReply} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.helloworld.HelloReply}
*/
proto.helloworld.HelloReply.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {string} */ (reader.readString());
msg.setMessage(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.helloworld.HelloReply} message
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloReply.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.helloworld.HelloReply.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.helloworld.HelloReply.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getMessage();
if (f.length > 0) {
writer.writeString(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.helloworld.HelloReply} The clone.
*/
proto.helloworld.HelloReply.prototype.cloneMessage = function() {
return /** @type {!proto.helloworld.HelloReply} */ (jspb.Message.cloneMessage(this));
};
/**
* optional string message = 1;
* @return {string}
*/
proto.helloworld.HelloReply.prototype.getMessage = function() {
return /** @type {string} */ (jspb.Message.getFieldProto3(this, 1, ""));
};
/** @param {string} value */
proto.helloworld.HelloReply.prototype.setMessage = function(value) {
jspb.Message.setField(this, 1, value);
};
goog.object.extend(exports, proto.helloworld);

@ -4,6 +4,7 @@
"dependencies": { "dependencies": {
"async": "^1.5.2", "async": "^1.5.2",
"grpc": "0.13.0", "grpc": "0.13.0",
"google-protobuf": "*",
"lodash": "^4.6.1", "lodash": "^4.6.1",
"minimist": "^1.2.0" "minimist": "^1.2.0"
} }

@ -144,6 +144,7 @@ Pod::Spec.new do |s|
'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/stack_lockfree.c',
'src/core/lib/support/string.c', 'src/core/lib/support/string.c',
'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_posix.c',
'src/core/lib/support/string_util_win32.c',
'src/core/lib/support/string_win32.c', 'src/core/lib/support/string_win32.c',
'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_posix.c',
'src/core/lib/support/subprocess_windows.c', 'src/core/lib/support/subprocess_windows.c',
@ -158,6 +159,7 @@ Pod::Spec.new do |s|
'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_precise.c',
'src/core/lib/support/time_win32.c', 'src/core/lib/support/time_win32.c',
'src/core/lib/support/tls_pthread.c', 'src/core/lib/support/tls_pthread.c',
'src/core/lib/support/tmpfile_msys.c',
'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_posix.c',
'src/core/lib/support/tmpfile_win32.c', 'src/core/lib/support/tmpfile_win32.c',
'src/core/lib/support/wrap_memcpy.c', 'src/core/lib/support/wrap_memcpy.c',

@ -24,10 +24,6 @@ Gem::Specification.new do |s|
s.files += Dir.glob('include/grpc/**/*') s.files += Dir.glob('include/grpc/**/*')
s.test_files = Dir.glob('src/ruby/spec/**/*') s.test_files = Dir.glob('src/ruby/spec/**/*')
s.bindir = 'src/ruby/bin' s.bindir = 'src/ruby/bin'
%w(math noproto).each do |b|
s.executables += ["#{b}_client.rb", "#{b}_server.rb"]
end
s.executables += %w(grpc_ruby_interop_client grpc_ruby_interop_server)
s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb ) s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
s.platform = Gem::Platform::RUBY s.platform = Gem::Platform::RUBY
@ -128,6 +124,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/stack_lockfree.c ) s.files += %w( src/core/lib/support/stack_lockfree.c )
s.files += %w( src/core/lib/support/string.c ) s.files += %w( src/core/lib/support/string.c )
s.files += %w( src/core/lib/support/string_posix.c ) s.files += %w( src/core/lib/support/string_posix.c )
s.files += %w( src/core/lib/support/string_util_win32.c )
s.files += %w( src/core/lib/support/string_win32.c ) s.files += %w( src/core/lib/support/string_win32.c )
s.files += %w( src/core/lib/support/subprocess_posix.c ) s.files += %w( src/core/lib/support/subprocess_posix.c )
s.files += %w( src/core/lib/support/subprocess_windows.c ) s.files += %w( src/core/lib/support/subprocess_windows.c )
@ -142,6 +139,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/support/time_precise.c ) s.files += %w( src/core/lib/support/time_precise.c )
s.files += %w( src/core/lib/support/time_win32.c ) s.files += %w( src/core/lib/support/time_win32.c )
s.files += %w( src/core/lib/support/tls_pthread.c ) s.files += %w( src/core/lib/support/tls_pthread.c )
s.files += %w( src/core/lib/support/tmpfile_msys.c )
s.files += %w( src/core/lib/support/tmpfile_posix.c ) s.files += %w( src/core/lib/support/tmpfile_posix.c )
s.files += %w( src/core/lib/support/tmpfile_win32.c ) s.files += %w( src/core/lib/support/tmpfile_win32.c )
s.files += %w( src/core/lib/support/wrap_memcpy.c ) s.files += %w( src/core/lib/support/wrap_memcpy.c )

@ -82,28 +82,31 @@
things. */ things. */
#if !defined(GPR_NO_AUTODETECT_PLATFORM) #if !defined(GPR_NO_AUTODETECT_PLATFORM)
#if defined(_WIN64) || defined(WIN64) || defined(_WIN32) || defined(WIN32)
#if defined(_WIN64) || defined(WIN64) #if defined(_WIN64) || defined(WIN64)
#define GPR_PLATFORM_STRING "windows"
#define GPR_WIN32 1
#define GPR_ARCH_64 1 #define GPR_ARCH_64 1
#define GPR_GETPID_IN_PROCESS_H 1
#define GPR_WINSOCK_SOCKET 1
#define GPR_WINDOWS_SUBPROCESS 1
#ifdef __GNUC__
#define GPR_GCC_ATOMIC 1
#define GPR_GCC_TLS 1
#else #else
#define GPR_WIN32_ATOMIC 1 #define GPR_ARCH_32 1
#define GPR_MSVC_TLS 1
#endif #endif
#define GPR_WINDOWS_CRASH_HANDLER 1
#elif defined(_WIN32) || defined(WIN32)
#define GPR_PLATFORM_STRING "windows" #define GPR_PLATFORM_STRING "windows"
#define GPR_ARCH_32 1
#define GPR_WIN32 1 #define GPR_WIN32 1
#define GPR_GETPID_IN_PROCESS_H 1
#define GPR_WINSOCK_SOCKET 1 #define GPR_WINSOCK_SOCKET 1
#define GPR_WINDOWS_SUBPROCESS 1 #define GPR_WINDOWS_SUBPROCESS 1
#define GPR_WIN32_ENV
#ifdef __MSYS__
#define GPR_GETPID_IN_UNISTD_H 1
#define GPR_MSYS_TMPFILE
#define GPR_POSIX_LOG
#define GPR_POSIX_STRING
#define GPR_POSIX_TIME
#else
#define GPR_GETPID_IN_PROCESS_H 1
#define GPR_WIN32_TMPFILE
#define GPR_WIN32_LOG
#define GPR_WINDOWS_CRASH_HANDLER 1
#define GPR_WIN32_STRING
#define GPR_WIN32_TIME
#endif
#ifdef __GNUC__ #ifdef __GNUC__
#define GPR_GCC_ATOMIC 1 #define GPR_GCC_ATOMIC 1
#define GPR_GCC_TLS 1 #define GPR_GCC_TLS 1
@ -111,7 +114,6 @@
#define GPR_WIN32_ATOMIC 1 #define GPR_WIN32_ATOMIC 1
#define GPR_MSVC_TLS 1 #define GPR_MSVC_TLS 1
#endif #endif
#define GPR_WINDOWS_CRASH_HANDLER 1
#elif defined(ANDROID) || defined(__ANDROID__) #elif defined(ANDROID) || defined(__ANDROID__)
#define GPR_PLATFORM_STRING "android" #define GPR_PLATFORM_STRING "android"
#define GPR_ANDROID 1 #define GPR_ANDROID 1
@ -127,6 +129,8 @@
#define GPR_POSIX_SOCKETUTILS 1 #define GPR_POSIX_SOCKETUTILS 1
#define GPR_POSIX_ENV 1 #define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1 #define GPR_POSIX_FILE 1
#define GPR_POSIX_TMPFILE 1
#define GPR_POSIX_LOG
#define GPR_POSIX_STRING 1 #define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1 #define GPR_POSIX_SYNC 1
@ -153,6 +157,7 @@
#define GPR_GCC_ATOMIC 1 #define GPR_GCC_ATOMIC 1
#define GPR_GCC_TLS 1 #define GPR_GCC_TLS 1
#define GPR_LINUX 1 #define GPR_LINUX 1
#define GPR_LINUX_LOG
#define GPR_LINUX_MULTIPOLL_WITH_EPOLL 1 #define GPR_LINUX_MULTIPOLL_WITH_EPOLL 1
#define GPR_POSIX_WAKEUP_FD 1 #define GPR_POSIX_WAKEUP_FD 1
#define GPR_POSIX_SOCKET 1 #define GPR_POSIX_SOCKET 1
@ -176,6 +181,7 @@
#define GPR_POSIX_SOCKETUTILS #define GPR_POSIX_SOCKETUTILS
#endif #endif
#define GPR_POSIX_FILE 1 #define GPR_POSIX_FILE 1
#define GPR_POSIX_TMPFILE 1
#define GPR_POSIX_STRING 1 #define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1 #define GPR_POSIX_SYNC 1
@ -214,6 +220,7 @@
#define GPR_POSIX_SOCKETUTILS 1 #define GPR_POSIX_SOCKETUTILS 1
#define GPR_POSIX_ENV 1 #define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1 #define GPR_POSIX_FILE 1
#define GPR_POSIX_TMPFILE 1
#define GPR_POSIX_STRING 1 #define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1 #define GPR_POSIX_SYNC 1
@ -244,6 +251,7 @@
#define GPR_POSIX_SOCKETUTILS 1 #define GPR_POSIX_SOCKETUTILS 1
#define GPR_POSIX_ENV 1 #define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1 #define GPR_POSIX_FILE 1
#define GPR_POSIX_TMPFILE 1
#define GPR_POSIX_STRING 1 #define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1 #define GPR_POSIX_SYNC 1
@ -281,6 +289,7 @@
#define GPR_POSIX_SOCKETUTILS 1 #define GPR_POSIX_SOCKETUTILS 1
#define GPR_POSIX_ENV 1 #define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1 #define GPR_POSIX_FILE 1
#define GPR_POSIX_TMPFILE 1
#define GPR_POSIX_STRING 1 #define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1 #define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1 #define GPR_POSIX_SYNC 1

@ -19,7 +19,7 @@
"lib": "src/node/src" "lib": "src/node/src"
}, },
"scripts": { "scripts": {
"lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js", "lint": "node ./node_modules/jshint/bin/jshint src/node/src src/node/test src/node/interop src/node/index.js --exclude-path=src/node/.jshintignore",
"test": "./node_modules/.bin/mocha src/node/test && npm run-script lint", "test": "./node_modules/.bin/mocha src/node/test && npm run-script lint",
"gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json", "gen_docs": "./node_modules/.bin/jsdoc -c src/node/jsdoc_conf.json",
"coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test", "coverage": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha src/node/test",
@ -35,6 +35,7 @@
"devDependencies": { "devDependencies": {
"async": "^1.5.0", "async": "^1.5.0",
"google-auth-library": "^0.9.2", "google-auth-library": "^0.9.2",
"google-protobuf": "^3.0.0-alpha.5",
"istanbul": "^0.3.21", "istanbul": "^0.3.21",
"jsdoc": "^3.3.2", "jsdoc": "^3.3.2",
"jshint": "^2.5.0", "jshint": "^2.5.0",
@ -72,5 +73,25 @@
"binding.gyp" "binding.gyp"
], ],
"main": "src/node/index.js", "main": "src/node/index.js",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"jshintConfig" : {
"bitwise": true,
"curly": true,
"eqeqeq": true,
"esnext": true,
"freeze": true,
"immed": true,
"indent": 2,
"latedef": "nofunc",
"maxlen": 80,
"mocha": true,
"newcap": true,
"node": true,
"noarg": true,
"quotmark": "single",
"strict": true,
"trailing": true,
"undef": true,
"unused": "vars"
}
} }

@ -10,7 +10,7 @@
<email>grpc-packages@google.com</email> <email>grpc-packages@google.com</email>
<active>yes</active> <active>yes</active>
</lead> </lead>
<date>2016-03-01</date> <date>2016-04-19</date>
<time>16:06:07</time> <time>16:06:07</time>
<version> <version>
<release>0.14.0</release> <release>0.14.0</release>
@ -22,7 +22,7 @@
</stability> </stability>
<license>BSD</license> <license>BSD</license>
<notes> <notes>
- Increase unit test code coverage #5225 - destroy grpc_byte_buffer after startBatch #6096
</notes> </notes>
<contents> <contents>
<dir baseinstalldir="/" name="/"> <dir baseinstalldir="/" name="/">
@ -131,6 +131,7 @@
<file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/stack_lockfree.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/string.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/string_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_util_win32.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/string_win32.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/string_win32.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/subprocess_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/subprocess_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/subprocess_windows.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/subprocess_windows.c" role="src" />
@ -145,6 +146,7 @@
<file baseinstalldir="/" name="src/core/lib/support/time_precise.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/time_precise.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/time_win32.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/time_win32.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/tls_pthread.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/tls_pthread.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/tmpfile_msys.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/tmpfile_posix.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/tmpfile_posix.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/tmpfile_win32.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/tmpfile_win32.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/support/wrap_memcpy.c" role="src" /> <file baseinstalldir="/" name="src/core/lib/support/wrap_memcpy.c" role="src" />
@ -998,8 +1000,8 @@ Update to wrap gRPC C Core version 0.10.0
</release> </release>
<release> <release>
<version> <version>
<release>0.14.0</release> <release>0.8.1</release>
<api>0.14.0</api> <api>0.8.1</api>
</version> </version>
<stability> <stability>
<release>beta</release> <release>beta</release>
@ -1011,5 +1013,20 @@ Update to wrap gRPC C Core version 0.10.0
- Increase unit test code coverage #5225 - Increase unit test code coverage #5225
</notes> </notes>
</release> </release>
<release>
<version>
<release>0.14.0</release>
<api>0.14.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2016-04-19</date>
<license>BSD</license>
<notes>
- destroy grpc_byte_buffer after startBatch #6096
</notes>
</release>
</changelog> </changelog>
</package> </package>

@ -1,7 +1,8 @@
# GRPC Python setup requirements # GRPC Python setup requirements
coverage>=4.0
cython>=0.23
enum34>=1.0.4 enum34>=1.0.4
futures>=2.2.0 futures>=2.2.0
cython>=0.23 protobuf>=3.0.0a3
coverage>=4.0
six>=1.10 six>=1.10
wheel>=0.29 wheel>=0.29

@ -42,8 +42,10 @@
#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/descriptor.pb.h>
#define GRPC_CUSTOM_DESCRIPTOR ::google::protobuf::Descriptor #define GRPC_CUSTOM_DESCRIPTOR ::google::protobuf::Descriptor
#define GRPC_CUSTOM_FILEDESCRIPTOR ::google::protobuf::FileDescriptor #define GRPC_CUSTOM_FILEDESCRIPTOR ::google::protobuf::FileDescriptor
#define GRPC_CUSTOM_FILEDESCRIPTORPROTO ::google::protobuf::FileDescriptorProto
#define GRPC_CUSTOM_METHODDESCRIPTOR ::google::protobuf::MethodDescriptor #define GRPC_CUSTOM_METHODDESCRIPTOR ::google::protobuf::MethodDescriptor
#define GRPC_CUSTOM_SERVICEDESCRIPTOR ::google::protobuf::ServiceDescriptor #define GRPC_CUSTOM_SERVICEDESCRIPTOR ::google::protobuf::ServiceDescriptor
#define GRPC_CUSTOM_SOURCELOCATION ::google::protobuf::SourceLocation
#endif #endif
#ifndef GRPC_CUSTOM_CODEGENERATOR #ifndef GRPC_CUSTOM_CODEGENERATOR
@ -68,12 +70,19 @@
#define GRPC_CUSTOM_PLUGINMAIN ::google::protobuf::compiler::PluginMain #define GRPC_CUSTOM_PLUGINMAIN ::google::protobuf::compiler::PluginMain
#endif #endif
#ifndef GRPC_CUSTOM_PARSEGENERATORPARAMETER
#include <google/protobuf/compiler/code_generator.h>
#define GRPC_CUSTOM_PARSEGENERATORPARAMETER ::google::protobuf::compiler::ParseGeneratorParameter
#endif
namespace grpc { namespace grpc {
namespace protobuf { namespace protobuf {
typedef GRPC_CUSTOM_DESCRIPTOR Descriptor; typedef GRPC_CUSTOM_DESCRIPTOR Descriptor;
typedef GRPC_CUSTOM_FILEDESCRIPTOR FileDescriptor; typedef GRPC_CUSTOM_FILEDESCRIPTOR FileDescriptor;
typedef GRPC_CUSTOM_FILEDESCRIPTORPROTO FileDescriptorProto;
typedef GRPC_CUSTOM_METHODDESCRIPTOR MethodDescriptor; typedef GRPC_CUSTOM_METHODDESCRIPTOR MethodDescriptor;
typedef GRPC_CUSTOM_SERVICEDESCRIPTOR ServiceDescriptor; typedef GRPC_CUSTOM_SERVICEDESCRIPTOR ServiceDescriptor;
typedef GRPC_CUSTOM_SOURCELOCATION SourceLocation;
namespace compiler { namespace compiler {
typedef GRPC_CUSTOM_CODEGENERATOR CodeGenerator; typedef GRPC_CUSTOM_CODEGENERATOR CodeGenerator;
typedef GRPC_CUSTOM_GENERATORCONTEXT GeneratorContext; typedef GRPC_CUSTOM_GENERATORCONTEXT GeneratorContext;
@ -81,6 +90,11 @@ static inline int PluginMain(int argc, char* argv[],
const CodeGenerator* generator) { const CodeGenerator* generator) {
return GRPC_CUSTOM_PLUGINMAIN(argc, argv, generator); return GRPC_CUSTOM_PLUGINMAIN(argc, argv, generator);
} }
static inline void ParseGeneratorParameter(const string& parameter,
std::vector<std::pair<string, string> >* options) {
GRPC_CUSTOM_PARSEGENERATORPARAMETER(parameter, options);
}
} // namespace compiler } // namespace compiler
namespace io { namespace io {
typedef GRPC_CUSTOM_PRINTER Printer; typedef GRPC_CUSTOM_PRINTER Printer;

@ -86,7 +86,7 @@ void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, c
} }
} }
grpc::string GetHeaderPrologue(File *file, const Parameters &params) { grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
grpc::string output; grpc::string output;
{ {
// Scope the output stream so it closes and finalizes output to the string. // Scope the output stream so it closes and finalizes output to the string.
@ -96,15 +96,21 @@ grpc::string GetHeaderPrologue(File *file, const Parameters &params) {
vars["filename"] = file->filename(); vars["filename"] = file->filename();
vars["filename_identifier"] = FilenameIdentifier(file->filename()); vars["filename_identifier"] = FilenameIdentifier(file->filename());
vars["filename_base"] = file->filename_without_ext(); vars["filename_base"] = file->filename_without_ext();
vars["message_header_ext"] = file->message_header_ext();
printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n"); printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
printer->Print(vars, printer->Print(vars,
"// If you make any local change, they will be lost.\n"); "// If you make any local change, they will be lost.\n");
printer->Print(vars, "// source: $filename$\n"); printer->Print(vars, "// source: $filename$\n");
grpc::string leading_comments = file->GetLeadingComments();
if (!leading_comments.empty()) {
printer->Print(vars, "// Original file comments:\n");
printer->Print(leading_comments.c_str());
}
printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n"); printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n"); printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
printer->Print(vars, "\n"); printer->Print(vars, "\n");
printer->Print(vars, "#include \"$filename_base$.pb.h\"\n"); printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
printer->Print(vars, "\n"); printer->Print(vars, "\n");
} }
return output; return output;
@ -455,6 +461,7 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
(*vars)["Method"] = method->name(); (*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name(); (*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name(); (*vars)["Response"] = method->output_type_name();
printer->Print(method->GetLeadingComments().c_str());
if (method->NoStreaming()) { if (method->NoStreaming()) {
printer->Print(*vars, printer->Print(*vars,
"virtual ::grpc::Status $Method$(" "virtual ::grpc::Status $Method$("
@ -479,6 +486,7 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
"::grpc::ServerReaderWriter< $Response$, $Request$>* stream);" "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);"
"\n"); "\n");
} }
printer->Print(method->GetTrailingComments().c_str());
} }
void PrintHeaderServerMethodAsync( void PrintHeaderServerMethodAsync(
@ -673,6 +681,7 @@ void PrintHeaderService(Printer *printer,
std::map<grpc::string, grpc::string> *vars) { std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name(); (*vars)["Service"] = service->name();
printer->Print(service->GetLeadingComments().c_str());
printer->Print(*vars, printer->Print(*vars,
"class $Service$ GRPC_FINAL {\n" "class $Service$ GRPC_FINAL {\n"
" public:\n"); " public:\n");
@ -685,7 +694,9 @@ void PrintHeaderService(Printer *printer,
printer->Indent(); printer->Indent();
printer->Print("virtual ~StubInterface() {}\n"); printer->Print("virtual ~StubInterface() {}\n");
for (int i = 0; i < service->method_count(); ++i) { for (int i = 0; i < service->method_count(); ++i) {
printer->Print(service->method(i)->GetLeadingComments().c_str());
PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true); PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true);
printer->Print(service->method(i)->GetTrailingComments().c_str());
} }
printer->Outdent(); printer->Outdent();
printer->Print("private:\n"); printer->Print("private:\n");
@ -761,6 +772,7 @@ void PrintHeaderService(Printer *printer,
printer->Outdent(); printer->Outdent();
printer->Print("};\n"); printer->Print("};\n");
printer->Print(service->GetTrailingComments().c_str());
} }
grpc::string GetHeaderServices(File *file, grpc::string GetHeaderServices(File *file,
@ -794,8 +806,7 @@ grpc::string GetHeaderServices(File *file,
return output; return output;
} }
grpc::string GetHeaderEpilogue(File *file, grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) {
const Parameters &params) {
grpc::string output; grpc::string output;
{ {
// Scope the output stream so it closes and finalizes output to the string. // Scope the output stream so it closes and finalizes output to the string.
@ -817,12 +828,13 @@ grpc::string GetHeaderEpilogue(File *file,
printer->Print(vars, "\n"); printer->Print(vars, "\n");
printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n"); printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n");
printer->Print(file->GetTrailingComments().c_str());
} }
return output; return output;
} }
grpc::string GetSourcePrologue(File *file, grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
const Parameters &params) {
grpc::string output; grpc::string output;
{ {
// Scope the output stream so it closes and finalizes output to the string. // Scope the output stream so it closes and finalizes output to the string.
@ -831,13 +843,17 @@ grpc::string GetSourcePrologue(File *file,
vars["filename"] = file->filename(); vars["filename"] = file->filename();
vars["filename_base"] = file->filename_without_ext(); vars["filename_base"] = file->filename_without_ext();
vars["message_header_ext"] = file->message_header_ext();
vars["service_header_ext"] = file->service_header_ext();
printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n"); printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n");
printer->Print(vars, printer->Print(vars,
"// If you make any local change, they will be lost.\n"); "// If you make any local change, they will be lost.\n");
printer->Print(vars, "// source: $filename$\n\n"); printer->Print(vars, "// source: $filename$\n\n");
printer->Print(vars, "#include \"$filename_base$.pb.h\"\n");
printer->Print(vars, "#include \"$filename_base$.grpc.pb.h\"\n"); printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
printer->Print(vars, file->additional_headers().c_str());
printer->Print(vars, "\n"); printer->Print(vars, "\n");
} }
return output; return output;
@ -1180,8 +1196,7 @@ grpc::string GetSourceServices(File *file,
return output; return output;
} }
grpc::string GetSourceEpilogue(File *file, grpc::string GetSourceEpilogue(File *file, const Parameters & /*params*/) {
const Parameters &params) {
grpc::string temp; grpc::string temp;
if (!file->package().empty()) { if (!file->package().empty()) {

@ -64,8 +64,16 @@ struct Parameters {
grpc::string grpc_search_path; grpc::string grpc_search_path;
}; };
// A common interface for objects having comments in the source.
// Return formatted comments to be inserted in generated code.
struct CommentHolder {
virtual ~CommentHolder() {}
virtual grpc::string GetLeadingComments() const = 0;
virtual grpc::string GetTrailingComments() const = 0;
};
// An abstract interface representing a method. // An abstract interface representing a method.
struct Method { struct Method : public CommentHolder {
virtual ~Method() {} virtual ~Method() {}
virtual grpc::string name() const = 0; virtual grpc::string name() const = 0;
@ -80,7 +88,7 @@ struct Method {
}; };
// An abstract interface representing a service. // An abstract interface representing a service.
struct Service { struct Service : public CommentHolder {
virtual ~Service() {} virtual ~Service() {}
virtual grpc::string name() const = 0; virtual grpc::string name() const = 0;
@ -101,13 +109,16 @@ struct Printer {
// An interface that allows the source generated to be output using various // An interface that allows the source generated to be output using various
// libraries/idls/serializers. // libraries/idls/serializers.
struct File { struct File : public CommentHolder {
virtual ~File() {} virtual ~File() {}
virtual grpc::string filename() const = 0; virtual grpc::string filename() const = 0;
virtual grpc::string filename_without_ext() const = 0; virtual grpc::string filename_without_ext() const = 0;
virtual grpc::string message_header_ext() const = 0;
virtual grpc::string service_header_ext() const = 0;
virtual grpc::string package() const = 0; virtual grpc::string package() const = 0;
virtual std::vector<grpc::string> package_parts() const = 0; virtual std::vector<grpc::string> package_parts() const = 0;
virtual grpc::string additional_headers() const = 0;
virtual int service_count() const = 0; virtual int service_count() const = 0;
virtual std::unique_ptr<const Service> service(int i) const = 0; virtual std::unique_ptr<const Service> service(int i) const = 0;

@ -35,11 +35,15 @@
// //
#include <memory> #include <memory>
#include <sstream>
#include "src/compiler/config.h" #include "src/compiler/config.h"
#include "src/compiler/cpp_generator.h" #include "src/compiler/cpp_generator.h"
#include "src/compiler/cpp_generator_helpers.h" #include "src/compiler/cpp_generator_helpers.h"
#include "src/compiler/generator_helpers.h"
using grpc_generator::GetCppComments;
class ProtoBufMethod : public grpc_cpp_generator::Method { class ProtoBufMethod : public grpc_cpp_generator::Method {
public: public:
@ -71,6 +75,14 @@ class ProtoBufMethod : public grpc_cpp_generator::Method {
return method_->client_streaming() && method_->server_streaming(); return method_->client_streaming() && method_->server_streaming();
} }
grpc::string GetLeadingComments() const {
return GetCppComments(method_, true);
}
grpc::string GetTrailingComments() const {
return GetCppComments(method_, false);
}
private: private:
const grpc::protobuf::MethodDescriptor *method_; const grpc::protobuf::MethodDescriptor *method_;
}; };
@ -88,6 +100,14 @@ class ProtoBufService : public grpc_cpp_generator::Service {
new ProtoBufMethod(service_->method(i))); new ProtoBufMethod(service_->method(i)));
}; };
grpc::string GetLeadingComments() const {
return GetCppComments(service_, true);
}
grpc::string GetTrailingComments() const {
return GetCppComments(service_, false);
}
private: private:
const grpc::protobuf::ServiceDescriptor *service_; const grpc::protobuf::ServiceDescriptor *service_;
}; };
@ -120,11 +140,16 @@ class ProtoBufFile : public grpc_cpp_generator::File {
return grpc_generator::StripProto(filename()); return grpc_generator::StripProto(filename());
} }
grpc::string message_header_ext() const { return ".pb.h"; }
grpc::string service_header_ext() const { return ".grpc.pb.h"; }
grpc::string package() const { return file_->package(); } grpc::string package() const { return file_->package(); }
std::vector<grpc::string> package_parts() const { std::vector<grpc::string> package_parts() const {
return grpc_generator::tokenize(package(), "."); return grpc_generator::tokenize(package(), ".");
} }
grpc::string additional_headers() const { return ""; }
int service_count() const { return file_->service_count(); }; int service_count() const { return file_->service_count(); };
std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const { std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Service> ( return std::unique_ptr<const grpc_cpp_generator::Service> (
@ -136,6 +161,14 @@ class ProtoBufFile : public grpc_cpp_generator::File {
new ProtoBufPrinter(str)); new ProtoBufPrinter(str));
} }
grpc::string GetLeadingComments() const {
return GetCppComments(file_, true);
}
grpc::string GetTrailingComments() const {
return GetCppComments(file_, false);
}
private: private:
const grpc::protobuf::FileDescriptor *file_; const grpc::protobuf::FileDescriptor *file_;
}; };

@ -123,6 +123,10 @@ std::string GetMethodRequestParamMaybe(const MethodDescriptor *method,
return GetClassName(method->input_type()) + " request, "; return GetClassName(method->input_type()) + " request, ";
} }
std::string GetAccessLevel(bool internal_access) {
return internal_access ? "internal" : "public";
}
std::string GetMethodReturnTypeClient(const MethodDescriptor *method) { std::string GetMethodReturnTypeClient(const MethodDescriptor *method) {
switch (GetMethodType(method)) { switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING: case METHODTYPE_NO_STREAMING:
@ -350,10 +354,12 @@ void GenerateServerClass(Printer* out, const ServiceDescriptor *service) {
void GenerateClientStub(Printer* out, const ServiceDescriptor *service) { void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Print("// client stub\n"); out->Print("// client stub\n");
out->Print("#pragma warning disable 0618\n");
out->Print( out->Print(
"public class $name$ : ClientBase<$name$>, $interface$\n", "public class $name$ : ClientBase<$name$>, $interface$\n",
"name", GetClientClassName(service), "name", GetClientClassName(service),
"interface", GetClientInterfaceName(service)); "interface", GetClientInterfaceName(service));
out->Print("#pragma warning restore 0618\n");
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
@ -480,10 +486,12 @@ void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service,
bool use_server_class) { bool use_server_class) {
out->Print( out->Print(
"// creates service definition that can be registered with a server\n"); "// creates service definition that can be registered with a server\n");
out->Print("#pragma warning disable 0618\n");
out->Print( out->Print(
"public static ServerServiceDefinition BindService($interface$ serviceImpl)\n", "public static ServerServiceDefinition BindService($interface$ serviceImpl)\n",
"interface", use_server_class ? GetServerClassName(service) : "interface", use_server_class ? GetServerClassName(service) :
GetServerInterfaceName(service)); GetServerInterfaceName(service));
out->Print("#pragma warning restore 0618\n");
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
@ -523,8 +531,11 @@ void GenerateNewStubMethods(Printer* out, const ServiceDescriptor *service) {
out->Print("\n"); out->Print("\n");
} }
void GenerateService(Printer* out, const ServiceDescriptor *service) { void GenerateService(Printer* out, const ServiceDescriptor *service,
out->Print("public static class $classname$\n", "classname", bool generate_client, bool generate_server,
bool internal_access) {
out->Print("$access_level$ static class $classname$\n", "access_level",
GetAccessLevel(internal_access), "classname",
GetServiceClassName(service)); GetServiceClassName(service));
out->Print("{\n"); out->Print("{\n");
out->Indent(); out->Indent();
@ -538,13 +549,22 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) {
GenerateStaticMethodField(out, service->method(i)); GenerateStaticMethodField(out, service->method(i));
} }
GenerateServiceDescriptorProperty(out, service); GenerateServiceDescriptorProperty(out, service);
if (generate_client) {
GenerateClientInterface(out, service); GenerateClientInterface(out, service);
}
if (generate_server) {
GenerateServerInterface(out, service); GenerateServerInterface(out, service);
GenerateServerClass(out, service); GenerateServerClass(out, service);
}
if (generate_client) {
GenerateClientStub(out, service); GenerateClientStub(out, service);
GenerateNewStubMethods(out, service);
}
if (generate_server) {
GenerateBindServiceMethod(out, service, false); GenerateBindServiceMethod(out, service, false);
GenerateBindServiceMethod(out, service, true); GenerateBindServiceMethod(out, service, true);
GenerateNewStubMethods(out, service); }
out->Outdent(); out->Outdent();
out->Print("}\n"); out->Print("}\n");
@ -552,7 +572,8 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) {
} // anonymous namespace } // anonymous namespace
grpc::string GetServices(const FileDescriptor *file) { grpc::string GetServices(const FileDescriptor *file, bool generate_client,
bool generate_server, bool internal_access) {
grpc::string output; grpc::string output;
{ {
// Scope the output stream so it closes and finalizes output to the string. // Scope the output stream so it closes and finalizes output to the string.
@ -580,7 +601,8 @@ grpc::string GetServices(const FileDescriptor *file) {
out.Print("namespace $namespace$ {\n", "namespace", GetFileNamespace(file)); out.Print("namespace $namespace$ {\n", "namespace", GetFileNamespace(file));
out.Indent(); out.Indent();
for (int i = 0; i < file->service_count(); i++) { for (int i = 0; i < file->service_count(); i++) {
GenerateService(&out, file->service(i)); GenerateService(&out, file->service(i), generate_client, generate_server,
internal_access);
} }
out.Outdent(); out.Outdent();
out.Print("}\n"); out.Print("}\n");

@ -40,7 +40,9 @@
namespace grpc_csharp_generator { namespace grpc_csharp_generator {
grpc::string GetServices(const grpc::protobuf::FileDescriptor *file); grpc::string GetServices(const grpc::protobuf::FileDescriptor *file,
bool generate_client, bool generate_server,
bool internal_access);
} // namespace grpc_csharp_generator } // namespace grpc_csharp_generator

@ -48,7 +48,29 @@ class CSharpGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
const grpc::string &parameter, const grpc::string &parameter,
grpc::protobuf::compiler::GeneratorContext *context, grpc::protobuf::compiler::GeneratorContext *context,
grpc::string *error) const { grpc::string *error) const {
grpc::string code = grpc_csharp_generator::GetServices(file); std::vector<std::pair<grpc::string, grpc::string> > options;
grpc::protobuf::compiler::ParseGeneratorParameter(parameter, &options);
bool generate_client = true;
bool generate_server = true;
bool internal_access = false;
for (size_t i = 0; i < options.size(); i++) {
if (options[i].first == "no_client") {
generate_client = false;
} else if (options[i].first == "no_server") {
generate_server = false;
} else if (options[i].first == "internal_access") {
internal_access = true;
} else {
*error = "Unknown generator option: " + options[i].first;
return false;
}
}
grpc::string code = grpc_csharp_generator::GetServices(file,
generate_client,
generate_server,
internal_access);
if (code.size() == 0) { if (code.size() == 0) {
return true; // don't generate a file if there are no services return true; // don't generate a file if there are no services
} }

@ -34,7 +34,11 @@
#ifndef GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H #ifndef GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H
#define GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H #define GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H
#include <iostream>
#include <map> #include <map>
#include <sstream>
#include <string>
#include <vector>
#include "src/compiler/config.h" #include "src/compiler/config.h"
@ -52,6 +56,16 @@ inline bool StripSuffix(grpc::string *filename, const grpc::string &suffix) {
return false; return false;
} }
inline bool StripPrefix(grpc::string *name, const grpc::string &prefix) {
if (name->length() >= prefix.length()) {
if (name->substr(0, prefix.size()) == prefix) {
*name = name->substr(prefix.size());
return true;
}
}
return false;
}
inline grpc::string StripProto(grpc::string filename) { inline grpc::string StripProto(grpc::string filename) {
if (!StripSuffix(&filename, ".protodevel")) { if (!StripSuffix(&filename, ".protodevel")) {
StripSuffix(&filename, ".proto"); StripSuffix(&filename, ".proto");
@ -165,6 +179,111 @@ inline MethodType GetMethodType(const grpc::protobuf::MethodDescriptor *method)
} }
} }
inline void Split(const grpc::string &s, char delim,
std::vector<grpc::string> *append_to) {
std::istringstream iss(s);
grpc::string piece;
while (std::getline(iss, piece)) {
append_to->push_back(piece);
}
}
enum CommentType {
COMMENTTYPE_LEADING,
COMMENTTYPE_TRAILING,
COMMENTTYPE_LEADING_DETACHED
};
// Get all the raw comments and append each line without newline to out.
template <typename DescriptorType>
inline void GetComment(const DescriptorType *desc, CommentType type,
std::vector<grpc::string> *out) {
grpc::protobuf::SourceLocation location;
if (!desc->GetSourceLocation(&location)) {
return;
}
if (type == COMMENTTYPE_LEADING || type == COMMENTTYPE_TRAILING) {
const grpc::string &comments = type == COMMENTTYPE_LEADING
? location.leading_comments
: location.trailing_comments;
Split(comments, '\n', out);
} else if (type == COMMENTTYPE_LEADING_DETACHED) {
for (unsigned int i = 0; i < location.leading_detached_comments.size();
i++) {
Split(location.leading_detached_comments[i], '\n', out);
out->push_back("");
}
} else {
std::cerr << "Unknown comment type " << type << std::endl;
abort();
}
}
// Each raw comment line without newline is appended to out.
// For file level leading and detached leading comments, we return comments
// above syntax line. Return nothing for trailing comments.
template <>
inline void GetComment(const grpc::protobuf::FileDescriptor *desc,
CommentType type, std::vector<grpc::string> *out) {
if (type == COMMENTTYPE_TRAILING) {
return;
}
grpc::protobuf::SourceLocation location;
std::vector<int> path;
path.push_back(grpc::protobuf::FileDescriptorProto::kSyntaxFieldNumber);
if (!desc->GetSourceLocation(path, &location)) {
return;
}
if (type == COMMENTTYPE_LEADING) {
Split(location.leading_comments, '\n', out);
} else if (type == COMMENTTYPE_LEADING_DETACHED) {
for (unsigned int i = 0; i < location.leading_detached_comments.size();
i++) {
Split(location.leading_detached_comments[i], '\n', out);
out->push_back("");
}
} else {
std::cerr << "Unknown comment type " << type << std::endl;
abort();
}
}
// Add prefix and newline to each comment line and concatenate them together.
// Make sure there is a space after the prefix unless the line is empty.
inline grpc::string GenerateCommentsWithPrefix(
const std::vector<grpc::string> &in, const grpc::string &prefix) {
std::ostringstream oss;
for (const grpc::string &elem : in) {
if (elem.empty()) {
oss << prefix << "\n";
} else if (elem[0] == ' ') {
oss << prefix << elem << "\n";
} else {
oss << prefix << " " << elem << "\n";
}
}
return oss.str();
}
// Get leading or trailing comments in a string. Comment lines start with "// ".
// Leading detached comments are put in in front of leading comments.
template <typename DescriptorType>
inline grpc::string GetCppComments(const DescriptorType *desc, bool leading) {
std::vector<grpc::string> out;
if (leading) {
grpc_generator::GetComment(
desc, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &out);
std::vector<grpc::string> leading;
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_LEADING,
&leading);
out.insert(out.end(), leading.begin(), leading.end());
} else {
grpc_generator::GetComment(desc, grpc_generator::COMMENTTYPE_TRAILING,
&out);
}
return GenerateCommentsWithPrefix(out, "//");
}
} // namespace grpc_generator } // namespace grpc_generator
#endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H #endif // GRPC_INTERNAL_COMPILER_GENERATOR_HELPERS_H

@ -0,0 +1,277 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <map>
#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
#include "src/compiler/node_generator_helpers.h"
using grpc::protobuf::FileDescriptor;
using grpc::protobuf::ServiceDescriptor;
using grpc::protobuf::MethodDescriptor;
using grpc::protobuf::Descriptor;
using grpc::protobuf::io::Printer;
using grpc::protobuf::io::StringOutputStream;
using std::map;
namespace grpc_node_generator {
namespace {
// Returns the alias we assign to the module of the given .proto filename
// when importing. Copied entirely from
// github:google/protobuf/src/google/protobuf/compiler/js/js_generator.cc#L154
grpc::string ModuleAlias(const grpc::string filename) {
// This scheme could technically cause problems if a file includes any 2 of:
// foo/bar_baz.proto
// foo_bar_baz.proto
// foo_bar/baz.proto
//
// We'll worry about this problem if/when we actually see it. This name isn't
// exposed to users so we can change it later if we need to.
grpc::string basename = grpc_generator::StripProto(filename);
basename = grpc_generator::StringReplace(basename, "-", "$");
basename = grpc_generator::StringReplace(basename, "/", "_");
return basename + "_pb";
}
// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// message file foo/bar/baz.js
grpc::string GetJSMessageFilename(const grpc::string& filename) {
grpc::string name = filename;
return grpc_generator::StripProto(name) + "_pb.js";
}
// Given a filename like foo/bar/baz.proto, returns the root directory
// path ../../
grpc::string GetRootPath(const grpc::string& filename) {
size_t slashes = std::count(filename.begin(), filename.end(), '/');
if (slashes == 0) {
return "./";
}
grpc::string result = "";
for (size_t i = 0; i < slashes; i++) {
result += "../";
}
return result;
}
// Return the relative path to load to_file from the directory containing
// from_file, assuming that both paths are relative to the same directory
grpc::string GetRelativePath(const grpc::string& from_file,
const grpc::string& to_file) {
return GetRootPath(from_file) + to_file;
}
/* Finds all message types used in all services in the file, and returns them
* as a map of fully qualified message type name to message descriptor */
map<grpc::string, const Descriptor*> GetAllMessages(const FileDescriptor *file) {
map<grpc::string, const Descriptor*> message_types;
for (int service_num = 0; service_num < file->service_count(); service_num++) {
const ServiceDescriptor* service = file->service(service_num);
for (int method_num = 0; method_num < service->method_count(); method_num++) {
const MethodDescriptor* method = service->method(method_num);
const Descriptor* input_type = method->input_type();
const Descriptor* output_type = method->output_type();
message_types[input_type->name()] = input_type;
message_types[output_type->name()] = output_type;
}
}
return message_types;
}
grpc::string MessageIdentifierName(const grpc::string& name) {
return grpc_generator::StringReplace(name, ".", "_");
}
grpc::string NodeObjectPath(const Descriptor *descriptor) {
grpc::string module_alias = ModuleAlias(descriptor->file()->name());
grpc::string name = descriptor->name();
grpc_generator::StripPrefix(&name, descriptor->file()->package() + ".");
return module_alias + "." + name;
}
// Prints out the message serializer and deserializer functions
void PrintMessageTransformer(const Descriptor *descriptor, Printer *out) {
map<grpc::string, grpc::string> template_vars;
template_vars["identifier_name"] = MessageIdentifierName(descriptor->name());
template_vars["name"] = descriptor->name();
template_vars["node_name"] = NodeObjectPath(descriptor);
// Print the serializer
out->Print(template_vars, "function serialize_$identifier_name$(arg) {\n");
out->Indent();
out->Print(template_vars, "if (!(arg instanceof $node_name$)) {\n");
out->Indent();
out->Print(template_vars,
"throw new Error('Expected argument of type $name$');\n");
out->Outdent();
out->Print("}\n");
out->Print("return new Buffer(arg.serializeBinary());\n");
out->Outdent();
out->Print("}\n\n");
// Print the deserializer
out->Print(template_vars,
"function deserialize_$identifier_name$(buffer_arg) {\n");
out->Indent();
out->Print(
template_vars,
"return $node_name$.deserializeBinary(new Uint8Array(buffer_arg));\n");
out->Outdent();
out->Print("}\n\n");
}
void PrintMethod(const MethodDescriptor *method, Printer *out) {
const Descriptor *input_type = method->input_type();
const Descriptor *output_type = method->output_type();
map<grpc::string, grpc::string> vars;
vars["service_name"] = method->service()->full_name();
vars["name"] = method->name();
vars["input_type"] = NodeObjectPath(input_type);
vars["input_type_id"] = MessageIdentifierName(input_type->name());
vars["output_type"] = NodeObjectPath(output_type);
vars["output_type_id"] = MessageIdentifierName(output_type->name());
vars["client_stream"] = method->client_streaming() ? "true" : "false";
vars["server_stream"] = method->server_streaming() ? "true" : "false";
out->Print("{\n");
out->Indent();
out->Print(vars, "path: '/$service_name$/$name$',\n");
out->Print(vars, "requestStream: $client_stream$,\n");
out->Print(vars, "responseStream: $server_stream$,\n");
out->Print(vars, "requestType: $input_type$,\n");
out->Print(vars, "responseType: $output_type$,\n");
out->Print(vars, "requestSerialize: serialize_$input_type_id$,\n");
out->Print(vars, "requestDeserialize: deserialize_$input_type_id$,\n");
out->Print(vars, "responseSerialize: serialize_$output_type_id$,\n");
out->Print(vars, "responseDeserialize: deserialize_$output_type_id$,\n");
out->Outdent();
out->Print("}");
}
// Prints out the service descriptor object
void PrintService(const ServiceDescriptor *service, Printer *out) {
map<grpc::string, grpc::string> template_vars;
template_vars["name"] = service->name();
out->Print(template_vars, "var $name$Service = exports.$name$Service = {\n");
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
grpc::string method_name = grpc_generator::LowercaseFirstLetter(
service->method(i)->name());
out->Print("$method_name$: ",
"method_name", method_name);
PrintMethod(service->method(i), out);
out->Print(",\n");
}
out->Outdent();
out->Print("};\n\n");
out->Print(template_vars, "exports.$name$Client = "
"grpc.makeGenericClientConstructor($name$Service);\n");
}
}
grpc::string GetImports(const FileDescriptor *file) {
grpc::string output;
{
StringOutputStream output_stream(&output);
Printer out(&output_stream, '$');
if (file->service_count() == 0) {
return output;
}
out.Print("// GENERATED CODE -- DO NOT EDIT!\n\n");
out.Print("'use strict';\n");
out.Print("var grpc = require('grpc');\n");
if (file->message_type_count() > 0) {
grpc::string file_path = GetRelativePath(file->name(),
GetJSMessageFilename(
file->name()));
out.Print("var $module_alias$ = require('$file_path$');\n",
"module_alias", ModuleAlias(file->name()),
"file_path", file_path);
}
for (int i = 0; i < file->dependency_count(); i++) {
grpc::string file_path = GetRelativePath(
file->name(), GetJSMessageFilename(file->dependency(i)->name()));
out.Print("var $module_alias$ = require('$file_path$');\n",
"module_alias", ModuleAlias(file->dependency(i)->name()),
"file_path", file_path);
}
out.Print("\n");
}
return output;
}
grpc::string GetTransformers(const FileDescriptor *file) {
grpc::string output;
{
StringOutputStream output_stream(&output);
Printer out(&output_stream, '$');
if (file->service_count() == 0) {
return output;
}
map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
for (std::map<grpc::string, const Descriptor*>::iterator it =
messages.begin();
it != messages.end(); it++) {
PrintMessageTransformer(it->second, &out);
}
out.Print("\n");
}
return output;
}
grpc::string GetServices(const FileDescriptor *file) {
grpc::string output;
{
StringOutputStream output_stream(&output);
Printer out(&output_stream, '$');
if (file->service_count() == 0) {
return output;
}
for (int i = 0; i < file->service_count(); i++) {
PrintService(file->service(i), &out);
}
}
return output;
}
} // namespace grpc_node_generator

@ -0,0 +1,49 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H
#define GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H
#include "src/compiler/config.h"
namespace grpc_node_generator {
grpc::string GetImports(const grpc::protobuf::FileDescriptor *file);
grpc::string GetTransformers(const grpc::protobuf::FileDescriptor *file);
grpc::string GetServices(const grpc::protobuf::FileDescriptor *file);
} // namespace grpc_node_generator
#endif // GRPC_INTERNAL_COMPILER_NODE_GENERATOR_H

@ -0,0 +1,50 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H
#define GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H
#include <algorithm>
#include "src/compiler/config.h"
#include "src/compiler/generator_helpers.h"
namespace grpc_node_generator {
inline grpc::string GetJSServiceFilename(const grpc::string& filename) {
return grpc_generator::StripProto(filename) + "_grpc_pb.js";
}
} // namespace grpc_node_generator
#endif // GRPC_INTERNAL_COMPILER_NODE_GENERATOR_HELPERS_H

@ -0,0 +1,77 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Generates Node gRPC service interface out of Protobuf IDL.
#include <memory>
#include "src/compiler/config.h"
#include "src/compiler/node_generator.h"
#include "src/compiler/node_generator_helpers.h"
using grpc_node_generator::GetImports;
using grpc_node_generator::GetJSServiceFilename;
using grpc_node_generator::GetServices;
using grpc_node_generator::GetTransformers;
class NodeGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
public:
NodeGrpcGenerator() {}
~NodeGrpcGenerator() {}
bool Generate(const grpc::protobuf::FileDescriptor *file,
const grpc::string &parameter,
grpc::protobuf::compiler::GeneratorContext *context,
grpc::string *error) const {
grpc::string code = GetImports(file) +
GetTransformers(file) +
GetServices(file);
if (code.size() == 0) {
return true;
}
// Get output file name
grpc::string file_name = GetJSServiceFilename(file->name());
std::unique_ptr<grpc::protobuf::io::ZeroCopyOutputStream> output(
context->Open(file_name));
grpc::protobuf::io::CodedOutputStream coded_out(output.get());
coded_out.WriteRaw(code.data(), code.size());
return true;
}
};
int main(int argc, char *argv[]) {
NodeGrpcGenerator generator;
return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
}

@ -205,7 +205,11 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_lock(&chand->mu_config); gpr_mu_lock(&chand->mu_config);
old_lb_policy = chand->lb_policy; old_lb_policy = chand->lb_policy;
chand->lb_policy = lb_policy; chand->lb_policy = lb_policy;
if (lb_policy != NULL || chand->resolver == NULL /* disconnected */) { if (lb_policy != NULL) {
grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
NULL);
} else if (chand->resolver == NULL /* disconnected */) {
grpc_closure_list_fail_all(&chand->waiting_for_config_closures);
grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures, grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
NULL); NULL);
} }
@ -293,6 +297,11 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_resolver_shutdown(exec_ctx, chand->resolver); grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel"); GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL; chand->resolver = NULL;
if (!chand->started_resolving) {
grpc_closure_list_fail_all(&chand->waiting_for_config_closures);
grpc_exec_ctx_enqueue_list(exec_ctx, &chand->waiting_for_config_closures,
NULL);
}
if (chand->lb_policy != NULL) { if (chand->lb_policy != NULL) {
grpc_pollset_set_del_pollset_set(exec_ctx, grpc_pollset_set_del_pollset_set(exec_ctx,
chand->lb_policy->interested_parties, chand->lb_policy->interested_parties,
@ -321,10 +330,10 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) { static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
continue_picking_args *cpa = arg; continue_picking_args *cpa = arg;
if (!success) { if (cpa->connected_subchannel == NULL) {
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
} else if (cpa->connected_subchannel == NULL) {
/* cancelled, do nothing */ /* cancelled, do nothing */
} else if (!success) {
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, false, NULL);
} else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata, } else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
cpa->initial_metadata_flags, cpa->initial_metadata_flags,
cpa->connected_subchannel, cpa->on_ready)) { cpa->connected_subchannel, cpa->on_ready)) {
@ -383,6 +392,7 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
&chand->incoming_configuration, &chand->incoming_configuration,
&chand->on_config_changed); &chand->on_config_changed);
} }
if (chand->resolver != NULL) {
cpa = gpr_malloc(sizeof(*cpa)); cpa = gpr_malloc(sizeof(*cpa));
cpa->initial_metadata = initial_metadata; cpa->initial_metadata = initial_metadata;
cpa->initial_metadata_flags = initial_metadata_flags; cpa->initial_metadata_flags = initial_metadata_flags;
@ -390,7 +400,11 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
cpa->on_ready = on_ready; cpa->on_ready = on_ready;
cpa->elem = elem; cpa->elem = elem;
grpc_closure_init(&cpa->closure, continue_picking, cpa); grpc_closure_init(&cpa->closure, continue_picking, cpa);
grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure, 1); grpc_closure_list_add(&chand->waiting_for_config_closures, &cpa->closure,
1);
} else {
grpc_exec_ctx_enqueue(exec_ctx, on_ready, false, NULL);
}
gpr_mu_unlock(&chand->mu_config); gpr_mu_unlock(&chand->mu_config);
return 0; return 0;
} }

@ -135,8 +135,6 @@ struct grpc_subchannel {
int have_alarm; int have_alarm;
/** our alarm */ /** our alarm */
grpc_timer alarm; grpc_timer alarm;
/** current random value */
uint32_t random;
}; };
struct grpc_subchannel_call { struct grpc_subchannel_call {
@ -297,10 +295,6 @@ void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
} }
} }
static uint32_t random_seed() {
return (uint32_t)(gpr_time_to_millis(gpr_now(GPR_CLOCK_MONOTONIC)));
}
grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_connector *connector, grpc_connector *connector,
grpc_subchannel_args *args) { grpc_subchannel_args *args) {
@ -332,7 +326,6 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_set_initial_connect_string(&c->addr, &c->addr_len, grpc_set_initial_connect_string(&c->addr, &c->addr_len,
&c->initial_connect_string); &c->initial_connect_string);
c->args = grpc_channel_args_copy(args->args); c->args = grpc_channel_args_copy(args->args);
c->random = random_seed();
c->root_external_state_watcher.next = c->root_external_state_watcher.prev = c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
&c->root_external_state_watcher; &c->root_external_state_watcher;
grpc_closure_init(&c->connected, subchannel_connected, c); grpc_closure_init(&c->connected, subchannel_connected, c);

@ -253,9 +253,9 @@ char *grpc_subchannel_call_holder_get_peer(
grpc_exec_ctx *exec_ctx, grpc_subchannel_call_holder *holder) { grpc_exec_ctx *exec_ctx, grpc_subchannel_call_holder *holder) {
grpc_subchannel_call *subchannel_call = GET_CALL(holder); grpc_subchannel_call *subchannel_call = GET_CALL(holder);
if (subchannel_call) { if (subchannel_call == NULL || subchannel_call == CANCELLED_CALL) {
return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
} else {
return NULL; return NULL;
} else {
return grpc_subchannel_call_get_peer(exec_ctx, subchannel_call);
} }
} }

@ -86,7 +86,8 @@ typedef struct {
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_start_resolving_locked(dns_resolver *r); static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r);
static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r); dns_resolver *r);
@ -119,7 +120,7 @@ static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
gpr_mu_lock(&r->mu); gpr_mu_lock(&r->mu);
if (!r->resolving) { if (!r->resolving) {
gpr_backoff_reset(&r->backoff_state); gpr_backoff_reset(&r->backoff_state);
dns_start_resolving_locked(r); dns_start_resolving_locked(exec_ctx, r);
} }
gpr_mu_unlock(&r->mu); gpr_mu_unlock(&r->mu);
} }
@ -134,7 +135,7 @@ static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
r->target_config = target_config; r->target_config = target_config;
if (r->resolved_version == 0 && !r->resolving) { if (r->resolved_version == 0 && !r->resolving) {
gpr_backoff_reset(&r->backoff_state); gpr_backoff_reset(&r->backoff_state);
dns_start_resolving_locked(r); dns_start_resolving_locked(exec_ctx, r);
} else { } else {
dns_maybe_finish_next_locked(exec_ctx, r); dns_maybe_finish_next_locked(exec_ctx, r);
} }
@ -149,7 +150,7 @@ static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
r->have_retry_timer = false; r->have_retry_timer = false;
if (success) { if (success) {
if (!r->resolving) { if (!r->resolving) {
dns_start_resolving_locked(r); dns_start_resolving_locked(exec_ctx, r);
} }
} }
gpr_mu_unlock(&r->mu); gpr_mu_unlock(&r->mu);
@ -201,11 +202,12 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving"); GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "dns-resolving");
} }
static void dns_start_resolving_locked(dns_resolver *r) { static void dns_start_resolving_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r) {
GRPC_RESOLVER_REF(&r->base, "dns-resolving"); GRPC_RESOLVER_REF(&r->base, "dns-resolving");
GPR_ASSERT(!r->resolving); GPR_ASSERT(!r->resolving);
r->resolving = 1; r->resolving = 1;
grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r); grpc_resolve_address(exec_ctx, r->name, r->default_port, dns_on_resolved, r);
} }
static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx, static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,

@ -299,7 +299,7 @@ static void zookeeper_get_children_node_completion(int rc, const char *value,
address = zookeeper_parse_address(value, (size_t)value_len); address = zookeeper_parse_address(value, (size_t)value_len);
if (address != NULL) { if (address != NULL) {
/** Further resolves address by DNS */ /** Further resolves address by DNS */
grpc_resolve_address(address, NULL, zookeeper_dns_resolved, r); grpc_resolve_address(&exec_ctx, address, NULL, zookeeper_dns_resolved, r);
gpr_free(address); gpr_free(address);
} else { } else {
gpr_log(GPR_ERROR, "Error in resolving a child node of %s", r->name); gpr_log(GPR_ERROR, "Error in resolving a child node of %s", r->name);
@ -375,8 +375,10 @@ static void zookeeper_get_node_completion(int rc, const char *value,
r->resolved_addrs->naddrs = 0; r->resolved_addrs->naddrs = 0;
r->resolved_total = 1; r->resolved_total = 1;
/** Further resolves address by DNS */ /** Further resolves address by DNS */
grpc_resolve_address(address, NULL, zookeeper_dns_resolved, r); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_resolve_address(&exec_ctx, address, NULL, zookeeper_dns_resolved, r);
gpr_free(address); gpr_free(address);
grpc_exec_ctx_finish(&exec_ctx);
return; return;
} }

@ -235,5 +235,7 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
return channel; /* may be NULL */ return channel != NULL ? channel : grpc_lame_client_channel_create(
target, GRPC_STATUS_INTERNAL,
"Failed to create client channel");
} }

@ -639,7 +639,7 @@ static int on_hdr(grpc_chttp2_hpack_parser *p, grpc_mdelem *md,
} }
} }
if (p->on_header == NULL) { if (p->on_header == NULL) {
grpc_mdelem_unref(md); GRPC_MDELEM_UNREF(md);
return 0; return 0;
} }
p->on_header(p->on_header_user_data, md); p->on_header(p->on_header_user_data, md);

@ -268,8 +268,14 @@ static void init_channel_elem(grpc_exec_ctx *exec_ctx,
channeld->default_compression_algorithm = channeld->default_compression_algorithm =
grpc_channel_args_get_compression_algorithm(args->channel_args); grpc_channel_args_get_compression_algorithm(args->channel_args);
/* Make sure the default isn't disabled. */ /* Make sure the default isn't disabled. */
GPR_ASSERT(grpc_compression_options_is_algorithm_enabled( if (!grpc_compression_options_is_algorithm_enabled(
&channeld->compression_options, channeld->default_compression_algorithm)); &channeld->compression_options,
channeld->default_compression_algorithm)) {
gpr_log(GPR_DEBUG,
"compression algorithm %d not enabled: switching to none",
channeld->default_compression_algorithm);
channeld->default_compression_algorithm = GRPC_COMPRESS_NONE;
}
channeld->compression_options.default_compression_algorithm = channeld->compression_options.default_compression_algorithm =
channeld->default_compression_algorithm; channeld->default_compression_algorithm;

@ -39,6 +39,9 @@
#include "src/core/lib/profiling/timers.h" #include "src/core/lib/profiling/timers.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
#define EXPECTED_CONTENT_TYPE "application/grpc"
#define EXPECTED_CONTENT_TYPE_LENGTH sizeof(EXPECTED_CONTENT_TYPE) - 1
typedef struct call_data { typedef struct call_data {
uint8_t seen_path; uint8_t seen_path;
uint8_t seen_method; uint8_t seen_method;
@ -92,8 +95,11 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
require */ require */
return NULL; return NULL;
} else if (md->key == GRPC_MDSTR_CONTENT_TYPE) { } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) {
if (strncmp(grpc_mdstr_as_c_string(md->value), "application/grpc+", 17) == const char *value_str = grpc_mdstr_as_c_string(md->value);
0) { if (strncmp(value_str, EXPECTED_CONTENT_TYPE,
EXPECTED_CONTENT_TYPE_LENGTH) == 0 &&
(value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' ||
value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) {
/* Although the C implementation doesn't (currently) generate them, /* Although the C implementation doesn't (currently) generate them,
any custom +-suffix is explicitly valid. */ any custom +-suffix is explicitly valid. */
/* TODO(klempner): We should consider preallocating common values such /* TODO(klempner): We should consider preallocating common values such
@ -102,8 +108,7 @@ static grpc_mdelem *server_filter(void *user_data, grpc_mdelem *md) {
} else { } else {
/* TODO(klempner): We're currently allowing this, but we shouldn't /* TODO(klempner): We're currently allowing this, but we shouldn't
see it without a proxy so log for now. */ see it without a proxy so log for now. */
gpr_log(GPR_INFO, "Unexpected content-type %s", gpr_log(GPR_INFO, "Unexpected content-type %s", value_str);
grpc_mdstr_as_c_string(md->value));
} }
return NULL; return NULL;
} else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD || } else if (md->key == GRPC_MDSTR_TE || md->key == GRPC_MDSTR_METHOD ||

@ -246,7 +246,7 @@ static void internal_request_begin(
grpc_pollset_set_add_pollset_set(exec_ctx, req->context->pollset_set, grpc_pollset_set_add_pollset_set(exec_ctx, req->context->pollset_set,
req->pollset_set); req->pollset_set);
grpc_resolve_address(request->host, req->handshaker->default_port, grpc_resolve_address(exec_ctx, request->host, req->handshaker->default_port,
on_resolved, req); on_resolved, req);
} }

@ -172,8 +172,8 @@ static int add_header(grpc_http_parser *parser) {
while (cur != end && (*cur == ' ' || *cur == '\t')) { while (cur != end && (*cur == ' ' || *cur == '\t')) {
cur++; cur++;
} }
GPR_ASSERT(end - cur >= 2); GPR_ASSERT((size_t)(end - cur) >= parser->cur_line_end_length);
hdr.value = buf2str(cur, (size_t)(end - cur) - 2); hdr.value = buf2str(cur, (size_t)(end - cur) - parser->cur_line_end_length);
if (parser->type == GRPC_HTTP_RESPONSE) { if (parser->type == GRPC_HTTP_RESPONSE) {
hdr_count = &parser->http.response.hdr_count; hdr_count = &parser->http.response.hdr_count;
@ -208,7 +208,7 @@ static int finish_line(grpc_http_parser *parser) {
parser->state = GRPC_HTTP_HEADERS; parser->state = GRPC_HTTP_HEADERS;
break; break;
case GRPC_HTTP_HEADERS: case GRPC_HTTP_HEADERS:
if (parser->cur_line_length == 2) { if (parser->cur_line_length == parser->cur_line_end_length) {
parser->state = GRPC_HTTP_BODY; parser->state = GRPC_HTTP_BODY;
break; break;
} }
@ -248,6 +248,30 @@ static int addbyte_body(grpc_http_parser *parser, uint8_t byte) {
return 1; return 1;
} }
static int check_line(grpc_http_parser *parser) {
if (parser->cur_line_length >= 2 &&
parser->cur_line[parser->cur_line_length - 2] == '\r' &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
return 1;
}
// HTTP request with \n\r line termiantors.
else if (parser->cur_line_length >= 2 &&
parser->cur_line[parser->cur_line_length - 2] == '\n' &&
parser->cur_line[parser->cur_line_length - 1] == '\r') {
return 1;
}
// HTTP request with only \n line terminators.
else if (parser->cur_line_length >= 1 &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
parser->cur_line_end_length = 1;
return 1;
}
return 0;
}
static int addbyte(grpc_http_parser *parser, uint8_t byte) { static int addbyte(grpc_http_parser *parser, uint8_t byte) {
switch (parser->state) { switch (parser->state) {
case GRPC_HTTP_FIRST_LINE: case GRPC_HTTP_FIRST_LINE:
@ -260,9 +284,7 @@ static int addbyte(grpc_http_parser *parser, uint8_t byte) {
} }
parser->cur_line[parser->cur_line_length] = byte; parser->cur_line[parser->cur_line_length] = byte;
parser->cur_line_length++; parser->cur_line_length++;
if (parser->cur_line_length >= 2 && if (check_line(parser)) {
parser->cur_line[parser->cur_line_length - 2] == '\r' &&
parser->cur_line[parser->cur_line_length - 1] == '\n') {
return finish_line(parser); return finish_line(parser);
} else { } else {
return 1; return 1;
@ -278,6 +300,7 @@ void grpc_http_parser_init(grpc_http_parser *parser) {
memset(parser, 0, sizeof(*parser)); memset(parser, 0, sizeof(*parser));
parser->state = GRPC_HTTP_FIRST_LINE; parser->state = GRPC_HTTP_FIRST_LINE;
parser->type = GRPC_HTTP_UNKNOWN; parser->type = GRPC_HTTP_UNKNOWN;
parser->cur_line_end_length = 2;
} }
void grpc_http_parser_destroy(grpc_http_parser *parser) { void grpc_http_parser_destroy(grpc_http_parser *parser) {

@ -105,6 +105,7 @@ typedef struct {
uint8_t cur_line[GRPC_HTTP_PARSER_MAX_HEADER_LENGTH]; uint8_t cur_line[GRPC_HTTP_PARSER_MAX_HEADER_LENGTH];
size_t cur_line_length; size_t cur_line_length;
size_t cur_line_end_length;
} grpc_http_parser; } grpc_http_parser;
void grpc_http_parser_init(grpc_http_parser *parser); void grpc_http_parser_init(grpc_http_parser *parser);

@ -54,6 +54,12 @@ void grpc_closure_list_add(grpc_closure_list *closure_list,
closure_list->tail = closure; closure_list->tail = closure;
} }
void grpc_closure_list_fail_all(grpc_closure_list *list) {
for (grpc_closure *c = list->head; c != NULL; c = grpc_closure_next(c)) {
c->final_data &= ~(uintptr_t)1;
}
}
bool grpc_closure_list_empty(grpc_closure_list closure_list) { bool grpc_closure_list_empty(grpc_closure_list closure_list) {
return closure_list.head == NULL; return closure_list.head == NULL;
} }

@ -86,6 +86,9 @@ grpc_closure *grpc_closure_create(grpc_iomgr_cb_func cb, void *cb_arg);
void grpc_closure_list_add(grpc_closure_list *list, grpc_closure *closure, void grpc_closure_list_add(grpc_closure_list *list, grpc_closure *closure,
bool success); bool success);
/** force all success bits in \a list to false */
void grpc_closure_list_fail_all(grpc_closure_list *list);
/** append all closures from \a src to \a dst and empty \a src. */ /** append all closures from \a src to \a dst and empty \a src. */
void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst); void grpc_closure_list_move(grpc_closure_list *src, grpc_closure_list *dst);

@ -92,6 +92,8 @@ void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
grpc_closure_list *list, grpc_closure_list *list,
grpc_workqueue *offload_target_or_null); grpc_workqueue *offload_target_or_null);
void grpc_exec_ctx_global_init(void);
void grpc_exec_ctx_global_init(void); void grpc_exec_ctx_global_init(void);
void grpc_exec_ctx_global_shutdown(void); void grpc_exec_ctx_global_shutdown(void);

@ -59,7 +59,8 @@ typedef void (*grpc_resolve_cb)(grpc_exec_ctx *exec_ctx, void *arg,
/* Asynchronously resolve addr. Use default_port if a port isn't designated /* Asynchronously resolve addr. Use default_port if a port isn't designated
in addr, otherwise use the port in addr. */ in addr, otherwise use the port in addr. */
/* TODO(ctiller): add a timeout here */ /* TODO(ctiller): add a timeout here */
void grpc_resolve_address(const char *addr, const char *default_port, extern void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *addr,
const char *default_port,
grpc_resolve_cb cb, void *arg); grpc_resolve_cb cb, void *arg);
/* Destroy resolved addresses */ /* Destroy resolved addresses */
void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses); void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);

@ -164,8 +164,9 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
gpr_free(addrs); gpr_free(addrs);
} }
void grpc_resolve_address(const char *name, const char *default_port, static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
grpc_resolve_cb cb, void *arg) { const char *default_port, grpc_resolve_cb cb,
void *arg) {
request *r = gpr_malloc(sizeof(request)); request *r = gpr_malloc(sizeof(request));
grpc_closure_init(&r->request_closure, do_request_thread, r); grpc_closure_init(&r->request_closure, do_request_thread, r);
r->name = gpr_strdup(name); r->name = gpr_strdup(name);
@ -175,4 +176,8 @@ void grpc_resolve_address(const char *name, const char *default_port,
grpc_executor_enqueue(&r->request_closure, 1); grpc_executor_enqueue(&r->request_closure, 1);
} }
void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port, grpc_resolve_cb cb,
void *arg) = resolve_address_impl;
#endif #endif

@ -155,8 +155,9 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
gpr_free(addrs); gpr_free(addrs);
} }
void grpc_resolve_address(const char *name, const char *default_port, static void resolve_address_impl(grpc_exec_ctx *exec_ctx, const char *name,
grpc_resolve_cb cb, void *arg) { const char *default_port, grpc_resolve_cb cb,
void *arg) {
request *r = gpr_malloc(sizeof(request)); request *r = gpr_malloc(sizeof(request));
grpc_closure_init(&r->request_closure, do_request_thread, r); grpc_closure_init(&r->request_closure, do_request_thread, r);
r->name = gpr_strdup(name); r->name = gpr_strdup(name);
@ -166,4 +167,8 @@ void grpc_resolve_address(const char *name, const char *default_port,
grpc_executor_enqueue(&r->request_closure, 1); grpc_executor_enqueue(&r->request_closure, 1);
} }
void (*grpc_resolve_address)(grpc_exec_ctx *exec_ctx, const char *name,
const char *default_port, grpc_resolve_cb cb,
void *arg) = resolve_address_impl;
#endif #endif

@ -211,11 +211,11 @@ finish:
grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL); grpc_exec_ctx_enqueue(exec_ctx, closure, *ep != NULL, NULL);
} }
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure, static void tcp_client_connect_impl(grpc_exec_ctx *exec_ctx,
grpc_endpoint **ep, grpc_closure *closure, grpc_endpoint **ep,
grpc_pollset_set *interested_parties, grpc_pollset_set *interested_parties,
const struct sockaddr *addr, size_t addr_len, const struct sockaddr *addr,
gpr_timespec deadline) { size_t addr_len, gpr_timespec deadline) {
int fd; int fd;
grpc_dualstack_mode dsmode; grpc_dualstack_mode dsmode;
int err; int err;
@ -303,4 +303,19 @@ done:
gpr_free(addr_str); gpr_free(addr_str);
} }
// overridden by api_fuzzer.c
void (*grpc_tcp_client_connect_impl)(
grpc_exec_ctx *exec_ctx, grpc_closure *closure, grpc_endpoint **ep,
grpc_pollset_set *interested_parties, const struct sockaddr *addr,
size_t addr_len, gpr_timespec deadline) = tcp_client_connect_impl;
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
grpc_endpoint **ep,
grpc_pollset_set *interested_parties,
const struct sockaddr *addr, size_t addr_len,
gpr_timespec deadline) {
grpc_tcp_client_connect_impl(exec_ctx, closure, ep, interested_parties, addr,
addr_len, deadline);
}
#endif #endif

@ -508,34 +508,6 @@ int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
} }
} }
unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
unsigned port_index) {
grpc_tcp_listener *sp;
for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index)
;
if (sp) {
return 1;
} else {
return 0;
}
}
int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
unsigned fd_index) {
grpc_tcp_listener *sp;
if (fd_index != 0) {
/* Windows implementation has only one fd per port_index. */
return -1;
}
for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index)
;
if (sp) {
return _open_osfhandle((intptr_t)sp->socket->socket, 0);
} else {
return -1;
}
}
void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
grpc_pollset **pollset, size_t pollset_count, grpc_pollset **pollset, size_t pollset_count,
grpc_tcp_server_cb on_accept_cb, grpc_tcp_server_cb on_accept_cb,

@ -35,6 +35,8 @@
#ifdef GPR_WINSOCK_SOCKET #ifdef GPR_WINSOCK_SOCKET
#include <limits.h>
#include "src/core/lib/iomgr/sockaddr_win32.h" #include "src/core/lib/iomgr/sockaddr_win32.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
@ -51,12 +53,20 @@
#include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#if defined(__MSYS__) && defined(GPR_ARCH_64)
/* Nasty workaround for nasty bug when using the 64 bits msys compiler
in conjunction with Microsoft Windows headers. */
#define GRPC_FIONBIO _IOW('f', 126, uint32_t)
#else
#define GRPC_FIONBIO FIONBIO
#endif
static int set_non_block(SOCKET sock) { static int set_non_block(SOCKET sock) {
int status; int status;
unsigned long param = 1; uint32_t param = 1;
DWORD ret; DWORD ret;
status = status = WSAIoctl(sock, GRPC_FIONBIO, &param, sizeof(param), NULL, 0, &ret,
WSAIoctl(sock, FIONBIO, &param, sizeof(param), NULL, 0, &ret, NULL, NULL); NULL, NULL);
return status == 0; return status == 0;
} }

@ -70,6 +70,7 @@ static gpr_clock_type g_clock_type;
static shard_type g_shards[NUM_SHARDS]; static shard_type g_shards[NUM_SHARDS];
/* Protected by g_mu */ /* Protected by g_mu */
static shard_type *g_shard_queue[NUM_SHARDS]; static shard_type *g_shard_queue[NUM_SHARDS];
static bool g_initialized = false;
static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now, static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
gpr_timespec *next, int success); gpr_timespec *next, int success);
@ -83,6 +84,7 @@ static gpr_timespec compute_min_deadline(shard_type *shard) {
void grpc_timer_list_init(gpr_timespec now) { void grpc_timer_list_init(gpr_timespec now) {
uint32_t i; uint32_t i;
g_initialized = true;
gpr_mu_init(&g_mu); gpr_mu_init(&g_mu);
gpr_mu_init(&g_checker_mu); gpr_mu_init(&g_checker_mu);
g_clock_type = now.clock_type; g_clock_type = now.clock_type;
@ -111,6 +113,7 @@ void grpc_timer_list_shutdown(grpc_exec_ctx *exec_ctx) {
} }
gpr_mu_destroy(&g_mu); gpr_mu_destroy(&g_mu);
gpr_mu_destroy(&g_checker_mu); gpr_mu_destroy(&g_checker_mu);
g_initialized = false;
} }
/* This is a cheap, but good enough, pointer hash for sharding the tasks: */ /* This is a cheap, but good enough, pointer hash for sharding the tasks: */
@ -180,6 +183,18 @@ void grpc_timer_init(grpc_exec_ctx *exec_ctx, grpc_timer *timer,
timer->deadline = deadline; timer->deadline = deadline;
timer->triggered = 0; timer->triggered = 0;
if (!g_initialized) {
timer->triggered = 1;
grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, false, NULL);
return;
}
if (gpr_time_cmp(deadline, now) <= 0) {
timer->triggered = 1;
grpc_exec_ctx_enqueue(exec_ctx, &timer->closure, true, NULL);
return;
}
/* TODO(ctiller): check deadline expired */ /* TODO(ctiller): check deadline expired */
gpr_mu_lock(&shard->mu); gpr_mu_lock(&shard->mu);

@ -33,41 +33,47 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_WIN32 #ifdef GPR_WIN32_ENV
#include <windows.h>
#include "src/core/lib/support/env.h" #include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
#include "src/core/lib/support/string_win32.h"
#ifdef __MINGW32__
errno_t getenv_s(size_t *size_needed, char *buffer, size_t size,
const char *varname);
#else
#include <stdlib.h>
#endif
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
char *gpr_getenv(const char *name) { char *gpr_getenv(const char *name) {
size_t size;
char *result = NULL; char *result = NULL;
errno_t err; DWORD size;
LPTSTR tresult = NULL;
LPTSTR tname = gpr_char_to_tchar(name);
DWORD ret;
err = getenv_s(&size, NULL, 0, name); ret = GetEnvironmentVariable(tname, NULL, 0);
if (err || (size == 0)) return NULL; if (ret == 0) return NULL;
result = gpr_malloc(size); size = ret * (DWORD)sizeof(TCHAR);
err = getenv_s(&size, result, size, name); tresult = gpr_malloc(size);
if (err) { ret = GetEnvironmentVariable(tname, tresult, size);
gpr_free(result); gpr_free(tname);
if (ret == 0) {
gpr_free(tresult);
return NULL; return NULL;
} }
result = gpr_tchar_to_char(tresult);
gpr_free(tresult);
return result; return result;
} }
void gpr_setenv(const char *name, const char *value) { void gpr_setenv(const char *name, const char *value) {
errno_t res = _putenv_s(name, value); LPTSTR tname = gpr_char_to_tchar(name);
GPR_ASSERT(res == 0); LPTSTR tvalue = gpr_char_to_tchar(value);
BOOL res = SetEnvironmentVariable(tname, tvalue);
gpr_free(tname);
gpr_free(tvalue);
GPR_ASSERT(res);
} }
#endif /* GPR_WIN32 */ #endif /* GPR_WIN32_ENV */

@ -41,7 +41,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_LINUX #ifdef GPR_LINUX_LOG
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
@ -103,4 +103,4 @@ void gpr_default_log(gpr_log_func_args *args) {
gpr_free(prefix); gpr_free(prefix);
} }
#endif #endif /* GPR_LINUX_LOG */

@ -33,7 +33,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_WIN32 #ifdef GPR_WIN32_LOG
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
@ -109,18 +109,4 @@ void gpr_default_log(gpr_log_func_args *args) {
fflush(stderr); fflush(stderr);
} }
char *gpr_format_message(int messageid) { #endif /* GPR_WIN32_LOG */
LPTSTR tmessage;
char *message;
DWORD status = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, (DWORD)messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)(&tmessage), 0, NULL);
if (status == 0) return gpr_strdup("Unable to retrieve error string");
message = gpr_tchar_to_char(tmessage);
LocalFree(tmessage);
return message;
}
#endif /* GPR_WIN32 */

@ -0,0 +1,94 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* Posix code for gpr snprintf support. */
#include <grpc/support/port_platform.h>
#ifdef GPR_WIN32
/* Some platforms (namely msys) need wchar to be included BEFORE
anything else, especially strsafe.h. */
#include <wchar.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <strsafe.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/support/string.h"
#if defined UNICODE || defined _UNICODE
LPTSTR
gpr_char_to_tchar(LPCSTR input) {
LPTSTR ret;
int needed = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0);
if (needed <= 0) return NULL;
ret = gpr_malloc((unsigned)needed * sizeof(TCHAR));
MultiByteToWideChar(CP_UTF8, 0, input, -1, ret, needed);
return ret;
}
LPSTR
gpr_tchar_to_char(LPCTSTR input) {
LPSTR ret;
int needed = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL);
if (needed <= 0) return NULL;
ret = gpr_malloc((unsigned)needed);
WideCharToMultiByte(CP_UTF8, 0, input, -1, ret, needed, NULL, NULL);
return ret;
}
#else
char *gpr_tchar_to_char(LPTSTR input) { return gpr_strdup(input); }
char *gpr_char_to_tchar(LPTSTR input) { return gpr_strdup(input); }
#endif
char *gpr_format_message(int messageid) {
LPTSTR tmessage;
char *message;
DWORD status = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, (DWORD)messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)(&tmessage), 0, NULL);
if (status == 0) return gpr_strdup("Unable to retrieve error string");
message = gpr_tchar_to_char(tmessage);
LocalFree(tmessage);
return message;
}
#endif /* GPR_WIN32 */

@ -31,11 +31,11 @@
* *
*/ */
/* Posix code for gpr snprintf support. */ /* Windows code for gpr snprintf support. */
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_WIN32 #ifdef GPR_WIN32_STRING
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
@ -80,30 +80,4 @@ int gpr_asprintf(char **strp, const char *format, ...) {
return -1; return -1;
} }
#if defined UNICODE || defined _UNICODE #endif /* GPR_WIN32_STRING */
LPTSTR
gpr_char_to_tchar(LPCSTR input) {
LPTSTR ret;
int needed = MultiByteToWideChar(CP_UTF8, 0, input, -1, NULL, 0);
if (needed <= 0) return NULL;
ret = gpr_malloc((unsigned)needed * sizeof(TCHAR));
MultiByteToWideChar(CP_UTF8, 0, input, -1, ret, needed);
return ret;
}
LPSTR
gpr_tchar_to_char(LPCTSTR input) {
LPSTR ret;
int needed = WideCharToMultiByte(CP_UTF8, 0, input, -1, NULL, 0, NULL, NULL);
if (needed <= 0) return NULL;
ret = gpr_malloc((unsigned)needed);
WideCharToMultiByte(CP_UTF8, 0, input, -1, ret, needed, NULL, NULL);
return ret;
}
#else
char *gpr_tchar_to_char(LPTSTR input) { return gpr_strdup(input); }
char *gpr_char_to_tchar(LPTSTR input) { return gpr_strdup(input); }
#endif
#endif /* GPR_WIN32 */

@ -78,7 +78,7 @@ static const clockid_t clockid_for_gpr_clock[] = {CLOCK_MONOTONIC,
void gpr_time_init(void) { gpr_precise_clock_init(); } void gpr_time_init(void) { gpr_precise_clock_init(); }
gpr_timespec gpr_now(gpr_clock_type clock_type) { static gpr_timespec now_impl(gpr_clock_type clock_type) {
struct timespec now; struct timespec now;
GPR_ASSERT(clock_type != GPR_TIMESPAN); GPR_ASSERT(clock_type != GPR_TIMESPAN);
if (clock_type == GPR_CLOCK_PRECISE) { if (clock_type == GPR_CLOCK_PRECISE) {
@ -114,7 +114,7 @@ void gpr_time_init(void) {
g_time_start = mach_absolute_time(); g_time_start = mach_absolute_time();
} }
gpr_timespec gpr_now(gpr_clock_type clock) { static gpr_timespec now_impl(gpr_clock_type clock) {
gpr_timespec now; gpr_timespec now;
struct timeval now_tv; struct timeval now_tv;
double now_dbl; double now_dbl;
@ -142,6 +142,12 @@ gpr_timespec gpr_now(gpr_clock_type clock) {
} }
#endif #endif
gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type) = now_impl;
gpr_timespec gpr_now(gpr_clock_type clock_type) {
return gpr_now_impl(clock_type);
}
void gpr_sleep_until(gpr_timespec until) { void gpr_sleep_until(gpr_timespec until) {
gpr_timespec now; gpr_timespec now;
gpr_timespec delta; gpr_timespec delta;

@ -35,7 +35,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_WIN32 #ifdef GPR_WIN32_TIME
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include <grpc/support/time.h> #include <grpc/support/time.h>
@ -107,4 +107,4 @@ void gpr_sleep_until(gpr_timespec until) {
} }
} }
#endif /* GPR_WIN32 */ #endif /* GPR_WIN32_TIME */

@ -0,0 +1,73 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/support/port_platform.h>
#ifdef GPR_MSYS_TMPFILE
#include <io.h>
#include <stdio.h>
#include <string.h>
#include <tchar.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/support/string_win32.h"
#include "src/core/lib/support/tmpfile.h"
FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) {
FILE *result = NULL;
char tmp_filename[MAX_PATH];
UINT success;
if (tmp_filename_out != NULL) *tmp_filename_out = NULL;
/* Generate a unique filename with our template + temporary path. */
success = GetTempFileNameA(".", prefix, 0, tmp_filename);
fprintf(stderr, "success = %d\n", success);
if (success) {
/* Open a file there. */
result = fopen(tmp_filename, "wb+");
fprintf(stderr, "result = %p\n", result);
}
if (result != NULL && tmp_filename_out) {
*tmp_filename_out = gpr_strdup(tmp_filename);
}
return result;
}
#endif /* GPR_MSYS_TMPFILE */

@ -33,7 +33,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_FILE #ifdef GPR_POSIX_TMPFILE
#include "src/core/lib/support/tmpfile.h" #include "src/core/lib/support/tmpfile.h"
@ -82,4 +82,4 @@ end:
return result; return result;
} }
#endif /* GPR_POSIX_FILE */ #endif /* GPR_POSIX_TMPFILE */

@ -33,7 +33,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#ifdef GPR_WIN32 #ifdef GPR_WIN32_TMPFILE
#include <io.h> #include <io.h>
#include <stdio.h> #include <stdio.h>
@ -81,4 +81,4 @@ end:
return result; return result;
} }
#endif /* GPR_WIN32 */ #endif /* GPR_WIN32_TMPFILE */

@ -143,22 +143,23 @@ struct grpc_call {
gpr_mu mu; gpr_mu mu;
/* client or server call */ /* client or server call */
uint8_t is_client; bool is_client;
/* is the alarm set */ /* is the alarm set */
uint8_t have_alarm; bool have_alarm;
/** has grpc_call_destroy been called */ /** has grpc_call_destroy been called */
uint8_t destroy_called; bool destroy_called;
/** flag indicating that cancellation is inherited */ /** flag indicating that cancellation is inherited */
uint8_t cancellation_is_inherited; bool cancellation_is_inherited;
/** bitmask of live batches */ /** bitmask of live batches */
uint8_t used_batches; uint8_t used_batches;
/** which ops are in-flight */ /** which ops are in-flight */
uint8_t sent_initial_metadata; bool sent_initial_metadata;
uint8_t sending_message; bool sending_message;
uint8_t sent_final_op; bool sent_final_op;
uint8_t received_initial_metadata; bool received_initial_metadata;
uint8_t receiving_message; bool receiving_message;
uint8_t received_final_op; bool requested_final_op;
bool received_final_op;
/* have we received initial metadata */ /* have we received initial metadata */
bool has_initial_md_been_received; bool has_initial_md_been_received;
@ -221,10 +222,7 @@ struct grpc_call {
} server; } server;
} final_op; } final_op;
struct { void *saved_receiving_stream_ready_bctlp;
void *bctlp;
bool success;
} saved_receiving_stream_ready_ctx;
}; };
#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) #define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1))
@ -566,21 +564,6 @@ static int prepare_application_metadata(grpc_call *call, int count,
int i; int i;
grpc_metadata_batch *batch = grpc_metadata_batch *batch =
&call->metadata_batch[0 /* is_receiving */][is_trailing]; &call->metadata_batch[0 /* is_receiving */][is_trailing];
if (prepend_extra_metadata) {
if (call->send_extra_metadata_count == 0) {
prepend_extra_metadata = 0;
} else {
for (i = 0; i < call->send_extra_metadata_count; i++) {
GRPC_MDELEM_REF(call->send_extra_metadata[i].md);
}
for (i = 1; i < call->send_extra_metadata_count; i++) {
call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1];
}
for (i = 0; i < call->send_extra_metadata_count - 1; i++) {
call->send_extra_metadata[i].next = &call->send_extra_metadata[i + 1];
}
}
}
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
grpc_metadata *md = &metadata[i]; grpc_metadata *md = &metadata[i];
grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data; grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
@ -591,15 +574,38 @@ static int prepare_application_metadata(grpc_call *call, int count,
GRPC_MDSTR_LENGTH(l->md->key))) { GRPC_MDSTR_LENGTH(l->md->key))) {
gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s", gpr_log(GPR_ERROR, "attempt to send invalid metadata key: %s",
grpc_mdstr_as_c_string(l->md->key)); grpc_mdstr_as_c_string(l->md->key));
return 0; break;
} else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key), } else if (!grpc_is_binary_header(grpc_mdstr_as_c_string(l->md->key),
GRPC_MDSTR_LENGTH(l->md->key)) && GRPC_MDSTR_LENGTH(l->md->key)) &&
!grpc_header_nonbin_value_is_legal( !grpc_header_nonbin_value_is_legal(
grpc_mdstr_as_c_string(l->md->value), grpc_mdstr_as_c_string(l->md->value),
GRPC_MDSTR_LENGTH(l->md->value))) { GRPC_MDSTR_LENGTH(l->md->value))) {
gpr_log(GPR_ERROR, "attempt to send invalid metadata value"); gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
break;
}
}
if (i != count) {
for (int j = 0; j <= i; j++) {
grpc_metadata *md = &metadata[j];
grpc_linked_mdelem *l = (grpc_linked_mdelem *)&md->internal_data;
GRPC_MDELEM_UNREF(l->md);
}
return 0; return 0;
} }
if (prepend_extra_metadata) {
if (call->send_extra_metadata_count == 0) {
prepend_extra_metadata = 0;
} else {
for (i = 0; i < call->send_extra_metadata_count; i++) {
GRPC_MDELEM_REF(call->send_extra_metadata[i].md);
}
for (i = 1; i < call->send_extra_metadata_count; i++) {
call->send_extra_metadata[i].prev = &call->send_extra_metadata[i - 1];
}
for (i = 0; i < call->send_extra_metadata_count - 1; i++) {
call->send_extra_metadata[i].next = &call->send_extra_metadata[i + 1];
}
}
} }
for (i = 1; i < count; i++) { for (i = 1; i < count; i++) {
linked_from_md(&metadata[i])->prev = linked_from_md(&metadata[i - 1]); linked_from_md(&metadata[i])->prev = linked_from_md(&metadata[i - 1]);
@ -1069,12 +1075,12 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
grpc_call *call = bctl->call; grpc_call *call = bctl->call;
gpr_mu_lock(&bctl->call->mu); gpr_mu_lock(&bctl->call->mu);
if (bctl->call->has_initial_md_been_received) { if (bctl->call->has_initial_md_been_received || !success ||
call->receiving_stream == NULL) {
gpr_mu_unlock(&bctl->call->mu); gpr_mu_unlock(&bctl->call->mu);
process_data_after_md(exec_ctx, bctlp, success); process_data_after_md(exec_ctx, bctlp, success);
} else { } else {
call->saved_receiving_stream_ready_ctx.bctlp = bctlp; call->saved_receiving_stream_ready_bctlp = bctlp;
call->saved_receiving_stream_ready_ctx.success = success;
gpr_mu_unlock(&bctl->call->mu); gpr_mu_unlock(&bctl->call->mu);
} }
} }
@ -1103,13 +1109,11 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
} }
call->has_initial_md_been_received = true; call->has_initial_md_been_received = true;
if (call->saved_receiving_stream_ready_ctx.bctlp != NULL) { if (call->saved_receiving_stream_ready_bctlp != NULL) {
grpc_closure *saved_rsr_closure = grpc_closure_create( grpc_closure *saved_rsr_closure = grpc_closure_create(
receiving_stream_ready, call->saved_receiving_stream_ready_ctx.bctlp); receiving_stream_ready, call->saved_receiving_stream_ready_bctlp);
grpc_exec_ctx_enqueue( call->saved_receiving_stream_ready_bctlp = NULL;
exec_ctx, saved_rsr_closure, grpc_exec_ctx_enqueue(exec_ctx, saved_rsr_closure, success, NULL);
call->saved_receiving_stream_ready_ctx.success && success, NULL);
call->saved_receiving_stream_ready_ctx.bctlp = NULL;
} }
gpr_mu_unlock(&call->mu); gpr_mu_unlock(&call->mu);
@ -1145,6 +1149,7 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, bool success) {
&call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */]; &call->metadata_batch[1 /* is_receiving */][1 /* is_trailing */];
grpc_metadata_batch_filter(md, recv_trailing_filter, call); grpc_metadata_batch_filter(md, recv_trailing_filter, call);
call->received_final_op = true;
if (call->have_alarm) { if (call->have_alarm) {
grpc_timer_cancel(exec_ctx, &call->alarm); grpc_timer_cancel(exec_ctx, &call->alarm);
} }
@ -1389,11 +1394,11 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
error = GRPC_CALL_ERROR_NOT_ON_SERVER; error = GRPC_CALL_ERROR_NOT_ON_SERVER;
goto done_with_error; goto done_with_error;
} }
if (call->received_final_op) { if (call->requested_final_op) {
error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
goto done_with_error; goto done_with_error;
} }
call->received_final_op = 1; call->requested_final_op = 1;
call->buffered_metadata[1] = call->buffered_metadata[1] =
op->data.recv_status_on_client.trailing_metadata; op->data.recv_status_on_client.trailing_metadata;
call->final_op.client.status = op->data.recv_status_on_client.status; call->final_op.client.status = op->data.recv_status_on_client.status;
@ -1416,11 +1421,11 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
error = GRPC_CALL_ERROR_NOT_ON_CLIENT; error = GRPC_CALL_ERROR_NOT_ON_CLIENT;
goto done_with_error; goto done_with_error;
} }
if (call->received_final_op) { if (call->requested_final_op) {
error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; error = GRPC_CALL_ERROR_TOO_MANY_OPERATIONS;
goto done_with_error; goto done_with_error;
} }
call->received_final_op = 1; call->requested_final_op = 1;
call->final_op.server.cancelled = call->final_op.server.cancelled =
op->data.recv_close_on_server.cancelled; op->data.recv_close_on_server.cancelled;
bctl->recv_final_op = 1; bctl->recv_final_op = 1;
@ -1469,7 +1474,7 @@ done_with_error:
call->receiving_message = 0; call->receiving_message = 0;
} }
if (bctl->recv_final_op) { if (bctl->recv_final_op) {
call->received_final_op = 0; call->requested_final_op = 0;
} }
gpr_mu_unlock(&call->mu); gpr_mu_unlock(&call->mu);
goto done; goto done;

@ -99,6 +99,9 @@ static void lame_start_transport_op(grpc_exec_ctx *exec_ctx,
if (op->on_consumed != NULL) { if (op->on_consumed != NULL) {
op->on_consumed->cb(exec_ctx, op->on_consumed->cb_arg, 1); op->on_consumed->cb(exec_ctx, op->on_consumed->cb_arg, 1);
} }
if (op->send_ping != NULL) {
op->send_ping->cb(exec_ctx, op->send_ping->cb_arg, 0);
}
} }
static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, static void init_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,

@ -40,7 +40,7 @@ static int conforms_to(const char *s, size_t len, const uint8_t *legal_bits) {
const char *p = s; const char *p = s;
const char *e = s + len; const char *e = s + len;
for (; p != e; p++) { for (; p != e; p++) {
int idx = *p; int idx = (uint8_t)*p;
int byte = idx / 8; int byte = idx / 8;
int bit = idx % 8; int bit = idx % 8;
if ((legal_bits[byte] & (1 << bit)) == 0) return 0; if ((legal_bits[byte] & (1 << bit)) == 0) return 0;

@ -386,18 +386,26 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
for (s = shard->strs[idx]; s; s = s->bucket_next) { for (s = shard->strs[idx]; s; s = s->bucket_next) {
if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length && if (s->hash == hash && GPR_SLICE_LENGTH(s->slice) == length &&
0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) { 0 == memcmp(buf, GPR_SLICE_START_PTR(s->slice), length)) {
GRPC_MDSTR_REF((grpc_mdstr *)s); if (gpr_atm_full_fetch_add(&s->refcnt, 1) == 0) {
/* If we get here, we've added a ref to something that was about to
* die - drop it immediately.
* The *only* possible path here (given the shard mutex) should be to
* drop from one ref back to zero - assert that with a CAS */
GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0));
/* and treat this as if we were never here... sshhh */
} else {
gpr_mu_unlock(&shard->mu); gpr_mu_unlock(&shard->mu);
GPR_TIMER_END("grpc_mdstr_from_buffer", 0); GPR_TIMER_END("grpc_mdstr_from_buffer", 0);
return (grpc_mdstr *)s; return (grpc_mdstr *)s;
} }
} }
}
/* not found: create a new string */ /* not found: create a new string */
if (length + 1 < GPR_SLICE_INLINED_SIZE) { if (length + 1 < GPR_SLICE_INLINED_SIZE) {
/* string data goes directly into the slice */ /* string data goes directly into the slice */
s = gpr_malloc(sizeof(internal_string)); s = gpr_malloc(sizeof(internal_string));
gpr_atm_rel_store(&s->refcnt, 2); gpr_atm_rel_store(&s->refcnt, 1);
s->slice.refcount = NULL; s->slice.refcount = NULL;
memcpy(s->slice.data.inlined.bytes, buf, length); memcpy(s->slice.data.inlined.bytes, buf, length);
s->slice.data.inlined.bytes[length] = 0; s->slice.data.inlined.bytes[length] = 0;
@ -406,7 +414,7 @@ grpc_mdstr *grpc_mdstr_from_buffer(const uint8_t *buf, size_t length) {
/* string data goes after the internal_string header, and we +1 for null /* string data goes after the internal_string header, and we +1 for null
terminator */ terminator */
s = gpr_malloc(sizeof(internal_string) + length + 1); s = gpr_malloc(sizeof(internal_string) + length + 1);
gpr_atm_rel_store(&s->refcnt, 2); gpr_atm_rel_store(&s->refcnt, 1);
s->refcount.ref = slice_ref; s->refcount.ref = slice_ref;
s->refcount.unref = slice_unref; s->refcount.unref = slice_unref;
s->slice.refcount = &s->refcount; s->slice.refcount = &s->refcount;
@ -675,20 +683,19 @@ const char *grpc_mdstr_as_c_string(grpc_mdstr *s) {
grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) { grpc_mdstr *grpc_mdstr_ref(grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs; internal_string *s = (internal_string *)gs;
if (is_mdstr_static(gs)) return gs; if (is_mdstr_static(gs)) return gs;
GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) != 0); GPR_ASSERT(gpr_atm_full_fetch_add(&s->refcnt, 1) > 0);
return gs; return gs;
} }
void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) { void grpc_mdstr_unref(grpc_mdstr *gs DEBUG_ARGS) {
internal_string *s = (internal_string *)gs; internal_string *s = (internal_string *)gs;
if (is_mdstr_static(gs)) return; if (is_mdstr_static(gs)) return;
if (2 == gpr_atm_full_fetch_add(&s->refcnt, -1)) { if (1 == gpr_atm_full_fetch_add(&s->refcnt, -1)) {
strtab_shard *shard = strtab_shard *shard =
&g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)]; &g_strtab_shard[SHARD_IDX(s->hash, LOG2_STRTAB_SHARD_COUNT)];
gpr_mu_lock(&shard->mu); gpr_mu_lock(&shard->mu);
if (1 == gpr_atm_no_barrier_load(&s->refcnt)) { GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt));
internal_destroy_string(shard, s); internal_destroy_string(shard, s);
}
gpr_mu_unlock(&shard->mu); gpr_mu_unlock(&shard->mu);
} }
} }

@ -120,6 +120,7 @@ void grpc_mdelem_set_user_data(grpc_mdelem *md, void (*destroy_func)(void *),
void *user_data); void *user_data);
/* Reference counting */ /* Reference counting */
//#define GRPC_METADATA_REFCOUNT_DEBUG
#ifdef GRPC_METADATA_REFCOUNT_DEBUG #ifdef GRPC_METADATA_REFCOUNT_DEBUG
#define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__) #define GRPC_MDSTR_REF(s) grpc_mdstr_ref((s), __FILE__, __LINE__)
#define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s), __FILE__, __LINE__) #define GRPC_MDSTR_UNREF(s) grpc_mdstr_unref((s), __FILE__, __LINE__)

@ -33,5 +33,6 @@
using System.Reflection; using System.Reflection;
// The current version of gRPC C#.
[assembly: AssemblyVersion(Grpc.Core.VersionInfo.CurrentAssemblyVersion)] [assembly: AssemblyVersion(Grpc.Core.VersionInfo.CurrentAssemblyVersion)]
[assembly: AssemblyFileVersion(Grpc.Core.VersionInfo.CurrentAssemblyFileVersion)]
[assembly: AssemblyInformationalVersion(Grpc.Core.VersionInfo.CurrentVersion)]

@ -35,13 +35,20 @@ namespace Grpc.Core
{ {
/// <summary> /// <summary>
/// Provides info about current version of gRPC. /// Provides info about current version of gRPC.
/// See https://codingforsmarties.wordpress.com/2016/01/21/how-to-version-assemblies-destined-for-nuget/
/// for rationale about assembly versioning.
/// </summary> /// </summary>
public static class VersionInfo public static class VersionInfo
{ {
/// <summary> /// <summary>
/// Current version of gRPC C# assemblies /// Current <c>AssemblyVersion</c> attribute of gRPC C# assemblies
/// </summary> /// </summary>
public const string CurrentAssemblyVersion = "0.14.0.0"; public const string CurrentAssemblyVersion = "1.0.0.0";
/// <summary>
/// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
/// </summary>
public const string CurrentAssemblyFileVersion = "0.14.0.0";
/// <summary> /// <summary>
/// Current version of gRPC C# /// Current version of gRPC C#

@ -103,7 +103,9 @@ namespace Math {
} }
// client stub // client stub
#pragma warning disable 0618
public class MathClient : ClientBase<MathClient>, IMathClient public class MathClient : ClientBase<MathClient>, IMathClient
#pragma warning restore 0618
{ {
public MathClient(Channel channel) : base(channel) public MathClient(Channel channel) : base(channel)
{ {
@ -166,8 +168,16 @@ namespace Math {
} }
} }
// creates a new client
public static MathClient NewClient(Channel channel)
{
return new MathClient(channel);
}
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(IMath serviceImpl) public static ServerServiceDefinition BindService(IMath serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Div, serviceImpl.Div) .AddMethod(__Method_Div, serviceImpl.Div)
@ -177,7 +187,9 @@ namespace Math {
} }
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(MathBase serviceImpl) public static ServerServiceDefinition BindService(MathBase serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Div, serviceImpl.Div) .AddMethod(__Method_Div, serviceImpl.Div)
@ -186,12 +198,6 @@ namespace Math {
.AddMethod(__Method_Sum, serviceImpl.Sum).Build(); .AddMethod(__Method_Sum, serviceImpl.Sum).Build();
} }
// creates a new client
public static MathClient NewClient(Channel channel)
{
return new MathClient(channel);
}
} }
} }
#endregion #endregion

@ -56,7 +56,9 @@ namespace Grpc.Health.V1 {
} }
// client stub // client stub
#pragma warning disable 0618
public class HealthClient : ClientBase<HealthClient>, IHealthClient public class HealthClient : ClientBase<HealthClient>, IHealthClient
#pragma warning restore 0618
{ {
public HealthClient(Channel channel) : base(channel) public HealthClient(Channel channel) : base(channel)
{ {
@ -95,26 +97,30 @@ namespace Grpc.Health.V1 {
} }
} }
// creates a new client
public static HealthClient NewClient(Channel channel)
{
return new HealthClient(channel);
}
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(IHealth serviceImpl) public static ServerServiceDefinition BindService(IHealth serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Check, serviceImpl.Check).Build(); .AddMethod(__Method_Check, serviceImpl.Check).Build();
} }
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(HealthBase serviceImpl) public static ServerServiceDefinition BindService(HealthBase serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Check, serviceImpl.Check).Build(); .AddMethod(__Method_Check, serviceImpl.Check).Build();
} }
// creates a new client
public static HealthClient NewClient(Channel channel)
{
return new HealthClient(channel);
}
} }
} }
#endregion #endregion

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{ADEBA147-80AE-4710-82E9-5B7F93690266}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Grpc.IntegrationTesting.StressClient</RootNamespace>
<AssemblyName>Grpc.IntegrationTesting.StressClient</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\ReleaseSigned</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Grpc.IntegrationTesting\Grpc.IntegrationTesting.csproj">
<Project>{C61154BA-DD4A-4838-8420-0162A28925E0}</Project>
<Name>Grpc.IntegrationTesting</Name>
</ProjectReference>
</ItemGroup>
</Project>

@ -1,5 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc. // Copyright 2016, Google Inc.
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -28,16 +29,17 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3"; #endregion
package grpc.testing; using System;
// An empty message that you can re-use to avoid defining duplicated empty namespace Grpc.IntegrationTesting.StressClient
// messages in your project. A typical example is to use it as argument or the {
// return value of a service API. For instance: class MainClass
// {
// service Foo { public static void Main(string[] args)
// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; {
// }; StressTestClient.Run(args);
// }
message Empty {} }
}

@ -0,0 +1,11 @@
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Grpc.IntegrationTesting.StressClient")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

@ -113,6 +113,9 @@
<Compile Include="GeneratedClientTest.cs" /> <Compile Include="GeneratedClientTest.cs" />
<Compile Include="InterarrivalTimers.cs" /> <Compile Include="InterarrivalTimers.cs" />
<Compile Include="NUnitMain.cs" /> <Compile Include="NUnitMain.cs" />
<Compile Include="StressTestClient.cs" />
<Compile Include="Metrics.cs" />
<Compile Include="MetricsGrpc.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>

@ -494,7 +494,8 @@ namespace Grpc.IntegrationTesting
} }
var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext()); var ex = Assert.ThrowsAsync<RpcException>(async () => await call.ResponseStream.MoveNext());
Assert.AreEqual(StatusCode.DeadlineExceeded, ex.Status.StatusCode); // We can't guarantee the status code always DeadlineExceeded. See issue #2685.
Assert.Contains(ex.Status.StatusCode, new[] { StatusCode.DeadlineExceeded, StatusCode.Internal });
} }
Console.WriteLine("Passed!"); Console.WriteLine("Passed!");
} }

@ -0,0 +1,452 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: src/proto/grpc/testing/metrics.proto
#pragma warning disable 1591, 0612, 3021
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Grpc.Testing {
/// <summary>Holder for reflection information generated from src/proto/grpc/testing/metrics.proto</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public static partial class MetricsReflection {
#region Descriptor
/// <summary>File descriptor for src/proto/grpc/testing/metrics.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static MetricsReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"CiRzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL21ldHJpY3MucHJvdG8SDGdycGMu",
"dGVzdGluZyJsCg1HYXVnZVJlc3BvbnNlEgwKBG5hbWUYASABKAkSFAoKbG9u",
"Z192YWx1ZRgCIAEoA0gAEhYKDGRvdWJsZV92YWx1ZRgDIAEoAUgAEhYKDHN0",
"cmluZ192YWx1ZRgEIAEoCUgAQgcKBXZhbHVlIhwKDEdhdWdlUmVxdWVzdBIM",
"CgRuYW1lGAEgASgJIg4KDEVtcHR5TWVzc2FnZTKgAQoOTWV0cmljc1NlcnZp",
"Y2USSQoMR2V0QWxsR2F1Z2VzEhouZ3JwYy50ZXN0aW5nLkVtcHR5TWVzc2Fn",
"ZRobLmdycGMudGVzdGluZy5HYXVnZVJlc3BvbnNlMAESQwoIR2V0R2F1Z2US",
"Gi5ncnBjLnRlc3RpbmcuR2F1Z2VSZXF1ZXN0GhsuZ3JwYy50ZXN0aW5nLkdh",
"dWdlUmVzcG9uc2ViBnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] {
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.GaugeResponse), global::Grpc.Testing.GaugeResponse.Parser, new[]{ "Name", "LongValue", "DoubleValue", "StringValue" }, new[]{ "Value" }, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.GaugeRequest), global::Grpc.Testing.GaugeRequest.Parser, new[]{ "Name" }, null, null, null),
new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.EmptyMessage), global::Grpc.Testing.EmptyMessage.Parser, null, null, null, null)
}));
}
#endregion
}
#region Messages
/// <summary>
/// Reponse message containing the gauge name and value
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class GaugeResponse : pb::IMessage<GaugeResponse> {
private static readonly pb::MessageParser<GaugeResponse> _parser = new pb::MessageParser<GaugeResponse>(() => new GaugeResponse());
public static pb::MessageParser<GaugeResponse> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[0]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public GaugeResponse() {
OnConstruction();
}
partial void OnConstruction();
public GaugeResponse(GaugeResponse other) : this() {
name_ = other.name_;
switch (other.ValueCase) {
case ValueOneofCase.LongValue:
LongValue = other.LongValue;
break;
case ValueOneofCase.DoubleValue:
DoubleValue = other.DoubleValue;
break;
case ValueOneofCase.StringValue:
StringValue = other.StringValue;
break;
}
}
public GaugeResponse Clone() {
return new GaugeResponse(this);
}
/// <summary>Field number for the "name" field.</summary>
public const int NameFieldNumber = 1;
private string name_ = "";
public string Name {
get { return name_; }
set {
name_ = pb::Preconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "long_value" field.</summary>
public const int LongValueFieldNumber = 2;
public long LongValue {
get { return valueCase_ == ValueOneofCase.LongValue ? (long) value_ : 0L; }
set {
value_ = value;
valueCase_ = ValueOneofCase.LongValue;
}
}
/// <summary>Field number for the "double_value" field.</summary>
public const int DoubleValueFieldNumber = 3;
public double DoubleValue {
get { return valueCase_ == ValueOneofCase.DoubleValue ? (double) value_ : 0D; }
set {
value_ = value;
valueCase_ = ValueOneofCase.DoubleValue;
}
}
/// <summary>Field number for the "string_value" field.</summary>
public const int StringValueFieldNumber = 4;
public string StringValue {
get { return valueCase_ == ValueOneofCase.StringValue ? (string) value_ : ""; }
set {
value_ = pb::Preconditions.CheckNotNull(value, "value");
valueCase_ = ValueOneofCase.StringValue;
}
}
private object value_;
/// <summary>Enum of possible cases for the "value" oneof.</summary>
public enum ValueOneofCase {
None = 0,
LongValue = 2,
DoubleValue = 3,
StringValue = 4,
}
private ValueOneofCase valueCase_ = ValueOneofCase.None;
public ValueOneofCase ValueCase {
get { return valueCase_; }
}
public void ClearValue() {
valueCase_ = ValueOneofCase.None;
value_ = null;
}
public override bool Equals(object other) {
return Equals(other as GaugeResponse);
}
public bool Equals(GaugeResponse other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Name != other.Name) return false;
if (LongValue != other.LongValue) return false;
if (DoubleValue != other.DoubleValue) return false;
if (StringValue != other.StringValue) return false;
if (ValueCase != other.ValueCase) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (valueCase_ == ValueOneofCase.LongValue) hash ^= LongValue.GetHashCode();
if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= DoubleValue.GetHashCode();
if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode();
hash ^= (int) valueCase_;
return hash;
}
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (Name.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (valueCase_ == ValueOneofCase.LongValue) {
output.WriteRawTag(16);
output.WriteInt64(LongValue);
}
if (valueCase_ == ValueOneofCase.DoubleValue) {
output.WriteRawTag(25);
output.WriteDouble(DoubleValue);
}
if (valueCase_ == ValueOneofCase.StringValue) {
output.WriteRawTag(34);
output.WriteString(StringValue);
}
}
public int CalculateSize() {
int size = 0;
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (valueCase_ == ValueOneofCase.LongValue) {
size += 1 + pb::CodedOutputStream.ComputeInt64Size(LongValue);
}
if (valueCase_ == ValueOneofCase.DoubleValue) {
size += 1 + 8;
}
if (valueCase_ == ValueOneofCase.StringValue) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue);
}
return size;
}
public void MergeFrom(GaugeResponse other) {
if (other == null) {
return;
}
if (other.Name.Length != 0) {
Name = other.Name;
}
switch (other.ValueCase) {
case ValueOneofCase.LongValue:
LongValue = other.LongValue;
break;
case ValueOneofCase.DoubleValue:
DoubleValue = other.DoubleValue;
break;
case ValueOneofCase.StringValue:
StringValue = other.StringValue;
break;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 10: {
Name = input.ReadString();
break;
}
case 16: {
LongValue = input.ReadInt64();
break;
}
case 25: {
DoubleValue = input.ReadDouble();
break;
}
case 34: {
StringValue = input.ReadString();
break;
}
}
}
}
}
/// <summary>
/// Request message containing the gauge name
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class GaugeRequest : pb::IMessage<GaugeRequest> {
private static readonly pb::MessageParser<GaugeRequest> _parser = new pb::MessageParser<GaugeRequest>(() => new GaugeRequest());
public static pb::MessageParser<GaugeRequest> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[1]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public GaugeRequest() {
OnConstruction();
}
partial void OnConstruction();
public GaugeRequest(GaugeRequest other) : this() {
name_ = other.name_;
}
public GaugeRequest Clone() {
return new GaugeRequest(this);
}
/// <summary>Field number for the "name" field.</summary>
public const int NameFieldNumber = 1;
private string name_ = "";
public string Name {
get { return name_; }
set {
name_ = pb::Preconditions.CheckNotNull(value, "value");
}
}
public override bool Equals(object other) {
return Equals(other as GaugeRequest);
}
public bool Equals(GaugeRequest other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Name != other.Name) return false;
return true;
}
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
return hash;
}
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
if (Name.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Name);
}
}
public int CalculateSize() {
int size = 0;
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
return size;
}
public void MergeFrom(GaugeRequest other) {
if (other == null) {
return;
}
if (other.Name.Length != 0) {
Name = other.Name;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
case 10: {
Name = input.ReadString();
break;
}
}
}
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public sealed partial class EmptyMessage : pb::IMessage<EmptyMessage> {
private static readonly pb::MessageParser<EmptyMessage> _parser = new pb::MessageParser<EmptyMessage>(() => new EmptyMessage());
public static pb::MessageParser<EmptyMessage> Parser { get { return _parser; } }
public static pbr::MessageDescriptor Descriptor {
get { return global::Grpc.Testing.MetricsReflection.Descriptor.MessageTypes[2]; }
}
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
public EmptyMessage() {
OnConstruction();
}
partial void OnConstruction();
public EmptyMessage(EmptyMessage other) : this() {
}
public EmptyMessage Clone() {
return new EmptyMessage(this);
}
public override bool Equals(object other) {
return Equals(other as EmptyMessage);
}
public bool Equals(EmptyMessage other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
return true;
}
public override int GetHashCode() {
int hash = 1;
return hash;
}
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
public void WriteTo(pb::CodedOutputStream output) {
}
public int CalculateSize() {
int size = 0;
return size;
}
public void MergeFrom(EmptyMessage other) {
if (other == null) {
return;
}
}
public void MergeFrom(pb::CodedInputStream input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
input.SkipLastField();
break;
}
}
}
}
#endregion
}
#endregion Designer generated code

@ -0,0 +1,152 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: src/proto/grpc/testing/metrics.proto
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
namespace Grpc.Testing {
public static class MetricsService
{
static readonly string __ServiceName = "grpc.testing.MetricsService";
static readonly Marshaller<global::Grpc.Testing.EmptyMessage> __Marshaller_EmptyMessage = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.EmptyMessage.Parser.ParseFrom);
static readonly Marshaller<global::Grpc.Testing.GaugeResponse> __Marshaller_GaugeResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.GaugeResponse.Parser.ParseFrom);
static readonly Marshaller<global::Grpc.Testing.GaugeRequest> __Marshaller_GaugeRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.GaugeRequest.Parser.ParseFrom);
static readonly Method<global::Grpc.Testing.EmptyMessage, global::Grpc.Testing.GaugeResponse> __Method_GetAllGauges = new Method<global::Grpc.Testing.EmptyMessage, global::Grpc.Testing.GaugeResponse>(
MethodType.ServerStreaming,
__ServiceName,
"GetAllGauges",
__Marshaller_EmptyMessage,
__Marshaller_GaugeResponse);
static readonly Method<global::Grpc.Testing.GaugeRequest, global::Grpc.Testing.GaugeResponse> __Method_GetGauge = new Method<global::Grpc.Testing.GaugeRequest, global::Grpc.Testing.GaugeResponse>(
MethodType.Unary,
__ServiceName,
"GetGauge",
__Marshaller_GaugeRequest,
__Marshaller_GaugeResponse);
// service descriptor
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Testing.MetricsReflection.Descriptor.Services[0]; }
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IMetricsServiceClient
{
AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, CallOptions options);
global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, CallOptions options);
AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, CallOptions options);
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IMetricsService
{
Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context);
Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context);
}
// server-side abstract class
public abstract class MetricsServiceBase
{
public virtual Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
#pragma warning disable 0618
public class MetricsServiceClient : ClientBase<MetricsServiceClient>, IMetricsServiceClient
#pragma warning restore 0618
{
public MetricsServiceClient(Channel channel) : base(channel)
{
}
public MetricsServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
}
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected MetricsServiceClient() : base()
{
}
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected MetricsServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
public virtual AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return GetAllGauges(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, CallOptions options)
{
return CallInvoker.AsyncServerStreamingCall(__Method_GetAllGauges, null, options, request);
}
public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return GetGauge(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_GetGauge, null, options, request);
}
public virtual AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return GetGaugeAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_GetGauge, null, options, request);
}
protected override MetricsServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new MetricsServiceClient(configuration);
}
}
// creates a new client
public static MetricsServiceClient NewClient(Channel channel)
{
return new MetricsServiceClient(channel);
}
// creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(IMetricsService serviceImpl)
#pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges)
.AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build();
}
// creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(MetricsServiceBase serviceImpl)
#pragma warning restore 0618
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges)
.AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build();
}
}
}
#endregion

@ -71,7 +71,9 @@ namespace Grpc.Testing {
} }
// client stub // client stub
#pragma warning disable 0618
public class BenchmarkServiceClient : ClientBase<BenchmarkServiceClient>, IBenchmarkServiceClient public class BenchmarkServiceClient : ClientBase<BenchmarkServiceClient>, IBenchmarkServiceClient
#pragma warning restore 0618
{ {
public BenchmarkServiceClient(Channel channel) : base(channel) public BenchmarkServiceClient(Channel channel) : base(channel)
{ {
@ -118,8 +120,16 @@ namespace Grpc.Testing {
} }
} }
// creates a new client
public static BenchmarkServiceClient NewClient(Channel channel)
{
return new BenchmarkServiceClient(channel);
}
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(IBenchmarkService serviceImpl) public static ServerServiceDefinition BindService(IBenchmarkService serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
@ -127,19 +137,15 @@ namespace Grpc.Testing {
} }
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl) public static ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall) .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build(); .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
} }
// creates a new client
public static BenchmarkServiceClient NewClient(Channel channel)
{
return new BenchmarkServiceClient(channel);
}
} }
public static class WorkerService public static class WorkerService
{ {
@ -241,7 +247,9 @@ namespace Grpc.Testing {
} }
// client stub // client stub
#pragma warning disable 0618
public class WorkerServiceClient : ClientBase<WorkerServiceClient>, IWorkerServiceClient public class WorkerServiceClient : ClientBase<WorkerServiceClient>, IWorkerServiceClient
#pragma warning restore 0618
{ {
public WorkerServiceClient(Channel channel) : base(channel) public WorkerServiceClient(Channel channel) : base(channel)
{ {
@ -312,8 +320,16 @@ namespace Grpc.Testing {
} }
} }
// creates a new client
public static WorkerServiceClient NewClient(Channel channel)
{
return new WorkerServiceClient(channel);
}
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(IWorkerService serviceImpl) public static ServerServiceDefinition BindService(IWorkerService serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_RunServer, serviceImpl.RunServer) .AddMethod(__Method_RunServer, serviceImpl.RunServer)
@ -323,7 +339,9 @@ namespace Grpc.Testing {
} }
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(WorkerServiceBase serviceImpl) public static ServerServiceDefinition BindService(WorkerServiceBase serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_RunServer, serviceImpl.RunServer) .AddMethod(__Method_RunServer, serviceImpl.RunServer)
@ -332,12 +350,6 @@ namespace Grpc.Testing {
.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build(); .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
} }
// creates a new client
public static WorkerServiceClient NewClient(Channel channel)
{
return new WorkerServiceClient(channel);
}
} }
} }
#endregion #endregion

@ -0,0 +1,318 @@
#region Copyright notice and license
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using CommandLine;
using CommandLine.Text;
using Grpc.Core;
using Grpc.Core.Logging;
using Grpc.Core.Utils;
using Grpc.Testing;
namespace Grpc.IntegrationTesting
{
public class StressTestClient
{
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<StressTestClient>();
const double SecondsToNanos = 1e9;
private class ClientOptions
{
[Option("server_addresses", DefaultValue = "localhost:8080")]
public string ServerAddresses { get; set; }
[Option("test_cases", DefaultValue = "large_unary:100")]
public string TestCases { get; set; }
[Option("test_duration_secs", DefaultValue = -1)]
public int TestDurationSecs { get; set; }
[Option("num_channels_per_server", DefaultValue = 1)]
public int NumChannelsPerServer { get; set; }
[Option("num_stubs_per_channel", DefaultValue = 1)]
public int NumStubsPerChannel { get; set; }
[Option("metrics_port", DefaultValue = 8081)]
public int MetricsPort { get; set; }
[HelpOption]
public string GetUsage()
{
var help = new HelpText
{
Heading = "gRPC C# stress test client",
AddDashesToOption = true
};
help.AddPreOptionsLine("Usage:");
help.AddOptions(this);
return help;
}
}
ClientOptions options;
List<string> serverAddresses;
Dictionary<string, int> weightedTestCases;
WeightedRandomGenerator testCaseGenerator;
// cancellation will be emitted once test_duration_secs has elapsed.
CancellationTokenSource finishedTokenSource = new CancellationTokenSource();
Histogram histogram = new Histogram(0.01, 60 * SecondsToNanos);
private StressTestClient(ClientOptions options, List<string> serverAddresses, Dictionary<string, int> weightedTestCases)
{
this.options = options;
this.serverAddresses = serverAddresses;
this.weightedTestCases = weightedTestCases;
this.testCaseGenerator = new WeightedRandomGenerator(this.weightedTestCases);
}
public static void Run(string[] args)
{
var options = new ClientOptions();
if (!Parser.Default.ParseArguments(args, options))
{
Environment.Exit(1);
}
GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0);
GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0);
var serverAddresses = options.ServerAddresses.Split(',');
GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address");
var testCases = ParseWeightedTestCases(options.TestCases);
GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case");
var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases);
interopClient.Run().Wait();
}
async Task Run()
{
var metricsServer = new Server()
{
Services = { MetricsService.BindService(new MetricsServiceImpl(histogram)) },
Ports = { { "[::]", options.MetricsPort, ServerCredentials.Insecure } }
};
metricsServer.Start();
if (options.TestDurationSecs >= 0)
{
finishedTokenSource.CancelAfter(TimeSpan.FromSeconds(options.TestDurationSecs));
}
var tasks = new List<Task>();
var channels = new List<Channel>();
foreach (var serverAddress in serverAddresses)
{
for (int i = 0; i < options.NumChannelsPerServer; i++)
{
var channel = new Channel(serverAddress, ChannelCredentials.Insecure);
channels.Add(channel);
for (int j = 0; j < options.NumStubsPerChannel; j++)
{
var client = TestService.NewClient(channel);
var task = Task.Factory.StartNew(() => RunBodyAsync(client).GetAwaiter().GetResult(),
TaskCreationOptions.LongRunning);
tasks.Add(task);
}
}
}
await Task.WhenAll(tasks);
foreach (var channel in channels)
{
await channel.ShutdownAsync();
}
await metricsServer.ShutdownAsync();
}
async Task RunBodyAsync(TestService.TestServiceClient client)
{
Logger.Info("Starting stress test client thread.");
while (!finishedTokenSource.Token.IsCancellationRequested)
{
var testCase = testCaseGenerator.GetNext();
var stopwatch = Stopwatch.StartNew();
await RunTestCaseAsync(client, testCase);
stopwatch.Stop();
histogram.AddObservation(stopwatch.Elapsed.TotalSeconds * SecondsToNanos);
}
Logger.Info("Stress test client thread finished.");
}
async Task RunTestCaseAsync(TestService.TestServiceClient client, string testCase)
{
switch (testCase)
{
case "empty_unary":
InteropClient.RunEmptyUnary(client);
break;
case "large_unary":
InteropClient.RunLargeUnary(client);
break;
case "client_streaming":
await InteropClient.RunClientStreamingAsync(client);
break;
case "server_streaming":
await InteropClient.RunServerStreamingAsync(client);
break;
case "ping_pong":
await InteropClient.RunPingPongAsync(client);
break;
case "empty_stream":
await InteropClient.RunEmptyStreamAsync(client);
break;
case "cancel_after_begin":
await InteropClient.RunCancelAfterBeginAsync(client);
break;
case "cancel_after_first_response":
await InteropClient.RunCancelAfterFirstResponseAsync(client);
break;
case "timeout_on_sleeping_server":
await InteropClient.RunTimeoutOnSleepingServerAsync(client);
break;
case "custom_metadata":
await InteropClient.RunCustomMetadataAsync(client);
break;
case "status_code_and_message":
await InteropClient.RunStatusCodeAndMessageAsync(client);
break;
default:
throw new ArgumentException("Unsupported test case " + testCase);
}
}
static Dictionary<string, int> ParseWeightedTestCases(string weightedTestCases)
{
var result = new Dictionary<string, int>();
foreach (var weightedTestCase in weightedTestCases.Split(','))
{
var parts = weightedTestCase.Split(new char[] {':'}, 2);
GrpcPreconditions.CheckArgument(parts.Length == 2, "Malformed test_cases option.");
result.Add(parts[0], int.Parse(parts[1]));
}
return result;
}
class WeightedRandomGenerator
{
readonly Random random = new Random();
readonly List<Tuple<int, string>> cumulativeSums;
readonly int weightSum;
public WeightedRandomGenerator(Dictionary<string, int> weightedItems)
{
cumulativeSums = new List<Tuple<int, string>>();
weightSum = 0;
foreach (var entry in weightedItems)
{
weightSum += entry.Value;
cumulativeSums.Add(Tuple.Create(weightSum, entry.Key));
}
}
public string GetNext()
{
int rand = random.Next(weightSum);
foreach (var entry in cumulativeSums)
{
if (rand < entry.Item1)
{
return entry.Item2;
}
}
throw new InvalidOperationException("GetNext() failed.");
}
}
class MetricsServiceImpl : MetricsService.MetricsServiceBase
{
const string GaugeName = "csharp_overall_qps";
readonly Histogram histogram;
readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();
public MetricsServiceImpl(Histogram histogram)
{
this.histogram = histogram;
}
public override Task<GaugeResponse> GetGauge(GaugeRequest request, ServerCallContext context)
{
if (request.Name == GaugeName)
{
long qps = GetQpsAndReset();
return Task.FromResult(new GaugeResponse
{
Name = GaugeName,
LongValue = qps
});
}
throw new RpcException(new Status(StatusCode.InvalidArgument, "Gauge does not exist"));
}
public override async Task GetAllGauges(EmptyMessage request, IServerStreamWriter<GaugeResponse> responseStream, ServerCallContext context)
{
long qps = GetQpsAndReset();
var response = new GaugeResponse
{
Name = GaugeName,
LongValue = qps
};
await responseStream.WriteAsync(response);
}
long GetQpsAndReset()
{
var snapshot = histogram.GetSnapshot(true);
var elapsedSnapshot = wallClockStopwatch.GetElapsedSnapshot(true);
return (long) (snapshot.Count / elapsedSnapshot.Seconds);
}
}
}
}

@ -138,7 +138,9 @@ namespace Grpc.Testing {
} }
// client stub // client stub
#pragma warning disable 0618
public class TestServiceClient : ClientBase<TestServiceClient>, ITestServiceClient public class TestServiceClient : ClientBase<TestServiceClient>, ITestServiceClient
#pragma warning restore 0618
{ {
public TestServiceClient(Channel channel) : base(channel) public TestServiceClient(Channel channel) : base(channel)
{ {
@ -225,8 +227,16 @@ namespace Grpc.Testing {
} }
} }
// creates a new client
public static TestServiceClient NewClient(Channel channel)
{
return new TestServiceClient(channel);
}
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(ITestService serviceImpl) public static ServerServiceDefinition BindService(ITestService serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall) .AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
@ -238,7 +248,9 @@ namespace Grpc.Testing {
} }
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(TestServiceBase serviceImpl) public static ServerServiceDefinition BindService(TestServiceBase serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall) .AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
@ -249,12 +261,6 @@ namespace Grpc.Testing {
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build(); .AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
} }
// creates a new client
public static TestServiceClient NewClient(Channel channel)
{
return new TestServiceClient(channel);
}
} }
public static class UnimplementedService public static class UnimplementedService
{ {
@ -303,7 +309,9 @@ namespace Grpc.Testing {
} }
// client stub // client stub
#pragma warning disable 0618
public class UnimplementedServiceClient : ClientBase<UnimplementedServiceClient>, IUnimplementedServiceClient public class UnimplementedServiceClient : ClientBase<UnimplementedServiceClient>, IUnimplementedServiceClient
#pragma warning restore 0618
{ {
public UnimplementedServiceClient(Channel channel) : base(channel) public UnimplementedServiceClient(Channel channel) : base(channel)
{ {
@ -342,26 +350,30 @@ namespace Grpc.Testing {
} }
} }
// creates a new client
public static UnimplementedServiceClient NewClient(Channel channel)
{
return new UnimplementedServiceClient(channel);
}
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(IUnimplementedService serviceImpl) public static ServerServiceDefinition BindService(IUnimplementedService serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
} }
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl) public static ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build(); .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
} }
// creates a new client
public static UnimplementedServiceClient NewClient(Channel channel)
{
return new UnimplementedServiceClient(channel);
}
} }
public static class ReconnectService public static class ReconnectService
{ {
@ -429,7 +441,9 @@ namespace Grpc.Testing {
} }
// client stub // client stub
#pragma warning disable 0618
public class ReconnectServiceClient : ClientBase<ReconnectServiceClient>, IReconnectServiceClient public class ReconnectServiceClient : ClientBase<ReconnectServiceClient>, IReconnectServiceClient
#pragma warning restore 0618
{ {
public ReconnectServiceClient(Channel channel) : base(channel) public ReconnectServiceClient(Channel channel) : base(channel)
{ {
@ -484,8 +498,16 @@ namespace Grpc.Testing {
} }
} }
// creates a new client
public static ReconnectServiceClient NewClient(Channel channel)
{
return new ReconnectServiceClient(channel);
}
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(IReconnectService serviceImpl) public static ServerServiceDefinition BindService(IReconnectService serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Start, serviceImpl.Start) .AddMethod(__Method_Start, serviceImpl.Start)
@ -493,19 +515,15 @@ namespace Grpc.Testing {
} }
// creates service definition that can be registered with a server // creates service definition that can be registered with a server
#pragma warning disable 0618
public static ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl) public static ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl)
#pragma warning restore 0618
{ {
return ServerServiceDefinition.CreateBuilder(__ServiceName) return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Start, serviceImpl.Start) .AddMethod(__Method_Start, serviceImpl.Start)
.AddMethod(__Method_Stop, serviceImpl.Stop).Build(); .AddMethod(__Method_Stop, serviceImpl.Stop).Build();
} }
// creates a new client
public static ReconnectServiceClient NewClient(Channel channel)
{
return new ReconnectServiceClient(channel);
}
} }
} }
#endregion #endregion

@ -34,6 +34,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.HealthCheck.Tests", "G
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.QpsWorker", "Grpc.IntegrationTesting.QpsWorker\Grpc.IntegrationTesting.QpsWorker.csproj", "{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.QpsWorker", "Grpc.IntegrationTesting.QpsWorker\Grpc.IntegrationTesting.QpsWorker.csproj", "{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.csproj", "{ADEBA147-80AE-4710-82E9-5B7F93690266}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -83,6 +85,12 @@ Global
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.Build.0 = Release|Any CPU {AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|Any CPU.Build.0 = Release|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU {AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU {AA5E328A-8835-49D7-98ED-C29F2B3049F0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{ADEBA147-80AE-4710-82E9-5B7F93690266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADEBA147-80AE-4710-82E9-5B7F93690266}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADEBA147-80AE-4710-82E9-5B7F93690266}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADEBA147-80AE-4710-82E9-5B7F93690266}.Release|Any CPU.Build.0 = Release|Any CPU
{ADEBA147-80AE-4710-82E9-5B7F93690266}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
{ADEBA147-80AE-4710-82E9-5B7F93690266}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU {AE21D0EE-9A2C-4C15-AB7F-5224EED5B0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU

@ -8,6 +8,12 @@ cd /d %~dp0
@rem Set VS variables (uses Visual Studio 2013) @rem Set VS variables (uses Visual Studio 2013)
@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86 @call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
@rem Fetch all dependencies
nuget restore ..\..\vsprojects\grpc.sln || goto :error
nuget restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
nuget restore ..\..\vsprojects\grpc_protoc_plugins.sln || goto :error
nuget restore Grpc.sln || goto :error
@rem Build the C# native extension @rem Build the C# native extension
msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Debug /p:PlatformToolset=v120 || goto :error msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Debug /p:PlatformToolset=v120 || goto :error
msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:Configuration=Release /p:PlatformToolset=v120 || goto :error

@ -45,4 +45,4 @@ $PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_D
-I src/proto/grpc/health/v1 src/proto/grpc/health/v1/health.proto -I src/proto/grpc/health/v1 src/proto/grpc/health/v1/health.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \ $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
-I . src/proto/grpc/testing/{control,empty,messages,payloads,services,stats,test}.proto -I . src/proto/grpc/testing/{control,empty,messages,metrics,payloads,services,stats,test}.proto

@ -1,2 +0,0 @@
build
node_modules

@ -1,28 +0,0 @@
{
"bitwise": true,
"curly": true,
"eqeqeq": true,
"esnext": true,
"freeze": true,
"immed": true,
"indent": 2,
"latedef": "nofunc",
"maxlen": 80,
"newcap": true,
"node": true,
"noarg": true,
"quotmark": "single",
"strict": true,
"trailing": true,
"undef": true,
"unused": "vars",
"globals": {
/* Mocha-provided globals */
"describe": false,
"it": false,
"before": false,
"beforeEach": false,
"after": false,
"afterEach": false
}
}

@ -815,8 +815,7 @@ exports.waitForClientReady = function(client, deadline, callback) {
* @return {function(string, Object)} New client constructor * @return {function(string, Object)} New client constructor
*/ */
exports.makeProtobufClientConstructor = function(service, options) { exports.makeProtobufClientConstructor = function(service, options) {
var method_attrs = common.getProtobufServiceAttrs(service, service.name, var method_attrs = common.getProtobufServiceAttrs(service, options);
options);
var deprecatedArgumentOrder = false; var deprecatedArgumentOrder = false;
if (options) { if (options) {
deprecatedArgumentOrder = options.deprecatedArgumentOrder; deprecatedArgumentOrder = options.deprecatedArgumentOrder;

@ -0,0 +1,99 @@
// GENERATED CODE -- DO NOT EDIT!
'use strict';
var grpc = require('grpc');
var math_pb = require('./math_pb.js');
function serialize_DivArgs(arg) {
if (!(arg instanceof math_pb.DivArgs)) {
throw new Error('Expected argument of type DivArgs');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_DivArgs(buffer_arg) {
return math_pb.DivArgs.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_DivReply(arg) {
if (!(arg instanceof math_pb.DivReply)) {
throw new Error('Expected argument of type DivReply');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_DivReply(buffer_arg) {
return math_pb.DivReply.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_FibArgs(arg) {
if (!(arg instanceof math_pb.FibArgs)) {
throw new Error('Expected argument of type FibArgs');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_FibArgs(buffer_arg) {
return math_pb.FibArgs.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_Num(arg) {
if (!(arg instanceof math_pb.Num)) {
throw new Error('Expected argument of type Num');
}
return new Buffer(arg.serializeBinary());
}
function deserialize_Num(buffer_arg) {
return math_pb.Num.deserializeBinary(new Uint8Array(buffer_arg));
}
var MathService = exports.MathService = {
div: {
path: '/math.Math/Div',
requestStream: false,
responseStream: false,
requestType: math_pb.DivArgs,
responseType: math_pb.DivReply,
requestSerialize: serialize_DivArgs,
requestDeserialize: deserialize_DivArgs,
responseSerialize: serialize_DivReply,
responseDeserialize: deserialize_DivReply,
},
divMany: {
path: '/math.Math/DivMany',
requestStream: true,
responseStream: true,
requestType: math_pb.DivArgs,
responseType: math_pb.DivReply,
requestSerialize: serialize_DivArgs,
requestDeserialize: deserialize_DivArgs,
responseSerialize: serialize_DivReply,
responseDeserialize: deserialize_DivReply,
},
fib: {
path: '/math.Math/Fib',
requestStream: false,
responseStream: true,
requestType: math_pb.FibArgs,
responseType: math_pb.Num,
requestSerialize: serialize_FibArgs,
requestDeserialize: deserialize_FibArgs,
responseSerialize: serialize_Num,
responseDeserialize: deserialize_Num,
},
sum: {
path: '/math.Math/Sum',
requestStream: true,
responseStream: false,
requestType: math_pb.Num,
responseType: math_pb.Num,
requestSerialize: serialize_Num,
requestDeserialize: deserialize_Num,
responseSerialize: serialize_Num,
responseDeserialize: deserialize_Num,
},
};
exports.MathClient = grpc.makeGenericClientConstructor(MathService);

@ -0,0 +1,866 @@
/**
* @fileoverview
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();
goog.exportSymbol('proto.math.DivArgs', null, global);
goog.exportSymbol('proto.math.DivReply', null, global);
goog.exportSymbol('proto.math.FibArgs', null, global);
goog.exportSymbol('proto.math.FibReply', null, global);
goog.exportSymbol('proto.math.Num', null, global);
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.math.DivArgs = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.math.DivArgs, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.math.DivArgs.displayName = 'proto.math.DivArgs';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.math.DivArgs.prototype.toObject = function(opt_includeInstance) {
return proto.math.DivArgs.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.math.DivArgs} msg The msg instance to transform.
* @return {!Object}
*/
proto.math.DivArgs.toObject = function(includeInstance, msg) {
var f, obj = {
dividend: msg.getDividend(),
divisor: msg.getDivisor()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.math.DivArgs}
*/
proto.math.DivArgs.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.math.DivArgs;
return proto.math.DivArgs.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.math.DivArgs} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.math.DivArgs}
*/
proto.math.DivArgs.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readInt64());
msg.setDividend(value);
break;
case 2:
var value = /** @type {number} */ (reader.readInt64());
msg.setDivisor(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.math.DivArgs} message
* @param {!jspb.BinaryWriter} writer
*/
proto.math.DivArgs.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.math.DivArgs.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.math.DivArgs.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getDividend();
if (f !== 0) {
writer.writeInt64(
1,
f
);
}
f = this.getDivisor();
if (f !== 0) {
writer.writeInt64(
2,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.math.DivArgs} The clone.
*/
proto.math.DivArgs.prototype.cloneMessage = function() {
return /** @type {!proto.math.DivArgs} */ (jspb.Message.cloneMessage(this));
};
/**
* optional int64 dividend = 1;
* @return {number}
*/
proto.math.DivArgs.prototype.getDividend = function() {
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
};
/** @param {number} value */
proto.math.DivArgs.prototype.setDividend = function(value) {
jspb.Message.setField(this, 1, value);
};
/**
* optional int64 divisor = 2;
* @return {number}
*/
proto.math.DivArgs.prototype.getDivisor = function() {
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0));
};
/** @param {number} value */
proto.math.DivArgs.prototype.setDivisor = function(value) {
jspb.Message.setField(this, 2, value);
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.math.DivReply = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.math.DivReply, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.math.DivReply.displayName = 'proto.math.DivReply';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.math.DivReply.prototype.toObject = function(opt_includeInstance) {
return proto.math.DivReply.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.math.DivReply} msg The msg instance to transform.
* @return {!Object}
*/
proto.math.DivReply.toObject = function(includeInstance, msg) {
var f, obj = {
quotient: msg.getQuotient(),
remainder: msg.getRemainder()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.math.DivReply}
*/
proto.math.DivReply.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.math.DivReply;
return proto.math.DivReply.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.math.DivReply} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.math.DivReply}
*/
proto.math.DivReply.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readInt64());
msg.setQuotient(value);
break;
case 2:
var value = /** @type {number} */ (reader.readInt64());
msg.setRemainder(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.math.DivReply} message
* @param {!jspb.BinaryWriter} writer
*/
proto.math.DivReply.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.math.DivReply.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.math.DivReply.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getQuotient();
if (f !== 0) {
writer.writeInt64(
1,
f
);
}
f = this.getRemainder();
if (f !== 0) {
writer.writeInt64(
2,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.math.DivReply} The clone.
*/
proto.math.DivReply.prototype.cloneMessage = function() {
return /** @type {!proto.math.DivReply} */ (jspb.Message.cloneMessage(this));
};
/**
* optional int64 quotient = 1;
* @return {number}
*/
proto.math.DivReply.prototype.getQuotient = function() {
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
};
/** @param {number} value */
proto.math.DivReply.prototype.setQuotient = function(value) {
jspb.Message.setField(this, 1, value);
};
/**
* optional int64 remainder = 2;
* @return {number}
*/
proto.math.DivReply.prototype.getRemainder = function() {
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 2, 0));
};
/** @param {number} value */
proto.math.DivReply.prototype.setRemainder = function(value) {
jspb.Message.setField(this, 2, value);
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.math.FibArgs = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.math.FibArgs, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.math.FibArgs.displayName = 'proto.math.FibArgs';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.math.FibArgs.prototype.toObject = function(opt_includeInstance) {
return proto.math.FibArgs.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.math.FibArgs} msg The msg instance to transform.
* @return {!Object}
*/
proto.math.FibArgs.toObject = function(includeInstance, msg) {
var f, obj = {
limit: msg.getLimit()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.math.FibArgs}
*/
proto.math.FibArgs.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.math.FibArgs;
return proto.math.FibArgs.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.math.FibArgs} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.math.FibArgs}
*/
proto.math.FibArgs.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readInt64());
msg.setLimit(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.math.FibArgs} message
* @param {!jspb.BinaryWriter} writer
*/
proto.math.FibArgs.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.math.FibArgs.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.math.FibArgs.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getLimit();
if (f !== 0) {
writer.writeInt64(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.math.FibArgs} The clone.
*/
proto.math.FibArgs.prototype.cloneMessage = function() {
return /** @type {!proto.math.FibArgs} */ (jspb.Message.cloneMessage(this));
};
/**
* optional int64 limit = 1;
* @return {number}
*/
proto.math.FibArgs.prototype.getLimit = function() {
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
};
/** @param {number} value */
proto.math.FibArgs.prototype.setLimit = function(value) {
jspb.Message.setField(this, 1, value);
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.math.Num = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.math.Num, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.math.Num.displayName = 'proto.math.Num';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.math.Num.prototype.toObject = function(opt_includeInstance) {
return proto.math.Num.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.math.Num} msg The msg instance to transform.
* @return {!Object}
*/
proto.math.Num.toObject = function(includeInstance, msg) {
var f, obj = {
num: msg.getNum()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.math.Num}
*/
proto.math.Num.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.math.Num;
return proto.math.Num.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.math.Num} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.math.Num}
*/
proto.math.Num.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readInt64());
msg.setNum(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.math.Num} message
* @param {!jspb.BinaryWriter} writer
*/
proto.math.Num.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.math.Num.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.math.Num.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getNum();
if (f !== 0) {
writer.writeInt64(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.math.Num} The clone.
*/
proto.math.Num.prototype.cloneMessage = function() {
return /** @type {!proto.math.Num} */ (jspb.Message.cloneMessage(this));
};
/**
* optional int64 num = 1;
* @return {number}
*/
proto.math.Num.prototype.getNum = function() {
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
};
/** @param {number} value */
proto.math.Num.prototype.setNum = function(value) {
jspb.Message.setField(this, 1, value);
};
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.math.FibReply = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.math.FibReply, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.math.FibReply.displayName = 'proto.math.FibReply';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto suitable for use in Soy templates.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS.
* @param {boolean=} opt_includeInstance Whether to include the JSPB instance
* for transitional soy proto support: http://goto/soy-param-migration
* @return {!Object}
*/
proto.math.FibReply.prototype.toObject = function(opt_includeInstance) {
return proto.math.FibReply.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Whether to include the JSPB
* instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.math.FibReply} msg The msg instance to transform.
* @return {!Object}
*/
proto.math.FibReply.toObject = function(includeInstance, msg) {
var f, obj = {
count: msg.getCount()
};
if (includeInstance) {
obj.$jspbMessageInstance = msg
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.math.FibReply}
*/
proto.math.FibReply.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.math.FibReply;
return proto.math.FibReply.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.math.FibReply} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.math.FibReply}
*/
proto.math.FibReply.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** @type {number} */ (reader.readInt64());
msg.setCount(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Class method variant: serializes the given message to binary data
* (in protobuf wire format), writing to the given BinaryWriter.
* @param {!proto.math.FibReply} message
* @param {!jspb.BinaryWriter} writer
*/
proto.math.FibReply.serializeBinaryToWriter = function(message, writer) {
message.serializeBinaryToWriter(writer);
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.math.FibReply.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
this.serializeBinaryToWriter(writer);
return writer.getResultBuffer();
};
/**
* Serializes the message to binary data (in protobuf wire format),
* writing to the given BinaryWriter.
* @param {!jspb.BinaryWriter} writer
*/
proto.math.FibReply.prototype.serializeBinaryToWriter = function (writer) {
var f = undefined;
f = this.getCount();
if (f !== 0) {
writer.writeInt64(
1,
f
);
}
};
/**
* Creates a deep clone of this proto. No data is shared with the original.
* @return {!proto.math.FibReply} The clone.
*/
proto.math.FibReply.prototype.cloneMessage = function() {
return /** @type {!proto.math.FibReply} */ (jspb.Message.cloneMessage(this));
};
/**
* optional int64 count = 1;
* @return {number}
*/
proto.math.FibReply.prototype.getCount = function() {
return /** @type {number} */ (jspb.Message.getFieldProto3(this, 1, 0));
};
/** @param {number} value */
proto.math.FibReply.prototype.setCount = function(value) {
jspb.Message.setField(this, 1, value);
};
goog.object.extend(exports, proto.math);

@ -34,8 +34,8 @@
'use strict'; 'use strict';
var grpc = require('../..'); var grpc = require('../..');
var math = grpc.load(__dirname + '/../../../proto/math/math.proto').math; var grpcMath = require('./math_grpc_pb');
var math = require('./math_pb');
/** /**
* Server function for division. Provides the /Math/DivMany and /Math/Div * Server function for division. Provides the /Math/DivMany and /Math/Div
@ -46,14 +46,16 @@ var math = grpc.load(__dirname + '/../../../proto/math/math.proto').math;
*/ */
function mathDiv(call, cb) { function mathDiv(call, cb) {
var req = call.request; var req = call.request;
var divisor = req.getDivisor();
var dividend = req.getDividend();
// Unary + is explicit coersion to integer // Unary + is explicit coersion to integer
if (+req.divisor === 0) { if (req.getDivisor() === 0) {
cb(new Error('cannot divide by zero')); cb(new Error('cannot divide by zero'));
} else { } else {
cb(null, { var response = new math.DivReply();
quotient: req.dividend / req.divisor, response.setQuotient(Math.floor(dividend / divisor));
remainder: req.dividend % req.divisor response.setRemainder(dividend % divisor);
}); cb(null, response);
} }
} }
@ -67,7 +69,9 @@ function mathFib(stream) {
// Here, call is a standard writable Node object Stream // Here, call is a standard writable Node object Stream
var previous = 0, current = 1; var previous = 0, current = 1;
for (var i = 0; i < stream.request.limit; i++) { for (var i = 0; i < stream.request.limit; i++) {
stream.write({num: current}); var response = new math.Num();
response.setNum(current);
stream.write(response);
var temp = current; var temp = current;
current += previous; current += previous;
previous = temp; previous = temp;
@ -85,22 +89,26 @@ function mathSum(call, cb) {
// Here, call is a standard readable Node object Stream // Here, call is a standard readable Node object Stream
var sum = 0; var sum = 0;
call.on('data', function(data) { call.on('data', function(data) {
sum += (+data.num); sum += data.getNum();
}); });
call.on('end', function() { call.on('end', function() {
cb(null, {num: sum}); var response = new math.Num();
response.setNum(sum);
cb(null, response);
}); });
} }
function mathDivMany(stream) { function mathDivMany(stream) {
stream.on('data', function(div_args) { stream.on('data', function(div_args) {
if (+div_args.divisor === 0) { var divisor = div_args.getDivisor();
var dividend = div_args.getDividend();
if (divisor === 0) {
stream.emit('error', new Error('cannot divide by zero')); stream.emit('error', new Error('cannot divide by zero'));
} else { } else {
stream.write({ var response = new math.DivReply();
quotient: div_args.dividend / div_args.divisor, response.setQuotient(Math.floor(dividend / divisor));
remainder: div_args.dividend % div_args.divisor response.setRemainder(dividend % divisor);
}); stream.write(response);
} }
}); });
stream.on('end', function() { stream.on('end', function() {
@ -110,7 +118,7 @@ function mathDivMany(stream) {
function getMathServer() { function getMathServer() {
var server = new grpc.Server(); var server = new grpc.Server();
server.addProtoService(math.Math.service, { server.addService(grpcMath.MathService, {
div: mathDiv, div: mathDiv,
fib: mathFib, fib: mathFib,
sum: mathSum, sum: mathSum,

@ -0,0 +1,37 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* This exists solely to allow the generated code to import the grpc module
* without using a relative path */
module.exports = require('../../..');

@ -36,7 +36,8 @@
var assert = require('assert'); var assert = require('assert');
var grpc = require('..'); var grpc = require('..');
var math = grpc.load(__dirname + '/../../proto/math/math.proto').math; var math = require('./math/math_pb');
var MathClient = require('./math/math_grpc_pb').MathClient;
/** /**
* Client to use to make requests to a running server. * Client to use to make requests to a running server.
@ -55,7 +56,7 @@ describe('Math client', function() {
var port_num = server.bind('0.0.0.0:0', var port_num = server.bind('0.0.0.0:0',
grpc.ServerCredentials.createInsecure()); grpc.ServerCredentials.createInsecure());
server.start(); server.start();
math_client = new math.Math('localhost:' + port_num, math_client = new MathClient('localhost:' + port_num,
grpc.credentials.createInsecure()); grpc.credentials.createInsecure());
done(); done();
}); });
@ -63,27 +64,33 @@ describe('Math client', function() {
server.forceShutdown(); server.forceShutdown();
}); });
it('should handle a single request', function(done) { it('should handle a single request', function(done) {
var arg = {dividend: 7, divisor: 4}; var arg = new math.DivArgs();
arg.setDividend(7);
arg.setDivisor(4);
math_client.div(arg, function handleDivResult(err, value) { math_client.div(arg, function handleDivResult(err, value) {
assert.ifError(err); assert.ifError(err);
assert.equal(value.quotient, 1); assert.equal(value.getQuotient(), 1);
assert.equal(value.remainder, 3); assert.equal(value.getRemainder(), 3);
done(); done();
}); });
}); });
it('should handle an error from a unary request', function(done) { it('should handle an error from a unary request', function(done) {
var arg = {dividend: 7, divisor: 0}; var arg = new math.DivArgs();
arg.setDividend(7);
arg.setDivisor(0);
math_client.div(arg, function handleDivResult(err, value) { math_client.div(arg, function handleDivResult(err, value) {
assert(err); assert(err);
done(); done();
}); });
}); });
it('should handle a server streaming request', function(done) { it('should handle a server streaming request', function(done) {
var call = math_client.fib({limit: 7}); var arg = new math.FibArgs();
arg.setLimit(7);
var call = math_client.fib(arg);
var expected_results = [1, 1, 2, 3, 5, 8, 13]; var expected_results = [1, 1, 2, 3, 5, 8, 13];
var next_expected = 0; var next_expected = 0;
call.on('data', function checkResponse(value) { call.on('data', function checkResponse(value) {
assert.equal(value.num, expected_results[next_expected]); assert.equal(value.getNum(), expected_results[next_expected]);
next_expected += 1; next_expected += 1;
}); });
call.on('status', function checkStatus(status) { call.on('status', function checkStatus(status) {
@ -94,10 +101,12 @@ describe('Math client', function() {
it('should handle a client streaming request', function(done) { it('should handle a client streaming request', function(done) {
var call = math_client.sum(function handleSumResult(err, value) { var call = math_client.sum(function handleSumResult(err, value) {
assert.ifError(err); assert.ifError(err);
assert.equal(value.num, 21); assert.equal(value.getNum(), 21);
}); });
for (var i = 0; i < 7; i++) { for (var i = 0; i < 7; i++) {
call.write({'num': i}); var arg = new math.Num();
arg.setNum(i);
call.write(arg);
} }
call.end(); call.end();
call.on('status', function checkStatus(status) { call.on('status', function checkStatus(status) {
@ -107,8 +116,8 @@ describe('Math client', function() {
}); });
it('should handle a bidirectional streaming request', function(done) { it('should handle a bidirectional streaming request', function(done) {
function checkResponse(index, value) { function checkResponse(index, value) {
assert.equal(value.quotient, index); assert.equal(value.getQuotient(), index);
assert.equal(value.remainder, 1); assert.equal(value.getRemainder(), 1);
} }
var call = math_client.divMany(); var call = math_client.divMany();
var response_index = 0; var response_index = 0;
@ -117,7 +126,10 @@ describe('Math client', function() {
response_index += 1; response_index += 1;
}); });
for (var i = 0; i < 7; i++) { for (var i = 0; i < 7; i++) {
call.write({dividend: 2 * i + 1, divisor: 2}); var arg = new math.DivArgs();
arg.setDividend(2 * i + 1);
arg.setDivisor(2);
call.write(arg);
} }
call.end(); call.end();
call.on('status', function checkStatus(status) { call.on('status', function checkStatus(status) {
@ -131,7 +143,10 @@ describe('Math client', function() {
assert.fail(value, undefined, 'Unexpected data response on failing call', assert.fail(value, undefined, 'Unexpected data response on failing call',
'!='); '!=');
}); });
call.write({dividend: 7, divisor: 0}); var arg = new math.DivArgs();
arg.setDividend(7);
arg.setDivisor(0);
call.write(arg);
call.end(); call.end();
call.on('error', function checkStatus(status) { call.on('error', function checkStatus(status) {
done(); done();

@ -0,0 +1,75 @@
// Copyright 2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// File detached comment 1
// File detached comment 2
// File leading comment 1
syntax = "proto3";
// Ignored detached comment
// Ignored package leading comment
package grpc.testing;
message Request {
}
message Response {
}
// ServiceA detached comment 1
// ServiceA detached comment 2
// ServiceA leading comment 1
service ServiceA {
// MethodA1 leading comment 1
rpc MethodA1(Request) returns (Response); // MethodA1 trailing comment 1
// MethodA2 detached leading comment 1
// Method A2 leading comment 1
// Method A2 leading comment 2
rpc MethodA2(stream Request) returns (Response);
// MethodA2 trailing comment 1
}
// Ignored ServiceA trailing comment 1
// ServiceB leading comment 1
service ServiceB {
// ServiceB trailing comment 1
// MethodB1 leading comment 1
rpc MethodB1(Request) returns (Response);
// MethodB1 trailing comment 1
}
// Ignored ServiceB trailing comment 2
// Ignored file trailing comment

@ -0,0 +1 @@
gens/

@ -50,6 +50,9 @@ from setuptools.command import test
import support import support
PYTHON_STEM = os.path.dirname(os.path.abspath(__file__)) PYTHON_STEM = os.path.dirname(os.path.abspath(__file__))
GRPC_STEM = os.path.abspath(PYTHON_STEM + '../../../../')
PROTO_STEM = os.path.join(GRPC_STEM, 'src', 'proto')
PROTO_GEN_STEM = os.path.join(GRPC_STEM, 'src', 'python', 'gens')
CONF_PY_ADDENDUM = """ CONF_PY_ADDENDUM = """
extensions.append('sphinx.ext.napoleon') extensions.append('sphinx.ext.napoleon')
@ -157,31 +160,46 @@ class BuildProtoModules(setuptools.Command):
if not self.grpc_python_plugin_command: if not self.grpc_python_plugin_command:
raise CommandError('could not find grpc_python_plugin ' raise CommandError('could not find grpc_python_plugin '
'(protoc plugin for GRPC Python)') '(protoc plugin for GRPC Python)')
if not os.path.exists(PROTO_GEN_STEM):
os.makedirs(PROTO_GEN_STEM)
include_regex = re.compile(self.include) include_regex = re.compile(self.include)
exclude_regex = re.compile(self.exclude) if self.exclude else None exclude_regex = re.compile(self.exclude) if self.exclude else None
paths = [] paths = []
root_directory = PYTHON_STEM for walk_root, directories, filenames in os.walk(PROTO_STEM):
for walk_root, directories, filenames in os.walk(root_directory):
for filename in filenames: for filename in filenames:
path = os.path.join(walk_root, filename) path = os.path.join(walk_root, filename)
if include_regex.match(path) and not ( if include_regex.match(path) and not (
exclude_regex and exclude_regex.match(path)): exclude_regex and exclude_regex.match(path)):
paths.append(path) paths.append(path)
# TODO(kpayson): It would be nice to do this in a batch command,
# but we currently have name conflicts in src/proto
for path in paths:
command = [ command = [
self.protoc_command, self.protoc_command,
'--plugin=protoc-gen-python-grpc={}'.format( '--plugin=protoc-gen-python-grpc={}'.format(
self.grpc_python_plugin_command), self.grpc_python_plugin_command),
'-I {}'.format(root_directory), '-I {}'.format(GRPC_STEM),
'--python_out={}'.format(root_directory), '--python_out={}'.format(PROTO_GEN_STEM),
'--python-grpc_out={}'.format(root_directory), '--python-grpc_out={}'.format(PROTO_GEN_STEM),
] + paths ] + [path]
try: try:
subprocess.check_output(' '.join(command), cwd=root_directory, shell=True, subprocess.check_output(' '.join(command), cwd=PYTHON_STEM, shell=True,
stderr=subprocess.STDOUT) stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
raise CommandError('Command:\n{}\nMessage:\n{}\nOutput:\n{}'.format( sys.stderr.write(
'warning: Command:\n{}\nMessage:\n{}\nOutput:\n{}'.format(
command, e.message, e.output)) command, e.message, e.output))
# Generated proto directories dont include __init__.py, but
# these are needed for python package resolution
for walk_root, _, _ in os.walk(PROTO_GEN_STEM):
if walk_root != PROTO_GEN_STEM:
path = os.path.join(walk_root, '__init__.py')
open(path, 'a').close()
class BuildProjectMetadata(setuptools.Command): class BuildProjectMetadata(setuptools.Command):
"""Command to generate project metadata in a module.""" """Command to generate project metadata in a module."""

@ -57,6 +57,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/support/stack_lockfree.c', 'src/core/lib/support/stack_lockfree.c',
'src/core/lib/support/string.c', 'src/core/lib/support/string.c',
'src/core/lib/support/string_posix.c', 'src/core/lib/support/string_posix.c',
'src/core/lib/support/string_util_win32.c',
'src/core/lib/support/string_win32.c', 'src/core/lib/support/string_win32.c',
'src/core/lib/support/subprocess_posix.c', 'src/core/lib/support/subprocess_posix.c',
'src/core/lib/support/subprocess_windows.c', 'src/core/lib/support/subprocess_windows.c',
@ -71,6 +72,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/support/time_precise.c', 'src/core/lib/support/time_precise.c',
'src/core/lib/support/time_win32.c', 'src/core/lib/support/time_win32.c',
'src/core/lib/support/tls_pthread.c', 'src/core/lib/support/tls_pthread.c',
'src/core/lib/support/tmpfile_msys.c',
'src/core/lib/support/tmpfile_posix.c', 'src/core/lib/support/tmpfile_posix.c',
'src/core/lib/support/tmpfile_win32.c', 'src/core/lib/support/tmpfile_win32.c',
'src/core/lib/support/wrap_memcpy.c', 'src/core/lib/support/wrap_memcpy.c',

@ -32,11 +32,11 @@
import unittest import unittest
from grpc.beta import implementations from grpc.beta import implementations
from src.proto.grpc.testing import test_pb2
from tests.interop import _interop_test_case from tests.interop import _interop_test_case
from tests.interop import methods from tests.interop import methods
from tests.interop import server from tests.interop import server
from tests.interop import test_pb2
class InsecureInteropTest( class InsecureInteropTest(

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save