Merge branch 'master' into hpack_table

pull/6029/head
Yang Gao 9 years ago
commit db566d2129
  1. 12
      BUILD
  2. 28
      Makefile
  3. 2
      README.md
  4. 2
      binding.gyp
  5. 4
      build.yaml
  6. 2
      config.m4
  7. 6
      gRPC.podspec
  8. 4
      grpc.gemspec
  9. 36
      include/grpc++/impl/codegen/async_stream.h
  10. 12
      include/grpc++/impl/codegen/async_unary_call.h
  11. 7
      include/grpc++/impl/codegen/call.h
  12. 13
      include/grpc++/impl/codegen/client_context.h
  13. 3
      include/grpc++/impl/codegen/client_unary_call.h
  14. 15
      include/grpc++/impl/codegen/method_handler_impl.h
  15. 2
      include/grpc++/impl/codegen/server_context.h
  16. 24
      include/grpc++/impl/codegen/sync_stream.h
  17. 15
      include/grpc/grpc.h
  18. 12
      include/grpc/impl/codegen/grpc_types.h
  19. 4
      package.json
  20. 4
      package.xml
  21. 157
      src/compiler/csharp_generator.cc
  22. 54
      src/core/ext/lb_policy/pick_first/pick_first.c
  23. 46
      src/core/ext/lb_policy/round_robin/round_robin.c
  24. 10
      src/core/ext/resolver/dns/native/dns_resolver.c
  25. 10
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  26. 11
      src/core/ext/resolver/zookeeper/zookeeper_resolver.c
  27. 89
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  28. 101
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  29. 40
      src/core/lib/channel/client_channel.c
  30. 10
      src/core/lib/channel/http_client_filter.c
  31. 5
      src/core/lib/channel/subchannel_call_holder.c
  32. 1
      src/core/lib/channel/subchannel_call_holder.h
  33. 2
      src/core/lib/client_config/README.md
  34. 20
      src/core/lib/client_config/client_channel_factory.c
  35. 51
      src/core/lib/client_config/client_channel_factory.h
  36. 11
      src/core/lib/client_config/lb_policy.c
  37. 13
      src/core/lib/client_config/lb_policy.h
  38. 4
      src/core/lib/client_config/lb_policy_factory.h
  39. 4
      src/core/lib/client_config/resolver_factory.h
  40. 4
      src/core/lib/client_config/resolver_registry.c
  41. 2
      src/core/lib/client_config/resolver_registry.h
  42. 21
      src/core/lib/client_config/subchannel.c
  43. 2
      src/core/lib/iomgr/ev_poll_and_epoll_posix.c
  44. 2
      src/core/lib/iomgr/ev_posix.c
  45. 2
      src/core/lib/iomgr/ev_posix.h
  46. 10
      src/core/lib/surface/call.c
  47. 2
      src/core/lib/surface/channel.h
  48. 259
      src/core/lib/surface/server.c
  49. 6
      src/core/lib/transport/transport.h
  50. 2
      src/cpp/client/client_context.cc
  51. 18
      src/cpp/server/server.cc
  52. 84
      src/csharp/Grpc.Core/CallInvoker.cs
  53. 161
      src/csharp/Grpc.Core/ClientBase.cs
  54. 112
      src/csharp/Grpc.Core/DefaultCallInvoker.cs
  55. 4
      src/csharp/Grpc.Core/Grpc.Core.csproj
  56. 134
      src/csharp/Grpc.Core/Internal/InterceptingCallInvoker.cs
  57. 75
      src/csharp/Grpc.Core/Internal/UnimplementedCallInvoker.cs
  58. 4
      src/csharp/Grpc.Examples.MathClient/MathClient.cs
  59. 14
      src/csharp/Grpc.Examples/MathExamples.cs
  60. 105
      src/csharp/Grpc.Examples/MathGrpc.cs
  61. 12
      src/csharp/Grpc.Examples/MathServiceImpl.cs
  62. 2
      src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs
  63. 57
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  64. 4
      src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs
  65. 8
      src/csharp/Grpc.IntegrationTesting/BenchmarkServiceImpl.cs
  66. 2
      src/csharp/Grpc.IntegrationTesting/ClientRunners.cs
  67. 106
      src/csharp/Grpc.IntegrationTesting/GeneratedClientTest.cs
  68. 116
      src/csharp/Grpc.IntegrationTesting/GeneratedServiceBaseTest.cs
  69. 3
      src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
  70. 26
      src/csharp/Grpc.IntegrationTesting/InteropClient.cs
  71. 2
      src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
  72. 8
      src/csharp/Grpc.IntegrationTesting/MetadataCredentialsTest.cs
  73. 188
      src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
  74. 4
      src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs
  75. 287
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  76. 16
      src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
  77. 10
      src/csharp/Grpc.IntegrationTesting/WorkerServiceImpl.cs
  78. 2
      src/csharp/grpc.native.csharp/grpc.native.csharp.nuspec
  79. 3
      src/csharp/tests.json
  80. 8
      src/proto/grpc/testing/messages.proto
  81. 4
      src/proto/grpc/testing/test.proto
  82. 2
      src/python/grpcio/grpc/_cython/imports.generated.h
  83. 2
      src/python/grpcio/grpc/beta/implementations.py
  84. 2
      src/python/grpcio/grpc_core_dependencies.py
  85. 2
      src/python/grpcio/tests/interop/_secure_interop_test.py
  86. 2
      src/python/grpcio/tests/interop/client.py
  87. 2
      src/python/grpcio/tests/unit/beta/_beta_features_test.py
  88. 2
      src/python/grpcio/tests/unit/beta/_face_interface_test.py
  89. 2
      src/ruby/ext/grpc/rb_grpc_imports.generated.h
  90. 4
      src/ruby/lib/grpc/generic/rpc_server.rb
  91. 5
      src/ruby/spec/generic/rpc_server_spec.rb
  92. 3
      test/core/bad_client/bad_client.c
  93. 1
      test/core/bad_client/gen_build_yaml.py
  94. 151
      test/core/bad_client/tests/head_of_line_blocking.c
  95. 2
      test/core/bad_ssl/bad_ssl_test.c
  96. 28
      test/core/client_config/resolvers/dns_resolver_connectivity_test.c
  97. 28
      test/core/client_config/resolvers/dns_resolver_test.c
  98. 28
      test/core/client_config/resolvers/sockaddr_resolver_test.c
  99. 4
      test/core/end2end/dualstack_socket_test.c
  100. 2
      test/core/end2end/fixtures/proxy.c
  101. Some files were not shown because too many files have changed in this diff Show More

12
BUILD

