aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD18
-rw-r--r--CMakeLists.txt7
-rw-r--r--Makefile44
-rw-r--r--binding.gyp2
-rw-r--r--build.yaml14
-rw-r--r--config.m42
-rw-r--r--doc/core/pending_api_cleanups.md15
-rw-r--r--doc/server_reflection_tutorial.md192
-rw-r--r--gRPC-Core.podspec8
-rwxr-xr-xgrpc.gemspec4
-rw-r--r--include/grpc++/impl/codegen/call.h73
-rw-r--r--include/grpc++/impl/codegen/method_handler_impl.h4
-rw-r--r--include/grpc++/impl/codegen/proto_utils.h7
-rw-r--r--include/grpc++/impl/codegen/rpc_service_method.h4
-rw-r--r--include/grpc++/impl/codegen/serialization_traits.h8
-rw-r--r--include/grpc++/impl/codegen/server_interface.h6
-rw-r--r--include/grpc++/impl/codegen/sync_stream.h8
-rw-r--r--include/grpc++/impl/codegen/thrift_utils.h2
-rw-r--r--include/grpc++/server.h12
-rw-r--r--include/grpc++/server_builder.h20
-rw-r--r--include/grpc++/support/byte_buffer.h2
-rw-r--r--include/grpc/impl/codegen/grpc_types.h6
-rw-r--r--package.xml4
-rw-r--r--src/core/ext/census/trace_context.c86
-rw-r--r--src/core/ext/census/trace_context.h68
-rw-r--r--src/core/ext/census/tracing.c18
-rw-r--r--src/core/ext/client_config/lb_policy_factory.c38
-rw-r--r--src/core/ext/client_config/lb_policy_factory.h32
-rw-r--r--src/core/ext/client_config/resolver_result.c80
-rw-r--r--src/core/ext/client_config/resolver_result.h83
-rw-r--r--src/core/ext/client_config/subchannel.c26
-rw-r--r--src/core/ext/lb_policy/grpclb/grpclb.c149
-rw-r--r--src/core/ext/lb_policy/pick_first/pick_first.c23
-rw-r--r--src/core/ext/lb_policy/round_robin/round_robin.c36
-rw-r--r--src/core/ext/resolver/dns/native/dns_resolver.c23
-rw-r--r--src/core/ext/resolver/sockaddr/sockaddr_resolver.c41
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c144
-rw-r--r--src/core/lib/channel/channel_args.c18
-rw-r--r--src/core/lib/channel/channel_args.h8
-rw-r--r--src/core/lib/channel/message_size_filter.c165
-rw-r--r--src/core/lib/channel/message_size_filter.h39
-rw-r--r--src/core/lib/security/credentials/plugin/plugin_credentials.c25
-rw-r--r--src/core/lib/surface/call.c11
-rw-r--r--src/core/lib/surface/channel.c21
-rw-r--r--src/core/lib/surface/channel.h1
-rw-r--r--src/core/lib/surface/init.c10
-rw-r--r--src/cpp/server/server_builder.cc15
-rw-r--r--src/cpp/server/server_cc.cc10
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs4
-rw-r--r--src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs102
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCall.cs31
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallBase.cs40
-rw-r--r--src/csharp/Grpc.Core/Internal/AsyncCallServer.cs6
-rw-r--r--src/objective-c/GRPCClient/private/GRPCHost.m2
-rw-r--r--src/objective-c/tests/InteropTests.m2
-rwxr-xr-xsrc/objective-c/tests/run_tests.sh4
-rw-r--r--src/python/grpcio/grpc/__init__.py12
-rw-r--r--src/python/grpcio/grpc/_channel.py17
-rw-r--r--src/python/grpcio/grpc/_common.py10
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi5
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi2
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi2
-rw-r--r--src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi4
-rw-r--r--src/python/grpcio/grpc/_server.py5
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py2
-rw-r--r--src/python/grpcio_tests/tests/tests.json1
-rw-r--r--src/python/grpcio_tests/tests/unit/_channel_args_test.py53
-rw-r--r--src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py10
-rw-r--r--src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py2
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py5
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py5
-rw-r--r--src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py9
-rw-r--r--src/ruby/ext/grpc/rb_channel.c2
-rw-r--r--test/core/census/data/context_empty.pb0
-rw-r--r--test/core/census/data/context_empty.txt0
-rw-r--r--test/core/census/data/context_full.pbbin0 -> 31 bytes
-rw-r--r--test/core/census/data/context_full.txt3
-rw-r--r--test/core/census/data/context_no_sample.pbbin0 -> 29 bytes
-rw-r--r--test/core/census/data/context_no_sample.txt2
-rw-r--r--test/core/census/data/context_span_only.pbbin0 -> 11 bytes
-rw-r--r--test/core/census/data/context_span_only.txt2
-rw-r--r--test/core/census/data/context_trace_only.pbbin0 -> 22 bytes
-rw-r--r--test/core/census/data/context_trace_only.txt2
-rw-r--r--test/core/census/trace_context_test.c231
-rw-r--r--test/core/end2end/tests/max_message_length.c51
-rw-r--r--test/core/surface/invalid_channel_args_test.c34
-rw-r--r--test/cpp/end2end/end2end_test.cc63
-rw-r--r--test/cpp/interop/interop_server.cc4
-rw-r--r--tools/doxygen/Doxyfile.c++.internal2
-rw-r--r--tools/doxygen/Doxyfile.core.internal4
-rwxr-xr-xtools/run_tests/run_build_statistics.py2
-rw-r--r--tools/run_tests/sources_and_headers.json24
-rw-r--r--tools/run_tests/tests.json21
-rw-r--r--vsprojects/buildtests_c.sln27
-rw-r--r--vsprojects/vcxproj/grpc++/grpc++.vcxproj3
-rw-r--r--vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters6
-rw-r--r--vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj3
-rw-r--r--vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters6
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj6
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj.filters12
-rw-r--r--vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj3
-rw-r--r--vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters6
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj6
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters12
-rw-r--r--vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj199
-rw-r--r--vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj.filters21
106 files changed, 2170 insertions, 554 deletions
diff --git a/BUILD b/BUILD
index 76ae0e94f2..5a692da75c 100644
--- a/BUILD
+++ b/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",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f2a6f53496..4aa31adaca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/Makefile b/Makefile
index 6d9c098e89..27308742b6 100644
--- a/Makefile
+++ b/Makefile
@@ -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 \
diff --git a/binding.gyp b/binding.gyp
index 15ee99ae1c..a54eb1a160 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -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',
],
diff --git a/build.yaml b/build.yaml
index b532216670..285d78f44b 100644
--- a/build.yaml
+++ b/build.yaml
@@ -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
diff --git a/config.m4 b/config.m4
index 01b448e593..422b26b1ab 100644
--- a/config.m4
+++ b/config.m4
@@ -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 \
diff --git a/doc/core/pending_api_cleanups.md b/doc/core/pending_api_cleanups.md
new file mode 100644
index 0000000000..6d30e0b0e6
--- /dev/null
+++ b/doc/core/pending_api_cleanups.md
@@ -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`)
diff --git a/doc/server_reflection_tutorial.md b/doc/server_reflection_tutorial.md
new file mode 100644
index 0000000000..ecb176723c
--- /dev/null
+++ b/doc/server_reflection_tutorial.md
@@ -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);
+ ```
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 6e4a1ce5c4..9348e972aa 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -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|
diff --git a/grpc.gemspec b/grpc.gemspec
index 83c413326e..aa87b2d191 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -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 )
diff --git a/include/grpc++/impl/codegen/call.h b/include/grpc++/impl/codegen/call.h
index 20087289f8..e211373e7d 100644
--- a/include/grpc++/impl/codegen/call.h
+++ b/include/grpc++/impl/codegen/call.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
diff --git a/include/grpc++/impl/codegen/method_handler_impl.h b/include/grpc++/impl/codegen/method_handler_impl.h
index d989263252..52f927631c 100644
--- a/include/grpc++/impl/codegen/method_handler_impl.h
+++ b/include/grpc++/impl/codegen/method_handler_impl.h
@@ -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);
diff --git a/include/grpc++/impl/codegen/proto_utils.h b/include/grpc++/impl/codegen/proto_utils.h
index d2e0f6fcdd..6f4786b87b 100644
--- a/include/grpc++/impl/codegen/proto_utils.h
+++ b/include/grpc++/impl/codegen/proto_utils.h
@@ -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());
diff --git a/include/grpc++/impl/codegen/rpc_service_method.h b/include/grpc++/impl/codegen/rpc_service_method.h
index 88da0965c8..78c54e3771 100644
--- a/include/grpc++/impl/codegen/rpc_service_method.h
+++ b/include/grpc++/impl/codegen/rpc_service_method.h
@@ -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;
};
diff --git a/include/grpc++/impl/codegen/serialization_traits.h b/include/grpc++/impl/codegen/serialization_traits.h
index fa99dbfa9c..54e5d47632 100644
--- a/include/grpc++/impl/codegen/serialization_traits.h
+++ b/include/grpc++/impl/codegen/serialization_traits.h
@@ -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.
diff --git a/include/grpc++/impl/codegen/server_interface.h b/include/grpc++/impl/codegen/server_interface.h
index 1f1b714cbf..4a00d7a3a1 100644
--- a/include/grpc++/impl/codegen/server_interface.h
+++ b/include/grpc++/impl/codegen/server_interface.h
@@ -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;
diff --git a/include/grpc++/impl/codegen/sync_stream.h b/include/grpc++/impl/codegen/sync_stream.h
index aba129811b..e3c5a919b1 100644
--- a/include/grpc++/impl/codegen/sync_stream.h
+++ b/include/grpc++/impl/codegen/sync_stream.h
@@ -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;
}
diff --git a/include/grpc++/impl/codegen/thrift_utils.h b/include/grpc++/impl/codegen/thrift_utils.h
index be558c5789..742d739703 100644
--- a/include/grpc++/impl/codegen/thrift_utils.h
+++ b/include/grpc++/impl/codegen/thrift_utils.h
@@ -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");
}
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index 6876961e21..6e15035125 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -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_;
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index b9c49f0b19..37f1f8cb80 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -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_;
diff --git a/include/grpc++/support/byte_buffer.h b/include/grpc++/support/byte_buffer.h
index 01249a0b88..06f8969b70 100644
--- a/include/grpc++/support/byte_buffer.h
+++ b/include/grpc++/support/byte_buffer.h
@@ -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;
}
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index b2c48406df..a8e8ebe6ea 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -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"
diff --git a/package.xml b/package.xml
index f2ef6e9b08..c2098ad19f 100644
--- a/package.xml
+++ b/package.xml
@@ -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" />
diff --git a/src/core/ext/census/trace_context.c b/src/core/ext/census/trace_context.c
new file mode 100644
index 0000000000..fbb20d3448
--- /dev/null
+++ b/src/core/ext/census/trace_context.c
@@ -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;
+}
diff --git a/src/core/ext/census/trace_context.h b/src/core/ext/census/trace_context.h
new file mode 100644
index 0000000000..ee71fef460
--- /dev/null
+++ b/src/core/ext/census/trace_context.h
@@ -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
diff --git a/src/core/ext/census/tracing.c b/src/core/ext/census/tracing.c
index 3b5d6dab2b..18f8daa176 100644
--- a/src/core/ext/census/tracing.c
+++ b/src/core/ext/census/tracing.c
@@ -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);
diff --git a/src/core/ext/client_config/lb_policy_factory.c b/src/core/ext/client_config/lb_policy_factory.c
index 70e46ef3cf..f86117aa38 100644
--- a/src/core/ext/client_config/lb_policy_factory.c
+++ b/src/core/ext/client_config/lb_policy_factory.c
@@ -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);
}
diff --git a/src/core/ext/client_config/lb_policy_factory.h b/src/core/ext/client_config/lb_policy_factory.h
index 7191ca7d89..b31179cf80 100644
--- a/src/core/ext/client_config/lb_policy_factory.h
+++ b/src/core/ext/client_config/lb_policy_factory.h
@@ -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;
diff --git a/src/core/ext/client_config/resolver_result.c b/src/core/ext/client_config/resolver_result.c
index c6c4166e83..242989a0da 100644
--- a/src/core/ext/client_config/resolver_result.c
+++ b/src/core/ext/client_config/resolver_result.c
@@ -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;
}
diff --git a/src/core/ext/client_config/resolver_result.h b/src/core/ext/client_config/resolver_result.h
index 402f7dbd7e..5a69d81990 100644
--- a/src/core/ext/client_config/resolver_result.h
+++ b/src/core/ext/client_config/resolver_result.h
@@ -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 */
diff --git a/src/core/ext/client_config/subchannel.c b/src/core/ext/client_config/subchannel.c
index e622862fc9..96595a38dd 100644
--- a/src/core/ext/client_config/subchannel.c
+++ b/src/core/ext/client_config/subchannel.c
@@ -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);
}
}
}
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index c6dfba0808..36db8ab00d 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -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);
}
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
index 9513078dce..09df92dd99 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -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);
diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c
index a9c37ac0f1..0feb0740a2 100644
--- a/src/core/ext/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -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);
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index 32e9de69a6..63682db7de 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -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);
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index 425285287c..fbfe5d774b 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -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;
}
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 88ae81a35d..3497d23a78 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -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;
+ }
}
}
}
diff --git a/src/core/lib/channel/channel_args.c b/src/core/lib/channel/channel_args.c
index 79ceeb66b3..3a56b1ff20 100644
--- a/src/core/lib/channel/channel_args.c
+++ b/src/core/lib/channel/channel_args.c
@@ -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;
+}
diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h
index aec61ee7c6..586a296d1f 100644
--- a/src/core/lib/channel/channel_args.h
+++ b/src/core/lib/channel/channel_args.h
@@ -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 */
diff --git a/src/core/lib/channel/message_size_filter.c b/src/core/lib/channel/message_size_filter.c
new file mode 100644
index 0000000000..6613785dea
--- /dev/null
+++ b/src/core/lib/channel/message_size_filter.c
@@ -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"};
diff --git a/src/core/lib/channel/message_size_filter.h b/src/core/lib/channel/message_size_filter.h
new file mode 100644
index 0000000000..a88ff7f81a
--- /dev/null
+++ b/src/core/lib/channel/message_size_filter.h
@@ -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 */
diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.c b/src/core/lib/security/credentials/plugin/plugin_credentials.c
index 824ff081dc..905de3723e 100644
--- a/src/core/lib/security/credentials/plugin/plugin_credentials.c
+++ b/src/core/lib/security/credentials/plugin/plugin_credentials.c
@@ -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);
diff --git a/src/core/lib/surface/call.c b/src/core/lib/surface/call.c
index 97bfd587d2..2438885ae9 100644
--- a/src/core/lib/surface/call.c
+++ b/src/core/lib/surface/call.c
@@ -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) &&
diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c
index aa8c052b41..92d783b78d 100644
--- a/src/core/lib/surface/channel.c
+++ b/src/core/lib/surface/channel.c
@@ -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;
-}
diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h
index 4c62974346..23cc8656ca 100644
--- a/src/core/lib/surface/channel.h
+++ b/src/core/lib/surface/channel.h
@@ -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);
diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c
index ac111253ef..2135507b7a 100644
--- a/src/core/lib/surface/init.c
+++ b/src/core/lib/surface/init.c
@@ -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"
@@ -99,6 +100,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);
grpc_channel_init_register_stage(
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index 1a014da3b8..2980b16c56 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -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
diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc
index af04fd4ca6..a693ce9b8e 100644
--- a/src/cpp/server/server_cc.cc
+++ b/src/cpp/server/server_cc.cc
@@ -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);
}
diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
index c35aaf680f..09790120d1 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
@@ -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);
diff --git a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
index 98e27a17a1..616bc06d76 100644
--- a/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
+++ b/src/csharp/Grpc.Core.Tests/Internal/AsyncCallTest.cs
@@ -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);
}
@@ -416,6 +469,49 @@ namespace Grpc.Core.Internal.Tests
}
[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()
{
asyncCall.StartDuplexStreamingCall();
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index f549c52876..9abaf1120f 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -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));
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
index eb9c3ea62d..9f9d260e7e 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
@@ -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
{
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
index 56c23ba3ef..50fdfa9006 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
@@ -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);
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index 9cd9593d17..1159aac7a7 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -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;
}
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index f04a7e6441..44f22c9e85 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -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];
}];
diff --git a/src/objective-c/tests/run_tests.sh b/src/objective-c/tests/run_tests.sh
index a265149f48..81c2885320 100755
--- a/src/objective-c/tests/run_tests.sh
+++ b/src/objective-c/tests/run_tests.sh
@@ -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
diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py
index faf3ab5f0d..b9b662c032 100644
--- a/src/python/grpcio/grpc/__init__.py
+++ b/src/python/grpcio/grpc/__init__.py
@@ -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__ #################################
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index 3117dd1cb3..53a26727ab 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -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)
diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py
index 4d7d521419..cc0984c8c6 100644
--- a/src/python/grpcio/grpc/_common.py
+++ b/src/python/grpcio/grpc/_common.py
@@ -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))
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index 3df937eb14..73d1ff7b97 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -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:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
index 42fced6545..dae28e15f2 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi
@@ -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
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
index 834a44123d..f444e33cf0 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/records.pyx.pxi
@@ -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
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
index ca2b831114..18db38b686 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
@@ -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:
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index 94a13bfb2f..5f846ce773 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -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)
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 15a8a10fca..288f02042e 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -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',
diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json
index dcaef0db1f..2071a33e13 100644
--- a/src/python/grpcio_tests/tests/tests.json
+++ b/src/python/grpcio_tests/tests/tests.json
@@ -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",
diff --git a/src/python/grpcio_tests/tests/unit/_channel_args_test.py b/src/python/grpcio_tests/tests/unit/_channel_args_test.py
new file mode 100644
index 0000000000..6a636d7993
--- /dev/null
+++ b/src/python/grpcio_tests/tests/unit/_channel_args_test.py
@@ -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)
diff --git a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
index 9cae96a00d..1324ad37b6 100644
--- a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
+++ b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
@@ -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.
diff --git a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
index 24f5b45b18..60d478bcd9 100644
--- a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
+++ b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
@@ -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))
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
index cf212c5653..20115fb22c 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
@@ -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()
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
index 152d8edde3..2ae5285232 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
@@ -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)
diff --git a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
index 142387d810..8dedebfabe 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
@@ -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
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index e6d30a174b..3b2b88eb77 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -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();
diff --git a/test/core/census/data/context_empty.pb b/test/core/census/data/context_empty.pb
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/core/census/data/context_empty.pb
diff --git a/test/core/census/data/context_empty.txt b/test/core/census/data/context_empty.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/core/census/data/context_empty.txt
diff --git a/test/core/census/data/context_full.pb b/test/core/census/data/context_full.pb
new file mode 100644
index 0000000000..80ebcf280b
--- /dev/null
+++ b/test/core/census/data/context_full.pb
Binary files differ
diff --git a/test/core/census/data/context_full.txt b/test/core/census/data/context_full.txt
new file mode 100644
index 0000000000..7901a10c33
--- /dev/null
+++ b/test/core/census/data/context_full.txt
@@ -0,0 +1,3 @@
+trace_id { hi : 5; lo : 1 }
+span_id : 7
+is_sampled : true
diff --git a/test/core/census/data/context_no_sample.pb b/test/core/census/data/context_no_sample.pb
new file mode 100644
index 0000000000..ab7ad7d109
--- /dev/null
+++ b/test/core/census/data/context_no_sample.pb
Binary files differ
diff --git a/test/core/census/data/context_no_sample.txt b/test/core/census/data/context_no_sample.txt
new file mode 100644
index 0000000000..150298002f
--- /dev/null
+++ b/test/core/census/data/context_no_sample.txt
@@ -0,0 +1,2 @@
+trace_id { hi : 5; lo : 1 }
+span_id : 7
diff --git a/test/core/census/data/context_span_only.pb b/test/core/census/data/context_span_only.pb
new file mode 100644
index 0000000000..2a9527a75a
--- /dev/null
+++ b/test/core/census/data/context_span_only.pb
Binary files differ
diff --git a/test/core/census/data/context_span_only.txt b/test/core/census/data/context_span_only.txt
new file mode 100644
index 0000000000..d90de2e614
--- /dev/null
+++ b/test/core/census/data/context_span_only.txt
@@ -0,0 +1,2 @@
+span_id : 7
+is_sampled : true
diff --git a/test/core/census/data/context_trace_only.pb b/test/core/census/data/context_trace_only.pb
new file mode 100644
index 0000000000..7fdf6f61a3
--- /dev/null
+++ b/test/core/census/data/context_trace_only.pb
Binary files differ
diff --git a/test/core/census/data/context_trace_only.txt b/test/core/census/data/context_trace_only.txt
new file mode 100644
index 0000000000..9b68a6aa92
--- /dev/null
+++ b/test/core/census/data/context_trace_only.txt
@@ -0,0 +1,2 @@
+trace_id { hi : 5; lo : 1 }
+is_sampled : true
diff --git a/test/core/census/trace_context_test.c b/test/core/census/trace_context_test.c
new file mode 100644
index 0000000000..ee409e8d1a
--- /dev/null
+++ b/test/core/census/trace_context_test.c
@@ -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;
+}
diff --git a/test/core/end2end/tests/max_message_length.c b/test/core/end2end/tests/max_message_length.c
index 43f71f51d1..cdca3e6748 100644
--- a/test/core/end2end/tests/max_message_length.c
+++ b/test/core/end2end/tests/max_message_length.c
@@ -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) {}
diff --git a/test/core/surface/invalid_channel_args_test.c b/test/core/surface/invalid_channel_args_test.c
index 1b1b8b8f92..0640879866 100644
--- a/test/core/surface/invalid_channel_args_test.c
+++ b/test/core/surface/invalid_channel_args_test.c
@@ -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();
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 66614922f1..b1d3ce92f6 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -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");
diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc
index e5878bb248..c05eb5d146 100644
--- a/test/cpp/interop/interop_server.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -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) {
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 659a79ea07..b34989937b 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -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 \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 5f4ef6d615..2dd8276a9d 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -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 \
diff --git a/tools/run_tests/run_build_statistics.py b/tools/run_tests/run_build_statistics.py
index 89aad2a399..9c17cd1db9 100755
--- a/tools/run_tests/run_build_statistics.py
+++ b/tools/run_tests/run_build_statistics.py
@@ -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\"',
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 3327c3a963..63781e40f2 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -165,6 +165,22 @@
],
"headers": [],
"language": "c",
+ "name": "census_trace_context_test",
+ "src": [
+ "test/core/census/trace_context_test.c"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "language": "c",
"name": "channel_create_test",
"src": [
"test/core/surface/channel_create_test.c"
@@ -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",
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index 709e52d0b3..bbf02f3340 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -203,6 +203,27 @@
"flaky": false,
"gtest": false,
"language": "c",
+ "name": "census_trace_context_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ]
+ },
+ {
+ "args": [],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "flaky": false,
+ "gtest": false,
+ "language": "c",
"name": "channel_create_test",
"platforms": [
"linux",
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 04f487689c..c46e86d78b 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -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
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
index e723f12429..0b1784f1f6 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
@@ -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">
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
index 2473983939..31930fc62f 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
@@ -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>
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
index 857adefa90..6ccb7a7902 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -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">
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index 0467d3b8c4..54acbe2e47 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -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>
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 94dc8fa9f4..83896360aa 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -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">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 771b52222f..521c9c6fd1 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -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>
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
index f4ceb0fb1e..d862c37b50 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj
@@ -195,6 +195,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" />
@@ -318,6 +319,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">
diff --git a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
index 80627f56c4..350cced68f 100644
--- a/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_test_util/grpc_test_util.vcxproj.filters
@@ -76,6 +76,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>
@@ -461,6 +464,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>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index f1a5e894cd..5ed9f8a908 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -294,6 +294,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" />
@@ -420,6 +421,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">
@@ -442,6 +444,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">
@@ -740,6 +744,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_unsecure_plugin_registry.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 923fa11beb..059fd67138 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -31,6 +31,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>
@@ -478,6 +481,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>
@@ -590,6 +596,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>
@@ -968,6 +977,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>
diff --git a/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj b/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj
new file mode 100644
index 0000000000..f0c76e7f04
--- /dev/null
+++ b/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{14511310-FAE4-C287-31DC-D6F456D10AF3}</ProjectGuid>
+ <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+ <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+ <PlatformToolset>v100</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+ <PlatformToolset>v140</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+ <TargetName>census_trace_context_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+ <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+ <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'">
+ <TargetName>census_trace_context_test</TargetName>
+ <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+ <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+ <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+ <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <SDLCheck>true</SDLCheck>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+ <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\test\core\census\trace_context_test.c">
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+ <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+ <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+ <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+ <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+ </ImportGroup>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+ <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+ </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj.filters b/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj.filters
new file mode 100644
index 0000000000..1aafe06ff0
--- /dev/null
+++ b/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\test\core\census\trace_context_test.c">
+ <Filter>test\core\census</Filter>
+ </ClCompile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Filter Include="test">
+ <UniqueIdentifier>{ceb3b75d-b5bc-0966-6724-06fb51237d08}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core">
+ <UniqueIdentifier>{8d294ce5-d65c-2fef-28ab-43b4d23722c3}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\core\census">
+ <UniqueIdentifier>{3981af30-20c0-647e-755f-fa184674d50a}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
+