Merge github.com:grpc/grpc into direct-calls

reviewable/pr8008/r5
Craig Tiller 8 years ago
commit 1edc77c7c6
  1. 18
      BUILD
  2. 7
      CMakeLists.txt
  3. 44
      Makefile
  4. 2
      binding.gyp
  5. 14
      build.yaml
  6. 2
      config.m4
  7. 15
      doc/core/pending_api_cleanups.md
  8. 192
      doc/server_reflection_tutorial.md
  9. 8
      gRPC-Core.podspec
  10. 4
      grpc.gemspec
  11. 73
      include/grpc++/impl/codegen/call.h
  12. 4
      include/grpc++/impl/codegen/method_handler_impl.h
  13. 7
      include/grpc++/impl/codegen/proto_utils.h
  14. 4
      include/grpc++/impl/codegen/rpc_service_method.h
  15. 8
      include/grpc++/impl/codegen/serialization_traits.h
  16. 6
      include/grpc++/impl/codegen/server_interface.h
  17. 8
      include/grpc++/impl/codegen/sync_stream.h
  18. 2
      include/grpc++/impl/codegen/thrift_utils.h
  19. 12
      include/grpc++/server.h
  20. 20
      include/grpc++/server_builder.h
  21. 2
      include/grpc++/support/byte_buffer.h
  22. 6
      include/grpc/impl/codegen/grpc_types.h
  23. 4
      package.xml
  24. 86
      src/core/ext/census/trace_context.c
  25. 68
      src/core/ext/census/trace_context.h
  26. 18
      src/core/ext/census/tracing.c
  27. 38
      src/core/ext/client_config/lb_policy_factory.c
  28. 32
      src/core/ext/client_config/lb_policy_factory.h
  29. 80
      src/core/ext/client_config/resolver_result.c
  30. 83
      src/core/ext/client_config/resolver_result.h
  31. 26
      src/core/ext/client_config/subchannel.c
  32. 149
      src/core/ext/lb_policy/grpclb/grpclb.c
  33. 23
      src/core/ext/lb_policy/pick_first/pick_first.c
  34. 36
      src/core/ext/lb_policy/round_robin/round_robin.c
  35. 23
      src/core/ext/resolver/dns/native/dns_resolver.c
  36. 41
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  37. 144
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  38. 18
      src/core/lib/channel/channel_args.c
  39. 8
      src/core/lib/channel/channel_args.h
  40. 165
      src/core/lib/channel/message_size_filter.c
  41. 39
      src/core/lib/channel/message_size_filter.h
  42. 25
      src/core/lib/security/credentials/plugin/plugin_credentials.c
  43. 11
      src/core/lib/surface/call.c
  44. 21
      src/core/lib/surface/channel.c
  45. 1
      src/core/lib/surface/channel.h
  46. 10
      src/core/lib/surface/init.c
  47. 15
      src/cpp/server/server_builder.cc
  48. 10
      src/cpp/server/server_cc.cc
  49. 4
      src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
  50. 102
      src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
  51. 31
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  52. 40
      src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
  53. 6
      src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
  54. 2
      src/objective-c/GRPCClient/private/GRPCHost.m
  55. 2
      src/objective-c/tests/InteropTests.m
  56. 4
      src/objective-c/tests/run_tests.sh
  57. 12
      src/python/grpcio/grpc/__init__.py
  58. 17
      src/python/grpcio/grpc/_channel.py
  59. 10
      src/python/grpcio/grpc/_common.py
  60. 5
      src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
  61. 2
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
  62. 2
      src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
  63. 4
      src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
  64. 5
      src/python/grpcio/grpc/_server.py
  65. 2
      src/python/grpcio/grpc_core_dependencies.py
  66. 1
      src/python/grpcio_tests/tests/tests.json
  67. 53
      src/python/grpcio_tests/tests/unit/_channel_args_test.py
  68. 10
      src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
  69. 2
      src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
  70. 5
      src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
  71. 5
      src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
  72. 9
      src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
  73. 2
      src/ruby/ext/grpc/rb_channel.c
  74. 0
      test/core/census/data/context_empty.pb
  75. 0
      test/core/census/data/context_empty.txt
  76. BIN
      test/core/census/data/context_full.pb
  77. 3
      test/core/census/data/context_full.txt
  78. BIN
      test/core/census/data/context_no_sample.pb
  79. 2
      test/core/census/data/context_no_sample.txt
  80. BIN
      test/core/census/data/context_span_only.pb
  81. 2
      test/core/census/data/context_span_only.txt
  82. BIN
      test/core/census/data/context_trace_only.pb
  83. 2
      test/core/census/data/context_trace_only.txt
  84. 231
      test/core/census/trace_context_test.c
  85. 51
      test/core/end2end/tests/max_message_length.c
  86. 34
      test/core/surface/invalid_channel_args_test.c
  87. 63
      test/cpp/end2end/end2end_test.cc
  88. 4
      test/cpp/interop/interop_server.cc
  89. 2
      tools/doxygen/Doxyfile.c++.internal
  90. 4
      tools/doxygen/Doxyfile.core.internal
  91. 2
      tools/run_tests/run_build_statistics.py
  92. 24
      tools/run_tests/sources_and_headers.json
  93. 21
      tools/run_tests/tests.json
  94. 27
      vsprojects/buildtests_c.sln
  95. 3
      vsprojects/vcxproj/grpc++/grpc++.vcxproj
  96. 6
      vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
  97. 3
      vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
  98. 6
      vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
  99. 6
      vsprojects/vcxproj/grpc/grpc.vcxproj
  100. 12
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  101. Some files were not shown because too many files have changed in this diff Show More

18
BUILD