@ -198,6 +198,7 @@ cc_library(
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/subchannel_call_holder.h",
"src/core/lib/client_config/client_channel_factory.h",
"src/core/lib/client_config/client_config.h",
"src/core/lib/client_config/connector.h",
"src/core/lib/client_config/initial_connect_string.h",
@ -208,7 +209,6 @@ cc_library(
"src/core/lib/client_config/resolver_factory.h",
"src/core/lib/client_config/resolver_registry.h",
"src/core/lib/client_config/subchannel.h",
"src/core/lib/client_config/subchannel_factory.h",
"src/core/lib/client_config/subchannel_index.h",
"src/core/lib/client_config/uri_parser.h",
"src/core/lib/compression/algorithm_metadata.h",
@ -339,6 +339,7 @@ cc_library(
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/subchannel_call_holder.c",
"src/core/lib/client_config/client_channel_factory.c",
"src/core/lib/client_config/client_config.c",
"src/core/lib/client_config/connector.c",
"src/core/lib/client_config/default_initial_connect_string.c",
@ -350,7 +351,6 @@ cc_library(
"src/core/lib/client_config/resolver_factory.c",
"src/core/lib/client_config/resolver_registry.c",
"src/core/lib/client_config/subchannel.c",
"src/core/lib/client_config/subchannel_factory.c",
"src/core/lib/client_config/subchannel_index.c",
"src/core/lib/client_config/uri_parser.c",
"src/core/lib/compression/compression_algorithm.c",
@ -561,6 +561,7 @@ cc_library(
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/subchannel_call_holder.h",
"src/core/lib/client_config/client_channel_factory.h",
"src/core/lib/client_config/client_config.h",
"src/core/lib/client_config/connector.h",
"src/core/lib/client_config/initial_connect_string.h",
@ -571,7 +572,6 @@ cc_library(
"src/core/lib/client_config/resolver_factory.h",
"src/core/lib/client_config/resolver_registry.h",
"src/core/lib/client_config/subchannel.h",
"src/core/lib/client_config/subchannel_factory.h",
"src/core/lib/client_config/subchannel_index.h",
"src/core/lib/client_config/uri_parser.h",
"src/core/lib/compression/algorithm_metadata.h",
@ -686,6 +686,7 @@ cc_library(
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/subchannel_call_holder.c",
"src/core/lib/client_config/client_channel_factory.c",
"src/core/lib/client_config/client_config.c",
"src/core/lib/client_config/connector.c",
"src/core/lib/client_config/default_initial_connect_string.c",
@ -697,7 +698,6 @@ cc_library(
"src/core/lib/client_config/resolver_factory.c",
"src/core/lib/client_config/resolver_registry.c",
"src/core/lib/client_config/subchannel.c",
"src/core/lib/client_config/subchannel_factory.c",
"src/core/lib/client_config/subchannel_index.c",
"src/core/lib/client_config/uri_parser.c",
"src/core/lib/compression/compression_algorithm.c",
@ -1393,6 +1393,7 @@ objc_library(
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/subchannel_call_holder.c",
"src/core/lib/client_config/client_channel_factory.c",
"src/core/lib/client_config/client_config.c",
"src/core/lib/client_config/connector.c",
"src/core/lib/client_config/default_initial_connect_string.c",
@ -1404,7 +1405,6 @@ objc_library(
"src/core/lib/client_config/resolver_factory.c",
"src/core/lib/client_config/resolver_registry.c",
"src/core/lib/client_config/subchannel.c",
"src/core/lib/client_config/subchannel_factory.c",
"src/core/lib/client_config/subchannel_index.c",
"src/core/lib/client_config/uri_parser.c",
"src/core/lib/compression/compression_algorithm.c",
@ -1557,6 +1557,7 @@ objc_library(
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/subchannel_call_holder.h",
"src/core/lib/client_config/client_channel_factory.h",
"src/core/lib/client_config/client_config.h",
"src/core/lib/client_config/connector.h",
"src/core/lib/client_config/initial_connect_string.h",
@ -1567,7 +1568,6 @@ objc_library(
"src/core/lib/client_config/resolver_factory.h",
"src/core/lib/client_config/resolver_registry.h",
"src/core/lib/client_config/subchannel.h",
"src/core/lib/client_config/subchannel_factory.h",
"src/core/lib/client_config/subchannel_index.h",
"src/core/lib/client_config/uri_parser.h",
"src/core/lib/compression/algorithm_metadata.h",

@ -1076,6 +1076,7 @@ boringssl_pqueue_test: $(BINDIR)/$(CONFIG)/boringssl_pqueue_test
boringssl_ssl_test: $(BINDIR)/$(CONFIG)/boringssl_ssl_test
badreq_bad_client_test: $(BINDIR)/$(CONFIG)/badreq_bad_client_test
connection_prefix_bad_client_test: $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test
head_of_line_blocking_bad_client_test: $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test
headers_bad_client_test: $(BINDIR)/$(CONFIG)/headers_bad_client_test
initial_settings_frame_bad_client_test: $(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test
server_registered_method_bad_client_test: $(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test
@ -1298,6 +1299,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/public_headers_must_be_c89 \
$(BINDIR)/$(CONFIG)/badreq_bad_client_test \
$(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test \
$(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test \
$(BINDIR)/$(CONFIG)/headers_bad_client_test \
$(BINDIR)/$(CONFIG)/initial_settings_frame_bad_client_test \
$(BINDIR)/$(CONFIG)/server_registered_method_bad_client_test \
@ -1620,6 +1622,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/badreq_bad_client_test || ( echo test badreq_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing connection_prefix_bad_client_test"
$(Q) $(BINDIR)/$(CONFIG)/connection_prefix_bad_client_test || ( echo test connection_prefix_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing head_of_line_blocking_bad_client_test"
$(Q) $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test || ( echo test head_of_line_blocking_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing headers_bad_client_test"
$(Q) $(BINDIR)/$(CONFIG)/headers_bad_client_test || ( echo test headers_bad_client_test failed ; exit 1 )
$(E) "[RUN] Testing initial_settings_frame_bad_client_test"
@ -2487,6 +2491,7 @@ LIBGRPC_SRC = \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/subchannel_call_holder.c \
src/core/lib/client_config/client_channel_factory.c \
src/core/lib/client_config/client_config.c \
src/core/lib/client_config/connector.c \
src/core/lib/client_config/default_initial_connect_string.c \
@ -2498,7 +2503,6 @@ LIBGRPC_SRC = \
src/core/lib/client_config/resolver_factory.c \
src/core/lib/client_config/resolver_registry.c \
src/core/lib/client_config/subchannel.c \
src/core/lib/client_config/subchannel_factory.c \
src/core/lib/client_config/subchannel_index.c \
src/core/lib/client_config/uri_parser.c \
src/core/lib/compression/compression_algorithm.c \
@ -2844,6 +2848,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/subchannel_call_holder.c \
src/core/lib/client_config/client_channel_factory.c \
src/core/lib/client_config/client_config.c \
src/core/lib/client_config/connector.c \
src/core/lib/client_config/default_initial_connect_string.c \
@ -2855,7 +2860,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/client_config/resolver_factory.c \
src/core/lib/client_config/resolver_registry.c \
src/core/lib/client_config/subchannel.c \
src/core/lib/client_config/subchannel_factory.c \
src/core/lib/client_config/subchannel_index.c \
src/core/lib/client_config/uri_parser.c \
src/core/lib/compression/compression_algorithm.c \
@ -12676,6 +12680,26 @@ ifneq ($(NO_DEPS),true)
endif
HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC = \
test/core/bad_client/tests/head_of_line_blocking.c \
HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_SRC))))
$(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) -o $(BINDIR)/$(CONFIG)/head_of_line_blocking_bad_client_test
$(OBJDIR)/$(CONFIG)/test/core/bad_client/tests/head_of_line_blocking.o: $(LIBDIR)/$(CONFIG)/libbad_client_test.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_head_of_line_blocking_bad_client_test: $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS:.o=.dep)
ifneq ($(NO_DEPS),true)
-include $(HEAD_OF_LINE_BLOCKING_BAD_CLIENT_TEST_OBJS:.o=.dep)
endif
HEADERS_BAD_CLIENT_TEST_SRC = \
test/core/bad_client/tests/headers.c \

@ -5,7 +5,7 @@
[![Join the chat at https://gitter.im/grpc/grpc](https://badges.gitter.im/grpc/grpc.svg)](https://gitter.im/grpc/grpc?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Copyright 2015-2016 Google Inc.
Copyright 2015 Google Inc.
#Documentation

@ -607,6 +607,7 @@
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/channel/subchannel_call_holder.c',
'src/core/lib/client_config/client_channel_factory.c',
'src/core/lib/client_config/client_config.c',
'src/core/lib/client_config/connector.c',
'src/core/lib/client_config/default_initial_connect_string.c',
@ -618,7 +619,6 @@
'src/core/lib/client_config/resolver_factory.c',
'src/core/lib/client_config/resolver_registry.c',
'src/core/lib/client_config/subchannel.c',
'src/core/lib/client_config/subchannel_factory.c',
'src/core/lib/client_config/subchannel_index.c',
'src/core/lib/client_config/uri_parser.c',
'src/core/lib/compression/compression_algorithm.c',

@ -264,6 +264,7 @@ filegroups:
- src/core/lib/channel/http_client_filter.h
- src/core/lib/channel/http_server_filter.h
- src/core/lib/channel/subchannel_call_holder.h
- src/core/lib/client_config/client_channel_factory.h
- src/core/lib/client_config/client_config.h
- src/core/lib/client_config/connector.h
- src/core/lib/client_config/initial_connect_string.h
@ -274,7 +275,6 @@ filegroups:
- src/core/lib/client_config/resolver_factory.h
- src/core/lib/client_config/resolver_registry.h
- src/core/lib/client_config/subchannel.h
- src/core/lib/client_config/subchannel_factory.h
- src/core/lib/client_config/subchannel_index.h
- src/core/lib/client_config/uri_parser.h
- src/core/lib/compression/algorithm_metadata.h
@ -352,6 +352,7 @@ filegroups:
- src/core/lib/channel/http_client_filter.c
- src/core/lib/channel/http_server_filter.c
- src/core/lib/channel/subchannel_call_holder.c
- src/core/lib/client_config/client_channel_factory.c
- src/core/lib/client_config/client_config.c
- src/core/lib/client_config/connector.c
- src/core/lib/client_config/default_initial_connect_string.c
@ -363,7 +364,6 @@ filegroups:
- src/core/lib/client_config/resolver_factory.c
- src/core/lib/client_config/resolver_registry.c
- src/core/lib/client_config/subchannel.c
- src/core/lib/client_config/subchannel_factory.c
- src/core/lib/client_config/subchannel_index.c
- src/core/lib/client_config/uri_parser.c
- src/core/lib/compression/compression_algorithm.c

@ -129,6 +129,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/subchannel_call_holder.c \
src/core/lib/client_config/client_channel_factory.c \
src/core/lib/client_config/client_config.c \
src/core/lib/client_config/connector.c \
src/core/lib/client_config/default_initial_connect_string.c \
@ -140,7 +141,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/client_config/resolver_factory.c \
src/core/lib/client_config/resolver_registry.c \
src/core/lib/client_config/subchannel.c \
src/core/lib/client_config/subchannel_factory.c \
src/core/lib/client_config/subchannel_index.c \
src/core/lib/client_config/uri_parser.c \
src/core/lib/compression/compression_algorithm.c \

@ -200,6 +200,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/http_client_filter.h',
'src/core/lib/channel/http_server_filter.h',
'src/core/lib/channel/subchannel_call_holder.h',
'src/core/lib/client_config/client_channel_factory.h',
'src/core/lib/client_config/client_config.h',
'src/core/lib/client_config/connector.h',
'src/core/lib/client_config/initial_connect_string.h',
@ -210,7 +211,6 @@ Pod::Spec.new do |s|
'src/core/lib/client_config/resolver_factory.h',
'src/core/lib/client_config/resolver_registry.h',
'src/core/lib/client_config/subchannel.h',
'src/core/lib/client_config/subchannel_factory.h',
'src/core/lib/client_config/subchannel_index.h',
'src/core/lib/client_config/uri_parser.h',
'src/core/lib/compression/algorithm_metadata.h',
@ -358,6 +358,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/channel/subchannel_call_holder.c',
'src/core/lib/client_config/client_channel_factory.c',
'src/core/lib/client_config/client_config.c',
'src/core/lib/client_config/connector.c',
'src/core/lib/client_config/default_initial_connect_string.c',
@ -369,7 +370,6 @@ Pod::Spec.new do |s|
'src/core/lib/client_config/resolver_factory.c',
'src/core/lib/client_config/resolver_registry.c',
'src/core/lib/client_config/subchannel.c',
'src/core/lib/client_config/subchannel_factory.c',
'src/core/lib/client_config/subchannel_index.c',
'src/core/lib/client_config/uri_parser.c',
'src/core/lib/compression/compression_algorithm.c',
@ -523,6 +523,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/http_client_filter.h',
'src/core/lib/channel/http_server_filter.h',
'src/core/lib/channel/subchannel_call_holder.h',
'src/core/lib/client_config/client_channel_factory.h',
'src/core/lib/client_config/client_config.h',
'src/core/lib/client_config/connector.h',
'src/core/lib/client_config/initial_connect_string.h',
@ -533,7 +534,6 @@ Pod::Spec.new do |s|
'src/core/lib/client_config/resolver_factory.h',
'src/core/lib/client_config/resolver_registry.h',
'src/core/lib/client_config/subchannel.h',
'src/core/lib/client_config/subchannel_factory.h',
'src/core/lib/client_config/subchannel_index.h',
'src/core/lib/client_config/uri_parser.h',
'src/core/lib/compression/algorithm_metadata.h',

@ -196,6 +196,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/http_client_filter.h )
s.files += %w( src/core/lib/channel/http_server_filter.h )
s.files += %w( src/core/lib/channel/subchannel_call_holder.h )
s.files += %w( src/core/lib/client_config/client_channel_factory.h )
s.files += %w( src/core/lib/client_config/client_config.h )
s.files += %w( src/core/lib/client_config/connector.h )
s.files += %w( src/core/lib/client_config/initial_connect_string.h )
@ -206,7 +207,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/client_config/resolver_factory.h )
s.files += %w( src/core/lib/client_config/resolver_registry.h )
s.files += %w( src/core/lib/client_config/subchannel.h )
s.files += %w( src/core/lib/client_config/subchannel_factory.h )
s.files += %w( src/core/lib/client_config/subchannel_index.h )
s.files += %w( src/core/lib/client_config/uri_parser.h )
s.files += %w( src/core/lib/compression/algorithm_metadata.h )
@ -341,6 +341,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/http_client_filter.c )
s.files += %w( src/core/lib/channel/http_server_filter.c )
s.files += %w( src/core/lib/channel/subchannel_call_holder.c )
s.files += %w( src/core/lib/client_config/client_channel_factory.c )
s.files += %w( src/core/lib/client_config/client_config.c )
s.files += %w( src/core/lib/client_config/connector.c )
s.files += %w( src/core/lib/client_config/default_initial_connect_string.c )
@ -352,7 +353,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/client_config/resolver_factory.c )
s.files += %w( src/core/lib/client_config/resolver_registry.c )
s.files += %w( src/core/lib/client_config/subchannel.c )
s.files += %w( src/core/lib/client_config/subchannel_factory.c )
s.files += %w( src/core/lib/client_config/subchannel_index.c )
s.files += %w( src/core/lib/client_config/uri_parser.c )
s.files += %w( src/core/lib/compression/compression_algorithm.c )

@ -108,7 +108,8 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> {
const W& request, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
init_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
init_ops_.ClientSendClose();
@ -173,7 +174,8 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
finish_ops_.RecvMessage(response);
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
init_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&init_ops_);
}
@ -240,7 +242,8 @@ class ClientAsyncReaderWriter GRPC_FINAL
void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
init_ops_.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&init_ops_);
}
@ -305,7 +308,8 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
@ -319,7 +323,8 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
void Finish(const W& msg, const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
@ -336,7 +341,8 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
GPR_CODEGEN_ASSERT(!status.ok());
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
@ -366,7 +372,8 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
@ -374,7 +381,8 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
write_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
@ -385,7 +393,8 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
void Finish(const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
@ -415,7 +424,8 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
@ -429,7 +439,8 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
write_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
@ -440,7 +451,8 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
void Finish(const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);

@ -67,7 +67,8 @@ class ClientAsyncResponseReader GRPC_FINAL
call_(channel->CreateCall(method, context, cq)),
collection_(new CallOpSetCollection) {
collection_->init_buf_.SetCollection(collection_);
collection_->init_buf_.SendInitialMetadata(context->send_initial_metadata_);
collection_->init_buf_.SendInitialMetadata(
context->send_initial_metadata_, context->initial_metadata_flags());
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(collection_->init_buf_.SendMessage(request).ok());
collection_->init_buf_.ClientSendClose();
@ -122,7 +123,8 @@ class ServerAsyncResponseWriter GRPC_FINAL
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_buf_.set_output_tag(tag);
meta_buf_.SendInitialMetadata(ctx_->initial_metadata_);
meta_buf_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_buf_);
}
@ -130,7 +132,8 @@ class ServerAsyncResponseWriter GRPC_FINAL
void Finish(const W& msg, const Status& status, void* tag) {
finish_buf_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.SendInitialMetadata(ctx_->initial_metadata_);
finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
@ -147,7 +150,8 @@ class ServerAsyncResponseWriter GRPC_FINAL
GPR_CODEGEN_ASSERT(!status.ok());
finish_buf_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.SendInitialMetadata(ctx_->initial_metadata_);
finish_buf_.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
finish_buf_.ServerSendStatus(ctx_->trailing_metadata_, status);

@ -181,8 +181,10 @@ class CallOpSendInitialMetadata {
CallOpSendInitialMetadata() : send_(false) {}
void SendInitialMetadata(
const std::multimap<grpc::string, grpc::string>& metadata) {
const std::multimap<grpc::string, grpc::string>& metadata,
uint32_t flags) {
send_ = true;
flags_ = flags;
initial_metadata_count_ = metadata.size();
initial_metadata_ = FillMetadataArray(metadata);
}
@ -192,7 +194,7 @@ class CallOpSendInitialMetadata {
if (!send_) return;
grpc_op* op = &ops[(*nops)++];
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->flags = 0;
op->flags = flags_;
op->reserved = NULL;
op->data.send_initial_metadata.count = initial_metadata_count_;
op->data.send_initial_metadata.metadata = initial_metadata_;
@ -204,6 +206,7 @@ class CallOpSendInitialMetadata {
}
bool send_;
uint32_t flags_;
size_t initial_metadata_count_;
grpc_metadata* initial_metadata_;
};

@ -221,6 +221,12 @@ class ClientContext {
deadline_ = deadline_tp.raw_time();
}
/// EXPERIMENTAL: Set this request to be idempotent
void set_idempotent(bool idempotent) { idempotent_ = idempotent; }
/// EXPERIMENTAL: Trigger fail-fast or not on this request
void set_fail_fast(bool fail_fast) { fail_fast_ = fail_fast; }
#ifndef GRPC_CXX0X_NO_CHRONO
/// Return the deadline for the client call.
std::chrono::system_clock::time_point deadline() {
@ -328,9 +334,16 @@ class ClientContext {
grpc_call* call() { return call_; }
void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel);
uint32_t initial_metadata_flags() const {
return (idempotent_ ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST : 0) |
(fail_fast_ ? 0 : GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY);
}
grpc::string authority() { return authority_; }
bool initial_metadata_received_;
bool fail_fast_;
bool idempotent_;
std::shared_ptr<Channel> channel_;
grpc::mutex mu_;
grpc_call* call_;

@ -62,7 +62,8 @@ Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
if (!status.ok()) {
return status;
}
ops.SendInitialMetadata(context->send_initial_metadata_);
ops.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
ops.RecvInitialMetadata(context);
ops.RecvMessage(result);
ops.ClientSendClose();

@ -63,7 +63,8 @@ class RpcMethodHandler : public MethodHandler {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus>
ops;
ops.SendInitialMetadata(param.server_context->initial_metadata_);
ops.SendInitialMetadata(param.server_context->initial_metadata_,
param.server_context->initial_metadata_flags());
if (status.ok()) {
status = ops.SendMessage(rsp);
}
@ -100,7 +101,8 @@ class ClientStreamingHandler : public MethodHandler {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus>
ops;
ops.SendInitialMetadata(param.server_context->initial_metadata_);
ops.SendInitialMetadata(param.server_context->initial_metadata_,
param.server_context->initial_metadata_flags());
if (status.ok()) {
status = ops.SendMessage(rsp);
}
@ -138,7 +140,8 @@ class ServerStreamingHandler : public MethodHandler {
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
if (!param.server_context->sent_initial_metadata_) {
ops.SendInitialMetadata(param.server_context->initial_metadata_);
ops.SendInitialMetadata(param.server_context->initial_metadata_,
param.server_context->initial_metadata_flags());
}
ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
param.call->PerformOps(&ops);
@ -170,7 +173,8 @@ class BidiStreamingHandler : public MethodHandler {
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
if (!param.server_context->sent_initial_metadata_) {
ops.SendInitialMetadata(param.server_context->initial_metadata_);
ops.SendInitialMetadata(param.server_context->initial_metadata_,
param.server_context->initial_metadata_flags());
}
ops.ServerSendStatus(param.server_context->trailing_metadata_, status);
param.call->PerformOps(&ops);
@ -191,7 +195,8 @@ class UnknownMethodHandler : public MethodHandler {
static void FillOps(ServerContext* context, T* ops) {
Status status(StatusCode::UNIMPLEMENTED, "");
if (!context->sent_initial_metadata_) {
ops->SendInitialMetadata(context->initial_metadata_);
ops->SendInitialMetadata(context->initial_metadata_,
context->initial_metadata_flags());
context->sent_initial_metadata_ = true;
}
ops->ServerSendStatus(context->trailing_metadata_, status);

@ -195,6 +195,8 @@ class ServerContext {
void set_call(grpc_call* call);
uint32_t initial_metadata_flags() const { return 0; }
CompletionOp* completion_op_;
bool has_notify_when_done_tag_;
void* async_notify_when_done_tag_;

@ -125,7 +125,8 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpClientSendClose>
ops;
ops.SendInitialMetadata(context->send_initial_metadata_);
ops.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
ops.ClientSendClose();
@ -190,7 +191,8 @@ class ClientWriter : public ClientWriterInterface<W> {
finish_ops_.RecvMessage(response);
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(context->send_initial_metadata_);
ops.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&ops);
cq_.Pluck(&ops);
}
@ -268,7 +270,8 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
ClientContext* context)
: context_(context), call_(channel->CreateCall(method, context, &cq_)) {
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(context->send_initial_metadata_);
ops.SendInitialMetadata(context->send_initial_metadata_,
context->initial_metadata_flags());
call_.PerformOps(&ops);
cq_.Pluck(&ops);
}
@ -334,7 +337,8 @@ class ServerReader GRPC_FINAL : public ReaderInterface<R> {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_);
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&ops);
call_->cq()->Pluck(&ops);
@ -361,7 +365,8 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_);
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&ops);
call_->cq()->Pluck(&ops);
@ -374,7 +379,8 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> {
return false;
}
if (!ctx_->sent_initial_metadata_) {
ops.SendInitialMetadata(ctx_->initial_metadata_);
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
call_->PerformOps(&ops);
@ -397,7 +403,8 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>,
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_);
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&ops);
call_->cq()->Pluck(&ops);
@ -417,7 +424,8 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>,
return false;
}
if (!ctx_->sent_initial_metadata_) {
ops.SendInitialMetadata(ctx_->initial_metadata_);
ops.SendInitialMetadata(ctx_->initial_metadata_,
ctx_->initial_metadata_flags());
ctx_->sent_initial_metadata_ = true;
}
call_->PerformOps(&ops);

@ -289,6 +289,14 @@ GRPCAPI grpc_call_error grpc_server_request_call(
grpc_completion_queue *cq_bound_to_call,
grpc_completion_queue *cq_for_notification, void *tag_new);
/** How to handle payloads for a registered method */
typedef enum {
/** Don't try to read the payload */
GRPC_SRM_PAYLOAD_NONE,
/** Read the initial payload as a byte buffer */
GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER
} grpc_server_register_method_payload_handling;
/** Registers a method in the server.
Methods to this (host, method) pair will not be reported by
grpc_server_request_call, but instead be reported by
@ -296,9 +304,10 @@ GRPCAPI grpc_call_error grpc_server_request_call(
registered_method (as returned by this function).
Must be called before grpc_server_start.
Returns NULL on failure. */
GRPCAPI void *grpc_server_register_method(grpc_server *server,
const char *method, const char *host,
uint32_t flags);
GRPCAPI void *grpc_server_register_method(
grpc_server *server, const char *method, const char *host,
grpc_server_register_method_payload_handling payload_handling,
uint32_t flags);
/** Request notification of a new pre-registered call. 'cq_for_notification'
must have been registered to the server via

@ -142,6 +142,8 @@ typedef struct {
/** Secondary user agent: goes at the end of the user-agent metadata
sent on each request */
#define GRPC_ARG_SECONDARY_USER_AGENT_STRING "grpc.secondary_user_agent"
/** The maximum time between subsequent connection attempts, in ms */
#define GRPC_ARG_MAX_RECONNECT_BACKOFF_MS "grpc.max_reconnect_backoff_ms"
/* The caller of the secure_channel_create functions may override the target
name used for SSL host name checking using this channel argument which is of
type GRPC_ARG_STRING. This *should* be used for testing only.
@ -185,7 +187,9 @@ typedef enum grpc_call_error {
server */
GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE,
/** this batch of operations leads to more operations than allowed */
GRPC_CALL_ERROR_BATCH_TOO_BIG
GRPC_CALL_ERROR_BATCH_TOO_BIG,
/** payload type requested is not the type registered */
GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH
} grpc_call_error;
/* Write Flags: */
@ -202,8 +206,12 @@ typedef enum grpc_call_error {
/* Initial metadata flags */
/** Signal that the call is idempotent */
#define GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST (0x00000010u)
/** Signal that the call should not return UNAVAILABLE before it has started */
#define GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY (0x00000020u)
/** Mask of all valid flags */
#define GRPC_INITIAL_METADATA_USED_MASK GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
#define GRPC_INITIAL_METADATA_USED_MASK \
(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST | \
GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY)
/** A single metadata element */
typedef struct grpc_metadata {

@ -139,6 +139,7 @@
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/subchannel_call_holder.h",
"src/core/lib/client_config/client_channel_factory.h",
"src/core/lib/client_config/client_config.h",
"src/core/lib/client_config/connector.h",
"src/core/lib/client_config/initial_connect_string.h",
@ -149,7 +150,6 @@
"src/core/lib/client_config/resolver_factory.h",
"src/core/lib/client_config/resolver_registry.h",
"src/core/lib/client_config/subchannel.h",
"src/core/lib/client_config/subchannel_factory.h",
"src/core/lib/client_config/subchannel_index.h",
"src/core/lib/client_config/uri_parser.h",
"src/core/lib/compression/algorithm_metadata.h",
@ -284,6 +284,7 @@
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/subchannel_call_holder.c",
"src/core/lib/client_config/client_channel_factory.c",
"src/core/lib/client_config/client_config.c",
"src/core/lib/client_config/connector.c",
"src/core/lib/client_config/default_initial_connect_string.c",
@ -295,7 +296,6 @@
"src/core/lib/client_config/resolver_factory.c",
"src/core/lib/client_config/resolver_registry.c",
"src/core/lib/client_config/subchannel.c",
"src/core/lib/client_config/subchannel_factory.c",
"src/core/lib/client_config/subchannel_index.c",
"src/core/lib/client_config/uri_parser.c",
"src/core/lib/compression/compression_algorithm.c",

@ -200,6 +200,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/subchannel_call_holder.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/client_channel_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/client_config.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/connector.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/initial_connect_string.h" role="src" />
@ -210,7 +211,6 @@
<file baseinstalldir="/" name="src/core/lib/client_config/resolver_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/resolver_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/subchannel.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/subchannel_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/subchannel_index.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/uri_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" />
@ -345,6 +345,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/http_client_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/http_server_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/subchannel_call_holder.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/client_channel_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/client_config.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/connector.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/default_initial_connect_string.c" role="src" />
@ -356,7 +357,6 @@
<file baseinstalldir="/" name="src/core/lib/client_config/resolver_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/resolver_registry.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/subchannel.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/subchannel_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/subchannel_index.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/client_config/uri_parser.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/compression_algorithm.c" role="src" />

@ -81,6 +81,10 @@ std::string GetServerInterfaceName(const ServiceDescriptor* service) {
return "I" + service->name();
}
std::string GetServerClassName(const ServiceDescriptor* service) {
return service->name() + "Base";
}
std::string GetCSharpMethodType(MethodType method_type) {
switch (method_type) {
case METHODTYPE_NO_STREAMING:
@ -108,10 +112,14 @@ std::string GetMethodFieldName(const MethodDescriptor *method) {
return "__Method_" + method->name();
}
std::string GetMethodRequestParamMaybe(const MethodDescriptor *method) {
std::string GetMethodRequestParamMaybe(const MethodDescriptor *method,
bool invocation_param=false) {
if (method->client_streaming()) {
return "";
}
if (invocation_param) {
return "request, ";
}
return GetClassName(method->input_type()) + " request, ";
}
@ -242,6 +250,8 @@ void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *se
void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("// client interface\n");
out->Print("[System.Obsolete(\"Client side interfaced will be removed "
"in the next release. Use client class directly.\")]\n");
out->Print("public interface $name$\n", "name",
GetClientInterfaceName(service));
out->Print("{\n");
@ -290,6 +300,8 @@ void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) {
void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("// server-side interface\n");
out->Print("[System.Obsolete(\"Service implementations should inherit"
" from the generated abstract base class instead.\")]\n");
out->Print("public interface $name$\n", "name",
GetServerInterfaceName(service));
out->Print("{\n");
@ -309,21 +321,64 @@ void GenerateServerInterface(Printer* out, const ServiceDescriptor *service) {
out->Print("\n");
}
void GenerateServerClass(Printer* out, const ServiceDescriptor *service) {
out->Print("// server-side abstract class\n");
out->Print("public abstract class $name$\n", "name",
GetServerClassName(service));
out->Print("{\n");
out->Indent();
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
out->Print(
"public virtual $returntype$ $methodname$($request$$response_stream_maybe$, "
"ServerCallContext context)\n",
"methodname", method->name(), "returntype",
GetMethodReturnTypeServer(method), "request",
GetMethodRequestParamServer(method), "response_stream_maybe",
GetMethodResponseStreamMaybe(method));
out->Print("{\n");
out->Indent();
out->Print("throw new RpcException("
"new Status(StatusCode.Unimplemented, \"\"));\n");
out->Outdent();
out->Print("}\n\n");
}
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Print("// client stub\n");
out->Print(
"public class $name$ : ClientBase, $interface$\n",
"name", GetClientClassName(service), "interface",
GetClientInterfaceName(service));
"public class $name$ : ClientBase<$name$>, $interface$\n",
"name", GetClientClassName(service),
"interface", GetClientInterfaceName(service));
out->Print("{\n");
out->Indent();
// constructors
out->Print(
"public $name$(Channel channel) : base(channel)\n",
"name", GetClientClassName(service));
out->Print("public $name$(Channel channel) : base(channel)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("public $name$(CallInvoker callInvoker) : base(callInvoker)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("///<summary>Protected parameterless constructor to allow creation"
" of test doubles.</summary>\n");
out->Print("protected $name$() : base()\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n");
out->Print("///<summary>Protected constructor to allow creation of configured"
" clients.</summary>\n");
out->Print("protected $name$(ClientBaseConfiguration configuration)"
" : base(configuration)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Print("}\n\n");
for (int i = 0; i < service->method_count(); i++) {
const MethodDescriptor *method = service->method(i);
@ -331,30 +386,26 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
if (method_type == METHODTYPE_NO_STREAMING) {
// unary calls have an extra synchronous stub method
out->Print(
"public $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
out->Print("public virtual $response$ $methodname$($request$ request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
"methodfield", GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request);\n");
out->Print("return $methodname$(request, new CallOptions(headers, deadline, cancellationToken));\n",
"methodname", method->name());
out->Outdent();
out->Print("}\n");
// overload taking CallOptions as a param
out->Print(
"public $response$ $methodname$($request$ request, CallOptions options)\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("public virtual $response$ $methodname$($request$ request, CallOptions options)\n",
"methodname", method->name(), "request",
GetClassName(method->input_type()), "response",
GetClassName(method->output_type()));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, options);\n",
out->Print("return CallInvoker.BlockingUnaryCall($methodfield$, null, options, request);\n",
"methodfield", GetMethodFieldName(method));
out->Print("return Calls.BlockingUnaryCall(call, request);\n");
out->Outdent();
out->Print("}\n");
}
@ -364,57 +415,44 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
method_name += "Async"; // prevent name clash with synchronous method.
}
out->Print(
"public $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
"public virtual $returntype$ $methodname$($request_maybe$Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, new CallOptions(headers, deadline, cancellationToken));\n",
"methodfield", GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request);\n");
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call);\n");
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request);\n");
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
}
out->Print("return $methodname$($request_maybe$new CallOptions(headers, deadline, cancellationToken));\n",
"methodname", method_name,
"request_maybe", GetMethodRequestParamMaybe(method, true));
out->Outdent();
out->Print("}\n");
// overload taking CallOptions as a param
out->Print(
"public $returntype$ $methodname$($request_maybe$CallOptions options)\n",
"public virtual $returntype$ $methodname$($request_maybe$CallOptions options)\n",
"methodname", method_name, "request_maybe",
GetMethodRequestParamMaybe(method), "returntype",
GetMethodReturnTypeClient(method));
out->Print("{\n");
out->Indent();
out->Print("var call = CreateCall($methodfield$, options);\n",
"methodfield", GetMethodFieldName(method));
switch (GetMethodType(method)) {
case METHODTYPE_NO_STREAMING:
out->Print("return Calls.AsyncUnaryCall(call, request);\n");
out->Print("return CallInvoker.AsyncUnaryCall($methodfield$, null, options, request);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_CLIENT_STREAMING:
out->Print("return Calls.AsyncClientStreamingCall(call);\n");
out->Print("return CallInvoker.AsyncClientStreamingCall($methodfield$, null, options);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_SERVER_STREAMING:
out->Print(
"return Calls.AsyncServerStreamingCall(call, request);\n");
"return CallInvoker.AsyncServerStreamingCall($methodfield$, null, options, request);\n",
"methodfield", GetMethodFieldName(method));
break;
case METHODTYPE_BIDI_STREAMING:
out->Print("return Calls.AsyncDuplexStreamingCall(call);\n");
out->Print("return CallInvoker.AsyncDuplexStreamingCall($methodfield$, null, options);\n",
"methodfield", GetMethodFieldName(method));
break;
default:
GOOGLE_LOG(FATAL)<< "Can't get here.";
@ -422,17 +460,30 @@ void GenerateClientStub(Printer* out, const ServiceDescriptor *service) {
out->Outdent();
out->Print("}\n");
}
// override NewInstance method
out->Print("protected override $name$ NewInstance(ClientBaseConfiguration configuration)\n",
"name", GetClientClassName(service));
out->Print("{\n");
out->Indent();
out->Print("return new $name$(configuration);\n",
"name", GetClientClassName(service));
out->Outdent();
out->Print("}\n");
out->Outdent();
out->Print("}\n");
out->Print("\n");
}
void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service) {
void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor *service,
bool use_server_class) {
out->Print(
"// creates service definition that can be registered with a server\n");
out->Print(
"public static ServerServiceDefinition BindService($interface$ serviceImpl)\n",
"interface", GetServerInterfaceName(service));
"interface", use_server_class ? GetServerClassName(service) :
GetServerInterfaceName(service));
out->Print("{\n");
out->Indent();
@ -489,8 +540,10 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) {
GenerateServiceDescriptorProperty(out, service);
GenerateClientInterface(out, service);
GenerateServerInterface(out, service);
GenerateServerClass(out, service);
GenerateClientStub(out, service);
GenerateBindServiceMethod(out, service);
GenerateBindServiceMethod(out, service, false);
GenerateBindServiceMethod(out, service, true);
GenerateNewStubMethods(out, service);
out->Outdent();

@ -40,6 +40,7 @@
typedef struct pending_pick {
struct pending_pick *next;
grpc_pollset *pollset;
uint32_t initial_metadata_flags;
grpc_connected_subchannel **target;
grpc_closure *on_complete;
} pending_pick;
@ -149,6 +150,31 @@ static void pf_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
gpr_mu_unlock(&p->mu);
}
static void pf_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
pending_pick *pp;
gpr_mu_lock(&p->mu);
pp = p->pending_picks;
p->pending_picks = NULL;
while (pp != NULL) {
pending_pick *next = pp->next;
if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq) {
grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
pp->pollset);
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
gpr_free(pp);
} else {
pp->next = p->pending_picks;
p->pending_picks = pp;
}
pp = next;
}
gpr_mu_unlock(&p->mu);
}
static void start_picking(grpc_exec_ctx *exec_ctx, pick_first_lb_policy *p) {
p->started_picking = 1;
p->checking_subchannel = 0;
@ -171,6 +197,7 @@ static void pf_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
uint32_t initial_metadata_flags,
grpc_connected_subchannel **target,
grpc_closure *on_complete) {
pick_first_lb_policy *p = (pick_first_lb_policy *)pol;
@ -199,6 +226,7 @@ static int pf_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
pp->next = p->pending_picks;
pp->pollset = pollset;
pp->target = target;
pp->initial_metadata_flags = initial_metadata_flags;
pp->on_complete = on_complete;
p->pending_picks = pp;
gpr_mu_unlock(&p->mu);
@ -286,11 +314,14 @@ static void pf_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
&p->checking_connectivity, &p->connectivity_changed);
break;
case GRPC_CHANNEL_TRANSIENT_FAILURE:
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connecting_transient_failure");
p->checking_subchannel =
(p->checking_subchannel + 1) % p->num_subchannels;
if (p->checking_subchannel == 0) {
/* only trigger transient failure when we've tried all alternatives */
grpc_connectivity_state_set(exec_ctx, &p->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connecting_transient_failure");
}
p->checking_connectivity = grpc_subchannel_check_connectivity(
p->subchannels[p->checking_subchannel]);
if (p->checking_connectivity == GRPC_CHANNEL_TRANSIENT_FAILURE) {
@ -378,14 +409,9 @@ static void pf_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
static const grpc_lb_policy_vtable pick_first_lb_policy_vtable = {
pf_destroy,
pf_shutdown,
pf_pick,
pf_cancel_pick,
pf_ping_one,
pf_exit_idle,
pf_check_connectivity,
pf_notify_on_state_change};
pf_destroy, pf_shutdown, pf_pick,
pf_cancel_pick, pf_cancel_picks, pf_ping_one,
pf_exit_idle, pf_check_connectivity, pf_notify_on_state_change};
static void pick_first_factory_ref(grpc_lb_policy_factory *factory) {}
@ -395,7 +421,7 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
GPR_ASSERT(args->addresses != NULL);
GPR_ASSERT(args->subchannel_factory != NULL);
GPR_ASSERT(args->client_channel_factory != NULL);
if (args->addresses->naddrs == 0) return NULL;
@ -412,8 +438,8 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr);
sc_args.addr_len = (size_t)args->addresses->addrs[i].len;
grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel(
exec_ctx, args->subchannel_factory, &sc_args);
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args);
if (subchannel != NULL) {
p->subchannels[subchannel_idx++] = subchannel;

@ -49,6 +49,7 @@ int grpc_lb_round_robin_trace = 0;
typedef struct pending_pick {
struct pending_pick *next;
grpc_pollset *pollset;
uint32_t initial_metadata_flags;
grpc_connected_subchannel **target;
grpc_closure *on_complete;
} pending_pick;
@ -275,6 +276,32 @@ static void rr_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
gpr_mu_unlock(&p->mu);
}
static void rr_cancel_picks(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
pending_pick *pp;
gpr_mu_lock(&p->mu);
pp = p->pending_picks;
p->pending_picks = NULL;
while (pp != NULL) {
pending_pick *next = pp->next;
if ((pp->initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq) {
grpc_pollset_set_del_pollset(exec_ctx, p->base.interested_parties,
pp->pollset);
*pp->target = NULL;
grpc_exec_ctx_enqueue(exec_ctx, pp->on_complete, false, NULL);
gpr_free(pp);
} else {
pp->next = p->pending_picks;
p->pending_picks = pp;
}
pp = next;
}
gpr_mu_unlock(&p->mu);
}
static void start_picking(grpc_exec_ctx *exec_ctx, round_robin_lb_policy *p) {
size_t i;
p->started_picking = 1;
@ -303,6 +330,7 @@ static void rr_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
uint32_t initial_metadata_flags,
grpc_connected_subchannel **target,
grpc_closure *on_complete) {
round_robin_lb_policy *p = (round_robin_lb_policy *)pol;
@ -330,6 +358,7 @@ static int rr_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
pp->pollset = pollset;
pp->target = target;
pp->on_complete = on_complete;
pp->initial_metadata_flags = initial_metadata_flags;
p->pending_picks = pp;
gpr_mu_unlock(&p->mu);
return 0;
@ -485,14 +514,9 @@ static void rr_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol,
}
static const grpc_lb_policy_vtable round_robin_lb_policy_vtable = {
rr_destroy,
rr_shutdown,
rr_pick,
rr_cancel_pick,
rr_ping_one,
rr_exit_idle,
rr_check_connectivity,
rr_notify_on_state_change};
rr_destroy, rr_shutdown, rr_pick,
rr_cancel_pick, rr_cancel_picks, rr_ping_one,
rr_exit_idle, rr_check_connectivity, rr_notify_on_state_change};
static void round_robin_factory_ref(grpc_lb_policy_factory *factory) {}
@ -502,7 +526,7 @@ static grpc_lb_policy *create_round_robin(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
GPR_ASSERT(args->addresses != NULL);
GPR_ASSERT(args->subchannel_factory != NULL);
GPR_ASSERT(args->client_channel_factory != NULL);
round_robin_lb_policy *p = gpr_malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
@ -518,8 +542,8 @@ static grpc_lb_policy *create_round_robin(grpc_exec_ctx *exec_ctx,
sc_args.addr = (struct sockaddr *)(args->addresses->addrs[i].addr);
sc_args.addr_len = (size_t)args->addresses->addrs[i].len;
grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel(
exec_ctx, args->subchannel_factory, &sc_args);
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args);
if (subchannel != NULL) {
subchannel_data *sd = gpr_malloc(sizeof(*sd));

@ -59,7 +59,7 @@ typedef struct {
/** default port to use */
char *default_port;
/** subchannel factory */
grpc_subchannel_factory *subchannel_factory;
grpc_client_channel_factory *client_channel_factory;
/** load balancing policy name */
char *lb_policy_name;
@ -170,7 +170,7 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
config = grpc_client_config_create();
memset(&lb_policy_args, 0, sizeof(lb_policy_args));
lb_policy_args.addresses = addresses;
lb_policy_args.subchannel_factory = r->subchannel_factory;
lb_policy_args.client_channel_factory = r->client_channel_factory;
lb_policy =
grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
if (lb_policy != NULL) {
@ -228,7 +228,7 @@ static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
if (r->resolved_config) {
grpc_client_config_unref(exec_ctx, r->resolved_config);
}
grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
gpr_free(r->name);
gpr_free(r->default_port);
gpr_free(r->lb_policy_name);
@ -255,10 +255,10 @@ static grpc_resolver *dns_create(grpc_resolver_args *args,
grpc_resolver_init(&r->base, &dns_resolver_vtable);
r->name = gpr_strdup(path);
r->default_port = gpr_strdup(default_port);
r->subchannel_factory = args->subchannel_factory;
r->client_channel_factory = args->client_channel_factory;
gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
grpc_subchannel_factory_ref(r->subchannel_factory);
grpc_client_channel_factory_ref(r->client_channel_factory);
r->lb_policy_name = gpr_strdup(lb_policy_name);
return &r->base;
}

@ -52,7 +52,7 @@ typedef struct {
/** refcount */
gpr_refcount refs;
/** subchannel factory */
grpc_subchannel_factory *subchannel_factory;
grpc_client_channel_factory *client_channel_factory;
/** load balancing policy name */
char *lb_policy_name;
@ -125,7 +125,7 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_args lb_policy_args;
memset(&lb_policy_args, 0, sizeof(lb_policy_args));
lb_policy_args.addresses = r->addresses;
lb_policy_args.subchannel_factory = r->subchannel_factory;
lb_policy_args.client_channel_factory = r->client_channel_factory;
grpc_lb_policy *lb_policy =
grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
grpc_client_config_set_lb_policy(cfg, lb_policy);
@ -140,7 +140,7 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
grpc_resolved_addresses_destroy(r->addresses);
gpr_free(r->lb_policy_name);
gpr_free(r);
@ -318,8 +318,8 @@ static grpc_resolver *sockaddr_create(
gpr_ref_init(&r->refs, 1);
gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
r->subchannel_factory = args->subchannel_factory;
grpc_subchannel_factory_ref(r->subchannel_factory);
r->client_channel_factory = args->client_channel_factory;
grpc_client_channel_factory_ref(r->client_channel_factory);
return &r->base;
}

@ -57,7 +57,7 @@ typedef struct {
/** name to resolve */
char *name;
/** subchannel factory */
grpc_subchannel_factory *subchannel_factory;
grpc_client_channel_factory *client_channel_factory;
/** load balancing policy name */
char *lb_policy_name;
@ -187,9 +187,8 @@ static void zookeeper_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
if (addresses != NULL) {
grpc_lb_policy_args lb_policy_args;
config = grpc_client_config_create();
lb_policy_args.addresses = addresses;
lb_policy_args.subchannel_factory = r->subchannel_factory;
lb_policy_args.client_channel_factory = r->client_channel_factory;
lb_policy =
grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
@ -424,7 +423,7 @@ static void zookeeper_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
if (r->resolved_config != NULL) {
grpc_client_config_unref(exec_ctx, r->resolved_config);
}
grpc_subchannel_factory_unref(exec_ctx, r->subchannel_factory);
grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
gpr_free(r->name);
gpr_free(r->lb_policy_name);
gpr_free(r);
@ -454,8 +453,8 @@ static grpc_resolver *zookeeper_create(grpc_resolver_args *args,
grpc_resolver_init(&r->base, &zookeeper_resolver_vtable);
r->name = gpr_strdup(path);
r->subchannel_factory = args->subchannel_factory;
grpc_subchannel_factory_ref(r->subchannel_factory);
r->client_channel_factory = args->client_channel_factory;
grpc_client_channel_factory_ref(r->client_channel_factory);
r->lb_policy_name = gpr_strdup(lb_policy_name);

@ -136,31 +136,35 @@ static const grpc_connector_vtable connector_vtable = {
connector_ref, connector_unref, connector_shutdown, connector_connect};
typedef struct {
grpc_subchannel_factory base;
grpc_client_channel_factory base;
gpr_refcount refs;
grpc_channel_args *merge_args;
grpc_channel *master;
} subchannel_factory;
} client_channel_factory;
static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
subchannel_factory *f = (subchannel_factory *)scf;
static void client_channel_factory_ref(
grpc_client_channel_factory *cc_factory) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
gpr_ref(&f->refs);
}
static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *scf) {
subchannel_factory *f = (subchannel_factory *)scf;
static void client_channel_factory_unref(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
if (gpr_unref(&f->refs)) {
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
if (f->master != NULL) {
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master,
"client_channel_factory");
}
grpc_channel_args_destroy(f->merge_args);
gpr_free(f);
}
}
static grpc_subchannel *subchannel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
grpc_subchannel_args *args) {
subchannel_factory *f = (subchannel_factory *)scf;
client_channel_factory *f = (client_channel_factory *)cc_factory;
connector *c = gpr_malloc(sizeof(*c));
grpc_channel_args *final_args =
grpc_channel_args_merge(args->args, f->merge_args);
@ -175,9 +179,33 @@ static grpc_subchannel *subchannel_factory_create_subchannel(
return s;
}
static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
subchannel_factory_ref, subchannel_factory_unref,
subchannel_factory_create_subchannel};
static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type,
grpc_channel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
GRPC_CLIENT_CHANNEL, NULL);
grpc_channel_args_destroy(final_args);
grpc_resolver *resolver = grpc_resolver_create(target, &f->base);
if (!resolver) {
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
"client_channel_factory_create_channel");
return NULL;
}
grpc_client_channel_set_resolver(
exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel");
return channel;
}
static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
{client_channel_factory_ref, client_channel_factory_unref,
client_channel_factory_create_subchannel,
client_channel_factory_create_channel};
/* Create a client channel:
Asynchronously: - resolve target
@ -186,38 +214,27 @@ static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
grpc_channel *grpc_insecure_channel_create(const char *target,
const grpc_channel_args *args,
void *reserved) {
grpc_channel *channel = NULL;
grpc_resolver *resolver;
subchannel_factory *f;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_API_TRACE(
"grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3,
(target, args, reserved));
GPR_ASSERT(!reserved);
channel =
grpc_channel_create(&exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
f = gpr_malloc(sizeof(*f));
f->base.vtable = &subchannel_factory_vtable;
client_channel_factory *f = gpr_malloc(sizeof(*f));
memset(f, 0, sizeof(*f));
f->base.vtable = &client_channel_factory_vtable;
gpr_ref_init(&f->refs, 1);
f->merge_args = grpc_channel_args_copy(args);
f->master = channel;
GRPC_CHANNEL_INTERNAL_REF(f->master, "subchannel_factory");
resolver = grpc_resolver_create(target, &f->base);
if (!resolver) {
GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, f->master, "subchannel_factory");
grpc_subchannel_factory_unref(&exec_ctx, &f->base);
grpc_exec_ctx_finish(&exec_ctx);
return NULL;
}
grpc_client_channel_set_resolver(
&exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
grpc_subchannel_factory_unref(&exec_ctx, &f->base);
grpc_channel *channel = client_channel_factory_create_channel(
&exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
if (channel != NULL) {
f->master = channel;
GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_insecure_channel_create");
}
grpc_client_channel_factory_unref(&exec_ctx, &f->base);
grpc_exec_ctx_finish(&exec_ctx);
return channel;
return channel; /* may be NULL */
}

@ -192,34 +192,38 @@ static const grpc_connector_vtable connector_vtable = {
connector_ref, connector_unref, connector_shutdown, connector_connect};
typedef struct {
grpc_subchannel_factory base;
grpc_client_channel_factory base;
gpr_refcount refs;
grpc_channel_args *merge_args;
grpc_channel_security_connector *security_connector;
grpc_channel *master;
} subchannel_factory;
} client_channel_factory;
static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
subchannel_factory *f = (subchannel_factory *)scf;
static void client_channel_factory_ref(
grpc_client_channel_factory *cc_factory) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
gpr_ref(&f->refs);
}
static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *scf) {
subchannel_factory *f = (subchannel_factory *)scf;
static void client_channel_factory_unref(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
if (gpr_unref(&f->refs)) {
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"subchannel_factory");
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
"client_channel_factory");
if (f->master != NULL) {
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master,
"client_channel_factory");
}
grpc_channel_args_destroy(f->merge_args);
gpr_free(f);
}
}
static grpc_subchannel *subchannel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
grpc_subchannel_args *args) {
subchannel_factory *f = (subchannel_factory *)scf;
client_channel_factory *f = (client_channel_factory *)cc_factory;
connector *c = gpr_malloc(sizeof(*c));
grpc_channel_args *final_args =
grpc_channel_args_merge(args->args, f->merge_args);
@ -236,9 +240,37 @@ static grpc_subchannel *subchannel_factory_create_subchannel(
return s;
}
static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
subchannel_factory_ref, subchannel_factory_unref,
subchannel_factory_create_subchannel};
static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type,
grpc_channel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
GRPC_CLIENT_CHANNEL, NULL);
grpc_channel_args_destroy(final_args);
grpc_resolver *resolver = grpc_resolver_create(target, &f->base);
if (resolver != NULL) {
grpc_client_channel_set_resolver(
exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create");
} else {
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
"client_channel_factory_create_channel");
channel = NULL;
}
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"client_channel_factory_create_channel");
return channel;
}
static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
{client_channel_factory_ref, client_channel_factory_unref,
client_channel_factory_create_subchannel,
client_channel_factory_create_channel};
/* Create a secure client channel:
Asynchronously: - resolve target
@ -248,13 +280,11 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
const char *target,
const grpc_channel_args *args,
void *reserved) {
grpc_channel *channel;
grpc_arg connector_arg;
grpc_channel_args *args_copy;
grpc_channel_args *new_args_from_connector;
grpc_channel_security_connector *security_connector;
grpc_resolver *resolver;
subchannel_factory *f;
client_channel_factory *f;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_API_TRACE(
@ -284,35 +314,30 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
new_args_from_connector != NULL ? new_args_from_connector : args,
&connector_arg, 1);
channel = grpc_channel_create(&exec_ctx, target, args_copy,
GRPC_CLIENT_CHANNEL, NULL);
f = gpr_malloc(sizeof(*f));
f->base.vtable = &subchannel_factory_vtable;
memset(f, 0, sizeof(*f));
f->base.vtable = &client_channel_factory_vtable;
gpr_ref_init(&f->refs, 1);
GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory");
f->security_connector = security_connector;
f->merge_args = grpc_channel_args_copy(args_copy);
f->master = channel;
GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory");
resolver = grpc_resolver_create(target, &f->base);
if (resolver) {
grpc_client_channel_set_resolver(
&exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
}
grpc_subchannel_factory_unref(&exec_ctx, &f->base);
GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create");
grpc_channel_args_destroy(args_copy);
if (new_args_from_connector != NULL) {
grpc_channel_args_destroy(new_args_from_connector);
}
if (!resolver) {
GRPC_CHANNEL_INTERNAL_UNREF(&exec_ctx, channel, "subchannel_factory");
channel = NULL;
GRPC_SECURITY_CONNECTOR_REF(&security_connector->base,
"grpc_secure_channel_create");
f->security_connector = security_connector;
grpc_channel *channel = client_channel_factory_create_channel(
&exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
if (channel != NULL) {
f->master = channel;
GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_secure_channel_create");
}
grpc_client_channel_factory_unref(&exec_ctx, &f->base);
grpc_exec_ctx_finish(&exec_ctx);
return channel;
return channel; /* may be NULL */
}

