aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD4
-rw-r--r--CMakeLists.txt2
-rw-r--r--Makefile112
-rw-r--r--build.yaml27
-rw-r--r--doc/health-checking.md2
-rw-r--r--examples/php/route_guide/README.md2
-rw-r--r--include/grpc/grpc.h8
-rw-r--r--src/core/ext/lb_policy/grpclb/grpclb.c3
-rw-r--r--src/core/ext/transport/chttp2/transport/chttp2_transport.c16
-rw-r--r--src/core/lib/channel/channel_stack.h8
-rw-r--r--src/core/lib/channel/channel_stack_builder.h8
-rw-r--r--src/core/lib/channel/context.h11
-rw-r--r--src/core/lib/iomgr/tcp_server_posix.c25
-rw-r--r--src/core/lib/security/context/security_context.h8
-rw-r--r--src/core/lib/surface/channel.h8
-rw-r--r--src/core/lib/surface/channel_init.h8
-rw-r--r--src/core/lib/surface/server.c9
-rw-r--r--src/core/lib/transport/byte_stream.h6
-rw-r--r--src/core/lib/transport/metadata.h8
-rw-r--r--src/core/lib/transport/metadata_batch.c3
-rw-r--r--src/core/lib/transport/metadata_batch.h12
-rw-r--r--src/core/lib/transport/transport.h10
-rw-r--r--src/cpp/common/channel_filter.cc112
-rw-r--r--src/cpp/common/channel_filter.h386
-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.py6
-rw-r--r--src/python/grpcio_tests/tests/unit/_thread_pool.py48
-rw-r--r--test/cpp/end2end/filter_end2end_test.cc353
-rw-r--r--test/cpp/interop/interop_server.cc23
-rw-r--r--test/cpp/interop/interop_server_bootstrap.cc54
-rw-r--r--test/cpp/interop/server_helper.h6
-rwxr-xr-xtools/dockerfile/interoptest/grpc_interop_go/build_interop.sh1
-rw-r--r--tools/doxygen/Doxyfile.c++.internal2
-rwxr-xr-xtools/run_tests/run_tests.py2
-rw-r--r--tools/run_tests/sources_and_headers.json39
-rw-r--r--tools/run_tests/tests.json21
-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/interop_server_lib/interop_server_lib.vcxproj212
-rw-r--r--vsprojects/vcxproj/interop_server_lib/interop_server_lib.vcxproj.filters42
-rw-r--r--vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj51
-rw-r--r--vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters23
-rw-r--r--vsprojects/vcxproj/test/filter_end2end_test/filter_end2end_test.vcxproj207
-rw-r--r--vsprojects/vcxproj/test/filter_end2end_test/filter_end2end_test.vcxproj.filters21
46 files changed, 1800 insertions, 137 deletions
diff --git a/BUILD b/BUILD
index f4ebeba310..b7044c5e68 100644
--- a/BUILD
+++ b/BUILD
@@ -1251,6 +1251,7 @@ cc_library(
"src/cpp/common/secure_auth_context.h",
"src/cpp/server/secure_server_credentials.h",
"src/cpp/client/create_channel_internal.h",
+ "src/cpp/common/channel_filter.h",
"src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h",
"src/cpp/client/secure_credentials.cc",
@@ -1268,6 +1269,7 @@ cc_library(
"src/cpp/client/generic_stub.cc",
"src/cpp/client/insecure_credentials.cc",
"src/cpp/common/channel_arguments.cc",
+ "src/cpp/common/channel_filter.cc",
"src/cpp/common/completion_queue.cc",
"src/cpp/common/core_codegen.cc",
"src/cpp/common/rpc_method.cc",
@@ -1482,6 +1484,7 @@ cc_library(
name = "grpc++_unsecure",
srcs = [
"src/cpp/client/create_channel_internal.h",
+ "src/cpp/common/channel_filter.h",
"src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h",
"src/cpp/common/insecure_create_auth_context.cc",
@@ -1494,6 +1497,7 @@ cc_library(
"src/cpp/client/generic_stub.cc",
"src/cpp/client/insecure_credentials.cc",
"src/cpp/common/channel_arguments.cc",
+ "src/cpp/common/channel_filter.cc",
"src/cpp/common/completion_queue.cc",
"src/cpp/common/core_codegen.cc",
"src/cpp/common/rpc_method.cc",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c9d28e6553..15e5ec9be0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1000,6 +1000,7 @@ add_library(grpc++
src/cpp/client/generic_stub.cc
src/cpp/client/insecure_credentials.cc
src/cpp/common/channel_arguments.cc
+ src/cpp/common/channel_filter.cc
src/cpp/common/completion_queue.cc
src/cpp/common/core_codegen.cc
src/cpp/common/rpc_method.cc
@@ -1255,6 +1256,7 @@ add_library(grpc++_unsecure
src/cpp/client/generic_stub.cc
src/cpp/client/insecure_credentials.cc
src/cpp/common/channel_arguments.cc
+ src/cpp/common/channel_filter.cc
src/cpp/common/completion_queue.cc
src/cpp/common/core_codegen.cc
src/cpp/common/rpc_method.cc
diff --git a/Makefile b/Makefile
index 98dabb3f3d..7cef08ce03 100644
--- a/Makefile
+++ b/Makefile
@@ -1039,6 +1039,7 @@ cxx_slice_test: $(BINDIR)/$(CONFIG)/cxx_slice_test
cxx_string_ref_test: $(BINDIR)/$(CONFIG)/cxx_string_ref_test
cxx_time_test: $(BINDIR)/$(CONFIG)/cxx_time_test
end2end_test: $(BINDIR)/$(CONFIG)/end2end_test
+filter_end2end_test: $(BINDIR)/$(CONFIG)/filter_end2end_test
generic_end2end_test: $(BINDIR)/$(CONFIG)/generic_end2end_test
golden_file_test: $(BINDIR)/$(CONFIG)/golden_file_test
grpc_cli: $(BINDIR)/$(CONFIG)/grpc_cli
@@ -1218,9 +1219,9 @@ pc_cxx: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++.pc
pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
ifeq ($(EMBED_OPENSSL),true)
-privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_reflection_codegen.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a
+privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_reflection_codegen.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a
else
-privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_reflection_codegen.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a
+privatelibs_cxx: $(LIBDIR)/$(CONFIG)/libgrpc++_reflection_codegen.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a
endif
@@ -1402,6 +1403,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/cxx_string_ref_test \
$(BINDIR)/$(CONFIG)/cxx_time_test \
$(BINDIR)/$(CONFIG)/end2end_test \
+ $(BINDIR)/$(CONFIG)/filter_end2end_test \
$(BINDIR)/$(CONFIG)/generic_end2end_test \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
@@ -1487,6 +1489,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/cxx_string_ref_test \
$(BINDIR)/$(CONFIG)/cxx_time_test \
$(BINDIR)/$(CONFIG)/end2end_test \
+ $(BINDIR)/$(CONFIG)/filter_end2end_test \
$(BINDIR)/$(CONFIG)/generic_end2end_test \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
@@ -1775,6 +1778,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/cxx_time_test || ( echo test cxx_time_test failed ; exit 1 )
$(E) "[RUN] Testing end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 )
+ $(E) "[RUN] Testing filter_end2end_test"
+ $(Q) $(BINDIR)/$(CONFIG)/filter_end2end_test || ( echo test filter_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing generic_end2end_test"
$(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing golden_file_test"
@@ -3581,6 +3586,7 @@ LIBGRPC++_SRC = \
src/cpp/client/generic_stub.cc \
src/cpp/client/insecure_credentials.cc \
src/cpp/common/channel_arguments.cc \
+ src/cpp/common/channel_filter.cc \
src/cpp/common/completion_queue.cc \
src/cpp/common/core_codegen.cc \
src/cpp/common/rpc_method.cc \
@@ -4117,6 +4123,7 @@ LIBGRPC++_UNSECURE_SRC = \
src/cpp/client/generic_stub.cc \
src/cpp/client/insecure_credentials.cc \
src/cpp/common/channel_arguments.cc \
+ src/cpp/common/channel_filter.cc \
src/cpp/common/completion_queue.cc \
src/cpp/common/core_codegen.cc \
src/cpp/common/rpc_method.cc \
@@ -4533,7 +4540,7 @@ endif
endif
-LIBINTEROP_SERVER_MAIN_SRC = \
+LIBINTEROP_SERVER_LIB_SRC = \
$(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
$(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc \
@@ -4541,6 +4548,56 @@ LIBINTEROP_SERVER_MAIN_SRC = \
PUBLIC_HEADERS_CXX += \
+LIBINTEROP_SERVER_LIB_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_SERVER_LIB_SRC))))
+
+
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure libraries if you don't have OpenSSL.
+
+$(LIBDIR)/$(CONFIG)/libinterop_server_lib.a: openssl_dep_error
+
+
+else
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
+
+$(LIBDIR)/$(CONFIG)/libinterop_server_lib.a: protobuf_dep_error
+
+
+else
+
+$(LIBDIR)/$(CONFIG)/libinterop_server_lib.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(PROTOBUF_DEP) $(LIBINTEROP_SERVER_LIB_OBJS)
+ $(E) "[AR] Creating $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) rm -f $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a
+ $(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBINTEROP_SERVER_LIB_OBJS)
+ifeq ($(SYSTEM),Darwin)
+ $(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a
+endif
+
+
+
+
+endif
+
+endif
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(LIBINTEROP_SERVER_LIB_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_server.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
+
+
+LIBINTEROP_SERVER_MAIN_SRC = \
+ test/cpp/interop/interop_server_bootstrap.cc \
+
+PUBLIC_HEADERS_CXX += \
+
LIBINTEROP_SERVER_MAIN_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBINTEROP_SERVER_MAIN_SRC))))
@@ -4583,7 +4640,6 @@ ifneq ($(NO_DEPS),true)
-include $(LIBINTEROP_SERVER_MAIN_OBJS:.o=.dep)
endif
endif
-$(OBJDIR)/$(CONFIG)/test/cpp/interop/interop_server.o: $(GENDIR)/src/proto/grpc/testing/empty.pb.cc $(GENDIR)/src/proto/grpc/testing/empty.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/test.pb.cc $(GENDIR)/src/proto/grpc/testing/test.grpc.pb.cc
LIBQPS_SRC = \
@@ -11119,6 +11175,49 @@ endif
endif
+FILTER_END2END_TEST_SRC = \
+ test/cpp/end2end/filter_end2end_test.cc \
+
+FILTER_END2END_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FILTER_END2END_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/filter_end2end_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/filter_end2end_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/filter_end2end_test: $(PROTOBUF_DEP) $(FILTER_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LDXX) $(LDFLAGS) $(FILTER_END2END_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/filter_end2end_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/end2end/filter_end2end_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_filter_end2end_test: $(FILTER_END2END_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(FILTER_END2END_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
GENERIC_END2END_TEST_SRC = \
test/cpp/end2end/generic_end2end_test.cc \
@@ -11625,10 +11724,10 @@ $(BINDIR)/$(CONFIG)/interop_server: protobuf_dep_error
else
-$(BINDIR)/$(CONFIG)/interop_server: $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
+$(BINDIR)/$(CONFIG)/interop_server: $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
- $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/interop_server
+ $(Q) $(LDXX) $(LDFLAGS) $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/interop_server
endif
@@ -15186,6 +15285,7 @@ test/cpp/interop/client.cc: $(OPENSSL_DEP)
test/cpp/interop/client_helper.cc: $(OPENSSL_DEP)
test/cpp/interop/interop_client.cc: $(OPENSSL_DEP)
test/cpp/interop/interop_server.cc: $(OPENSSL_DEP)
+test/cpp/interop/interop_server_bootstrap.cc: $(OPENSSL_DEP)
test/cpp/interop/server_helper.cc: $(OPENSSL_DEP)
test/cpp/qps/client_async.cc: $(OPENSSL_DEP)
test/cpp/qps/client_sync.cc: $(OPENSSL_DEP)
diff --git a/build.yaml b/build.yaml
index ce6783ee87..6ca2e9ebac 100644
--- a/build.yaml
+++ b/build.yaml
@@ -692,6 +692,7 @@ filegroups:
- include/grpc++/support/time.h
headers:
- src/cpp/client/create_channel_internal.h
+ - src/cpp/common/channel_filter.h
- src/cpp/server/dynamic_thread_pool.h
- src/cpp/server/thread_pool_interface.h
src:
@@ -704,6 +705,7 @@ filegroups:
- src/cpp/client/generic_stub.cc
- src/cpp/client/insecure_credentials.cc
- src/cpp/common/channel_arguments.cc
+ - src/cpp/common/channel_filter.cc
- src/cpp/common/completion_queue.cc
- src/cpp/common/core_codegen.cc
- src/cpp/common/rpc_method.cc
@@ -823,7 +825,6 @@ libs:
- grpc_lb_policy_grpclb
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin
- - grpc_lb_policy_grpclb
- grpc_resolver_dns_native
- grpc_resolver_sockaddr
- grpc_load_reporting
@@ -922,7 +923,6 @@ libs:
- grpc_lb_policy_grpclb
- grpc_lb_policy_pick_first
- grpc_lb_policy_round_robin
- - grpc_lb_policy_grpclb
- census
generate_plugin_registry: true
secure: false
@@ -1140,7 +1140,7 @@ libs:
- grpc++
- grpc
- gpr
-- name: interop_server_main
+- name: interop_server_lib
build: private
language: c++
src:
@@ -1157,6 +1157,13 @@ libs:
- gpr_test_util
- gpr
- grpc++_test_config
+- name: interop_server_main
+ build: private
+ language: c++
+ src:
+ - test/cpp/interop/interop_server_bootstrap.cc
+ deps:
+ - interop_server_lib
- name: qps
build: private
language: c++
@@ -2659,6 +2666,19 @@ targets:
- grpc
- gpr_test_util
- gpr
+- name: filter_end2end_test
+ gtest: true
+ build: test
+ language: c++
+ src:
+ - test/cpp/end2end/filter_end2end_test.cc
+ deps:
+ - grpc++_test_util
+ - grpc_test_util
+ - grpc++
+ - grpc
+ - gpr_test_util
+ - gpr
- name: generic_end2end_test
gtest: true
build: test
@@ -2824,6 +2844,7 @@ targets:
deps:
- interop_server_main
- interop_server_helper
+ - interop_server_lib
- grpc++_test_util
- grpc_test_util
- grpc++
diff --git a/doc/health-checking.md b/doc/health-checking.md
index 92512e942b..7be8107b60 100644
--- a/doc/health-checking.md
+++ b/doc/health-checking.md
@@ -58,7 +58,7 @@ a response must be sent back with an `OK` status and the status field should be
set to `SERVING` or `NOT_SERVING` accordingly. If the service name is not
registered, the server returns a `NOT_FOUND` GRPC status.
-The server should use an empty string as the key for server’s
+The server should use an empty string as the key for server's
overall health status, so that a client not interested in a specific service can
query the server's status with an empty request. The server can just do exact
matching of the service name without support of any kind of wildcard matching.
diff --git a/examples/php/route_guide/README.md b/examples/php/route_guide/README.md
index 4e74a79f13..26f1704f12 100644
--- a/examples/php/route_guide/README.md
+++ b/examples/php/route_guide/README.md
@@ -1,6 +1,6 @@
#gRPC Basics: PHP sample code
The files in this folder are the samples used in [gRPC Basics: PHP][],
-a detailed tutorial for using gRPC in Ruby.
+a detailed tutorial for using gRPC in PHP.
[gRPC Basics: PHP]:http://www.grpc.io/docs/tutorials/basic/php.html
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 6f7a67b715..4ca018edb3 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -170,8 +170,9 @@ GRPCAPI void grpc_channel_watch_connectivity_state(
completions are sent to 'completion_queue'. 'method' and 'host' need only
live through the invocation of this function.
If parent_call is non-NULL, it must be a server-side call. It will be used
- to propagate properties from the server call to this new client call.
- */
+ to propagate properties from the server call to this new client call,
+ depending on the value of \a propagation_mask (see propagation_bits.h for
+ possible values). */
GRPCAPI grpc_call *grpc_channel_create_call(
grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
grpc_completion_queue *completion_queue, const char *method,
@@ -187,7 +188,8 @@ GRPCAPI void *grpc_channel_register_call(grpc_channel *channel,
const char *method, const char *host,
void *reserved);
-/** Create a call given a handle returned from grpc_channel_register_call */
+/** Create a call given a handle returned from grpc_channel_register_call.
+ \sa grpc_channel_create_call. */
GRPCAPI grpc_call *grpc_channel_create_registered_call(
grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
grpc_completion_queue *completion_queue, void *registered_call_handle,
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index dec25efe61..af913d8a9d 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -767,6 +767,9 @@ static lb_client_data *lb_client_data_create(glb_lb_policy *glb_policy) {
lb_client->deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(3, GPR_TIMESPAN));
+ /* Note the following LB call progresses every time there's activity in \a
+ * glb_policy->base.interested_parties, which is comprised of the polling
+ * entities passed to glb_pick(). */
lb_client->lb_call = grpc_channel_create_pollset_set_call(
glb_policy->lb_channel, NULL, GRPC_PROPAGATE_DEFAULTS,
glb_policy->base.interested_parties, "/BalanceLoad",
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index f2f5465201..0e8dfb7d96 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -94,7 +94,8 @@ static void initiate_writing(grpc_exec_ctx *exec_ctx, void *t,
static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t);
static void end_waiting_for_write(grpc_exec_ctx *exec_ctx,
- grpc_chttp2_transport *t, grpc_error *error);
+ grpc_chttp2_transport *t, grpc_error *error,
+ const char *reason);
/** Set a transport level setting, and push it to our peer */
static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@@ -876,7 +877,7 @@ static void start_writing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
set_write_state(t, GRPC_CHTTP2_WRITING_INACTIVE,
"start_writing:nothing_to_write");
}
- end_waiting_for_write(exec_ctx, t, GRPC_ERROR_CREATE("Nothing to write"));
+ end_waiting_for_write(exec_ctx, t, GRPC_ERROR_NONE, "Nothing to write");
if (t->ep && !t->endpoint_reading) {
destroy_endpoint(exec_ctx, t);
}
@@ -925,11 +926,18 @@ static void push_setting(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
}
}
+/* error may be GRPC_ERROR_NONE if there is no error allocated yet.
+ In that case, use "reason" as the text for a new error. */
static void end_waiting_for_write(grpc_exec_ctx *exec_ctx,
- grpc_chttp2_transport *t, grpc_error *error) {
+ grpc_chttp2_transport *t, grpc_error *error,
+ const char *reason) {
grpc_chttp2_stream_global *stream_global;
while (grpc_chttp2_list_pop_closed_waiting_for_writing(&t->global,
&stream_global)) {
+ if (error == GRPC_ERROR_NONE && reason != NULL) {
+ /* create error object. */
+ error = GRPC_ERROR_CREATE(reason);
+ }
fail_pending_writes(exec_ctx, &t->global, stream_global,
GRPC_ERROR_REF(error));
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "finish_writes");
@@ -951,7 +959,7 @@ static void terminate_writing_with_lock(grpc_exec_ctx *exec_ctx,
grpc_chttp2_cleanup_writing(exec_ctx, &t->global, &t->writing);
- end_waiting_for_write(exec_ctx, t, error);
+ end_waiting_for_write(exec_ctx, t, error, NULL);
switch (t->executor.write_state) {
case GRPC_CHTTP2_WRITING_INACTIVE:
diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h
index ee68701456..6b73cce380 100644
--- a/src/core/lib/channel/channel_stack.h
+++ b/src/core/lib/channel/channel_stack.h
@@ -51,6 +51,10 @@
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/transport/transport.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct grpc_channel_element grpc_channel_element;
typedef struct grpc_call_element grpc_call_element;
@@ -291,4 +295,8 @@ extern int grpc_trace_channel;
#define GRPC_CALL_LOG_OP(sev, elem, op) \
if (grpc_trace_channel) grpc_call_log_op(sev, elem, op)
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_H */
diff --git a/src/core/lib/channel/channel_stack_builder.h b/src/core/lib/channel/channel_stack_builder.h
index 0e6bfd9aa6..4a00f7bfdb 100644
--- a/src/core/lib/channel/channel_stack_builder.h
+++ b/src/core/lib/channel/channel_stack_builder.h
@@ -39,6 +39,10 @@
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/channel/channel_stack.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/// grpc_channel_stack_builder offers a programmatic interface to selected
/// and order channel filters
typedef struct grpc_channel_stack_builder grpc_channel_stack_builder;
@@ -158,4 +162,8 @@ void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder *builder);
extern int grpc_trace_channel_stack_builder;
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_STACK_BUILDER_H */
diff --git a/src/core/lib/channel/context.h b/src/core/lib/channel/context.h
index c50e84279d..071c5f695c 100644
--- a/src/core/lib/channel/context.h
+++ b/src/core/lib/channel/context.h
@@ -34,10 +34,19 @@
#ifndef GRPC_CORE_LIB_CHANNEL_CONTEXT_H
#define GRPC_CORE_LIB_CHANNEL_CONTEXT_H
-/* Call object context pointers */
+/// Call object context pointers.
+
+/// Call context is represented as an array of \a grpc_call_context_elements.
+/// This enum represents the indexes into the array, where each index
+/// contains a different type of value.
typedef enum {
+ /// Value is either a \a grpc_client_security_context or a
+ /// \a grpc_server_security_context.
GRPC_CONTEXT_SECURITY = 0,
+
+ /// Value is a \a census_context.
GRPC_CONTEXT_TRACING,
+
GRPC_CONTEXT_COUNT
} grpc_context_index;
diff --git a/src/core/lib/iomgr/tcp_server_posix.c b/src/core/lib/iomgr/tcp_server_posix.c
index 38ebd2dbcb..ea8d241154 100644
--- a/src/core/lib/iomgr/tcp_server_posix.c
+++ b/src/core/lib/iomgr/tcp_server_posix.c
@@ -90,10 +90,12 @@ struct grpc_tcp_listener {
grpc_closure read_closure;
grpc_closure destroyed_closure;
struct grpc_tcp_listener *next;
- /* When we add a listener, more than one can be created, mainly because of
- IPv6. A sibling will still be in the normal list, but will be flagged
- as such. Any action, such as ref or unref, will affect all of the
- siblings in the list. */
+ /* sibling is a linked list of all listeners for a given port. add_port and
+ clone_port place all new listeners in the same sibling list. A member of
+ the 'sibling' list is also a member of the 'next' list. The head of each
+ sibling list has is_sibling==0, and subsequent members of sibling lists
+ have is_sibling==1. is_sibling allows separate sibling lists to be
+ identified while iterating through 'next'. */
struct grpc_tcp_listener *sibling;
int is_sibling;
};
@@ -306,7 +308,7 @@ static grpc_error *prepare_socket(int fd, const struct sockaddr *addr,
GPR_ASSERT(fd >= 0);
- if (so_reuseport) {
+ if (so_reuseport && !grpc_is_unix_socket(addr)) {
err = grpc_set_socket_reuse_port(fd, 1);
if (err != GRPC_ERROR_NONE) goto error;
}
@@ -480,6 +482,9 @@ static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
return err;
}
+/* Insert count new listeners after listener. Every new listener will have the
+ same listen address as listener (SO_REUSEPORT must be enabled). Every new
+ listener is a sibling of listener. */
static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
grpc_tcp_listener *sp = NULL;
char *addr_str;
@@ -506,6 +511,11 @@ static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
sp = gpr_malloc(sizeof(grpc_tcp_listener));
sp->next = listener->next;
listener->next = sp;
+ /* sp (the new listener) is a sibling of 'listener' (the original
+ listener). */
+ sp->is_sibling = 1;
+ sp->sibling = listener->sibling;
+ listener->sibling = sp;
sp->server = listener->server;
sp->fd = fd;
sp->emfd = grpc_fd_create(fd, name);
@@ -514,8 +524,6 @@ static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
sp->port = port;
sp->port_index = listener->port_index;
sp->fd_index = listener->fd_index + count - i;
- sp->is_sibling = 1;
- sp->sibling = listener->is_sibling ? listener->sibling : listener;
GPR_ASSERT(sp->emfd);
while (listener->server->tail->next != NULL) {
listener->server->tail = listener->server->tail->next;
@@ -685,7 +693,8 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
s->pollset_count = pollset_count;
sp = s->head;
while (sp != NULL) {
- if (s->so_reuseport && pollset_count > 1) {
+ if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr.sockaddr) &&
+ pollset_count > 1) {
GPR_ASSERT(GRPC_LOG_IF_ERROR(
"clone_port", clone_port(sp, (unsigned)(pollset_count - 1))));
for (i = 0; i < pollset_count; i++) {
diff --git a/src/core/lib/security/context/security_context.h b/src/core/lib/security/context/security_context.h
index ef0c06b1fb..4e7666dfe3 100644
--- a/src/core/lib/security/context/security_context.h
+++ b/src/core/lib/security/context/security_context.h
@@ -37,6 +37,10 @@
#include "src/core/lib/iomgr/pollset.h"
#include "src/core/lib/security/credentials/credentials.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* --- grpc_auth_context ---
High level authentication context object. Can optionally be chained. */
@@ -111,4 +115,8 @@ grpc_auth_context *grpc_auth_context_from_arg(const grpc_arg *arg);
grpc_auth_context *grpc_find_auth_context_in_args(
const grpc_channel_args *args);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_SECURITY_CONTEXT_SECURITY_CONTEXT_H */
diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h
index 7eff7b8883..4c62974346 100644
--- a/src/core/lib/surface/channel.h
+++ b/src/core/lib/surface/channel.h
@@ -42,6 +42,14 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target,
grpc_channel_stack_type channel_stack_type,
grpc_transport *optional_transport);
+/** Create a call given a grpc_channel, in order to call \a method.
+ Progress is tied to activity on \a pollset_set. The returned call object is
+ meant to be used with \a grpc_call_start_batch_and_execute, which relies on
+ callbacks to signal completions. \a method and \a host need
+ only live through the invocation of this function. If \a parent_call is
+ non-NULL, it must be a server-side call. It will be used to propagate
+ properties from the server call to this new client call, depending on the
+ value of \a propagation_mask (see propagation_bits.h for possible values) */
grpc_call *grpc_channel_create_pollset_set_call(
grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask,
grpc_pollset_set *pollset_set, const char *method, const char *host,
diff --git a/src/core/lib/surface/channel_init.h b/src/core/lib/surface/channel_init.h
index 3a18a61ddb..b53f2aefb9 100644
--- a/src/core/lib/surface/channel_init.h
+++ b/src/core/lib/surface/channel_init.h
@@ -40,6 +40,10 @@
#define GRPC_CHANNEL_INIT_BUILTIN_PRIORITY 10000
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/// This module provides a way for plugins (and the grpc core library itself)
/// to register mutators for channel stacks.
/// It also provides a universal entry path to run those mutators to build
@@ -84,4 +88,8 @@ bool grpc_channel_init_create_stack(grpc_exec_ctx *exec_ctx,
grpc_channel_stack_builder *builder,
grpc_channel_stack_type type);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_SURFACE_CHANNEL_INIT_H */
diff --git a/src/core/lib/surface/server.c b/src/core/lib/surface/server.c
index 1d61ec3bbb..64afcecc07 100644
--- a/src/core/lib/surface/server.c
+++ b/src/core/lib/surface/server.c
@@ -272,7 +272,7 @@ static void shutdown_cleanup(grpc_exec_ctx *exec_ctx, void *arg,
}
static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
- int send_goaway, grpc_error *send_disconnect) {
+ bool send_goaway, grpc_error *send_disconnect) {
grpc_transport_op op;
struct shutdown_cleanup_args *sc;
grpc_channel_element *elem;
@@ -293,7 +293,7 @@ static void send_shutdown(grpc_exec_ctx *exec_ctx, grpc_channel *channel,
static void channel_broadcaster_shutdown(grpc_exec_ctx *exec_ctx,
channel_broadcaster *cb,
- int send_goaway,
+ bool send_goaway,
grpc_error *force_disconnect) {
size_t i;
@@ -1252,7 +1252,8 @@ void grpc_server_shutdown_and_notify(grpc_server *server,
l->destroy(&exec_ctx, server, l->arg, &l->destroy_done);
}
- channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 1, 0);
+ channel_broadcaster_shutdown(&exec_ctx, &broadcaster, true /* send_goaway */,
+ GRPC_ERROR_NONE);
done:
grpc_exec_ctx_finish(&exec_ctx);
@@ -1268,7 +1269,7 @@ void grpc_server_cancel_all_calls(grpc_server *server) {
channel_broadcaster_init(server, &broadcaster);
gpr_mu_unlock(&server->mu_global);
- channel_broadcaster_shutdown(&exec_ctx, &broadcaster, 0,
+ channel_broadcaster_shutdown(&exec_ctx, &broadcaster, false /* send_goaway */,
GRPC_ERROR_CREATE("Cancelling all calls"));
grpc_exec_ctx_finish(&exec_ctx);
}
diff --git a/src/core/lib/transport/byte_stream.h b/src/core/lib/transport/byte_stream.h
index 95519a9eaf..e64dce6283 100644
--- a/src/core/lib/transport/byte_stream.h
+++ b/src/core/lib/transport/byte_stream.h
@@ -59,13 +59,9 @@ struct grpc_byte_stream {
* on_complete will not be called), 0 if the bytes will be available
* asynchronously.
*
- * on entry, *remaining can be set as a hint as to the maximum number
+ * max_size_hint can be set as a hint as to the maximum number
* of bytes that would be acceptable to read.
*
- * fills *buffer, *length, *remaining with the bytes, length of bytes
- * and length of data remaining to be read before either returning 1
- * or calling on_complete.
- *
* once a slice is returned into *slice, it is owned by the caller.
*/
int grpc_byte_stream_next(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index 6d82f4d681..2b0921c8d7 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -37,6 +37,10 @@
#include <grpc/support/slice.h>
#include <grpc/support/useful.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* This file provides a mechanism for tracking metadata through the grpc stack.
It's not intended for consumption outside of the library.
@@ -164,4 +168,8 @@ void grpc_mdctx_global_shutdown(void);
extern gpr_slice (*grpc_chttp2_base64_encode_and_huffman_compress)(
gpr_slice input);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_H */
diff --git a/src/core/lib/transport/metadata_batch.c b/src/core/lib/transport/metadata_batch.c
index e4398abeb7..84b5a74d51 100644
--- a/src/core/lib/transport/metadata_batch.c
+++ b/src/core/lib/transport/metadata_batch.c
@@ -33,6 +33,7 @@
#include "src/core/lib/transport/metadata_batch.h"
+#include <stdbool.h>
#include <string.h>
#include <grpc/support/alloc.h>
@@ -187,7 +188,7 @@ void grpc_metadata_batch_clear(grpc_metadata_batch *batch) {
grpc_metadata_batch_filter(batch, no_metadata_for_you, NULL);
}
-int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) {
+bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch) {
return batch->list.head == NULL &&
gpr_time_cmp(gpr_inf_future(batch->deadline.clock_type),
batch->deadline) == 0;
diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h
index 7af823f7ca..0424b4db98 100644
--- a/src/core/lib/transport/metadata_batch.h
+++ b/src/core/lib/transport/metadata_batch.h
@@ -34,12 +34,18 @@
#ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
#define GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H
+#include <stdbool.h>
+
#include <grpc/grpc.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
#include <grpc/support/time.h>
#include "src/core/lib/transport/metadata.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct grpc_linked_mdelem {
grpc_mdelem *md;
struct grpc_linked_mdelem *next;
@@ -64,7 +70,7 @@ typedef struct grpc_metadata_batch {
void grpc_metadata_batch_init(grpc_metadata_batch *batch);
void grpc_metadata_batch_destroy(grpc_metadata_batch *batch);
void grpc_metadata_batch_clear(grpc_metadata_batch *batch);
-int grpc_metadata_batch_is_empty(grpc_metadata_batch *batch);
+bool grpc_metadata_batch_is_empty(grpc_metadata_batch *batch);
/* Returns the transport size of the batch. */
size_t grpc_metadata_batch_size(grpc_metadata_batch *batch);
@@ -125,4 +131,8 @@ void grpc_metadata_batch_assert_ok(grpc_metadata_batch *comd);
} while (0)
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */
diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h
index e33fc5c761..1705e6e582 100644
--- a/src/core/lib/transport/transport.h
+++ b/src/core/lib/transport/transport.h
@@ -43,6 +43,10 @@
#include "src/core/lib/transport/byte_stream.h"
#include "src/core/lib/transport/metadata_batch.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* forward declarations */
typedef struct grpc_transport grpc_transport;
@@ -158,7 +162,7 @@ typedef struct grpc_transport_op {
/** should we send a goaway?
after a goaway is sent, once there are no more active calls on
the transport, the transport should disconnect */
- int send_goaway;
+ bool send_goaway;
/** what should the goaway contain? */
grpc_status_code goaway_status;
gpr_slice *goaway_message;
@@ -268,4 +272,8 @@ void grpc_transport_destroy(grpc_exec_ctx *exec_ctx, grpc_transport *transport);
char *grpc_transport_get_peer(grpc_exec_ctx *exec_ctx,
grpc_transport *transport);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* GRPC_CORE_LIB_TRANSPORT_TRANSPORT_H */
diff --git a/src/cpp/common/channel_filter.cc b/src/cpp/common/channel_filter.cc
new file mode 100644
index 0000000000..25cd49cb7c
--- /dev/null
+++ b/src/cpp/common/channel_filter.cc
@@ -0,0 +1,112 @@
+/*
+ *
+ * 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 <string.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/cpp/common/channel_filter.h"
+
+namespace grpc {
+
+// MetadataBatch
+
+grpc_linked_mdelem *MetadataBatch::AddMetadata(const string &key,
+ const string &value) {
+ grpc_linked_mdelem *storage = new grpc_linked_mdelem;
+ memset(storage, 0, sizeof(grpc_linked_mdelem));
+ storage->md = grpc_mdelem_from_strings(key.c_str(), value.c_str());
+ grpc_metadata_batch_link_head(batch_, storage);
+ return storage;
+}
+
+// ChannelData
+
+void ChannelData::StartTransportOp(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ TransportOp *op) {
+ grpc_channel_next_op(exec_ctx, elem, op->op());
+}
+
+// CallData
+
+void CallData::StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ TransportStreamOp *op) {
+ grpc_call_next_op(exec_ctx, elem, op->op());
+}
+
+void CallData::SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_polling_entity *pollent) {
+ grpc_call_stack_ignore_set_pollset_or_pollset_set(exec_ctx, elem, pollent);
+}
+
+char *CallData::GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+ return grpc_call_next_get_peer(exec_ctx, elem);
+}
+
+// internal code used by RegisterChannelFilter()
+
+namespace internal {
+
+// Note: Implicitly initialized to nullptr due to static lifetime.
+std::vector<FilterRecord> *channel_filters;
+
+namespace {
+
+bool MaybeAddFilter(grpc_channel_stack_builder *builder, void *arg) {
+ const FilterRecord &filter = *(FilterRecord *)arg;
+ if (filter.include_filter) {
+ const grpc_channel_args *args =
+ grpc_channel_stack_builder_get_channel_arguments(builder);
+ if (!filter.include_filter(*args)) return true;
+ }
+ return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter,
+ nullptr, nullptr);
+}
+
+} // namespace
+
+void ChannelFilterPluginInit() {
+ for (size_t i = 0; i < channel_filters->size(); ++i) {
+ FilterRecord &filter = (*channel_filters)[i];
+ grpc_channel_init_register_stage(filter.stack_type, filter.priority,
+ MaybeAddFilter, (void *)&filter);
+ }
+}
+
+void ChannelFilterPluginShutdown() {}
+
+} // namespace internal
+
+} // namespace grpc
diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h
new file mode 100644
index 0000000000..3fbacd824c
--- /dev/null
+++ b/src/cpp/common/channel_filter.h
@@ -0,0 +1,386 @@
+/*
+ *
+ * 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 GRPCXX_CHANNEL_FILTER_H
+#define GRPCXX_CHANNEL_FILTER_H
+
+#include <grpc++/impl/codegen/config.h>
+#include <grpc/census.h>
+#include <grpc/grpc.h>
+#include <grpc/impl/codegen/alloc.h>
+
+#include <functional>
+#include <vector>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/security/context/security_context.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/transport/metadata_batch.h"
+
+/// An interface to define filters.
+///
+/// To define a filter, implement a subclass of each of \c CallData and
+/// \c ChannelData. Then register the filter using something like this:
+/// \code{.cpp}
+/// RegisterChannelFilter<MyChannelDataSubclass, MyCallDataSubclass>(
+/// "name-of-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
+/// \endcode
+
+namespace grpc {
+
+/// A C++ wrapper for the \c grpc_metadata_batch struct.
+class MetadataBatch {
+ public:
+ /// Borrows a pointer to \a batch, but does NOT take ownership.
+ /// The caller must ensure that \a batch continues to exist for as
+ /// long as the MetadataBatch object does.
+ explicit MetadataBatch(grpc_metadata_batch *batch) : batch_(batch) {}
+
+ grpc_metadata_batch *batch() const { return batch_; }
+
+ /// Adds metadata and returns the newly allocated storage.
+ /// The caller takes ownership of the result, which must exist for the
+ /// lifetime of the gRPC call.
+ grpc_linked_mdelem *AddMetadata(const string &key, const string &value);
+
+ class const_iterator : public std::iterator<std::bidirectional_iterator_tag,
+ const grpc_mdelem> {
+ public:
+ const grpc_mdelem &operator*() const { return *elem_->md; }
+ const grpc_mdelem *operator->() const { return elem_->md; }
+
+ const_iterator &operator++() {
+ elem_ = elem_->next;
+ return *this;
+ }
+ const_iterator operator++(int) {
+ const_iterator tmp(*this);
+ operator++();
+ return tmp;
+ }
+ const_iterator &operator--() {
+ elem_ = elem_->prev;
+ return *this;
+ }
+ const_iterator operator--(int) {
+ const_iterator tmp(*this);
+ operator--();
+ return tmp;
+ }
+
+ bool operator==(const const_iterator &other) const {
+ return elem_ == other.elem_;
+ }
+ bool operator!=(const const_iterator &other) const {
+ return elem_ != other.elem_;
+ }
+
+ private:
+ friend class MetadataBatch;
+ explicit const_iterator(grpc_linked_mdelem *elem) : elem_(elem) {}
+
+ grpc_linked_mdelem *elem_;
+ };
+
+ const_iterator begin() const { return const_iterator(batch_->list.head); }
+ const_iterator end() const { return const_iterator(nullptr); }
+
+ private:
+ grpc_metadata_batch *batch_; // Not owned.
+};
+
+/// A C++ wrapper for the \c grpc_transport_op struct.
+class TransportOp {
+ public:
+ /// Borrows a pointer to \a op, but does NOT take ownership.
+ /// The caller must ensure that \a op continues to exist for as
+ /// long as the TransportOp object does.
+ explicit TransportOp(grpc_transport_op *op) : op_(op) {}
+
+ grpc_transport_op *op() const { return op_; }
+
+ // TODO(roth): Add a C++ wrapper for grpc_error?
+ grpc_error *disconnect_with_error() const {
+ return op_->disconnect_with_error;
+ }
+ bool send_goaway() const { return op_->send_goaway; }
+
+ // TODO(roth): Add methods for additional fields as needed.
+
+ private:
+ grpc_transport_op *op_; // Not owned.
+};
+
+/// A C++ wrapper for the \c grpc_transport_stream_op struct.
+class TransportStreamOp {
+ public:
+ /// Borrows a pointer to \a op, but does NOT take ownership.
+ /// The caller must ensure that \a op continues to exist for as
+ /// long as the TransportStreamOp object does.
+ explicit TransportStreamOp(grpc_transport_stream_op *op)
+ : op_(op),
+ send_initial_metadata_(op->send_initial_metadata),
+ send_trailing_metadata_(op->send_trailing_metadata),
+ recv_initial_metadata_(op->recv_initial_metadata),
+ recv_trailing_metadata_(op->recv_trailing_metadata) {}
+
+ grpc_transport_stream_op *op() const { return op_; }
+
+ grpc_closure *on_complete() const { return op_->on_complete; }
+ void set_on_complete(grpc_closure *closure) { op_->on_complete = closure; }
+
+ MetadataBatch *send_initial_metadata() {
+ return op_->send_initial_metadata == nullptr ? nullptr
+ : &send_initial_metadata_;
+ }
+ MetadataBatch *send_trailing_metadata() {
+ return op_->send_trailing_metadata == nullptr ? nullptr
+ : &send_trailing_metadata_;
+ }
+ MetadataBatch *recv_initial_metadata() {
+ return op_->recv_initial_metadata == nullptr ? nullptr
+ : &recv_initial_metadata_;
+ }
+ MetadataBatch *recv_trailing_metadata() {
+ return op_->recv_trailing_metadata == nullptr ? nullptr
+ : &recv_trailing_metadata_;
+ }
+
+ uint32_t *send_initial_metadata_flags() const {
+ return &op_->send_initial_metadata_flags;
+ }
+
+ grpc_closure *recv_initial_metadata_ready() const {
+ return op_->recv_initial_metadata_ready;
+ }
+ void set_recv_initial_metadata_ready(grpc_closure *closure) {
+ op_->recv_initial_metadata_ready = closure;
+ }
+
+ grpc_byte_stream *send_message() const { return op_->send_message; }
+ void set_send_message(grpc_byte_stream *send_message) {
+ op_->send_message = send_message;
+ }
+
+ /// To be called only on clients and servers, respectively.
+ grpc_client_security_context *client_security_context() const {
+ return (grpc_client_security_context *)op_->context[GRPC_CONTEXT_SECURITY]
+ .value;
+ }
+ grpc_server_security_context *server_security_context() const {
+ return (grpc_server_security_context *)op_->context[GRPC_CONTEXT_SECURITY]
+ .value;
+ }
+
+ census_context *get_census_context() const {
+ return (census_context *)op_->context[GRPC_CONTEXT_TRACING].value;
+ }
+
+ private:
+ grpc_transport_stream_op *op_; // Not owned.
+ MetadataBatch send_initial_metadata_;
+ MetadataBatch send_trailing_metadata_;
+ MetadataBatch recv_initial_metadata_;
+ MetadataBatch recv_trailing_metadata_;
+};
+
+/// Represents channel data.
+class ChannelData {
+ public:
+ virtual ~ChannelData() {
+ if (peer_) gpr_free((void *)peer_);
+ }
+
+ /// Caller does NOT take ownership of result.
+ const char *peer() const { return peer_; }
+
+ // TODO(roth): Find a way to avoid passing elem into these methods.
+ virtual void StartTransportOp(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem, TransportOp *op);
+
+ protected:
+ /// Takes ownership of \a peer.
+ ChannelData(const grpc_channel_args &args, const char *peer) : peer_(peer) {}
+
+ private:
+ const char *peer_;
+};
+
+/// Represents call data.
+class CallData {
+ public:
+ virtual ~CallData() {}
+
+ /// Initializes the call data.
+ virtual grpc_error *Init() { return GRPC_ERROR_NONE; }
+
+ // TODO(roth): Find a way to avoid passing elem into these methods.
+
+ /// Starts a new stream operation.
+ virtual void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ TransportStreamOp *op);
+
+ /// Sets a pollset or pollset set.
+ virtual void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_polling_entity *pollent);
+
+ /// Gets the peer name.
+ virtual char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem);
+
+ protected:
+ explicit CallData(const ChannelData &) {}
+};
+
+namespace internal {
+
+// Defines static members for passing to C core.
+// Members of this class correspond to the members of the C
+// grpc_channel_filter struct.
+template <typename ChannelDataType, typename CallDataType>
+class ChannelFilter GRPC_FINAL {
+ public:
+ static const size_t channel_data_size = sizeof(ChannelDataType);
+
+ static void InitChannelElement(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ grpc_channel_element_args *args) {
+ const char *peer =
+ args->optional_transport
+ ? grpc_transport_get_peer(exec_ctx, args->optional_transport)
+ : nullptr;
+ // Construct the object in the already-allocated memory.
+ new (elem->channel_data) ChannelDataType(*args->channel_args, peer);
+ }
+
+ static void DestroyChannelElement(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem) {
+ reinterpret_cast<ChannelDataType *>(elem->channel_data)->~ChannelDataType();
+ }
+
+ static void StartTransportOp(grpc_exec_ctx *exec_ctx,
+ grpc_channel_element *elem,
+ grpc_transport_op *op) {
+ ChannelDataType *channel_data = (ChannelDataType *)elem->channel_data;
+ TransportOp op_wrapper(op);
+ channel_data->StartTransportOp(exec_ctx, elem, &op_wrapper);
+ }
+
+ static const size_t call_data_size = sizeof(CallDataType);
+
+ static grpc_error *InitCallElement(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_call_element_args *args) {
+ const ChannelDataType &channel_data =
+ *(ChannelDataType *)elem->channel_data;
+ // Construct the object in the already-allocated memory.
+ CallDataType *call_data = new (elem->call_data) CallDataType(channel_data);
+ return call_data->Init();
+ }
+
+ static void DestroyCallElement(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ const grpc_call_final_info *final_info,
+ void *and_free_memory) {
+ reinterpret_cast<CallDataType *>(elem->call_data)->~CallDataType();
+ }
+
+ static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_transport_stream_op *op) {
+ CallDataType *call_data = (CallDataType *)elem->call_data;
+ TransportStreamOp op_wrapper(op);
+ call_data->StartTransportStreamOp(exec_ctx, elem, &op_wrapper);
+ }
+
+ static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
+ grpc_call_element *elem,
+ grpc_polling_entity *pollent) {
+ CallDataType *call_data = (CallDataType *)elem->call_data;
+ call_data->SetPollsetOrPollsetSet(exec_ctx, elem, pollent);
+ }
+
+ static char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
+ CallDataType *call_data = (CallDataType *)elem->call_data;
+ return call_data->GetPeer(exec_ctx, elem);
+ }
+};
+
+struct FilterRecord {
+ grpc_channel_stack_type stack_type;
+ int priority;
+ std::function<bool(const grpc_channel_args &)> include_filter;
+ grpc_channel_filter filter;
+};
+extern std::vector<FilterRecord> *channel_filters;
+
+void ChannelFilterPluginInit();
+void ChannelFilterPluginShutdown();
+
+} // namespace internal
+
+/// Registers a new filter.
+/// Must be called by only one thread at a time.
+/// The \a include_filter argument specifies a function that will be called
+/// to determine at run-time whether or not to add the filter. If the
+/// value is nullptr, the filter will be added unconditionally.
+template <typename ChannelDataType, typename CallDataType>
+void RegisterChannelFilter(
+ const char *name, grpc_channel_stack_type stack_type, int priority,
+ std::function<bool(const grpc_channel_args &)> include_filter) {
+ // If we haven't been called before, initialize channel_filters and
+ // call grpc_register_plugin().
+ if (internal::channel_filters == nullptr) {
+ grpc_register_plugin(internal::ChannelFilterPluginInit,
+ internal::ChannelFilterPluginShutdown);
+ internal::channel_filters = new std::vector<internal::FilterRecord>();
+ }
+ // Add an entry to channel_filters. The filter will be added when the
+ // C-core initialization code calls ChannelFilterPluginInit().
+ typedef internal::ChannelFilter<ChannelDataType, CallDataType> FilterType;
+ internal::FilterRecord filter_record = {
+ stack_type,
+ priority,
+ include_filter,
+ {FilterType::StartTransportStreamOp, FilterType::StartTransportOp,
+ FilterType::call_data_size, FilterType::InitCallElement,
+ FilterType::SetPollsetOrPollsetSet, FilterType::DestroyCallElement,
+ FilterType::channel_data_size, FilterType::InitChannelElement,
+ FilterType::DestroyChannelElement, FilterType::GetPeer, name}};
+ internal::channel_filters->push_back(filter_record);
+}
+
+} // namespace grpc
+
+#endif // GRPCXX_CHANNEL_FILTER_H
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 3c00f686ce..9cae96a00d 100644
--- a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
+++ b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
@@ -32,12 +32,12 @@
import threading
import time
import unittest
-from concurrent import futures
import grpc
from grpc import _channel
from grpc import _server
from tests.unit.framework.common import test_constants
+from tests.unit import _thread_pool
def _ready_in_connectivities(connectivities):
@@ -104,7 +104,8 @@ class ChannelConnectivityTest(unittest.TestCase):
grpc.ChannelConnectivity.READY, fifth_connectivities)
def test_immediately_connectable_channel_connectivity(self):
- server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ())
+ thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
+ server = _server.Server(thread_pool, ())
port = server.add_insecure_port('[::]:0')
server.start()
first_callback = _Callback()
@@ -141,9 +142,11 @@ class ChannelConnectivityTest(unittest.TestCase):
fourth_connectivities)
self.assertNotIn(
grpc.ChannelConnectivity.SHUTDOWN, fourth_connectivities)
+ self.assertFalse(thread_pool.was_used())
def test_reachable_then_unreachable_channel_connectivity(self):
- server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ())
+ thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
+ server = _server.Server(thread_pool, ())
port = server.add_insecure_port('[::]:0')
server.start()
callback = _Callback()
@@ -155,6 +158,7 @@ class ChannelConnectivityTest(unittest.TestCase):
server.stop(None)
callback.block_until_connectivities_satisfy(_last_connectivity_is_not_ready)
channel.unsubscribe(callback.update)
+ self.assertFalse(thread_pool.was_used())
if __name__ == '__main__':
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 e8982ed2de..24f5b45b18 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
@@ -31,12 +31,12 @@
import threading
import unittest
-from concurrent import futures
import grpc
from grpc import _channel
from grpc import _server
from tests.unit.framework.common import test_constants
+from tests.unit import _thread_pool
class _Callback(object):
@@ -78,7 +78,8 @@ class ChannelReadyFutureTest(unittest.TestCase):
self.assertFalse(ready_future.running())
def test_immediately_connectable_channel_connectivity(self):
- server = _server.Server(futures.ThreadPoolExecutor(max_workers=0), ())
+ thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
+ server = _server.Server(thread_pool, ())
port = server.add_insecure_port('[::]:0')
server.start()
channel = grpc.insecure_channel('localhost:{}'.format(port))
@@ -97,6 +98,7 @@ class ChannelReadyFutureTest(unittest.TestCase):
self.assertFalse(ready_future.cancelled())
self.assertTrue(ready_future.done())
self.assertFalse(ready_future.running())
+ self.assertFalse(thread_pool.was_used())
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/unit/_thread_pool.py b/src/python/grpcio_tests/tests/unit/_thread_pool.py
new file mode 100644
index 0000000000..f13cc2f86f
--- /dev/null
+++ b/src/python/grpcio_tests/tests/unit/_thread_pool.py
@@ -0,0 +1,48 @@
+# 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.
+
+import threading
+from concurrent import futures
+
+
+class RecordingThreadPool(futures.Executor):
+ """A thread pool that records if used."""
+ def __init__(self, max_workers):
+ self._tp_executor = futures.ThreadPoolExecutor(max_workers=max_workers)
+ self._lock = threading.Lock()
+ self._was_used = False
+
+ def submit(self, fn, *args, **kwargs):
+ with self._lock:
+ self._was_used = True
+ self._tp_executor.submit(fn, *args, **kwargs)
+
+ def was_used(self):
+ with self._lock:
+ return self._was_used
diff --git a/test/cpp/end2end/filter_end2end_test.cc b/test/cpp/end2end/filter_end2end_test.cc
new file mode 100644
index 0000000000..853720fd0d
--- /dev/null
+++ b/test/cpp/end2end/filter_end2end_test.cc
@@ -0,0 +1,353 @@
+/*
+ *
+ * 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 <memory>
+#include <mutex>
+
+#include <grpc++/channel.h>
+#include <grpc++/client_context.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/generic/async_generic_service.h>
+#include <grpc++/generic/generic_stub.h>
+#include <grpc++/impl/codegen/proto_utils.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc++/server_context.h>
+#include <grpc++/support/config.h>
+#include <grpc++/support/slice.h>
+#include <grpc/grpc.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/time.h>
+#include <gtest/gtest.h>
+
+#include "src/cpp/common/channel_filter.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+#include "test/cpp/util/byte_buffer_proto_helper.h"
+
+using grpc::testing::EchoRequest;
+using grpc::testing::EchoResponse;
+using std::chrono::system_clock;
+
+namespace grpc {
+namespace testing {
+namespace {
+
+void* tag(int i) { return (void*)(intptr_t)i; }
+
+void verify_ok(CompletionQueue* cq, int i, bool expect_ok) {
+ bool ok;
+ void* got_tag;
+ EXPECT_TRUE(cq->Next(&got_tag, &ok));
+ EXPECT_EQ(expect_ok, ok);
+ EXPECT_EQ(tag(i), got_tag);
+}
+
+namespace {
+
+int global_num_connections = 0;
+int global_num_calls = 0;
+mutex global_mu;
+
+void IncrementConnectionCounter() {
+ unique_lock<mutex> lock(global_mu);
+ ++global_num_connections;
+}
+
+void ResetConnectionCounter() {
+ unique_lock<mutex> lock(global_mu);
+ global_num_connections = 0;
+}
+
+int GetConnectionCounterValue() {
+ unique_lock<mutex> lock(global_mu);
+ return global_num_connections;
+}
+
+void IncrementCallCounter() {
+ unique_lock<mutex> lock(global_mu);
+ ++global_num_calls;
+}
+
+void ResetCallCounter() {
+ unique_lock<mutex> lock(global_mu);
+ global_num_calls = 0;
+}
+
+int GetCallCounterValue() {
+ unique_lock<mutex> lock(global_mu);
+ return global_num_calls;
+}
+
+} // namespace
+
+class ChannelDataImpl : public ChannelData {
+ public:
+ ChannelDataImpl(const grpc_channel_args& args, const char* peer)
+ : ChannelData(args, peer) {
+ IncrementConnectionCounter();
+ }
+};
+
+class CallDataImpl : public CallData {
+ public:
+ explicit CallDataImpl(const ChannelDataImpl& channel_data)
+ : CallData(channel_data) {}
+
+ void StartTransportStreamOp(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
+ TransportStreamOp* op) GRPC_OVERRIDE {
+ // Incrementing the counter could be done from the ctor, but we want
+ // to test that the individual methods are actually called correctly.
+ if (op->recv_initial_metadata() != nullptr) IncrementCallCounter();
+ grpc_call_next_op(exec_ctx, elem, op->op());
+ }
+};
+
+class FilterEnd2endTest : public ::testing::Test {
+ protected:
+ FilterEnd2endTest() : server_host_("localhost") {}
+
+ void SetUp() GRPC_OVERRIDE {
+ int port = grpc_pick_unused_port_or_die();
+ server_address_ << server_host_ << ":" << port;
+ // Setup server
+ ServerBuilder builder;
+ builder.AddListeningPort(server_address_.str(),
+ InsecureServerCredentials());
+ builder.RegisterAsyncGenericService(&generic_service_);
+ srv_cq_ = builder.AddCompletionQueue();
+ server_ = builder.BuildAndStart();
+ }
+
+ void TearDown() GRPC_OVERRIDE {
+ server_->Shutdown();
+ void* ignored_tag;
+ bool ignored_ok;
+ cli_cq_.Shutdown();
+ srv_cq_->Shutdown();
+ while (cli_cq_.Next(&ignored_tag, &ignored_ok))
+ ;
+ while (srv_cq_->Next(&ignored_tag, &ignored_ok))
+ ;
+ }
+
+ void ResetStub() {
+ std::shared_ptr<Channel> channel =
+ CreateChannel(server_address_.str(), InsecureChannelCredentials());
+ generic_stub_.reset(new GenericStub(channel));
+ ResetConnectionCounter();
+ ResetCallCounter();
+ }
+
+ void server_ok(int i) { verify_ok(srv_cq_.get(), i, true); }
+ void client_ok(int i) { verify_ok(&cli_cq_, i, true); }
+ void server_fail(int i) { verify_ok(srv_cq_.get(), i, false); }
+ void client_fail(int i) { verify_ok(&cli_cq_, i, false); }
+
+ void SendRpc(int num_rpcs) {
+ const grpc::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo");
+ for (int i = 0; i < num_rpcs; i++) {
+ EchoRequest send_request;
+ EchoRequest recv_request;
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ Status recv_status;
+
+ ClientContext cli_ctx;
+ GenericServerContext srv_ctx;
+ GenericServerAsyncReaderWriter stream(&srv_ctx);
+
+ // The string needs to be long enough to test heap-based slice.
+ send_request.set_message("Hello world. Hello world. Hello world.");
+ std::unique_ptr<GenericClientAsyncReaderWriter> call =
+ generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1));
+ client_ok(1);
+ std::unique_ptr<ByteBuffer> send_buffer =
+ SerializeToByteBuffer(&send_request);
+ call->Write(*send_buffer, tag(2));
+ // Send ByteBuffer can be destroyed after calling Write.
+ send_buffer.reset();
+ client_ok(2);
+ call->WritesDone(tag(3));
+ client_ok(3);
+
+ generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(),
+ srv_cq_.get(), tag(4));
+
+ verify_ok(srv_cq_.get(), 4, true);
+ EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length()));
+ EXPECT_EQ(kMethodName, srv_ctx.method());
+ ByteBuffer recv_buffer;
+ stream.Read(&recv_buffer, tag(5));
+ server_ok(5);
+ EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request));
+ EXPECT_EQ(send_request.message(), recv_request.message());
+
+ send_response.set_message(recv_request.message());
+ send_buffer = SerializeToByteBuffer(&send_response);
+ stream.Write(*send_buffer, tag(6));
+ send_buffer.reset();
+ server_ok(6);
+
+ stream.Finish(Status::OK, tag(7));
+ server_ok(7);
+
+ recv_buffer.Clear();
+ call->Read(&recv_buffer, tag(8));
+ client_ok(8);
+ EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response));
+
+ call->Finish(&recv_status, tag(9));
+ client_ok(9);
+
+ EXPECT_EQ(send_response.message(), recv_response.message());
+ EXPECT_TRUE(recv_status.ok());
+ }
+ }
+
+ CompletionQueue cli_cq_;
+ std::unique_ptr<ServerCompletionQueue> srv_cq_;
+ std::unique_ptr<grpc::testing::EchoTestService::Stub> stub_;
+ std::unique_ptr<grpc::GenericStub> generic_stub_;
+ std::unique_ptr<Server> server_;
+ AsyncGenericService generic_service_;
+ const grpc::string server_host_;
+ std::ostringstream server_address_;
+};
+
+TEST_F(FilterEnd2endTest, SimpleRpc) {
+ ResetStub();
+ EXPECT_EQ(0, GetConnectionCounterValue());
+ EXPECT_EQ(0, GetCallCounterValue());
+ SendRpc(1);
+ EXPECT_EQ(1, GetConnectionCounterValue());
+ EXPECT_EQ(1, GetCallCounterValue());
+}
+
+TEST_F(FilterEnd2endTest, SequentialRpcs) {
+ ResetStub();
+ EXPECT_EQ(0, GetConnectionCounterValue());
+ EXPECT_EQ(0, GetCallCounterValue());
+ SendRpc(10);
+ EXPECT_EQ(1, GetConnectionCounterValue());
+ EXPECT_EQ(10, GetCallCounterValue());
+}
+
+// One ping, one pong.
+TEST_F(FilterEnd2endTest, SimpleBidiStreaming) {
+ ResetStub();
+ EXPECT_EQ(0, GetConnectionCounterValue());
+ EXPECT_EQ(0, GetCallCounterValue());
+
+ const grpc::string kMethodName(
+ "/grpc.cpp.test.util.EchoTestService/BidiStream");
+ EchoRequest send_request;
+ EchoRequest recv_request;
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ Status recv_status;
+ ClientContext cli_ctx;
+ GenericServerContext srv_ctx;
+ GenericServerAsyncReaderWriter srv_stream(&srv_ctx);
+
+ cli_ctx.set_compression_algorithm(GRPC_COMPRESS_GZIP);
+ send_request.set_message("Hello");
+ std::unique_ptr<GenericClientAsyncReaderWriter> cli_stream =
+ generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1));
+ client_ok(1);
+
+ generic_service_.RequestCall(&srv_ctx, &srv_stream, srv_cq_.get(),
+ srv_cq_.get(), tag(2));
+
+ verify_ok(srv_cq_.get(), 2, true);
+ EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length()));
+ EXPECT_EQ(kMethodName, srv_ctx.method());
+
+ std::unique_ptr<ByteBuffer> send_buffer =
+ SerializeToByteBuffer(&send_request);
+ cli_stream->Write(*send_buffer, tag(3));
+ send_buffer.reset();
+ client_ok(3);
+
+ ByteBuffer recv_buffer;
+ srv_stream.Read(&recv_buffer, tag(4));
+ server_ok(4);
+ EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_request));
+ EXPECT_EQ(send_request.message(), recv_request.message());
+
+ send_response.set_message(recv_request.message());
+ send_buffer = SerializeToByteBuffer(&send_response);
+ srv_stream.Write(*send_buffer, tag(5));
+ send_buffer.reset();
+ server_ok(5);
+
+ cli_stream->Read(&recv_buffer, tag(6));
+ client_ok(6);
+ EXPECT_TRUE(ParseFromByteBuffer(&recv_buffer, &recv_response));
+ EXPECT_EQ(send_response.message(), recv_response.message());
+
+ cli_stream->WritesDone(tag(7));
+ client_ok(7);
+
+ srv_stream.Read(&recv_buffer, tag(8));
+ server_fail(8);
+
+ srv_stream.Finish(Status::OK, tag(9));
+ server_ok(9);
+
+ cli_stream->Finish(&recv_status, tag(10));
+ client_ok(10);
+
+ EXPECT_EQ(send_response.message(), recv_response.message());
+ EXPECT_TRUE(recv_status.ok());
+
+ EXPECT_EQ(1, GetCallCounterValue());
+ EXPECT_EQ(1, GetConnectionCounterValue());
+}
+
+void RegisterFilter() {
+ grpc::RegisterChannelFilter<ChannelDataImpl, CallDataImpl>(
+ "test-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
+}
+
+} // namespace
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ grpc::testing::RegisterFilter();
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc
index ebef0002a3..e5878bb248 100644
--- a/test/cpp/interop/interop_server.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -31,7 +31,6 @@
*
*/
-#include <signal.h>
#include <unistd.h>
#include <fstream>
@@ -78,8 +77,6 @@ using grpc::testing::StreamingOutputCallResponse;
using grpc::testing::TestService;
using grpc::Status;
-static bool got_sigint = false;
-
const char kEchoInitialMetadataKey[] = "x-grpc-test-echo-initial";
const char kEchoTrailingBinMetadataKey[] = "x-grpc-test-echo-trailing-bin";
const char kEchoUserAgentKey[] = "x-grpc-test-echo-useragent";
@@ -311,7 +308,9 @@ class TestServiceImpl : public TestService::Service {
}
};
-void RunServer() {
+void grpc::testing::interop::RunServer(
+ std::shared_ptr<ServerCredentials> creds) {
+ GPR_ASSERT(FLAGS_port != 0);
std::ostringstream server_address;
server_address << "0.0.0.0:" << FLAGS_port;
TestServiceImpl service;
@@ -321,24 +320,10 @@ void RunServer() {
ServerBuilder builder;
builder.RegisterService(&service);
- std::shared_ptr<ServerCredentials> creds =
- grpc::testing::CreateInteropServerCredentials();
builder.AddListeningPort(server_address.str(), creds);
std::unique_ptr<Server> server(builder.BuildAndStart());
gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str());
- while (!got_sigint) {
+ while (!g_got_sigint) {
sleep(5);
}
}
-
-static void sigint_handler(int x) { got_sigint = true; }
-
-int main(int argc, char** argv) {
- grpc::testing::InitTest(&argc, &argv, true);
- signal(SIGINT, sigint_handler);
-
- GPR_ASSERT(FLAGS_port != 0);
- RunServer();
-
- return 0;
-}
diff --git a/test/cpp/interop/interop_server_bootstrap.cc b/test/cpp/interop/interop_server_bootstrap.cc
new file mode 100644
index 0000000000..424f7ca7f0
--- /dev/null
+++ b/test/cpp/interop/interop_server_bootstrap.cc
@@ -0,0 +1,54 @@
+/*
+ *
+ * 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 <signal.h>
+#include <unistd.h>
+
+#include "test/cpp/interop/server_helper.h"
+#include "test/cpp/util/test_config.h"
+
+bool grpc::testing::interop::g_got_sigint = false;
+
+static void sigint_handler(int x) {
+ grpc::testing::interop::g_got_sigint = true;
+}
+
+int main(int argc, char** argv) {
+ grpc::testing::InitTest(&argc, &argv, true);
+ signal(SIGINT, sigint_handler);
+
+ grpc::testing::interop::RunServer(
+ grpc::testing::CreateInteropServerCredentials());
+
+ return 0;
+}
diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h
index a1da14a4c8..fc4ea8b3e8 100644
--- a/test/cpp/interop/server_helper.h
+++ b/test/cpp/interop/server_helper.h
@@ -60,6 +60,12 @@ class InteropServerContextInspector {
const ::grpc::ServerContext& context_;
};
+namespace interop {
+
+extern bool g_got_sigint;
+void RunServer(std::shared_ptr<ServerCredentials> creds);
+
+} // namespace interop
} // namespace testing
} // namespace grpc
diff --git a/tools/dockerfile/interoptest/grpc_interop_go/build_interop.sh b/tools/dockerfile/interoptest/grpc_interop_go/build_interop.sh
index e891549342..1fd088322c 100755
--- a/tools/dockerfile/interoptest/grpc_interop_go/build_interop.sh
+++ b/tools/dockerfile/interoptest/grpc_interop_go/build_interop.sh
@@ -46,6 +46,7 @@ go get github.com/golang/protobuf/proto
go get golang.org/x/net/context
go get golang.org/x/net/trace
go get golang.org/x/oauth2
+go get golang.org/x/oauth2/google
go get google.golang.org/cloud
# Build the interop client and server
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 945298b964..95c0e853c2 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -863,6 +863,7 @@ src/cpp/client/secure_credentials.h \
src/cpp/common/secure_auth_context.h \
src/cpp/server/secure_server_credentials.h \
src/cpp/client/create_channel_internal.h \
+src/cpp/common/channel_filter.h \
src/cpp/server/dynamic_thread_pool.h \
src/cpp/server/thread_pool_interface.h \
src/cpp/client/secure_credentials.cc \
@@ -880,6 +881,7 @@ src/cpp/client/credentials.cc \
src/cpp/client/generic_stub.cc \
src/cpp/client/insecure_credentials.cc \
src/cpp/common/channel_arguments.cc \
+src/cpp/common/channel_filter.cc \
src/cpp/common/completion_queue.cc \
src/cpp/common/core_codegen.cc \
src/cpp/common/rpc_method.cc \
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 542415d908..8be15dda4e 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -706,7 +706,7 @@ class ObjCLanguage(object):
shortname='objc-tests',
environ=_FORCE_ENVIRON_FOR_WRAPPERS),
self.config.job_spec(['src/objective-c/tests/build_example_test.sh'],
- timeout_seconds=15*60,
+ timeout_seconds=30*60,
shortname='objc-examples-build',
environ=_FORCE_ENVIRON_FOR_WRAPPERS)]
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 5294dddda0..4071eba94d 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -2118,6 +2118,24 @@
],
"headers": [],
"language": "c++",
+ "name": "filter_end2end_test",
+ "src": [
+ "test/cpp/end2end/filter_end2end_test.cc"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc++",
+ "grpc++_test_util",
+ "grpc_test_util"
+ ],
+ "headers": [],
+ "language": "c++",
"name": "generic_end2end_test",
"src": [
"test/cpp/end2end/generic_end2end_test.cc"
@@ -2329,6 +2347,7 @@
"grpc++_test_util",
"grpc_test_util",
"interop_server_helper",
+ "interop_server_lib",
"interop_server_main"
],
"headers": [],
@@ -4214,7 +4233,6 @@
"gpr",
"grpc_base",
"grpc_lb_policy_grpclb",
- "grpc_lb_policy_grpclb",
"grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin",
"grpc_load_reporting",
@@ -4310,7 +4328,6 @@
"gpr",
"grpc_base",
"grpc_lb_policy_grpclb",
- "grpc_lb_policy_grpclb",
"grpc_lb_policy_pick_first",
"grpc_lb_policy_round_robin",
"grpc_load_reporting",
@@ -4668,7 +4685,7 @@
"src/proto/grpc/testing/test.pb.h"
],
"language": "c++",
- "name": "interop_server_main",
+ "name": "interop_server_lib",
"src": [
"test/cpp/interop/interop_server.cc"
],
@@ -4677,6 +4694,19 @@
},
{
"deps": [
+ "interop_server_lib"
+ ],
+ "headers": [],
+ "language": "c++",
+ "name": "interop_server_main",
+ "src": [
+ "test/cpp/interop/interop_server_bootstrap.cc"
+ ],
+ "third_party": false,
+ "type": "lib"
+ },
+ {
+ "deps": [
"grpc++",
"grpc++_test_util",
"grpc_test_util"
@@ -6618,6 +6648,7 @@
"include/grpc++/support/sync_stream.h",
"include/grpc++/support/time.h",
"src/cpp/client/create_channel_internal.h",
+ "src/cpp/common/channel_filter.h",
"src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h"
],
@@ -6681,6 +6712,8 @@
"src/cpp/client/generic_stub.cc",
"src/cpp/client/insecure_credentials.cc",
"src/cpp/common/channel_arguments.cc",
+ "src/cpp/common/channel_filter.cc",
+ "src/cpp/common/channel_filter.h",
"src/cpp/common/completion_queue.cc",
"src/cpp/common/core_codegen.cc",
"src/cpp/common/rpc_method.cc",
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index f608aa96d9..11fb460dd5 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -2261,6 +2261,27 @@
"flaky": false,
"gtest": true,
"language": "c++",
+ "name": "filter_end2end_test",
+ "platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ]
+ },
+ {
+ "args": [],
+ "ci_platforms": [
+ "linux",
+ "mac",
+ "posix",
+ "windows"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "flaky": false,
+ "gtest": true,
+ "language": "c++",
"name": "generic_end2end_test",
"platforms": [
"linux",
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
index cb9e41ea22..835e2527c9 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj
@@ -363,6 +363,7 @@
<ClInclude Include="$(SolutionDir)\..\src\cpp\common\secure_auth_context.h" />
<ClInclude Include="$(SolutionDir)\..\src\cpp\server\secure_server_credentials.h" />
<ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\cpp\common\channel_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h" />
<ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h" />
</ItemGroup>
@@ -397,6 +398,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_arguments.cc">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_filter.cc">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\completion_queue.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\core_codegen.cc">
diff --git a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
index a9051182b3..883e66e1df 100644
--- a/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++/grpc++.vcxproj.filters
@@ -46,6 +46,9 @@
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_arguments.cc">
<Filter>src\cpp\common</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_filter.cc">
+ <Filter>src\cpp\common</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\completion_queue.cc">
<Filter>src\cpp\common</Filter>
</ClCompile>
@@ -413,6 +416,9 @@
<ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h">
<Filter>src\cpp\client</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\cpp\common\channel_filter.h">
+ <Filter>src\cpp\common</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h">
<Filter>src\cpp\server</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
index 03be485b29..e71180feb0 100644
--- a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -359,6 +359,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\cpp\common\channel_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h" />
<ClInclude Include="$(SolutionDir)\..\src\cpp\server\thread_pool_interface.h" />
</ItemGroup>
@@ -383,6 +384,8 @@
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_arguments.cc">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_filter.cc">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\completion_queue.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\core_codegen.cc">
diff --git a/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index ba99bc53c8..a9aa147e56 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\cpp\common\channel_arguments.cc">
<Filter>src\cpp\common</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\cpp\common\channel_filter.cc">
+ <Filter>src\cpp\common</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\cpp\common\completion_queue.cc">
<Filter>src\cpp\common</Filter>
</ClCompile>
@@ -386,6 +389,9 @@
<ClInclude Include="$(SolutionDir)\..\src\cpp\client\create_channel_internal.h">
<Filter>src\cpp\client</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\cpp\common\channel_filter.h">
+ <Filter>src\cpp\common</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\cpp\server\dynamic_thread_pool.h">
<Filter>src\cpp\server</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/interop_server_lib/interop_server_lib.vcxproj b/vsprojects/vcxproj/interop_server_lib/interop_server_lib.vcxproj
new file mode 100644
index 0000000000..204d3f770b
--- /dev/null
+++ b/vsprojects/vcxproj/interop_server_lib/interop_server_lib.vcxproj
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <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>{458DCA09-83B9-5E68-D7E9-118864ECBD94}</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>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</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\winsock.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+ <TargetName>interop_server_lib</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)'=='Release'">
+ <TargetName>interop_server_lib</TargetName>
+ </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>Windows</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>Windows</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>Windows</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>Windows</SubSystem>
+ <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+ <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.grpc.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.grpc.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\test.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.grpc.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\test.grpc.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\interop_server.cc">
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\interop_server_helper\interop_server_helper.vcxproj">
+ <Project>{F55BEA2C-B61D-AAFE-CA15-223B8AC0DE5A}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+ <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+ </ProjectReference>
+ <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>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</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>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
+ <Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </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>
+ </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/interop_server_lib/interop_server_lib.vcxproj.filters b/vsprojects/vcxproj/interop_server_lib/interop_server_lib.vcxproj.filters
new file mode 100644
index 0000000000..63fc0f7f51
--- /dev/null
+++ b/vsprojects/vcxproj/interop_server_lib/interop_server_lib.vcxproj.filters
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.proto">
+ <Filter>src\proto\grpc\testing</Filter>
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.proto">
+ <Filter>src\proto\grpc\testing</Filter>
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.proto">
+ <Filter>src\proto\grpc\testing</Filter>
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\interop_server.cc">
+ <Filter>test\cpp\interop</Filter>
+ </ClCompile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Filter Include="src">
+ <UniqueIdentifier>{356c90d7-2dcd-5f6a-d3ca-6461f2597581}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto">
+ <UniqueIdentifier>{70740334-0cbf-ab29-0e1c-f0ffa390d77f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto\grpc">
+ <UniqueIdentifier>{d581eb6c-94b6-eb79-6b76-d122c13cff3c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto\grpc\testing">
+ <UniqueIdentifier>{27f43e87-cfd9-68cc-179a-fc44046797c4}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test">
+ <UniqueIdentifier>{3402c01e-a9f6-2dd8-6963-03a5774d37f2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\cpp">
+ <UniqueIdentifier>{656eed4b-782e-224c-6101-8a61c2daa94e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\cpp\interop">
+ <UniqueIdentifier>{61c0dab5-5c69-82b0-2961-4104445f2e06}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
+
diff --git a/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj b/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj
index 18971d6a34..9fd4d11be9 100644
--- a/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj
+++ b/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj
@@ -147,57 +147,12 @@
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.pb.cc">
- </ClCompile>
- <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.pb.h">
- </ClInclude>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.grpc.pb.cc">
- </ClCompile>
- <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.grpc.pb.h">
- </ClInclude>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.cc">
- </ClCompile>
- <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.pb.h">
- </ClInclude>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.cc">
- </ClCompile>
- <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.grpc.pb.h">
- </ClInclude>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.pb.cc">
- </ClCompile>
- <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\test.pb.h">
- </ClInclude>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.grpc.pb.cc">
- </ClCompile>
- <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\test.grpc.pb.h">
- </ClInclude>
- <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\interop_server.cc">
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\interop_server_bootstrap.cc">
</ClCompile>
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\interop_server_helper\interop_server_helper.vcxproj">
- <Project>{F55BEA2C-B61D-AAFE-CA15-223B8AC0DE5A}</Project>
- </ProjectReference>
- <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
- <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
- </ProjectReference>
- <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>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</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>
- <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_config\grpc++_test_config.vcxproj">
- <Project>{3F7D093D-11F9-C4BC-BEB7-18EB28E3F290}</Project>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\interop_server_lib\interop_server_lib.vcxproj">
+ <Project>{458DCA09-83B9-5E68-D7E9-118864ECBD94}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters b/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters
index 4ee8135c04..d8d049299b 100644
--- a/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters
+++ b/vsprojects/vcxproj/interop_server_main/interop_server_main.vcxproj.filters
@@ -1,33 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\empty.proto">
- <Filter>src\proto\grpc\testing</Filter>
- </ClCompile>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\messages.proto">
- <Filter>src\proto\grpc\testing</Filter>
- </ClCompile>
- <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\test.proto">
- <Filter>src\proto\grpc\testing</Filter>
- </ClCompile>
- <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\interop_server.cc">
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\interop\interop_server_bootstrap.cc">
<Filter>test\cpp\interop</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
- <Filter Include="src">
- <UniqueIdentifier>{9dfb04b3-9e58-7efb-70a2-b02ec8c5e83e}</UniqueIdentifier>
- </Filter>
- <Filter Include="src\proto">
- <UniqueIdentifier>{ebd8177f-6130-a4fb-1c41-d894f801e3b9}</UniqueIdentifier>
- </Filter>
- <Filter Include="src\proto\grpc">
- <UniqueIdentifier>{1df1acf2-4654-4530-10af-912381c69012}</UniqueIdentifier>
- </Filter>
- <Filter Include="src\proto\grpc\testing">
- <UniqueIdentifier>{ba56d830-1546-c07f-f5ee-03164e41914e}</UniqueIdentifier>
- </Filter>
<Filter Include="test">
<UniqueIdentifier>{02523054-816a-75a0-b24b-f527e99c7142}</UniqueIdentifier>
</Filter>
diff --git a/vsprojects/vcxproj/test/filter_end2end_test/filter_end2end_test.vcxproj b/vsprojects/vcxproj/test/filter_end2end_test/filter_end2end_test.vcxproj
new file mode 100644
index 0000000000..99c000e4fa
--- /dev/null
+++ b/vsprojects/vcxproj/test/filter_end2end_test/filter_end2end_test.vcxproj
@@ -0,0 +1,207 @@
+<?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>{1D42975A-18A5-09D0-30B1-2AE6A97FB9DE}</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\cpptest.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\protobuf.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+ <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+ <TargetName>filter_end2end_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>filter_end2end_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\cpp\end2end\filter_end2end_test.cc">
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
+ <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
+ </ProjectReference>
+ <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>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</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/filter_end2end_test/filter_end2end_test.vcxproj.filters b/vsprojects/vcxproj/test/filter_end2end_test/filter_end2end_test.vcxproj.filters
new file mode 100644
index 0000000000..c68442365c
--- /dev/null
+++ b/vsprojects/vcxproj/test/filter_end2end_test/filter_end2end_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\cpp\end2end\filter_end2end_test.cc">
+ <Filter>test\cpp\end2end</Filter>
+ </ClCompile>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Filter Include="test">
+ <UniqueIdentifier>{f7581160-220d-1118-f29e-6b37e45671c9}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\cpp">
+ <UniqueIdentifier>{63784d35-03cc-1a7e-0c95-a9451bc1daf4}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\cpp\end2end">
+ <UniqueIdentifier>{d2a01682-970e-d23d-1eb8-ef020e3a1ca3}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
+