@ -171,6 +171,7 @@ cc_library(
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/debug/trace.h",
@ -317,6 +318,7 @@ cc_library(
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
"src/core/ext/census/trace_context.h",
"src/core/lib/surface/init.c",
"src/core/lib/channel/channel_args.c",
"src/core/lib/channel/channel_stack.c",
@ -326,6 +328,7 @@ cc_library(
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/debug/trace.c",
@ -502,6 +505,7 @@ cc_library(
"src/core/ext/census/operation.c",
"src/core/ext/census/placeholders.c",
"src/core/ext/census/resource.c",
"src/core/ext/census/trace_context.c",
"src/core/ext/census/tracing.c",
"src/core/plugin_registry/grpc_plugin_registry.c",
],
@ -562,6 +566,7 @@ cc_library(
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/debug/trace.h",
@ -703,6 +708,7 @@ cc_library(
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/debug/trace.c",
@ -910,6 +916,7 @@ cc_library(
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/debug/trace.h",
@ -1032,6 +1039,7 @@ cc_library(
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
"src/core/ext/census/trace_context.h",
"src/core/lib/surface/init.c",
"src/core/lib/surface/init_unsecure.c",
"src/core/lib/channel/channel_args.c",
@ -1042,6 +1050,7 @@ cc_library(
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/debug/trace.c",
@ -1188,6 +1197,7 @@ cc_library(
"src/core/ext/census/operation.c",
"src/core/ext/census/placeholders.c",
"src/core/ext/census/resource.c",
"src/core/ext/census/trace_context.c",
"src/core/ext/census/tracing.c",
"src/core/plugin_registry/grpc_unsecure_plugin_registry.c",
],
@ -1253,6 +1263,7 @@ cc_library(
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/debug/trace.h",
@ -1365,6 +1376,7 @@ cc_library(
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/debug/trace.c",
@ -1657,6 +1669,7 @@ cc_library(
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/debug/trace.h",
@ -1764,6 +1777,7 @@ cc_library(
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/debug/trace.c",
@ -2150,6 +2164,7 @@ objc_library(
"src/core/lib/channel/handshaker.c",
"src/core/lib/channel/http_client_filter.c",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",
"src/core/lib/debug/trace.c",
@ -2326,6 +2341,7 @@ objc_library(
"src/core/ext/census/operation.c",
"src/core/ext/census/placeholders.c",
"src/core/ext/census/resource.c",
"src/core/ext/census/trace_context.c",
"src/core/ext/census/tracing.c",
"src/core/plugin_registry/grpc_plugin_registry.c",
],
@ -2365,6 +2381,7 @@ objc_library(
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/debug/trace.h",
@ -2511,6 +2528,7 @@ objc_library(
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
"src/core/ext/census/trace_context.h",
],
includes = [
"include",

@ -298,6 +298,7 @@ add_library(grpc
src/core/lib/channel/handshaker.c
src/core/lib/channel/http_client_filter.c
src/core/lib/channel/http_server_filter.c
src/core/lib/channel/message_size_filter.c
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/debug/trace.c
@ -477,6 +478,7 @@ add_library(grpc
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
src/core/ext/census/resource.c
src/core/ext/census/trace_context.c
src/core/ext/census/tracing.c
src/core/plugin_registry/grpc_plugin_registry.c
)
@ -552,6 +554,7 @@ add_library(grpc_cronet
src/core/lib/channel/handshaker.c
src/core/lib/channel/http_client_filter.c
src/core/lib/channel/http_server_filter.c
src/core/lib/channel/message_size_filter.c
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/debug/trace.c
@ -779,6 +782,7 @@ add_library(grpc_unsecure
src/core/lib/channel/handshaker.c
src/core/lib/channel/http_client_filter.c
src/core/lib/channel/http_server_filter.c
src/core/lib/channel/message_size_filter.c
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/debug/trace.c
@ -928,6 +932,7 @@ add_library(grpc_unsecure
src/core/ext/census/operation.c
src/core/ext/census/placeholders.c
src/core/ext/census/resource.c
src/core/ext/census/trace_context.c
src/core/ext/census/tracing.c
src/core/plugin_registry/grpc_unsecure_plugin_registry.c
)
@ -1032,6 +1037,7 @@ add_library(grpc++
src/core/lib/channel/handshaker.c
src/core/lib/channel/http_client_filter.c
src/core/lib/channel/http_server_filter.c
src/core/lib/channel/message_size_filter.c
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/debug/trace.c
@ -1383,6 +1389,7 @@ add_library(grpc++_unsecure
src/core/lib/channel/handshaker.c
src/core/lib/channel/http_client_filter.c
src/core/lib/channel/http_server_filter.c
src/core/lib/channel/message_size_filter.c
src/core/lib/compression/compression.c
src/core/lib/compression/message_compress.c
src/core/lib/debug/trace.c

@ -909,6 +909,7 @@ bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test
census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test
channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test
chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
@ -1237,6 +1238,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/bin_encoder_test \
$(BINDIR)/$(CONFIG)/census_context_test \
$(BINDIR)/$(CONFIG)/census_resource_test \
$(BINDIR)/$(CONFIG)/census_trace_context_test \
$(BINDIR)/$(CONFIG)/channel_create_test \
$(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \
$(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \
@ -1551,6 +1553,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
$(E) "[RUN] Testing census_resource_test"
$(Q) $(BINDIR)/$(CONFIG)/census_resource_test || ( echo test census_resource_test failed ; exit 1 )
$(E) "[RUN] Testing census_trace_context_test"
$(Q) $(BINDIR)/$(CONFIG)/census_trace_context_test || ( echo test census_trace_context_test failed ; exit 1 )
$(E) "[RUN] Testing channel_create_test"
$(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 )
$(E) "[RUN] Testing chttp2_hpack_encoder_test"
@ -2527,6 +2531,7 @@ LIBGRPC_SRC = \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
@ -2706,6 +2711,7 @@ LIBGRPC_SRC = \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
src/core/ext/census/resource.c \
src/core/ext/census/trace_context.c \
src/core/ext/census/tracing.c \
src/core/plugin_registry/grpc_plugin_registry.c \
@ -2799,6 +2805,7 @@ LIBGRPC_CRONET_SRC = \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
@ -3060,6 +3067,7 @@ LIBGRPC_TEST_UTIL_SRC = \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
@ -3249,6 +3257,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
@ -3398,6 +3407,7 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
src/core/ext/census/resource.c \
src/core/ext/census/trace_context.c \
src/core/ext/census/tracing.c \
src/core/plugin_registry/grpc_unsecure_plugin_registry.c \
@ -3585,6 +3595,7 @@ LIBGRPC++_SRC = \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
@ -4211,6 +4222,7 @@ LIBGRPC++_UNSECURE_SRC = \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
@ -7199,6 +7211,38 @@ endif
endif
CENSUS_TRACE_CONTEXT_TEST_SRC = \
test/core/census/trace_context_test.c \
CENSUS_TRACE_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_TRACE_CONTEXT_TEST_SRC))))
ifeq ($(NO_SECURE),true)
# You can't build secure targets if you don't have OpenSSL.
$(BINDIR)/$(CONFIG)/census_trace_context_test: openssl_dep_error
else
$(BINDIR)/$(CONFIG)/census_trace_context_test: $(CENSUS_TRACE_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
$(Q) $(LD) $(LDFLAGS) $(CENSUS_TRACE_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_trace_context_test
endif
$(OBJDIR)/$(CONFIG)/test/core/census/trace_context_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
deps_census_trace_context_test: $(CENSUS_TRACE_CONTEXT_TEST_OBJS:.o=.dep)
ifneq ($(NO_SECURE),true)
ifneq ($(NO_DEPS),true)
-include $(CENSUS_TRACE_CONTEXT_TEST_OBJS:.o=.dep)
endif
endif
CHANNEL_CREATE_TEST_SRC = \
test/core/surface/channel_create_test.c \

@ -573,6 +573,7 @@
'src/core/lib/channel/handshaker.c',
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/channel/message_size_filter.c',
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/debug/trace.c',
@ -752,6 +753,7 @@
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
'src/core/ext/census/resource.c',
'src/core/ext/census/trace_context.c',
'src/core/ext/census/tracing.c',
'src/core/plugin_registry/grpc_plugin_registry.c',
],

@ -29,6 +29,7 @@ filegroups:
- src/core/ext/census/mlog.h
- src/core/ext/census/resource.h
- src/core/ext/census/rpc_metric_id.h
- src/core/ext/census/trace_context.h
src:
- src/core/ext/census/base_resources.c
- src/core/ext/census/context.c
@ -42,6 +43,7 @@ filegroups:
- src/core/ext/census/operation.c
- src/core/ext/census/placeholders.c
- src/core/ext/census/resource.c
- src/core/ext/census/trace_context.c
- src/core/ext/census/tracing.c
plugin: census_grpc_plugin
uses:
@ -173,6 +175,7 @@ filegroups:
- src/core/lib/channel/handshaker.h
- src/core/lib/channel/http_client_filter.h
- src/core/lib/channel/http_server_filter.h
- src/core/lib/channel/message_size_filter.h
- src/core/lib/compression/algorithm_metadata.h
- src/core/lib/compression/message_compress.h
- src/core/lib/debug/trace.h
@ -253,6 +256,7 @@ filegroups:
- src/core/lib/channel/handshaker.c
- src/core/lib/channel/http_client_filter.c
- src/core/lib/channel/http_server_filter.c
- src/core/lib/channel/message_size_filter.c
- src/core/lib/compression/compression.c
- src/core/lib/compression/message_compress.c
- src/core/lib/debug/trace.c
@ -1343,6 +1347,16 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: census_trace_context_test
build: test
language: c
src:
- test/core/census/trace_context_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: channel_create_test
build: test
language: c

@ -92,6 +92,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
@ -271,6 +272,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
src/core/ext/census/resource.c \
src/core/ext/census/trace_context.c \
src/core/ext/census/tracing.c \
src/core/plugin_registry/grpc_plugin_registry.c \
src/boringssl/err_data.c \

@ -0,0 +1,15 @@
There are times when we make changes that include a temporary shim for
backward-compatibility (e.g., a macro or some other function to preserve
the original API) to avoid having to bump the major version number in
the next release. However, when we do eventually want to release a
feature that does change the API in a non-backward-compatible way, we
will wind up bumping the major version number anyway, at which point we
can take the opportunity to clean up any pending backward-compatibility
shims.
This file lists all pending backward-compatibility changes that should
be cleaned up the next time we are going to bump the major version
number:
- remove `GRPC_ARG_MAX_MESSAGE_LENGTH` channel arg from
`include/grpc/impl/codegen/grpc_types.h` (commit `af00d8b`)

@ -0,0 +1,192 @@
# gRPC Server Reflection Tutorial
gRPC Server Reflection provides information about publicly-accessible gRPC
services on a server, and assists clients at runtime to construct RPC
requests and responses without precompiled service information. It is used by
gRPC CLI, which can be used to introspect server protos and send/receive test
RPCs.
## Enable Server Reflection
### Enable server reflection in C++ servers
C++ Server Reflection is an add-on library, `libgrpc++_reflction`. To enable C++
server reflection, you can link this library to your server binary.
Some platforms (e.g. Ubuntu 11.10 onwards) only link in libraries that directly
contain symbols used by the application. On these platforms, LD flag
`--no-as-needed` is needed for for dynamic linking and `--whole-archive` is
needed for for static linking.
This [Makefile](../examples/cpp/helloworld/Makefile#L37#L45) demonstrates
enabling c++ server reflection on Linux and MacOS.
## Test services using Server Reflection
After enabling Server Reflection in a server application, you can use gRPC CLI
to test its services.
Instructions on how to use gRPC CLI can be found at
[command_line_tool.md](command_line_tool.md), or using `grpc_cli help` command.
Here we use `examples/cpp/helloworld` as an example to show the use of gRPC
Server Reflection and gRPC CLI. First, we need to build gRPC CLI and setup an
example server with Server Reflection enabled.
- Setup an example server
Server Reflection has already been enabled in the
[Makefile](../examples/cpp/helloworld/Makefile) of the helloworld example. We
can simply make it and run the greeter_server.
```sh
$ make -C examples/cpp/helloworld
$ examples/cpp/helloworld/greeter_server &
```
- Build gRPC CLI
```sh
make grpc_cli
cd bins/opt
```
gRPC CLI binary `grpc_cli` can be found at `bins/opt/` folder. This tool is
still new and does not have a `make install` target yet.
### List services
`grpc_cli ls` command lists services and methods exposed at a given port
- List all the services exposed at a given port
```sh
$ grpc_cli ls localhost:50051
```
output:
```sh
helloworld.Greeter
grpc.reflection.v1alpha.ServerReflection
```
- List one service with details
`grpc_cli ls` command inspects a service given its full name (in the format of
\<package\>.\<service\>). It can print information with a long listing format
when `-l` flag is set. This flag can be used to get more details about a
service.
```sh
$ grpc_cli ls localhost:50051 helloworld.Greeter -l
```
output:
```sh
filename: helloworld.proto
package: helloworld;
service Greeter {
rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
}
```
### List methods
- List one method with details
`grpc_cli ls` command also inspects a method given its full name (in the
format of \<package\>.\<service\>.\<method\>).
```sh
$ grpc_cli ls localhost:50051 helloworld.Greeter.SayHello -l
```
output:
```sh
rpc SayHello(helloworld.HelloRequest) returns (helloworld.HelloReply) {}
```
### Inspect message types
We can use`grpc_cli type` command to inspect request/response types given the
full name of the type (in the format of \<package\>.\<type\>).
- Get information about the request type
```sh
$ grpc_cli type localhost:50051 helloworld.HelloRequest
```
output:
```sh
message HelloRequest {
optional string name = 1;
}
```
### Call a remote method
We can send RPCs to a server and get responses using `grpc_cli call` command.
- Call a unary method
```sh
$ grpc_cli call localhost:50051 SayHello "name: 'gRPC CLI'"
```
output:
```sh
message: "Hello gRPC CLI"
```
## Use Server Reflection in a C++ client
Server Reflection can be used by clients to get information about gRPC services
at runtime. We've provided a descriptor database called
[grpc::ProtoReflectionDescriptorDatabase](../test/cpp/util/proto_reflection_descriptor_database.h)
which implements the
[google::protobuf::DescriptorDatabase](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor_database#DescriptorDatabase)
interface. It manages the communication between clients and reflection services
and the storage of received information. Clients can use it as using a local
descriptor database.
- To use Server Reflection with grpc::ProtoReflectionDescriptorDatabase, first
initialize an instance with a grpc::Channel.
```c++
std::shared_ptr<grpc::Channel> channel =
grpc::CreateChannel(server_address, server_cred);
grpc::ProtoReflectionDescriptorDatabase reflection_db(channel);
```
- Then use this instance to feed a
[google::protobuf::DescriptorPool](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.descriptor#DescriptorPool).
```c++
google::protobuf::DescriptorPool desc_pool(&reflection_db);
```
- Example usage of this descriptor pool
* Get Service/method descriptors.
```c++
const google::protobuf::ServiceDescriptor* service_desc =
desc_pool->FindServiceByName("helloworld.Greeter");
const google::protobuf::MethodDescriptor* method_desc =
desc_pool->FindMethodByName("helloworld.Greeter.SayHello");
```
* Get message type descriptors.
```c++
const google::protobuf::Descriptor* request_desc =
desc_pool->FindMessageTypeByName("helloworld.HelloRequest");
```
* Feed [google::protobuf::DynamicMessageFactory](https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.dynamic_message#DynamicMessageFactory).
```c++
google::protobuf::DynamicMessageFactory(&desc_pool);
```

@ -258,6 +258,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/handshaker.h',
'src/core/lib/channel/http_client_filter.h',
'src/core/lib/channel/http_server_filter.h',
'src/core/lib/channel/message_size_filter.h',
'src/core/lib/compression/algorithm_metadata.h',
'src/core/lib/compression/message_compress.h',
'src/core/lib/debug/trace.h',
@ -408,6 +409,7 @@ Pod::Spec.new do |s|
'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h',
'src/core/ext/census/trace_context.h',
'src/core/lib/surface/init.c',
'src/core/lib/channel/channel_args.c',
'src/core/lib/channel/channel_stack.c',
@ -417,6 +419,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/handshaker.c',
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/channel/message_size_filter.c',
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/debug/trace.c',
@ -596,6 +599,7 @@ Pod::Spec.new do |s|
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
'src/core/ext/census/resource.c',
'src/core/ext/census/trace_context.c',
'src/core/ext/census/tracing.c',
'src/core/plugin_registry/grpc_plugin_registry.c'
@ -621,6 +625,7 @@ Pod::Spec.new do |s|
'src/core/lib/channel/handshaker.h',
'src/core/lib/channel/http_client_filter.h',
'src/core/lib/channel/http_server_filter.h',
'src/core/lib/channel/message_size_filter.h',
'src/core/lib/compression/algorithm_metadata.h',
'src/core/lib/compression/message_compress.h',
'src/core/lib/debug/trace.h',
@ -770,7 +775,8 @@ Pod::Spec.new do |s|
'src/core/ext/census/grpc_filter.h',
'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h'
'src/core/ext/census/rpc_metric_id.h',
'src/core/ext/census/trace_context.h'
end
s.subspec 'Cronet-Interface' do |ss|

@ -178,6 +178,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/handshaker.h )
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/message_size_filter.h )
s.files += %w( src/core/lib/compression/algorithm_metadata.h )
s.files += %w( src/core/lib/compression/message_compress.h )
s.files += %w( src/core/lib/debug/trace.h )
@ -328,6 +329,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/mlog.h )
s.files += %w( src/core/ext/census/resource.h )
s.files += %w( src/core/ext/census/rpc_metric_id.h )
s.files += %w( src/core/ext/census/trace_context.h )
s.files += %w( src/core/lib/surface/init.c )
s.files += %w( src/core/lib/channel/channel_args.c )
s.files += %w( src/core/lib/channel/channel_stack.c )
@ -337,6 +339,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/channel/handshaker.c )
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/message_size_filter.c )
s.files += %w( src/core/lib/compression/compression.c )
s.files += %w( src/core/lib/compression/message_compress.c )
s.files += %w( src/core/lib/debug/trace.c )
@ -516,6 +519,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/operation.c )
s.files += %w( src/core/ext/census/placeholders.c )
s.files += %w( src/core/ext/census/resource.c )
s.files += %w( src/core/ext/census/trace_context.c )
s.files += %w( src/core/ext/census/tracing.c )
s.files += %w( src/core/plugin_registry/grpc_plugin_registry.c )
s.files += %w( third_party/boringssl/crypto/aes/internal.h )

@ -175,7 +175,7 @@ template <int I>
class CallNoOp {
protected:
void AddOp(grpc_op* ops, size_t* nops) {}
void FinishOp(bool* status, int max_message_size) {}
void FinishOp(bool* status, int max_receive_message_size) {}
};
class CallOpSendInitialMetadata {
@ -213,7 +213,7 @@ class CallOpSendInitialMetadata {
op->data.send_initial_metadata.maybe_compression_level.level =
maybe_compression_level_.level;
}
void FinishOp(bool* status, int max_message_size) {
void FinishOp(bool* status, int max_receive_message_size) {
if (!send_) return;
g_core_codegen_interface->gpr_free(initial_metadata_);
send_ = false;
@ -253,7 +253,7 @@ class CallOpSendMessage {
// Flags are per-message: clear them after use.
write_options_.Clear();
}
void FinishOp(bool* status, int max_message_size) {
void FinishOp(bool* status, int max_receive_message_size) {
if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
send_buf_ = nullptr;
}
@ -301,13 +301,14 @@ class CallOpRecvMessage {
op->data.recv_message = &recv_buf_;
}
void FinishOp(bool* status, int max_message_size) {
void FinishOp(bool* status, int max_receive_message_size) {
if (message_ == nullptr) return;
if (recv_buf_) {
if (*status) {
got_message = *status = SerializationTraits<R>::Deserialize(
recv_buf_, message_, max_message_size)
.ok();
got_message = *status =
SerializationTraits<R>::Deserialize(recv_buf_, message_,
max_receive_message_size)
.ok();
} else {
got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@ -330,7 +331,8 @@ class CallOpRecvMessage {
namespace CallOpGenericRecvMessageHelper {
class DeserializeFunc {
public:
virtual Status Deserialize(grpc_byte_buffer* buf, int max_message_size) = 0;
virtual Status Deserialize(grpc_byte_buffer* buf,
int max_receive_message_size) = 0;
virtual ~DeserializeFunc() {}
};
@ -339,8 +341,9 @@ class DeserializeFuncType GRPC_FINAL : public DeserializeFunc {
public:
DeserializeFuncType(R* message) : message_(message) {}
Status Deserialize(grpc_byte_buffer* buf,
int max_message_size) GRPC_OVERRIDE {
return SerializationTraits<R>::Deserialize(buf, message_, max_message_size);
int max_receive_message_size) GRPC_OVERRIDE {
return SerializationTraits<R>::Deserialize(buf, message_,
max_receive_message_size);
}
~DeserializeFuncType() GRPC_OVERRIDE {}
@ -379,12 +382,13 @@ class CallOpGenericRecvMessage {
op->data.recv_message = &recv_buf_;
}
void FinishOp(bool* status, int max_message_size) {
void FinishOp(bool* status, int max_receive_message_size) {
if (!deserialize_) return;
if (recv_buf_) {
if (*status) {
got_message = true;
*status = deserialize_->Deserialize(recv_buf_, max_message_size).ok();
*status =
deserialize_->Deserialize(recv_buf_, max_receive_message_size).ok();
} else {
got_message = false;
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
@ -418,7 +422,7 @@ class CallOpClientSendClose {
op->flags = 0;
op->reserved = NULL;
}
void FinishOp(bool* status, int max_message_size) { send_ = false; }
void FinishOp(bool* status, int max_receive_message_size) { send_ = false; }
private:
bool send_;
@ -453,7 +457,7 @@ class CallOpServerSendStatus {
op->reserved = NULL;
}
void FinishOp(bool* status, int max_message_size) {
void FinishOp(bool* status, int max_receive_message_size) {
if (!send_status_available_) return;
g_core_codegen_interface->gpr_free(trailing_metadata_);
send_status_available_ = false;
@ -486,7 +490,7 @@ class CallOpRecvInitialMetadata {
op->flags = 0;
op->reserved = NULL;
}
void FinishOp(bool* status, int max_message_size) {
void FinishOp(bool* status, int max_receive_message_size) {
if (recv_initial_metadata_ == nullptr) return;
FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
recv_initial_metadata_ = nullptr;
@ -525,7 +529,7 @@ class CallOpClientRecvStatus {
op->reserved = NULL;
}
void FinishOp(bool* status, int max_message_size) {
void FinishOp(bool* status, int max_receive_message_size) {
if (recv_status_ == nullptr) return;
FillMetadataMap(&recv_trailing_metadata_arr_, recv_trailing_metadata_);
*recv_status_ = Status(
@ -562,13 +566,13 @@ class CallOpSetCollectionInterface
/// API.
class CallOpSetInterface : public CompletionQueueTag {
public:
CallOpSetInterface() : max_message_size_(0) {}
CallOpSetInterface() : max_receive_message_size_(0) {}
/// Fills in grpc_op, starting from ops[*nops] and moving
/// upwards.
virtual void FillOps(grpc_op* ops, size_t* nops) = 0;
void set_max_message_size(int max_message_size) {
max_message_size_ = max_message_size;
void set_max_receive_message_size(int max_receive_message_size) {
max_receive_message_size_ = max_receive_message_size;
}
/// Mark this as belonging to a collection if needed
@ -577,7 +581,7 @@ class CallOpSetInterface : public CompletionQueueTag {
}
protected:
int max_message_size_;
int max_receive_message_size_;
std::shared_ptr<CallOpSetCollectionInterface> collection_;
};
@ -609,12 +613,12 @@ class CallOpSet : public CallOpSetInterface,
}
bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
this->Op1::FinishOp(status, max_message_size_);
this->Op2::FinishOp(status, max_message_size_);
this->Op3::FinishOp(status, max_message_size_);
this->Op4::FinishOp(status, max_message_size_);
this->Op5::FinishOp(status, max_message_size_);
this->Op6::FinishOp(status, max_message_size_);
this->Op1::FinishOp(status, max_receive_message_size_);
this->Op2::FinishOp(status, max_receive_message_size_);
this->Op3::FinishOp(status, max_receive_message_size_);
this->Op4::FinishOp(status, max_receive_message_size_);
this->Op5::FinishOp(status, max_receive_message_size_);
this->Op6::FinishOp(status, max_receive_message_size_);
*tag = return_tag_;
collection_.reset(); // drop the ref at this point
return true;
@ -646,18 +650,21 @@ class Call GRPC_FINAL {
public:
/* call is owned by the caller */
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
: call_hook_(call_hook), cq_(cq), call_(call), max_message_size_(-1) {}
: call_hook_(call_hook),
cq_(cq),
call_(call),
max_receive_message_size_(-1) {}
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
int max_message_size)
int max_receive_message_size)
: call_hook_(call_hook),
cq_(cq),
call_(call),
max_message_size_(max_message_size) {}
max_receive_message_size_(max_receive_message_size) {}
void PerformOps(CallOpSetInterface* ops) {
if (max_message_size_ > 0) {
ops->set_max_message_size(max_message_size_);
if (max_receive_message_size_ > 0) {
ops->set_max_receive_message_size(max_receive_message_size_);
}
call_hook_->PerformOpsOnCall(ops, this);
}
@ -665,13 +672,13 @@ class Call GRPC_FINAL {
grpc_call* call() const { return call_; }
CompletionQueue* cq() const { return cq_; }
int max_message_size() const { return max_message_size_; }
int max_receive_message_size() { return max_receive_message_size_; }
private:
CallHook* call_hook_;
CompletionQueue* cq_;
grpc_call* call_;
int max_message_size_;
int max_receive_message_size_;
};
} // namespace grpc

@ -53,7 +53,7 @@ class RpcMethodHandler : public MethodHandler {
void RunHandler(const HandlerParameter& param) GRPC_FINAL {
RequestType req;
Status status = SerializationTraits<RequestType>::Deserialize(
param.request, &req, param.max_message_size);
param.request, &req, param.max_receive_message_size);
ResponseType rsp;
if (status.ok()) {
status = func_(service_, param.server_context, &req, &rsp);
@ -139,7 +139,7 @@ class ServerStreamingHandler : public MethodHandler {
void RunHandler(const HandlerParameter& param) GRPC_FINAL {
RequestType req;
Status status = SerializationTraits<RequestType>::Deserialize(
param.request, &req, param.max_message_size);
param.request, &req, param.max_receive_message_size);
if (status.ok()) {
ServerWriter<ResponseType> writer(param.call, param.server_context);

@ -204,7 +204,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
static Status Deserialize(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg,
int max_message_size) {
int max_receive_message_size) {
if (buffer == nullptr) {
return Status(StatusCode::INTERNAL, "No payload");
}
@ -215,8 +215,9 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
return reader.status();
}
::grpc::protobuf::io::CodedInputStream decoder(&reader);
if (max_message_size > 0) {
decoder.SetTotalBytesLimit(max_message_size, max_message_size);
if (max_receive_message_size > 0) {
decoder.SetTotalBytesLimit(max_receive_message_size,
max_receive_message_size);
}
if (!msg->ParseFromCodedStream(&decoder)) {
result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());

@ -62,12 +62,12 @@ class MethodHandler {
: call(c),
server_context(context),
request(req),
max_message_size(max_size) {}
max_receive_message_size(max_size) {}
Call* call;
ServerContext* server_context;
// Handler required to grpc_byte_buffer_destroy this
grpc_byte_buffer* request;
int max_message_size;
int max_receive_message_size;
};
virtual void RunHandler(const HandlerParameter& param) = 0;
};

@ -43,10 +43,10 @@ namespace grpc {
/// functions:
/// static Status Serialize(const Message& msg,
/// grpc_byte_buffer** buffer,
// bool* own_buffer);
/// bool* own_buffer);
/// static Status Deserialize(grpc_byte_buffer* buffer,
/// Message* msg,
/// int max_message_size);
/// int max_receive_message_size);
///
/// Serialize is required to convert message to a grpc_byte_buffer, and
/// to store a pointer to that byte buffer at *buffer. *own_buffer should
@ -54,8 +54,8 @@ namespace grpc {
/// ownership is retained elsewhere.
///
/// Deserialize is required to convert buffer into the message stored at
/// msg. max_message_size is passed in as a bound on the maximum number of
/// message bytes Deserialize should accept.
/// msg. max_receive_message_size is passed in as a bound on the maximum
/// number of message bytes Deserialize should accept.
///
/// Both functions return a Status, allowing them to explain what went
/// wrong if required.

@ -134,7 +134,7 @@ class ServerInterface : public CallHook {
virtual void ShutdownInternal(gpr_timespec deadline) = 0;
virtual int max_message_size() const = 0;
virtual int max_receive_message_size() const = 0;
virtual grpc_server* server() = 0;
@ -205,8 +205,8 @@ class ServerInterface : public CallHook {
bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
bool serialization_status =
*status && payload_ &&
SerializationTraits<Message>::Deserialize(payload_, request_,
server_->max_message_size())
SerializationTraits<Message>::Deserialize(
payload_, request_, server_->max_receive_message_size())
.ok();
bool ret = RegisteredAsyncRequest::FinalizeResult(tag, status);
*status = serialization_status && *status;

@ -160,7 +160,7 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
}
bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE {
*sz = call_.max_message_size();
*sz = call_.max_receive_message_size();
return true;
}
@ -310,7 +310,7 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
}
bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE {
*sz = call_.max_message_size();
*sz = call_.max_receive_message_size();
return true;
}
@ -382,7 +382,7 @@ class ServerReader GRPC_FINAL : public ServerReaderInterface<R> {
}
bool NextMessageSize(uint32_t* sz) GRPC_OVERRIDE {
*sz = call_->max_message_size();
*sz = call_->max_receive_message_size();
return true;
}
@ -474,7 +474,7 @@ class ServerReaderWriterBody GRPC_FINAL {
}
bool NextMessageSize(uint32_t* sz) {
*sz = call_->max_message_size();
*sz = call_->max_receive_message_size();
return true;
}

@ -64,7 +64,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
}
static Status Deserialize(grpc_byte_buffer* buffer, T* msg,
int max_message_size) {
int max_receive_message_size) {
if (!buffer) {
return Status(StatusCode::INTERNAL, "No payload");
}

@ -116,10 +116,10 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
///
/// \param thread_pool The threadpool instance to use for call processing.
/// \param thread_pool_owned Does the server own the \a thread_pool instance?
/// \param max_message_size Maximum message length that the channel can
/// receive.
/// \param max_receive_message_size Maximum message length that the channel
/// can receive.
Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
int max_message_size, ChannelArguments* args);
int max_receive_message_size, ChannelArguments* args);
/// Register a service. This call does not take ownership of the service.
/// The service must exist for the lifetime of the Server instance.
@ -164,13 +164,15 @@ class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
void ShutdownInternal(gpr_timespec deadline) GRPC_OVERRIDE;
int max_message_size() const GRPC_OVERRIDE { return max_message_size_; };
int max_receive_message_size() const GRPC_OVERRIDE {
return max_receive_message_size_;
};
grpc_server* server() GRPC_OVERRIDE { return server_; };
ServerInitializer* initializer();
const int max_message_size_;
const int max_receive_message_size_;
// Completion queue.
CompletionQueue cq_;

@ -78,12 +78,23 @@ class ServerBuilder {
/// Only matches requests with :authority \a host
ServerBuilder& RegisterService(const grpc::string& host, Service* service);
/// Set max message size in bytes.
ServerBuilder& SetMaxMessageSize(int max_message_size) {
max_message_size_ = max_message_size;
/// Set max receive message size in bytes.
ServerBuilder& SetMaxReceiveMessageSize(int max_receive_message_size) {
max_receive_message_size_ = max_receive_message_size;
return *this;
}
/// Set max send message size in bytes.
ServerBuilder& SetMaxSendMessageSize(int max_send_message_size) {
max_send_message_size_ = max_send_message_size;
return *this;
}
/// \deprecated For backward compatibility.
ServerBuilder& SetMaxMessageSize(int max_message_size) {
return SetMaxReceiveMessageSize(max_message_size);
}
/// Set the support status for compression algorithms. All algorithms are
/// enabled by default.
///
@ -168,7 +179,8 @@ class ServerBuilder {
Service* service;
};
int max_message_size_;
int max_receive_message_size_;
int max_send_message_size_;
std::vector<std::unique_ptr<ServerBuilderOption>> options_;
std::vector<std::unique_ptr<NamedService>> services_;
std::vector<Port> ports_;

@ -96,7 +96,7 @@ template <>
class SerializationTraits<ByteBuffer, void> {
public:
static Status Deserialize(grpc_byte_buffer* byte_buffer, ByteBuffer* dest,
int max_message_size) {
int max_receive_message_size) {
dest->set_buffer(byte_buffer);
return Status::OK;
}

@ -149,7 +149,11 @@ typedef struct {
connection. Int valued. */
#define GRPC_ARG_MAX_CONCURRENT_STREAMS "grpc.max_concurrent_streams"
/** Maximum message length that the channel can receive. Int valued, bytes. */
#define GRPC_ARG_MAX_MESSAGE_LENGTH "grpc.max_message_length"
#define GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH "grpc.max_receive_message_length"
/** \deprecated For backward compatibility. */
#define GRPC_ARG_MAX_MESSAGE_LENGTH GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH
/** Maximum message length that the channel can send. Int valued, bytes. */
#define GRPC_ARG_MAX_SEND_MESSAGE_LENGTH "grpc.max_send_message_length"
/** Initial sequence number for http2 transports. Int valued. */
#define GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER \
"grpc.http2.initial_sequence_number"

@ -185,6 +185,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/handshaker.h" role="src" />
<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/message_size_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/algorithm_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/message_compress.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/trace.h" role="src" />
@ -335,6 +336,7 @@
<file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/trace_context.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/surface/init.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_args.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/channel/channel_stack.c" role="src" />
@ -344,6 +346,7 @@
<file baseinstalldir="/" name="src/core/lib/channel/handshaker.c" role="src" />
<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/message_size_filter.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/compression.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/compression/message_compress.c" role="src" />
<file baseinstalldir="/" name="src/core/lib/debug/trace.c" role="src" />
@ -523,6 +526,7 @@
<file baseinstalldir="/" name="src/core/ext/census/operation.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/placeholders.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/resource.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/trace_context.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/tracing.c" role="src" />
<file baseinstalldir="/" name="src/core/plugin_registry/grpc_plugin_registry.c" role="src" />
<file baseinstalldir="/" name="third_party/boringssl/crypto/aes/internal.h" role="src" />

@ -0,0 +1,86 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "src/core/ext/census/trace_context.h"
#include <grpc/census.h>
#include <grpc/support/log.h>
#include <stdbool.h>
#include "third_party/nanopb/pb_decode.h"
#include "third_party/nanopb/pb_encode.h"
// This function assumes the TraceContext is valid.
size_t encode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
const size_t buf_size) {
// Create a stream that will write to our buffer.
pb_ostream_t stream = pb_ostream_from_buffer(buffer, buf_size);
// encode message
bool status = pb_encode(&stream, google_trace_TraceContext_fields, ctxt);
if (!status) {
gpr_log(GPR_DEBUG, "TraceContext encoding failed: %s",
PB_GET_ERROR(&stream));
return 0;
}
return stream.bytes_written;
}
bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
const size_t nbytes) {
// Create a stream that reads nbytes from the buffer.
pb_istream_t stream = pb_istream_from_buffer(buffer, nbytes);
// decode message
bool status = pb_decode(&stream, google_trace_TraceContext_fields, ctxt);
if (!status) {
gpr_log(GPR_DEBUG, "TraceContext decoding failed: %s",
PB_GET_ERROR(&stream));
return false;
}
// check fields
if (!ctxt->has_trace_id) {
gpr_log(GPR_DEBUG, "Invalid TraceContext: missing trace_id");
return false;
}
if (!ctxt->has_span_id) {
gpr_log(GPR_DEBUG, "Invalid TraceContext: missing span_id");
return false;
}
return true;
}

@ -0,0 +1,68 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/* Functions for manipulating trace contexts as defined in
src/proto/census/trace.proto */
#ifndef GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H
#define GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H
#include "src/core/ext/census/gen/trace_context.pb.h"
/* Maximum number of bytes required to encode a TraceContext (31)
1 byte for trace_id field
1 byte for trace_id length
1 byte for trace_id.hi field
8 bytes for trace_id.hi (uint64_t)
1 byte for trace_id.lo field
8 bytes for trace_id.lo (uint64_t)
1 byte for span_id field
8 bytes for span_id (uint64_t)
1 byte for is_sampled field
1 byte for is_sampled (bool) */
#define TRACE_MAX_CONTEXT_SIZE 31
/* Encode a trace context (ctxt) into proto format to the buffer provided. The
size of buffer must be at least TRACE_MAX_CONTEXT_SIZE. On success, returns the
number of bytes successfully encoded into buffer. On failure, returns 0. */
size_t encode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
const size_t buf_size);
/* Decode a proto-encoded TraceContext from the provided buffer into the
TraceContext structure (ctxt). The function expects to be supplied the number
of bytes to be read from buffer (nbytes). This function will also validate that
the TraceContext has a span_id and a trace_id, and will return false if either
of these do not exist. On success, returns true and false otherwise. */
bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
const size_t nbytes);
#endif

@ -31,15 +31,21 @@
*
*/
//#include "src/core/ext/census/tracing.h"
#include <grpc/census.h>
/* TODO(aveitch): These are all placeholder implementations. */
int census_trace_mask(const census_context *context) {
return CENSUS_TRACE_MASK_NONE;
}
// int census_trace_mask(const census_context *context) {
// return CENSUS_TRACE_MASK_NONE;
// }
// void census_set_trace_mask(int trace_mask) {}
void census_set_trace_mask(int trace_mask) {}
// void census_trace_print(census_context *context, uint32_t type,
// const char *buffer, size_t n) {}
void census_trace_print(census_context *context, uint32_t type,
const char *buffer, size_t n) {}
// void SetTracerParams(const Params& params);

@ -31,8 +31,46 @@
*
*/
#include <string.h>
#include <grpc/support/alloc.h>
#include "src/core/ext/client_config/lb_policy_factory.h"
grpc_lb_addresses* grpc_lb_addresses_create(size_t num_addresses) {
grpc_lb_addresses* addresses = gpr_malloc(sizeof(grpc_lb_addresses));
addresses->num_addresses = num_addresses;
const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses;
addresses->addresses = gpr_malloc(addresses_size);
memset(addresses->addresses, 0, addresses_size);
return addresses;
}
void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
void* address, size_t address_len,
bool is_balancer, char* balancer_name,
void* user_data) {
GPR_ASSERT(index < addresses->num_addresses);
grpc_lb_address* target = &addresses->addresses[index];
memcpy(target->address.addr, address, address_len);
target->address.len = address_len;
target->is_balancer = is_balancer;
target->balancer_name = balancer_name;
target->user_data = user_data;
}
void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses,
void (*user_data_destroy)(void*)) {
for (size_t i = 0; i < addresses->num_addresses; ++i) {
gpr_free(addresses->addresses[i].balancer_name);
if (user_data_destroy != NULL) {
user_data_destroy(addresses->addresses[i].user_data);
}
}
gpr_free(addresses->addresses);
gpr_free(addresses);
}
void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {
factory->vtable->ref(factory);
}

@ -36,7 +36,7 @@
#include "src/core/ext/client_config/client_channel_factory.h"
#include "src/core/ext/client_config/lb_policy.h"
#include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/ext/client_config/resolver_result.h"
#include "src/core/lib/iomgr/exec_ctx.h"
@ -53,13 +53,37 @@ struct grpc_lb_policy_factory {
* Those who don't will simply ignore it and will correspondingly return NULL in
* their namesake pick() output argument. */
typedef struct grpc_lb_address {
grpc_resolved_address *resolved_address;
grpc_resolved_address address;
bool is_balancer;
char *balancer_name; /* For secure naming. */
void *user_data;
} grpc_lb_address;
typedef struct grpc_lb_policy_args {
grpc_lb_address *addresses;
typedef struct grpc_lb_addresses {
size_t num_addresses;
grpc_lb_address *addresses;
} grpc_lb_addresses;
/** Returns a grpc_addresses struct with enough space for
* \a num_addresses addresses. */
grpc_lb_addresses *grpc_lb_addresses_create(size_t num_addresses);
/** Sets the value of the address at index \a index of \a addresses.
* \a address is a socket address of length \a address_len.
* Takes ownership of \a balancer_name. */
void grpc_lb_addresses_set_address(grpc_lb_addresses *addresses, size_t index,
void *address, size_t address_len,
bool is_balancer, char *balancer_name,
void *user_data);
/** Destroys \a addresses. If \a user_data_destroy is not NULL, it will
* be invoked to destroy the \a user_data field of each address. */
void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses,
void (*user_data_destroy)(void *));
/** Arguments passed to LB policies. */
typedef struct grpc_lb_policy_args {
grpc_lb_addresses *addresses;
grpc_client_channel_factory *client_channel_factory;
} grpc_lb_policy_args;

@ -1,35 +1,33 @@
/*
*
* 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.
*
*/
//
// 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 "src/core/ext/client_config/resolver_result.h"
@ -39,20 +37,20 @@
struct grpc_resolver_result {
gpr_refcount refs;
grpc_lb_policy *lb_policy;
grpc_lb_policy* lb_policy;
};
grpc_resolver_result *grpc_resolver_result_create() {
grpc_resolver_result *c = gpr_malloc(sizeof(*c));
grpc_resolver_result* grpc_resolver_result_create() {
grpc_resolver_result* c = gpr_malloc(sizeof(*c));
memset(c, 0, sizeof(*c));
gpr_ref_init(&c->refs, 1);
return c;
}
void grpc_resolver_result_ref(grpc_resolver_result *c) { gpr_ref(&c->refs); }
void grpc_resolver_result_ref(grpc_resolver_result* c) { gpr_ref(&c->refs); }
void grpc_resolver_result_unref(grpc_exec_ctx *exec_ctx,
grpc_resolver_result *c) {
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
grpc_resolver_result* c) {
if (gpr_unref(&c->refs)) {
if (c->lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "resolver_result");
@ -61,8 +59,8 @@ void grpc_resolver_result_unref(grpc_exec_ctx *exec_ctx,
}
}
void grpc_resolver_result_set_lb_policy(grpc_resolver_result *c,
grpc_lb_policy *lb_policy) {
void grpc_resolver_result_set_lb_policy(grpc_resolver_result* c,
grpc_lb_policy* lb_policy) {
GPR_ASSERT(c->lb_policy == NULL);
if (lb_policy) {
GRPC_LB_POLICY_REF(lb_policy, "resolver_result");
@ -70,6 +68,6 @@ void grpc_resolver_result_set_lb_policy(grpc_resolver_result *c,
c->lb_policy = lb_policy;
}
grpc_lb_policy *grpc_resolver_result_get_lb_policy(grpc_resolver_result *c) {
grpc_lb_policy* grpc_resolver_result_get_lb_policy(grpc_resolver_result* c) {
return c->lb_policy;
}

@ -1,52 +1,53 @@
/*
*
* 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.
*
*/
//
// 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.
//
#ifndef GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_RESULT_H
#define GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_RESULT_H
#include <stdbool.h>
#include "src/core/ext/client_config/lb_policy.h"
#include "src/core/lib/iomgr/resolve_address.h"
/** Results reported from a grpc_resolver. */
/// Results reported from a grpc_resolver.
typedef struct grpc_resolver_result grpc_resolver_result;
grpc_resolver_result *grpc_resolver_result_create();
void grpc_resolver_result_ref(grpc_resolver_result *client_config);
void grpc_resolver_result_unref(grpc_exec_ctx *exec_ctx,
grpc_resolver_result *client_config);
grpc_resolver_result* grpc_resolver_result_create();
void grpc_resolver_result_ref(grpc_resolver_result* result);
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
grpc_resolver_result* result);
void grpc_resolver_result_set_lb_policy(grpc_resolver_result *client_config,
grpc_lb_policy *lb_policy);
grpc_lb_policy *grpc_resolver_result_get_lb_policy(
grpc_resolver_result *client_config);
void grpc_resolver_result_set_lb_policy(grpc_resolver_result* result,
grpc_lb_policy* lb_policy);
grpc_lb_policy* grpc_resolver_result_get_lb_policy(
grpc_resolver_result* result);
#endif /* GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_RESULT_H */

@ -33,6 +33,7 @@
#include "src/core/ext/client_config/subchannel.h"
#include <limits.h>
#include <string.h>
#include <grpc/support/alloc.h>
@ -347,21 +348,16 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
}
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");
const grpc_integer_options options = {-1, 0, INT_MAX};
const int value =
grpc_channel_arg_get_integer(&c->args->args[i], options);
if (value >= 0) {
gpr_backoff_init(
&c->backoff_state, GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
GRPC_SUBCHANNEL_RECONNECT_JITTER,
GPR_MIN(value,
GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000),
value);
}
}
}

@ -107,6 +107,7 @@
#include <grpc/support/string_util.h>
#include "src/core/ext/client_config/client_channel_factory.h"
#include "src/core/ext/client_config/lb_policy_factory.h"
#include "src/core/ext/client_config/lb_policy_registry.h"
#include "src/core/ext/client_config/parse_address.h"
#include "src/core/ext/lb_policy/grpclb/grpclb.h"
@ -120,18 +121,6 @@
int grpc_lb_glb_trace = 0;
static void lb_addrs_destroy(grpc_lb_address *lb_addresses,
size_t num_addresses) {
/* free "resolved" addresses memblock */
gpr_free(lb_addresses->resolved_address);
for (size_t i = 0; i < num_addresses; ++i) {
if (lb_addresses[i].user_data != NULL) {
GRPC_MDELEM_UNREF(lb_addresses[i].user_data);
}
}
gpr_free(lb_addresses);
}
/* add lb_token of selected subchannel (address) to the call's initial
* metadata */
static void initial_metadata_add_lb_token(
@ -311,11 +300,8 @@ typedef struct glb_lb_policy {
* response has arrived. */
grpc_grpclb_serverlist *serverlist;
/** total number of valid addresses received in \a serverlist */
size_t num_ok_serverlist_addresses;
/** LB addresses from \a serverlist, \a num_ok_serverlist_addresses of them */
grpc_lb_address *lb_addresses;
/** addresses from \a serverlist */
grpc_lb_addresses *addresses;
/** list of picks that are waiting on RR's policy connectivity */
pending_pick *pending_picks;
@ -368,26 +354,18 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
return true;
}
/* populate \a addresses according to \a serverlist. Returns the number of
* addresses successfully parsed and added to \a addresses */
static size_t process_serverlist(const grpc_grpclb_serverlist *serverlist,
grpc_lb_address **lb_addresses) {
/* Returns addresses extracted from \a serverlist. */
static grpc_lb_addresses *process_serverlist(
const grpc_grpclb_serverlist *serverlist) {
size_t num_valid = 0;
/* first pass: count how many are valid in order to allocate the necessary
* memory in a single block */
for (size_t i = 0; i < serverlist->num_servers; ++i) {
if (is_server_valid(serverlist->servers[i], i, true)) ++num_valid;
}
if (num_valid == 0) {
return 0;
}
if (num_valid == 0) return NULL;
/* allocate the memory block for the "resolved" addresses. */
grpc_resolved_address *r_addrs_memblock =
gpr_malloc(sizeof(grpc_resolved_address) * num_valid);
memset(r_addrs_memblock, 0, sizeof(grpc_resolved_address) * num_valid);
grpc_lb_address *lb_addrs = gpr_malloc(sizeof(grpc_lb_address) * num_valid);
memset(lb_addrs, 0, sizeof(grpc_lb_address) * num_valid);
grpc_lb_addresses *lb_addresses = grpc_lb_addresses_create(num_valid);
/* second pass: actually populate the addresses and LB tokens (aka user data
* to the outside world) to be read by the RR policy during its creation.
@ -399,56 +377,58 @@ static size_t process_serverlist(const grpc_grpclb_serverlist *serverlist,
GPR_ASSERT(addr_idx < num_valid);
const grpc_grpclb_server *server = serverlist->servers[sl_idx];
if (!is_server_valid(serverlist->servers[sl_idx], sl_idx, false)) continue;
grpc_lb_address *const lb_addr = &lb_addrs[addr_idx];
/* address processing */
const uint16_t netorder_port = htons((uint16_t)server->port);
/* the addresses are given in binary format (a in(6)_addr struct) in
* server->ip_address.bytes. */
const grpc_grpclb_ip_address *ip = &server->ip_address;
lb_addr->resolved_address = &r_addrs_memblock[addr_idx];
struct sockaddr_storage *sa =
(struct sockaddr_storage *)lb_addr->resolved_address->addr;
size_t *sa_len = &lb_addr->resolved_address->len;
*sa_len = 0;
grpc_resolved_address addr;
memset(&addr, 0, sizeof(addr));
if (ip->size == 4) {
struct sockaddr_in *addr4 = (struct sockaddr_in *)sa;
*sa_len = sizeof(struct sockaddr_in);
memset(addr4, 0, *sa_len);
addr.len = sizeof(struct sockaddr_in);
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
addr4->sin_family = AF_INET;
memcpy(&addr4->sin_addr, ip->bytes, ip->size);
addr4->sin_port = netorder_port;
} else if (ip->size == 16) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)sa;
*sa_len = sizeof(struct sockaddr_in6);
memset(addr6, 0, *sa_len);
addr.len = sizeof(struct sockaddr_in6);
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr;
addr6->sin6_family = AF_INET;
memcpy(&addr6->sin6_addr, ip->bytes, ip->size);
addr6->sin6_port = netorder_port;
}
GPR_ASSERT(*sa_len > 0);
/* lb token processing */
void *user_data;
if (server->has_load_balance_token) {
const size_t lb_token_size =
GPR_ARRAY_SIZE(server->load_balance_token) - 1;
grpc_mdstr *lb_token_mdstr = grpc_mdstr_from_buffer(
(uint8_t *)server->load_balance_token, lb_token_size);
lb_addr->user_data = grpc_mdelem_from_metadata_strings(
user_data = grpc_mdelem_from_metadata_strings(
GRPC_MDSTR_LOAD_REPORTING_INITIAL, lb_token_mdstr);
} else {
gpr_log(GPR_ERROR,
"Missing LB token for backend address '%s'. The empty token will "
"be used instead",
grpc_sockaddr_to_uri((struct sockaddr *)sa));
lb_addr->user_data = GRPC_MDELEM_LOAD_REPORTING_INITIAL_EMPTY;
grpc_sockaddr_to_uri((struct sockaddr *)&addr.addr));
user_data = GRPC_MDELEM_LOAD_REPORTING_INITIAL_EMPTY;
}
grpc_lb_addresses_set_address(lb_addresses, addr_idx, &addr.addr, addr.len,
false /* is_balancer */,
NULL /* balancer_name */, user_data);
++addr_idx;
}
GPR_ASSERT(addr_idx == num_valid);
*lb_addresses = lb_addrs;
return num_valid;
return lb_addresses;
}
/* A plugin for grpc_lb_addresses_destroy that unrefs the LB token metadata. */
static void lb_token_destroy(void *token) {
if (token != NULL) GRPC_MDELEM_UNREF(token);
}
static grpc_lb_policy *create_rr(grpc_exec_ctx *exec_ctx,
@ -459,19 +439,15 @@ static grpc_lb_policy *create_rr(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_args args;
memset(&args, 0, sizeof(args));
args.client_channel_factory = glb_policy->cc_factory;
const size_t num_ok_addresses =
process_serverlist(serverlist, &args.addresses);
args.num_addresses = num_ok_addresses;
args.addresses = process_serverlist(serverlist);
grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
if (glb_policy->lb_addresses != NULL) {
if (glb_policy->addresses != NULL) {
/* dispose of the previous version */
lb_addrs_destroy(glb_policy->lb_addresses,
glb_policy->num_ok_serverlist_addresses);
grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
}
glb_policy->num_ok_serverlist_addresses = num_ok_addresses;
glb_policy->lb_addresses = args.addresses;
glb_policy->addresses = args.addresses;
return rr;
}
@ -565,6 +541,19 @@ static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
/* Count the number of gRPC-LB addresses. There must be at least one.
* TODO(roth): For now, we ignore non-balancer addresses, but in the
* future, we may change the behavior such that we fall back to using
* the non-balancer addresses if we cannot reach any balancers. At that
* time, this should be changed to allow a list with no balancer addresses,
* since the resolver might fail to return a balancer address even when
* this is the right LB policy to use. */
size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; ++i) {
if (args->addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
}
if (num_grpclb_addrs == 0) return NULL;
glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
memset(glb_policy, 0, sizeof(*glb_policy));
@ -576,36 +565,34 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
* Create a client channel over them to communicate with a LB service */
glb_policy->cc_factory = args->client_channel_factory;
GPR_ASSERT(glb_policy->cc_factory != NULL);
if (args->num_addresses == 0) {
return NULL;
}
if (args->addresses[0].user_data != NULL) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
}
/* construct a target from the addresses in args, given in the form
* ipvX://ip1:port1,ip2:port2,...
* TODO(dgq): support mixed ip version */
char **addr_strs = gpr_malloc(sizeof(char *) * args->num_addresses);
addr_strs[0] = grpc_sockaddr_to_uri(
(const struct sockaddr *)&args->addresses[0].resolved_address->addr);
for (size_t i = 1; i < args->num_addresses; i++) {
if (args->addresses[i].user_data != NULL) {
char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
size_t addr_index = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
if (args->addresses->addresses[i].user_data != NULL) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
}
GPR_ASSERT(
grpc_sockaddr_to_string(
&addr_strs[i],
(const struct sockaddr *)&args->addresses[i].resolved_address->addr,
true) == 0);
if (args->addresses->addresses[i].is_balancer) {
if (addr_index == 0) {
addr_strs[addr_index++] = grpc_sockaddr_to_uri(
(const struct sockaddr *)&args->addresses->addresses[i]
.address.addr);
} else {
GPR_ASSERT(grpc_sockaddr_to_string(
&addr_strs[addr_index++],
(const struct sockaddr *)&args->addresses->addresses[i]
.address.addr,
true) == 0);
}
}
}
size_t uri_path_len;
char *target_uri_str = gpr_strjoin_sep(
(const char **)addr_strs, args->num_addresses, ",", &uri_path_len);
char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
num_grpclb_addrs, ",", &uri_path_len);
/* will pick using pick_first */
glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
@ -613,7 +600,7 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, NULL);
gpr_free(target_uri_str);
for (size_t i = 0; i < args->num_addresses; i++) {
for (size_t i = 0; i < num_grpclb_addrs; i++) {
gpr_free(addr_strs[i]);
}
gpr_free(addr_strs);
@ -649,9 +636,7 @@ static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
}
gpr_mu_destroy(&glb_policy->mu);
lb_addrs_destroy(glb_policy->lb_addresses,
glb_policy->num_ok_serverlist_addresses);
grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
gpr_free(glb_policy);
}

@ -441,25 +441,34 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(args->addresses != NULL);
GPR_ASSERT(args->client_channel_factory != NULL);
if (args->num_addresses == 0) return NULL;
/* Find the number of backend addresses. We ignore balancer
* addresses, since we don't know how to handle them. */
size_t num_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
if (!args->addresses->addresses[i].is_balancer) ++num_addrs;
}
if (num_addrs == 0) return NULL;
pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * args->num_addresses);
memset(p->subchannels, 0, sizeof(*p->subchannels) * args->num_addresses);
p->subchannels = gpr_malloc(sizeof(grpc_subchannel *) * num_addrs);
memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
grpc_subchannel_args sc_args;
size_t subchannel_idx = 0;
for (size_t i = 0; i < args->num_addresses; i++) {
if (args->addresses[i].user_data != NULL) {
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
/* Skip balancer addresses, since we only know how to handle backends. */
if (args->addresses->addresses[i].is_balancer) continue;
if (args->addresses->addresses[i].user_data != NULL) {
gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored");
}
memset(&sc_args, 0, sizeof(grpc_subchannel_args));
sc_args.addr =
(struct sockaddr *)(args->addresses[i].resolved_address->addr);
sc_args.addr_len = (size_t)args->addresses[i].resolved_address->len;
(struct sockaddr *)(&args->addresses->addresses[i].address.addr);
sc_args.addr_len = args->addresses->addresses[i].address.len;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args);

@ -130,10 +130,6 @@ struct round_robin_lb_policy {
/** total number of addresses received at creation time */
size_t num_addresses;
/** array holding the borrowed and opaque pointers to incoming user data, one
* per incoming address. These individual pointers will be returned as-is in
* successful picks. */
void **user_data_pointers;
/** all our subchannels */
size_t num_subchannels;
@ -282,7 +278,6 @@ static void rr_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
elem = tmp;
}
gpr_free(p->user_data_pointers);
gpr_free(p);
}
@ -611,25 +606,32 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_args *args) {
GPR_ASSERT(args->addresses != NULL);
GPR_ASSERT(args->client_channel_factory != NULL);
if (args->num_addresses == 0) return NULL;
/* Find the number of backend addresses. We ignore balancer
* addresses, since we don't know how to handle them. */
size_t num_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
if (!args->addresses->addresses[i].is_balancer) ++num_addrs;
}
if (num_addrs == 0) return NULL;
round_robin_lb_policy *p = gpr_malloc(sizeof(*p));
memset(p, 0, sizeof(*p));
p->num_addresses = args->num_addresses;
p->subchannels = gpr_malloc(sizeof(subchannel_data) * p->num_addresses);
memset(p->subchannels, 0, sizeof(*p->subchannels) * p->num_addresses);
p->user_data_pointers = gpr_malloc(sizeof(void *) * p->num_addresses);
memset(p->user_data_pointers, 0, sizeof(void *) * p->num_addresses);
p->num_addresses = num_addrs;
p->subchannels = gpr_malloc(sizeof(*p->subchannels) * num_addrs);
memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
grpc_subchannel_args sc_args;
size_t subchannel_idx = 0;
for (size_t i = 0; i < p->num_addresses; i++) {
memset(&sc_args, 0, sizeof(grpc_subchannel_args));
sc_args.addr = (struct sockaddr *)args->addresses[i].resolved_address->addr;
sc_args.addr_len = args->addresses[i].resolved_address->len;
for (size_t i = 0; i < args->addresses->num_addresses; i++) {
/* Skip balancer addresses, since we only know how to handle backends. */
if (args->addresses->addresses[i].is_balancer) continue;
p->user_data_pointers[i] = args->addresses[i].user_data;
memset(&sc_args, 0, sizeof(grpc_subchannel_args));
sc_args.addr =
(struct sockaddr *)(&args->addresses->addresses[i].address.addr);
sc_args.addr_len = args->addresses->addresses[i].address.len;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args);
@ -641,7 +643,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
sd->policy = p;
sd->index = subchannel_idx;
sd->subchannel = subchannel;
sd->user_data = p->user_data_pointers[i];
sd->user_data = args->addresses->addresses[i].user_data;
++subchannel_idx;
grpc_closure_init(&sd->connectivity_changed_closure,
rr_connectivity_changed, sd);

@ -170,28 +170,27 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = 0;
grpc_resolved_addresses *addresses = r->addresses;
if (addresses != NULL) {
if (r->addresses != NULL) {
grpc_lb_policy_args lb_policy_args;
result = grpc_resolver_result_create();
memset(&lb_policy_args, 0, sizeof(lb_policy_args));
lb_policy_args.num_addresses = addresses->naddrs;
lb_policy_args.addresses =
gpr_malloc(sizeof(grpc_lb_address) * lb_policy_args.num_addresses);
memset(lb_policy_args.addresses, 0,
sizeof(grpc_lb_address) * lb_policy_args.num_addresses);
for (size_t i = 0; i < addresses->naddrs; ++i) {
lb_policy_args.addresses[i].resolved_address = &r->addresses->addrs[i];
lb_policy_args.addresses = grpc_lb_addresses_create(r->addresses->naddrs);
for (size_t i = 0; i < r->addresses->naddrs; ++i) {
grpc_lb_addresses_set_address(
lb_policy_args.addresses, i, &r->addresses->addrs[i].addr,
r->addresses->addrs[i].len, false /* is_balancer */,
NULL /* balancer_name */, NULL /* user_data */);
}
grpc_resolved_addresses_destroy(r->addresses);
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);
gpr_free(lb_policy_args.addresses);
grpc_lb_addresses_destroy(lb_policy_args.addresses,
NULL /* user_data_destroy */);
result = grpc_resolver_result_create();
if (lb_policy != NULL) {
grpc_resolver_result_set_lb_policy(result, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
}
grpc_resolved_addresses_destroy(addresses);
} else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);

@ -58,12 +58,12 @@ typedef struct {
char *lb_policy_name;
/** the addresses that we've 'resolved' */
grpc_resolved_addresses *addresses;
grpc_lb_addresses *addresses;
/** mutex guarding the rest of the state */
gpr_mu mu;
/** have we published? */
int published;
bool published;
/** pending next completion, or NULL */
grpc_closure *next_completion;
/** target result address for next completion */
@ -102,7 +102,7 @@ static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu);
r->published = 0;
r->published = false;
sockaddr_maybe_finish_next_locked(exec_ctx, r);
gpr_mu_unlock(&r->mu);
}
@ -125,21 +125,13 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
grpc_resolver_result *result = grpc_resolver_result_create();
grpc_lb_policy_args lb_policy_args;
memset(&lb_policy_args, 0, sizeof(lb_policy_args));
lb_policy_args.num_addresses = r->addresses->naddrs;
lb_policy_args.addresses =
gpr_malloc(sizeof(grpc_lb_address) * lb_policy_args.num_addresses);
memset(lb_policy_args.addresses, 0,
sizeof(grpc_lb_address) * lb_policy_args.num_addresses);
for (size_t i = 0; i < lb_policy_args.num_addresses; ++i) {
lb_policy_args.addresses[i].resolved_address = &r->addresses->addrs[i];
}
lb_policy_args.addresses = r->addresses;
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);
gpr_free(lb_policy_args.addresses);
grpc_resolver_result_set_lb_policy(result, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr");
r->published = 1;
r->published = true;
*r->target_result = result;
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL;
@ -150,7 +142,7 @@ static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
grpc_resolved_addresses_destroy(r->addresses);
grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */);
gpr_free(r->lb_policy_name);
gpr_free(r);
}
@ -183,7 +175,7 @@ static void do_nothing(void *ignored) {}
static grpc_resolver *sockaddr_create(
grpc_resolver_args *args, const char *default_lb_policy_name,
int parse(grpc_uri *uri, struct sockaddr_storage *dst, size_t *len)) {
int errors_found = 0; /* GPR_FALSE */
bool errors_found = false;
sockaddr_resolver *r;
gpr_slice path_slice;
gpr_slice_buffer path_parts;
@ -224,21 +216,18 @@ static grpc_resolver *sockaddr_create(
gpr_slice_buffer_init(&path_parts);
gpr_slice_split(path_slice, ",", &path_parts);
r->addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
r->addresses->naddrs = path_parts.count;
r->addresses->addrs =
gpr_malloc(sizeof(grpc_resolved_address) * r->addresses->naddrs);
for (size_t i = 0; i < r->addresses->naddrs; i++) {
r->addresses = grpc_lb_addresses_create(path_parts.count);
for (size_t i = 0; i < r->addresses->num_addresses; i++) {
grpc_uri ith_uri = *args->uri;
char *part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
ith_uri.path = part_str;
if (!parse(&ith_uri,
(struct sockaddr_storage *)(&r->addresses->addrs[i].addr),
&r->addresses->addrs[i].len)) {
errors_found = 1; /* GPR_TRUE */
if (!parse(&ith_uri, (struct sockaddr_storage *)(&r->addresses->addresses[i]
.address.addr),
&r->addresses->addresses[i].address.len)) {
errors_found = true;
}
gpr_free(part_str);
r->addresses->addresses[i].is_balancer = lb_enabled;
if (errors_found) break;
}
@ -246,7 +235,7 @@ static grpc_resolver *sockaddr_create(
gpr_slice_unref(path_slice);
if (errors_found) {
gpr_free(r->lb_policy_name);
grpc_resolved_addresses_destroy(r->addresses);
grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */);
gpr_free(r);
return NULL;
}

@ -33,6 +33,7 @@
#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
@ -46,6 +47,7 @@
#include "src/core/ext/transport/chttp2/transport/http2_errors.h"
#include "src/core/ext/transport/chttp2/transport/internal.h"
#include "src/core/ext/transport/chttp2/transport/status_conversion.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/workqueue.h"
#include "src/core/lib/profiling/timers.h"
@ -281,91 +283,77 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (channel_args) {
for (i = 0; i < channel_args->num_args; i++) {
if (0 ==
strcmp(channel_args->args[i].key, GRPC_ARG_MAX_CONCURRENT_STREAMS)) {
if (is_client) {
gpr_log(GPR_ERROR, "%s: is ignored on the client",
GRPC_ARG_MAX_CONCURRENT_STREAMS);
} else if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_MAX_CONCURRENT_STREAMS);
} else {
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
(uint32_t)channel_args->args[i].value.integer);
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) {
if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER);
} else if ((t->next_stream_id & 1) !=
(channel_args->args[i].value.integer & 1)) {
gpr_log(GPR_ERROR, "%s: low bit must be %d on %s",
GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER, t->next_stream_id & 1,
is_client ? "client" : "server");
} else {
t->next_stream_id = (uint32_t)channel_args->args[i].value.integer;
if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) {
const grpc_integer_options options = {-1, 0, INT_MAX};
const int value =
grpc_channel_arg_get_integer(&channel_args->args[i], options);
if (value >= 0) {
if ((t->next_stream_id & 1) != (value & 1)) {
gpr_log(GPR_ERROR, "%s: low bit must be %d on %s",
GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER,
t->next_stream_id & 1, is_client ? "client" : "server");
} else {
t->next_stream_id = (uint32_t)value;
}
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) {
if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
} else if (channel_args->args[i].value.integer <= 5) {
gpr_log(GPR_ERROR, "%s: must be at least 5",
GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES);
} else {
t->stream_lookahead = (uint32_t)channel_args->args[i].value.integer;
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER)) {
if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
} else if (channel_args->args[i].value.integer < 0) {
gpr_log(GPR_ERROR, "%s: must be non-negative",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER);
} else {
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
(uint32_t)channel_args->args[i].value.integer);
const grpc_integer_options options = {-1, 5, INT_MAX};
const int value =
grpc_channel_arg_get_integer(&channel_args->args[i], options);
if (value >= 0) {
t->stream_lookahead = (uint32_t)value;
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
} else if (channel_args->args[i].value.integer < 0) {
gpr_log(GPR_ERROR, "%s: must be non-negative",
GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER);
} else {
grpc_chttp2_hpack_compressor_set_max_usable_size(
&t->hpack_compressor,
(uint32_t)channel_args->args[i].value.integer);
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_MAX_METADATA_SIZE)) {
if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_MAX_METADATA_SIZE);
} else if (channel_args->args[i].value.integer < 0) {
gpr_log(GPR_ERROR, "%s: must be non-negative",
GRPC_ARG_MAX_METADATA_SIZE);
} else {
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
(uint32_t)channel_args->args[i].value.integer);
const grpc_integer_options options = {-1, 0, INT_MAX};
const int value =
grpc_channel_arg_get_integer(&channel_args->args[i], options);
if (value >= 0) {
grpc_chttp2_hpack_compressor_set_max_usable_size(&t->hpack_compressor,
(uint32_t)value);
}
} else if (0 == strcmp(channel_args->args[i].key,
GRPC_ARG_HTTP2_MAX_FRAME_SIZE)) {
if (channel_args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s: must be an integer",
GRPC_ARG_HTTP2_MAX_FRAME_SIZE);
} else if (channel_args->args[i].value.integer < 16384 ||
channel_args->args[i].value.integer > 16777215) {
gpr_log(GPR_ERROR, "%s: must be between 16384 and 16777215",
GRPC_ARG_HTTP2_MAX_FRAME_SIZE);
} else {
push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
(uint32_t)channel_args->args[i].value.integer);
} else {
static const struct {
const char *channel_arg_name;
grpc_chttp2_setting_id setting_id;
grpc_integer_options integer_options;
bool availability[2] /* client, server */;
} settings_map[] = {
{GRPC_ARG_MAX_CONCURRENT_STREAMS,
GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
{-1, 0, INT_MAX},
{false, true}},
{GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
{-1, 0, INT_MAX},
{true, true}},
{GRPC_ARG_MAX_METADATA_SIZE,
GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
{-1, 0, INT_MAX},
{true, true}},
{GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
{-1, 16384, 16777215},
{true, true}},
};
for (size_t j = 0; j < GPR_ARRAY_SIZE(settings_map); j++) {
if (0 == strcmp(channel_args->args[i].key,
settings_map[j].channel_arg_name)) {
if (!settings_map[j].availability[is_client]) {
gpr_log(GPR_DEBUG, "%s is not available on %s",
settings_map[j].channel_arg_name,
is_client ? "clients" : "servers");
} else {
int value = grpc_channel_arg_get_integer(
&channel_args->args[i], settings_map[j].integer_options);
if (value >= 0) {
push_setting(exec_ctx, t, settings_map[j].setting_id, value);
}
}
break;
}
}
}
}

@ -271,3 +271,21 @@ int grpc_channel_args_compare(const grpc_channel_args *a,
}
return 0;
}
int grpc_channel_arg_get_integer(grpc_arg *arg, grpc_integer_options options) {
if (arg->type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s ignored: it must be an integer", arg->key);
return options.default_value;
}
if (arg->value.integer < options.min_value) {
gpr_log(GPR_ERROR, "%s ignored: it must be >= %d", arg->key,
options.min_value);
return options.default_value;
}
if (arg->value.integer > options.max_value) {
gpr_log(GPR_ERROR, "%s ignored: it must be <= %d", arg->key,
options.max_value);
return options.default_value;
}
return arg->value.integer;
}

@ -89,4 +89,12 @@ uint32_t grpc_channel_args_compression_algorithm_get_states(
int grpc_channel_args_compare(const grpc_channel_args *a,
const grpc_channel_args *b);
typedef struct grpc_integer_options {
int default_value; // Return this if value is outside of expected bounds.
int min_value;
int max_value;
} grpc_integer_options;
/** Returns the value of \a arg, subject to the contraints in \a options. */
int grpc_channel_arg_get_integer(grpc_arg *arg, grpc_integer_options options);
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */

@ -0,0 +1,165 @@
//
// Copyright 2016, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include "src/core/lib/channel/message_size_filter.h"
#include <limits.h>
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
// The protobuf library will (by default) start warning at 100 megs.
#define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024)
typedef struct call_data {
// Receive closures are chained: we inject this closure as the
// recv_message_ready up-call on transport_stream_op, and remember to
// call our next_recv_message_ready member after handling it.
grpc_closure recv_message_ready;
// Used by recv_message_ready.
grpc_byte_stream** recv_message;
// Original recv_message_ready callback, invoked after our own.
grpc_closure* next_recv_message_ready;
} call_data;
typedef struct channel_data {
size_t max_send_size;
size_t max_recv_size;
} channel_data;
// Callback invoked when we receive a message. Here we check the max
// receive message size.
static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data,
grpc_error* error) {
grpc_call_element* elem = user_data;
call_data* calld = elem->call_data;
channel_data* chand = elem->channel_data;
if (*calld->recv_message != NULL &&
(*calld->recv_message)->length > chand->max_recv_size) {
char* message_string;
gpr_asprintf(
&message_string, "Received message larger than max (%u vs. %lu)",
(*calld->recv_message)->length, (unsigned long)chand->max_recv_size);
gpr_slice message = gpr_slice_from_copied_string(message_string);
gpr_free(message_string);
grpc_call_element_send_cancel_with_message(
exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message);
}
// Invoke the next callback.
grpc_exec_ctx_sched(exec_ctx, calld->next_recv_message_ready, error, NULL);
}
// Start transport op.
static void start_transport_stream_op(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem,
grpc_transport_stream_op* op) {
call_data* calld = elem->call_data;
channel_data* chand = elem->channel_data;
// Check max send message size.
if (op->send_message != NULL &&
op->send_message->length > chand->max_send_size) {
char* message_string;
gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %lu)",
op->send_message->length, (unsigned long)chand->max_send_size);
gpr_slice message = gpr_slice_from_copied_string(message_string);
gpr_free(message_string);
grpc_call_element_send_cancel_with_message(
exec_ctx, elem, GRPC_STATUS_INVALID_ARGUMENT, &message);
}
// Inject callback for receiving a message.
if (op->recv_message_ready != NULL) {
calld->next_recv_message_ready = op->recv_message_ready;
calld->recv_message = op->recv_message;
op->recv_message_ready = &calld->recv_message_ready;
}
// Chain to the next filter.
grpc_call_next_op(exec_ctx, elem, op);
}
// Constructor for call_data.
static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
grpc_call_element* elem,
grpc_call_element_args* args) {
call_data* calld = elem->call_data;
calld->next_recv_message_ready = NULL;
grpc_closure_init(&calld->recv_message_ready, recv_message_ready, elem);
return GRPC_ERROR_NONE;
}
// Destructor for call_data.
static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
const grpc_call_final_info* final_info,
void* ignored) {}
// Constructor for channel_data.
static void init_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_element* elem,
grpc_channel_element_args* args) {
GPR_ASSERT(!args->is_last);
channel_data* chand = elem->channel_data;
memset(chand, 0, sizeof(*chand));
chand->max_send_size = DEFAULT_MAX_MESSAGE_LENGTH;
chand->max_recv_size = DEFAULT_MAX_MESSAGE_LENGTH;
const grpc_integer_options options = {DEFAULT_MAX_MESSAGE_LENGTH, 0, INT_MAX};
for (size_t i = 0; i < args->channel_args->num_args; ++i) {
if (strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) {
chand->max_send_size = (size_t)grpc_channel_arg_get_integer(
&args->channel_args->args[i], options);
}
if (strcmp(args->channel_args->args[i].key,
GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) {
chand->max_recv_size = (size_t)grpc_channel_arg_get_integer(
&args->channel_args->args[i], options);
}
}
}
// Destructor for channel_data.
static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
grpc_channel_element* elem) {}
const grpc_channel_filter grpc_message_size_filter = {
start_transport_stream_op,
grpc_channel_next_op,
sizeof(call_data),
init_call_elem,
grpc_call_stack_ignore_set_pollset_or_pollset_set,
destroy_call_elem,
sizeof(channel_data),
init_channel_elem,
destroy_channel_elem,
grpc_call_next_get_peer,
"message_size"};

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

@ -37,6 +37,7 @@
#include "src/core/lib/surface/api_trace.h"
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
@ -71,17 +72,33 @@ static void plugin_md_request_metadata_ready(void *request,
error_details);
} else {
size_t i;
bool seen_illegal_header = false;
grpc_credentials_md *md_array = NULL;
if (num_md > 0) {
for (i = 0; i < num_md; i++) {
if (!grpc_header_key_is_legal(md[i].key, strlen(md[i].key))) {
gpr_log(GPR_ERROR, "Plugin added invalid metadata key: %s", md[i].key);
seen_illegal_header = true;
break;
} else if (!grpc_is_binary_header(md[i].key, strlen(md[i].key)) &&
!grpc_header_nonbin_value_is_legal(md[i].value,
md[i].value_length)) {
gpr_log(GPR_ERROR, "Plugin added invalid metadata value.");
seen_illegal_header = true;
break;
}
}
if (seen_illegal_header) {
r->cb(&exec_ctx, r->user_data, NULL, 0, GRPC_CREDENTIALS_ERROR,
"Illegal metadata");
} else if (num_md > 0) {
md_array = gpr_malloc(num_md * sizeof(grpc_credentials_md));
for (i = 0; i < num_md; i++) {
md_array[i].key = gpr_slice_from_copied_string(md[i].key);
md_array[i].value =
gpr_slice_from_copied_buffer(md[i].value, md[i].value_length);
}
}
r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK, NULL);
if (md_array != NULL) {
r->cb(&exec_ctx, r->user_data, md_array, num_md, GRPC_CREDENTIALS_OK,
NULL);
for (i = 0; i < num_md; i++) {
gpr_slice_unref(md_array[i].key);
gpr_slice_unref(md_array[i].value);

@ -1169,17 +1169,6 @@ static void process_data_after_md(grpc_exec_ctx *exec_ctx, batch_control *bctl,
if (gpr_unref(&bctl->steps_to_complete)) {
post_batch_completion(exec_ctx, bctl);
}
} else if (call->receiving_stream->length >
grpc_channel_get_max_message_length(call->channel)) {
cancel_with_status(exec_ctx, call, GRPC_STATUS_INTERNAL,
"Max message size exceeded");
grpc_byte_stream_destroy(exec_ctx, call->receiving_stream);
call->receiving_stream = NULL;
*call->receiving_buffer = NULL;
call->receiving_message = 0;
if (gpr_unref(&bctl->steps_to_complete)) {
post_batch_completion(exec_ctx, bctl);
}
} else {
call->test_only_last_message_flags = call->receiving_stream->flags;
if ((call->receiving_stream->flags & GRPC_WRITE_INTERNAL_COMPRESS) &&

@ -64,7 +64,6 @@ typedef struct registered_call {
struct grpc_channel {
int is_client;
uint32_t max_message_length;
grpc_compression_options compression_options;
grpc_mdelem *default_authority;
@ -80,9 +79,6 @@ struct grpc_channel {
#define CHANNEL_FROM_TOP_ELEM(top_elem) \
CHANNEL_FROM_CHANNEL_STACK(grpc_channel_stack_from_top_element(top_elem))
/* the protobuf library will (by default) start warning at 100megs */
#define DEFAULT_MAX_MESSAGE_LENGTH (4 * 1024 * 1024)
static void destroy_channel(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error);
@ -114,21 +110,10 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
gpr_mu_init(&channel->registered_call_mu);
channel->registered_calls = NULL;
channel->max_message_length = DEFAULT_MAX_MESSAGE_LENGTH;
grpc_compression_options_init(&channel->compression_options);
if (args) {
for (size_t i = 0; i < args->num_args; i++) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_MAX_MESSAGE_LENGTH)) {
if (args->args[i].type != GRPC_ARG_INTEGER) {
gpr_log(GPR_ERROR, "%s ignored: it must be an integer",
GRPC_ARG_MAX_MESSAGE_LENGTH);
} else if (args->args[i].value.integer < 0) {
gpr_log(GPR_ERROR, "%s ignored: it must be >= 0",
GRPC_ARG_MAX_MESSAGE_LENGTH);
} else {
channel->max_message_length = (uint32_t)args->args[i].value.integer;
}
} else if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
if (args->args[i].type != GRPC_ARG_STRING) {
gpr_log(GPR_ERROR, "%s ignored: it must be a string",
GRPC_ARG_DEFAULT_AUTHORITY);
@ -382,7 +367,3 @@ grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel, int i) {
return grpc_mdelem_from_metadata_strings(GRPC_MDSTR_GRPC_STATUS,
grpc_mdstr_from_string(tmp));
}
uint32_t grpc_channel_get_max_message_length(grpc_channel *channel) {
return channel->max_message_length;
}

@ -64,7 +64,6 @@ grpc_channel_stack *grpc_channel_get_channel_stack(grpc_channel *channel);
The returned elem is owned by the caller. */
grpc_mdelem *grpc_channel_get_reffed_status_elem(grpc_channel *channel,
int status_code);
uint32_t grpc_channel_get_max_message_length(grpc_channel *channel);
#ifdef GRPC_STREAM_REFCOUNT_DEBUG
void grpc_channel_internal_ref(grpc_channel *channel, const char *reason);

@ -45,6 +45,7 @@
#include "src/core/lib/channel/connected_channel.h"
#include "src/core/lib/channel/http_client_filter.h"
#include "src/core/lib/channel/http_server_filter.h"
#include "src/core/lib/channel/message_size_filter.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/combiner.h"
@ -98,6 +99,15 @@ static bool maybe_add_http_filter(grpc_channel_stack_builder *builder,
}
static void register_builtin_channel_init() {
grpc_channel_init_register_stage(
GRPC_CLIENT_SUBCHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
prepend_filter, (void *)&grpc_message_size_filter);
grpc_channel_init_register_stage(
GRPC_CLIENT_DIRECT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
prepend_filter, (void *)&grpc_message_size_filter);
grpc_channel_init_register_stage(
GRPC_SERVER_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter,
(void *)&grpc_message_size_filter);
grpc_channel_init_register_stage(
GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, prepend_filter,
(void *)&grpc_compress_filter);

@ -52,7 +52,9 @@ static void do_plugin_list_init(void) {
}
ServerBuilder::ServerBuilder()
: max_message_size_(-1), generic_service_(nullptr) {
: max_receive_message_size_(-1),
max_send_message_size_(-1),
generic_service_(nullptr) {
gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
for (auto it = g_plugin_factory_list->begin();
it != g_plugin_factory_list->end(); it++) {
@ -160,8 +162,11 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
}
(*plugin)->UpdateChannelArguments(&args);
}
if (max_message_size_ > 0) {
args.SetInt(GRPC_ARG_MAX_MESSAGE_LENGTH, max_message_size_);
if (max_receive_message_size_ >= 0) {
args.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, max_receive_message_size_);
}
if (max_send_message_size_ >= 0) {
args.SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, max_send_message_size_);
}
args.SetInt(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
enabled_compression_algorithms_bitset_);
@ -173,8 +178,8 @@ std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
args.SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM,
maybe_default_compression_algorithm_.algorithm);
}
std::unique_ptr<Server> server(
new Server(thread_pool.release(), true, max_message_size_, &args));
std::unique_ptr<Server> server(new Server(thread_pool.release(), true,
max_receive_message_size_, &args));
ServerInitializer* initializer = server->initializer();
// If the server has atleast one sync methods, we know that this is a Sync

@ -220,7 +220,7 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
public:
explicit CallData(Server* server, SyncRequest* mrd)
: cq_(mrd->cq_),
call_(mrd->call_, server, &cq_, server->max_message_size_),
call_(mrd->call_, server, &cq_, server->max_receive_message_size_),
ctx_(mrd->deadline_, mrd->request_metadata_.metadata,
mrd->request_metadata_.count),
has_request_payload_(mrd->has_request_payload_),
@ -243,7 +243,7 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
ctx_.BeginCompletionOp(&call_);
global_callbacks->PreSynchronousRequest(&ctx_);
method_->handler()->RunHandler(MethodHandler::HandlerParameter(
&call_, &ctx_, request_payload_, call_.max_message_size()));
&call_, &ctx_, request_payload_, call_.max_receive_message_size()));
global_callbacks->PostSynchronousRequest(&ctx_);
request_payload_ = nullptr;
void* ignored_tag;
@ -277,8 +277,8 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
static internal::GrpcLibraryInitializer g_gli_initializer;
Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
int max_message_size, ChannelArguments* args)
: max_message_size_(max_message_size),
int max_receive_message_size, ChannelArguments* args)
: max_receive_message_size_(max_receive_message_size),
started_(false),
shutdown_(false),
shutdown_notified_(false),
@ -514,7 +514,7 @@ bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag,
grpc_metadata_array_destroy(&initial_metadata_array_);
context_->set_call(call_);
context_->cq_ = call_cq_;
Call call(call_, server_, call_cq_, server_->max_message_size());
Call call(call_, server_, call_cq_, server_->max_receive_message_size());
if (*status && call_) {
context_->BeginCompletionOp(&call);
}

@ -33,6 +33,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
@ -149,8 +150,7 @@ namespace Grpc.Core.Internal.Tests
var writeTask = responseStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// TODO(jtattermusch): should we throw a different exception type instead?
Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await writeTask);
Assert.ThrowsAsync(typeof(IOException), async () => await writeTask);
fakeCall.ReceivedCloseOnServerHandler(true, cancelled: true);
AssertFinished(asyncCallServer, fakeCall, finishedTask);

@ -180,21 +180,74 @@ namespace Grpc.Core.Internal.Tests
}
[Test]
public void ClientStreaming_WriteCompletionFailure()
public void ClientStreaming_WriteFailureThrowsRpcException()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// TODO: maybe IOException or waiting for RPCException is more appropriate here.
Assert.ThrowsAsync(typeof(InvalidOperationException), async () => await writeTask);
// The write will wait for call to finish to receive the status code.
Assert.IsFalse(writeTask.IsCompleted);
fakeCall.UnaryResponseClientHandler(true,
CreateClientSideStatus(StatusCode.Internal),
null,
new Metadata());
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
}
[Test]
public void ClientStreaming_WriteFailureThrowsRpcException2()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.UnaryResponseClientHandler(true,
CreateClientSideStatus(StatusCode.Internal),
null,
new Metadata());
fakeCall.SendCompletionHandler(false);
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
}
[Test]
public void ClientStreaming_WriteFailureThrowsRpcException3()
{
var resultTask = asyncCall.ClientStreamingCallAsync();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// Until the delayed write completion has been triggered,
// we still act as if there was an active write.
Assert.Throws(typeof(InvalidOperationException), () => requestStream.WriteAsync("request2"));
fakeCall.UnaryResponseClientHandler(true,
CreateClientSideStatus(StatusCode.Internal),
null,
new Metadata());
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode);
// Following attempts to write keep delivering the same status
var ex2 = Assert.ThrowsAsync<RpcException>(async () => await requestStream.WriteAsync("after call has finished"));
Assert.AreEqual(StatusCode.Internal, ex2.Status.StatusCode);
AssertUnaryResponseError(asyncCall, fakeCall, resultTask, StatusCode.Internal);
}
@ -415,6 +468,49 @@ namespace Grpc.Core.Internal.Tests
Assert.DoesNotThrowAsync(async () => await requestStream.CompleteAsync());
}
[Test]
public void DuplexStreaming_WriteFailureThrowsRpcException()
{
asyncCall.StartDuplexStreamingCall();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var responseStream = new ClientResponseStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
fakeCall.SendCompletionHandler(false);
// The write will wait for call to finish to receive the status code.
Assert.IsFalse(writeTask.IsCompleted);
var readTask = responseStream.MoveNext();
fakeCall.ReceivedMessageHandler(true, null);
fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.PermissionDenied));
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.PermissionDenied, ex.Status.StatusCode);
AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.PermissionDenied);
}
[Test]
public void DuplexStreaming_WriteFailureThrowsRpcException2()
{
asyncCall.StartDuplexStreamingCall();
var requestStream = new ClientRequestStream<string, string>(asyncCall);
var responseStream = new ClientResponseStream<string, string>(asyncCall);
var writeTask = requestStream.WriteAsync("request1");
var readTask = responseStream.MoveNext();
fakeCall.ReceivedMessageHandler(true, null);
fakeCall.ReceivedStatusOnClientHandler(true, CreateClientSideStatus(StatusCode.PermissionDenied));
fakeCall.SendCompletionHandler(false);
var ex = Assert.ThrowsAsync<RpcException>(async () => await writeTask);
Assert.AreEqual(StatusCode.PermissionDenied, ex.Status.StatusCode);
AssertStreamingResponseError(asyncCall, fakeCall, readTask, StatusCode.PermissionDenied);
}
[Test]
public void DuplexStreaming_WriteAfterCancellationRequestThrowsTaskCanceledException()
{

@ -341,6 +341,11 @@ namespace Grpc.Core.Internal
get { return true; }
}
protected override Exception GetRpcExceptionClientOnly()
{
return new RpcException(finishedStatus.Value.Status);
}
protected override Task CheckSendAllowedOrEarlyResult()
{
var earlyResult = CheckSendPreconditionsClientSide();
@ -452,6 +457,7 @@ namespace Grpc.Core.Internal
using (Profilers.ForCurrentThread().NewScope("AsyncCall.HandleUnaryResponse"))
{
TaskCompletionSource<object> delayedStreamingWriteTcs = null;
TResponse msg = default(TResponse);
var deserializeException = TryDeserialize(receivedMessage, out msg);
@ -465,13 +471,23 @@ namespace Grpc.Core.Internal
}
finishedStatus = receivedStatus;
if (isStreamingWriteCompletionDelayed)
{
delayedStreamingWriteTcs = streamingWriteTcs;
streamingWriteTcs = null;
}
ReleaseResourcesIfPossible();
}
responseHeadersTcs.SetResult(responseHeaders);
var status = receivedStatus.Status;
if (delayedStreamingWriteTcs != null)
{
delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly());
}
var status = receivedStatus.Status;
if (status.StatusCode != StatusCode.OK)
{
unaryResponseTcs.SetException(new RpcException(status));
@ -490,16 +506,27 @@ namespace Grpc.Core.Internal
// NOTE: because this event is a result of batch containing GRPC_OP_RECV_STATUS_ON_CLIENT,
// success will be always set to true.
TaskCompletionSource<object> delayedStreamingWriteTcs = null;
lock (myLock)
{
finished = true;
finishedStatus = receivedStatus;
if (isStreamingWriteCompletionDelayed)
{
delayedStreamingWriteTcs = streamingWriteTcs;
streamingWriteTcs = null;
}
ReleaseResourcesIfPossible();
}
var status = receivedStatus.Status;
if (delayedStreamingWriteTcs != null)
{
delayedStreamingWriteTcs.SetException(GetRpcExceptionClientOnly());
}
var status = receivedStatus.Status;
if (status.StatusCode != StatusCode.OK)
{
streamingCallFinishedTcs.SetException(new RpcException(status));

@ -69,6 +69,7 @@ namespace Grpc.Core.Internal
protected TaskCompletionSource<TRead> streamingReadTcs; // Completion of a pending streaming read if not null.
protected TaskCompletionSource<object> streamingWriteTcs; // Completion of a pending streaming write or send close from client if not null.
protected TaskCompletionSource<object> sendStatusFromServerTcs;
protected bool isStreamingWriteCompletionDelayed; // Only used for the client side.
protected bool readingDone; // True if last read (i.e. read with null payload) was already received.
protected bool halfcloseRequested; // True if send close have been initiated.
@ -200,6 +201,12 @@ namespace Grpc.Core.Internal
get;
}
/// <summary>
/// Returns an exception to throw for a failed send operation.
/// It is only allowed to call this method for a call that has already finished.
/// </summary>
protected abstract Exception GetRpcExceptionClientOnly();
private void ReleaseResources()
{
if (call != null)
@ -252,18 +259,43 @@ namespace Grpc.Core.Internal
/// </summary>
protected void HandleSendFinished(bool success)
{
bool delayCompletion = false;
TaskCompletionSource<object> origTcs = null;
lock (myLock)
{
origTcs = streamingWriteTcs;
streamingWriteTcs = null;
if (!success && !finished && IsClient) {
// We should be setting this only once per call, following writes will be short circuited
// because they cannot start until the entire call finishes.
GrpcPreconditions.CheckState(!isStreamingWriteCompletionDelayed);
// leave streamingWriteTcs set, it will be completed once call finished.
isStreamingWriteCompletionDelayed = true;
delayCompletion = true;
}
else
{
origTcs = streamingWriteTcs;
streamingWriteTcs = null;
}
ReleaseResourcesIfPossible();
}
if (!success)
{
origTcs.SetException(new InvalidOperationException("Send failed"));
if (!delayCompletion)
{
if (IsClient)
{
GrpcPreconditions.CheckState(finished); // implied by !success && !delayCompletion && IsClient
origTcs.SetException(GetRpcExceptionClientOnly());
}
else
{
origTcs.SetException (new IOException("Error sending from server."));
}
}
// if delayCompletion == true, postpone SetException until call finishes.
}
else
{
@ -283,7 +315,7 @@ namespace Grpc.Core.Internal
if (!success)
{
sendStatusFromServerTcs.SetException(new InvalidOperationException("Error sending status from server."));
sendStatusFromServerTcs.SetException(new IOException("Error sending status from server."));
}
else
{

@ -33,6 +33,7 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
@ -193,6 +194,11 @@ namespace Grpc.Core.Internal
get { return false; }
}
protected override Exception GetRpcExceptionClientOnly()
{
throw new InvalidOperationException("Call be only called for client calls");
}
protected override void OnAfterReleaseResources()
{
server.RemoveCallReference(this);

@ -217,7 +217,7 @@ static NSMutableDictionary *kHostCache;
}
if (_responseSizeLimitOverride) {
args[@GRPC_ARG_MAX_MESSAGE_LENGTH] = _responseSizeLimitOverride;
args[@GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH] = _responseSizeLimitOverride;
}
return args;
}

@ -180,7 +180,7 @@
// - If you're developing the server, consider using response streaming, or let clients filter
// responses by setting a google.protobuf.FieldMask in the request:
// https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto
XCTAssertEqualObjects(error.localizedDescription, @"Max message size exceeded");
XCTAssertEqualObjects(error.localizedDescription, @"Received message larger than max (4194305 vs. 4194304)");
[expectation fulfill];
}];

@ -44,8 +44,8 @@ BINDIR=../../../bins/$CONFIG
"interop_server before calling this script."
exit 1
}
$BINDIR/interop_server --port=5050 &
$BINDIR/interop_server --port=5051 --use_tls &
$BINDIR/interop_server --port=5050 --max_send_message_size=8388608 &
$BINDIR/interop_server --port=5051 --max_send_message_size=8388608 --use_tls &
# Kill them when this script exits.
trap 'kill -9 `jobs -p`' EXIT

@ -1189,7 +1189,7 @@ def insecure_channel(target, options=None):
A Channel to the target through which RPCs may be conducted.
"""
from grpc import _channel
return _channel.Channel(target, options, None)
return _channel.Channel(target, () if options is None else options, None)
def secure_channel(target, credentials, options=None):
@ -1205,10 +1205,11 @@ def secure_channel(target, credentials, options=None):
A Channel to the target through which RPCs may be conducted.
"""
from grpc import _channel
return _channel.Channel(target, options, credentials._credentials)
return _channel.Channel(target, () if options is None else options,
credentials._credentials)
def server(thread_pool, handlers=None):
def server(thread_pool, handlers=None, options=None):
"""Creates a Server with which RPCs can be serviced.
Args:
@ -1219,12 +1220,15 @@ def server(thread_pool, handlers=None):
only handlers the server will use to service RPCs; other handlers may
later be added by calling add_generic_rpc_handlers any time before the
returned Server is started.
options: A sequence of string-value pairs according to which to configure
the created server.
Returns:
A Server with which RPCs can be serviced.
"""
from grpc import _server
return _server.Server(thread_pool, () if handlers is None else handlers)
return _server.Server(thread_pool, () if handlers is None else handlers,
() if options is None else options)
################################### __all__ #################################

@ -842,18 +842,8 @@ def _unsubscribe(state, callback):
def _options(options):
if options is None:
pairs = ((cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT),)
else:
pairs = list(options) + [
(cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT)]
encoded_pairs = [
(_common.encode(arg_name), arg_value) if isinstance(arg_value, int)
else (_common.encode(arg_name), _common.encode(arg_value))
for arg_name, arg_value in pairs]
return cygrpc.ChannelArgs([
cygrpc.ChannelArg(arg_name, arg_value)
for arg_name, arg_value in encoded_pairs])
return list(options) + [
(cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT)]
class Channel(grpc.Channel):
@ -867,7 +857,8 @@ class Channel(grpc.Channel):
credentials: A cygrpc.ChannelCredentials or None.
"""
self._channel = cygrpc.Channel(
_common.encode(target), _options(options), credentials)
_common.encode(target), _common.channel_args(_options(options)),
credentials)
self._call_state = _ChannelCallState(self._channel)
self._connectivity_state = _ChannelConnectivityState(self._channel)

@ -94,6 +94,16 @@ def decode(b):
return b.decode('latin1')
def channel_args(options):
channel_args = []
for key, value in options:
if isinstance(value, six.string_types):
channel_args.append(cygrpc.ChannelArg(encode(key), encode(value)))
else:
channel_args.append(cygrpc.ChannelArg(encode(key), value))
return cygrpc.ChannelArgs(channel_args)
def cygrpc_metadata(application_metadata):
return _EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
cygrpc.Metadatum(encode(key), encode(value))

@ -32,15 +32,16 @@ cimport cpython
cdef class Channel:
def __cinit__(self, bytes target, ChannelArgs arguments=None,
def __cinit__(self, bytes target, ChannelArgs arguments,
ChannelCredentials channel_credentials=None):
grpc_init()
cdef grpc_channel_args *c_arguments = NULL
cdef char *c_target = NULL
self.c_channel = NULL
self.references = []
if arguments is not None:
if len(arguments) > 0:
c_arguments = &arguments.c_args
self.references.append(arguments)
c_target = target
if channel_credentials is None:
with nogil:

@ -135,7 +135,7 @@ cdef extern from "grpc/grpc.h":
const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING
const char *GRPC_ARG_ENABLE_CENSUS
const char *GRPC_ARG_MAX_CONCURRENT_STREAMS
const char *GRPC_ARG_MAX_MESSAGE_LENGTH
const char *GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH
const char *GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER
const char *GRPC_ARG_DEFAULT_AUTHORITY
const char *GRPC_ARG_PRIMARY_USER_AGENT_STRING

@ -39,7 +39,7 @@ class ConnectivityState:
class ChannelArgKey:
enable_census = GRPC_ARG_ENABLE_CENSUS
max_concurrent_streams = GRPC_ARG_MAX_CONCURRENT_STREAMS
max_message_length = GRPC_ARG_MAX_MESSAGE_LENGTH
max_message_length = GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH
http2_initial_sequence_number = GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER
default_authority = GRPC_ARG_DEFAULT_AUTHORITY
primary_user_agent_string = GRPC_ARG_PRIMARY_USER_AGENT_STRING

@ -34,12 +34,12 @@ import time
cdef class Server:
def __cinit__(self, ChannelArgs arguments=None):
def __cinit__(self, ChannelArgs arguments):
grpc_init()
cdef grpc_channel_args *c_arguments = NULL
self.references = []
self.registered_completion_queues = []
if arguments is not None:
if len(arguments) > 0:
c_arguments = &arguments.c_args
self.references.append(arguments)
with nogil:

@ -728,12 +728,11 @@ def _start(state):
cleanup_server, target=_serve, args=(state,))
thread.start()
class Server(grpc.Server):
def __init__(self, thread_pool, generic_handlers):
def __init__(self, thread_pool, generic_handlers, options):
completion_queue = cygrpc.CompletionQueue()
server = cygrpc.Server()
server = cygrpc.Server(_common.channel_args(options))
server.register_completion_queue(completion_queue)
self._state = _ServerState(
completion_queue, server, generic_handlers, thread_pool)

@ -86,6 +86,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/channel/handshaker.c',
'src/core/lib/channel/http_client_filter.c',
'src/core/lib/channel/http_server_filter.c',
'src/core/lib/channel/message_size_filter.c',
'src/core/lib/compression/compression.c',
'src/core/lib/compression/message_compress.c',
'src/core/lib/debug/trace.c',
@ -265,6 +266,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/census/operation.c',
'src/core/ext/census/placeholders.c',
'src/core/ext/census/resource.c',
'src/core/ext/census/trace_context.c',
'src/core/ext/census/tracing.c',
'src/core/plugin_registry/grpc_plugin_registry.c',
'src/boringssl/err_data.c',

@ -7,6 +7,7 @@
"_beta_features_test.BetaFeaturesTest",
"_beta_features_test.ContextManagementAndLifecycleTest",
"_cancel_many_calls_test.CancelManyCallsTest",
"_channel_args_test.ChannelArgsTest",
"_channel_connectivity_test.ChannelConnectivityTest",
"_channel_ready_future_test.ChannelReadyFutureTest",
"_channel_test.ChannelTest",

@ -0,0 +1,53 @@
# Copyright 2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Tests of Channel Args on client/server side."""
import unittest
import grpc
TEST_CHANNEL_ARGS = (
('arg1', b'bytes_val'),
('arg2', 'str_val'),
('arg3', 1),
(b'arg4', 'str_val'),
)
class ChannelArgsTest(unittest.TestCase):
def test_client(self):
grpc.insecure_channel('localhost:8080', options=TEST_CHANNEL_ARGS)
def test_server(self):
grpc.server(None, options=TEST_CHANNEL_ARGS)
if __name__ == '__main__':
unittest.main(verbosity=2)

@ -78,7 +78,7 @@ class ChannelConnectivityTest(unittest.TestCase):
def test_lonely_channel_connectivity(self):
callback = _Callback()
channel = _channel.Channel('localhost:12345', None, None)
channel = _channel.Channel('localhost:12345', (), None)
channel.subscribe(callback.update, try_to_connect=False)
first_connectivities = callback.block_until_connectivities_satisfy(bool)
channel.subscribe(callback.update, try_to_connect=True)
@ -105,13 +105,13 @@ class ChannelConnectivityTest(unittest.TestCase):
def test_immediately_connectable_channel_connectivity(self):
thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
server = _server.Server(thread_pool, ())
server = _server.Server(thread_pool, (), ())
port = server.add_insecure_port('[::]:0')
server.start()
first_callback = _Callback()
second_callback = _Callback()
channel = _channel.Channel('localhost:{}'.format(port), None, None)
channel = _channel.Channel('localhost:{}'.format(port), (), None)
channel.subscribe(first_callback.update, try_to_connect=False)
first_connectivities = first_callback.block_until_connectivities_satisfy(
bool)
@ -146,12 +146,12 @@ class ChannelConnectivityTest(unittest.TestCase):
def test_reachable_then_unreachable_channel_connectivity(self):
thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
server = _server.Server(thread_pool, ())
server = _server.Server(thread_pool, (), ())
port = server.add_insecure_port('[::]:0')
server.start()
callback = _Callback()
channel = _channel.Channel('localhost:{}'.format(port), None, None)
channel = _channel.Channel('localhost:{}'.format(port), (), None)
channel.subscribe(callback.update, try_to_connect=True)
callback.block_until_connectivities_satisfy(_ready_in_connectivities)
# Now take down the server and confirm that channel readiness is repudiated.

@ -79,7 +79,7 @@ class ChannelReadyFutureTest(unittest.TestCase):
def test_immediately_connectable_channel_connectivity(self):
thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
server = _server.Server(thread_pool, ())
server = _server.Server(thread_pool, (), ())
port = server.add_insecure_port('[::]:0')
server.start()
channel = grpc.insecure_channel('localhost:{}'.format(port))

@ -157,11 +157,12 @@ class CancelManyCallsTest(unittest.TestCase):
server_thread_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY)
server_completion_queue = cygrpc.CompletionQueue()
server = cygrpc.Server()
server = cygrpc.Server(cygrpc.ChannelArgs([]))
server.register_completion_queue(server_completion_queue)
port = server.add_http2_port(b'[::]:0')
server.start()
channel = cygrpc.Channel('localhost:{}'.format(port).encode())
channel = cygrpc.Channel('localhost:{}'.format(port).encode(),
cygrpc.ChannelArgs([]))
state = _State()

@ -124,11 +124,12 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase):
def testReadSomeButNotAllResponses(self):
server_completion_queue = cygrpc.CompletionQueue()
server = cygrpc.Server()
server = cygrpc.Server(cygrpc.ChannelArgs([]))
server.register_completion_queue(server_completion_queue)
port = server.add_http2_port(b'[::]:0')
server.start()
channel = cygrpc.Channel('localhost:{}'.format(port).encode())
channel = cygrpc.Channel('localhost:{}'.format(port).encode(),
cygrpc.ChannelArgs([]))
server_shutdown_tag = 'server_shutdown_tag'
server_driver = _ServerDriver(server_completion_queue, server_shutdown_tag)

@ -121,7 +121,7 @@ class TypeSmokeTest(unittest.TestCase):
del call_credentials
def testServerStartNoExplicitShutdown(self):
server = cygrpc.Server()
server = cygrpc.Server(cygrpc.ChannelArgs([]))
completion_queue = cygrpc.CompletionQueue()
server.register_completion_queue(completion_queue)
port = server.add_http2_port(b'[::]:0')
@ -131,7 +131,7 @@ class TypeSmokeTest(unittest.TestCase):
def testServerStartShutdown(self):
completion_queue = cygrpc.CompletionQueue()
server = cygrpc.Server()
server = cygrpc.Server(cygrpc.ChannelArgs([]))
server.add_http2_port(b'[::]:0')
server.register_completion_queue(completion_queue)
server.start()
@ -148,7 +148,7 @@ class ServerClientMixin(object):
def setUpMixin(self, server_credentials, client_credentials, host_override):
self.server_completion_queue = cygrpc.CompletionQueue()
self.server = cygrpc.Server()
self.server = cygrpc.Server(cygrpc.ChannelArgs([]))
self.server.register_completion_queue(self.server_completion_queue)
if server_credentials:
self.port = self.server.add_http2_port(b'[::]:0', server_credentials)
@ -164,7 +164,8 @@ class ServerClientMixin(object):
'localhost:{}'.format(self.port).encode(), client_channel_arguments,
client_credentials)
else:
self.client_channel = cygrpc.Channel('localhost:{}'.format(self.port).encode())
self.client_channel = cygrpc.Channel(
'localhost:{}'.format(self.port).encode(), cygrpc.ChannelArgs([]))
if host_override:
self.host_argument = None # default host
self.expected_host = host_override

@ -386,7 +386,7 @@ void Init_grpc_channel() {
rb_define_const(grpc_rb_cChannel, "MAX_CONCURRENT_STREAMS",
ID2SYM(rb_intern(GRPC_ARG_MAX_CONCURRENT_STREAMS)));
rb_define_const(grpc_rb_cChannel, "MAX_MESSAGE_LENGTH",
ID2SYM(rb_intern(GRPC_ARG_MAX_MESSAGE_LENGTH)));
ID2SYM(rb_intern(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH)));
id_insecure_channel = rb_intern("this_channel_is_insecure");
Init_grpc_propagate_masks();
Init_grpc_connectivity_states();

@ -0,0 +1,3 @@
trace_id { hi : 5; lo : 1 }
span_id : 7
is_sampled : true

@ -0,0 +1,2 @@
trace_id { hi : 5; lo : 1 }
span_id : 7

@ -0,0 +1,2 @@
span_id : 7
is_sampled : true

@ -0,0 +1,2 @@
trace_id { hi : 5; lo : 1 }
is_sampled : true

@ -0,0 +1,231 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <grpc/census.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/useful.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "src/core/ext/census/base_resources.h"
#include "src/core/ext/census/resource.h"
#include "test/core/util/test_config.h"
#include "src/core/ext/census/gen/trace_context.pb.h"
#include "src/core/ext/census/trace_context.h"
#include "third_party/nanopb/pb_decode.h"
#include "third_party/nanopb/pb_encode.h"
#define BUF_SIZE 256
/* Encodes a TraceContext structure (ctxt1) to a buffer, and then decodes it
to a second TraceContext (ctxt2). Validates that the resulting TraceContext
has a span_id, trace_id, and that the values are equal to those in initial
TraceContext. On success, returns true. If encode_trace_context returns 0,
decode_trace_context fails, or the resulting TraceContext is missing a trace_id
or span_id, it will return false. */
bool validate_encode_decode_context(google_trace_TraceContext *ctxt1,
uint8_t *buffer, size_t buf_size) {
google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero;
size_t msg_length;
GPR_ASSERT(ctxt1->has_trace_id && ctxt1->has_span_id);
msg_length = encode_trace_context(ctxt1, buffer, buf_size);
if (msg_length == 0) {
return false;
}
if (!decode_trace_context(&ctxt2, buffer, msg_length)) {
return false;
}
if (!ctxt2.has_trace_id || !ctxt2.has_span_id) {
return false;
}
GPR_ASSERT(
ctxt1->trace_id.hi == ctxt2.trace_id.hi &&
ctxt1->trace_id.lo == ctxt2.trace_id.lo &&
ctxt1->span_id == ctxt2.span_id &&
ctxt1->has_is_sampled == ctxt2.has_is_sampled &&
(ctxt1->has_is_sampled ? ctxt1->is_sampled == ctxt2.is_sampled : true));
return true;
}
/* Decodes a proto-encoded TraceContext from a buffer. If decode_trace_context
fails or the resulting TraceContext is missing a trace_id or span_id it will
return false, otherwise returns true. */
bool validate_decode_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
size_t msg_length) {
// Validate the decoding of a context written to buffer.
if (!decode_trace_context(ctxt, buffer, msg_length)) {
return false;
}
if (!ctxt->has_trace_id || !ctxt->has_span_id) {
return false;
}
return true;
}
/* Read an encoded trace context from a file. Validates that the decoding
gives the expected result (succeed). */
static void read_and_validate_context_from_file(google_trace_TraceContext *ctxt,
const char *file,
const bool succeed) {
uint8_t buffer[BUF_SIZE];
FILE *input = fopen(file, "rb");
GPR_ASSERT(input != NULL);
size_t nbytes = fread(buffer, 1, BUF_SIZE, input);
GPR_ASSERT(nbytes <= BUF_SIZE && feof(input) && !ferror(input));
bool res = validate_decode_context(ctxt, buffer, nbytes);
GPR_ASSERT(res == succeed);
GPR_ASSERT(fclose(input) == 0);
}
// Test full proto-buffer.
static void test_full() {
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
read_and_validate_context_from_file(
&ctxt, "test/core/census/data/context_full.pb", true);
}
// Test empty proto-buffer.
static void test_empty() {
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
read_and_validate_context_from_file(
&ctxt, "test/core/census/data/context_empty.pb", false);
}
// Test proto-buffer with only trace_id.
static void test_trace_only() {
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
read_and_validate_context_from_file(
&ctxt, "test/core/census/data/context_trace_only.pb", false);
}
// Test proto-buffer with only span_id.
static void test_span_only() {
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
read_and_validate_context_from_file(
&ctxt, "test/core/census/data/context_span_only.pb", false);
}
// Test proto-buffer without is_sampled value.
static void test_no_sample() {
google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
read_and_validate_context_from_file(
&ctxt, "test/core/census/data/context_no_sample.pb", true);
GPR_ASSERT(ctxt.has_is_sampled == false && ctxt.is_sampled == false);
}
static void test_encode_decode() {
uint8_t buffer[BUF_SIZE] = {0};
google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
ctxt1.has_trace_id = true;
ctxt1.trace_id.has_hi = true;
ctxt1.trace_id.has_lo = true;
ctxt1.trace_id.lo = 1;
ctxt1.trace_id.hi = 2;
ctxt1.has_span_id = true;
ctxt1.span_id = 3;
validate_encode_decode_context(&ctxt1, buffer, sizeof(buffer));
google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero;
ctxt2.has_trace_id = true;
ctxt2.trace_id.has_hi = false;
ctxt2.trace_id.has_lo = false;
ctxt2.has_span_id = true;
validate_encode_decode_context(&ctxt2, buffer, sizeof(buffer));
}
// Test a corrupted proto-buffer.
static void test_corrupt() {
uint8_t buffer[BUF_SIZE] = {0};
google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
size_t msg_length;
ctxt1.has_trace_id = true;
ctxt1.trace_id.has_hi = true;
ctxt1.trace_id.has_lo = true;
ctxt1.trace_id.lo = 1;
ctxt1.trace_id.hi = 2;
ctxt1.has_span_id = true;
ctxt1.span_id = 3;
ctxt1.is_sampled = true;
msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer));
/* Corrupt some bytes. 255 (0xFF) should be illegal for the first byte of the
proto encoded object. */
buffer[0] = 255;
bool res = validate_decode_context(&ctxt1, buffer, msg_length);
GPR_ASSERT(res == false);
}
static void test_buffer_size() {
// This buffer is too small, so the encode should fail.
uint8_t buffer[16] = {0};
google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
size_t msg_length;
ctxt1.has_trace_id = true;
ctxt1.trace_id.has_hi = true;
ctxt1.trace_id.has_lo = true;
ctxt1.trace_id.lo = 1;
ctxt1.trace_id.hi = 2;
ctxt1.has_span_id = true;
ctxt1.span_id = 3;
ctxt1.is_sampled = true;
msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer));
GPR_ASSERT(msg_length == 0);
}
int main(int argc, char **argv) {
grpc_test_init(argc, argv);
test_full();
test_empty();
test_trace_only();
test_span_only();
test_encode_decode();
test_corrupt();
test_no_sample();
test_buffer_size();
return 0;
}

@ -98,19 +98,22 @@ static void end_test(grpc_end2end_test_fixture *f) {
grpc_completion_queue_destroy(f->cq);
}
static void test_max_message_length(grpc_end2end_test_config config) {
static void test_max_message_length(grpc_end2end_test_config config,
bool send_limit) {
gpr_log(GPR_INFO, "testing with send_limit=%d", send_limit);
grpc_end2end_test_fixture f;
grpc_arg server_arg;
grpc_channel_args server_args;
grpc_call *c;
grpc_call *s;
grpc_arg channel_arg;
grpc_channel_args channel_args;
grpc_call *c = NULL;
grpc_call *s = NULL;
cq_verifier *cqv;
grpc_op ops[6];
grpc_op *op;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
grpc_byte_buffer *request_payload =
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
grpc_byte_buffer *recv_payload;
grpc_byte_buffer *recv_payload = NULL;
grpc_metadata_array initial_metadata_recv;
grpc_metadata_array trailing_metadata_recv;
grpc_metadata_array request_metadata_recv;
@ -121,14 +124,17 @@ static void test_max_message_length(grpc_end2end_test_config config) {
size_t details_capacity = 0;
int was_cancelled = 2;
server_arg.key = GRPC_ARG_MAX_MESSAGE_LENGTH;
server_arg.type = GRPC_ARG_INTEGER;
server_arg.value.integer = 5;
channel_arg.key = send_limit ? GRPC_ARG_MAX_SEND_MESSAGE_LENGTH
: GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH;
channel_arg.type = GRPC_ARG_INTEGER;
channel_arg.value.integer = 5;
server_args.num_args = 1;
server_args.args = &server_arg;
channel_args.num_args = 1;
channel_args.args = &channel_arg;
f = begin_test(config, "test_max_message_length", NULL, &server_args);
f = begin_test(config, "test_max_message_length",
send_limit ? &channel_args : NULL,
send_limit ? NULL : &channel_args);
cqv = cq_verifier_create(f.cq);
c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq,
@ -173,6 +179,12 @@ static void test_max_message_length(grpc_end2end_test_config config) {
error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
if (send_limit) {
CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
cq_verify(cqv);
goto done;
}
error =
grpc_server_request_call(f.server, &s, &call_details,
&request_metadata_recv, f.cq, f.cq, tag(101));
@ -199,11 +211,16 @@ static void test_max_message_length(grpc_end2end_test_config config) {
CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
cq_verify(cqv);
GPR_ASSERT(status != GRPC_STATUS_OK);
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234"));
GPR_ASSERT(was_cancelled == 1);
GPR_ASSERT(recv_payload == NULL);
done:
GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
GPR_ASSERT(strcmp(details,
send_limit
? "Sent message larger than max (11 vs. 5)"
: "Received message larger than max (11 vs. 5)") == 0);
gpr_free(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
@ -211,9 +228,10 @@ static void test_max_message_length(grpc_end2end_test_config config) {
grpc_metadata_array_destroy(&request_metadata_recv);
grpc_call_details_destroy(&call_details);
grpc_byte_buffer_destroy(request_payload);
grpc_byte_buffer_destroy(recv_payload);
grpc_call_destroy(c);
grpc_call_destroy(s);
if (s != NULL) grpc_call_destroy(s);
cq_verifier_destroy(cqv);
@ -222,7 +240,8 @@ static void test_max_message_length(grpc_end2end_test_config config) {
}
void max_message_length(grpc_end2end_test_config config) {
test_max_message_length(config);
test_max_message_length(config, true);
test_max_message_length(config, false);
}
void max_message_length_pre_init(void) {}

@ -84,38 +84,6 @@ static void one_test(grpc_channel_args *args, char *expected_error_message) {
static void test_no_error_message(void) { one_test(NULL, NULL); }
static void test_max_message_length_type(void) {
grpc_arg client_arg;
grpc_channel_args client_args;
char *expected_error_message;
client_arg.type = GRPC_ARG_STRING;
client_arg.key = GRPC_ARG_MAX_MESSAGE_LENGTH;
client_arg.value.string = NULL;
client_args.num_args = 1;
client_args.args = &client_arg;
expected_error_message = compose_error_string(
GRPC_ARG_MAX_MESSAGE_LENGTH, " ignored: it must be an integer");
one_test(&client_args, expected_error_message);
}
static void test_max_message_length_negative(void) {
grpc_arg client_arg;
grpc_channel_args client_args;
char *expected_error_message;
client_arg.type = GRPC_ARG_INTEGER;
client_arg.key = GRPC_ARG_MAX_MESSAGE_LENGTH;
client_arg.value.integer = -1;
client_args.num_args = 1;
client_args.args = &client_arg;
expected_error_message = compose_error_string(GRPC_ARG_MAX_MESSAGE_LENGTH,
" ignored: it must be >= 0");
one_test(&client_args, expected_error_message);
}
static void test_default_authority_type(void) {
grpc_arg client_arg;
grpc_channel_args client_args;
@ -174,8 +142,6 @@ int main(int argc, char **argv) {
gpr_set_log_function(log_error_sink);
test_no_error_message();
test_max_message_length_type();
test_max_message_length_negative();
test_default_authority_type();
test_ssl_name_override_type();
test_ssl_name_override_failed();

@ -80,11 +80,14 @@ const char kTestCredsPluginErrorMsg[] = "Could not find plugin metadata.";
class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
public:
static const char kMetadataKey[];
static const char kGoodMetadataKey[];
static const char kBadMetadataKey[];
TestMetadataCredentialsPlugin(grpc::string_ref metadata_value,
TestMetadataCredentialsPlugin(grpc::string_ref metadata_key,
grpc::string_ref metadata_value,
bool is_blocking, bool is_successful)
: metadata_value_(metadata_value.data(), metadata_value.length()),
: metadata_key_(metadata_key.data(), metadata_key.length()),
metadata_value_(metadata_value.data(), metadata_value.length()),
is_blocking_(is_blocking),
is_successful_(is_successful) {}
@ -99,7 +102,7 @@ class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
EXPECT_TRUE(channel_auth_context.IsPeerAuthenticated());
EXPECT_TRUE(metadata != nullptr);
if (is_successful_) {
metadata->insert(std::make_pair(kMetadataKey, metadata_value_));
metadata->insert(std::make_pair(metadata_key_, metadata_value_));
return Status::OK;
} else {
return Status(StatusCode::NOT_FOUND, kTestCredsPluginErrorMsg);
@ -107,12 +110,16 @@ class TestMetadataCredentialsPlugin : public MetadataCredentialsPlugin {
}
private:
grpc::string metadata_key_;
grpc::string metadata_value_;
bool is_blocking_;
bool is_successful_;
};
const char TestMetadataCredentialsPlugin::kMetadataKey[] = "TestPluginMetadata";
const char TestMetadataCredentialsPlugin::kBadMetadataKey[] =
"TestPluginMetadata";
const char TestMetadataCredentialsPlugin::kGoodMetadataKey[] =
"test-plugin-metadata";
class TestAuthMetadataProcessor : public AuthMetadataProcessor {
public:
@ -123,13 +130,17 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor {
std::shared_ptr<CallCredentials> GetCompatibleClientCreds() {
return MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(kGoodGuy, is_blocking_, true)));
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey, kGoodGuy,
is_blocking_, true)));
}
std::shared_ptr<CallCredentials> GetIncompatibleClientCreds() {
return MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin("Mr Hyde", is_blocking_, true)));
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey, "Mr Hyde",
is_blocking_, true)));
}
// Interface implementation
@ -142,7 +153,7 @@ class TestAuthMetadataProcessor : public AuthMetadataProcessor {
EXPECT_TRUE(context != nullptr);
EXPECT_TRUE(response_metadata != nullptr);
auto auth_md =
auth_metadata.find(TestMetadataCredentialsPlugin::kMetadataKey);
auth_metadata.find(TestMetadataCredentialsPlugin::kGoodMetadataKey);
EXPECT_NE(auth_md, auth_metadata.end());
string_ref auth_md_value = auth_md->second;
if (auth_md_value == kGoodGuy) {
@ -1322,6 +1333,40 @@ TEST_P(SecureEnd2endTest, OverridePerCallCredentials) {
EXPECT_TRUE(s.ok());
}
TEST_P(SecureEnd2endTest, AuthMetadataPluginKeyFailure) {
ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kBadMetadataKey,
"Does not matter, will fail the key is invalid.", false, true))));
request.set_message("Hello");
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
TEST_P(SecureEnd2endTest, AuthMetadataPluginValueFailure) {
ResetStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey,
"With illegal \n value.", false, true))));
request.set_message("Hello");
Status s = stub_->Echo(&context, request, &response);
EXPECT_FALSE(s.ok());
EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
}
TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) {
ResetStub();
EchoRequest request;
@ -1330,6 +1375,7 @@ TEST_P(SecureEnd2endTest, NonBlockingAuthMetadataPluginFailure) {
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey,
"Does not matter, will fail anyway (see 3rd param)", false,
false))));
request.set_message("Hello");
@ -1388,6 +1434,7 @@ TEST_P(SecureEnd2endTest, BlockingAuthMetadataPluginFailure) {
context.set_credentials(
MetadataCredentialsFromPlugin(std::unique_ptr<MetadataCredentialsPlugin>(
new TestMetadataCredentialsPlugin(
TestMetadataCredentialsPlugin::kGoodMetadataKey,
"Does not matter, will fail anyway (see 3rd param)", true,
false))));
request.set_message("Hello");

@ -56,6 +56,7 @@
DEFINE_bool(use_tls, false, "Whether to use tls.");
DEFINE_int32(port, 0, "Server port.");
DEFINE_int32(max_send_message_size, -1, "The maximum send message size.");
using grpc::Server;
using grpc::ServerBuilder;
@ -321,6 +322,9 @@ void grpc::testing::interop::RunServer(
ServerBuilder builder;
builder.RegisterService(&service);
builder.AddListeningPort(server_address.str(), creds);
if (FLAGS_max_send_message_size >= 0) {
builder.SetMaxSendMessageSize(FLAGS_max_send_message_size);
}
std::unique_ptr<Server> server(builder.BuildAndStart());
gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str());
while (!g_got_sigint) {

@ -879,6 +879,7 @@ src/core/lib/channel/context.h \
src/core/lib/channel/handshaker.h \
src/core/lib/channel/http_client_filter.h \
src/core/lib/channel/http_server_filter.h \
src/core/lib/channel/message_size_filter.h \
src/core/lib/compression/algorithm_metadata.h \
src/core/lib/compression/message_compress.h \
src/core/lib/debug/trace.h \
@ -991,6 +992,7 @@ src/core/lib/channel/connected_channel.c \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \

@ -795,6 +795,7 @@ src/core/lib/channel/context.h \
src/core/lib/channel/handshaker.h \
src/core/lib/channel/http_client_filter.h \
src/core/lib/channel/http_server_filter.h \
src/core/lib/channel/message_size_filter.h \
src/core/lib/compression/algorithm_metadata.h \
src/core/lib/compression/message_compress.h \
src/core/lib/debug/trace.h \
@ -945,6 +946,7 @@ src/core/ext/census/grpc_filter.h \
src/core/ext/census/mlog.h \
src/core/ext/census/resource.h \
src/core/ext/census/rpc_metric_id.h \
src/core/ext/census/trace_context.h \
src/core/lib/surface/init.c \
src/core/lib/channel/channel_args.c \
src/core/lib/channel/channel_stack.c \
@ -954,6 +956,7 @@ src/core/lib/channel/connected_channel.c \
src/core/lib/channel/handshaker.c \
src/core/lib/channel/http_client_filter.c \
src/core/lib/channel/http_server_filter.c \
src/core/lib/channel/message_size_filter.c \
src/core/lib/compression/compression.c \
src/core/lib/compression/message_compress.c \
src/core/lib/debug/trace.c \
@ -1133,6 +1136,7 @@ src/core/ext/census/mlog.c \
src/core/ext/census/operation.c \
src/core/ext/census/placeholders.c \
src/core/ext/census/resource.c \
src/core/ext/census/trace_context.c \
src/core/ext/census/tracing.c \
src/core/plugin_registry/grpc_plugin_registry.c \
include/grpc/support/alloc.h \

@ -63,6 +63,8 @@ _URL_BASE = 'https://grpc-testing.appspot.com/job'
_KNOWN_ERRORS = [
'Failed to build workspace Tests with scheme AllTests',
'Build timed out',
'TIMEOUT: tools/run_tests/pre_build_node.sh',
'TIMEOUT: tools/run_tests/pre_build_ruby.sh',
'FATAL: Unable to produce a script file',
'FAILED: build_docker_c\+\+',
'cannot find package \"cloud.google.com/go/compute/metadata\"',

@ -156,6 +156,22 @@
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
],
"headers": [],
"language": "c",
"name": "census_trace_context_test",
"src": [
"test/core/census/trace_context_test.c"
],
"third_party": false,
"type": "target"
},
{
"deps": [
"gpr",
@ -5695,7 +5711,8 @@
"src/core/ext/census/grpc_filter.h",
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h"
"src/core/ext/census/rpc_metric_id.h",
"src/core/ext/census/trace_context.h"
],
"language": "c",
"name": "census",
@ -5723,6 +5740,8 @@
"src/core/ext/census/resource.c",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
"src/core/ext/census/trace_context.c",
"src/core/ext/census/trace_context.h",
"src/core/ext/census/tracing.c"
],
"third_party": false,
@ -5925,6 +5944,7 @@
"src/core/lib/channel/handshaker.h",
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/message_compress.h",
"src/core/lib/debug/trace.h",
@ -6024,6 +6044,8 @@
"src/core/lib/channel/http_client_filter.h",
"src/core/lib/channel/http_server_filter.c",
"src/core/lib/channel/http_server_filter.h",
"src/core/lib/channel/message_size_filter.c",
"src/core/lib/channel/message_size_filter.h",
"src/core/lib/compression/algorithm_metadata.h",
"src/core/lib/compression/compression.c",
"src/core/lib/compression/message_compress.c",

@ -190,6 +190,27 @@
"windows"
]
},
{
"args": [],
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"flaky": false,
"gtest": false,
"language": "c",
"name": "census_trace_context_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
]
},
{
"args": [],
"ci_platforms": [

@ -120,6 +120,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_resource_test", "vcx
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_trace_context_test", "vcxproj\test\census_trace_context_test\census_trace_context_test.vcxproj", "{14511310-FAE4-C287-31DC-D6F456D10AF3}"
ProjectSection(myProperties) = preProject
lib = "False"
EndProjectSection
ProjectSection(ProjectDependencies) = postProject
{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "channel_create_test", "vcxproj\test\channel_create_test\channel_create_test.vcxproj", "{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}"
ProjectSection(myProperties) = preProject
lib = "False"
@ -1660,6 +1671,22 @@ Global
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|Win32.Build.0 = Release|Win32
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|x64.ActiveCfg = Release|x64
{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|x64.Build.0 = Release|x64
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug|Win32.ActiveCfg = Debug|Win32
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug|x64.ActiveCfg = Debug|x64
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release|Win32.ActiveCfg = Release|Win32
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release|x64.ActiveCfg = Release|x64
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug|Win32.Build.0 = Debug|Win32
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug|x64.Build.0 = Debug|x64
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release|Win32.Build.0 = Release|Win32
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release|x64.Build.0 = Release|x64
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug-DLL|Win32.Build.0 = Debug|Win32
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug-DLL|x64.ActiveCfg = Debug|x64
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug-DLL|x64.Build.0 = Debug|x64
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release-DLL|Win32.ActiveCfg = Release|Win32
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release-DLL|Win32.Build.0 = Release|Win32
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release-DLL|x64.ActiveCfg = Release|x64
{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release-DLL|x64.Build.0 = Release|x64
{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|Win32.ActiveCfg = Debug|Win32
{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|x64.ActiveCfg = Debug|x64
{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Release|Win32.ActiveCfg = Release|Win32

@ -379,6 +379,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
@ -534,6 +535,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">

@ -124,6 +124,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
<Filter>src\core\lib\compression</Filter>
</ClCompile>
@ -731,6 +734,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
<Filter>src\core\lib\compression</Filter>
</ClInclude>

@ -375,6 +375,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
@ -520,6 +521,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">

@ -109,6 +109,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
<Filter>src\core\lib\compression</Filter>
</ClCompile>
@ -704,6 +707,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
<Filter>src\core\lib\compression</Filter>
</ClInclude>

@ -304,6 +304,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\handshaker.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_client_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\lib\debug\trace.h" />
@ -454,6 +455,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
@ -474,6 +476,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\message_compress.c">
@ -832,6 +836,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\trace_context.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_plugin_registry.c">

@ -28,6 +28,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.c">
<Filter>src\core\lib\channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\lib\compression\compression.c">
<Filter>src\core\lib\compression</Filter>
</ClCompile>
@ -565,6 +568,9 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\trace_context.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
<Filter>src\core\ext\census</Filter>
</ClCompile>
@ -680,6 +686,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\http_server_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\channel\message_size_filter.h">
<Filter>src\core\lib\channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\lib\compression\algorithm_metadata.h">
<Filter>src\core\lib\compression</Filter>
</ClInclude>
@ -1130,6 +1139,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>

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

Loading…
Cancel
Save