@ -114,6 +114,22 @@ static void watch_lb_policy(grpc_exec_ctx *exec_ctx, channel_data *chand,
grpc_lb_policy *lb_policy,
grpc_connectivity_state current_state);
static void set_channel_connectivity_state_locked(grpc_exec_ctx *exec_ctx,
channel_data *chand,
grpc_connectivity_state state,
const char *reason) {
if ((state == GRPC_CHANNEL_TRANSIENT_FAILURE ||
state == GRPC_CHANNEL_FATAL_FAILURE) &&
chand->lb_policy != NULL) {
/* cancel fail-fast picks */
grpc_lb_policy_cancel_picks(
exec_ctx, chand->lb_policy,
/* mask= */ GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY,
/* check= */ 0);
}
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state, reason);
}
static void on_lb_policy_state_changed_locked(
grpc_exec_ctx *exec_ctx, lb_policy_connectivity_watcher *w) {
grpc_connectivity_state publish_state = w->state;
@ -127,8 +143,8 @@ static void on_lb_policy_state_changed_locked(
GRPC_LB_POLICY_UNREF(exec_ctx, w->chand->lb_policy, "channel");
w->chand->lb_policy = NULL;
}
grpc_connectivity_state_set(exec_ctx, &w->chand->state_tracker, publish_state,
"lb_changed");
set_channel_connectivity_state_locked(exec_ctx, w->chand, publish_state,
"lb_changed");
if (w->state != GRPC_CHANNEL_FATAL_FAILURE) {
watch_lb_policy(exec_ctx, w->chand, w->lb_policy, w->state);
}
@ -200,8 +216,8 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
}
if (iomgr_success && chand->resolver) {
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
"new_lb+resolver");
set_channel_connectivity_state_locked(exec_ctx, chand, state,
"new_lb+resolver");
if (lb_policy != NULL) {
watch_lb_policy(exec_ctx, chand, lb_policy, state);
}
@ -216,8 +232,8 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
}
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
set_channel_connectivity_state_locked(
exec_ctx, chand, GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
gpr_mu_unlock(&chand->mu_config);
}
@ -272,8 +288,8 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
}
if (op->disconnect && chand->resolver != NULL) {
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
set_channel_connectivity_state_locked(
exec_ctx, chand, GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
@ -290,6 +306,7 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
typedef struct {
grpc_metadata_batch *initial_metadata;
uint32_t initial_metadata_flags;
grpc_connected_subchannel **connected_subchannel;
grpc_closure *on_ready;
grpc_call_element *elem;
@ -298,6 +315,7 @@ typedef struct {
static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *arg,
grpc_metadata_batch *initial_metadata,
uint32_t initial_metadata_flags,
grpc_connected_subchannel **connected_subchannel,
grpc_closure *on_ready);
@ -308,6 +326,7 @@ static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
} else if (cpa->connected_subchannel == NULL) {
/* cancelled, do nothing */
} else if (cc_pick_subchannel(exec_ctx, cpa->elem, cpa->initial_metadata,
cpa->initial_metadata_flags,
cpa->connected_subchannel, cpa->on_ready)) {
grpc_exec_ctx_enqueue(exec_ctx, cpa->on_ready, true, NULL);
}
@ -316,6 +335,7 @@ static void continue_picking(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
grpc_metadata_batch *initial_metadata,
uint32_t initial_metadata_flags,
grpc_connected_subchannel **connected_subchannel,
grpc_closure *on_ready) {
grpc_call_element *elem = elemp;
@ -349,7 +369,8 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
GRPC_LB_POLICY_REF(lb_policy, "cc_pick_subchannel");
gpr_mu_unlock(&chand->mu_config);
r = grpc_lb_policy_pick(exec_ctx, lb_policy, calld->pollset,
initial_metadata, connected_subchannel, on_ready);
initial_metadata, initial_metadata_flags,
connected_subchannel, on_ready);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "cc_pick_subchannel");
return r;
}
@ -362,6 +383,7 @@ static int cc_pick_subchannel(grpc_exec_ctx *exec_ctx, void *elemp,
}
cpa = gpr_malloc(sizeof(*cpa));
cpa->initial_metadata = initial_metadata;
cpa->initial_metadata_flags = initial_metadata_flags;
cpa->connected_subchannel = connected_subchannel;
cpa->on_ready = on_ready;
cpa->elem = elem;

@ -111,10 +111,12 @@ static void hc_mutate_op(grpc_call_element *elem,
elem);
/* Send : prefixed headers, which have to be before any application
layer headers. */
grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method,
op->send_idempotent_request
? GRPC_MDELEM_METHOD_PUT
: GRPC_MDELEM_METHOD_POST);
grpc_metadata_batch_add_head(
op->send_initial_metadata, &calld->method,
op->send_initial_metadata_flags &
GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
? GRPC_MDELEM_METHOD_PUT
: GRPC_MDELEM_METHOD_POST);
grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme,
channeld->static_scheme);
grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers,

@ -127,7 +127,7 @@ retry:
break;
case GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL:
holder->pick_subchannel(exec_ctx, holder->pick_subchannel_arg, NULL,
&holder->connected_subchannel, NULL);
0, &holder->connected_subchannel, NULL);
break;
}
gpr_mu_unlock(&holder->mu);
@ -145,7 +145,8 @@ retry:
GRPC_CALL_STACK_REF(holder->owning_call, "pick_subchannel");
if (holder->pick_subchannel(
exec_ctx, holder->pick_subchannel_arg, op->send_initial_metadata,
&holder->connected_subchannel, &holder->next_step)) {
op->send_initial_metadata_flags, &holder->connected_subchannel,
&holder->next_step)) {
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
GRPC_CALL_STACK_UNREF(exec_ctx, holder->owning_call, "pick_subchannel");
}

@ -42,6 +42,7 @@
called when the subchannel is available) */
typedef int (*grpc_subchannel_call_holder_pick_subchannel)(
grpc_exec_ctx *exec_ctx, void *arg, grpc_metadata_batch *initial_metadata,
uint32_t initial_metadata_flags,
grpc_connected_subchannel **connected_subchannel, grpc_closure *on_ready);
typedef enum {

@ -40,7 +40,7 @@ decisions (for example, by avoiding disconnected backends).
Configured sub-channels are fully setup to participate in the grpc data plane.
Their behavior is specified by a set of grpc channel filters defined at their
construction. To customize this behavior, resolvers build
grpc_subchannel_factory objects, which use the decorator pattern to customize
grpc_client_channel_factory objects, which use the decorator pattern to customize
construction arguments for concrete grpc_subchannel instances.

@ -31,19 +31,27 @@
*
*/
#include "src/core/lib/client_config/subchannel_factory.h"
#include "src/core/lib/client_config/client_channel_factory.h"
void grpc_subchannel_factory_ref(grpc_subchannel_factory* factory) {
void grpc_client_channel_factory_ref(grpc_client_channel_factory* factory) {
factory->vtable->ref(factory);
}
void grpc_subchannel_factory_unref(grpc_exec_ctx* exec_ctx,
grpc_subchannel_factory* factory) {
void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx,
grpc_client_channel_factory* factory) {
factory->vtable->unref(exec_ctx, factory);
}
grpc_subchannel* grpc_subchannel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_subchannel_factory* factory,
grpc_subchannel* grpc_client_channel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
grpc_subchannel_args* args) {
return factory->vtable->create_subchannel(exec_ctx, factory, args);
}
grpc_channel* grpc_client_channel_factory_create_channel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
const char* target, grpc_client_channel_type type,
grpc_channel_args* args) {
return factory->vtable->create_client_channel(exec_ctx, factory, target, type,
args);
}

@ -31,36 +31,55 @@
*
*/
#ifndef GRPC_CORE_LIB_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H
#define GRPC_CORE_LIB_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H
#ifndef GRPC_CORE_LIB_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H
#define GRPC_CORE_LIB_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H
#include <grpc/impl/codegen/grpc_types.h>
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/client_config/subchannel.h"
typedef struct grpc_subchannel_factory grpc_subchannel_factory;
typedef struct grpc_subchannel_factory_vtable grpc_subchannel_factory_vtable;
typedef struct grpc_client_channel_factory grpc_client_channel_factory;
typedef struct grpc_client_channel_factory_vtable
grpc_client_channel_factory_vtable;
typedef enum {
GRPC_CLIENT_CHANNEL_TYPE_REGULAR, /** for the user-level regular calls */
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, /** for communication with a load
balancing service */
} grpc_client_channel_type;
/** Constructor for new configured channels.
Creating decorators around this type is encouraged to adapt behavior. */
struct grpc_subchannel_factory {
const grpc_subchannel_factory_vtable *vtable;
struct grpc_client_channel_factory {
const grpc_client_channel_factory_vtable *vtable;
};
struct grpc_subchannel_factory_vtable {
void (*ref)(grpc_subchannel_factory *factory);
void (*unref)(grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory);
struct grpc_client_channel_factory_vtable {
void (*ref)(grpc_client_channel_factory *factory);
void (*unref)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory);
grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *factory,
grpc_client_channel_factory *factory,
grpc_subchannel_args *args);
grpc_channel *(*create_client_channel)(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory,
const char *target,
grpc_client_channel_type type,
grpc_channel_args *args);
};
void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory);
void grpc_subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *factory);
void grpc_client_channel_factory_ref(grpc_client_channel_factory *factory);
void grpc_client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory);
/** Create a new grpc_subchannel */
grpc_subchannel *grpc_subchannel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
grpc_subchannel *grpc_client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
grpc_subchannel_args *args);
#endif /* GRPC_CORE_LIB_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H */
/** Create a new grpc_channel */
grpc_channel *grpc_client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
const char *target, grpc_client_channel_type type, grpc_channel_args *args);
#endif /* GRPC_CORE_LIB_CLIENT_CONFIG_CLIENT_CHANNEL_FACTORY_H */

@ -101,10 +101,11 @@ void grpc_lb_policy_weak_unref(grpc_exec_ctx *exec_ctx,
int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_pollset *pollset,
grpc_metadata_batch *initial_metadata,
uint32_t initial_metadata_flags,
grpc_connected_subchannel **target,
grpc_closure *on_complete) {
return policy->vtable->pick(exec_ctx, policy, pollset, initial_metadata,
target, on_complete);
initial_metadata_flags, target, on_complete);
}
void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
@ -112,6 +113,14 @@ void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
policy->vtable->cancel_pick(exec_ctx, policy, target);
}
void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq) {
policy->vtable->cancel_picks(exec_ctx, policy, initial_metadata_flags_mask,
initial_metadata_flags_eq);
}
void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy) {
policy->vtable->exit_idle(exec_ctx, policy);
}

@ -60,9 +60,13 @@ struct grpc_lb_policy_vtable {
/** implement grpc_lb_policy_pick */
int (*pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_pollset *pollset, grpc_metadata_batch *initial_metadata,
uint32_t initial_metadata_flags,
grpc_connected_subchannel **target, grpc_closure *on_complete);
void (*cancel_pick)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_connected_subchannel **target);
void (*cancel_picks)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq);
void (*ping_one)(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_closure *closure);
@ -122,6 +126,7 @@ void grpc_lb_policy_init(grpc_lb_policy *policy,
int grpc_lb_policy_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_pollset *pollset,
grpc_metadata_batch *initial_metadata,
uint32_t initial_metadata_flags,
grpc_connected_subchannel **target,
grpc_closure *on_complete);
@ -131,6 +136,14 @@ void grpc_lb_policy_ping_one(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
void grpc_lb_policy_cancel_pick(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy,
grpc_connected_subchannel **target);
/** Cancel all pending picks which have:
(initial_metadata_flags & initial_metadata_flags_mask) ==
initial_metadata_flags_eq */
void grpc_lb_policy_cancel_picks(grpc_exec_ctx *exec_ctx,
grpc_lb_policy *policy,
uint32_t initial_metadata_flags_mask,
uint32_t initial_metadata_flags_eq);
void grpc_lb_policy_exit_idle(grpc_exec_ctx *exec_ctx, grpc_lb_policy *policy);
void grpc_lb_policy_notify_on_state_change(grpc_exec_ctx *exec_ctx,

@ -34,8 +34,8 @@
#ifndef GRPC_CORE_LIB_CLIENT_CONFIG_LB_POLICY_FACTORY_H
#define GRPC_CORE_LIB_CLIENT_CONFIG_LB_POLICY_FACTORY_H
#include "src/core/lib/client_config/client_channel_factory.h"
#include "src/core/lib/client_config/lb_policy.h"
#include "src/core/lib/client_config/subchannel_factory.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/exec_ctx.h"
@ -51,7 +51,7 @@ struct grpc_lb_policy_factory {
typedef struct grpc_lb_policy_args {
grpc_resolved_addresses *addresses;
grpc_subchannel_factory *subchannel_factory;
grpc_client_channel_factory *client_channel_factory;
} grpc_lb_policy_args;
struct grpc_lb_policy_factory_vtable {

@ -34,8 +34,8 @@
#ifndef GRPC_CORE_LIB_CLIENT_CONFIG_RESOLVER_FACTORY_H
#define GRPC_CORE_LIB_CLIENT_CONFIG_RESOLVER_FACTORY_H
#include "src/core/lib/client_config/client_channel_factory.h"
#include "src/core/lib/client_config/resolver.h"
#include "src/core/lib/client_config/subchannel_factory.h"
#include "src/core/lib/client_config/uri_parser.h"
typedef struct grpc_resolver_factory grpc_resolver_factory;
@ -49,7 +49,7 @@ struct grpc_resolver_factory {
typedef struct grpc_resolver_args {
grpc_uri *uri;
grpc_subchannel_factory *subchannel_factory;
grpc_client_channel_factory *client_channel_factory;
} grpc_resolver_args;
struct grpc_resolver_factory_vtable {

@ -123,14 +123,14 @@ static grpc_resolver_factory *resolve_factory(const char *target,
}
grpc_resolver *grpc_resolver_create(
const char *target, grpc_subchannel_factory *subchannel_factory) {
const char *target, grpc_client_channel_factory *client_channel_factory) {
grpc_uri *uri = NULL;
grpc_resolver_factory *factory = resolve_factory(target, &uri);
grpc_resolver *resolver;
grpc_resolver_args args;
memset(&args, 0, sizeof(args));
args.uri = uri;
args.subchannel_factory = subchannel_factory;
args.client_channel_factory = client_channel_factory;
resolver = grpc_resolver_factory_create_resolver(factory, &args);
grpc_uri_destroy(uri);
return resolver;

@ -56,7 +56,7 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory);
return it.
If a resolver factory was not found, return NULL. */
grpc_resolver *grpc_resolver_create(
const char *target, grpc_subchannel_factory *subchannel_factory);
const char *target, grpc_client_channel_factory *client_channel_factory);
/** Find a resolver factory given a name and return an (owned-by-the-caller)
* reference to it */

@ -54,7 +54,7 @@
#define STRONG_REF_MASK (~(gpr_atm)((1 << INTERNAL_REF_BITS) - 1))
#define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20
#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1
#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 2
#define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6
#define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
#define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
@ -352,6 +352,25 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
c->args->args[i].value.integer,
c->args->args[i].value.integer);
}
if (0 ==
strcmp(c->args->args[i].key, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS)) {
if (c->args->args[i].type == GRPC_ARG_INTEGER) {
if (c->args->args[i].value.integer >= 0) {
gpr_backoff_init(
&c->backoff_state, GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
GRPC_SUBCHANNEL_RECONNECT_JITTER,
GPR_MIN(c->args->args[i].value.integer,
GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000),
c->args->args[i].value.integer);
} else {
gpr_log(GPR_ERROR, GRPC_ARG_MAX_RECONNECT_BACKOFF_MS
" : must be non-negative");
}
} else {
gpr_log(GPR_ERROR,
GRPC_ARG_MAX_RECONNECT_BACKOFF_MS " : must be an integer");
}
}
}
}
gpr_mu_init(&c->mu);

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -81,11 +81,11 @@ typedef enum {
/* Status came from the application layer overriding whatever
the wire says */
STATUS_FROM_API_OVERRIDE = 0,
/* Status was created by some internal channel stack operation */
STATUS_FROM_CORE,
/* Status came from 'the wire' - or somewhere below the surface
layer */
STATUS_FROM_WIRE,
/* Status was created by some internal channel stack operation */
STATUS_FROM_CORE,
/* Status came from the server sending status */
STATUS_FROM_SERVER_STATUS,
STATUS_SOURCE_COUNT
@ -1110,6 +1110,9 @@ static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp, bool success) {
gpr_mu_lock(&call->mu);
if (bctl->send_initial_metadata) {
if (!success) {
set_status_code(call, STATUS_FROM_CORE, GRPC_STATUS_UNAVAILABLE);
}
grpc_metadata_batch_destroy(
&call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */]);
}
@ -1232,8 +1235,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
call->metadata_batch[0][0].deadline = call->send_deadline;
stream_op.send_initial_metadata =
&call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */];
stream_op.send_idempotent_request =
(op->flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) != 0;
stream_op.send_initial_metadata_flags = op->flags;
break;
case GRPC_OP_SEND_MESSAGE:
if (!are_write_flags_valid(op->flags)) {

@ -35,7 +35,7 @@
#define GRPC_CORE_LIB_SURFACE_CHANNEL_H
#include "src/core/lib/channel/channel_stack.h"
#include "src/core/lib/client_config/subchannel_factory.h"
#include "src/core/lib/client_config/client_channel_factory.h"
#include "src/core/lib/surface/channel_stack_type.h"
grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,

@ -95,7 +95,6 @@ typedef struct requested_call {
grpc_byte_buffer **optional_payload;
} registered;
} data;
grpc_closure publish;
} requested_call;
typedef struct channel_registered_method {
@ -156,15 +155,21 @@ struct call_data {
bool recv_idempotent_request;
grpc_metadata_array initial_metadata;
request_matcher *request_matcher;
grpc_byte_buffer *payload;
grpc_closure got_initial_metadata;
grpc_closure server_on_recv_initial_metadata;
grpc_closure kill_zombie_closure;
grpc_closure *on_done_recv_initial_metadata;
grpc_closure publish;
call_data *pending_next;
};
struct request_matcher {
grpc_server *server;
call_data *pending_head;
call_data *pending_tail;
gpr_stack_lockfree *requests;
@ -173,6 +178,7 @@ struct request_matcher {
struct registered_method {
char *method;
char *host;
grpc_server_register_method_payload_handling payload_handling;
uint32_t flags;
request_matcher request_matcher;
registered_method *next;
@ -226,8 +232,7 @@ struct grpc_server {
#define SERVER_FROM_CALL_ELEM(elem) \
(((channel_data *)(elem)->channel_data)->server)
static void begin_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
call_data *calld, requested_call *rc);
static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *calld, bool success);
static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
requested_call *rc);
/* Before calling maybe_finish_shutdown, we must hold mu_global and not
@ -303,8 +308,10 @@ static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx,
* request_matcher
*/
static void request_matcher_init(request_matcher *rm, size_t entries) {
static void request_matcher_init(request_matcher *rm, size_t entries,
grpc_server *server) {
memset(rm, 0, sizeof(*rm));
rm->server = server;
rm->requests = gpr_stack_lockfree_create(entries);
}
@ -417,21 +424,90 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) {
&op);
}
static void finish_start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_server *server,
grpc_call_element *elem, request_matcher *rm) {
call_data *calld = elem->call_data;
int request_id;
static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
gpr_slice slice = value->slice;
size_t len = GPR_SLICE_LENGTH(slice);
if (gpr_atm_acq_load(&server->shutdown_flag)) {
if (len + 1 > *capacity) {
*capacity = GPR_MAX(len + 1, *capacity * 2);
*dest = gpr_realloc(*dest, *capacity);
}
memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
}
static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
grpc_cq_completion *c) {
requested_call *rc = req;
grpc_server *server = rc->server;
if (rc >= server->requested_calls &&
rc < server->requested_calls + server->max_requested_calls) {
GPR_ASSERT(rc - server->requested_calls <= INT_MAX);
gpr_stack_lockfree_push(server->request_freelist,
(int)(rc - server->requested_calls));
} else {
gpr_free(req);
}
server_unref(exec_ctx, server);
}
static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
call_data *calld, requested_call *rc) {
grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
grpc_call *call = calld->call;
*rc->call = call;
calld->cq_new = rc->cq_for_notification;
GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
switch (rc->type) {
case BATCH_CALL:
GPR_ASSERT(calld->host != NULL);
GPR_ASSERT(calld->path != NULL);
cpstr(&rc->data.batch.details->host,
&rc->data.batch.details->host_capacity, calld->host);
cpstr(&rc->data.batch.details->method,
&rc->data.batch.details->method_capacity, calld->path);
rc->data.batch.details->deadline = calld->deadline;
rc->data.batch.details->flags =
0 | (calld->recv_idempotent_request
? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
: 0);
break;
case REGISTERED_CALL:
*rc->data.registered.deadline = calld->deadline;
if (rc->data.registered.optional_payload) {
*rc->data.registered.optional_payload = calld->payload;
}
break;
default:
GPR_UNREACHABLE_CODE(return );
}
grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
channel_data *chand = elem->channel_data;
server_ref(chand->server);
grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, true, done_request_event, rc,
&rc->completion);
}
static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
call_data *calld = arg;
request_matcher *rm = calld->request_matcher;
grpc_server *server = rm->server;
if (!success || gpr_atm_acq_load(&server->shutdown_flag)) {
gpr_mu_lock(&calld->mu_state);
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_closure_init(
&calld->kill_zombie_closure, kill_zombie,
grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
return;
}
request_id = gpr_stack_lockfree_pop(rm->requests);
int request_id = gpr_stack_lockfree_pop(rm->requests);
if (request_id == -1) {
gpr_mu_lock(&server->mu_call);
gpr_mu_lock(&calld->mu_state);
@ -449,7 +525,41 @@ static void finish_start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_server *server,
gpr_mu_lock(&calld->mu_state);
calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state);
begin_call(exec_ctx, server, calld, &server->requested_calls[request_id]);
publish_call(exec_ctx, server, calld, &server->requested_calls[request_id]);
}
}
static void finish_start_new_rpc(
grpc_exec_ctx *exec_ctx, grpc_server *server, grpc_call_element *elem,
request_matcher *rm,
grpc_server_register_method_payload_handling payload_handling) {
call_data *calld = elem->call_data;
if (gpr_atm_acq_load(&server->shutdown_flag)) {
gpr_mu_lock(&calld->mu_state);
calld->state = ZOMBIED;
gpr_mu_unlock(&calld->mu_state);
grpc_closure_init(&calld->kill_zombie_closure, kill_zombie, elem);
grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
return;
}
calld->request_matcher = rm;
switch (payload_handling) {
case GRPC_SRM_PAYLOAD_NONE:
publish_new_rpc(exec_ctx, calld, true);
break;
case GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER: {
grpc_op op;
memset(&op, 0, sizeof(op));
op.op = GRPC_OP_RECV_MESSAGE;
op.data.recv_message = &calld->payload;
grpc_closure_init(&calld->publish, publish_new_rpc, calld);
grpc_call_start_batch_and_execute(exec_ctx, calld->call, &op, 1,
&calld->publish);
break;
}
}
}
@ -475,7 +585,8 @@ static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
!calld->recv_idempotent_request)
continue;
finish_start_new_rpc(exec_ctx, server, elem,
&rm->server_registered_method->request_matcher);
&rm->server_registered_method->request_matcher,
rm->server_registered_method->payload_handling);
return;
}
/* check for a wildcard method definition (no host set) */
@ -490,12 +601,14 @@ static void start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
!calld->recv_idempotent_request)
continue;
finish_start_new_rpc(exec_ctx, server, elem,
&rm->server_registered_method->request_matcher);
&rm->server_registered_method->request_matcher,
rm->server_registered_method->payload_handling);
return;
}
}
finish_start_new_rpc(exec_ctx, server, elem,
&server->unregistered_request_matcher);
&server->unregistered_request_matcher,
GRPC_SRM_PAYLOAD_NONE);
}
static int num_listeners(grpc_server *server) {
@ -824,7 +937,7 @@ grpc_server *grpc_server_create(const grpc_channel_args *args, void *reserved) {
gpr_stack_lockfree_push(server->request_freelist, (int)i);
}
request_matcher_init(&server->unregistered_request_matcher,
server->max_requested_calls);
server->max_requested_calls, server);
server->requested_calls = gpr_malloc(server->max_requested_calls *
sizeof(*server->requested_calls));
@ -840,8 +953,10 @@ static int streq(const char *a, const char *b) {
return 0 == strcmp(a, b);
}
void *grpc_server_register_method(grpc_server *server, const char *method,
const char *host, uint32_t flags) {
void *grpc_server_register_method(
grpc_server *server, const char *method, const char *host,
grpc_server_register_method_payload_handling payload_handling,
uint32_t flags) {
registered_method *m;
GRPC_API_TRACE(
"grpc_server_register_method(server=%p, method=%s, host=%s, "
@ -866,10 +981,12 @@ void *grpc_server_register_method(grpc_server *server, const char *method,
}
m = gpr_malloc(sizeof(registered_method));
memset(m, 0, sizeof(*m));
request_matcher_init(&m->request_matcher, server->max_requested_calls);
request_matcher_init(&m->request_matcher, server->max_requested_calls,
server);
m->method = gpr_strdup(method);
m->host = gpr_strdup(host);
m->next = server->registered_methods;
m->payload_handling = payload_handling;
m->flags = flags;
server->registered_methods = m;
return m;
@ -1143,8 +1260,8 @@ static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(calld->state == PENDING);
calld->state = ACTIVATED;
gpr_mu_unlock(&calld->mu_state);
begin_call(exec_ctx, server, calld,
&server->requested_calls[request_id]);
publish_call(exec_ctx, server, calld,
&server->requested_calls[request_id]);
}
gpr_mu_lock(&server->mu_call);
}
@ -1209,6 +1326,12 @@ grpc_call_error grpc_server_request_registered_call(
error = GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE;
goto done;
}
if ((optional_payload == NULL) !=
(rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)) {
gpr_free(rc);
error = GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH;
goto done;
}
grpc_cq_begin_op(cq_for_notification, tag);
rc->type = REGISTERED_CALL;
rc->server = server;
@ -1226,86 +1349,6 @@ done:
return error;
}
static void publish_registered_or_batch(grpc_exec_ctx *exec_ctx,
void *user_data, bool success);
static void cpstr(char **dest, size_t *capacity, grpc_mdstr *value) {
gpr_slice slice = value->slice;
size_t len = GPR_SLICE_LENGTH(slice);
if (len + 1 > *capacity) {
*capacity = GPR_MAX(len + 1, *capacity * 2);
*dest = gpr_realloc(*dest, *capacity);
}
memcpy(*dest, grpc_mdstr_as_c_string(value), len + 1);
}
static void begin_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
call_data *calld, requested_call *rc) {
grpc_op ops[1];
grpc_op *op = ops;
memset(ops, 0, sizeof(ops));
/* called once initial metadata has been read by the call, but BEFORE
the ioreq to fetch it out of the call has been executed.
This means metadata related fields can be relied on in calld, but to
fill in the metadata array passed by the client, we need to perform
an ioreq op, that should complete immediately. */
grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
grpc_closure_init(&rc->publish, publish_registered_or_batch, rc);
*rc->call = calld->call;
calld->cq_new = rc->cq_for_notification;
GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
switch (rc->type) {
case BATCH_CALL:
GPR_ASSERT(calld->host != NULL);
GPR_ASSERT(calld->path != NULL);
cpstr(&rc->data.batch.details->host,
&rc->data.batch.details->host_capacity, calld->host);
cpstr(&rc->data.batch.details->method,
&rc->data.batch.details->method_capacity, calld->path);
rc->data.batch.details->deadline = calld->deadline;
rc->data.batch.details->flags =
0 | (calld->recv_idempotent_request
? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
: 0);
break;
case REGISTERED_CALL:
*rc->data.registered.deadline = calld->deadline;
if (rc->data.registered.optional_payload) {
op->op = GRPC_OP_RECV_MESSAGE;
op->data.recv_message = rc->data.registered.optional_payload;
op++;
}
break;
default:
GPR_UNREACHABLE_CODE(return );
}
GRPC_CALL_INTERNAL_REF(calld->call, "server");
grpc_call_start_batch_and_execute(exec_ctx, calld->call, ops,
(size_t)(op - ops), &rc->publish);
}
static void done_request_event(grpc_exec_ctx *exec_ctx, void *req,
grpc_cq_completion *c) {
requested_call *rc = req;
grpc_server *server = rc->server;
if (rc >= server->requested_calls &&
rc < server->requested_calls + server->max_requested_calls) {
GPR_ASSERT(rc - server->requested_calls <= INT_MAX);
gpr_stack_lockfree_push(server->request_freelist,
(int)(rc - server->requested_calls));
} else {
gpr_free(req);
}
server_unref(exec_ctx, server);
}
static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
requested_call *rc) {
*rc->call = NULL;
@ -1316,20 +1359,6 @@ static void fail_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
done_request_event, rc, &rc->completion);
}
static void publish_registered_or_batch(grpc_exec_ctx *exec_ctx, void *prc,
bool success) {
requested_call *rc = prc;
grpc_call *call = *rc->call;
grpc_call_element *elem =
grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
server_ref(chand->server);
grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, success, done_request_event,
rc, &rc->completion);
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "server");
}
const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) {
return server->channel_args;
}

@ -101,9 +101,9 @@ typedef struct grpc_transport_stream_op {
/** Send initial metadata to the peer, from the provided metadata batch.
idempotent_request MUST be set if this is non-null */
grpc_metadata_batch *send_initial_metadata;
/** Iff send_initial_metadata != NULL, flags if this is an idempotent request
or not */
bool send_idempotent_request;
/** Iff send_initial_metadata != NULL, flags associated with
send_initial_metadata: a bitfield of GRPC_INITIAL_METADATA_xxx */
uint32_t send_initial_metadata_flags;
/** Send trailing metadata to the peer, from the provided metadata batch. */
grpc_metadata_batch *send_trailing_metadata;

@ -60,6 +60,8 @@ static ClientContext::GlobalCallbacks* g_client_callbacks =
ClientContext::ClientContext()
: initial_metadata_received_(false),
fail_fast_(true),
idempotent_(false),
call_(nullptr),
call_canceled_(false),
deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),

@ -321,6 +321,19 @@ void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
g_callbacks.reset(callbacks);
}
static grpc_server_register_method_payload_handling PayloadHandlingForMethod(
RpcServiceMethod* method) {
switch (method->method_type()) {
case RpcMethod::NORMAL_RPC:
case RpcMethod::SERVER_STREAMING:
return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER;
case RpcMethod::CLIENT_STREAMING:
case RpcMethod::BIDI_STREAMING:
return GRPC_SRM_PAYLOAD_NONE;
}
GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;);
}
bool Server::RegisterService(const grpc::string* host, Service* service) {
bool has_async_methods = service->has_async_methods();
if (has_async_methods) {
@ -334,8 +347,9 @@ bool Server::RegisterService(const grpc::string* host, Service* service) {
continue;
}
RpcServiceMethod* method = it->get();
void* tag = grpc_server_register_method(server_, method->name(),
host ? host->c_str() : nullptr, 0);
void* tag = grpc_server_register_method(
server_, method->name(), host ? host->c_str() : nullptr,
PayloadHandlingForMethod(method), 0);
if (tag == nullptr) {
gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
method->name());

@ -0,0 +1,84 @@
#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.Threading.Tasks;
using Grpc.Core.Internal;
namespace Grpc.Core
{
/// <summary>
/// Abstraction of client-side RPC invocation.
/// </summary>
/// <seealso cref="Calls"/>
public abstract class CallInvoker
{
/// <summary>
/// Invokes a simple remote call in a blocking fashion.
/// </summary>
public abstract TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
where TRequest : class
where TResponse : class;
/// <summary>
/// Invokes a simple remote call asynchronously.
/// </summary>
public abstract AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
where TRequest : class
where TResponse : class;
/// <summary>
/// Invokes a server streaming call asynchronously.
/// In server streaming scenario, client sends on request and server responds with a stream of responses.
/// </summary>
public abstract AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
where TRequest : class
where TResponse : class;
/// <summary>
/// Invokes a client streaming call asynchronously.
/// In client streaming scenario, client sends a stream of requests and server responds with a single response.
/// </summary>
public abstract AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
where TRequest : class
where TResponse : class;
/// <summary>
/// Invokes a duplex streaming call asynchronously.
/// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
/// The response stream is completely independent and both side can be sending messages at the same time.
/// </summary>
public abstract AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
where TRequest : class
where TResponse : class;
}
}

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -31,93 +31,156 @@
#endregion
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
/// Interceptor for call headers.
/// Generic base class for client-side stubs.
/// </summary>
/// <remarks>Header interceptor is no longer to recommented way to perform authentication.
/// For header (initial metadata) based auth such as OAuth2 or JWT access token, use <see cref="MetadataCredentials"/>.
/// </remarks>
public delegate void HeaderInterceptor(IMethod method, Metadata metadata);
public abstract class ClientBase<T> : ClientBase
where T : ClientBase<T>
{
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class that
/// throws <c>NotImplementedException</c> upon invocation of any RPC.
/// This constructor is only provided to allow creation of test doubles
/// for client classes (e.g. mocking requires a parameterless constructor).
/// </summary>
protected ClientBase() : base()
{
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
protected ClientBase(ClientBaseConfiguration configuration) : base(configuration)
{
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="channel">The channel to use for remote call invocation.</param>
public ClientBase(Channel channel) : base(channel)
{
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="callInvoker">The <c>CallInvoker</c> for remote call invocation.</param>
public ClientBase(CallInvoker callInvoker) : base(callInvoker)
{
}
/// <summary>
/// Creates a new client that sets host field for calls explicitly.
/// gRPC supports multiple "hosts" being served by a single server.
/// By default (if a client was not created by calling this method),
/// host <c>null</c> with the meaning "use default host" is used.
/// </summary>
public T WithHost(string host)
{
var newConfiguration = this.Configuration.WithHost(host);
return NewInstance(newConfiguration);
}
/// <summary>
/// Creates a new instance of client from given <c>ClientBaseConfiguration</c>.
/// </summary>
protected abstract T NewInstance(ClientBaseConfiguration configuration);
}
/// <summary>
/// Base class for client-side stubs.
/// </summary>
public abstract class ClientBase
{
readonly Channel channel;
readonly ClientBaseConfiguration configuration;
readonly CallInvoker callInvoker;
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class that
/// throws <c>NotImplementedException</c> upon invocation of any RPC.
/// This constructor is only provided to allow creation of test doubles
/// for client classes (e.g. mocking requires a parameterless constructor).
/// </summary>
protected ClientBase() : this(new UnimplementedCallInvoker())
{
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="configuration">The configuration.</param>
protected ClientBase(ClientBaseConfiguration configuration)
{
this.configuration = GrpcPreconditions.CheckNotNull(configuration, "configuration");
this.callInvoker = configuration.CreateDecoratedCallInvoker();
}
/// <summary>
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <param name="channel">The channel to use for remote call invocation.</param>
public ClientBase(Channel channel)
public ClientBase(Channel channel) : this(new DefaultCallInvoker(channel))
{
this.channel = channel;
}
/// <summary>
/// Can be used to register a custom header interceptor.
/// The interceptor is invoked each time a new call on this client is started.
/// It is not recommented to use header interceptor to add auth headers to RPC calls.
/// Initializes a new instance of <c>ClientBase</c> class.
/// </summary>
/// <seealso cref="HeaderInterceptor"/>
public HeaderInterceptor HeaderInterceptor
/// <param name="callInvoker">The <c>CallInvoker</c> for remote call invocation.</param>
public ClientBase(CallInvoker callInvoker) : this(new ClientBaseConfiguration(callInvoker, null))
{
get;
set;
}
/// <summary>
/// gRPC supports multiple "hosts" being served by a single server.
/// This property can be used to set the target host explicitly.
/// By default, this will be set to <c>null</c> with the meaning
/// "use default host".
/// Gets the call invoker.
/// </summary>
public string Host
protected CallInvoker CallInvoker
{
get;
set;
get { return this.callInvoker; }
}
/// <summary>
/// Channel associated with this client.
/// Gets the configuration.
/// </summary>
public Channel Channel
internal ClientBaseConfiguration Configuration
{
get
{
return this.channel;
}
get { return this.configuration; }
}
/// <summary>
/// Creates a new call to given method.
/// Represents configuration of ClientBase. The class itself is visible to
/// subclasses, but contents are marked as internal to make the instances opaque.
/// The verbose name of this class was chosen to make name clash in generated code
/// less likely.
/// </summary>
/// <param name="method">The method to invoke.</param>
/// <param name="options">The call options.</param>
/// <typeparam name="TRequest">Request message type.</typeparam>
/// <typeparam name="TResponse">Response message type.</typeparam>
/// <returns>The call invocation details.</returns>
protected CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, CallOptions options)
where TRequest : class
where TResponse : class
protected internal class ClientBaseConfiguration
{
var interceptor = HeaderInterceptor;
if (interceptor != null)
readonly CallInvoker undecoratedCallInvoker;
readonly string host;
internal ClientBaseConfiguration(CallInvoker undecoratedCallInvoker, string host)
{
this.undecoratedCallInvoker = GrpcPreconditions.CheckNotNull(undecoratedCallInvoker);
this.host = host;
}
internal CallInvoker CreateDecoratedCallInvoker()
{
return new InterceptingCallInvoker(undecoratedCallInvoker, hostInterceptor: (h) => host);
}
internal ClientBaseConfiguration WithHost(string host)
{
if (options.Headers == null)
{
options = options.WithHeaders(new Metadata());
}
interceptor(method, options.Headers);
GrpcPreconditions.CheckNotNull(host, "host");
return new ClientBaseConfiguration(this.undecoratedCallInvoker, host);
}
return new CallInvocationDetails<TRequest, TResponse>(channel, method, Host, options);
}
}
}

@ -0,0 +1,112 @@
#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.Threading.Tasks;
using Grpc.Core.Internal;
using Grpc.Core.Utils;
namespace Grpc.Core
{
/// <summary>
/// Invokes client RPCs using <see cref="Calls"/>.
/// </summary>
public class DefaultCallInvoker : CallInvoker
{
readonly Channel channel;
/// <summary>
/// Initializes a new instance of the <see cref="Grpc.Core.DefaultCallInvoker"/> class.
/// </summary>
/// <param name="channel">Channel to use.</param>
public DefaultCallInvoker(Channel channel)
{
this.channel = GrpcPreconditions.CheckNotNull(channel);
}
/// <summary>
/// Invokes a simple remote call in a blocking fashion.
/// </summary>
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
var call = CreateCall(method, host, options);
return Calls.BlockingUnaryCall(call, request);
}
/// <summary>
/// Invokes a simple remote call asynchronously.
/// </summary>
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
var call = CreateCall(method, host, options);
return Calls.AsyncUnaryCall(call, request);
}
/// <summary>
/// Invokes a server streaming call asynchronously.
/// In server streaming scenario, client sends on request and server responds with a stream of responses.
/// </summary>
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
var call = CreateCall(method, host, options);
return Calls.AsyncServerStreamingCall(call, request);
}
/// <summary>
/// Invokes a client streaming call asynchronously.
/// In client streaming scenario, client sends a stream of requests and server responds with a single response.
/// </summary>
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
var call = CreateCall(method, host, options);
return Calls.AsyncClientStreamingCall(call);
}
/// <summary>
/// Invokes a duplex streaming call asynchronously.
/// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
/// The response stream is completely independent and both side can be sending messages at the same time.
/// </summary>
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
var call = CreateCall(method, host, options);
return Calls.AsyncDuplexStreamingCall(call);
}
protected virtual CallInvocationDetails<TRequest, TResponse> CreateCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
where TRequest : class
where TResponse : class
{
return new CallInvocationDetails<TRequest, TResponse>(channel, method, host, options);
}
}
}

@ -129,6 +129,10 @@
<Compile Include="Profiling\Profilers.cs" />
<Compile Include="Internal\DefaultSslRootsOverride.cs" />
<Compile Include="Utils\GrpcPreconditions.cs" />
<Compile Include="CallInvoker.cs" />
<Compile Include="DefaultCallInvoker.cs" />
<Compile Include="Internal\UnimplementedCallInvoker.cs" />
<Compile Include="Internal\InterceptingCallInvoker.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Core.nuspec" />

@ -0,0 +1,134 @@
#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.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
/// Decorates an underlying <c>CallInvoker</c> to intercept call invocations.
/// </summary>
internal class InterceptingCallInvoker : CallInvoker
{
readonly CallInvoker callInvoker;
readonly Func<string, string> hostInterceptor;
readonly Func<CallOptions, CallOptions> callOptionsInterceptor;
/// <summary>
/// Initializes a new instance of the <see cref="Grpc.Core.InterceptingCallInvoker"/> class.
/// </summary>
public InterceptingCallInvoker(CallInvoker callInvoker,
Func<string, string> hostInterceptor = null,
Func<CallOptions, CallOptions> callOptionsInterceptor = null)
{
this.callInvoker = GrpcPreconditions.CheckNotNull(callInvoker);
this.hostInterceptor = hostInterceptor;
this.callOptionsInterceptor = callOptionsInterceptor;
}
/// <summary>
/// Intercepts a unary call.
/// </summary>
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.BlockingUnaryCall(method, host, options, request);
}
/// <summary>
/// Invokes a simple remote call asynchronously.
/// </summary>
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncUnaryCall(method, host, options, request);
}
/// <summary>
/// Invokes a server streaming call asynchronously.
/// In server streaming scenario, client sends on request and server responds with a stream of responses.
/// </summary>
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncServerStreamingCall(method, host, options, request);
}
/// <summary>
/// Invokes a client streaming call asynchronously.
/// In client streaming scenario, client sends a stream of requests and server responds with a single response.
/// </summary>
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncClientStreamingCall(method, host, options);
}
/// <summary>
/// Invokes a duplex streaming call asynchronously.
/// In duplex streaming scenario, client sends a stream of requests and server responds with a stream of responses.
/// The response stream is completely independent and both side can be sending messages at the same time.
/// </summary>
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
host = InterceptHost(host);
options = InterceptCallOptions(options);
return callInvoker.AsyncDuplexStreamingCall(method, host, options);
}
private string InterceptHost(string host)
{
if (hostInterceptor == null)
{
return host;
}
return hostInterceptor(host);
}
private CallOptions InterceptCallOptions(CallOptions options)
{
if (callOptionsInterceptor == null)
{
return options;
}
return callOptionsInterceptor(options);
}
}
}

@ -0,0 +1,75 @@
#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.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
/// <summary>
/// Call invoker that throws <c>NotImplementedException</c> for all requests.
/// </summary>
internal class UnimplementedCallInvoker : CallInvoker
{
public UnimplementedCallInvoker()
{
}
public override TResponse BlockingUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
throw new NotImplementedException();
}
public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
throw new NotImplementedException();
}
public override AsyncServerStreamingCall<TResponse> AsyncServerStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options, TRequest request)
{
throw new NotImplementedException();
}
public override AsyncClientStreamingCall<TRequest, TResponse> AsyncClientStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
throw new NotImplementedException();
}
public override AsyncDuplexStreamingCall<TRequest, TResponse> AsyncDuplexStreamingCall<TRequest, TResponse>(Method<TRequest, TResponse> method, string host, CallOptions options)
{
throw new NotImplementedException();
}
}
}

@ -1,5 +1,5 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -40,7 +40,7 @@ namespace Math
public static void Main(string[] args)
{
var channel = new Channel("127.0.0.1", 23456, ChannelCredentials.Insecure);
Math.IMathClient client = new Math.MathClient(channel);
Math.MathClient client = new Math.MathClient(channel);
MathExamples.DivExample(client);
MathExamples.DivAsyncExample(client).Wait();

@ -1,5 +1,5 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -38,19 +38,19 @@ namespace Math
{
public static class MathExamples
{
public static void DivExample(Math.IMathClient client)
public static void DivExample(Math.MathClient client)
{
DivReply result = client.Div(new DivArgs { Dividend = 10, Divisor = 3 });
Console.WriteLine("Div Result: " + result);
}
public static async Task DivAsyncExample(Math.IMathClient client)
public static async Task DivAsyncExample(Math.MathClient client)
{
DivReply result = await client.DivAsync(new DivArgs { Dividend = 4, Divisor = 5 });
Console.WriteLine("DivAsync Result: " + result);
}
public static async Task FibExample(Math.IMathClient client)
public static async Task FibExample(Math.MathClient client)
{
using (var call = client.Fib(new FibArgs { Limit = 5 }))
{
@ -59,7 +59,7 @@ namespace Math
}
}
public static async Task SumExample(Math.IMathClient client)
public static async Task SumExample(Math.MathClient client)
{
var numbers = new List<Num>
{
@ -75,7 +75,7 @@ namespace Math
}
}
public static async Task DivManyExample(Math.IMathClient client)
public static async Task DivManyExample(Math.MathClient client)
{
var divArgsList = new List<DivArgs>
{
@ -90,7 +90,7 @@ namespace Math
}
}
public static async Task DependendRequestsExample(Math.IMathClient client)
public static async Task DependendRequestsExample(Math.MathClient client)
{
var numbers = new List<Num>
{

@ -52,6 +52,7 @@ namespace Math {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IMathClient
{
global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -67,6 +68,7 @@ namespace Math {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IMath
{
Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context);
@ -75,61 +77,92 @@ namespace Math {
Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context);
}
// server-side abstract class
public abstract class MathBase
{
public virtual Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class MathClient : ClientBase, IMathClient
public class MathClient : ClientBase<MathClient>, IMathClient
{
public MathClient(Channel channel) : base(channel)
{
}
public global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public MathClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options)
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected MathClient() : base()
{
var call = CreateCall(__Method_Div, options);
return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected MathClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options)
public virtual global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Div, options);
return Calls.AsyncUnaryCall(call, request);
return Div(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options)
{
var call = CreateCall(__Method_DivMany, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.BlockingUnaryCall(__Method_Div, null, options, request);
}
public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options)
public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_DivMany, options);
return Calls.AsyncDuplexStreamingCall(call);
return DivAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options)
{
var call = CreateCall(__Method_Fib, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncServerStreamingCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_Div, null, options, request);
}
public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Fib, options);
return Calls.AsyncServerStreamingCall(call, request);
return DivMany(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options)
{
var call = CreateCall(__Method_Sum, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncClientStreamingCall(call);
return CallInvoker.AsyncDuplexStreamingCall(__Method_DivMany, null, options);
}
public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options)
public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Sum, options);
return Calls.AsyncClientStreamingCall(call);
return Fib(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options)
{
return CallInvoker.AsyncServerStreamingCall(__Method_Fib, null, options, request);
}
public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return Sum(new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options)
{
return CallInvoker.AsyncClientStreamingCall(__Method_Sum, null, options);
}
protected override MathClient NewInstance(ClientBaseConfiguration configuration)
{
return new MathClient(configuration);
}
}
@ -143,6 +176,16 @@ namespace Math {
.AddMethod(__Method_Sum, serviceImpl.Sum).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(MathBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Div, serviceImpl.Div)
.AddMethod(__Method_DivMany, serviceImpl.DivMany)
.AddMethod(__Method_Fib, serviceImpl.Fib)
.AddMethod(__Method_Sum, serviceImpl.Sum).Build();
}
// creates a new client
public static MathClient NewClient(Channel channel)
{

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -43,14 +43,14 @@ namespace Math
/// <summary>
/// Implementation of MathService server
/// </summary>
public class MathServiceImpl : Math.IMath
public class MathServiceImpl : Math.MathBase
{
public Task<DivReply> Div(DivArgs request, ServerCallContext context)
public override Task<DivReply> Div(DivArgs request, ServerCallContext context)
{
return Task.FromResult(DivInternal(request));
}
public async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context)
public override async Task Fib(FibArgs request, IServerStreamWriter<Num> responseStream, ServerCallContext context)
{
if (request.Limit <= 0)
{
@ -72,7 +72,7 @@ namespace Math
}
}
public async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context)
public override async Task<Num> Sum(IAsyncStreamReader<Num> requestStream, ServerCallContext context)
{
long sum = 0;
await requestStream.ForEachAsync(async num =>
@ -82,7 +82,7 @@ namespace Math
return new Num { Num_ = sum };
}
public async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context)
public override async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context)
{
await requestStream.ForEachAsync(async divArgs => await responseStream.WriteAsync(DivInternal(divArgs)));
}

@ -49,7 +49,7 @@ namespace Grpc.HealthCheck.Tests
const string Host = "localhost";
Server server;
Channel channel;
Grpc.Health.V1.Health.IHealthClient client;
Grpc.Health.V1.Health.HealthClient client;
Grpc.HealthCheck.HealthServiceImpl serviceImpl;
[TestFixtureSetUp]

@ -29,6 +29,7 @@ namespace Grpc.Health.V1 {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IHealthClient
{
global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -38,36 +39,59 @@ namespace Grpc.Health.V1 {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IHealth
{
Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context);
}
// server-side abstract class
public abstract class HealthBase
{
public virtual Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class HealthClient : ClientBase, IHealthClient
public class HealthClient : ClientBase<HealthClient>, IHealthClient
{
public HealthClient(Channel channel) : base(channel)
{
}
public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public HealthClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected HealthClient() : base()
{
}
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected HealthClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Check, options);
return Calls.BlockingUnaryCall(call, request);
return Check(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
{
var call = CreateCall(__Method_Check, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_Check, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Check, options);
return Calls.AsyncUnaryCall(call, request);
return CheckAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_Check, null, options, request);
}
protected override HealthClient NewInstance(ClientBaseConfiguration configuration)
{
return new HealthClient(configuration);
}
}
@ -78,6 +102,13 @@ namespace Grpc.Health.V1 {
.AddMethod(__Method_Check, serviceImpl.Check).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(HealthBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Check, serviceImpl.Check).Build();
}
// creates a new client
public static HealthClient NewClient(Channel channel)
{

@ -51,7 +51,7 @@ namespace Grpc.HealthCheck
/// server.AddServiceDefinition(Grpc.Health.V1.Health.BindService(serviceImpl));
/// </code>
/// </summary>
public class HealthServiceImpl : Grpc.Health.V1.Health.IHealth
public class HealthServiceImpl : Grpc.Health.V1.Health.HealthBase
{
private readonly object myLock = new object();
private readonly Dictionary<string, HealthCheckResponse.Types.ServingStatus> statusMap =
@ -99,7 +99,7 @@ namespace Grpc.HealthCheck
/// <param name="request">The check request.</param>
/// <param name="context">The call context.</param>
/// <returns>The asynchronous response.</returns>
public Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context)
public override Task<HealthCheckResponse> Check(HealthCheckRequest request, ServerCallContext context)
{
lock (myLock)
{

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -44,19 +44,19 @@ namespace Grpc.Testing
/// <summary>
/// Implementation of BenchmarkService server
/// </summary>
public class BenchmarkServiceImpl : BenchmarkService.IBenchmarkService
public class BenchmarkServiceImpl : BenchmarkService.BenchmarkServiceBase
{
public BenchmarkServiceImpl()
{
}
public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
public override Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
{
var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) };
return Task.FromResult(response);
}
public async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
public override async Task StreamingCall(IAsyncStreamReader<SimpleRequest> requestStream, IServerStreamWriter<SimpleResponse> responseStream, ServerCallContext context)
{
await requestStream.ForEachAsync(async request =>
{

@ -112,7 +112,7 @@ namespace Grpc.IntegrationTesting
readonly PayloadConfig payloadConfig;
readonly Histogram histogram;
readonly BenchmarkService.IBenchmarkServiceClient client;
readonly BenchmarkService.BenchmarkServiceClient client;
readonly Task runnerTask;
readonly CancellationTokenSource stoppedCts;
readonly WallClockStopwatch wallClockStopwatch = new WallClockStopwatch();

@ -0,0 +1,106 @@
#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.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using Moq;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
public class GeneratedClientTest
{
TestService.TestServiceClient unimplementedClient = new UnimplementedTestServiceClient();
[Test]
public void ExpandedParamOverloadCanBeMocked()
{
var expected = new SimpleResponse();
var mockClient = new Mock<TestService.TestServiceClient>();
// mocking is relatively clumsy because one needs to specify value for all the optional params.
mockClient.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), null, null, CancellationToken.None)).Returns(expected);
Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest()));
}
[Test]
public void CallOptionsOverloadCanBeMocked()
{
var expected = new SimpleResponse();
var mockClient = new Mock<TestService.TestServiceClient>();
mockClient.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<CallOptions>())).Returns(expected);
Assert.AreSame(expected, mockClient.Object.UnaryCall(new SimpleRequest(), new CallOptions()));
}
[Test]
public void DefaultMethodStubThrows_UnaryCall()
{
Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.UnaryCall(new SimpleRequest()));
}
[Test]
public void DefaultMethodStubThrows_ClientStreaming()
{
Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingInputCall());
}
[Test]
public void DefaultMethodStubThrows_ServerStreaming()
{
Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.StreamingOutputCall(new StreamingOutputCallRequest()));
}
[Test]
public void DefaultMethodStubThrows_DuplexStreaming()
{
Assert.Throws(typeof(NotImplementedException), () => unimplementedClient.FullDuplexCall());
}
/// <summary>
/// Subclass of the generated client that doesn't override any method stubs.
/// </summary>
private class UnimplementedTestServiceClient : TestService.TestServiceClient
{
}
}
}

@ -0,0 +1,116 @@
#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.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Testing;
using Moq;
using NUnit.Framework;
namespace Grpc.IntegrationTesting
{
public class GeneratedServiceBaseTest
{
const string Host = "localhost";
Server server;
Channel channel;
TestService.TestServiceClient client;
[SetUp]
public void Init()
{
server = new Server
{
Services = { TestService.BindService(new UnimplementedTestServiceImpl()) },
Ports = { { Host, ServerPort.PickUnused, SslServerCredentials.Insecure } }
};
server.Start();
channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
client = TestService.NewClient(channel);
}
[TearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
[Test]
public void UnimplementedByDefault_Unary()
{
var ex = Assert.Throws<RpcException>(() => client.UnaryCall(new SimpleRequest { }));
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
[Test]
public async Task UnimplementedByDefault_ClientStreaming()
{
var call = client.StreamingInputCall();
var ex = Assert.Throws<RpcException>(async () => await call);
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
[Test]
public async Task UnimplementedByDefault_ServerStreamingCall()
{
var call = client.StreamingOutputCall(new StreamingOutputCallRequest());
var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
[Test]
public async Task UnimplementedByDefault_DuplexStreamingCall()
{
var call = client.FullDuplexCall();
var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext());
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
/// <summary>
/// Implementation of TestService that doesn't override any methods.
/// </summary>
private class UnimplementedTestServiceImpl : TestService.TestServiceBase
{
}
}
}

@ -84,7 +84,6 @@
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="HeaderInterceptorTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Empty.cs" />
<Compile Include="Messages.cs" />
@ -114,6 +113,8 @@
<Compile Include="QpsWorker.cs" />
<Compile Include="WallClockStopwatch.cs" />
<Compile Include="GenericService.cs" />
<Compile Include="GeneratedServiceBaseTest.cs" />
<Compile Include="GeneratedClientTest.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -217,7 +217,7 @@ namespace Grpc.IntegrationTesting
}
}
public static void RunEmptyUnary(TestService.ITestServiceClient client)
public static void RunEmptyUnary(TestService.TestServiceClient client)
{
Console.WriteLine("running empty_unary");
var response = client.EmptyCall(new Empty());
@ -225,7 +225,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunLargeUnary(TestService.ITestServiceClient client)
public static void RunLargeUnary(TestService.TestServiceClient client)
{
Console.WriteLine("running large_unary");
var request = new SimpleRequest
@ -241,7 +241,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunClientStreamingAsync(TestService.ITestServiceClient client)
public static async Task RunClientStreamingAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running client_streaming");
@ -257,7 +257,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunServerStreamingAsync(TestService.ITestServiceClient client)
public static async Task RunServerStreamingAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running server_streaming");
@ -281,7 +281,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunPingPongAsync(TestService.ITestServiceClient client)
public static async Task RunPingPongAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running ping_pong");
@ -338,7 +338,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunEmptyStreamAsync(TestService.ITestServiceClient client)
public static async Task RunEmptyStreamAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running empty_stream");
using (var call = client.FullDuplexCall())
@ -434,7 +434,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunCancelAfterBeginAsync(TestService.ITestServiceClient client)
public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running cancel_after_begin");
@ -451,7 +451,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunCancelAfterFirstResponseAsync(TestService.ITestServiceClient client)
public static async Task RunCancelAfterFirstResponseAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running cancel_after_first_response");
@ -477,7 +477,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunTimeoutOnSleepingServerAsync(TestService.ITestServiceClient client)
public static async Task RunTimeoutOnSleepingServerAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running timeout_on_sleeping_server");
@ -499,7 +499,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunCustomMetadataAsync(TestService.ITestServiceClient client)
public static async Task RunCustomMetadataAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running custom_metadata");
{
@ -546,7 +546,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static async Task RunStatusCodeAndMessageAsync(TestService.ITestServiceClient client)
public static async Task RunStatusCodeAndMessageAsync(TestService.TestServiceClient client)
{
Console.WriteLine("running status_code_and_message");
var echoStatus = new EchoStatus
@ -580,7 +580,7 @@ namespace Grpc.IntegrationTesting
Console.WriteLine("Passed!");
}
public static void RunUnimplementedMethod(UnimplementedService.IUnimplementedServiceClient client)
public static void RunUnimplementedMethod(UnimplementedService.UnimplementedServiceClient client)
{
Console.WriteLine("running unimplemented_method");
var e = Assert.Throws<RpcException>(() => client.UnimplementedCall(new Empty()));

@ -51,7 +51,7 @@ namespace Grpc.IntegrationTesting
const string Host = "localhost";
Server server;
Channel channel;
TestService.ITestServiceClient client;
TestService.TestServiceClient client;
[TestFixtureSetUp]
public void Init()

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -50,15 +50,15 @@ namespace Grpc.IntegrationTesting
const string Host = "localhost";
Server server;
Channel channel;
TestService.ITestServiceClient client;
TestService.TestServiceClient client;
List<ChannelOption> options;
Mock<TestService.ITestService> serviceMock;
Mock<TestService.TestServiceBase> serviceMock;
AsyncAuthInterceptor asyncAuthInterceptor;
[SetUp]
public void Init()
{
serviceMock = new Mock<TestService.ITestService>();
serviceMock = new Mock<TestService.TestServiceBase>();
serviceMock.Setup(m => m.UnaryCall(It.IsAny<SimpleRequest>(), It.IsAny<ServerCallContext>()))
.Returns(new Func<SimpleRequest, ServerCallContext, Task<SimpleResponse>>(UnaryCallHandler));

@ -36,6 +36,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IBenchmarkServiceClient
{
global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -47,47 +48,73 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IBenchmarkService
{
Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context);
Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context);
}
// server-side abstract class
public abstract class BenchmarkServiceBase
{
public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class BenchmarkServiceClient : ClientBase, IBenchmarkServiceClient
public class BenchmarkServiceClient : ClientBase<BenchmarkServiceClient>, IBenchmarkServiceClient
{
public BenchmarkServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public BenchmarkServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
}
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected BenchmarkServiceClient() : base()
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected BenchmarkServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_StreamingCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_StreamingCall, options);
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
}
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StreamingCall(new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options);
}
protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new BenchmarkServiceClient(configuration);
}
}
@ -99,6 +126,14 @@ namespace Grpc.Testing {
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall).Build();
}
// creates a new client
public static BenchmarkServiceClient NewClient(Channel channel)
{
@ -153,6 +188,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IWorkerServiceClient
{
AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -170,6 +206,7 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IWorkerService
{
Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context);
@ -178,71 +215,100 @@ namespace Grpc.Testing {
Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context);
}
// server-side abstract class
public abstract class WorkerServiceBase
{
public virtual Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class WorkerServiceClient : ClientBase, IWorkerServiceClient
public class WorkerServiceClient : ClientBase<WorkerServiceClient>, IWorkerServiceClient
{
public WorkerServiceClient(Channel channel) : base(channel)
{
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public WorkerServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_RunServer, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected WorkerServiceClient() : base()
{
var call = CreateCall(__Method_RunServer, options);
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected WorkerServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_RunClient, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_RunClient, options);
return Calls.AsyncDuplexStreamingCall(call);
return RunServer(new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
{
var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options);
}
public global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_CoreCount, options);
return Calls.BlockingUnaryCall(call, request);
return RunClient(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
{
var call = CreateCall(__Method_CoreCount, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options);
}
public AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_CoreCount, options);
return Calls.AsyncUnaryCall(call, request);
return CoreCount(request, new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
{
var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request);
}
public global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_QuitWorker, options);
return Calls.BlockingUnaryCall(call, request);
return CoreCountAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
{
var call = CreateCall(__Method_QuitWorker, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_QuitWorker, options);
return Calls.AsyncUnaryCall(call, request);
return QuitWorker(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request);
}
public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return QuitWorkerAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request);
}
protected override WorkerServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new WorkerServiceClient(configuration);
}
}
@ -256,6 +322,16 @@ namespace Grpc.Testing {
.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(WorkerServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_RunServer, serviceImpl.RunServer)
.AddMethod(__Method_RunClient, serviceImpl.RunClient)
.AddMethod(__Method_CoreCount, serviceImpl.CoreCount)
.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
}
// creates a new client
public static WorkerServiceClient NewClient(Channel channel)
{

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -53,7 +53,7 @@ namespace Grpc.IntegrationTesting
const string Host = "localhost";
Server server;
Channel channel;
TestService.ITestServiceClient client;
TestService.TestServiceClient client;
[TestFixtureSetUp]
public void Init()

@ -69,6 +69,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface ITestServiceClient
{
global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -90,6 +91,7 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface ITestService
{
Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context);
@ -100,91 +102,126 @@ namespace Grpc.Testing {
Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context);
}
// server-side abstract class
public abstract class TestServiceBase
{
public virtual Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class TestServiceClient : ClientBase, ITestServiceClient
public class TestServiceClient : ClientBase<TestServiceClient>, ITestServiceClient
{
public TestServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public TestServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
}
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected TestServiceClient() : base()
{
}
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected TestServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return EmptyCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options)
public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_EmptyCall, options);
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_EmptyCall, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return EmptyCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_EmptyCall, options);
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_EmptyCall, null, options, request);
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
{
var call = CreateCall(__Method_UnaryCall, options);
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
}
public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_StreamingOutputCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncServerStreamingCall(call, request);
return StreamingOutputCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options)
public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options)
{
var call = CreateCall(__Method_StreamingOutputCall, options);
return Calls.AsyncServerStreamingCall(call, request);
return CallInvoker.AsyncServerStreamingCall(__Method_StreamingOutputCall, null, options, request);
}
public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_StreamingInputCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncClientStreamingCall(call);
return StreamingInputCall(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
{
var call = CreateCall(__Method_StreamingInputCall, options);
return Calls.AsyncClientStreamingCall(call);
return CallInvoker.AsyncClientStreamingCall(__Method_StreamingInputCall, null, options);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_FullDuplexCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return FullDuplexCall(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
{
var call = CreateCall(__Method_FullDuplexCall, options);
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.AsyncDuplexStreamingCall(__Method_FullDuplexCall, null, options);
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_HalfDuplexCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncDuplexStreamingCall(call);
return HalfDuplexCall(new CallOptions(headers, deadline, cancellationToken));
}
public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
{
var call = CreateCall(__Method_HalfDuplexCall, options);
return Calls.AsyncDuplexStreamingCall(call);
return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options);
}
protected override TestServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new TestServiceClient(configuration);
}
}
@ -200,6 +237,18 @@ namespace Grpc.Testing {
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(TestServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall)
.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
.AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall)
.AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall)
.AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall)
.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall).Build();
}
// creates a new client
public static TestServiceClient NewClient(Channel channel)
{
@ -227,6 +276,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IUnimplementedServiceClient
{
global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -236,36 +286,59 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IUnimplementedService
{
Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context);
}
// server-side abstract class
public abstract class UnimplementedServiceBase
{
public virtual Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class UnimplementedServiceClient : ClientBase, IUnimplementedServiceClient
public class UnimplementedServiceClient : ClientBase<UnimplementedServiceClient>, IUnimplementedServiceClient
{
public UnimplementedServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public UnimplementedServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
}
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected UnimplementedServiceClient() : base()
{
}
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected UnimplementedServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return UnimplementedCall(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_UnimplementedCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request);
}
public global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_UnimplementedCall, options);
return Calls.BlockingUnaryCall(call, request);
return UnimplementedCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_UnimplementedCall, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
protected override UnimplementedServiceClient NewInstance(ClientBaseConfiguration configuration)
{
var call = CreateCall(__Method_UnimplementedCall, options);
return Calls.AsyncUnaryCall(call, request);
return new UnimplementedServiceClient(configuration);
}
}
@ -276,6 +349,13 @@ namespace Grpc.Testing {
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
}
// creates a new client
public static UnimplementedServiceClient NewClient(Channel channel)
{
@ -311,6 +391,7 @@ namespace Grpc.Testing {
}
// client interface
[System.Obsolete("Client side interfaced will be removed in the next release. Use client class directly.")]
public interface IReconnectServiceClient
{
global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken));
@ -324,57 +405,81 @@ namespace Grpc.Testing {
}
// server-side interface
[System.Obsolete("Service implementations should inherit from the generated abstract base class instead.")]
public interface IReconnectService
{
Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.Empty request, ServerCallContext context);
Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context);
}
// server-side abstract class
public abstract class ReconnectServiceBase
{
public virtual Task<global::Grpc.Testing.Empty> Start(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
public virtual Task<global::Grpc.Testing.ReconnectInfo> Stop(global::Grpc.Testing.Empty request, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
// client stub
public class ReconnectServiceClient : ClientBase, IReconnectServiceClient
public class ReconnectServiceClient : ClientBase<ReconnectServiceClient>, IReconnectServiceClient
{
public ReconnectServiceClient(Channel channel) : base(channel)
{
}
public global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public ReconnectServiceClient(CallInvoker callInvoker) : base(callInvoker)
{
var call = CreateCall(__Method_Start, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
}
public global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, CallOptions options)
///<summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected ReconnectServiceClient() : base()
{
var call = CreateCall(__Method_Start, options);
return Calls.BlockingUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
///<summary>Protected constructor to allow creation of configured clients.</summary>
protected ReconnectServiceClient(ClientBaseConfiguration configuration) : base(configuration)
{
var call = CreateCall(__Method_Start, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
}
public AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, CallOptions options)
public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Start, options);
return Calls.AsyncUnaryCall(call, request);
return Start(request, new CallOptions(headers, deadline, cancellationToken));
}
public global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual global::Grpc.Testing.Empty Start(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_Stop, new CallOptions(headers, deadline, cancellationToken));
return Calls.BlockingUnaryCall(call, request);
return CallInvoker.BlockingUnaryCall(__Method_Start, null, options, request);
}
public global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options)
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Stop, options);
return Calls.BlockingUnaryCall(call, request);
return StartAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> StartAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
var call = CreateCall(__Method_Stop, new CallOptions(headers, deadline, cancellationToken));
return Calls.AsyncUnaryCall(call, request);
return CallInvoker.AsyncUnaryCall(__Method_Start, null, options, request);
}
public AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options)
public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
var call = CreateCall(__Method_Stop, options);
return Calls.AsyncUnaryCall(call, request);
return Stop(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual global::Grpc.Testing.ReconnectInfo Stop(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.BlockingUnaryCall(__Method_Stop, null, options, request);
}
public virtual AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return StopAsync(request, new CallOptions(headers, deadline, cancellationToken));
}
public virtual AsyncUnaryCall<global::Grpc.Testing.ReconnectInfo> StopAsync(global::Grpc.Testing.Empty request, CallOptions options)
{
return CallInvoker.AsyncUnaryCall(__Method_Stop, null, options, request);
}
protected override ReconnectServiceClient NewInstance(ClientBaseConfiguration configuration)
{
return new ReconnectServiceClient(configuration);
}
}
@ -386,6 +491,14 @@ namespace Grpc.Testing {
.AddMethod(__Method_Stop, serviceImpl.Stop).Build();
}
// creates service definition that can be registered with a server
public static ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder(__ServiceName)
.AddMethod(__Method_Start, serviceImpl.Start)
.AddMethod(__Method_Stop, serviceImpl.Stop).Build();
}
// creates a new client
public static ReconnectServiceClient NewClient(Channel channel)
{

@ -1,6 +1,6 @@
#region Copyright notice and license
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -45,14 +45,14 @@ namespace Grpc.Testing
/// <summary>
/// Implementation of TestService server
/// </summary>
public class TestServiceImpl : TestService.ITestService
public class TestServiceImpl : TestService.TestServiceBase
{
public Task<Empty> EmptyCall(Empty request, ServerCallContext context)
public override Task<Empty> EmptyCall(Empty request, ServerCallContext context)
{
return Task.FromResult(new Empty());
}
public async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
public override async Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context)
{
await EnsureEchoMetadataAsync(context);
EnsureEchoStatus(request.ResponseStatus, context);
@ -61,7 +61,7 @@ namespace Grpc.Testing
return response;
}
public async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
public override async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
await EnsureEchoMetadataAsync(context);
EnsureEchoStatus(request.ResponseStatus, context);
@ -73,7 +73,7 @@ namespace Grpc.Testing
}
}
public async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
public override async Task<StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<StreamingInputCallRequest> requestStream, ServerCallContext context)
{
await EnsureEchoMetadataAsync(context);
@ -85,7 +85,7 @@ namespace Grpc.Testing
return new StreamingInputCallResponse { AggregatedPayloadSize = sum };
}
public async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
public override async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
await EnsureEchoMetadataAsync(context);
@ -100,7 +100,7 @@ namespace Grpc.Testing
});
}
public async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
public override async Task HalfDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context)
{
throw new NotImplementedException();
}

@ -45,7 +45,7 @@ namespace Grpc.Testing
/// <summary>
/// Implementation of WorkerService server
/// </summary>
public class WorkerServiceImpl : WorkerService.IWorkerService
public class WorkerServiceImpl : WorkerService.WorkerServiceBase
{
readonly Action stopRequestHandler;
@ -54,7 +54,7 @@ namespace Grpc.Testing
this.stopRequestHandler = GrpcPreconditions.CheckNotNull(stopRequestHandler);
}
public async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
public override async Task RunServer(IAsyncStreamReader<ServerArgs> requestStream, IServerStreamWriter<ServerStatus> responseStream, ServerCallContext context)
{
GrpcPreconditions.CheckState(await requestStream.MoveNext());
var serverConfig = requestStream.Current.Setup;
@ -78,7 +78,7 @@ namespace Grpc.Testing
await runner.StopAsync();
}
public async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
public override async Task RunClient(IAsyncStreamReader<ClientArgs> requestStream, IServerStreamWriter<ClientStatus> responseStream, ServerCallContext context)
{
GrpcPreconditions.CheckState(await requestStream.MoveNext());
var clientConfig = requestStream.Current.Setup;
@ -100,12 +100,12 @@ namespace Grpc.Testing
await runner.StopAsync();
}
public Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context)
public override Task<CoreResponse> CoreCount(CoreRequest request, ServerCallContext context)
{
return Task.FromResult(new CoreResponse { Cores = Environment.ProcessorCount });
}
public Task<Void> QuitWorker(Void request, ServerCallContext context)
public override Task<Void> QuitWorker(Void request, ServerCallContext context)
{
stopRequestHandler();
return Task.FromResult(new Void());

@ -10,7 +10,7 @@
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Native extension needed by gRPC C# library. This is not the package you are looking for, it is only meant to be used as a dependency.</description>
<releaseNotes>Release of gRPC C core $version$ libraries.</releaseNotes>
<copyright>Copyright 2015-2016</copyright>
<copyright>Copyright 2015</copyright>
<title>gRPC C# Native Extension</title>
<summary>Native library required by gRPC C#</summary>
<tags>gRPC native</tags>

@ -36,8 +36,9 @@
"Math.Tests.MathClientServerTest",
"Grpc.HealthCheck.Tests.HealthClientServerTest",
"Grpc.HealthCheck.Tests.HealthServiceImplTest",
"Grpc.IntegrationTesting.HeaderInterceptorTest",
"Grpc.IntegrationTesting.HistogramTest",
"Grpc.IntegrationTesting.GeneratedClientTest",
"Grpc.IntegrationTesting.GeneratedServiceBaseTest",
"Grpc.IntegrationTesting.InteropClientServerTest",
"Grpc.IntegrationTesting.MetadataCredentialsTest",
"Grpc.IntegrationTesting.RunnerClientServerTest",

@ -1,5 +1,5 @@
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -158,6 +158,12 @@ message StreamingOutputCallResponse {
Payload payload = 1;
}
// For reconnect interop test only.
// Client tells server what reconnection parameters it used.
message ReconnectParams {
int32 max_reconnect_backoff_ms = 1;
}
// For reconnect interop test only.
// Server tells client whether its reconnects are following the spec and the
// reconnect backoffs it saw.

@ -1,5 +1,5 @@
// Copyright 2015, Google Inc.
// Copyright 2015-2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -80,6 +80,6 @@ service UnimplementedService {
// A service used to control reconnect server.
service ReconnectService {
rpc Start(grpc.testing.Empty) returns (grpc.testing.Empty);
rpc Start(grpc.testing.ReconnectParams) returns (grpc.testing.Empty);
rpc Stop(grpc.testing.Empty) returns (grpc.testing.ReconnectInfo);
}

@ -283,7 +283,7 @@ extern grpc_call_destroy_type grpc_call_destroy_import;
typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
extern grpc_server_request_call_type grpc_server_request_call_import;
#define grpc_server_request_call grpc_server_request_call_import
typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, uint32_t flags);
typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags);
extern grpc_server_register_method_type grpc_server_register_method_import;
#define grpc_server_register_method grpc_server_register_method_import
typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -123,6 +123,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/channel/subchannel_call_holder.c',
'src/core/lib/client_config/client_channel_factory.c',
'src/core/lib/client_config/client_config.c',
'src/core/lib/client_config/connector.c',
'src/core/lib/client_config/default_initial_connect_string.c',
@ -134,7 +135,6 @@ CORE_SOURCE_FILES = [
'src/core/lib/client_config/resolver_factory.c',
'src/core/lib/client_config/resolver_registry.c',
'src/core/lib/client_config/subchannel.c',
'src/core/lib/client_config/subchannel_factory.c',
'src/core/lib/client_config/subchannel_index.c',
'src/core/lib/client_config/uri_parser.c',
'src/core/lib/compression/compression_algorithm.c',

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -1,4 +1,4 @@
# Copyright 2015-2016, Google Inc.
# Copyright 2015, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without

@ -283,7 +283,7 @@ extern grpc_call_destroy_type grpc_call_destroy_import;
typedef grpc_call_error(*grpc_server_request_call_type)(grpc_server *server, grpc_call **call, grpc_call_details *details, grpc_metadata_array *request_metadata, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);
extern grpc_server_request_call_type grpc_server_request_call_import;
#define grpc_server_request_call grpc_server_request_call_import
typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, uint32_t flags);
typedef void *(*grpc_server_register_method_type)(grpc_server *server, const char *method, const char *host, grpc_server_register_method_payload_handling payload_handling, uint32_t flags);
extern grpc_server_register_method_type grpc_server_register_method_import;
#define grpc_server_register_method grpc_server_register_method_import
typedef grpc_call_error(*grpc_server_request_registered_call_type)(grpc_server *server, void *registered_method, grpc_call **call, gpr_timespec *deadline, grpc_metadata_array *request_metadata, grpc_byte_buffer **optional_payload, grpc_completion_queue *cq_bound_to_call, grpc_completion_queue *cq_for_notification, void *tag_new);

@ -403,7 +403,7 @@ module GRPC
loop_handle_server_calls
end
# Sends UNAVAILABLE if there are too many unprocessed jobs
# Sends RESOURCE_EXHAUSTED if there are too many unprocessed jobs
def available?(an_rpc)
jobs_count, max = @pool.jobs_waiting, @max_waiting_requests
GRPC.logger.info("waiting: #{jobs_count}, max: #{max}")
@ -411,7 +411,7 @@ module GRPC
GRPC.logger.warn("NOT AVAILABLE: too many jobs_waiting: #{an_rpc}")
noop = proc { |x| x }
c = ActiveCall.new(an_rpc.call, @cq, noop, noop, an_rpc.deadline)
c.send_status(StatusCodes::UNAVAILABLE, '')
c.send_status(StatusCodes::RESOURCE_EXHAUSTED, '')
nil
end

@ -426,7 +426,7 @@ describe GRPC::RpcServer do
threads.each(&:join)
end
it 'should return UNAVAILABLE on too many jobs', server: true do
it 'should return RESOURCE_EXHAUSTED on too many jobs', server: true do
opts = {
a_channel_arg: 'an_arg',
server_override: @server,
@ -449,7 +449,8 @@ describe GRPC::RpcServer do
begin
stub.an_rpc(req)
rescue GRPC::BadStatus => e
one_failed_as_unavailable = e.code == StatusCodes::UNAVAILABLE
one_failed_as_unavailable =
e.code == StatusCodes::RESOURCE_EXHAUSTED
end
end
end

@ -109,7 +109,8 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator,
grpc_server_register_completion_queue(a.server, a.cq, NULL);
a.registered_method =
grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD,
GRPC_BAD_CLIENT_REGISTERED_HOST, 0);
GRPC_BAD_CLIENT_REGISTERED_HOST,
GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0);
grpc_server_start(a.server);
transport = grpc_create_chttp2_transport(&exec_ctx, NULL, sfd.server, 0);
server_setup_transport(&a, transport);

@ -44,6 +44,7 @@ BAD_CLIENT_TESTS = {
'connection_prefix': default_test_options._replace(cpu_cost=0.2),
'headers': default_test_options._replace(cpu_cost=0.2),
'initial_settings_frame': default_test_options._replace(cpu_cost=0.2),
'head_of_line_blocking': default_test_options,
'server_registered_method': default_test_options,
'simple_request': default_test_options,
'window_overflow': default_test_options,

@ -0,0 +1,151 @@
/*
*
* 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 "test/core/bad_client/bad_client.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include "src/core/lib/surface/server.h"
#include "test/core/end2end/cq_verifier.h"
static const char prefix[] =
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
// settings frame
"\x00\x00\x00\x04\x00\x00\x00\x00\x00"
// stream 1 headers: generated from server_registered_method.headers in this
// directory
"\x00\x00\xd0\x01\x04\x00\x00\x00\x01"
"\x10\x05:path\x0f/registered/bar"
"\x10\x07:scheme\x04http"
"\x10\x07:method\x04POST"
"\x10\x0a:authority\x09localhost"
"\x10\x0c"
"content-type\x10"
"application/grpc"
"\x10\x14grpc-accept-encoding\x15identity,deflate,gzip"
"\x10\x02te\x08trailers"
"\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
// data frame for stream 1: advertise a 10000 byte payload (that we won't
// fulfill)
"\x00\x00\x05\x00\x00\x00\x00\x00\x01"
"\x01\x00\x00\x27\x10"
// stream 3 headers: generated from server_registered_method.headers in this
// directory
"\x00\x00\xd0\x01\x04\x00\x00\x00\x03"
"\x10\x05:path\x0f/registered/bar"
"\x10\x07:scheme\x04http"
"\x10\x07:method\x04POST"
"\x10\x0a:authority\x09localhost"
"\x10\x0c"
"content-type\x10"
"application/grpc"
"\x10\x14grpc-accept-encoding\x15identity,deflate,gzip"
"\x10\x02te\x08trailers"
"\x10\x0auser-agent\"bad-client grpc-c/0.12.0.0 (linux)"
// data frame for stream 3: advertise a 10000 byte payload (that we will
// fulfill)
"\x00\x00\x05\x00\x00\x00\x00\x00\x03"
"\x01\x00\x00\x27\x10"
"";
static void *tag(intptr_t t) { return (void *)t; }
static void verifier(grpc_server *server, grpc_completion_queue *cq,
void *registered_method) {
grpc_call_error error;
grpc_call *s;
cq_verifier *cqv = cq_verifier_create(cq);
grpc_metadata_array request_metadata_recv;
gpr_timespec deadline;
grpc_byte_buffer *payload = NULL;
grpc_metadata_array_init(&request_metadata_recv);
error = grpc_server_request_registered_call(server, registered_method, &s,
&deadline, &request_metadata_recv,
&payload, cq, cq, tag(101));
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(101), 1);
cq_verify(cqv);
GPR_ASSERT(payload != NULL);
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_destroy(s);
grpc_byte_buffer_destroy(payload);
cq_verifier_destroy(cqv);
}
char *g_buffer;
size_t g_cap = 0;
size_t g_count = 0;
static void addbuf(const void *data, size_t len) {
if (g_count + len > g_cap) {
g_cap = GPR_MAX(g_count + len, g_cap * 2);
g_buffer = gpr_realloc(g_buffer, g_cap);
}
memcpy(g_buffer + g_count, data, len);
g_count += len;
}
int main(int argc, char **argv) {
int i;
grpc_test_init(argc, argv);
#define NUM_FRAMES 10
#define FRAME_SIZE 1000
addbuf(prefix, sizeof(prefix) - 1);
for (i = 0; i < NUM_FRAMES; i++) {
uint8_t hdr[9] = {(uint8_t)(FRAME_SIZE >> 16),
(uint8_t)(FRAME_SIZE >> 8),
(uint8_t)FRAME_SIZE,
0,
0,
0,
0,
0,
3};
uint8_t msg[FRAME_SIZE];
memset(msg, 'a', sizeof(msg));
addbuf(hdr, sizeof(hdr));
addbuf(msg, FRAME_SIZE);
}
grpc_run_bad_client_test(verifier, g_buffer, g_count, 0);
gpr_free(g_buffer);
return 0;
}

@ -87,7 +87,7 @@ static void run_test(const char *target, size_t nops) {
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->flags = GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY;
op->reserved = NULL;
op++;
op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;

@ -41,20 +41,28 @@
#include "src/core/lib/iomgr/timer.h"
#include "test/core/util/test_config.h"
static void subchannel_factory_ref(grpc_subchannel_factory *scv) {}
static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *scv) {}
static grpc_subchannel *subchannel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *scv) {}
static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
grpc_subchannel_args *args) {
return NULL;
}
static const grpc_subchannel_factory_vtable sc_vtable = {
subchannel_factory_ref, subchannel_factory_unref,
subchannel_factory_create_subchannel};
static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type,
grpc_channel_args *args) {
GPR_UNREACHABLE_CODE(return NULL);
}
static const grpc_client_channel_factory_vtable sc_vtable = {
client_channel_factory_ref, client_channel_factory_unref,
client_channel_factory_create_subchannel,
client_channel_factory_create_channel};
static grpc_subchannel_factory sc_factory = {&sc_vtable};
static grpc_client_channel_factory cc_factory = {&sc_vtable};
static gpr_mu g_mu;
static bool g_fail_resolution = true;
@ -84,7 +92,7 @@ static grpc_resolver *create_resolver(const char *name) {
grpc_resolver_args args;
memset(&args, 0, sizeof(args));
args.uri = uri;
args.subchannel_factory = &sc_factory;
args.client_channel_factory = &cc_factory;
grpc_resolver *resolver =
grpc_resolver_factory_create_resolver(factory, &args);
grpc_resolver_factory_unref(factory);

@ -38,20 +38,28 @@
#include "src/core/lib/client_config/resolver_registry.h"
#include "test/core/util/test_config.h"
static void subchannel_factory_ref(grpc_subchannel_factory *scv) {}
static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *scv) {}
static grpc_subchannel *subchannel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *scv) {}
static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
grpc_subchannel_args *args) {
GPR_UNREACHABLE_CODE(return NULL);
}
static const grpc_subchannel_factory_vtable sc_vtable = {
subchannel_factory_ref, subchannel_factory_unref,
subchannel_factory_create_subchannel};
static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type,
grpc_channel_args *args) {
GPR_UNREACHABLE_CODE(return NULL);
}
static const grpc_client_channel_factory_vtable sc_vtable = {
client_channel_factory_ref, client_channel_factory_unref,
client_channel_factory_create_subchannel,
client_channel_factory_create_channel};
static grpc_subchannel_factory sc_factory = {&sc_vtable};
static grpc_client_channel_factory cc_factory = {&sc_vtable};
static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@ -63,7 +71,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri);
memset(&args, 0, sizeof(args));
args.uri = uri;
args.subchannel_factory = &sc_factory;
args.client_channel_factory = &cc_factory;
resolver = grpc_resolver_factory_create_resolver(factory, &args);
GPR_ASSERT(resolver != NULL);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");

@ -38,20 +38,28 @@
#include "src/core/lib/client_config/resolver_registry.h"
#include "test/core/util/test_config.h"
static void subchannel_factory_ref(grpc_subchannel_factory *scv) {}
static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel_factory *scv) {}
static grpc_subchannel *subchannel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *factory,
static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *scv) {}
static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
grpc_subchannel_args *args) {
GPR_UNREACHABLE_CODE(return NULL);
}
static const grpc_subchannel_factory_vtable sc_vtable = {
subchannel_factory_ref, subchannel_factory_unref,
subchannel_factory_create_subchannel};
static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type,
grpc_channel_args *args) {
GPR_UNREACHABLE_CODE(return NULL);
}
static const grpc_client_channel_factory_vtable sc_vtable = {
client_channel_factory_ref, client_channel_factory_unref,
client_channel_factory_create_subchannel,
client_channel_factory_create_channel};
static grpc_subchannel_factory sc_factory = {&sc_vtable};
static grpc_client_channel_factory cc_factory = {&sc_vtable};
static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@ -63,7 +71,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
GPR_ASSERT(uri);
memset(&args, 0, sizeof(args));
args.uri = uri;
args.subchannel_factory = &sc_factory;
args.client_channel_factory = &cc_factory;
resolver = grpc_resolver_factory_create_resolver(factory, &args);
GPR_ASSERT(resolver != NULL);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");

@ -168,7 +168,7 @@ void test_connect(const char *server_host, const char *client_host, int port,
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
op->flags = 0;
op->flags = expect_ok ? GRPC_INITIAL_METADATA_IGNORE_CONNECTIVITY : 0;
op->reserved = NULL;
op++;
op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
@ -237,7 +237,7 @@ void test_connect(const char *server_host, const char *client_host, int port,
cq_expect_completion(cqv, tag(1), 1);
cq_verify(cqv);
GPR_ASSERT(status == GRPC_STATUS_DEADLINE_EXCEEDED);
GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
}
grpc_call_destroy(c);

@ -1,6 +1,6 @@
/*
*
* Copyright 2015-2016, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

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

Loading…
Cancel
Save