aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile102
-rw-r--r--build.yaml40
-rw-r--r--examples/cpp/cpptutorial.md2
-rw-r--r--examples/csharp/helloworld-from-cli/Greeter/Helloworld.cs259
-rw-r--r--examples/csharp/helloworld-from-cli/Greeter/HelloworldGrpc.cs143
-rw-r--r--examples/csharp/helloworld-from-cli/Greeter/project.json22
-rw-r--r--examples/csharp/helloworld-from-cli/GreeterClient/Program.cs53
-rw-r--r--examples/csharp/helloworld-from-cli/GreeterClient/project.json26
-rw-r--r--examples/csharp/helloworld-from-cli/GreeterServer/Program.cs66
-rw-r--r--examples/csharp/helloworld-from-cli/GreeterServer/project.json26
-rw-r--r--examples/csharp/helloworld-from-cli/README.md59
-rw-r--r--examples/csharp/helloworld/README.md18
-rw-r--r--examples/node/package.json4
-rwxr-xr-xexamples/ruby/greeter_client.rb2
-rwxr-xr-xexamples/ruby/greeter_server.rb2
-rw-r--r--examples/ruby/grpc-demo.gemspec4
-rw-r--r--examples/ruby/lib/helloworld_pb.rb (renamed from examples/ruby/lib/helloworld.rb)0
-rw-r--r--examples/ruby/lib/helloworld_services_pb.rb (renamed from examples/ruby/lib/helloworld_services.rb)2
-rw-r--r--examples/ruby/lib/route_guide_pb.rb (renamed from examples/ruby/lib/route_guide.rb)0
-rw-r--r--examples/ruby/lib/route_guide_services_pb.rb (renamed from examples/ruby/lib/route_guide_services.rb)2
-rwxr-xr-xexamples/ruby/route_guide/route_guide_client.rb2
-rwxr-xr-xexamples/ruby/route_guide/route_guide_server.rb2
-rwxr-xr-xgrpc.gemspec2
-rw-r--r--include/grpc++/impl/codegen/thrift_serializer.h219
-rw-r--r--include/grpc++/impl/codegen/thrift_utils.h85
-rw-r--r--include/grpc++/support/byte_buffer.h3
-rw-r--r--package.json2
-rw-r--r--package.xml19
-rw-r--r--src/core/ext/transport/cronet/transport/cronet_transport.c1303
-rw-r--r--src/cpp/util/byte_buffer.cc25
-rw-r--r--src/csharp/Grpc.Auth/Grpc.Auth.csproj31
-rw-r--r--src/csharp/Grpc.Auth/Grpc.Auth.nuspec2
-rw-r--r--src/csharp/Grpc.Auth/packages.config4
-rw-r--r--src/csharp/Grpc.Auth/project.json4
-rw-r--r--src/csharp/Grpc.Core.Tests/SanityTest.cs6
-rw-r--r--src/csharp/Grpc.Examples.MathClient/project.json5
-rw-r--r--src/csharp/Grpc.Examples.MathServer/project.json5
-rw-r--r--src/csharp/Grpc.Examples/project.json3
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj31
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Client/packages.config4
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj1
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config15
-rw-r--r--src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json5
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj31
-rw-r--r--src/csharp/Grpc.IntegrationTesting.Server/packages.config4
-rw-r--r--src/csharp/Grpc.IntegrationTesting.StressClient/project.json5
-rw-r--r--src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj24
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropClient.cs63
-rw-r--r--src/csharp/Grpc.IntegrationTesting/InteropServer.cs32
-rw-r--r--src/csharp/Grpc.IntegrationTesting/QpsWorker.cs30
-rw-r--r--src/csharp/Grpc.IntegrationTesting/StressTestClient.cs51
-rw-r--r--src/csharp/Grpc.IntegrationTesting/packages.config6
-rw-r--r--src/csharp/Grpc.IntegrationTesting/project.json2
-rw-r--r--src/csharp/build_packages.bat8
-rw-r--r--src/node/health_check/package.json4
-rwxr-xr-xsrc/node/tools/bin/protoc.js6
-rw-r--r--src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m394
-rw-r--r--src/php/ext/grpc/php7_wrapper.h3
-rw-r--r--src/python/grpcio_tests/tests/interop/_insecure_interop_test.py14
-rw-r--r--src/python/grpcio_tests/tests/interop/_secure_interop_test.py24
-rw-r--r--src/python/grpcio_tests/tests/interop/client.py56
-rw-r--r--src/python/grpcio_tests/tests/interop/methods.py270
-rw-r--r--src/python/grpcio_tests/tests/interop/server.py12
-rw-r--r--src/python/grpcio_tests/tests/stress/client.py21
-rw-r--r--src/python/grpcio_tests/tests/stress/metrics_server.py2
-rw-r--r--src/ruby/lib/grpc/generic/bidi_call.rb97
-rw-r--r--templates/Makefile.template31
-rw-r--r--templates/grpc.gemspec.template2
-rw-r--r--templates/package.json.template2
-rw-r--r--templates/package.xml.template19
-rw-r--r--templates/src/csharp/Grpc.Auth/project.json.template4
-rw-r--r--templates/src/csharp/Grpc.Examples.MathClient/project.json.template2
-rw-r--r--templates/src/csharp/Grpc.Examples.MathServer/project.json.template2
-rw-r--r--templates/src/csharp/Grpc.Examples/project.json.template3
-rw-r--r--templates/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json.template2
-rw-r--r--templates/src/csharp/Grpc.IntegrationTesting.StressClient/project.json.template2
-rw-r--r--templates/src/csharp/Grpc.IntegrationTesting/project.json.template2
-rw-r--r--templates/src/csharp/build_options.include4
-rw-r--r--templates/src/csharp/build_packages.bat.template8
-rw-r--r--templates/src/node/health_check/package.json.template4
-rw-r--r--test/cpp/util/cli_credentials.cc63
-rw-r--r--test/cpp/util/cli_credentials.h53
-rw-r--r--test/cpp/util/config_grpc_cli.h85
-rw-r--r--test/cpp/util/grpc_cli.cc194
-rw-r--r--test/cpp/util/grpc_tool.cc365
-rw-r--r--test/cpp/util/grpc_tool.h54
-rw-r--r--test/cpp/util/grpc_tool_test.cc227
-rw-r--r--test/cpp/util/proto_file_parser.cc201
-rw-r--r--test/cpp/util/proto_file_parser.h65
-rw-r--r--test/cpp/util/proto_reflection_descriptor_database.cc2
-rw-r--r--test/distrib/csharp/DistribTest/App.config14
-rw-r--r--test/distrib/csharp/DistribTest/DistribTest.csproj54
-rw-r--r--test/distrib/csharp/DistribTest/packages.config8
-rw-r--r--test/distrib/python/distribtest.py4
m---------third_party/thrift0
-rwxr-xr-xtools/gce/create_linux_worker.sh4
-rwxr-xr-xtools/gource/gen-all-logs.sh3
-rwxr-xr-xtools/gource/gource.sh2
-rwxr-xr-xtools/gource/make-video.sh2
-rw-r--r--tools/grift/Dockerfile67
-rw-r--r--tools/grift/README.md26
-rw-r--r--tools/grift/grpc_plugins_generator.patch2505
-rwxr-xr-xtools/run_tests/build_package_node.sh1
-rw-r--r--tools/run_tests/package_targets.py9
-rwxr-xr-xtools/run_tests/sanity/check_submodules.sh1
-rw-r--r--tools/run_tests/sources_and_headers.json64
-rw-r--r--tools/run_tests/tests.json21
-rw-r--r--vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj2
-rw-r--r--vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters6
-rw-r--r--vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj11
-rw-r--r--vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters15
-rw-r--r--vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj9
-rw-r--r--vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj286
-rw-r--r--vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters232
115 files changed, 6686 insertions, 1828 deletions
diff --git a/.gitmodules b/.gitmodules
index d41b8d5213..92d5ac3e4f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -17,3 +17,6 @@
[submodule "third_party/nanopb"]
path = third_party/nanopb
url = https://github.com/nanopb/nanopb.git
+[submodule "third_party/thrift"]
+ path = third_party/thrift
+ url = https://github.com/apache/thrift.git
diff --git a/Makefile b/Makefile
index 7cef08ce03..2db87e83ae 100644
--- a/Makefile
+++ b/Makefile
@@ -800,13 +800,6 @@ ifeq ($(MAKECMDGOALS),clean)
NO_DEPS = true
endif
-INSTALL_OK = false
-ifeq ($(HAS_VALID_PROTOC),true)
-ifeq ($(HAS_SYSTEM_PROTOBUF_VERIFY),true)
-INSTALL_OK = true
-endif
-endif
-
.SECONDARY = %.pb.h %.pb.cc
ifeq ($(DEP_MISSING),)
@@ -1049,6 +1042,7 @@ grpc_node_plugin: $(BINDIR)/$(CONFIG)/grpc_node_plugin
grpc_objective_c_plugin: $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin
grpc_python_plugin: $(BINDIR)/$(CONFIG)/grpc_python_plugin
grpc_ruby_plugin: $(BINDIR)/$(CONFIG)/grpc_ruby_plugin
+grpc_tool_test: $(BINDIR)/$(CONFIG)/grpc_tool_test
grpclb_api_test: $(BINDIR)/$(CONFIG)/grpclb_api_test
grpclb_test: $(BINDIR)/$(CONFIG)/grpclb_test
hybrid_end2end_test: $(BINDIR)/$(CONFIG)/hybrid_end2end_test
@@ -1407,6 +1401,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/generic_end2end_test \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
+ $(BINDIR)/$(CONFIG)/grpc_tool_test \
$(BINDIR)/$(CONFIG)/grpclb_api_test \
$(BINDIR)/$(CONFIG)/grpclb_test \
$(BINDIR)/$(CONFIG)/hybrid_end2end_test \
@@ -1493,6 +1488,7 @@ buildtests_cxx: privatelibs_cxx \
$(BINDIR)/$(CONFIG)/generic_end2end_test \
$(BINDIR)/$(CONFIG)/golden_file_test \
$(BINDIR)/$(CONFIG)/grpc_cli \
+ $(BINDIR)/$(CONFIG)/grpc_tool_test \
$(BINDIR)/$(CONFIG)/grpclb_api_test \
$(BINDIR)/$(CONFIG)/grpclb_test \
$(BINDIR)/$(CONFIG)/hybrid_end2end_test \
@@ -1784,6 +1780,8 @@ test_cxx: buildtests_cxx
$(Q) $(BINDIR)/$(CONFIG)/generic_end2end_test || ( echo test generic_end2end_test failed ; exit 1 )
$(E) "[RUN] Testing golden_file_test"
$(Q) $(BINDIR)/$(CONFIG)/golden_file_test || ( echo test golden_file_test failed ; exit 1 )
+ $(E) "[RUN] Testing grpc_tool_test"
+ $(Q) $(BINDIR)/$(CONFIG)/grpc_tool_test || ( echo test grpc_tool_test failed ; exit 1 )
$(E) "[RUN] Testing grpclb_api_test"
$(Q) $(BINDIR)/$(CONFIG)/grpclb_api_test || ( echo test grpclb_api_test failed ; exit 1 )
$(E) "[RUN] Testing grpclb_test"
@@ -2163,7 +2161,7 @@ $(OBJDIR)/$(CONFIG)/%.o : %.cc
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
-install: install_c install_cxx install-plugins install-certs verify-install
+install: install_c install_cxx install-plugins install-certs
install_c: install-headers_c install-static_c install-shared_c
@@ -2346,28 +2344,6 @@ install-certs: etc/roots.pem
$(Q) $(INSTALL) -d $(prefix)/share/grpc
$(Q) $(INSTALL) etc/roots.pem $(prefix)/share/grpc/roots.pem
-verify-install:
-ifeq ($(INSTALL_OK),true)
- @echo "Your system looks ready to go."
- @echo
-else
- @echo "Warning: it looks like protoc 3.0.0+ isn't installed on your system,"
- @echo "which means that you won't be able to compile .proto files for use"
- @echo "with gRPC."
- @echo
- @echo "If you are just using pre-compiled protocol buffers, or you otherwise"
- @echo "have no need to compile .proto files, you can ignore this."
- @echo
- @echo "If you do need protobuf for some reason, you can download and install"
- @echo "it from:"
- @echo
- @echo " https://github.com/google/protobuf/releases"
- @echo
- @echo "Once you've done so, you can re-run this check by doing:"
- @echo
- @echo " make verify-install"
-endif
-
clean:
$(E) "[CLEAN] Cleaning build directories."
$(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR) cache.mk
@@ -4060,6 +4036,8 @@ PUBLIC_HEADERS_CXX += \
include/grpc/impl/codegen/time.h \
include/grpc++/impl/codegen/proto_utils.h \
include/grpc++/impl/codegen/config_protobuf.h \
+ include/grpc++/impl/codegen/thrift_serializer.h \
+ include/grpc++/impl/codegen/thrift_utils.h \
LIBGRPC++_TEST_UTIL_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_TEST_UTIL_SRC))))
@@ -4294,6 +4272,8 @@ endif
LIBGRPC_CLI_LIBS_SRC = \
test/cpp/util/cli_call.cc \
+ test/cpp/util/cli_credentials.cc \
+ test/cpp/util/grpc_tool.cc \
test/cpp/util/proto_file_parser.cc \
test/cpp/util/proto_reflection_descriptor_database.cc \
@@ -11331,16 +11311,16 @@ $(BINDIR)/$(CONFIG)/grpc_cli: protobuf_dep_error
else
-$(BINDIR)/$(CONFIG)/grpc_cli: $(PROTOBUF_DEP) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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)/grpc_cli: $(PROTOBUF_DEP) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
$(E) "[LD] Linking $@"
$(Q) mkdir -p `dirname $@`
- $(Q) $(LDXX) $(LDFLAGS) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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)/grpc_cli
+ $(Q) $(LDXX) $(LDFLAGS) $(GRPC_CLI_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/grpc_cli
endif
endif
-$(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_cli.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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
+$(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_cli.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
deps_grpc_cli: $(GRPC_CLI_OBJS:.o=.dep)
@@ -11537,6 +11517,60 @@ ifneq ($(NO_DEPS),true)
endif
+GRPC_TOOL_TEST_SRC = \
+ $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \
+ $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc \
+ test/cpp/util/grpc_tool_test.cc \
+ test/cpp/util/string_ref_helper.cc \
+
+GRPC_TOOL_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_TOOL_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/grpc_tool_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)/grpc_tool_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/grpc_tool_test: $(PROTOBUF_DEP) $(GRPC_TOOL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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) $(GRPC_TOOL_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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)/grpc_tool_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo_messages.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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
+
+$(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_tool_test.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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
+
+$(OBJDIR)/$(CONFIG)/test/cpp/util/string_ref_helper.o: $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libgrpc++_reflection.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_grpc_tool_test: $(GRPC_TOOL_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GRPC_TOOL_TEST_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/util/grpc_tool_test.o: $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/util/string_ref_helper.o: $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+
+
GRPCLB_API_TEST_SRC = \
$(GENDIR)/src/proto/grpc/lb/v1/load_balancer.pb.cc $(GENDIR)/src/proto/grpc/lb/v1/load_balancer.grpc.pb.cc \
test/cpp/grpclb/grpclb_api_test.cc \
@@ -15300,7 +15334,9 @@ test/cpp/qps/usage_timer.cc: $(OPENSSL_DEP)
test/cpp/util/benchmark_config.cc: $(OPENSSL_DEP)
test/cpp/util/byte_buffer_proto_helper.cc: $(OPENSSL_DEP)
test/cpp/util/cli_call.cc: $(OPENSSL_DEP)
+test/cpp/util/cli_credentials.cc: $(OPENSSL_DEP)
test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP)
+test/cpp/util/grpc_tool.cc: $(OPENSSL_DEP)
test/cpp/util/proto_file_parser.cc: $(OPENSSL_DEP)
test/cpp/util/proto_reflection_descriptor_database.cc: $(OPENSSL_DEP)
test/cpp/util/string_ref_helper.cc: $(OPENSSL_DEP)
diff --git a/build.yaml b/build.yaml
index 6ca2e9ebac..2f57859fc1 100644
--- a/build.yaml
+++ b/build.yaml
@@ -789,6 +789,13 @@ filegroups:
- src/cpp/ext/reflection.pb.cc
uses:
- grpc++_codegen_proto
+- name: thrift_util
+ language: c++
+ public_headers:
+ - include/grpc++/impl/codegen/thrift_serializer.h
+ - include/grpc++/impl/codegen/thrift_utils.h
+ uses:
+ - grpc++_codegen_base
libs:
- name: gpr
build: all
@@ -1031,6 +1038,7 @@ libs:
- grpc++_codegen_base_src
- grpc++_codegen_proto
- grpc++_config_proto
+ - thrift_util
- name: grpc++_unsecure
build: all
language: c++
@@ -1052,16 +1060,21 @@ libs:
language: c++
headers:
- test/cpp/util/cli_call.h
+ - test/cpp/util/cli_credentials.h
+ - test/cpp/util/config_grpc_cli.h
+ - test/cpp/util/grpc_tool.h
- test/cpp/util/proto_file_parser.h
- test/cpp/util/proto_reflection_descriptor_database.h
src:
- test/cpp/util/cli_call.cc
+ - test/cpp/util/cli_credentials.cc
+ - test/cpp/util/grpc_tool.cc
- test/cpp/util/proto_file_parser.cc
- test/cpp/util/proto_reflection_descriptor_database.cc
deps:
- grpc++_reflection
- grpc++
- - grpc_plugin_support
+ - grpc++_test_config
- name: grpc_plugin_support
build: protoc
language: c++
@@ -2711,12 +2724,9 @@ targets:
- test/cpp/util/grpc_cli.cc
deps:
- grpc_cli_libs
- - grpc++_test_util
- - grpc_test_util
- grpc++_reflection
- grpc++
- grpc
- - gpr_test_util
- gpr
- grpc++_test_config
- name: grpc_cpp_plugin
@@ -2778,6 +2788,28 @@ targets:
secure: false
vs_config_type: Application
vs_project_guid: '{069E9D05-B78B-4751-9252-D21EBAE7DE8E}'
+- name: grpc_tool_test
+ gtest: true
+ build: test
+ language: c++
+ headers:
+ - test/cpp/util/string_ref_helper.h
+ src:
+ - src/proto/grpc/testing/echo.proto
+ - src/proto/grpc/testing/echo_messages.proto
+ - test/cpp/util/grpc_tool_test.cc
+ - test/cpp/util/string_ref_helper.cc
+ deps:
+ - grpc_cli_libs
+ - grpc++_reflection
+ - grpc_test_util
+ - grpc++
+ - grpc
+ - gpr_test_util
+ - gpr
+ filegroups:
+ - grpc++_codegen_proto
+ - grpc++_config_proto
- name: grpclb_api_test
gtest: true
build: test
diff --git a/examples/cpp/cpptutorial.md b/examples/cpp/cpptutorial.md
index de7e4b2636..ae84aba916 100644
--- a/examples/cpp/cpptutorial.md
+++ b/examples/cpp/cpptutorial.md
@@ -127,7 +127,7 @@ Next we need to generate the gRPC client and server interfaces from our `.proto`
service definition. We do this using the protocol buffer compiler `protoc` with
a special gRPC C++ plugin.
-For simplicity, we've provided a [makefile](route_guide/Makefile) that runs
+For simplicity, we've provided a [Makefile](route_guide/Makefile) that runs
`protoc` for you with the appropriate plugin, input, and output (if you want to
run this yourself, make sure you've installed protoc and followed the gRPC code
[installation instructions](../../INSTALL.md) first):
diff --git a/examples/csharp/helloworld-from-cli/Greeter/Helloworld.cs b/examples/csharp/helloworld-from-cli/Greeter/Helloworld.cs
new file mode 100644
index 0000000000..6477b4f35b
--- /dev/null
+++ b/examples/csharp/helloworld-from-cli/Greeter/Helloworld.cs
@@ -0,0 +1,259 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: helloworld.proto
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Helloworld {
+
+ /// <summary>Holder for reflection information generated from helloworld.proto</summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class HelloworldReflection {
+
+ #region Descriptor
+ /// <summary>File descriptor for helloworld.proto</summary>
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static HelloworldReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChBoZWxsb3dvcmxkLnByb3RvEgpoZWxsb3dvcmxkIhwKDEhlbGxvUmVxdWVz",
+ "dBIMCgRuYW1lGAEgASgJIh0KCkhlbGxvUmVwbHkSDwoHbWVzc2FnZRgBIAEo",
+ "CTJJCgdHcmVldGVyEj4KCFNheUhlbGxvEhguaGVsbG93b3JsZC5IZWxsb1Jl",
+ "cXVlc3QaFi5oZWxsb3dvcmxkLkhlbGxvUmVwbHkiAEI2Chtpby5ncnBjLmV4",
+ "YW1wbGVzLmhlbGxvd29ybGRCD0hlbGxvV29ybGRQcm90b1ABogIDSExXYgZw",
+ "cm90bzM="));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
+ new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloRequest), global::Helloworld.HelloRequest.Parser, new[]{ "Name" }, null, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::Helloworld.HelloReply), global::Helloworld.HelloReply.Parser, new[]{ "Message" }, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ /// <summary>
+ /// The request message containing the user's name.
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class HelloRequest : pb::IMessage<HelloRequest> {
+ private static readonly pb::MessageParser<HelloRequest> _parser = new pb::MessageParser<HelloRequest>(() => new HelloRequest());
+ public static pb::MessageParser<HelloRequest> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public HelloRequest() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public HelloRequest(HelloRequest other) : this() {
+ name_ = other.name_;
+ }
+
+ public HelloRequest Clone() {
+ return new HelloRequest(this);
+ }
+
+ /// <summary>Field number for the "name" field.</summary>
+ public const int NameFieldNumber = 1;
+ private string name_ = "";
+ public string Name {
+ get { return name_; }
+ set {
+ name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as HelloRequest);
+ }
+
+ public bool Equals(HelloRequest other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Name != other.Name) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Name.Length != 0) hash ^= Name.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Name.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(Name);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (Name.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
+ }
+ return size;
+ }
+
+ public void MergeFrom(HelloRequest other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Name.Length != 0) {
+ Name = other.Name;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ Name = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ /// <summary>
+ /// The response message containing the greetings
+ /// </summary>
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public sealed partial class HelloReply : pb::IMessage<HelloReply> {
+ private static readonly pb::MessageParser<HelloReply> _parser = new pb::MessageParser<HelloReply>(() => new HelloReply());
+ public static pb::MessageParser<HelloReply> Parser { get { return _parser; } }
+
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::Helloworld.HelloworldReflection.Descriptor.MessageTypes[1]; }
+ }
+
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ public HelloReply() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ public HelloReply(HelloReply other) : this() {
+ message_ = other.message_;
+ }
+
+ public HelloReply Clone() {
+ return new HelloReply(this);
+ }
+
+ /// <summary>Field number for the "message" field.</summary>
+ public const int MessageFieldNumber = 1;
+ private string message_ = "";
+ public string Message {
+ get { return message_; }
+ set {
+ message_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ public override bool Equals(object other) {
+ return Equals(other as HelloReply);
+ }
+
+ public bool Equals(HelloReply other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (Message != other.Message) return false;
+ return true;
+ }
+
+ public override int GetHashCode() {
+ int hash = 1;
+ if (Message.Length != 0) hash ^= Message.GetHashCode();
+ return hash;
+ }
+
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ public void WriteTo(pb::CodedOutputStream output) {
+ if (Message.Length != 0) {
+ output.WriteRawTag(10);
+ output.WriteString(Message);
+ }
+ }
+
+ public int CalculateSize() {
+ int size = 0;
+ if (Message.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
+ }
+ return size;
+ }
+
+ public void MergeFrom(HelloReply other) {
+ if (other == null) {
+ return;
+ }
+ if (other.Message.Length != 0) {
+ Message = other.Message;
+ }
+ }
+
+ public void MergeFrom(pb::CodedInputStream input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ input.SkipLastField();
+ break;
+ case 10: {
+ Message = input.ReadString();
+ break;
+ }
+ }
+ }
+ }
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/examples/csharp/helloworld-from-cli/Greeter/HelloworldGrpc.cs b/examples/csharp/helloworld-from-cli/Greeter/HelloworldGrpc.cs
new file mode 100644
index 0000000000..041f5a78d7
--- /dev/null
+++ b/examples/csharp/helloworld-from-cli/Greeter/HelloworldGrpc.cs
@@ -0,0 +1,143 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: helloworld.proto
+// Original file comments:
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+#region Designer generated code
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Helloworld {
+ /// <summary>
+ /// The greeting service definition.
+ /// </summary>
+ public static class Greeter
+ {
+ static readonly string __ServiceName = "helloworld.Greeter";
+
+ static readonly Marshaller<global::Helloworld.HelloRequest> __Marshaller_HelloRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloRequest.Parser.ParseFrom);
+ static readonly Marshaller<global::Helloworld.HelloReply> __Marshaller_HelloReply = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Helloworld.HelloReply.Parser.ParseFrom);
+
+ static readonly Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply> __Method_SayHello = new Method<global::Helloworld.HelloRequest, global::Helloworld.HelloReply>(
+ MethodType.Unary,
+ __ServiceName,
+ "SayHello",
+ __Marshaller_HelloRequest,
+ __Marshaller_HelloReply);
+
+ /// <summary>Service descriptor</summary>
+ public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+ {
+ get { return global::Helloworld.HelloworldReflection.Descriptor.Services[0]; }
+ }
+
+ /// <summary>Base class for server-side implementations of Greeter</summary>
+ public abstract class GreeterBase
+ {
+ /// <summary>
+ /// Sends a greeting
+ /// </summary>
+ public virtual global::System.Threading.Tasks.Task<global::Helloworld.HelloReply> SayHello(global::Helloworld.HelloRequest request, ServerCallContext context)
+ {
+ throw new RpcException(new Status(StatusCode.Unimplemented, ""));
+ }
+
+ }
+
+ /// <summary>Client for Greeter</summary>
+ public class GreeterClient : ClientBase<GreeterClient>
+ {
+ /// <summary>Creates a new client for Greeter</summary>
+ /// <param name="channel">The channel to use to make remote calls.</param>
+ public GreeterClient(Channel channel) : base(channel)
+ {
+ }
+ /// <summary>Creates a new client for Greeter that uses a custom <c>CallInvoker</c>.</summary>
+ /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
+ public GreeterClient(CallInvoker callInvoker) : base(callInvoker)
+ {
+ }
+ /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+ protected GreeterClient() : base()
+ {
+ }
+ /// <summary>Protected constructor to allow creation of configured clients.</summary>
+ /// <param name="configuration">The client configuration.</param>
+ protected GreeterClient(ClientBaseConfiguration configuration) : base(configuration)
+ {
+ }
+
+ /// <summary>
+ /// Sends a greeting
+ /// </summary>
+ public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return SayHello(request, new CallOptions(headers, deadline, cancellationToken));
+ }
+ /// <summary>
+ /// Sends a greeting
+ /// </summary>
+ public virtual global::Helloworld.HelloReply SayHello(global::Helloworld.HelloRequest request, CallOptions options)
+ {
+ return CallInvoker.BlockingUnaryCall(__Method_SayHello, null, options, request);
+ }
+ /// <summary>
+ /// Sends a greeting
+ /// </summary>
+ public virtual AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return SayHelloAsync(request, new CallOptions(headers, deadline, cancellationToken));
+ }
+ /// <summary>
+ /// Sends a greeting
+ /// </summary>
+ public virtual AsyncUnaryCall<global::Helloworld.HelloReply> SayHelloAsync(global::Helloworld.HelloRequest request, CallOptions options)
+ {
+ return CallInvoker.AsyncUnaryCall(__Method_SayHello, null, options, request);
+ }
+ protected override GreeterClient NewInstance(ClientBaseConfiguration configuration)
+ {
+ return new GreeterClient(configuration);
+ }
+ }
+
+ /// <summary>Creates service definition that can be registered with a server</summary>
+ public static ServerServiceDefinition BindService(GreeterBase serviceImpl)
+ {
+ return ServerServiceDefinition.CreateBuilder()
+ .AddMethod(__Method_SayHello, serviceImpl.SayHello).Build();
+ }
+
+ }
+}
+#endregion
diff --git a/examples/csharp/helloworld-from-cli/Greeter/project.json b/examples/csharp/helloworld-from-cli/Greeter/project.json
new file mode 100644
index 0000000000..8774941810
--- /dev/null
+++ b/examples/csharp/helloworld-from-cli/Greeter/project.json
@@ -0,0 +1,22 @@
+{
+ "title": "Greeter",
+ "version": "1.0.0-*",
+ "buildOptions": {
+ "debugType": "portable",
+ },
+ "dependencies": {
+ "Google.Protobuf": "3.0.0-beta3",
+ "Grpc": "1.0.0-pre1",
+ },
+ "frameworks": {
+ "net45": {
+ "frameworkAssemblies": {
+ "System.Runtime": "",
+ "System.IO": ""
+ },
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1"
+ }
+ }
+ }
+}
diff --git a/examples/csharp/helloworld-from-cli/GreeterClient/Program.cs b/examples/csharp/helloworld-from-cli/GreeterClient/Program.cs
new file mode 100644
index 0000000000..444d473509
--- /dev/null
+++ b/examples/csharp/helloworld-from-cli/GreeterClient/Program.cs
@@ -0,0 +1,53 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+using System;
+using Grpc.Core;
+using Helloworld;
+
+namespace GreeterClient
+{
+ class Program
+ {
+ public static void Main(string[] args)
+ {
+ Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
+
+ var client = new Greeter.GreeterClient(channel);
+ String user = "you";
+
+ var reply = client.SayHello(new HelloRequest { Name = user });
+ Console.WriteLine("Greeting: " + reply.Message);
+
+ channel.ShutdownAsync().Wait();
+ Console.WriteLine("Press any key to exit...");
+ Console.ReadKey();
+ }
+ }
+}
diff --git a/examples/csharp/helloworld-from-cli/GreeterClient/project.json b/examples/csharp/helloworld-from-cli/GreeterClient/project.json
new file mode 100644
index 0000000000..c2bf694cd8
--- /dev/null
+++ b/examples/csharp/helloworld-from-cli/GreeterClient/project.json
@@ -0,0 +1,26 @@
+{
+ "title": "GreeterClient",
+ "version": "1.0.0-*",
+ "buildOptions": {
+ "debugType": "portable",
+ "emitEntryPoint": "true"
+ },
+ "dependencies": {
+ "Google.Protobuf": "3.0.0-beta3",
+ "Grpc": "1.0.0-pre1",
+ "Greeter": {
+ "target": "project"
+ }
+ },
+ "frameworks": {
+ "net45": {
+ "frameworkAssemblies": {
+ "System.Runtime": "",
+ "System.IO": ""
+ },
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1"
+ }
+ }
+ }
+}
diff --git a/examples/csharp/helloworld-from-cli/GreeterServer/Program.cs b/examples/csharp/helloworld-from-cli/GreeterServer/Program.cs
new file mode 100644
index 0000000000..fdab379e81
--- /dev/null
+++ b/examples/csharp/helloworld-from-cli/GreeterServer/Program.cs
@@ -0,0 +1,66 @@
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+using System;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Helloworld;
+
+namespace GreeterServer
+{
+ class GreeterImpl : Greeter.GreeterBase
+ {
+ // Server side handler of the SayHello RPC
+ public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
+ {
+ return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
+ }
+ }
+
+ class Program
+ {
+ const int Port = 50051;
+
+ public static void Main(string[] args)
+ {
+ Server server = new Server
+ {
+ Services = { Greeter.BindService(new GreeterImpl()) },
+ Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
+ };
+ server.Start();
+
+ Console.WriteLine("Greeter server listening on port " + Port);
+ Console.WriteLine("Press any key to stop the server...");
+ Console.ReadKey();
+
+ server.ShutdownAsync().Wait();
+ }
+ }
+}
diff --git a/examples/csharp/helloworld-from-cli/GreeterServer/project.json b/examples/csharp/helloworld-from-cli/GreeterServer/project.json
new file mode 100644
index 0000000000..29a10670f4
--- /dev/null
+++ b/examples/csharp/helloworld-from-cli/GreeterServer/project.json
@@ -0,0 +1,26 @@
+{
+ "title": "GreeterServer",
+ "version": "1.0.0-*",
+ "buildOptions": {
+ "debugType": "portable",
+ "emitEntryPoint": "true"
+ },
+ "dependencies": {
+ "Google.Protobuf": "3.0.0-beta3",
+ "Grpc": "1.0.0-pre1",
+ "Greeter": {
+ "target": "project"
+ }
+ },
+ "frameworks": {
+ "net45": {
+ "frameworkAssemblies": {
+ "System.Runtime": "",
+ "System.IO": ""
+ },
+ "dependencies": {
+ "Microsoft.NETCore.Platforms": "1.0.1"
+ }
+ }
+ }
+}
diff --git a/examples/csharp/helloworld-from-cli/README.md b/examples/csharp/helloworld-from-cli/README.md
new file mode 100644
index 0000000000..4db077631d
--- /dev/null
+++ b/examples/csharp/helloworld-from-cli/README.md
@@ -0,0 +1,59 @@
+gRPC in 3 minutes (C#)
+========================
+
+BACKGROUND
+-------------
+This is a different version of the helloworld example, using the dotnet sdk
+tools to build and run.
+
+For this sample, we've already generated the server and client stubs from [helloworld.proto][].
+
+Example projects in this directory depend on the [Grpc](https://www.nuget.org/packages/Grpc/)
+and [Google.Protobuf](https://www.nuget.org/packages/Google.Protobuf/) NuGet packages
+which have been already added to the project for you.
+
+The examples in this directory target .NET 4.5 framework, as .NET Core support is
+currently experimental.
+
+PREREQUISITES
+-------------
+
+- The DotNetCore SDK cli.
+
+- The .NET 4.5 framework.
+
+Both are available to download at https://www.microsoft.com/net/download
+
+BUILD
+-------
+
+From the `examples/csharp/helloworld-from-cli` directory:
+
+- `dotnet restore`
+
+- `dotnet build **/project.json` (this will automatically download NuGet dependencies)
+
+Try it!
+-------
+
+- Run the server
+
+ ```
+ > cd GreeterServer
+ > dotnet run
+ ```
+
+- Run the client
+
+ ```
+ > cd GreeterClient
+ > dotnet run
+ ```
+
+Tutorial
+--------
+
+You can find a more detailed tutorial about Grpc in [gRPC Basics: C#][]
+
+[helloworld.proto]:../../protos/helloworld.proto
+[gRPC Basics: C#]:http://www.grpc.io/docs/tutorials/basic/csharp.html
diff --git a/examples/csharp/helloworld/README.md b/examples/csharp/helloworld/README.md
index d13c9ac9db..71840ad48b 100644
--- a/examples/csharp/helloworld/README.md
+++ b/examples/csharp/helloworld/README.md
@@ -13,7 +13,7 @@ PREREQUISITES
-------------
- Windows: .NET Framework 4.5+, Visual Studio 2013 or 2015
-- Linux: Mono 4+, MonoDevelop 5.9+ (with NuGet add-in installed)
+- Linux: Mono 4+, MonoDevelop 5.9+
- Mac OS X: Xamarin Studio 5.9+
BUILD
@@ -21,7 +21,20 @@ BUILD
- Open solution `Greeter.sln` with Visual Studio, Monodevelop (on Linux) or Xamarin Studio (on Mac OS X)
-- Build the solution (this will automatically download NuGet dependencies)
+# Using Visual Studio
+
+* Build the solution (this will automatically download NuGet dependencies)
+
+# Using Monodevelop or Xamarin Studio
+
+The nuget add-in available for Xamarin Studio and Monodevelop IDEs is too old to
+download all of the nuget dependencies of gRPC. One alternative to is to use the dotnet command line tools instead (see [helloworld-from-cli]).
+
+Using these IDEs, a workaround is as follows:
+* Obtain a nuget executable for your platform and update it with
+ `nuget update -self`.
+* Navigate to this directory and run `nuget restore`.
+* Now that packages have been restored into their proper package folder, build the solution from your IDE.
Try it!
-------
@@ -49,5 +62,6 @@ Tutorial
You can find a more detailed tutorial in [gRPC Basics: C#][]
+[helloworld-from-cli]:../helloworld-from-cli/README.md
[helloworld.proto]:../../protos/helloworld.proto
[gRPC Basics: C#]:http://www.grpc.io/docs/tutorials/basic/csharp.html
diff --git a/examples/node/package.json b/examples/node/package.json
index 2cae031175..6317838295 100644
--- a/examples/node/package.json
+++ b/examples/node/package.json
@@ -3,8 +3,8 @@
"version": "0.1.0",
"dependencies": {
"async": "^1.5.2",
- "google-protobuf": "^3.0.0-alpha.5",
- "grpc": "^0.14.0",
+ "google-protobuf": "^3.0.0",
+ "grpc": "^1.0.0",
"lodash": "^4.6.1",
"minimist": "^1.2.0"
}
diff --git a/examples/ruby/greeter_client.rb b/examples/ruby/greeter_client.rb
index cb4aa195e7..1cdf79ebf4 100755
--- a/examples/ruby/greeter_client.rb
+++ b/examples/ruby/greeter_client.rb
@@ -38,7 +38,7 @@ lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
-require 'helloworld_services'
+require 'helloworld_services_pb'
def main
stub = Helloworld::Greeter::Stub.new('localhost:50051', :this_channel_is_insecure)
diff --git a/examples/ruby/greeter_server.rb b/examples/ruby/greeter_server.rb
index 622513d380..6d82043c52 100755
--- a/examples/ruby/greeter_server.rb
+++ b/examples/ruby/greeter_server.rb
@@ -38,7 +38,7 @@ lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
-require 'helloworld_services'
+require 'helloworld_services_pb'
# GreeterServer is simple server that implements the Helloworld Greeter server.
class GreeterServer < Helloworld::Greeter::Service
diff --git a/examples/ruby/grpc-demo.gemspec b/examples/ruby/grpc-demo.gemspec
index b1dfdae6ab..e1b77a56ac 100644
--- a/examples/ruby/grpc-demo.gemspec
+++ b/examples/ruby/grpc-demo.gemspec
@@ -3,7 +3,7 @@
Gem::Specification.new do |s|
s.name = 'grpc-demo'
- s.version = '0.11.0'
+ s.version = '1.0.0'
s.authors = ['gRPC Authors']
s.email = 'temiola@google.com'
s.homepage = 'https://github.com/grpc/grpc'
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.require_paths = ['lib']
s.platform = Gem::Platform::RUBY
- s.add_dependency 'grpc', '~> 0.11'
+ s.add_dependency 'grpc', '~> 1.0.0'
s.add_development_dependency 'bundler', '~> 1.7'
end
diff --git a/examples/ruby/lib/helloworld.rb b/examples/ruby/lib/helloworld_pb.rb
index 82bdd78e2a..82bdd78e2a 100644
--- a/examples/ruby/lib/helloworld.rb
+++ b/examples/ruby/lib/helloworld_pb.rb
diff --git a/examples/ruby/lib/helloworld_services.rb b/examples/ruby/lib/helloworld_services_pb.rb
index fbec667794..4fee0aa2a9 100644
--- a/examples/ruby/lib/helloworld_services.rb
+++ b/examples/ruby/lib/helloworld_services_pb.rb
@@ -32,7 +32,7 @@
#
require 'grpc'
-require 'helloworld'
+require 'helloworld_pb'
module Helloworld
module Greeter
diff --git a/examples/ruby/lib/route_guide.rb b/examples/ruby/lib/route_guide_pb.rb
index 424395c4f5..424395c4f5 100644
--- a/examples/ruby/lib/route_guide.rb
+++ b/examples/ruby/lib/route_guide_pb.rb
diff --git a/examples/ruby/lib/route_guide_services.rb b/examples/ruby/lib/route_guide_services_pb.rb
index d8f123dd95..d43fcc64e9 100644
--- a/examples/ruby/lib/route_guide_services.rb
+++ b/examples/ruby/lib/route_guide_services_pb.rb
@@ -32,7 +32,7 @@
#
require 'grpc'
-require 'route_guide'
+require 'route_guide_pb'
module Routeguide
module RouteGuide
diff --git a/examples/ruby/route_guide/route_guide_client.rb b/examples/ruby/route_guide/route_guide_client.rb
index e7f802c21e..330725ece0 100755
--- a/examples/ruby/route_guide/route_guide_client.rb
+++ b/examples/ruby/route_guide/route_guide_client.rb
@@ -39,7 +39,7 @@ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'multi_json'
-require 'route_guide_services'
+require 'route_guide_services_pb'
include Routeguide
diff --git a/examples/ruby/route_guide/route_guide_server.rb b/examples/ruby/route_guide/route_guide_server.rb
index bebe49b3be..a5a73a8bac 100755
--- a/examples/ruby/route_guide/route_guide_server.rb
+++ b/examples/ruby/route_guide/route_guide_server.rb
@@ -40,7 +40,7 @@ $LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'multi_json'
-require 'route_guide_services'
+require 'route_guide_services_pb'
include Routeguide
COORD_FACTOR = 1e7
diff --git a/grpc.gemspec b/grpc.gemspec
index 29d8afef9b..a7516a369f 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
s.platform = Gem::Platform::RUBY
- s.add_dependency 'google-protobuf', '~> 3.0.0.alpha.5.0.3'
+ s.add_dependency 'google-protobuf', '~> 3.0'
s.add_dependency 'googleauth', '~> 0.5.1'
s.add_development_dependency 'bundler', '~> 1.9'
diff --git a/include/grpc++/impl/codegen/thrift_serializer.h b/include/grpc++/impl/codegen/thrift_serializer.h
new file mode 100644
index 0000000000..7308a1577c
--- /dev/null
+++ b/include/grpc++/impl/codegen/thrift_serializer.h
@@ -0,0 +1,219 @@
+/*
+ *
+ * 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_IMPL_CODEGEN_THRIFT_SERIALIZER_H
+#define GRPCXX_IMPL_CODEGEN_THRIFT_SERIALIZER_H
+
+#include <grpc/impl/codegen/byte_buffer.h>
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/slice.h>
+#include <grpc/impl/codegen/slice_buffer.h>
+#include <thrift/protocol/TBinaryProtocol.h>
+#include <thrift/protocol/TCompactProtocol.h>
+#include <thrift/protocol/TProtocolException.h>
+#include <thrift/transport/TBufferTransports.h>
+#include <thrift/transport/TTransportUtils.h>
+#include <boost/make_shared.hpp>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+namespace apache {
+namespace thrift {
+namespace util {
+
+using apache::thrift::protocol::TBinaryProtocolT;
+using apache::thrift::protocol::TCompactProtocolT;
+using apache::thrift::protocol::TMessageType;
+using apache::thrift::protocol::TNetworkBigEndian;
+using apache::thrift::transport::TMemoryBuffer;
+using apache::thrift::transport::TBufferBase;
+using apache::thrift::transport::TTransport;
+
+template <typename Dummy, typename Protocol>
+class ThriftSerializer {
+ public:
+ ThriftSerializer()
+ : prepared_(false),
+ last_deserialized_(false),
+ serialize_version_(false) {}
+
+ virtual ~ThriftSerializer() {}
+
+ // Serialize the passed type into the internal buffer
+ // and returns a pointer to internal buffer and its size
+ template <typename T>
+ void Serialize(const T& fields, const uint8_t** serialized_buffer,
+ size_t* serialized_len) {
+ // prepare or reset buffer
+ if (!prepared_ || last_deserialized_) {
+ prepare();
+ } else {
+ buffer_->resetBuffer();
+ }
+ last_deserialized_ = false;
+
+ // if required serialize protocol version
+ if (serialize_version_) {
+ protocol_->writeMessageBegin("", TMessageType(0), 0);
+ }
+
+ // serialize fields into buffer
+ fields.write(protocol_.get());
+
+ // write the end of message
+ if (serialize_version_) {
+ protocol_->writeMessageEnd();
+ }
+
+ uint8_t* byte_buffer;
+ uint32_t byte_buffer_size;
+ buffer_->getBuffer(&byte_buffer, &byte_buffer_size);
+ *serialized_buffer = byte_buffer;
+ *serialized_len = byte_buffer_size;
+ }
+
+ // Serialize the passed type into the byte buffer
+ template <typename T>
+ void Serialize(const T& fields, grpc_byte_buffer** bp) {
+ const uint8_t* byte_buffer;
+ size_t byte_buffer_size;
+
+ Serialize(fields, &byte_buffer, &byte_buffer_size);
+
+ gpr_slice slice = gpr_slice_from_copied_buffer(
+ reinterpret_cast<const char*>(byte_buffer), byte_buffer_size);
+
+ *bp = grpc_raw_byte_buffer_create(&slice, 1);
+
+ gpr_slice_unref(slice);
+ }
+
+ // Deserialize the passed char array into the passed type, returns the number
+ // of bytes that have been consumed from the passed string.
+ template <typename T>
+ uint32_t Deserialize(uint8_t* serialized_buffer, size_t length, T* fields) {
+ // prepare buffer if necessary
+ if (!prepared_) {
+ prepare();
+ }
+ last_deserialized_ = true;
+
+ // reset buffer transport
+ buffer_->resetBuffer(serialized_buffer, length);
+
+ // read the protocol version if necessary
+ if (serialize_version_) {
+ std::string name = "";
+ TMessageType mt = static_cast<TMessageType>(0);
+ int32_t seq_id = 0;
+ protocol_->readMessageBegin(name, mt, seq_id);
+ }
+
+ // deserialize buffer into fields
+ uint32_t len = fields->read(protocol_.get());
+
+ // read the end of message
+ if (serialize_version_) {
+ protocol_->readMessageEnd();
+ }
+
+ return len;
+ }
+
+ // Deserialize the passed byte buffer to passed type, returns the number
+ // of bytes consumed from byte buffer
+ template <typename T>
+ uint32_t Deserialize(grpc_byte_buffer* buffer, T* msg) {
+ grpc_byte_buffer_reader reader;
+ grpc_byte_buffer_reader_init(&reader, buffer);
+
+ gpr_slice slice = grpc_byte_buffer_reader_readall(&reader);
+
+ uint32_t len =
+ Deserialize(GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice), msg);
+
+ gpr_slice_unref(slice);
+
+ grpc_byte_buffer_reader_destroy(&reader);
+
+ return len;
+ }
+
+ // set serialization version flag
+ void SetSerializeVersion(bool value) { serialize_version_ = value; }
+
+ // Set the container size limit to deserialize
+ // This function should be called after buffer_ is initialized
+ void SetContainerSizeLimit(int32_t container_limit) {
+ if (!prepared_) {
+ prepare();
+ }
+ protocol_->setContainerSizeLimit(container_limit);
+ }
+
+ // Set the string size limit to deserialize
+ // This function should be called after buffer_ is initialized
+ void SetStringSizeLimit(int32_t string_limit) {
+ if (!prepared_) {
+ prepare();
+ }
+ protocol_->setStringSizeLimit(string_limit);
+ }
+
+ private:
+ bool prepared_;
+ bool last_deserialized_;
+ boost::shared_ptr<TMemoryBuffer> buffer_;
+ std::shared_ptr<Protocol> protocol_;
+ bool serialize_version_;
+
+ void prepare() {
+ buffer_ = boost::make_shared<TMemoryBuffer>();
+ // create a protocol for the memory buffer transport
+ protocol_ = std::make_shared<Protocol>(buffer_);
+ prepared_ = true;
+ }
+
+}; // ThriftSerializer
+
+typedef ThriftSerializer<void, TBinaryProtocolT<TBufferBase, TNetworkBigEndian>>
+ ThriftSerializerBinary;
+typedef ThriftSerializer<void, TCompactProtocolT<TBufferBase>>
+ ThriftSerializerCompact;
+
+} // namespace util
+} // namespace thrift
+} // namespace apache
+
+#endif \ No newline at end of file
diff --git a/include/grpc++/impl/codegen/thrift_utils.h b/include/grpc++/impl/codegen/thrift_utils.h
new file mode 100644
index 0000000000..7d19b247f4
--- /dev/null
+++ b/include/grpc++/impl/codegen/thrift_utils.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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_IMPL_CODEGEN_THRIFT_UTILS_H
+#define GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H
+
+#include <grpc++/impl/codegen/config.h>
+#include <grpc++/impl/codegen/core_codegen_interface.h>
+#include <grpc++/impl/codegen/serialization_traits.h>
+#include <grpc++/impl/codegen/status.h>
+#include <grpc++/impl/codegen/status_code_enum.h>
+#include <grpc++/impl/codegen/thrift_serializer.h>
+#include <grpc/impl/codegen/byte_buffer.h>
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/slice.h>
+#include <grpc/impl/codegen/slice_buffer.h>
+#include <cstdint>
+#include <cstdlib>
+
+namespace grpc {
+
+using apache::thrift::util::ThriftSerializerCompact;
+
+template <class T>
+class SerializationTraits<T, typename std::enable_if<std::is_base_of<
+ apache::thrift::TBase, T>::value>::type> {
+ public:
+ static Status Serialize(const T& msg, grpc_byte_buffer** bp,
+ bool* own_buffer) {
+ *own_buffer = true;
+
+ ThriftSerializerCompact serializer;
+ serializer.Serialize(msg, bp);
+
+ return Status(StatusCode::OK, "ok");
+ }
+
+ static Status Deserialize(grpc_byte_buffer* buffer, T* msg,
+ int max_message_size) {
+ if (!buffer) {
+ return Status(StatusCode::INTERNAL, "No payload");
+ }
+
+ ThriftSerializerCompact deserializer;
+ deserializer.Deserialize(buffer, msg);
+
+ grpc_byte_buffer_destroy(buffer);
+
+ return Status(StatusCode::OK, "ok");
+ }
+};
+
+} // namespace grpc
+
+#endif // GRPCXX_IMPL_CODEGEN_THRIFT_UTILS_H
diff --git a/include/grpc++/support/byte_buffer.h b/include/grpc++/support/byte_buffer.h
index 20bd407109..01249a0b88 100644
--- a/include/grpc++/support/byte_buffer.h
+++ b/include/grpc++/support/byte_buffer.h
@@ -72,6 +72,9 @@ class ByteBuffer GRPC_FINAL {
/// Buffer size in bytes.
size_t Length() const;
+ /// Swap the state of *this and *other.
+ void Swap(ByteBuffer* other);
+
private:
friend class SerializationTraits<ByteBuffer, void>;
diff --git a/package.json b/package.json
index 0e229c9842..9afba31816 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
"devDependencies": {
"async": "^1.5.0",
"google-auth-library": "^0.9.2",
- "google-protobuf": "^3.0.0-alpha.5",
+ "google-protobuf": "^3.0.0",
"istanbul": "^0.3.21",
"jsdoc": "^3.3.2",
"jshint": "^2.5.0",
diff --git a/package.xml b/package.xml
index 38b74f526b..890cf32337 100644
--- a/package.xml
+++ b/package.xml
@@ -10,7 +10,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
- <date>2016-07-28</date>
+ <date>2016-08-09</date>
<time>16:06:07</time>
<version>
<release>1.1.0</release>
@@ -22,7 +22,7 @@
</stability>
<license>BSD</license>
<notes>
-- PHP7 Support continued, reduce code duplication #7543
+- Fixed Ubuntu compile error #7571, #7642
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@@ -1139,5 +1139,20 @@ Update to wrap gRPC C Core version 0.10.0
- PHP7 Support continued, reduce code duplication #7543
</notes>
</release>
+ <release>
+ <version>
+ <release>1.0.0RC4</release>
+ <api>1.0.0RC4</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2016-08-09</date>
+ <license>BSD</license>
+ <notes>
+- Fixed Ubuntu compile error #7571, #7642
+ </notes>
+ </release>
</changelog>
</package>
diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.c b/src/core/ext/transport/cronet/transport/cronet_transport.c
index 25d8aca250..029c15014e 100644
--- a/src/core/ext/transport/cronet/transport/cronet_transport.c
+++ b/src/core/ext/transport/cronet/transport/cronet_transport.c
@@ -46,617 +46,964 @@
#include "src/core/lib/support/string.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/transport/metadata_batch.h"
+#include "src/core/lib/transport/static_metadata.h"
#include "src/core/lib/transport/transport_impl.h"
#include "third_party/objective_c/Cronet/cronet_c_for_grpc.h"
#define GRPC_HEADER_SIZE_IN_BYTES 5
-// Global flag that gets set with GRPC_TRACE env variable
-int grpc_cronet_trace = 1;
+#define CRONET_LOG(...) \
+ do { \
+ if (grpc_cronet_trace) gpr_log(__VA_ARGS__); \
+ } while (0)
-// Cronet transport object
+/* TODO (makdharma): Hook up into the wider tracing mechanism */
+int grpc_cronet_trace = 0;
+
+enum e_op_result {
+ ACTION_TAKEN_WITH_CALLBACK,
+ ACTION_TAKEN_NO_CALLBACK,
+ NO_ACTION_POSSIBLE
+};
+
+enum e_op_id {
+ OP_SEND_INITIAL_METADATA = 0,
+ OP_SEND_MESSAGE,
+ OP_SEND_TRAILING_METADATA,
+ OP_RECV_MESSAGE,
+ OP_RECV_INITIAL_METADATA,
+ OP_RECV_TRAILING_METADATA,
+ OP_CANCEL_ERROR,
+ OP_ON_COMPLETE,
+ OP_FAILED,
+ OP_SUCCEEDED,
+ OP_CANCELED,
+ OP_RECV_MESSAGE_AND_ON_COMPLETE,
+ OP_READ_REQ_MADE,
+ OP_NUM_OPS
+};
+
+/* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */
+
+static void on_request_headers_sent(cronet_bidirectional_stream *);
+static void on_response_headers_received(
+ cronet_bidirectional_stream *,
+ const cronet_bidirectional_stream_header_array *, const char *);
+static void on_write_completed(cronet_bidirectional_stream *, const char *);
+static void on_read_completed(cronet_bidirectional_stream *, char *, int);
+static void on_response_trailers_received(
+ cronet_bidirectional_stream *,
+ const cronet_bidirectional_stream_header_array *);
+static void on_succeeded(cronet_bidirectional_stream *);
+static void on_failed(cronet_bidirectional_stream *, int);
+static void on_canceled(cronet_bidirectional_stream *);
+static cronet_bidirectional_stream_callback cronet_callbacks = {
+ on_request_headers_sent,
+ on_response_headers_received,
+ on_read_completed,
+ on_write_completed,
+ on_response_trailers_received,
+ on_succeeded,
+ on_failed,
+ on_canceled};
+
+/* Cronet transport object */
struct grpc_cronet_transport {
grpc_transport base; /* must be first element in this structure */
cronet_engine *engine;
char *host;
};
-
typedef struct grpc_cronet_transport grpc_cronet_transport;
-enum send_state {
- CRONET_SEND_IDLE = 0,
- CRONET_REQ_STARTED,
- CRONET_SEND_HEADER,
- CRONET_WRITE,
- CRONET_WRITE_COMPLETED,
+/* TODO (makdharma): reorder structure for memory efficiency per
+ http://www.catb.org/esr/structure-packing/#_structure_reordering: */
+struct read_state {
+ /* vars to store data coming from server */
+ char *read_buffer;
+ bool length_field_received;
+ int received_bytes;
+ int remaining_bytes;
+ int length_field;
+ char grpc_header_bytes[GRPC_HEADER_SIZE_IN_BYTES];
+ char *payload_field;
+ bool read_stream_closed;
+
+ /* vars for holding data destined for the application */
+ struct grpc_slice_buffer_stream sbs;
+ gpr_slice_buffer read_slice_buffer;
+
+ /* vars for trailing metadata */
+ grpc_chttp2_incoming_metadata_buffer trailing_metadata;
+ bool trailing_metadata_valid;
+
+ /* vars for initial metadata */
+ grpc_chttp2_incoming_metadata_buffer initial_metadata;
};
-enum recv_state {
- CRONET_RECV_IDLE = 0,
- CRONET_RECV_READ_LENGTH,
- CRONET_RECV_READ_DATA,
- CRONET_RECV_CLOSED,
+struct write_state {
+ char *write_buffer;
};
-static const char *recv_state_name[] = {
- "CRONET_RECV_IDLE", "CRONET_RECV_READ_LENGTH", "CRONET_RECV_READ_DATA,",
- "CRONET_RECV_CLOSED"};
+/* track state of one stream op */
+struct op_state {
+ bool state_op_done[OP_NUM_OPS];
+ bool state_callback_received[OP_NUM_OPS];
+ /* data structure for storing data coming from server */
+ struct read_state rs;
+ /* data structure for storing data going to the server */
+ struct write_state ws;
+};
-// Enum that identifies calling function.
-enum e_caller {
- PERFORM_STREAM_OP,
- ON_READ_COMPLETE,
- ON_RESPONSE_HEADERS_RECEIVED,
- ON_RESPONSE_TRAILERS_RECEIVED
+struct op_and_state {
+ grpc_transport_stream_op op;
+ struct op_state state;
+ bool done;
+ struct stream_obj *s; /* Pointer back to the stream object */
+ struct op_and_state *next; /* next op_and_state in the linked list */
};
-enum callback_id {
- CB_SEND_INITIAL_METADATA = 0,
- CB_SEND_MESSAGE,
- CB_SEND_TRAILING_METADATA,
- CB_RECV_MESSAGE,
- CB_RECV_INITIAL_METADATA,
- CB_RECV_TRAILING_METADATA,
- CB_NUM_CALLBACKS
+struct op_storage {
+ int num_pending_ops;
+ struct op_and_state *head;
};
struct stream_obj {
- // we store received bytes here as they trickle in.
- gpr_slice_buffer write_slice_buffer;
+ struct op_and_state *oas;
+ grpc_transport_stream_op *curr_op;
+ grpc_cronet_transport curr_ct;
+ grpc_stream *curr_gs;
cronet_bidirectional_stream *cbs;
- gpr_slice slice;
- gpr_slice_buffer read_slice_buffer;
- struct grpc_slice_buffer_stream sbs;
- char *read_buffer;
- int remaining_read_bytes;
- int total_read_bytes;
-
- char *write_buffer;
- size_t write_buffer_size;
-
- // Hold the URL
- char *url;
-
- bool response_headers_received;
- bool read_requested;
- bool response_trailers_received;
- bool read_closed;
-
- // Recv message stuff
- grpc_byte_buffer **recv_message;
- // Initial metadata stuff
- grpc_metadata_batch *recv_initial_metadata;
- // Trailing metadata stuff
- grpc_metadata_batch *recv_trailing_metadata;
- grpc_chttp2_incoming_metadata_buffer imb;
-
- // This mutex protects receive state machine execution
- gpr_mu recv_mu;
- // we can queue up up to 2 callbacks for each OP
- grpc_closure *callback_list[CB_NUM_CALLBACKS][2];
-
- // storage for header
- cronet_bidirectional_stream_header *headers;
- uint32_t num_headers;
cronet_bidirectional_stream_header_array header_array;
- // state tracking
- enum recv_state cronet_recv_state;
- enum send_state cronet_send_state;
-};
-typedef struct stream_obj stream_obj;
+ /* Stream level state. Some state will be tracked both at stream and stream_op
+ * level */
+ struct op_state state;
-static void next_send_step(stream_obj *s);
-static void next_recv_step(stream_obj *s, enum e_caller caller);
+ /* OP storage */
+ struct op_storage storage;
-static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
- grpc_stream *gs, grpc_pollset *pollset) {}
+ /* Mutex to protect storage */
+ gpr_mu mu;
+};
+typedef struct stream_obj stream_obj;
-static void set_pollset_set_do_nothing(grpc_exec_ctx *exec_ctx,
- grpc_transport *gt, grpc_stream *gs,
- grpc_pollset_set *pollset_set) {}
+static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
+ struct op_and_state *oas);
-static void enqueue_callbacks(grpc_closure *callback_list[]) {
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- if (callback_list[0]) {
- grpc_exec_ctx_sched(&exec_ctx, callback_list[0], GRPC_ERROR_NONE, NULL);
- callback_list[0] = NULL;
- }
- if (callback_list[1]) {
- grpc_exec_ctx_sched(&exec_ctx, callback_list[1], GRPC_ERROR_NONE, NULL);
- callback_list[1] = NULL;
+/*
+ Utility function to translate enum into string for printing
+*/
+static const char *op_result_string(enum e_op_result i) {
+ switch (i) {
+ case ACTION_TAKEN_WITH_CALLBACK:
+ return "ACTION_TAKEN_WITH_CALLBACK";
+ case ACTION_TAKEN_NO_CALLBACK:
+ return "ACTION_TAKEN_NO_CALLBACK";
+ case NO_ACTION_POSSIBLE:
+ return "NO_ACTION_POSSIBLE";
}
- grpc_exec_ctx_finish(&exec_ctx);
+ GPR_UNREACHABLE_CODE(return "UNKNOWN");
}
-static void on_canceled(cronet_bidirectional_stream *stream) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "on_canceled %p", stream);
+static const char *op_id_string(enum e_op_id i) {
+ switch (i) {
+ case OP_SEND_INITIAL_METADATA:
+ return "OP_SEND_INITIAL_METADATA";
+ case OP_SEND_MESSAGE:
+ return "OP_SEND_MESSAGE";
+ case OP_SEND_TRAILING_METADATA:
+ return "OP_SEND_TRAILING_METADATA";
+ case OP_RECV_MESSAGE:
+ return "OP_RECV_MESSAGE";
+ case OP_RECV_INITIAL_METADATA:
+ return "OP_RECV_INITIAL_METADATA";
+ case OP_RECV_TRAILING_METADATA:
+ return "OP_RECV_TRAILING_METADATA";
+ case OP_CANCEL_ERROR:
+ return "OP_CANCEL_ERROR";
+ case OP_ON_COMPLETE:
+ return "OP_ON_COMPLETE";
+ case OP_FAILED:
+ return "OP_FAILED";
+ case OP_SUCCEEDED:
+ return "OP_SUCCEEDED";
+ case OP_CANCELED:
+ return "OP_CANCELED";
+ case OP_RECV_MESSAGE_AND_ON_COMPLETE:
+ return "OP_RECV_MESSAGE_AND_ON_COMPLETE";
+ case OP_READ_REQ_MADE:
+ return "OP_READ_REQ_MADE";
+ case OP_NUM_OPS:
+ return "OP_NUM_OPS";
}
+ return "UNKNOWN";
}
-static void on_failed(cronet_bidirectional_stream *stream, int net_error) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "on_failed %p, error = %d", stream, net_error);
- }
+/*
+ Add a new stream op to op storage.
+*/
+static void add_to_storage(struct stream_obj *s, grpc_transport_stream_op *op) {
+ struct op_storage *storage = &s->storage;
+ /* add new op at the beginning of the linked list. The memory is freed
+ in remove_from_storage */
+ struct op_and_state *new_op = gpr_malloc(sizeof(struct op_and_state));
+ memcpy(&new_op->op, op, sizeof(grpc_transport_stream_op));
+ memset(&new_op->state, 0, sizeof(new_op->state));
+ new_op->s = s;
+ new_op->done = false;
+ gpr_mu_lock(&s->mu);
+ new_op->next = storage->head;
+ storage->head = new_op;
+ storage->num_pending_ops++;
+ CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op,
+ storage->num_pending_ops);
+ gpr_mu_unlock(&s->mu);
}
-static void on_succeeded(cronet_bidirectional_stream *stream) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "on_succeeded %p", stream);
+/*
+ Traverse the linked list and delete op and free memory
+*/
+static void remove_from_storage(struct stream_obj *s,
+ struct op_and_state *oas) {
+ struct op_and_state *curr;
+ if (s->storage.head == NULL || oas == NULL) {
+ return;
}
-}
-
-static void on_response_trailers_received(
- cronet_bidirectional_stream *stream,
- const cronet_bidirectional_stream_header_array *trailers) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: on_response_trailers_received");
+ if (s->storage.head == oas) {
+ s->storage.head = oas->next;
+ gpr_free(oas);
+ s->storage.num_pending_ops--;
+ CRONET_LOG(GPR_DEBUG, "Freed %p. Now %d in the queue", oas,
+ s->storage.num_pending_ops);
+ } else {
+ for (curr = s->storage.head; curr != NULL; curr = curr->next) {
+ if (curr->next == oas) {
+ curr->next = oas->next;
+ s->storage.num_pending_ops--;
+ CRONET_LOG(GPR_DEBUG, "Freed %p. Now %d in the queue", oas,
+ s->storage.num_pending_ops);
+ gpr_free(oas);
+ break;
+ } else if (curr->next == NULL) {
+ CRONET_LOG(GPR_ERROR, "Reached end of LL and did not find op to free");
+ }
+ }
}
- stream_obj *s = (stream_obj *)stream->annotation;
+}
- memset(&s->imb, 0, sizeof(s->imb));
- grpc_chttp2_incoming_metadata_buffer_init(&s->imb);
- unsigned int i = 0;
- for (i = 0; i < trailers->count; i++) {
- grpc_chttp2_incoming_metadata_buffer_add(
- &s->imb, grpc_mdelem_from_metadata_strings(
- grpc_mdstr_from_string(trailers->headers[i].key),
- grpc_mdstr_from_string(trailers->headers[i].value)));
+/*
+ Cycle through ops and try to take next action. Break when either
+ an action with callback is taken, or no action is possible.
+ This can be executed from the Cronet network thread via cronet callback
+ or on the application supplied thread via the perform_stream_op function.
+*/
+static void execute_from_storage(stream_obj *s) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ gpr_mu_lock(&s->mu);
+ for (struct op_and_state *curr = s->storage.head; curr != NULL;) {
+ CRONET_LOG(GPR_DEBUG, "calling op at %p. done = %d", curr, curr->done);
+ GPR_ASSERT(curr->done == 0);
+ enum e_op_result result = execute_stream_op(&exec_ctx, curr);
+ CRONET_LOG(GPR_DEBUG, "execute_stream_op[%p] returns %s", curr,
+ op_result_string(result));
+ /* if this op is done, then remove it and free memory */
+ if (curr->done) {
+ struct op_and_state *next = curr->next;
+ remove_from_storage(s, curr);
+ curr = next;
+ }
+ /* continue processing the same op if ACTION_TAKEN_WITHOUT_CALLBACK */
+ if (result == NO_ACTION_POSSIBLE) {
+ curr = curr->next;
+ } else if (result == ACTION_TAKEN_WITH_CALLBACK) {
+ break;
+ }
}
- s->response_trailers_received = true;
- next_recv_step(s, ON_RESPONSE_TRAILERS_RECEIVED);
+ gpr_mu_unlock(&s->mu);
+ grpc_exec_ctx_finish(&exec_ctx);
}
-static void on_write_completed(cronet_bidirectional_stream *stream,
- const char *data) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "W: on_write_completed");
- }
+/*
+ Cronet callback
+*/
+static void on_failed(cronet_bidirectional_stream *stream, int net_error) {
+ CRONET_LOG(GPR_DEBUG, "on_failed(%p, %d)", stream, net_error);
stream_obj *s = (stream_obj *)stream->annotation;
- enqueue_callbacks(s->callback_list[CB_SEND_MESSAGE]);
- s->cronet_send_state = CRONET_WRITE_COMPLETED;
- next_send_step(s);
+ cronet_bidirectional_stream_destroy(s->cbs);
+ s->state.state_callback_received[OP_FAILED] = true;
+ s->cbs = NULL;
+ if (s->header_array.headers) {
+ gpr_free(s->header_array.headers);
+ s->header_array.headers = NULL;
+ }
+ if (s->state.ws.write_buffer) {
+ gpr_free(s->state.ws.write_buffer);
+ s->state.ws.write_buffer = NULL;
+ }
+ execute_from_storage(s);
}
-static void process_recv_message(stream_obj *s, const uint8_t *recv_data) {
- gpr_slice read_data_slice = gpr_slice_malloc((uint32_t)s->total_read_bytes);
- uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice);
- if (s->total_read_bytes > 0) {
- // Only copy if there is non-zero number of bytes
- memcpy(dst_p, recv_data, (size_t)s->total_read_bytes);
- gpr_slice_buffer_add(&s->read_slice_buffer, read_data_slice);
+/*
+ Cronet callback
+*/
+static void on_canceled(cronet_bidirectional_stream *stream) {
+ CRONET_LOG(GPR_DEBUG, "on_canceled(%p)", stream);
+ stream_obj *s = (stream_obj *)stream->annotation;
+ cronet_bidirectional_stream_destroy(s->cbs);
+ s->state.state_callback_received[OP_CANCELED] = true;
+ s->cbs = NULL;
+ if (s->header_array.headers) {
+ gpr_free(s->header_array.headers);
+ s->header_array.headers = NULL;
}
- grpc_slice_buffer_stream_init(&s->sbs, &s->read_slice_buffer, 0);
- *s->recv_message = (grpc_byte_buffer *)&s->sbs;
+ if (s->state.ws.write_buffer) {
+ gpr_free(s->state.ws.write_buffer);
+ s->state.ws.write_buffer = NULL;
+ }
+ execute_from_storage(s);
}
-static int parse_grpc_header(const uint8_t *data) {
- const uint8_t *p = data + 1;
- int length = 0;
- length |= ((uint8_t)*p++) << 24;
- length |= ((uint8_t)*p++) << 16;
- length |= ((uint8_t)*p++) << 8;
- length |= ((uint8_t)*p++);
- return length;
+/*
+ Cronet callback
+*/
+static void on_succeeded(cronet_bidirectional_stream *stream) {
+ CRONET_LOG(GPR_DEBUG, "on_succeeded(%p)", stream);
+ stream_obj *s = (stream_obj *)stream->annotation;
+ cronet_bidirectional_stream_destroy(s->cbs);
+ s->state.state_callback_received[OP_SUCCEEDED] = true;
+ s->cbs = NULL;
+ execute_from_storage(s);
}
-static void on_read_completed(cronet_bidirectional_stream *stream, char *data,
- int count) {
+/*
+ Cronet callback
+*/
+static void on_request_headers_sent(cronet_bidirectional_stream *stream) {
+ CRONET_LOG(GPR_DEBUG, "W: on_request_headers_sent(%p)", stream);
stream_obj *s = (stream_obj *)stream->annotation;
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: on_read_completed count=%d, total=%d, remaining=%d",
- count, s->total_read_bytes, s->remaining_read_bytes);
- }
- if (count > 0) {
- GPR_ASSERT(s->recv_message);
- s->remaining_read_bytes -= count;
- next_recv_step(s, ON_READ_COMPLETE);
- } else {
- s->read_closed = true;
- next_recv_step(s, ON_READ_COMPLETE);
+ s->state.state_op_done[OP_SEND_INITIAL_METADATA] = true;
+ s->state.state_callback_received[OP_SEND_INITIAL_METADATA] = true;
+ /* Free the memory allocated for headers */
+ if (s->header_array.headers) {
+ gpr_free(s->header_array.headers);
+ s->header_array.headers = NULL;
}
+ execute_from_storage(s);
}
+/*
+ Cronet callback
+*/
static void on_response_headers_received(
cronet_bidirectional_stream *stream,
const cronet_bidirectional_stream_header_array *headers,
const char *negotiated_protocol) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: on_response_headers_received");
- }
+ CRONET_LOG(GPR_DEBUG, "R: on_response_headers_received(%p, %p, %s)", stream,
+ headers, negotiated_protocol);
stream_obj *s = (stream_obj *)stream->annotation;
- enqueue_callbacks(s->callback_list[CB_RECV_INITIAL_METADATA]);
- s->response_headers_received = true;
- next_recv_step(s, ON_RESPONSE_HEADERS_RECEIVED);
-}
-
-static void on_request_headers_sent(cronet_bidirectional_stream *stream) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "W: on_request_headers_sent");
+ memset(&s->state.rs.initial_metadata, 0,
+ sizeof(s->state.rs.initial_metadata));
+ grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.initial_metadata);
+ for (size_t i = 0; i < headers->count; i++) {
+ grpc_chttp2_incoming_metadata_buffer_add(
+ &s->state.rs.initial_metadata,
+ grpc_mdelem_from_metadata_strings(
+ grpc_mdstr_from_string(headers->headers[i].key),
+ grpc_mdstr_from_string(headers->headers[i].value)));
}
- stream_obj *s = (stream_obj *)stream->annotation;
- enqueue_callbacks(s->callback_list[CB_SEND_INITIAL_METADATA]);
- s->cronet_send_state = CRONET_SEND_HEADER;
- next_send_step(s);
+ s->state.state_callback_received[OP_RECV_INITIAL_METADATA] = true;
+ execute_from_storage(s);
}
-// Callback function pointers (invoked by cronet in response to events)
-static cronet_bidirectional_stream_callback callbacks = {
- on_request_headers_sent,
- on_response_headers_received,
- on_read_completed,
- on_write_completed,
- on_response_trailers_received,
- on_succeeded,
- on_failed,
- on_canceled};
-
-static void invoke_closing_callback(stream_obj *s) {
- grpc_chttp2_incoming_metadata_buffer_publish(&s->imb,
- s->recv_trailing_metadata);
- if (s->callback_list[CB_RECV_TRAILING_METADATA]) {
- enqueue_callbacks(s->callback_list[CB_RECV_TRAILING_METADATA]);
+/*
+ Cronet callback
+*/
+static void on_write_completed(cronet_bidirectional_stream *stream,
+ const char *data) {
+ stream_obj *s = (stream_obj *)stream->annotation;
+ CRONET_LOG(GPR_DEBUG, "W: on_write_completed(%p, %s)", stream, data);
+ if (s->state.ws.write_buffer) {
+ gpr_free(s->state.ws.write_buffer);
+ s->state.ws.write_buffer = NULL;
}
+ s->state.state_callback_received[OP_SEND_MESSAGE] = true;
+ execute_from_storage(s);
}
-static void set_recv_state(stream_obj *s, enum recv_state state) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "next_state = %s", recv_state_name[state]);
+/*
+ Cronet callback
+*/
+static void on_read_completed(cronet_bidirectional_stream *stream, char *data,
+ int count) {
+ stream_obj *s = (stream_obj *)stream->annotation;
+ CRONET_LOG(GPR_DEBUG, "R: on_read_completed(%p, %p, %d)", stream, data,
+ count);
+ s->state.state_callback_received[OP_RECV_MESSAGE] = true;
+ if (count > 0) {
+ s->state.rs.received_bytes += count;
+ s->state.rs.remaining_bytes -= count;
+ if (s->state.rs.remaining_bytes > 0) {
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs);
+ s->state.state_op_done[OP_READ_REQ_MADE] = true;
+ cronet_bidirectional_stream_read(
+ s->cbs, s->state.rs.read_buffer + s->state.rs.received_bytes,
+ s->state.rs.remaining_bytes);
+ } else {
+ execute_from_storage(s);
+ }
+ } else {
+ s->state.rs.read_stream_closed = true;
+ execute_from_storage(s);
}
- s->cronet_recv_state = state;
}
-// This is invoked from perform_stream_op, and all on_xxxx callbacks.
-static void next_recv_step(stream_obj *s, enum e_caller caller) {
- gpr_mu_lock(&s->recv_mu);
- switch (s->cronet_recv_state) {
- case CRONET_RECV_IDLE:
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_IDLE");
- }
- if (caller == PERFORM_STREAM_OP ||
- caller == ON_RESPONSE_HEADERS_RECEIVED) {
- if (s->read_closed && s->response_trailers_received) {
- invoke_closing_callback(s);
- set_recv_state(s, CRONET_RECV_CLOSED);
- } else if (s->response_headers_received == true &&
- s->read_requested == true) {
- set_recv_state(s, CRONET_RECV_READ_LENGTH);
- s->total_read_bytes = s->remaining_read_bytes =
- GRPC_HEADER_SIZE_IN_BYTES;
- GPR_ASSERT(s->read_buffer);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
- }
- cronet_bidirectional_stream_read(s->cbs, s->read_buffer,
- s->remaining_read_bytes);
- }
- }
- break;
- case CRONET_RECV_READ_LENGTH:
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_LENGTH");
- }
- if (caller == ON_READ_COMPLETE) {
- if (s->read_closed) {
- invoke_closing_callback(s);
- enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
- set_recv_state(s, CRONET_RECV_CLOSED);
- } else {
- GPR_ASSERT(s->remaining_read_bytes == 0);
- set_recv_state(s, CRONET_RECV_READ_DATA);
- s->total_read_bytes = s->remaining_read_bytes =
- parse_grpc_header((const uint8_t *)s->read_buffer);
- s->read_buffer =
- gpr_realloc(s->read_buffer, (uint32_t)s->remaining_read_bytes);
- GPR_ASSERT(s->read_buffer);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
- }
- if (s->remaining_read_bytes > 0) {
- cronet_bidirectional_stream_read(s->cbs, (char *)s->read_buffer,
- s->remaining_read_bytes);
- } else {
- // Calling the closing callback directly since this is a 0 byte read
- // for an empty message.
- process_recv_message(s, NULL);
- enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
- invoke_closing_callback(s);
- set_recv_state(s, CRONET_RECV_CLOSED);
- }
- }
- }
- break;
- case CRONET_RECV_READ_DATA:
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_recv_state = CRONET_RECV_READ_DATA");
- }
- if (caller == ON_READ_COMPLETE) {
- if (s->remaining_read_bytes > 0) {
- int offset = s->total_read_bytes - s->remaining_read_bytes;
- GPR_ASSERT(s->read_buffer);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "R: cronet_bidirectional_stream_read()");
- }
- cronet_bidirectional_stream_read(
- s->cbs, (char *)s->read_buffer + offset, s->remaining_read_bytes);
- } else {
- gpr_slice_buffer_init(&s->read_slice_buffer);
- uint8_t *p = (uint8_t *)s->read_buffer;
- process_recv_message(s, p);
- set_recv_state(s, CRONET_RECV_IDLE);
- enqueue_callbacks(s->callback_list[CB_RECV_MESSAGE]);
- }
- }
- break;
- case CRONET_RECV_CLOSED:
- break;
- default:
- GPR_ASSERT(0); // Should not reach here
- break;
+/*
+ Cronet callback
+*/
+static void on_response_trailers_received(
+ cronet_bidirectional_stream *stream,
+ const cronet_bidirectional_stream_header_array *trailers) {
+ CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream,
+ trailers);
+ stream_obj *s = (stream_obj *)stream->annotation;
+ memset(&s->state.rs.trailing_metadata, 0,
+ sizeof(s->state.rs.trailing_metadata));
+ s->state.rs.trailing_metadata_valid = false;
+ grpc_chttp2_incoming_metadata_buffer_init(&s->state.rs.trailing_metadata);
+ for (size_t i = 0; i < trailers->count; i++) {
+ CRONET_LOG(GPR_DEBUG, "trailer key=%s, value=%s", trailers->headers[i].key,
+ trailers->headers[i].value);
+ grpc_chttp2_incoming_metadata_buffer_add(
+ &s->state.rs.trailing_metadata,
+ grpc_mdelem_from_metadata_strings(
+ grpc_mdstr_from_string(trailers->headers[i].key),
+ grpc_mdstr_from_string(trailers->headers[i].value)));
+ s->state.rs.trailing_metadata_valid = true;
}
- gpr_mu_unlock(&s->recv_mu);
+ s->state.state_callback_received[OP_RECV_TRAILING_METADATA] = true;
+ execute_from_storage(s);
}
-// This function takes the data from s->write_slice_buffer and assembles into
-// a contiguous byte stream with 5 byte gRPC header prepended.
-static void create_grpc_frame(stream_obj *s) {
- gpr_slice slice = gpr_slice_buffer_take_first(&s->write_slice_buffer);
- uint8_t *raw_data = GPR_SLICE_START_PTR(slice);
+/*
+ Utility function that takes the data from s->write_slice_buffer and assembles
+ into a contiguous byte stream with 5 byte gRPC header prepended.
+*/
+static void create_grpc_frame(gpr_slice_buffer *write_slice_buffer,
+ char **pp_write_buffer,
+ size_t *p_write_buffer_size) {
+ gpr_slice slice = gpr_slice_buffer_take_first(write_slice_buffer);
size_t length = GPR_SLICE_LENGTH(slice);
- s->write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES;
- s->write_buffer = gpr_realloc(s->write_buffer, s->write_buffer_size);
- uint8_t *p = (uint8_t *)s->write_buffer;
- // Append 5 byte header
+ *p_write_buffer_size = length + GRPC_HEADER_SIZE_IN_BYTES;
+ /* This is freed in the on_write_completed callback */
+ char *write_buffer = gpr_malloc(length + GRPC_HEADER_SIZE_IN_BYTES);
+ *pp_write_buffer = write_buffer;
+ uint8_t *p = (uint8_t *)write_buffer;
+ /* Append 5 byte header */
*p++ = 0;
*p++ = (uint8_t)(length >> 24);
*p++ = (uint8_t)(length >> 16);
*p++ = (uint8_t)(length >> 8);
*p++ = (uint8_t)(length);
- // append actual data
- memcpy(p, raw_data, length);
+ /* append actual data */
+ memcpy(p, GPR_SLICE_START_PTR(slice), length);
}
-static void do_write(stream_obj *s) {
- gpr_slice_buffer *sb = &s->write_slice_buffer;
- GPR_ASSERT(sb->count <= 1);
- if (sb->count > 0) {
- create_grpc_frame(s);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write");
- }
- cronet_bidirectional_stream_write(s->cbs, s->write_buffer,
- (int)s->write_buffer_size, false);
- }
-}
-
-//
-static void next_send_step(stream_obj *s) {
- switch (s->cronet_send_state) {
- case CRONET_SEND_IDLE:
- GPR_ASSERT(
- s->cbs); // cronet_bidirectional_stream is not initialized yet.
- s->cronet_send_state = CRONET_REQ_STARTED;
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_start to %s", s->url);
- }
- cronet_bidirectional_stream_start(s->cbs, s->url, 0, "POST",
- &s->header_array, false);
- // we no longer need the memory that was allocated earlier.
- gpr_free(s->header_array.headers);
- break;
- case CRONET_SEND_HEADER:
- do_write(s);
- s->cronet_send_state = CRONET_WRITE;
- break;
- case CRONET_WRITE_COMPLETED:
- do_write(s);
- break;
- default:
- GPR_ASSERT(0);
- break;
- }
-}
-
-static void convert_metadata_to_cronet_headers(grpc_linked_mdelem *head,
- const char *host,
- stream_obj *s) {
+/*
+ Convert metadata in a format that Cronet can consume
+*/
+static void convert_metadata_to_cronet_headers(
+ grpc_linked_mdelem *head, const char *host, char **pp_url,
+ cronet_bidirectional_stream_header **pp_headers, size_t *p_num_headers) {
grpc_linked_mdelem *curr = head;
- // Walk the linked list and get number of header fields
- uint32_t num_headers_available = 0;
+ /* Walk the linked list and get number of header fields */
+ size_t num_headers_available = 0;
while (curr != NULL) {
curr = curr->next;
num_headers_available++;
}
- // Allocate enough memory
- s->headers = (cronet_bidirectional_stream_header *)gpr_malloc(
- sizeof(cronet_bidirectional_stream_header) * num_headers_available);
-
- // Walk the linked list again, this time copying the header fields.
- // s->num_headers
- // can be less than num_headers_available, as some headers are not used for
- // cronet
+ /* Allocate enough memory. It is freed in the on_request_headers_sent callback
+ */
+ cronet_bidirectional_stream_header *headers =
+ (cronet_bidirectional_stream_header *)gpr_malloc(
+ sizeof(cronet_bidirectional_stream_header) * num_headers_available);
+ *pp_headers = headers;
+
+ /* Walk the linked list again, this time copying the header fields.
+ s->num_headers can be less than num_headers_available, as some headers
+ are not used for cronet.
+ TODO (makdharma): Eliminate need to traverse the LL second time for perf.
+ */
curr = head;
- s->num_headers = 0;
- while (s->num_headers < num_headers_available) {
+ size_t num_headers = 0;
+ while (num_headers < num_headers_available) {
grpc_mdelem *mdelem = curr->md;
curr = curr->next;
const char *key = grpc_mdstr_as_c_string(mdelem->key);
const char *value = grpc_mdstr_as_c_string(mdelem->value);
- if (strcmp(key, ":scheme") == 0 || strcmp(key, ":method") == 0 ||
- strcmp(key, ":authority") == 0) {
- // Cronet populates these fields on its own.
+ if (mdelem->key == GRPC_MDSTR_METHOD || mdelem->key == GRPC_MDSTR_SCHEME ||
+ mdelem->key == GRPC_MDSTR_AUTHORITY) {
+ /* Cronet populates these fields on its own */
continue;
}
- if (strcmp(key, ":path") == 0) {
- // Create URL by appending :path value to the hostname
- gpr_asprintf(&s->url, "https://%s%s", host, value);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "extracted URL = %s", s->url);
- }
+ if (mdelem->key == GRPC_MDSTR_PATH) {
+ /* Create URL by appending :path value to the hostname */
+ gpr_asprintf(pp_url, "https://%s%s", host, value);
continue;
}
- s->headers[s->num_headers].key = key;
- s->headers[s->num_headers].value = value;
- s->num_headers++;
+ CRONET_LOG(GPR_DEBUG, "header %s = %s", key, value);
+ headers[num_headers].key = key;
+ headers[num_headers].value = value;
+ num_headers++;
if (curr == NULL) {
break;
}
}
+ *p_num_headers = (size_t)num_headers;
}
-static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
- grpc_stream *gs, grpc_transport_stream_op *op) {
- grpc_cronet_transport *ct = (grpc_cronet_transport *)gt;
- GPR_ASSERT(ct->engine);
- stream_obj *s = (stream_obj *)gs;
- if (op->recv_trailing_metadata) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG,
- "perform_stream_op - recv_trailing_metadata: on_complete=%p",
- op->on_complete);
+static int parse_grpc_header(const uint8_t *data) {
+ const uint8_t *p = data + 1;
+ int length = 0;
+ length |= ((uint8_t)*p++) << 24;
+ length |= ((uint8_t)*p++) << 16;
+ length |= ((uint8_t)*p++) << 8;
+ length |= ((uint8_t)*p++);
+ return length;
+}
+
+/*
+ Op Execution: Decide if one of the actions contained in the stream op can be
+ executed. This is the heart of the state machine.
+*/
+static bool op_can_be_run(grpc_transport_stream_op *curr_op,
+ struct op_state *stream_state,
+ struct op_state *op_state, enum e_op_id op_id) {
+ bool result = true;
+ /* When call is canceled, every op can be run, except under following
+ conditions
+ */
+ bool is_canceled_of_failed = stream_state->state_op_done[OP_CANCEL_ERROR] ||
+ stream_state->state_callback_received[OP_FAILED];
+ if (is_canceled_of_failed) {
+ if (op_id == OP_SEND_INITIAL_METADATA) result = false;
+ if (op_id == OP_SEND_MESSAGE) result = false;
+ if (op_id == OP_SEND_TRAILING_METADATA) result = false;
+ if (op_id == OP_CANCEL_ERROR) result = false;
+ /* already executed */
+ if (op_id == OP_RECV_INITIAL_METADATA &&
+ stream_state->state_op_done[OP_RECV_INITIAL_METADATA])
+ result = false;
+ if (op_id == OP_RECV_MESSAGE &&
+ stream_state->state_op_done[OP_RECV_MESSAGE])
+ result = false;
+ if (op_id == OP_RECV_TRAILING_METADATA &&
+ stream_state->state_op_done[OP_RECV_TRAILING_METADATA])
+ result = false;
+ } else if (op_id == OP_SEND_INITIAL_METADATA) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_SEND_INITIAL_METADATA]) result = false;
+ } else if (op_id == OP_RECV_INITIAL_METADATA) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) result = false;
+ /* we haven't sent headers yet. */
+ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
+ result = false;
+ /* we haven't received headers yet. */
+ else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA])
+ result = false;
+ } else if (op_id == OP_SEND_MESSAGE) {
+ /* already executed (note we're checking op specific state, not stream
+ state) */
+ if (op_state->state_op_done[OP_SEND_MESSAGE]) result = false;
+ /* we haven't sent headers yet. */
+ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
+ result = false;
+ } else if (op_id == OP_RECV_MESSAGE) {
+ /* already executed */
+ if (op_state->state_op_done[OP_RECV_MESSAGE]) result = false;
+ /* we haven't received headers yet. */
+ else if (!stream_state->state_callback_received[OP_RECV_INITIAL_METADATA])
+ result = false;
+ } else if (op_id == OP_RECV_TRAILING_METADATA) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) result = false;
+ /* we have asked for but haven't received message yet. */
+ else if (stream_state->state_op_done[OP_READ_REQ_MADE] &&
+ !stream_state->state_op_done[OP_RECV_MESSAGE])
+ result = false;
+ /* we haven't received trailers yet. */
+ else if (!stream_state->state_callback_received[OP_RECV_TRAILING_METADATA])
+ result = false;
+ /* we haven't received on_succeeded yet. */
+ else if (!stream_state->state_callback_received[OP_SUCCEEDED])
+ result = false;
+ } else if (op_id == OP_SEND_TRAILING_METADATA) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_SEND_TRAILING_METADATA]) result = false;
+ /* we haven't sent initial metadata yet */
+ else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA])
+ result = false;
+ /* we haven't sent message yet */
+ else if (curr_op->send_message &&
+ !stream_state->state_op_done[OP_SEND_MESSAGE])
+ result = false;
+ /* we haven't got on_write_completed for the send yet */
+ else if (stream_state->state_op_done[OP_SEND_MESSAGE] &&
+ !stream_state->state_callback_received[OP_SEND_MESSAGE])
+ result = false;
+ } else if (op_id == OP_CANCEL_ERROR) {
+ /* already executed */
+ if (stream_state->state_op_done[OP_CANCEL_ERROR]) result = false;
+ } else if (op_id == OP_ON_COMPLETE) {
+ /* already executed (note we're checking op specific state, not stream
+ state) */
+ if (op_state->state_op_done[OP_ON_COMPLETE]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
}
- s->recv_trailing_metadata = op->recv_trailing_metadata;
- GPR_ASSERT(!s->callback_list[CB_RECV_TRAILING_METADATA][0]);
- s->callback_list[CB_RECV_TRAILING_METADATA][0] = op->on_complete;
- }
- if (op->recv_message) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "perform_stream_op - recv_message: on_complete=%p",
- op->on_complete);
+ /* Check if every op that was asked for is done. */
+ else if (curr_op->send_initial_metadata &&
+ !stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->send_message &&
+ !op_state->state_op_done[OP_SEND_MESSAGE]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->send_message &&
+ !stream_state->state_callback_received[OP_SEND_MESSAGE]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->send_trailing_metadata &&
+ !stream_state->state_op_done[OP_SEND_TRAILING_METADATA]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->recv_initial_metadata &&
+ !stream_state->state_op_done[OP_RECV_INITIAL_METADATA]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->recv_message &&
+ !stream_state->state_op_done[OP_RECV_MESSAGE]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ } else if (curr_op->recv_trailing_metadata) {
+ /* We aren't done with trailing metadata yet */
+ if (!stream_state->state_op_done[OP_RECV_TRAILING_METADATA]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ }
+ /* We've asked for actual message in an earlier op, and it hasn't been
+ delivered yet. */
+ else if (stream_state->state_op_done[OP_READ_REQ_MADE]) {
+ /* If this op is not the one asking for read, (which means some earlier
+ op has asked), and the read hasn't been delivered. */
+ if (!curr_op->recv_message &&
+ !stream_state->state_callback_received[OP_SUCCEEDED]) {
+ CRONET_LOG(GPR_DEBUG, "Because");
+ result = false;
+ }
+ }
}
- s->recv_message = (grpc_byte_buffer **)op->recv_message;
- GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][0]);
- GPR_ASSERT(!s->callback_list[CB_RECV_MESSAGE][1]);
- s->callback_list[CB_RECV_MESSAGE][0] = op->recv_message_ready;
- s->callback_list[CB_RECV_MESSAGE][1] = op->on_complete;
- s->read_requested = true;
- next_recv_step(s, PERFORM_STREAM_OP);
+ /* We should see at least one on_write_completed for the trailers that we
+ sent */
+ else if (curr_op->send_trailing_metadata &&
+ !stream_state->state_callback_received[OP_SEND_MESSAGE])
+ result = false;
}
- if (op->recv_initial_metadata) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "perform_stream_op - recv_initial_metadata:=%p",
- op->on_complete);
+ CRONET_LOG(GPR_DEBUG, "op_can_be_run %s : %s", op_id_string(op_id),
+ result ? "YES" : "NO");
+ return result;
+}
+
+/*
+ TODO (makdharma): Break down this function in smaller chunks for readability.
+*/
+static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx,
+ struct op_and_state *oas) {
+ grpc_transport_stream_op *stream_op = &oas->op;
+ struct stream_obj *s = oas->s;
+ struct op_state *stream_state = &s->state;
+ enum e_op_result result = NO_ACTION_POSSIBLE;
+ if (stream_op->send_initial_metadata &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_SEND_INITIAL_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas);
+ /* This OP is the beginning. Reset various states */
+ memset(&s->header_array, 0, sizeof(s->header_array));
+ memset(&stream_state->rs, 0, sizeof(stream_state->rs));
+ memset(&stream_state->ws, 0, sizeof(stream_state->ws));
+ memset(stream_state->state_op_done, 0, sizeof(stream_state->state_op_done));
+ memset(stream_state->state_callback_received, 0,
+ sizeof(stream_state->state_callback_received));
+ /* Start new cronet stream. It is destroyed in on_succeeded, on_canceled,
+ * on_failed */
+ GPR_ASSERT(s->cbs == NULL);
+ s->cbs = cronet_bidirectional_stream_create(s->curr_ct.engine, s->curr_gs,
+ &cronet_callbacks);
+ CRONET_LOG(GPR_DEBUG, "%p = cronet_bidirectional_stream_create()", s->cbs);
+ char *url;
+ s->header_array.headers = NULL;
+ convert_metadata_to_cronet_headers(
+ stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url,
+ &s->header_array.headers, &s->header_array.count);
+ s->header_array.capacity = s->header_array.count;
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_start(%p, %s)", s->cbs,
+ url);
+ cronet_bidirectional_stream_start(s->cbs, url, 0, "POST", &s->header_array,
+ false);
+ stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true;
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else if (stream_op->recv_initial_metadata &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_RECV_INITIAL_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas);
+ if (!stream_state->state_op_done[OP_CANCEL_ERROR]) {
+ grpc_chttp2_incoming_metadata_buffer_publish(
+ &oas->s->state.rs.initial_metadata, stream_op->recv_initial_metadata);
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+ GRPC_ERROR_NONE, NULL);
+ } else {
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_initial_metadata_ready,
+ GRPC_ERROR_CANCELLED, NULL);
}
- s->recv_initial_metadata = op->recv_initial_metadata;
- GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][0]);
- GPR_ASSERT(!s->callback_list[CB_RECV_INITIAL_METADATA][1]);
- s->callback_list[CB_RECV_INITIAL_METADATA][0] =
- op->recv_initial_metadata_ready;
- s->callback_list[CB_RECV_INITIAL_METADATA][1] = op->on_complete;
- }
- if (op->send_initial_metadata) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG,
- "perform_stream_op - send_initial_metadata: on_complete=%p",
- op->on_complete);
+ stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
+ } else if (stream_op->send_message &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_SEND_MESSAGE)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_MESSAGE", oas);
+ gpr_slice_buffer write_slice_buffer;
+ gpr_slice slice;
+ gpr_slice_buffer_init(&write_slice_buffer);
+ grpc_byte_stream_next(NULL, stream_op->send_message, &slice,
+ stream_op->send_message->length, NULL);
+ /* Check that compression flag is OFF. We don't support compression yet. */
+ if (stream_op->send_message->flags != 0) {
+ gpr_log(GPR_ERROR, "Compression is not supported");
+ GPR_ASSERT(stream_op->send_message->flags == 0);
}
- s->num_headers = 0;
- convert_metadata_to_cronet_headers(op->send_initial_metadata->list.head,
- ct->host, s);
- s->header_array.count = s->num_headers;
- s->header_array.capacity = s->num_headers;
- s->header_array.headers = s->headers;
- GPR_ASSERT(!s->callback_list[CB_SEND_INITIAL_METADATA][0]);
- s->callback_list[CB_SEND_INITIAL_METADATA][0] = op->on_complete;
- }
- if (op->send_message) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "perform_stream_op - send_message: on_complete=%p",
- op->on_complete);
+ gpr_slice_buffer_add(&write_slice_buffer, slice);
+ if (write_slice_buffer.count != 1) {
+ /* Empty request not handled yet */
+ gpr_log(GPR_ERROR, "Empty request is not supported");
+ GPR_ASSERT(write_slice_buffer.count == 1);
+ }
+ if (write_slice_buffer.count > 0) {
+ size_t write_buffer_size;
+ create_grpc_frame(&write_slice_buffer, &stream_state->ws.write_buffer,
+ &write_buffer_size);
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_write (%p, %p)",
+ s->cbs, stream_state->ws.write_buffer);
+ stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
+ cronet_bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer,
+ (int)write_buffer_size, false);
+ result = ACTION_TAKEN_WITH_CALLBACK;
}
- grpc_byte_stream_next(exec_ctx, op->send_message, &s->slice,
- op->send_message->length, NULL);
- // Check that compression flag is not ON. We don't support compression yet.
- // TODO (makdharma): add compression support
- GPR_ASSERT(op->send_message->flags == 0);
- gpr_slice_buffer_add(&s->write_slice_buffer, s->slice);
- if (s->cbs == NULL) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_bidirectional_stream_create");
+ stream_state->state_op_done[OP_SEND_MESSAGE] = true;
+ oas->state.state_op_done[OP_SEND_MESSAGE] = true;
+ } else if (stream_op->recv_message &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_RECV_MESSAGE)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_MESSAGE", oas);
+ if (stream_state->state_op_done[OP_CANCEL_ERROR]) {
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_CANCELLED, NULL);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ } else if (stream_state->rs.read_stream_closed == true) {
+ /* No more data will be received */
+ CRONET_LOG(GPR_DEBUG, "read stream closed");
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_NONE, NULL);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+ } else if (stream_state->rs.length_field_received == false) {
+ if (stream_state->rs.received_bytes == GRPC_HEADER_SIZE_IN_BYTES &&
+ stream_state->rs.remaining_bytes == 0) {
+ /* Start a read operation for data */
+ stream_state->rs.length_field_received = true;
+ stream_state->rs.length_field = stream_state->rs.remaining_bytes =
+ parse_grpc_header((const uint8_t *)stream_state->rs.read_buffer);
+ CRONET_LOG(GPR_DEBUG, "length field = %d",
+ stream_state->rs.length_field);
+ if (stream_state->rs.length_field > 0) {
+ stream_state->rs.read_buffer =
+ gpr_malloc((size_t)stream_state->rs.length_field);
+ GPR_ASSERT(stream_state->rs.read_buffer);
+ stream_state->rs.remaining_bytes = stream_state->rs.length_field;
+ stream_state->rs.received_bytes = 0;
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs);
+ stream_state->state_op_done[OP_READ_REQ_MADE] =
+ true; /* Indicates that at least one read request has been made */
+ cronet_bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
+ stream_state->rs.remaining_bytes);
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else {
+ stream_state->rs.remaining_bytes = 0;
+ CRONET_LOG(GPR_DEBUG, "read operation complete. Empty response.");
+ gpr_slice_buffer_init(&stream_state->rs.read_slice_buffer);
+ grpc_slice_buffer_stream_init(&stream_state->rs.sbs,
+ &stream_state->rs.read_slice_buffer, 0);
+ *((grpc_byte_buffer **)stream_op->recv_message) =
+ (grpc_byte_buffer *)&stream_state->rs.sbs;
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_NONE, NULL);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
+ }
+ } else if (stream_state->rs.remaining_bytes == 0) {
+ /* Start a read operation for first 5 bytes (GRPC header) */
+ stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes;
+ stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES;
+ stream_state->rs.received_bytes = 0;
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_read(%p)", s->cbs);
+ stream_state->state_op_done[OP_READ_REQ_MADE] =
+ true; /* Indicates that at least one read request has been made */
+ cronet_bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer,
+ stream_state->rs.remaining_bytes);
}
- s->cbs = cronet_bidirectional_stream_create(ct->engine, s, &callbacks);
- GPR_ASSERT(s->cbs);
- s->read_closed = false;
- s->response_trailers_received = false;
- s->response_headers_received = false;
- s->cronet_send_state = CRONET_SEND_IDLE;
- s->cronet_recv_state = CRONET_RECV_IDLE;
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else if (stream_state->rs.remaining_bytes == 0) {
+ CRONET_LOG(GPR_DEBUG, "read operation complete");
+ gpr_slice read_data_slice =
+ gpr_slice_malloc((uint32_t)stream_state->rs.length_field);
+ uint8_t *dst_p = GPR_SLICE_START_PTR(read_data_slice);
+ memcpy(dst_p, stream_state->rs.read_buffer,
+ (size_t)stream_state->rs.length_field);
+ gpr_slice_buffer_init(&stream_state->rs.read_slice_buffer);
+ gpr_slice_buffer_add(&stream_state->rs.read_slice_buffer,
+ read_data_slice);
+ grpc_slice_buffer_stream_init(&stream_state->rs.sbs,
+ &stream_state->rs.read_slice_buffer, 0);
+ *((grpc_byte_buffer **)stream_op->recv_message) =
+ (grpc_byte_buffer *)&stream_state->rs.sbs;
+ grpc_exec_ctx_sched(exec_ctx, stream_op->recv_message_ready,
+ GRPC_ERROR_NONE, NULL);
+ stream_state->state_op_done[OP_RECV_MESSAGE] = true;
+ oas->state.state_op_done[OP_RECV_MESSAGE] = true;
+ /* Clear read state of the stream, so next read op (if it were to come)
+ * will work */
+ stream_state->rs.received_bytes = stream_state->rs.remaining_bytes =
+ stream_state->rs.length_field_received = 0;
+ result = ACTION_TAKEN_NO_CALLBACK;
}
- GPR_ASSERT(!s->callback_list[CB_SEND_MESSAGE][0]);
- s->callback_list[CB_SEND_MESSAGE][0] = op->on_complete;
- next_send_step(s);
- }
- if (op->send_trailing_metadata) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG,
- "perform_stream_op - send_trailing_metadata: on_complete=%p",
- op->on_complete);
+ } else if (stream_op->recv_trailing_metadata &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_RECV_TRAILING_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas);
+ if (oas->s->state.rs.trailing_metadata_valid) {
+ grpc_chttp2_incoming_metadata_buffer_publish(
+ &oas->s->state.rs.trailing_metadata,
+ stream_op->recv_trailing_metadata);
+ stream_state->rs.trailing_metadata_valid = false;
}
- GPR_ASSERT(!s->callback_list[CB_SEND_TRAILING_METADATA][0]);
- s->callback_list[CB_SEND_TRAILING_METADATA][0] = op->on_complete;
+ stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true;
+ result = ACTION_TAKEN_NO_CALLBACK;
+ } else if (stream_op->send_trailing_metadata &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_SEND_TRAILING_METADATA)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas);
+ CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_write (%p, 0)", s->cbs);
+ stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
+ cronet_bidirectional_stream_write(s->cbs, "", 0, true);
+ stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true;
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else if (stream_op->cancel_error &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_CANCEL_ERROR)) {
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas);
+ CRONET_LOG(GPR_DEBUG, "W: cronet_bidirectional_stream_cancel(%p)", s->cbs);
if (s->cbs) {
- // Send an "empty" write to the far end to signal that we're done.
- // This will induce the server to send down trailers.
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "W: cronet_bidirectional_stream_write");
- }
- cronet_bidirectional_stream_write(s->cbs, "abc", 0, true);
- } else {
- // We never created a stream. This was probably an empty request.
- invoke_closing_callback(s);
+ cronet_bidirectional_stream_cancel(s->cbs);
}
+ stream_state->state_op_done[OP_CANCEL_ERROR] = true;
+ result = ACTION_TAKEN_WITH_CALLBACK;
+ } else if (stream_op->on_complete &&
+ op_can_be_run(stream_op, stream_state, &oas->state,
+ OP_ON_COMPLETE)) {
+ /* All actions in this stream_op are complete. Call the on_complete callback
+ */
+ CRONET_LOG(GPR_DEBUG, "running: %p OP_ON_COMPLETE", oas);
+ grpc_exec_ctx_sched(exec_ctx, stream_op->on_complete, GRPC_ERROR_NONE,
+ NULL);
+ oas->state.state_op_done[OP_ON_COMPLETE] = true;
+ oas->done = true;
+ /* reset any send message state, only if this ON_COMPLETE is about a send.
+ */
+ if (stream_op->send_message) {
+ stream_state->state_callback_received[OP_SEND_MESSAGE] = false;
+ stream_state->state_op_done[OP_SEND_MESSAGE] = false;
+ }
+ result = ACTION_TAKEN_NO_CALLBACK;
+ /* If this is the on_complete callback being called for a received message -
+ make a note */
+ if (stream_op->recv_message)
+ stream_state->state_op_done[OP_RECV_MESSAGE_AND_ON_COMPLETE] = true;
+ } else {
+ result = NO_ACTION_POSSIBLE;
}
+ return result;
}
+/*
+ Functions used by upper layers to access transport functionality.
+*/
+
static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_stream *gs, grpc_stream_refcount *refcount,
const void *server_data) {
stream_obj *s = (stream_obj *)gs;
- memset(s->callback_list, 0, sizeof(s->callback_list));
+ memset(&s->storage, 0, sizeof(s->storage));
+ s->storage.head = NULL;
+ memset(&s->state, 0, sizeof(s->state));
+ s->curr_op = NULL;
s->cbs = NULL;
- gpr_mu_init(&s->recv_mu);
- s->read_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES);
- s->write_buffer = gpr_malloc(GRPC_HEADER_SIZE_IN_BYTES);
- gpr_slice_buffer_init(&s->write_slice_buffer);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "cronet_transport - init_stream");
- }
+ memset(&s->header_array, 0, sizeof(s->header_array));
+ memset(&s->state.rs, 0, sizeof(s->state.rs));
+ memset(&s->state.ws, 0, sizeof(s->state.ws));
+ memset(s->state.state_op_done, 0, sizeof(s->state.state_op_done));
+ memset(s->state.state_callback_received, 0,
+ sizeof(s->state.state_callback_received));
+ gpr_mu_init(&s->mu);
return 0;
}
-static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
- grpc_stream *gs, void *and_free_memory) {
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "Destroy stream");
- }
+static void set_pollset_do_nothing(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_stream *gs, grpc_pollset *pollset) {}
+
+static void set_pollset_set_do_nothing(grpc_exec_ctx *exec_ctx,
+ grpc_transport *gt, grpc_stream *gs,
+ grpc_pollset_set *pollset_set) {}
+
+static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_stream *gs, grpc_transport_stream_op *op) {
+ CRONET_LOG(GPR_DEBUG, "perform_stream_op");
stream_obj *s = (stream_obj *)gs;
- s->cbs = NULL;
- gpr_free(s->read_buffer);
- gpr_free(s->write_buffer);
- gpr_free(s->url);
- gpr_mu_destroy(&s->recv_mu);
- if (and_free_memory) {
- gpr_free(and_free_memory);
- }
+ s->curr_gs = gs;
+ memcpy(&s->curr_ct, gt, sizeof(grpc_cronet_transport));
+ add_to_storage(s, op);
+ execute_from_storage(s);
}
-static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
- grpc_cronet_transport *ct = (grpc_cronet_transport *)gt;
- gpr_free(ct->host);
- if (grpc_cronet_trace) {
- gpr_log(GPR_DEBUG, "Destroy transport");
- }
+static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_stream *gs, void *and_free_memory) {}
+
+static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {}
+
+static char *get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
+ return NULL;
}
+static void perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
+ grpc_transport_op *op) {}
+
const grpc_transport_vtable grpc_cronet_vtable = {sizeof(stream_obj),
"cronet_http",
init_stream,
set_pollset_do_nothing,
set_pollset_set_do_nothing,
perform_stream_op,
- NULL,
+ perform_op,
destroy_stream,
destroy_transport,
- NULL};
+ get_peer};
diff --git a/src/cpp/util/byte_buffer.cc b/src/cpp/util/byte_buffer.cc
index c2cd20ee07..4c4772a92b 100644
--- a/src/cpp/util/byte_buffer.cc
+++ b/src/cpp/util/byte_buffer.cc
@@ -37,12 +37,19 @@
namespace grpc {
ByteBuffer::ByteBuffer(const Slice* slices, size_t nslices) {
- // TODO(yangg) maybe expose some core API to simplify this
- std::vector<gpr_slice> c_slices(nslices);
- for (size_t i = 0; i < nslices; i++) {
- c_slices[i] = slices[i].slice_;
- }
- buffer_ = grpc_raw_byte_buffer_create(c_slices.data(), nslices);
+ // The following assertions check that the representation of a grpc::Slice is
+ // identical to that of a gpr_slice: it has a gpr_slice field, and nothing
+ // else.
+ static_assert(std::is_same<decltype(slices[0].slice_), gpr_slice>::value,
+ "Slice must have same representation as gpr_slice");
+ static_assert(sizeof(Slice) == sizeof(gpr_slice),
+ "Slice must have same representation as gpr_slice");
+ // The const_cast is legal if grpc_raw_byte_buffer_create() does no more
+ // than its advertised side effect of increasing the reference count of the
+ // slices it processes, and such an increase does not affect the semantics
+ // seen by the caller of this constructor.
+ buffer_ = grpc_raw_byte_buffer_create(
+ reinterpret_cast<gpr_slice*>(const_cast<Slice*>(slices)), nslices);
}
ByteBuffer::~ByteBuffer() {
@@ -95,4 +102,10 @@ ByteBuffer& ByteBuffer::operator=(const ByteBuffer& buf) {
return *this;
}
+void ByteBuffer::Swap(ByteBuffer* other) {
+ grpc_byte_buffer* tmp = other->buffer_;
+ other->buffer_ = this->buffer_;
+ this->buffer_ = tmp;
+}
+
} // namespace grpc
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
index 1fa14fc3df..7a6955311a 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
@@ -39,30 +39,25 @@
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="System" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
+ <Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
</Reference>
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
- <Reference Include="System" />
- <Reference Include="System.Net" />
- <Reference Include="System.Net.Http" />
- <Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
index 4baed3704c..a1f5668e2e 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
@@ -15,7 +15,7 @@
<copyright>Copyright 2015, Google Inc.</copyright>
<tags>gRPC RPC Protocol HTTP/2 Auth OAuth2</tags>
<dependencies>
- <dependency id="Google.Apis.Auth" version="1.11.1" />
+ <dependency id="Google.Apis.Auth" version="1.15.0" />
<dependency id="Grpc.Core" version="$version$" />
</dependencies>
</metadata>
diff --git a/src/csharp/Grpc.Auth/packages.config b/src/csharp/Grpc.Auth/packages.config
index c20d9ceed6..738d3e6f3b 100644
--- a/src/csharp/Grpc.Auth/packages.config
+++ b/src/csharp/Grpc.Auth/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.Auth/project.json b/src/csharp/Grpc.Auth/project.json
index 6215ca3585..30f0944693 100644
--- a/src/csharp/Grpc.Auth/project.json
+++ b/src/csharp/Grpc.Auth/project.json
@@ -23,13 +23,13 @@
},
"dependencies": {
"Grpc.Core": "1.1.0-dev",
- "Google.Apis.Auth": "1.11.1"
+ "Google.Apis.Auth": "1.15.0"
},
"frameworks": {
"net45": { },
"netstandard1.5": {
"imports": [
- "net45"
+ "portable-net45"
],
"dependencies": {
"Microsoft.NETCore.Portable.Compatibility": "1.0.1",
diff --git a/src/csharp/Grpc.Core.Tests/SanityTest.cs b/src/csharp/Grpc.Core.Tests/SanityTest.cs
index df887d82b3..f1eb13dffc 100644
--- a/src/csharp/Grpc.Core.Tests/SanityTest.cs
+++ b/src/csharp/Grpc.Core.Tests/SanityTest.cs
@@ -58,9 +58,9 @@ namespace Grpc.Core.Tests
[Test]
public void TestsJsonUpToDate()
{
- Dictionary<string, List<string>> discoveredTests = DiscoverAllTestClasses();
- Dictionary<string, List<string>> testsFromFile
- = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(ReadTestsJson());
+ var discoveredTests = DiscoverAllTestClasses();
+ var testsFromFile
+ = JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(ReadTestsJson());
Assert.AreEqual(discoveredTests, testsFromFile);
}
diff --git a/src/csharp/Grpc.Examples.MathClient/project.json b/src/csharp/Grpc.Examples.MathClient/project.json
index 764a335ddf..ad319478ab 100644
--- a/src/csharp/Grpc.Examples.MathClient/project.json
+++ b/src/csharp/Grpc.Examples.MathClient/project.json
@@ -42,6 +42,11 @@
}
}
},
+ "runtimes": {
+ "win7-x64": { },
+ "debian.8-x64": { },
+ "osx.10.11-x64": { }
+ },
"dependencies": {
"Grpc.Examples": {
diff --git a/src/csharp/Grpc.Examples.MathServer/project.json b/src/csharp/Grpc.Examples.MathServer/project.json
index 764a335ddf..ad319478ab 100644
--- a/src/csharp/Grpc.Examples.MathServer/project.json
+++ b/src/csharp/Grpc.Examples.MathServer/project.json
@@ -42,6 +42,11 @@
}
}
},
+ "runtimes": {
+ "win7-x64": { },
+ "debian.8-x64": { },
+ "osx.10.11-x64": { }
+ },
"dependencies": {
"Grpc.Examples": {
diff --git a/src/csharp/Grpc.Examples/project.json b/src/csharp/Grpc.Examples/project.json
index 5329f390e4..98bd5d852c 100644
--- a/src/csharp/Grpc.Examples/project.json
+++ b/src/csharp/Grpc.Examples/project.json
@@ -20,11 +20,12 @@
"System.IO": ""
}
},
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
+ "Microsoft.NETCore.App": "1.0.0",
"NETStandard.Library": "1.6.0"
}
}
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
index 91fb3ce5bc..6816b5c5a2 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
@@ -39,30 +39,25 @@
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="System" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
+ <Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
</Reference>
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
- <Reference Include="System" />
- <Reference Include="System.Net" />
- <Reference Include="System.Net.Http" />
- <Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/packages.config b/src/csharp/Grpc.IntegrationTesting.Client/packages.config
index c20d9ceed6..738d3e6f3b 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting.Client/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
index dda26a6892..593bf0939d 100644
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/Grpc.IntegrationTesting.QpsWorker.csproj
@@ -58,7 +58,6 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
- <None Include="app.config" />
<None Include="Grpc.IntegrationTesting.QpsWorker.project.json" />
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config b/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
deleted file mode 100644
index e204447bb3..0000000000
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/app.config
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <runtime>
- <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
- <dependentAssembly>
- <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
- </dependentAssembly>
- <dependentAssembly>
- <assemblyIdentity name="Google.Apis.Core" publicKeyToken="4b01fa6e34db77ab" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-1.11.1.0" newVersion="1.11.1.0" />
- </dependentAssembly>
- </assemblyBinding>
- </runtime>
-</configuration> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
index 9afcb306b4..287950720f 100644
--- a/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json
@@ -44,6 +44,11 @@
}
}
},
+ "runtimes": {
+ "win7-x64": { },
+ "debian.8-x64": { },
+ "osx.10.11-x64": { }
+ },
"dependencies": {
"Grpc.IntegrationTesting": {
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
index f73d99dbd1..987387ca25 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
@@ -39,30 +39,25 @@
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BouncyCastle.Crypto, Version=1.7.4137.9688, Culture=neutral, PublicKeyToken=a4292a325f69b123, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
+ <Reference Include="System" />
+ <Reference Include="System.Net" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Net.Http.WebRequest" />
+ <Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Core, Version=1.11.1.0, Culture=neutral, PublicKeyToken=4b01fa6e34db77ab, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
</Reference>
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
</Reference>
- <Reference Include="System" />
- <Reference Include="System.Net" />
- <Reference Include="System.Net.Http" />
- <Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/packages.config b/src/csharp/Grpc.IntegrationTesting.Server/packages.config
index c20d9ceed6..738d3e6f3b 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting.Server/packages.config
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
index 9afcb306b4..287950720f 100644
--- a/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
+++ b/src/csharp/Grpc.IntegrationTesting.StressClient/project.json
@@ -44,6 +44,11 @@
}
}
},
+ "runtimes": {
+ "win7-x64": { },
+ "debian.8-x64": { },
+ "osx.10.11-x64": { }
+ },
"dependencies": {
"Grpc.IntegrationTesting": {
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 7512d2a5d1..e030b21eec 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -38,9 +38,6 @@
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
- <Reference Include="CommandLine">
- <HintPath>..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll</HintPath>
- </Reference>
<Reference Include="Moq">
<HintPath>..\packages\Moq.4.2.1510.2205\lib\net40\Moq.dll</HintPath>
</Reference>
@@ -51,15 +48,6 @@
<Reference Include="BouncyCastle.Crypto">
<HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
</Reference>
- <Reference Include="Google.Apis.Auth">
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices">
- <HintPath>..\packages\Google.Apis.Auth.1.11.1\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Core">
- <HintPath>..\packages\Google.Apis.Core.1.11.1\lib\net45\Google.Apis.Core.dll</HintPath>
- </Reference>
<Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0-beta3\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath>
</Reference>
@@ -75,6 +63,18 @@
<Reference Include="nunitlite">
<HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
</Reference>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ </Reference>
+ <Reference Include="CommandLineParser.Unofficial">
+ <HintPath>..\packages\CommandLineParser.Unofficial.2.0.275\lib\net45\CommandLineParser.Unofficial.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index ec407d3fcf..79fd18b6d5 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -56,24 +56,24 @@ namespace Grpc.IntegrationTesting
{
private class ClientOptions
{
- [Option("server_host", DefaultValue = "127.0.0.1")]
+ [Option("server_host", Default = "127.0.0.1")]
public string ServerHost { get; set; }
- [Option("server_host_override", DefaultValue = TestCredentials.DefaultHostOverride)]
+ [Option("server_host_override", Default = TestCredentials.DefaultHostOverride)]
public string ServerHostOverride { get; set; }
[Option("server_port", Required = true)]
public int ServerPort { get; set; }
- [Option("test_case", DefaultValue = "large_unary")]
+ [Option("test_case", Default = "large_unary")]
public string TestCase { get; set; }
// Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls)
- [Option("use_tls", DefaultValue = false)]
+ [Option("use_tls", Default = false)]
public bool? UseTls { get; set; }
// Deliberately using nullable bool type to allow --use_test_ca=true syntax (as opposed to --use_test_ca)
- [Option("use_test_ca", DefaultValue = false)]
+ [Option("use_test_ca", Default = false)]
public bool? UseTestCa { get; set; }
[Option("default_service_account", Required = false)]
@@ -84,19 +84,6 @@ namespace Grpc.IntegrationTesting
[Option("service_account_key_file", Required = false)]
public string ServiceAccountKeyFile { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- var help = new HelpText
- {
- Heading = "gRPC C# interop testing client",
- AddDashesToOption = true
- };
- help.AddPreOptionsLine("Usage:");
- help.AddOptions(this);
- return help;
- }
}
ClientOptions options;
@@ -108,14 +95,13 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
- var options = new ClientOptions();
- if (!Parser.Default.ParseArguments(args, options))
- {
- Environment.Exit(1);
- }
-
- var interopClient = new InteropClient(options);
- interopClient.Run().Wait();
+ var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
+ .WithNotParsed(errors => Environment.Exit(1))
+ .WithParsed(options =>
+ {
+ var interopClient = new InteropClient(options);
+ interopClient.Run().Wait();
+ });
}
private async Task Run()
@@ -145,26 +131,16 @@ namespace Grpc.IntegrationTesting
if (options.TestCase == "jwt_token_creds")
{
-#if !NETCOREAPP1_0
var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
Assert.IsTrue(googleCredential.IsCreateScopedRequired);
credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
if (options.TestCase == "compute_engine_creds")
{
-#if !NETCOREAPP1_0
var googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
Assert.IsFalse(googleCredential.IsCreateScopedRequired);
credentials = ChannelCredentials.Create(credentials, googleCredential.ToCallCredentials());
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
return credentials;
}
@@ -395,7 +371,6 @@ namespace Grpc.IntegrationTesting
public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string oauthScope)
{
-#if !NETCOREAPP1_0
Console.WriteLine("running oauth2_auth_token");
ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope });
string oauth2Token = await credential.GetAccessTokenForRequestAsync();
@@ -413,15 +388,10 @@ namespace Grpc.IntegrationTesting
Assert.True(oauthScope.Contains(response.OauthScope));
Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Console.WriteLine("Passed!");
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string oauthScope)
{
-#if !NETCOREAPP1_0
Console.WriteLine("running per_rpc_creds");
ITokenAccess googleCredential = await GoogleCredential.GetApplicationDefaultAsync();
@@ -435,10 +405,6 @@ namespace Grpc.IntegrationTesting
Assert.AreEqual(GetEmailFromServiceAccountFile(), response.Username);
Console.WriteLine("Passed!");
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
public static async Task RunCancelAfterBeginAsync(TestService.TestServiceClient client)
@@ -731,17 +697,12 @@ namespace Grpc.IntegrationTesting
// extracts the client_email field from service account file used for auth test cases
private static string GetEmailFromServiceAccountFile()
{
-#if !NETCOREAPP1_0
string keyFile = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
Assert.IsNotNull(keyFile);
var jobject = JObject.Parse(File.ReadAllText(keyFile));
string email = jobject.GetValue("client_email").Value<string>();
Assert.IsTrue(email.Length > 0); // spec requires nonempty client email.
return email;
-#else
- // TODO(jtattermusch): implement this
- throw new NotImplementedException("Not supported on CoreCLR yet");
-#endif
}
private static Metadata CreateTestMetadata()
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index cd47e31c2b..4118f99c2b 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -51,25 +51,12 @@ namespace Grpc.IntegrationTesting
{
private class ServerOptions
{
- [Option("port", DefaultValue = 8070)]
+ [Option("port", Default = 8070)]
public int Port { get; set; }
// Deliberately using nullable bool type to allow --use_tls=true syntax (as opposed to --use_tls)
- [Option("use_tls", DefaultValue = false)]
+ [Option("use_tls", Default = false)]
public bool? UseTls { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- var help = new HelpText
- {
- Heading = "gRPC C# interop testing server",
- AddDashesToOption = true
- };
- help.AddPreOptionsLine("Usage:");
- help.AddOptions(this);
- return help;
- }
}
ServerOptions options;
@@ -81,14 +68,13 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
- var options = new ServerOptions();
- if (!Parser.Default.ParseArguments(args, options))
- {
- Environment.Exit(1);
- }
-
- var interopServer = new InteropServer(options);
- interopServer.Run();
+ var parserResult = Parser.Default.ParseArguments<ServerOptions>(args)
+ .WithNotParsed(errors => Environment.Exit(1))
+ .WithParsed(options =>
+ {
+ var interopServer = new InteropServer(options);
+ interopServer.Run();
+ });
}
private void Run()
diff --git a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
index a7c9fa894d..865556c242 100644
--- a/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
+++ b/src/csharp/Grpc.IntegrationTesting/QpsWorker.cs
@@ -52,21 +52,8 @@ namespace Grpc.IntegrationTesting
{
private class ServerOptions
{
- [Option("driver_port", DefaultValue = 0)]
+ [Option("driver_port", Default = 0)]
public int DriverPort { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- var help = new HelpText
- {
- Heading = "gRPC C# performance testing worker",
- AddDashesToOption = true
- };
- help.AddPreOptionsLine("Usage:");
- help.AddOptions(this);
- return help;
- }
}
ServerOptions options;
@@ -78,14 +65,13 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
- var options = new ServerOptions();
- if (!Parser.Default.ParseArguments(args, options))
- {
- Environment.Exit(1);
- }
-
- var workerServer = new QpsWorker(options);
- workerServer.RunAsync().Wait();
+ var parserResult = Parser.Default.ParseArguments<ServerOptions>(args)
+ .WithNotParsed((x) => Environment.Exit(1))
+ .WithParsed(options =>
+ {
+ var workerServer = new QpsWorker(options);
+ workerServer.RunAsync().Wait();
+ });
}
private async Task RunAsync()
diff --git a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
index 74ee040ae4..750613b078 100644
--- a/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/StressTestClient.cs
@@ -54,36 +54,23 @@ namespace Grpc.IntegrationTesting
private class ClientOptions
{
- [Option("server_addresses", DefaultValue = "localhost:8080")]
+ [Option("server_addresses", Default = "localhost:8080")]
public string ServerAddresses { get; set; }
- [Option("test_cases", DefaultValue = "large_unary:100")]
+ [Option("test_cases", Default = "large_unary:100")]
public string TestCases { get; set; }
- [Option("test_duration_secs", DefaultValue = -1)]
+ [Option("test_duration_secs", Default = -1)]
public int TestDurationSecs { get; set; }
- [Option("num_channels_per_server", DefaultValue = 1)]
+ [Option("num_channels_per_server", Default = 1)]
public int NumChannelsPerServer { get; set; }
- [Option("num_stubs_per_channel", DefaultValue = 1)]
+ [Option("num_stubs_per_channel", Default = 1)]
public int NumStubsPerChannel { get; set; }
- [Option("metrics_port", DefaultValue = 8081)]
+ [Option("metrics_port", Default = 8081)]
public int MetricsPort { get; set; }
-
- [HelpOption]
- public string GetUsage()
- {
- var help = new HelpText
- {
- Heading = "gRPC C# stress test client",
- AddDashesToOption = true
- };
- help.AddPreOptionsLine("Usage:");
- help.AddOptions(this);
- return help;
- }
}
ClientOptions options;
@@ -105,23 +92,21 @@ namespace Grpc.IntegrationTesting
public static void Run(string[] args)
{
- var options = new ClientOptions();
- if (!Parser.Default.ParseArguments(args, options))
- {
- Environment.Exit(1);
- }
-
- GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0);
- GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0);
+ var parserResult = Parser.Default.ParseArguments<ClientOptions>(args)
+ .WithNotParsed((x) => Environment.Exit(1))
+ .WithParsed(options => {
+ GrpcPreconditions.CheckArgument(options.NumChannelsPerServer > 0);
+ GrpcPreconditions.CheckArgument(options.NumStubsPerChannel > 0);
- var serverAddresses = options.ServerAddresses.Split(',');
- GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address");
+ var serverAddresses = options.ServerAddresses.Split(',');
+ GrpcPreconditions.CheckArgument(serverAddresses.Length > 0, "You need to provide at least one server address");
- var testCases = ParseWeightedTestCases(options.TestCases);
- GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case");
+ var testCases = ParseWeightedTestCases(options.TestCases);
+ GrpcPreconditions.CheckArgument(testCases.Count > 0, "You need to provide at least one test case");
- var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases);
- interopClient.Run().Wait();
+ var interopClient = new StressTestClient(options, serverAddresses.ToList(), testCases);
+ interopClient.Run().Wait();
+ });
}
async Task Run()
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index e6e64e6558..8bf9dd4937 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="CommandLineParser" version="1.9.71" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.11.1" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.11.1" targetFramework="net45" />
+ <package id="CommandLineParser.Unofficial" version="2.0.275" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Google.Protobuf" version="3.0.0-beta3" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.0.0" targetFramework="net45" />
<package id="Moq" version="4.2.1510.2205" targetFramework="net45" />
diff --git a/src/csharp/Grpc.IntegrationTesting/project.json b/src/csharp/Grpc.IntegrationTesting/project.json
index bb61a679c1..9d706510b2 100644
--- a/src/csharp/Grpc.IntegrationTesting/project.json
+++ b/src/csharp/Grpc.IntegrationTesting/project.json
@@ -58,7 +58,7 @@
"target": "project"
},
"Google.Protobuf": "3.0.0-beta3",
- "CommandLineParser": "1.9.71",
+ "CommandLineParser.Unofficial": "2.0.275",
"NUnit": "3.2.0",
"NUnitLite": "3.2.0-*"
},
diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index f05c0241b6..b92189c840 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -31,10 +31,7 @@
@rem Current package versions
set VERSION=1.1.0-dev
-set PROTOBUF_VERSION=3.0.0-beta3
-
-@rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well.
-set VERSION_WITH_BETA=%VERSION%-beta
+set PROTOBUF_VERSION=3.0.0
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe
@@ -58,7 +55,6 @@ xcopy /Y /I ..\..\architecture=x64,language=protoc,platform=macos\artifacts\* pr
@rem Fetch all dependencies
%NUGET% restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
-%NUGET% restore Grpc.sln || goto :error
setlocal
@@ -73,7 +69,7 @@ endlocal
%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
-%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
+%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
%NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error
%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error
diff --git a/src/node/health_check/package.json b/src/node/health_check/package.json
index 40e276055b..e673359809 100644
--- a/src/node/health_check/package.json
+++ b/src/node/health_check/package.json
@@ -15,9 +15,9 @@
}
],
"dependencies": {
- "grpc": "^0.15.0",
+ "grpc": "^1.1.0-dev",
"lodash": "^3.9.3",
- "google-protobuf": "^3.0.0-alpha.5"
+ "google-protobuf": "^3.0.0"
},
"files": [
"LICENSE",
diff --git a/src/node/tools/bin/protoc.js b/src/node/tools/bin/protoc.js
index 53fc5dc428..7f8356867a 100755
--- a/src/node/tools/bin/protoc.js
+++ b/src/node/tools/bin/protoc.js
@@ -47,7 +47,11 @@ var exe_ext = process.platform === 'win32' ? '.exe' : '';
var protoc = path.resolve(__dirname, 'protoc' + exe_ext);
-var child_process = execFile(protoc, process.argv.slice(2), function(error, stdout, stderr) {
+var plugin = path.resolve(__dirname, 'grpc_node_plugin' + exe_ext);
+
+var args = ['--plugin=protoc-gen-grpc=' + plugin].concat(process.argv.slice(2));
+
+var child_process = execFile(protoc, args, function(error, stdout, stderr) {
if (error) {
throw error;
}
diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
deleted file mode 100644
index 58abb492ce..0000000000
--- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.m
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * This test file is derived from fixture h2_ssl.c in core end2end test
- * (test/core/end2end/fixture/h2_ssl.c). The structure of the fixture is
- * preserved as much as possible
- *
- * This fixture creates a server full stack using chttp2 and a client
- * full stack using Cronet. End-to-end tests are run against this
- * configuration
- *
- */
-
-
-#import <XCTest/XCTest.h>
-#include "test/core/end2end/end2end_tests.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/host_port.h>
-#include <grpc/support/log.h>
-
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/security/credentials/credentials.h"
-#include "src/core/lib/support/env.h"
-#include "src/core/lib/support/string.h"
-#include "src/core/lib/support/tmpfile.h"
-#include "test/core/end2end/data/ssl_test_data.h"
-#include "test/core/util/port.h"
-#include "test/core/util/test_config.h"
-
-#include <grpc/grpc_cronet.h>
-#import <Cronet/Cronet.h>
-
-typedef struct fullstack_secure_fixture_data {
- char *localaddr;
-} fullstack_secure_fixture_data;
-
-static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack(
- grpc_channel_args *client_args, grpc_channel_args *server_args) {
- grpc_end2end_test_fixture f;
- int port = grpc_pick_unused_port_or_die();
- fullstack_secure_fixture_data *ffd =
- gpr_malloc(sizeof(fullstack_secure_fixture_data));
- memset(&f, 0, sizeof(f));
-
- gpr_join_host_port(&ffd->localaddr, "localhost", port);
-
- f.fixture_data = ffd;
- f.cq = grpc_completion_queue_create(NULL);
-
- return f;
-}
-
-static void process_auth_failure(void *state, grpc_auth_context *ctx,
- const grpc_metadata *md, size_t md_count,
- grpc_process_auth_metadata_done_cb cb,
- void *user_data) {
- GPR_ASSERT(state == NULL);
- cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
-}
-
-static void cronet_init_client_secure_fullstack(
- grpc_end2end_test_fixture *f, grpc_channel_args *client_args,
- cronet_engine *cronetEngine) {
- fullstack_secure_fixture_data *ffd = f->fixture_data;
- f->client =
- grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr, client_args, NULL);
- GPR_ASSERT(f->client != NULL);
-}
-
-static void chttp2_init_server_secure_fullstack(
- grpc_end2end_test_fixture *f, grpc_channel_args *server_args,
- grpc_server_credentials *server_creds) {
- fullstack_secure_fixture_data *ffd = f->fixture_data;
- if (f->server) {
- grpc_server_destroy(f->server);
- }
- f->server = grpc_server_create(server_args, NULL);
- grpc_server_register_completion_queue(f->server, f->cq, NULL);
- GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr,
- server_creds));
- grpc_server_credentials_release(server_creds);
- grpc_server_start(f->server);
-}
-
-static void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) {
- fullstack_secure_fixture_data *ffd = f->fixture_data;
- gpr_free(ffd->localaddr);
- gpr_free(ffd);
-}
-
-static void cronet_init_client_simple_ssl_secure_fullstack(
- grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
- grpc_arg ssl_name_override = {GRPC_ARG_STRING,
- GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
- {"foo.test.google.fr"}};
-
- grpc_channel_args *new_client_args =
- grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);
- [Cronet setHttp2Enabled:YES];
- [Cronet start];
- cronet_engine *cronetEngine = [Cronet getGlobalEngine];
-
- cronet_init_client_secure_fullstack(f, new_client_args, cronetEngine);
- grpc_channel_args_destroy(new_client_args);
-}
-
-static int fail_server_auth_check(grpc_channel_args *server_args) {
- size_t i;
- if (server_args == NULL) return 0;
- for (i = 0; i < server_args->num_args; i++) {
- if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) ==
- 0) {
- return 1;
- }
- }
- return 0;
-}
-
-static void chttp2_init_server_simple_ssl_secure_fullstack(
- grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
- grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key,
- test_server1_cert};
- grpc_server_credentials *ssl_creds =
- grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
- if (fail_server_auth_check(server_args)) {
- grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
- grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
- }
- chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
-}
-
-/* All test configurations */
-
-static grpc_end2end_test_config configs[] = {
- {"chttp2/simple_ssl_fullstack",
- FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
- FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
- chttp2_create_fixture_secure_fullstack,
- cronet_init_client_simple_ssl_secure_fullstack,
- chttp2_init_server_simple_ssl_secure_fullstack,
- chttp2_tear_down_secure_fullstack},
-};
-
-
-
-static char *roots_filename;
-
-@interface CoreCronetEnd2EndTests : XCTestCase
-
-@end
-
-@implementation CoreCronetEnd2EndTests
-
-
-// The setUp() function is run before the test cases run and only run once
-+ (void)setUp {
- [super setUp];
-
- FILE *roots_file;
- size_t roots_size = strlen(test_root_cert);
-
- char *argv[] = {"CoreCronetEnd2EndTests"};
- grpc_test_init(1, argv);
- grpc_end2end_tests_pre_init();
-
- /* Set the SSL roots env var. */
- roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename);
- GPR_ASSERT(roots_filename != NULL);
- GPR_ASSERT(roots_file != NULL);
- GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size);
- fclose(roots_file);
- gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename);
-
- grpc_init();
-
-}
-
-// The tearDown() function is run after all test cases finish running
-+ (void)tearDown {
- grpc_shutdown();
-
- /* Cleanup. */
- remove(roots_filename);
- gpr_free(roots_filename);
-
- [super tearDown];
-}
-
-- (void)testIndividualCase:(char*)test_case {
- char *argv[] = {"h2_ssl", test_case};
-
- for (int i = 0; i < sizeof(configs) / sizeof(*configs); i++) {
- grpc_end2end_tests(sizeof(argv) / sizeof(argv[0]), argv, configs[i]);
- }
-}
-
-// TODO(mxyan): Use NSStringFromSelector(_cmd) to acquire test name from the
-// test case method name, so that bodies of test cases can stay identical
-- (void)testBadHostname {
- [self testIndividualCase:"bad_hostname"];
-}
-
-- (void)testBinaryMetadata {
- [self testIndividualCase:"binary_metadata"];
-}
-
-- (void)testCallCreds {
- [self testIndividualCase:"call_creds"];
-}
-
-- (void)testCancelAfterAccept {
- [self testIndividualCase:"cancel_after_accept"];
-}
-
-- (void)testCancelAfterClientDone {
- [self testIndividualCase:"cancel_after_client_done"];
-}
-
-- (void)testCancelAfterInvoke {
- [self testIndividualCase:"cancel_after_invoke"];
-}
-
-- (void)testCancelBeforeInvoke {
- [self testIndividualCase:"cancel_before_invoke"];
-}
-
-- (void)testCancelInAVacuum {
- [self testIndividualCase:"cancel_in_a_vacuum"];
-}
-
-- (void)testCancelWithStatus {
- [self testIndividualCase:"cancel_with_status"];
-}
-
-- (void)testCompressedPayload {
- [self testIndividualCase:"compressed_payload"];
-}
-
-- (void)testConnectivity {
- [self testIndividualCase:"connectivity"];
-}
-
-- (void)testDefaultHost {
- [self testIndividualCase:"default_host"];
-}
-
-- (void)testDisappearingServer {
- [self testIndividualCase:"disappearing_server"];
-}
-
-- (void)testEmptyBatch {
- [self testIndividualCase:"empty_batch"];
-}
-
-- (void)testFilterCausesClose {
- [self testIndividualCase:"filter_causes_close"];
-}
-
-- (void)testGracefulServerShutdown {
- [self testIndividualCase:"graceful_server_shutdown"];
-}
-
-- (void)testHighInitialSeqno {
- [self testIndividualCase:"high_initial_seqno"];
-}
-
-- (void)testHpackSize {
- [self testIndividualCase:"hpack_size"];
-}
-
-- (void)testIdempotentRequest {
- [self testIndividualCase:"idempotent_request"];
-}
-
-- (void)testInvokeLargeRequest {
- [self testIndividualCase:"invoke_large_request"];
-}
-
-- (void)testLargeMetadata {
- [self testIndividualCase:"large_metadata"];
-}
-
-- (void)testMaxConcurrentStreams {
- [self testIndividualCase:"max_concurrent_streams"];
-}
-
-- (void)testMaxMessageLength {
- [self testIndividualCase:"max_message_length"];
-}
-
-- (void)testNegativeDeadline {
- [self testIndividualCase:"negative_deadline"];
-}
-
-- (void)testNetworkStatusChange {
- [self testIndividualCase:"network_status_change"];
-}
-
-- (void)testNoOp {
- [self testIndividualCase:"no_op"];
-}
-
-- (void)testPayload {
- [self testIndividualCase:"payload"];
-}
-
-- (void)testPing {
- [self testIndividualCase:"ping"];
-}
-
-- (void)testPingPongStreaming {
- [self testIndividualCase:"ping_pong_streaming"];
-}
-
-- (void)testRegisteredCall {
- [self testIndividualCase:"registered_call"];
-}
-
-- (void)testRequestWithFlags {
- [self testIndividualCase:"request_with_flags"];
-}
-
-- (void)testRequestWithPayload {
- [self testIndividualCase:"request_with_payload"];
-}
-
-- (void)testServerFinishesRequest {
- [self testIndividualCase:"server_finishes_request"];
-}
-
-- (void)testShutdownFinishesCalls {
- [self testIndividualCase:"shutdown_finishes_calls"];
-}
-
-- (void)testShutdownFinishesTags {
- [self testIndividualCase:"shutdown_finishes_tags"];
-}
-
-- (void)testSimpleDelayedRequest {
- [self testIndividualCase:"simple_delayed_request"];
-}
-
-- (void)testSimpleMetadata {
- [self testIndividualCase:"simple_metadata"];
-}
-
-- (void)testSimpleRequest {
- [self testIndividualCase:"simple_request"];
-}
-
-- (void)testStreamingErrorResponse {
- [self testIndividualCase:"streaming_error_response"];
-}
-
-- (void)testTrailingMetadata {
- [self testIndividualCase:"trailing_metadata"];
-}
-
-@end
diff --git a/src/php/ext/grpc/php7_wrapper.h b/src/php/ext/grpc/php7_wrapper.h
index fd8d35636f..1d7824113f 100644
--- a/src/php/ext/grpc/php7_wrapper.h
+++ b/src/php/ext/grpc/php7_wrapper.h
@@ -143,8 +143,7 @@ static inline int php_grpc_zend_hash_find(HashTable *ht, char *key, int len,
#define PHP_GRPC_RETURN_STRING(val, dup) RETURN_STRING(val)
#define PHP_GRPC_MAKE_STD_ZVAL(pzv) \
- zval _stack_zval_##pzv; \
- pzv = &(_stack_zval_##pzv)
+ pzv = (zval *)emalloc(sizeof(zval));
#define PHP_GRPC_DELREF(zv)
#define PHP_GRPC_WRAP_OBJECT_START(name) \
diff --git a/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py b/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py
index c753d6faf0..936c895bd2 100644
--- a/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py
+++ b/src/python/grpcio_tests/tests/interop/_insecure_interop_test.py
@@ -29,9 +29,10 @@
"""Insecure client-server interoperability as a unit test."""
+from concurrent import futures
import unittest
-from grpc.beta import implementations
+import grpc
from src.proto.grpc.testing import test_pb2
from tests.interop import _interop_test_case
@@ -44,14 +45,13 @@ class InsecureInteropTest(
unittest.TestCase):
def setUp(self):
- self.server = test_pb2.beta_create_TestService_server(methods.TestService())
+ self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ test_pb2.add_TestServiceServicer_to_server(
+ methods.TestService(), self.server)
port = self.server.add_insecure_port('[::]:0')
self.server.start()
- self.stub = test_pb2.beta_create_TestService_stub(
- implementations.insecure_channel('localhost', port))
-
- def tearDown(self):
- self.server.stop(0)
+ self.stub = test_pb2.TestServiceStub(
+ grpc.insecure_channel('localhost:{}'.format(port)))
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/interop/_secure_interop_test.py b/src/python/grpcio_tests/tests/interop/_secure_interop_test.py
index cb09f54a34..eaca553e1b 100644
--- a/src/python/grpcio_tests/tests/interop/_secure_interop_test.py
+++ b/src/python/grpcio_tests/tests/interop/_secure_interop_test.py
@@ -29,17 +29,16 @@
"""Secure client-server interoperability as a unit test."""
+from concurrent import futures
import unittest
-from grpc.beta import implementations
+import grpc
from src.proto.grpc.testing import test_pb2
from tests.interop import _interop_test_case
from tests.interop import methods
from tests.interop import resources
-from tests.unit.beta import test_utilities
-
_SERVER_HOST_OVERRIDE = 'foo.test.google.fr'
@@ -48,19 +47,18 @@ class SecureInteropTest(
unittest.TestCase):
def setUp(self):
- self.server = test_pb2.beta_create_TestService_server(methods.TestService())
+ self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ test_pb2.add_TestServiceServicer_to_server(
+ methods.TestService(), self.server)
port = self.server.add_secure_port(
- '[::]:0', implementations.ssl_server_credentials(
+ '[::]:0', grpc.ssl_server_credentials(
[(resources.private_key(), resources.certificate_chain())]))
self.server.start()
- self.stub = test_pb2.beta_create_TestService_stub(
- test_utilities.not_really_secure_channel(
- 'localhost', port, implementations.ssl_channel_credentials(
- resources.test_root_certificates()),
- _SERVER_HOST_OVERRIDE))
-
- def tearDown(self):
- self.server.stop(0)
+ self.stub = test_pb2.TestServiceStub(
+ grpc.secure_channel(
+ 'localhost:{}'.format(port),
+ grpc.ssl_channel_credentials(resources.test_root_certificates()),
+ (('grpc.ssl_target_name_override', _SERVER_HOST_OVERRIDE,),)))
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/interop/client.py b/src/python/grpcio_tests/tests/interop/client.py
index 8aa1ce30c1..9d61d18975 100644
--- a/src/python/grpcio_tests/tests/interop/client.py
+++ b/src/python/grpcio_tests/tests/interop/client.py
@@ -32,14 +32,12 @@
import argparse
from oauth2client import client as oauth2client_client
+import grpc
from grpc.beta import implementations
from src.proto.grpc.testing import test_pb2
from tests.interop import methods
from tests.interop import resources
-from tests.unit.beta import test_utilities
-
-_ONE_DAY_IN_SECONDS = 60 * 60 * 24
def _args():
@@ -66,41 +64,49 @@ def _args():
return parser.parse_args()
+def _application_default_credentials():
+ return oauth2client_client.GoogleCredentials.get_application_default()
+
+
def _stub(args):
+ target = '{}:{}'.format(args.server_host, args.server_port)
if args.test_case == 'oauth2_auth_token':
- creds = oauth2client_client.GoogleCredentials.get_application_default()
- scoped_creds = creds.create_scoped([args.oauth_scope])
- access_token = scoped_creds.get_access_token().access_token
- call_creds = implementations.access_token_call_credentials(access_token)
+ google_credentials = _application_default_credentials()
+ scoped_credentials = google_credentials.create_scoped([args.oauth_scope])
+ access_token = scoped_credentials.get_access_token().access_token
+ call_credentials = grpc.access_token_call_credentials(access_token)
elif args.test_case == 'compute_engine_creds':
- creds = oauth2client_client.GoogleCredentials.get_application_default()
- scoped_creds = creds.create_scoped([args.oauth_scope])
- call_creds = implementations.google_call_credentials(scoped_creds)
+ google_credentials = _application_default_credentials()
+ scoped_credentials = google_credentials.create_scoped([args.oauth_scope])
+ # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last
+ # remaining use of the Beta API.
+ call_credentials = implementations.google_call_credentials(
+ scoped_credentials)
elif args.test_case == 'jwt_token_creds':
- creds = oauth2client_client.GoogleCredentials.get_application_default()
- call_creds = implementations.google_call_credentials(creds)
+ google_credentials = _application_default_credentials()
+ # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last
+ # remaining use of the Beta API.
+ call_credentials = implementations.google_call_credentials(
+ google_credentials)
else:
- call_creds = None
+ call_credentials = None
if args.use_tls:
if args.use_test_ca:
root_certificates = resources.test_root_certificates()
else:
root_certificates = None # will load default roots.
- channel_creds = implementations.ssl_channel_credentials(root_certificates)
- if call_creds is not None:
- channel_creds = implementations.composite_channel_credentials(
- channel_creds, call_creds)
+ channel_credentials = grpc.ssl_channel_credentials(root_certificates)
+ if call_credentials is not None:
+ channel_credentials = grpc.composite_channel_credentials(
+ channel_credentials, call_credentials)
- channel = test_utilities.not_really_secure_channel(
- args.server_host, args.server_port, channel_creds,
- args.server_host_override)
- stub = test_pb2.beta_create_TestService_stub(channel)
+ channel = grpc.secure_channel(
+ target, channel_credentials,
+ (('grpc.ssl_target_name_override', args.server_host_override,),))
else:
- channel = implementations.insecure_channel(
- args.server_host, args.server_port)
- stub = test_pb2.beta_create_TestService_stub(channel)
- return stub
+ channel = grpc.insecure_channel(target)
+ return test_pb2.TestServiceStub(channel)
def _test_case_from_arg(test_case_arg):
diff --git a/src/python/grpcio_tests/tests/interop/methods.py b/src/python/grpcio_tests/tests/interop/methods.py
index 97e6c9e27e..7edd75c56c 100644
--- a/src/python/grpcio_tests/tests/interop/methods.py
+++ b/src/python/grpcio_tests/tests/interop/methods.py
@@ -29,8 +29,6 @@
"""Implementations of interoperability test methods."""
-from __future__ import print_function
-
import enum
import json
import os
@@ -41,26 +39,21 @@ from oauth2client import client as oauth2client_client
import grpc
from grpc.beta import implementations
-from grpc.beta import interfaces
-from grpc.framework.common import cardinality
-from grpc.framework.interfaces.face import face
from src.proto.grpc.testing import empty_pb2
from src.proto.grpc.testing import messages_pb2
from src.proto.grpc.testing import test_pb2
-_TIMEOUT = 7
-
-class TestService(test_pb2.BetaTestServiceServicer):
+class TestService(test_pb2.TestServiceServicer):
def EmptyCall(self, request, context):
return empty_pb2.Empty()
def UnaryCall(self, request, context):
if request.HasField('response_status'):
- context.code(request.response_status.code)
- context.details(request.response_status.message)
+ context.set_code(request.response_status.code)
+ context.set_details(request.response_status.message)
return messages_pb2.SimpleResponse(
payload=messages_pb2.Payload(
type=messages_pb2.COMPRESSABLE,
@@ -68,8 +61,8 @@ class TestService(test_pb2.BetaTestServiceServicer):
def StreamingOutputCall(self, request, context):
if request.HasField('response_status'):
- context.code(request.response_status.code)
- context.details(request.response_status.message)
+ context.set_code(request.response_status.code)
+ context.set_details(request.response_status.message)
for response_parameters in request.response_parameters:
yield messages_pb2.StreamingOutputCallResponse(
payload=messages_pb2.Payload(
@@ -79,7 +72,7 @@ class TestService(test_pb2.BetaTestServiceServicer):
def StreamingInputCall(self, request_iterator, context):
aggregate_size = 0
for request in request_iterator:
- if request.payload and request.payload.body:
+ if request.payload is not None and request.payload.body:
aggregate_size += len(request.payload.body)
return messages_pb2.StreamingInputCallResponse(
aggregated_payload_size=aggregate_size)
@@ -87,8 +80,8 @@ class TestService(test_pb2.BetaTestServiceServicer):
def FullDuplexCall(self, request_iterator, context):
for request in request_iterator:
if request.HasField('response_status'):
- context.code(request.response_status.code)
- context.details(request.response_status.message)
+ context.set_code(request.response_status.code)
+ context.set_details(request.response_status.message)
for response_parameters in request.response_parameters:
yield messages_pb2.StreamingOutputCallResponse(
payload=messages_pb2.Payload(
@@ -101,83 +94,80 @@ class TestService(test_pb2.BetaTestServiceServicer):
return self.FullDuplexCall(request_iterator, context)
-def _large_unary_common_behavior(stub, fill_username, fill_oauth_scope,
- protocol_options=None):
- with stub:
- request = messages_pb2.SimpleRequest(
- response_type=messages_pb2.COMPRESSABLE, response_size=314159,
- payload=messages_pb2.Payload(body=b'\x00' * 271828),
- fill_username=fill_username, fill_oauth_scope=fill_oauth_scope)
- response_future = stub.UnaryCall.future(request, _TIMEOUT,
- protocol_options=protocol_options)
- response = response_future.result()
- if response.payload.type is not messages_pb2.COMPRESSABLE:
- raise ValueError(
- 'response payload type is "%s"!' % type(response.payload.type))
- if len(response.payload.body) != 314159:
- raise ValueError(
- 'response body of incorrect size %d!' % len(response.payload.body))
+def _large_unary_common_behavior(
+ stub, fill_username, fill_oauth_scope, call_credentials):
+ request = messages_pb2.SimpleRequest(
+ response_type=messages_pb2.COMPRESSABLE, response_size=314159,
+ payload=messages_pb2.Payload(body=b'\x00' * 271828),
+ fill_username=fill_username, fill_oauth_scope=fill_oauth_scope)
+ response_future = stub.UnaryCall.future(
+ request, credentials=call_credentials)
+ response = response_future.result()
+ if response.payload.type is not messages_pb2.COMPRESSABLE:
+ raise ValueError(
+ 'response payload type is "%s"!' % type(response.payload.type))
+ elif len(response.payload.body) != 314159:
+ raise ValueError(
+ 'response body of incorrect size %d!' % len(response.payload.body))
+ else:
return response
def _empty_unary(stub):
- with stub:
- response = stub.EmptyCall(empty_pb2.Empty(), _TIMEOUT)
- if not isinstance(response, empty_pb2.Empty):
- raise TypeError(
- 'response is of type "%s", not empty_pb2.Empty!', type(response))
+ response = stub.EmptyCall(empty_pb2.Empty())
+ if not isinstance(response, empty_pb2.Empty):
+ raise TypeError(
+ 'response is of type "%s", not empty_pb2.Empty!', type(response))
def _large_unary(stub):
- _large_unary_common_behavior(stub, False, False)
+ _large_unary_common_behavior(stub, False, False, None)
def _client_streaming(stub):
- with stub:
- payload_body_sizes = (27182, 8, 1828, 45904)
- payloads = (
- messages_pb2.Payload(body=b'\x00' * size)
- for size in payload_body_sizes)
- requests = (
- messages_pb2.StreamingInputCallRequest(payload=payload)
- for payload in payloads)
- response = stub.StreamingInputCall(requests, _TIMEOUT)
- if response.aggregated_payload_size != 74922:
- raise ValueError(
- 'incorrect size %d!' % response.aggregated_payload_size)
+ payload_body_sizes = (27182, 8, 1828, 45904,)
+ payloads = (
+ messages_pb2.Payload(body=b'\x00' * size)
+ for size in payload_body_sizes)
+ requests = (
+ messages_pb2.StreamingInputCallRequest(payload=payload)
+ for payload in payloads)
+ response = stub.StreamingInputCall(requests)
+ if response.aggregated_payload_size != 74922:
+ raise ValueError(
+ 'incorrect size %d!' % response.aggregated_payload_size)
def _server_streaming(stub):
- sizes = (31415, 9, 2653, 58979)
-
- with stub:
- request = messages_pb2.StreamingOutputCallRequest(
- response_type=messages_pb2.COMPRESSABLE,
- response_parameters=(
- messages_pb2.ResponseParameters(size=sizes[0]),
- messages_pb2.ResponseParameters(size=sizes[1]),
- messages_pb2.ResponseParameters(size=sizes[2]),
- messages_pb2.ResponseParameters(size=sizes[3]),
- ))
- response_iterator = stub.StreamingOutputCall(request, _TIMEOUT)
- for index, response in enumerate(response_iterator):
- if response.payload.type != messages_pb2.COMPRESSABLE:
- raise ValueError(
- 'response body of invalid type %s!' % response.payload.type)
- if len(response.payload.body) != sizes[index]:
- raise ValueError(
- 'response body of invalid size %d!' % len(response.payload.body))
+ sizes = (31415, 9, 2653, 58979,)
+
+ request = messages_pb2.StreamingOutputCallRequest(
+ response_type=messages_pb2.COMPRESSABLE,
+ response_parameters=(
+ messages_pb2.ResponseParameters(size=sizes[0]),
+ messages_pb2.ResponseParameters(size=sizes[1]),
+ messages_pb2.ResponseParameters(size=sizes[2]),
+ messages_pb2.ResponseParameters(size=sizes[3]),
+ )
+ )
+ response_iterator = stub.StreamingOutputCall(request)
+ for index, response in enumerate(response_iterator):
+ if response.payload.type != messages_pb2.COMPRESSABLE:
+ raise ValueError(
+ 'response body of invalid type %s!' % response.payload.type)
+ elif len(response.payload.body) != sizes[index]:
+ raise ValueError(
+ 'response body of invalid size %d!' % len(response.payload.body))
def _cancel_after_begin(stub):
- with stub:
- sizes = (27182, 8, 1828, 45904)
- payloads = [messages_pb2.Payload(body=b'\x00' * size) for size in sizes]
- requests = [messages_pb2.StreamingInputCallRequest(payload=payload)
- for payload in payloads]
- responses = stub.StreamingInputCall.future(requests, _TIMEOUT)
- responses.cancel()
- if not responses.cancelled():
- raise ValueError('expected call to be cancelled')
+ sizes = (27182, 8, 1828, 45904,)
+ payloads = (messages_pb2.Payload(body=b'\x00' * size) for size in sizes)
+ requests = (messages_pb2.StreamingInputCallRequest(payload=payload)
+ for payload in payloads)
+ response_future = stub.StreamingInputCall.future(requests)
+ response_future.cancel()
+ if not response_future.cancelled():
+ raise ValueError('expected call to be cancelled')
class _Pipe(object):
@@ -220,18 +210,17 @@ class _Pipe(object):
def _ping_pong(stub):
- request_response_sizes = (31415, 9, 2653, 58979)
- request_payload_sizes = (27182, 8, 1828, 45904)
+ request_response_sizes = (31415, 9, 2653, 58979,)
+ request_payload_sizes = (27182, 8, 1828, 45904,)
- with stub, _Pipe() as pipe:
- response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
- print('Starting ping-pong with response iterator %s' % response_iterator)
+ with _Pipe() as pipe:
+ response_iterator = stub.FullDuplexCall(pipe)
for response_size, payload_size in zip(
request_response_sizes, request_payload_sizes):
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
- response_parameters=(messages_pb2.ResponseParameters(
- size=response_size),),
+ response_parameters=(
+ messages_pb2.ResponseParameters(size=response_size),),
payload=messages_pb2.Payload(body=b'\x00' * payload_size))
pipe.add(request)
response = next(response_iterator)
@@ -244,17 +233,17 @@ def _ping_pong(stub):
def _cancel_after_first_response(stub):
- request_response_sizes = (31415, 9, 2653, 58979)
- request_payload_sizes = (27182, 8, 1828, 45904)
- with stub, _Pipe() as pipe:
- response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
+ request_response_sizes = (31415, 9, 2653, 58979,)
+ request_payload_sizes = (27182, 8, 1828, 45904,)
+ with _Pipe() as pipe:
+ response_iterator = stub.FullDuplexCall(pipe)
response_size = request_response_sizes[0]
payload_size = request_payload_sizes[0]
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
- response_parameters=(messages_pb2.ResponseParameters(
- size=response_size),),
+ response_parameters=(
+ messages_pb2.ResponseParameters(size=response_size),),
payload=messages_pb2.Payload(body=b'\x00' * payload_size))
pipe.add(request)
response = next(response_iterator)
@@ -264,16 +253,17 @@ def _cancel_after_first_response(stub):
try:
next(response_iterator)
- except Exception:
- pass
+ except grpc.RpcError as rpc_error:
+ if rpc_error.code() is not grpc.StatusCode.CANCELLED:
+ raise
else:
raise ValueError('expected call to be cancelled')
def _timeout_on_sleeping_server(stub):
request_payload_size = 27182
- with stub, _Pipe() as pipe:
- response_iterator = stub.FullDuplexCall(pipe, 0.001)
+ with _Pipe() as pipe:
+ response_iterator = stub.FullDuplexCall(pipe, timeout=0.001)
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
@@ -282,15 +272,16 @@ def _timeout_on_sleeping_server(stub):
time.sleep(0.1)
try:
next(response_iterator)
- except face.ExpirationError:
- pass
+ except grpc.RpcError as rpc_error:
+ if rpc_error.code() is not grpc.StatusCode.DEADLINE_EXCEEDED:
+ raise
else:
raise ValueError('expected call to exceed deadline')
def _empty_stream(stub):
- with stub, _Pipe() as pipe:
- response_iterator = stub.FullDuplexCall(pipe, _TIMEOUT)
+ with _Pipe() as pipe:
+ response_iterator = stub.FullDuplexCall(pipe)
pipe.close()
try:
next(response_iterator)
@@ -300,65 +291,64 @@ def _empty_stream(stub):
def _status_code_and_message(stub):
- with stub:
- message = 'test status message'
- code = 2
- status = grpc.StatusCode.UNKNOWN # code = 2
- request = messages_pb2.SimpleRequest(
- response_type=messages_pb2.COMPRESSABLE,
- response_size=1,
- payload=messages_pb2.Payload(body=b'\x00'),
- response_status=messages_pb2.EchoStatus(code=code, message=message)
- )
- response_future = stub.UnaryCall.future(request, _TIMEOUT)
- if response_future.code() != status:
- raise ValueError(
- 'expected code %s, got %s' % (status, response_future.code()))
- if response_future.details() != message:
- raise ValueError(
- 'expected message %s, got %s' % (message, response_future.details()))
-
- request = messages_pb2.StreamingOutputCallRequest(
- response_type=messages_pb2.COMPRESSABLE,
- response_parameters=(
- messages_pb2.ResponseParameters(size=1),),
- response_status=messages_pb2.EchoStatus(code=code, message=message))
- response_iterator = stub.StreamingOutputCall(request, _TIMEOUT)
- if response_future.code() != status:
- raise ValueError(
- 'expected code %s, got %s' % (status, response_iterator.code()))
- if response_future.details() != message:
- raise ValueError(
- 'expected message %s, got %s' % (message, response_iterator.details()))
+ message = 'test status message'
+ code = 2
+ status = grpc.StatusCode.UNKNOWN # code = 2
+ request = messages_pb2.SimpleRequest(
+ response_type=messages_pb2.COMPRESSABLE,
+ response_size=1,
+ payload=messages_pb2.Payload(body=b'\x00'),
+ response_status=messages_pb2.EchoStatus(code=code, message=message)
+ )
+ response_future = stub.UnaryCall.future(request)
+ if response_future.code() != status:
+ raise ValueError(
+ 'expected code %s, got %s' % (status, response_future.code()))
+ elif response_future.details() != message:
+ raise ValueError(
+ 'expected message %s, got %s' % (message, response_future.details()))
+
+ request = messages_pb2.StreamingOutputCallRequest(
+ response_type=messages_pb2.COMPRESSABLE,
+ response_parameters=(
+ messages_pb2.ResponseParameters(size=1),),
+ response_status=messages_pb2.EchoStatus(code=code, message=message))
+ response_iterator = stub.StreamingOutputCall(request)
+ if response_future.code() != status:
+ raise ValueError(
+ 'expected code %s, got %s' % (status, response_iterator.code()))
+ elif response_future.details() != message:
+ raise ValueError(
+ 'expected message %s, got %s' % (message, response_iterator.details()))
def _compute_engine_creds(stub, args):
- response = _large_unary_common_behavior(stub, True, True)
+ response = _large_unary_common_behavior(stub, True, True, None)
if args.default_service_account != response.username:
raise ValueError(
- 'expected username %s, got %s' % (args.default_service_account,
- response.username))
+ 'expected username %s, got %s' % (
+ args.default_service_account, response.username))
def _oauth2_auth_token(stub, args):
json_key_filename = os.environ[
oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS]
wanted_email = json.load(open(json_key_filename, 'rb'))['client_email']
- response = _large_unary_common_behavior(stub, True, True)
+ response = _large_unary_common_behavior(stub, True, True, None)
if wanted_email != response.username:
raise ValueError(
'expected username %s, got %s' % (wanted_email, response.username))
if args.oauth_scope.find(response.oauth_scope) == -1:
raise ValueError(
- 'expected to find oauth scope "%s" in received "%s"' %
- (response.oauth_scope, args.oauth_scope))
+ 'expected to find oauth scope "{}" in received "{}"'.format(
+ response.oauth_scope, args.oauth_scope))
def _jwt_token_creds(stub, args):
json_key_filename = os.environ[
oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS]
wanted_email = json.load(open(json_key_filename, 'rb'))['client_email']
- response = _large_unary_common_behavior(stub, True, False)
+ response = _large_unary_common_behavior(stub, True, False, None)
if wanted_email != response.username:
raise ValueError(
'expected username %s, got %s' % (wanted_email, response.username))
@@ -370,11 +360,11 @@ def _per_rpc_creds(stub, args):
wanted_email = json.load(open(json_key_filename, 'rb'))['client_email']
credentials = oauth2client_client.GoogleCredentials.get_application_default()
scoped_credentials = credentials.create_scoped([args.oauth_scope])
- call_creds = implementations.google_call_credentials(scoped_credentials)
- options = interfaces.grpc_call_options(disable_compression=False,
- credentials=call_creds)
- response = _large_unary_common_behavior(stub, True, False,
- protocol_options=options)
+ # TODO(https://github.com/grpc/grpc/issues/6799): Eliminate this last
+ # remaining use of the Beta API.
+ call_credentials = implementations.google_call_credentials(
+ scoped_credentials)
+ response = _large_unary_common_behavior(stub, True, False, call_credentials)
if wanted_email != response.username:
raise ValueError(
'expected username %s, got %s' % (wanted_email, response.username))
diff --git a/src/python/grpcio_tests/tests/interop/server.py b/src/python/grpcio_tests/tests/interop/server.py
index ab2c3c708f..1ae83bc57d 100644
--- a/src/python/grpcio_tests/tests/interop/server.py
+++ b/src/python/grpcio_tests/tests/interop/server.py
@@ -30,10 +30,11 @@
"""The Python implementation of the GRPC interoperability test server."""
import argparse
+from concurrent import futures
import logging
import time
-from grpc.beta import implementations
+import grpc
from src.proto.grpc.testing import test_pb2
from tests.interop import methods
@@ -51,12 +52,13 @@ def serve():
default=False, type=resources.parse_bool)
args = parser.parse_args()
- server = test_pb2.beta_create_TestService_server(methods.TestService())
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ test_pb2.add_TestServiceServicer_to_server(methods.TestService(), server)
if args.use_tls:
private_key = resources.private_key()
certificate_chain = resources.certificate_chain()
- credentials = implementations.ssl_server_credentials(
- [(private_key, certificate_chain)])
+ credentials = grpc.ssl_server_credentials(
+ ((private_key, certificate_chain),))
server.add_secure_port('[::]:{}'.format(args.port), credentials)
else:
server.add_insecure_port('[::]:{}'.format(args.port))
@@ -68,7 +70,7 @@ def serve():
time.sleep(_ONE_DAY_IN_SECONDS)
except BaseException as e:
logging.info('Caught exception "%s"; stopping server...', e)
- server.stop(0)
+ server.stop(None)
logging.info('Server stopped; exiting.')
if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/stress/client.py b/src/python/grpcio_tests/tests/stress/client.py
index 0de2532cd8..975f33b4c1 100644
--- a/src/python/grpcio_tests/tests/stress/client.py
+++ b/src/python/grpcio_tests/tests/stress/client.py
@@ -30,9 +30,10 @@
"""Entry point for running stress tests."""
import argparse
+from concurrent import futures
import threading
-from grpc.beta import implementations
+import grpc
from six.moves import queue
from src.proto.grpc.testing import metrics_pb2
from src.proto.grpc.testing import test_pb2
@@ -92,24 +93,24 @@ def _parse_weighted_test_cases(test_case_args):
def run_test(args):
test_cases = _parse_weighted_test_cases(args.test_cases)
- test_servers = args.server_addresses.split(',')
+ test_server_targets = args.server_addresses.split(',')
# Propagate any client exceptions with a queue
exception_queue = queue.Queue()
stop_event = threading.Event()
hist = histogram.Histogram(1, 1)
runners = []
- server = metrics_pb2.beta_create_MetricsService_server(
- metrics_server.MetricsServer(hist))
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=25))
+ metrics_pb2.add_MetricsServiceServicer_to_server(
+ metrics_server.MetricsServer(hist), server)
server.add_insecure_port('[::]:{}'.format(args.metrics_port))
server.start()
- for test_server in test_servers:
- host, port = test_server.split(':', 1)
+ for test_server_target in test_server_targets:
for _ in xrange(args.num_channels_per_server):
- channel = implementations.insecure_channel(host, int(port))
+ channel = grpc.insecure_channel(test_server_target)
for _ in xrange(args.num_stubs_per_channel):
- stub = test_pb2.beta_create_TestService_stub(channel)
+ stub = test_pb2.TestServiceStub(channel)
runner = test_runner.TestRunner(stub, test_cases, hist,
exception_queue, stop_event)
runners.append(runner)
@@ -128,8 +129,8 @@ def run_test(args):
stop_event.set()
for runner in runners:
runner.join()
- runner = None
- server.stop(0)
+ runner = None
+ server.stop(None)
if __name__ == '__main__':
run_test(_args())
diff --git a/src/python/grpcio_tests/tests/stress/metrics_server.py b/src/python/grpcio_tests/tests/stress/metrics_server.py
index b994e4643e..33dd1d6f2a 100644
--- a/src/python/grpcio_tests/tests/stress/metrics_server.py
+++ b/src/python/grpcio_tests/tests/stress/metrics_server.py
@@ -36,7 +36,7 @@ from src.proto.grpc.testing import metrics_pb2
GAUGE_NAME = 'python_overall_qps'
-class MetricsServer(metrics_pb2.BetaMetricsServiceServicer):
+class MetricsServer(metrics_pb2.MetricsServiceServicer):
def __init__(self, histogram):
self._start_time = time.time()
diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb
index 196f84f65f..d7cd9e6df2 100644
--- a/src/ruby/lib/grpc/generic/bidi_call.rb
+++ b/src/ruby/lib/grpc/generic/bidi_call.rb
@@ -62,7 +62,6 @@ module GRPC
@call = call
@marshal = marshal
@op_notifier = nil # signals completion on clients
- @readq = Queue.new
@unmarshal = unmarshal
@metadata_received = metadata_received
@reads_complete = false
@@ -83,8 +82,7 @@ module GRPC
def run_on_client(requests, op_notifier, &blk)
@op_notifier = op_notifier
@enq_th = Thread.new { write_loop(requests) }
- @loop_th = start_read_loop
- each_queued_msg(&blk)
+ read_loop(&blk)
end
# Begins orchestration of the Bidi stream for a server generating replies.
@@ -101,14 +99,13 @@ module GRPC
def run_on_server(gen_each_reply)
# Pass in the optional call object parameter if possible
if gen_each_reply.arity == 1
- replys = gen_each_reply.call(each_queued_msg)
+ replys = gen_each_reply.call(read_loop(is_client: false))
elsif gen_each_reply.arity == 2
- replys = gen_each_reply.call(each_queued_msg, @req_view)
+ replys = gen_each_reply.call(read_loop(is_client: false), @req_view)
else
fail 'Illegal arity of reply generator'
end
- @loop_th = start_read_loop(is_client: false)
write_loop(replys, is_client: false)
end
@@ -145,24 +142,6 @@ module GRPC
batch_result
end
- # each_queued_msg yields each message on this instances readq
- #
- # - messages are added to the readq by #read_loop
- # - iteration ends when the instance itself is added
- def each_queued_msg
- return enum_for(:each_queued_msg) unless block_given?
- count = 0
- loop do
- GRPC.logger.debug("each_queued_msg: waiting##{count}")
- count += 1
- req = @readq.pop
- GRPC.logger.debug("each_queued_msg: req = #{req}")
- fail req if req.is_a? StandardError
- break if req.equal?(END_OF_READS)
- yield req
- end
- end
-
def write_loop(requests, is_client: true)
GRPC.logger.debug('bidi-write-loop: starting')
count = 0
@@ -201,47 +180,45 @@ module GRPC
raise e
end
- # starts the read loop
- def start_read_loop(is_client: true)
- Thread.new do
- GRPC.logger.debug('bidi-read-loop: starting')
- begin
- count = 0
- # queue the initial read before beginning the loop
- loop do
- GRPC.logger.debug("bidi-read-loop: #{count}")
- count += 1
- batch_result = read_using_run_batch
-
- # handle the next message
- if batch_result.message.nil?
- GRPC.logger.debug("bidi-read-loop: null batch #{batch_result}")
-
- if is_client
- batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
- @call.status = batch_result.status
- batch_result.check_status
- GRPC.logger.debug("bidi-read-loop: done status #{@call.status}")
- end
-
- @readq.push(END_OF_READS)
- GRPC.logger.debug('bidi-read-loop: done reading!')
- break
+ # Provides an enumerator that yields results of remote reads
+ def read_loop(is_client: true)
+ return enum_for(:read_loop,
+ is_client: is_client) unless block_given?
+ GRPC.logger.debug('bidi-read-loop: starting')
+ begin
+ count = 0
+ # queue the initial read before beginning the loop
+ loop do
+ GRPC.logger.debug("bidi-read-loop: #{count}")
+ count += 1
+ batch_result = read_using_run_batch
+
+ # handle the next message
+ if batch_result.message.nil?
+ GRPC.logger.debug("bidi-read-loop: null batch #{batch_result}")
+
+ if is_client
+ batch_result = @call.run_batch(RECV_STATUS_ON_CLIENT => nil)
+ @call.status = batch_result.status
+ batch_result.check_status
+ GRPC.logger.debug("bidi-read-loop: done status #{@call.status}")
end
- # push the latest read onto the queue and continue reading
- res = @unmarshal.call(batch_result.message)
- @readq.push(res)
+ GRPC.logger.debug('bidi-read-loop: done reading!')
+ break
end
- rescue StandardError => e
- GRPC.logger.warn('bidi: read-loop failed')
- GRPC.logger.warn(e)
- @readq.push(e) # let each_queued_msg terminate with this error
+
+ res = @unmarshal.call(batch_result.message)
+ yield res
end
- GRPC.logger.debug('bidi-read-loop: finished')
- @reads_complete = true
- finished
+ rescue StandardError => e
+ GRPC.logger.warn('bidi: read-loop failed')
+ GRPC.logger.warn(e)
+ raise e
end
+ GRPC.logger.debug('bidi-read-loop: finished')
+ @reads_complete = true
+ finished
end
end
end
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 9afc6566e2..6a7805cf6d 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -694,13 +694,6 @@
NO_DEPS = true
endif
- INSTALL_OK = false
- ifeq ($(HAS_VALID_PROTOC),true)
- ifeq ($(HAS_SYSTEM_PROTOBUF_VERIFY),true)
- INSTALL_OK = true
- endif
- endif
-
.SECONDARY = %.pb.h %.pb.cc
ifeq ($(DEP_MISSING),)
@@ -1193,7 +1186,7 @@
$(Q) mkdir -p `dirname $@`
$(Q) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -MMD -MF $(addsuffix .dep, $(basename $@)) -c -o $@ $<
- install: install_c install_cxx install-plugins install-certs verify-install
+ install: install_c install_cxx install-plugins install-certs
install_c: install-headers_c install-static_c install-shared_c
@@ -1311,28 +1304,6 @@
$(Q) $(INSTALL) -d $(prefix)/share/grpc
$(Q) $(INSTALL) etc/roots.pem $(prefix)/share/grpc/roots.pem
- verify-install:
- ifeq ($(INSTALL_OK),true)
- @echo "Your system looks ready to go."
- @echo
- else
- @echo "Warning: it looks like protoc 3.0.0+ isn't installed on your system,"
- @echo "which means that you won't be able to compile .proto files for use"
- @echo "with gRPC."
- @echo
- @echo "If you are just using pre-compiled protocol buffers, or you otherwise"
- @echo "have no need to compile .proto files, you can ignore this."
- @echo
- @echo "If you do need protobuf for some reason, you can download and install"
- @echo "it from:"
- @echo
- @echo " https://github.com/google/protobuf/releases"
- @echo
- @echo "Once you've done so, you can re-run this check by doing:"
- @echo
- @echo " make verify-install"
- endif
-
clean:
$(E) "[CLEAN] Cleaning build directories."
$(Q) $(RM) -rf $(OBJDIR) $(LIBDIR) $(BINDIR) $(GENDIR) cache.mk
diff --git a/templates/grpc.gemspec.template b/templates/grpc.gemspec.template
index ce775ffb90..f95adaf30f 100644
--- a/templates/grpc.gemspec.template
+++ b/templates/grpc.gemspec.template
@@ -29,7 +29,7 @@
s.require_paths = %w( src/ruby/bin src/ruby/lib src/ruby/pb )
s.platform = Gem::Platform::RUBY
- s.add_dependency 'google-protobuf', '~> 3.0.0.alpha.5.0.3'
+ s.add_dependency 'google-protobuf', '~> 3.0'
s.add_dependency 'googleauth', '~> 0.5.1'
s.add_development_dependency 'bundler', '~> 1.9'
diff --git a/templates/package.json.template b/templates/package.json.template
index f68f64d047..e9596d4d4c 100644
--- a/templates/package.json.template
+++ b/templates/package.json.template
@@ -37,7 +37,7 @@
"devDependencies": {
"async": "^1.5.0",
"google-auth-library": "^0.9.2",
- "google-protobuf": "^3.0.0-alpha.5",
+ "google-protobuf": "^3.0.0",
"istanbul": "^0.3.21",
"jsdoc": "^3.3.2",
"jshint": "^2.5.0",
diff --git a/templates/package.xml.template b/templates/package.xml.template
index 87b1038959..43d3aa2a58 100644
--- a/templates/package.xml.template
+++ b/templates/package.xml.template
@@ -12,7 +12,7 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
- <date>2016-07-28</date>
+ <date>2016-08-09</date>
<time>16:06:07</time>
<version>
<release>${settings.php_version.php()}</release>
@@ -24,7 +24,7 @@
</stability>
<license>BSD</license>
<notes>
- - PHP7 Support continued, reduce code duplication #7543
+ - Fixed Ubuntu compile error #7571, #7642
</notes>
<contents>
<dir baseinstalldir="/" name="/">
@@ -249,5 +249,20 @@
- PHP7 Support continued, reduce code duplication #7543
</notes>
</release>
+ <release>
+ <version>
+ <release>1.0.0RC4</release>
+ <api>1.0.0RC4</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <date>2016-08-09</date>
+ <license>BSD</license>
+ <notes>
+ - Fixed Ubuntu compile error #7571, #7642
+ </notes>
+ </release>
</changelog>
</package>
diff --git a/templates/src/csharp/Grpc.Auth/project.json.template b/templates/src/csharp/Grpc.Auth/project.json.template
index b3244e4d3c..19d4b42cf0 100644
--- a/templates/src/csharp/Grpc.Auth/project.json.template
+++ b/templates/src/csharp/Grpc.Auth/project.json.template
@@ -25,13 +25,13 @@
},
"dependencies": {
"Grpc.Core": "${settings.csharp_version}",
- "Google.Apis.Auth": "1.11.1"
+ "Google.Apis.Auth": "1.15.0"
},
"frameworks": {
"net45": { },
"netstandard1.5": {
"imports": [
- "net45"
+ "portable-net45"
],
"dependencies": {
"Microsoft.NETCore.Portable.Compatibility": "1.0.1",
diff --git a/templates/src/csharp/Grpc.Examples.MathClient/project.json.template b/templates/src/csharp/Grpc.Examples.MathClient/project.json.template
index 51c5e85c66..67151dbcfa 100644
--- a/templates/src/csharp/Grpc.Examples.MathClient/project.json.template
+++ b/templates/src/csharp/Grpc.Examples.MathClient/project.json.template
@@ -1,7 +1,7 @@
%YAML 1.2
--- |
{
- <%include file="../build_options.include" args="executable=True,includeRuntimes=False"/>
+ <%include file="../build_options.include" args="executable=True"/>
"dependencies": {
"Grpc.Examples": {
"target": "project"
diff --git a/templates/src/csharp/Grpc.Examples.MathServer/project.json.template b/templates/src/csharp/Grpc.Examples.MathServer/project.json.template
index 51c5e85c66..67151dbcfa 100644
--- a/templates/src/csharp/Grpc.Examples.MathServer/project.json.template
+++ b/templates/src/csharp/Grpc.Examples.MathServer/project.json.template
@@ -1,7 +1,7 @@
%YAML 1.2
--- |
{
- <%include file="../build_options.include" args="executable=True,includeRuntimes=False"/>
+ <%include file="../build_options.include" args="executable=True"/>
"dependencies": {
"Grpc.Examples": {
"target": "project"
diff --git a/templates/src/csharp/Grpc.Examples/project.json.template b/templates/src/csharp/Grpc.Examples/project.json.template
index d5d63f658e..117f842e01 100644
--- a/templates/src/csharp/Grpc.Examples/project.json.template
+++ b/templates/src/csharp/Grpc.Examples/project.json.template
@@ -15,11 +15,12 @@
"System.IO": ""
}
},
- "netstandard1.5": {
+ "netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
+ "Microsoft.NETCore.App": "1.0.0",
"NETStandard.Library": "1.6.0"
}
}
diff --git a/templates/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json.template b/templates/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json.template
index af1ee42509..93151f2b89 100644
--- a/templates/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json.template
+++ b/templates/src/csharp/Grpc.IntegrationTesting.QpsWorker/project.json.template
@@ -1,7 +1,7 @@
%YAML 1.2
--- |
{
- <%include file="../build_options.include" args="executable=True,includeData=True,includeRuntimes=False"/>
+ <%include file="../build_options.include" args="executable=True,includeData=True"/>
"dependencies": {
"Grpc.IntegrationTesting": {
"target": "project"
diff --git a/templates/src/csharp/Grpc.IntegrationTesting.StressClient/project.json.template b/templates/src/csharp/Grpc.IntegrationTesting.StressClient/project.json.template
index af1ee42509..93151f2b89 100644
--- a/templates/src/csharp/Grpc.IntegrationTesting.StressClient/project.json.template
+++ b/templates/src/csharp/Grpc.IntegrationTesting.StressClient/project.json.template
@@ -1,7 +1,7 @@
%YAML 1.2
--- |
{
- <%include file="../build_options.include" args="executable=True,includeData=True,includeRuntimes=False"/>
+ <%include file="../build_options.include" args="executable=True,includeData=True"/>
"dependencies": {
"Grpc.IntegrationTesting": {
"target": "project"
diff --git a/templates/src/csharp/Grpc.IntegrationTesting/project.json.template b/templates/src/csharp/Grpc.IntegrationTesting/project.json.template
index 0a7d5e9af4..1cb5ca4ba3 100644
--- a/templates/src/csharp/Grpc.IntegrationTesting/project.json.template
+++ b/templates/src/csharp/Grpc.IntegrationTesting/project.json.template
@@ -10,7 +10,7 @@
"target": "project"
},
"Google.Protobuf": "3.0.0-beta3",
- "CommandLineParser": "1.9.71",
+ "CommandLineParser.Unofficial": "2.0.275",
"NUnit": "3.2.0",
"NUnitLite": "3.2.0-*"
},
diff --git a/templates/src/csharp/build_options.include b/templates/src/csharp/build_options.include
index a200897e0f..8597ae3367 100644
--- a/templates/src/csharp/build_options.include
+++ b/templates/src/csharp/build_options.include
@@ -1,4 +1,4 @@
-<%page args="executable=False,includeData=False,includeRuntimes=True"/>\
+<%page args="executable=False,includeData=False"/>\
"buildOptions": {
% if executable:
"emitEntryPoint": true
@@ -52,10 +52,8 @@
}
},
%endif
- % if includeRuntimes:
"runtimes": {
"win7-x64": { },
"debian.8-x64": { },
"osx.10.11-x64": { }
},
- % endif \ No newline at end of file
diff --git a/templates/src/csharp/build_packages.bat.template b/templates/src/csharp/build_packages.bat.template
index ea2acb661e..5cbd8e3746 100644
--- a/templates/src/csharp/build_packages.bat.template
+++ b/templates/src/csharp/build_packages.bat.template
@@ -33,10 +33,7 @@
@rem Current package versions
set VERSION=${settings.csharp_version}
- set PROTOBUF_VERSION=3.0.0-beta3
-
- @rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well.
- set VERSION_WITH_BETA=%VERSION%-beta
+ set PROTOBUF_VERSION=3.0.0
@rem Adjust the location of nuget.exe
set NUGET=C:\nuget\nuget.exe
@@ -60,7 +57,6 @@
@rem Fetch all dependencies
%%NUGET% restore ..\..\vsprojects\grpc_csharp_ext.sln || goto :error
- %%NUGET% restore Grpc.sln || goto :error
setlocal
@@ -75,7 +71,7 @@
%%NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
%%NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% || goto :error
- %%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
+ %%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error
%%NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error
%%NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error
diff --git a/templates/src/node/health_check/package.json.template b/templates/src/node/health_check/package.json.template
index 96b9748aa7..c2bb232245 100644
--- a/templates/src/node/health_check/package.json.template
+++ b/templates/src/node/health_check/package.json.template
@@ -17,9 +17,9 @@
}
],
"dependencies": {
- "grpc": "^0.15.0",
+ "grpc": "^${settings.node_version}",
"lodash": "^3.9.3",
- "google-protobuf": "^3.0.0-alpha.5"
+ "google-protobuf": "^3.0.0"
},
"files": [
"LICENSE",
diff --git a/test/cpp/util/cli_credentials.cc b/test/cpp/util/cli_credentials.cc
new file mode 100644
index 0000000000..8de9393e4d
--- /dev/null
+++ b/test/cpp/util/cli_credentials.cc
@@ -0,0 +1,63 @@
+/*
+ *
+ * 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 "test/cpp/util/cli_credentials.h"
+
+#include <gflags/gflags.h>
+
+DEFINE_bool(enable_ssl, false, "Whether to use ssl/tls.");
+DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
+
+namespace grpc {
+namespace testing {
+
+std::shared_ptr<grpc::ChannelCredentials> CliCredentials::GetCredentials()
+ const {
+ if (!FLAGS_enable_ssl) {
+ return grpc::InsecureChannelCredentials();
+ } else {
+ if (FLAGS_use_auth) {
+ return grpc::GoogleDefaultCredentials();
+ } else {
+ return grpc::SslCredentials(grpc::SslCredentialsOptions());
+ }
+ }
+}
+
+const grpc::string CliCredentials::GetCredentialUsage() const {
+ return " --enable_ssl ; Set whether to use tls\n"
+ " --use_auth ; Set whether to create default google"
+ " credentials\n";
+}
+} // namespace testing
+} // namespace grpc
diff --git a/test/cpp/util/cli_credentials.h b/test/cpp/util/cli_credentials.h
new file mode 100644
index 0000000000..581b77a9c6
--- /dev/null
+++ b/test/cpp/util/cli_credentials.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_TEST_CPP_UTIL_CLI_CREDENTIALS_H
+#define GRPC_TEST_CPP_UTIL_CLI_CREDENTIALS_H
+
+#include <grpc++/security/credentials.h>
+#include <grpc++/support/config.h>
+
+namespace grpc {
+namespace testing {
+
+class CliCredentials {
+ public:
+ virtual ~CliCredentials() {}
+ virtual std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const;
+ virtual const grpc::string GetCredentialUsage() const;
+};
+
+} // namespace testing
+} // namespace grpc
+
+#endif // GRPC_TEST_CPP_UTIL_CLI_CREDENTIALS_H
diff --git a/test/cpp/util/config_grpc_cli.h b/test/cpp/util/config_grpc_cli.h
new file mode 100644
index 0000000000..ea8231aa26
--- /dev/null
+++ b/test/cpp/util/config_grpc_cli.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_TEST_CPP_UTIL_CONFIG_GRPC_CLI_H
+#define GRPC_TEST_CPP_UTIL_CONFIG_GRPC_CLI_H
+
+#include <grpc++/impl/codegen/config_protobuf.h>
+
+#ifndef GRPC_CUSTOM_DYNAMICMESSAGEFACTORY
+#include <google/protobuf/dynamic_message.h>
+#define GRPC_CUSTOM_DYNAMICMESSAGEFACTORY \
+ ::google::protobuf::DynamicMessageFactory
+#endif
+
+#ifndef GRPC_CUSTOM_DESCRIPTORPOOLDATABASE
+#include <google/protobuf/descriptor.h>
+#define GRPC_CUSTOM_DESCRIPTORPOOLDATABASE \
+ ::google::protobuf::DescriptorPoolDatabase
+#define GRPC_CUSTOM_MERGEDDESCRIPTORDATABASE \
+ ::google::protobuf::MergedDescriptorDatabase
+#endif
+
+#ifndef GRPC_CUSTOM_TEXTFORMAT
+#include <google/protobuf/text_format.h>
+#define GRPC_CUSTOM_TEXTFORMAT ::google::protobuf::TextFormat
+#endif
+
+#ifndef GRPC_CUSTOM_DISKSOURCETREE
+#include <google/protobuf/compiler/importer.h>
+#define GRPC_CUSTOM_DISKSOURCETREE ::google::protobuf::compiler::DiskSourceTree
+#define GRPC_CUSTOM_IMPORTER ::google::protobuf::compiler::Importer
+#define GRPC_CUSTOM_MULTIFILEERRORCOLLECTOR \
+ ::google::protobuf::compiler::MultiFileErrorCollector
+#endif
+
+namespace grpc {
+namespace protobuf {
+
+typedef GRPC_CUSTOM_DYNAMICMESSAGEFACTORY DynamicMessageFactory;
+
+typedef GRPC_CUSTOM_DESCRIPTORPOOLDATABASE DescriptorPoolDatabase;
+typedef GRPC_CUSTOM_MERGEDDESCRIPTORDATABASE MergedDescriptorDatabase;
+
+typedef GRPC_CUSTOM_TEXTFORMAT TextFormat;
+
+namespace compiler {
+typedef GRPC_CUSTOM_DISKSOURCETREE DiskSourceTree;
+typedef GRPC_CUSTOM_IMPORTER Importer;
+typedef GRPC_CUSTOM_MULTIFILEERRORCOLLECTOR MultiFileErrorCollector;
+} // namespace importer
+
+} // namespace protobuf
+} // namespace grpc
+
+#endif // GRPC_TEST_CPP_UTIL_CONFIG_GRPC_CLI_H
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index 53529da782..fe248601ee 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -33,12 +33,14 @@
/*
A command line tool to talk to a grpc server.
+ Run `grpc_cli help` command to see its usage information.
+
Example of talking to grpc interop server:
grpc_cli call localhost:50051 UnaryCall "response_size:10" \
--protofiles=src/proto/grpc/testing/test.proto --enable_ssl=false
Options:
- 1. --protofiles, use this flag to provide a proto file if the server does
+ 1. --protofiles, use this flag to provide proto files if the server does
does not have the reflection service.
2. --proto_path, if your proto file is not under current working directory,
use this flag to provide a search root. It should work similar to the
@@ -48,15 +50,17 @@
--metadata="MyHeaderKey1:Value1:MyHeaderKey2:Value2"
4. --enable_ssl, whether to use tls.
5. --use_auth, if set to true, attach a GoogleDefaultCredentials to the call
- 6. --input_binary_file, a file containing the serialized request. The file
- can be generated by calling something like:
+ 6. --infile, input filename (defaults to stdin)
+ 7. --outfile, output filename (defaults to stdout)
+ 8. --binary_input, use the serialized request as input. The serialized
+ request can be generated by calling something like:
protoc --proto_path=src/proto/grpc/testing/ \
--encode=grpc.testing.SimpleRequest \
src/proto/grpc/testing/messages.proto \
< input.txt > input.bin
If this is used and no proto file is provided in the argument list, the
method string has to be exact in the form of /package.service/method.
- 7. --output_binary_file, a file to write binary format response into, it can
+ 9. --binary_output, use binary format response as output, it can
be later decoded using protoc:
protoc --proto_path=src/proto/grpc/testing/ \
--decode=grpc.testing.SimpleResponse \
@@ -64,182 +68,34 @@
< output.bin > output.txt
*/
-#include <unistd.h>
#include <fstream>
+#include <functional>
#include <iostream>
-#include <sstream>
#include <gflags/gflags.h>
-#include <grpc++/channel.h>
-#include <grpc++/create_channel.h>
-#include <grpc++/security/credentials.h>
-#include <grpc++/support/string_ref.h>
-#include <grpc/grpc.h>
-
-#include "test/cpp/util/cli_call.h"
-#include "test/cpp/util/proto_file_parser.h"
-#include "test/cpp/util/string_ref_helper.h"
+#include <grpc++/support/config.h>
+#include "test/cpp/util/cli_credentials.h"
+#include "test/cpp/util/grpc_tool.h"
#include "test/cpp/util/test_config.h"
-DEFINE_bool(enable_ssl, true, "Whether to use ssl/tls.");
-DEFINE_bool(use_auth, false, "Whether to create default google credentials.");
-DEFINE_string(input_binary_file, "",
- "Path to input file containing serialized request.");
-DEFINE_string(output_binary_file, "",
- "Path to output file to write serialized response.");
-DEFINE_string(metadata, "",
- "Metadata to send to server, in the form of key1:val1:key2:val2");
-DEFINE_string(proto_path, ".", "Path to look for the proto file.");
-// TODO(zyc): support a list of input proto files
-DEFINE_string(protofiles, "", "Name of the proto file.");
-
-void ParseMetadataFlag(
- std::multimap<grpc::string, grpc::string>* client_metadata) {
- if (FLAGS_metadata.empty()) {
- return;
- }
- std::vector<grpc::string> fields;
- const char* delim = ":";
- size_t cur, next = -1;
- do {
- cur = next + 1;
- next = FLAGS_metadata.find_first_of(delim, cur);
- fields.push_back(FLAGS_metadata.substr(cur, next - cur));
- } while (next != grpc::string::npos);
- if (fields.size() % 2) {
- std::cout << "Failed to parse metadata flag" << std::endl;
- exit(1);
- }
- for (size_t i = 0; i < fields.size(); i += 2) {
- client_metadata->insert(
- std::pair<grpc::string, grpc::string>(fields[i], fields[i + 1]));
- }
-}
+DEFINE_string(outfile, "", "Output file (default is stdout)");
-template <typename T>
-void PrintMetadata(const T& m, const grpc::string& message) {
- if (m.empty()) {
- return;
- }
- std::cout << message << std::endl;
- grpc::string pair;
- for (typename T::const_iterator iter = m.begin(); iter != m.end(); ++iter) {
- pair.clear();
- pair.append(iter->first.data(), iter->first.size());
- pair.append(" : ");
- pair.append(iter->second.data(), iter->second.size());
- std::cout << pair << std::endl;
+static bool SimplePrint(const grpc::string& outfile,
+ const grpc::string& output) {
+ if (outfile.empty()) {
+ std::cout << output;
+ } else {
+ std::ofstream output_file(outfile, std::ios::trunc | std::ios::binary);
+ output_file << output;
+ output_file.close();
}
+ return true;
}
int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
- if (argc < 4 || grpc::string(argv[1]) != "call") {
- std::cout << "Usage: grpc_cli call server_host:port method_name "
- << "[proto file] [text format request] [<options>]" << std::endl;
- return 1;
- }
-
- grpc::string request_text;
- grpc::string server_address(argv[2]);
- grpc::string method_name(argv[3]);
- std::unique_ptr<grpc::testing::ProtoFileParser> parser;
- grpc::string serialized_request_proto;
-
- if (argc == 5) {
- request_text = argv[4];
- }
-
- std::shared_ptr<grpc::ChannelCredentials> creds;
- if (!FLAGS_enable_ssl) {
- creds = grpc::InsecureChannelCredentials();
- } else {
- if (FLAGS_use_auth) {
- creds = grpc::GoogleDefaultCredentials();
- } else {
- creds = grpc::SslCredentials(grpc::SslCredentialsOptions());
- }
- }
- std::shared_ptr<grpc::Channel> channel =
- grpc::CreateChannel(server_address, creds);
-
- if (request_text.empty() && FLAGS_input_binary_file.empty()) {
- if (isatty(STDIN_FILENO)) {
- std::cout << "reading request message from stdin..." << std::endl;
- }
- std::stringstream input_stream;
- input_stream << std::cin.rdbuf();
- request_text = input_stream.str();
- }
-
- if (!request_text.empty()) {
- if (!FLAGS_protofiles.empty()) {
- parser.reset(new grpc::testing::ProtoFileParser(
- FLAGS_proto_path, FLAGS_protofiles, method_name));
- } else {
- parser.reset(new grpc::testing::ProtoFileParser(channel, method_name));
- }
- method_name = parser->GetFullMethodName();
- if (parser->HasError()) {
- return 1;
- }
-
- if (!FLAGS_input_binary_file.empty()) {
- std::cout
- << "warning: request given in argv, ignoring --input_binary_file"
- << std::endl;
- }
- }
-
- if (parser) {
- serialized_request_proto =
- parser->GetSerializedProto(request_text, true /* is_request */);
- if (parser->HasError()) {
- return 1;
- }
- } else if (!FLAGS_input_binary_file.empty()) {
- std::ifstream input_file(FLAGS_input_binary_file,
- std::ios::in | std::ios::binary);
- std::stringstream input_stream;
- input_stream << input_file.rdbuf();
- serialized_request_proto = input_stream.str();
- }
- std::cout << "connecting to " << server_address << std::endl;
-
- grpc::string serialized_response_proto;
- std::multimap<grpc::string, grpc::string> client_metadata;
- std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
- server_trailing_metadata;
- ParseMetadataFlag(&client_metadata);
- PrintMetadata(client_metadata, "Sending client initial metadata:");
- grpc::Status s = grpc::testing::CliCall::Call(
- channel, method_name, serialized_request_proto,
- &serialized_response_proto, client_metadata, &server_initial_metadata,
- &server_trailing_metadata);
- PrintMetadata(server_initial_metadata,
- "Received initial metadata from server:");
- PrintMetadata(server_trailing_metadata,
- "Received trailing metadata from server:");
- if (s.ok()) {
- std::cout << "Rpc succeeded with OK status" << std::endl;
- if (parser) {
- grpc::string response_text = parser->GetTextFormat(
- serialized_response_proto, false /* is_request */);
- if (parser->HasError()) {
- return 1;
- }
- std::cout << "Response: \n " << response_text << std::endl;
- }
- if (!FLAGS_output_binary_file.empty()) {
- std::ofstream output_file(FLAGS_output_binary_file,
- std::ios::trunc | std::ios::binary);
- output_file << serialized_response_proto;
- }
- } else {
- std::cout << "Rpc failed with status code " << s.error_code()
- << ", error message: " << s.error_message() << std::endl;
- }
-
- return 0;
+ return grpc::testing::GrpcToolMainLib(
+ argc, (const char**)argv, grpc::testing::CliCredentials(),
+ std::bind(SimplePrint, FLAGS_outfile, std::placeholders::_1));
}
diff --git a/test/cpp/util/grpc_tool.cc b/test/cpp/util/grpc_tool.cc
new file mode 100644
index 0000000000..f06053ca23
--- /dev/null
+++ b/test/cpp/util/grpc_tool.cc
@@ -0,0 +1,365 @@
+/*
+ *
+ * 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 "test/cpp/util/grpc_tool.h"
+
+#include <unistd.h>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include <gflags/gflags.h>
+#include <grpc++/channel.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/grpc++.h>
+#include <grpc++/security/credentials.h>
+#include <grpc++/support/string_ref.h>
+#include <grpc/grpc.h>
+
+#include "test/cpp/util/cli_call.h"
+#include "test/cpp/util/proto_file_parser.h"
+#include "test/cpp/util/proto_reflection_descriptor_database.h"
+#include "test/cpp/util/test_config.h"
+
+DEFINE_bool(remotedb, true, "Use server types to parse and format messages");
+DEFINE_string(metadata, "",
+ "Metadata to send to server, in the form of key1:val1:key2:val2");
+DEFINE_string(proto_path, ".", "Path to look for the proto file.");
+DEFINE_string(proto_file, "", "Name of the proto file.");
+DEFINE_bool(binary_input, false, "Input in binary format");
+DEFINE_bool(binary_output, false, "Output in binary format");
+DEFINE_string(infile, "", "Input file (default is stdin)");
+
+namespace grpc {
+namespace testing {
+namespace {
+
+class GrpcTool {
+ public:
+ explicit GrpcTool();
+ virtual ~GrpcTool() {}
+
+ bool Help(int argc, const char** argv, CliCredentials cred,
+ GrpcToolOutputCallback callback);
+ bool CallMethod(int argc, const char** argv, CliCredentials cred,
+ GrpcToolOutputCallback callback);
+ // TODO(zyc): implement the following methods
+ // bool ListServices(int argc, const char** argv, GrpcToolOutputCallback
+ // callback);
+ // bool PrintType(int argc, const char** argv, GrpcToolOutputCallback
+ // callback);
+ // bool PrintTypeId(int argc, const char** argv, GrpcToolOutputCallback
+ // callback);
+ // bool ParseMessage(int argc, const char** argv, GrpcToolOutputCallback
+ // callback);
+ // bool ToText(int argc, const char** argv, GrpcToolOutputCallback callback);
+ // bool ToBinary(int argc, const char** argv, GrpcToolOutputCallback
+ // callback);
+
+ void SetPrintCommandMode(int exit_status) {
+ print_command_usage_ = true;
+ usage_exit_status_ = exit_status;
+ }
+
+ private:
+ void CommandUsage(const grpc::string& usage) const;
+ bool print_command_usage_;
+ int usage_exit_status_;
+ const grpc::string cred_usage_;
+};
+
+template <typename T>
+std::function<bool(GrpcTool*, int, const char**, const CliCredentials,
+ GrpcToolOutputCallback)>
+BindWith5Args(T&& func) {
+ return std::bind(std::forward<T>(func), std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3,
+ std::placeholders::_4, std::placeholders::_5);
+}
+
+template <typename T>
+size_t ArraySize(T& a) {
+ return ((sizeof(a) / sizeof(*(a))) /
+ static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
+}
+
+void ParseMetadataFlag(
+ std::multimap<grpc::string, grpc::string>* client_metadata) {
+ if (FLAGS_metadata.empty()) {
+ return;
+ }
+ std::vector<grpc::string> fields;
+ const char* delim = ":";
+ size_t cur, next = -1;
+ do {
+ cur = next + 1;
+ next = FLAGS_metadata.find_first_of(delim, cur);
+ fields.push_back(FLAGS_metadata.substr(cur, next - cur));
+ } while (next != grpc::string::npos);
+ if (fields.size() % 2) {
+ fprintf(stderr, "Failed to parse metadata flag.\n");
+ exit(1);
+ }
+ for (size_t i = 0; i < fields.size(); i += 2) {
+ client_metadata->insert(
+ std::pair<grpc::string, grpc::string>(fields[i], fields[i + 1]));
+ }
+}
+
+template <typename T>
+void PrintMetadata(const T& m, const grpc::string& message) {
+ if (m.empty()) {
+ return;
+ }
+ fprintf(stderr, "%s\n", message.c_str());
+ grpc::string pair;
+ for (typename T::const_iterator iter = m.begin(); iter != m.end(); ++iter) {
+ pair.clear();
+ pair.append(iter->first.data(), iter->first.size());
+ pair.append(" : ");
+ pair.append(iter->second.data(), iter->second.size());
+ fprintf(stderr, "%s\n", pair.c_str());
+ }
+}
+
+struct Command {
+ const char* command;
+ std::function<bool(GrpcTool*, int, const char**, const CliCredentials,
+ GrpcToolOutputCallback)>
+ function;
+ int min_args;
+ int max_args;
+};
+
+const Command ops[] = {
+ {"help", BindWith5Args(&GrpcTool::Help), 0, INT_MAX},
+ // {"ls", BindWith5Args(&GrpcTool::ListServices), 1, 3},
+ // {"list", BindWith5Args(&GrpcTool::ListServices), 1, 3},
+ {"call", BindWith5Args(&GrpcTool::CallMethod), 2, 3},
+ // {"type", BindWith5Args(&GrpcTool::PrintType), 2, 2},
+ // {"parse", BindWith5Args(&GrpcTool::ParseMessage), 2, 3},
+ // {"totext", BindWith5Args(&GrpcTool::ToText), 2, 3},
+ // {"tobinary", BindWith5Args(&GrpcTool::ToBinary), 2, 3},
+};
+
+void Usage(const grpc::string& msg) {
+ fprintf(
+ stderr,
+ "%s\n"
+ // " grpc_cli ls ... ; List services\n"
+ " grpc_cli call ... ; Call method\n"
+ // " grpc_cli type ... ; Print type\n"
+ // " grpc_cli parse ... ; Parse message\n"
+ // " grpc_cli totext ... ; Convert binary message to text\n"
+ // " grpc_cli tobinary ... ; Convert text message to binary\n"
+ " grpc_cli help ... ; Print this message, or per-command usage\n"
+ "\n",
+ msg.c_str());
+
+ exit(1);
+}
+
+const Command* FindCommand(const grpc::string& name) {
+ for (int i = 0; i < (int)ArraySize(ops); i++) {
+ if (name == ops[i].command) {
+ return &ops[i];
+ }
+ }
+ return NULL;
+}
+} // namespace
+
+int GrpcToolMainLib(int argc, const char** argv, const CliCredentials cred,
+ GrpcToolOutputCallback callback) {
+ if (argc < 2) {
+ Usage("No command specified");
+ }
+
+ grpc::string command = argv[1];
+ argc -= 2;
+ argv += 2;
+
+ const Command* cmd = FindCommand(command);
+ if (cmd != NULL) {
+ GrpcTool grpc_tool;
+ if (argc < cmd->min_args || argc > cmd->max_args) {
+ // Force the command to print its usage message
+ fprintf(stderr, "\nWrong number of arguments for %s\n", command.c_str());
+ grpc_tool.SetPrintCommandMode(1);
+ return cmd->function(&grpc_tool, -1, NULL, cred, callback);
+ }
+ const bool ok = cmd->function(&grpc_tool, argc, argv, cred, callback);
+ return ok ? 0 : 1;
+ } else {
+ Usage("Invalid command '" + grpc::string(command.c_str()) + "'");
+ }
+ return 1;
+}
+
+GrpcTool::GrpcTool() : print_command_usage_(false), usage_exit_status_(0) {}
+
+void GrpcTool::CommandUsage(const grpc::string& usage) const {
+ if (print_command_usage_) {
+ fprintf(stderr, "\n%s%s\n", usage.c_str(),
+ (usage.empty() || usage[usage.size() - 1] != '\n') ? "\n" : "");
+ exit(usage_exit_status_);
+ }
+}
+
+bool GrpcTool::Help(int argc, const char** argv, const CliCredentials cred,
+ GrpcToolOutputCallback callback) {
+ CommandUsage(
+ "Print help\n"
+ " grpc_cli help [subcommand]\n");
+
+ if (argc == 0) {
+ Usage("");
+ } else {
+ const Command* cmd = FindCommand(argv[0]);
+ if (cmd == NULL) {
+ Usage("Unknown command '" + grpc::string(argv[0]) + "'");
+ }
+ SetPrintCommandMode(0);
+ cmd->function(this, -1, NULL, cred, callback);
+ }
+ return true;
+}
+
+bool GrpcTool::CallMethod(int argc, const char** argv,
+ const CliCredentials cred,
+ GrpcToolOutputCallback callback) {
+ CommandUsage(
+ "Call method\n"
+ " grpc_cli call <address> <service>[.<method>] <request>\n"
+ " <address> ; host:port\n"
+ " <service> ; Exported service name\n"
+ " <method> ; Method name\n"
+ " <request> ; Text protobuffer (overrides infile)\n"
+ " --proto_file ; Comma separated proto files used as a"
+ " fallback when parsing request/response\n"
+ " --proto_path ; The search path of proto files, valid"
+ " only when --proto_file is given\n"
+ " --metadata ; The metadata to be sent to the server\n"
+ " --infile ; Input filename (defaults to stdin)\n"
+ " --outfile ; Output filename (defaults to stdout)\n"
+ " --binary_input ; Input in binary format\n"
+ " --binary_output ; Output in binary format\n" +
+ cred.GetCredentialUsage());
+
+ std::stringstream output_ss;
+ grpc::string request_text;
+ grpc::string server_address(argv[0]);
+ grpc::string method_name(argv[1]);
+ std::unique_ptr<grpc::testing::ProtoFileParser> parser;
+ grpc::string serialized_request_proto;
+
+ if (argc == 3) {
+ request_text = argv[2];
+ if (!FLAGS_infile.empty()) {
+ fprintf(stderr, "warning: request given in argv, ignoring --infile\n");
+ }
+ } else {
+ std::stringstream input_stream;
+ if (FLAGS_infile.empty()) {
+ if (isatty(STDIN_FILENO)) {
+ fprintf(stderr, "reading request message from stdin...\n");
+ }
+ input_stream << std::cin.rdbuf();
+ } else {
+ std::ifstream input_file(FLAGS_infile, std::ios::in | std::ios::binary);
+ input_stream << input_file.rdbuf();
+ input_file.close();
+ }
+ request_text = input_stream.str();
+ }
+
+ std::shared_ptr<grpc::Channel> channel =
+ grpc::CreateChannel(server_address, cred.GetCredentials());
+ if (!FLAGS_binary_input || !FLAGS_binary_output) {
+ parser.reset(
+ new grpc::testing::ProtoFileParser(FLAGS_remotedb ? channel : nullptr,
+ FLAGS_proto_path, FLAGS_proto_file));
+ if (parser->HasError()) {
+ return false;
+ }
+ }
+
+ if (FLAGS_binary_input) {
+ serialized_request_proto = request_text;
+ } else {
+ serialized_request_proto = parser->GetSerializedProtoFromMethod(
+ method_name, request_text, true /* is_request */);
+ if (parser->HasError()) {
+ return false;
+ }
+ }
+ fprintf(stderr, "connecting to %s\n", server_address.c_str());
+
+ grpc::string serialized_response_proto;
+ std::multimap<grpc::string, grpc::string> client_metadata;
+ std::multimap<grpc::string_ref, grpc::string_ref> server_initial_metadata,
+ server_trailing_metadata;
+ ParseMetadataFlag(&client_metadata);
+ PrintMetadata(client_metadata, "Sending client initial metadata:");
+ grpc::Status status = grpc::testing::CliCall::Call(
+ channel, parser->GetFormatedMethodName(method_name),
+ serialized_request_proto, &serialized_response_proto, client_metadata,
+ &server_initial_metadata, &server_trailing_metadata);
+ PrintMetadata(server_initial_metadata,
+ "Received initial metadata from server:");
+ PrintMetadata(server_trailing_metadata,
+ "Received trailing metadata from server:");
+ if (status.ok()) {
+ fprintf(stderr, "Rpc succeeded with OK status\n");
+ if (FLAGS_binary_output) {
+ output_ss << serialized_response_proto;
+ } else {
+ grpc::string response_text = parser->GetTextFormatFromMethod(
+ method_name, serialized_response_proto, false /* is_request */);
+ if (parser->HasError()) {
+ return false;
+ }
+ output_ss << "Response: \n " << response_text << std::endl;
+ }
+ } else {
+ fprintf(stderr, "Rpc failed with status code %d, error message: %s\n",
+ status.error_code(), status.error_message().c_str());
+ }
+
+ return callback(output_ss.str());
+}
+
+} // namespace testing
+} // namespace grpc
diff --git a/test/cpp/util/grpc_tool.h b/test/cpp/util/grpc_tool.h
new file mode 100644
index 0000000000..3da86937c2
--- /dev/null
+++ b/test/cpp/util/grpc_tool.h
@@ -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.
+ *
+ */
+
+#ifndef GRPC_TEST_CPP_UTIL_GRPC_TOOL_H
+#define GRPC_TEST_CPP_UTIL_GRPC_TOOL_H
+
+#include <functional>
+
+#include <grpc++/support/config.h>
+
+#include "test/cpp/util/cli_credentials.h"
+
+namespace grpc {
+namespace testing {
+
+typedef std::function<bool(const grpc::string &)> GrpcToolOutputCallback;
+
+int GrpcToolMainLib(int argc, const char **argv, CliCredentials cred,
+ GrpcToolOutputCallback callback);
+
+} // namespace testing
+} // namespace grpc
+
+#endif // GRPC_TEST_CPP_UTIL_GRPC_TOOL_H
diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc
new file mode 100644
index 0000000000..b96afaf50c
--- /dev/null
+++ b/test/cpp/util/grpc_tool_test.cc
@@ -0,0 +1,227 @@
+/*
+ *
+ * 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 "test/cpp/util/grpc_tool.h"
+
+#include <sstream>
+
+#include <grpc++/channel.h>
+#include <grpc++/client_context.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/ext/proto_server_reflection_plugin.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc++/server_context.h>
+#include <grpc/grpc.h>
+#include <gtest/gtest.h>
+
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "src/proto/grpc/testing/echo.pb.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+#include "test/cpp/util/cli_credentials.h"
+#include "test/cpp/util/string_ref_helper.h"
+
+using grpc::testing::EchoRequest;
+using grpc::testing::EchoResponse;
+
+namespace grpc {
+namespace testing {
+namespace {
+
+class TestCliCredentials GRPC_FINAL : public grpc::testing::CliCredentials {
+ public:
+ std::shared_ptr<grpc::ChannelCredentials> GetCredentials() const
+ GRPC_OVERRIDE {
+ return InsecureChannelCredentials();
+ }
+ const grpc::string GetCredentialUsage() const GRPC_OVERRIDE { return ""; }
+};
+
+} // namespame
+
+class TestServiceImpl : public ::grpc::testing::EchoTestService::Service {
+ public:
+ Status Echo(ServerContext* context, const EchoRequest* request,
+ EchoResponse* response) GRPC_OVERRIDE {
+ if (!context->client_metadata().empty()) {
+ for (std::multimap<grpc::string_ref, grpc::string_ref>::const_iterator
+ iter = context->client_metadata().begin();
+ iter != context->client_metadata().end(); ++iter) {
+ context->AddInitialMetadata(ToString(iter->first),
+ ToString(iter->second));
+ }
+ }
+ context->AddTrailingMetadata("trailing_key", "trailing_value");
+ response->set_message(request->message());
+ return Status::OK;
+ }
+};
+
+class GrpcToolTest : public ::testing::Test {
+ protected:
+ GrpcToolTest() {}
+
+ // SetUpServer cannot be used with EXPECT_EXIT. grpc_pick_unused_port_or_die()
+ // uses atexit() to free chosen ports, and it will spawn a new thread in
+ // resolve_address_posix.c:192 at exit time.
+ const grpc::string SetUpServer() {
+ std::ostringstream server_address;
+ int port = grpc_pick_unused_port_or_die();
+ server_address << "localhost:" << port;
+ // Setup server
+ ServerBuilder builder;
+ builder.AddListeningPort(server_address.str(), InsecureServerCredentials());
+ builder.RegisterService(&service_);
+ server_ = builder.BuildAndStart();
+ return server_address.str();
+ }
+
+ void ShutdownServer() { server_->Shutdown(); }
+
+ std::unique_ptr<Server> server_;
+ TestServiceImpl service_;
+ reflection::ProtoServerReflectionPlugin plugin_;
+};
+
+static bool PrintStream(std::stringstream* ss, const grpc::string& output) {
+ (*ss) << output << std::endl;
+ return true;
+}
+
+template <typename T>
+static size_t ArraySize(T& a) {
+ return ((sizeof(a) / sizeof(*(a))) /
+ static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))));
+}
+
+#define USAGE_REGEX "( grpc_cli .+\n){2,10}"
+
+TEST_F(GrpcToolTest, NoCommand) {
+ // Test input "grpc_cli"
+ std::stringstream output_stream;
+ const char* argv[] = {"grpc_cli"};
+ // Exit with 1, print usage instruction in stderr
+ EXPECT_EXIT(
+ GrpcToolMainLib(
+ ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream, std::placeholders::_1)),
+ ::testing::ExitedWithCode(1), "No command specified\n" USAGE_REGEX);
+ // No output
+ EXPECT_TRUE(0 == output_stream.tellp());
+}
+
+TEST_F(GrpcToolTest, InvalidCommand) {
+ // Test input "grpc_cli"
+ std::stringstream output_stream;
+ const char* argv[] = {"grpc_cli", "abc"};
+ // Exit with 1, print usage instruction in stderr
+ EXPECT_EXIT(
+ GrpcToolMainLib(
+ ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream, std::placeholders::_1)),
+ ::testing::ExitedWithCode(1), "Invalid command 'abc'\n" USAGE_REGEX);
+ // No output
+ EXPECT_TRUE(0 == output_stream.tellp());
+}
+
+TEST_F(GrpcToolTest, HelpCommand) {
+ // Test input "grpc_cli help"
+ std::stringstream output_stream;
+ const char* argv[] = {"grpc_cli", "help"};
+ // Exit with 1, print usage instruction in stderr
+ EXPECT_EXIT(GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)),
+ ::testing::ExitedWithCode(1), USAGE_REGEX);
+ // No output
+ EXPECT_TRUE(0 == output_stream.tellp());
+}
+
+TEST_F(GrpcToolTest, CallCommand) {
+ // Test input "grpc_cli call Echo"
+ std::stringstream output_stream;
+
+ const grpc::string server_address = SetUpServer();
+ const char* argv[] = {"grpc_cli", "call", server_address.c_str(), "Echo",
+ "message: 'Hello'"};
+
+ EXPECT_TRUE(0 == GrpcToolMainLib(ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream,
+ std::placeholders::_1)));
+ // Expected output: "message: \"Hello\""
+ EXPECT_TRUE(NULL !=
+ strstr(output_stream.str().c_str(), "message: \"Hello\""));
+ ShutdownServer();
+}
+
+TEST_F(GrpcToolTest, TooFewArguments) {
+ // Test input "grpc_cli call localhost:<port> Echo "message: 'Hello'"
+ std::stringstream output_stream;
+ const char* argv[] = {"grpc_cli", "call", "Echo"};
+
+ // Exit with 1
+ EXPECT_EXIT(
+ GrpcToolMainLib(
+ ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream, std::placeholders::_1)),
+ ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
+ // No output
+ EXPECT_TRUE(0 == output_stream.tellp());
+}
+
+TEST_F(GrpcToolTest, TooManyArguments) {
+ // Test input "grpc_cli call localhost:<port> Echo Echo "message: 'Hello'"
+ std::stringstream output_stream;
+ const char* argv[] = {"grpc_cli", "call", "localhost:10000",
+ "Echo", "Echo", "message: 'Hello'"};
+
+ // Exit with 1
+ EXPECT_EXIT(
+ GrpcToolMainLib(
+ ArraySize(argv), argv, TestCliCredentials(),
+ std::bind(PrintStream, &output_stream, std::placeholders::_1)),
+ ::testing::ExitedWithCode(1), ".*Wrong number of arguments for call.*");
+ // No output
+ EXPECT_TRUE(0 == output_stream.tellp());
+}
+
+} // namespace testing
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ ::testing::InitGoogleTest(&argc, argv);
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/util/proto_file_parser.cc b/test/cpp/util/proto_file_parser.cc
index 5b0d925e1c..0c88c24448 100644
--- a/test/cpp/util/proto_file_parser.cc
+++ b/test/cpp/util/proto_file_parser.cc
@@ -37,7 +37,6 @@
#include <iostream>
#include <sstream>
-#include <google/protobuf/text_format.h>
#include <grpc++/support/config.h>
namespace grpc {
@@ -56,8 +55,7 @@ bool MethodNameMatch(const grpc::string& full_name, const grpc::string& input) {
}
} // namespace
-class ErrorPrinter
- : public google::protobuf::compiler::MultiFileErrorCollector {
+class ErrorPrinter : public protobuf::compiler::MultiFileErrorCollector {
public:
explicit ErrorPrinter(ProtoFileParser* parser) : parser_(parser) {}
@@ -71,7 +69,7 @@ class ErrorPrinter
void AddWarning(const grpc::string& filename, int line, int column,
const grpc::string& message) GRPC_OVERRIDE {
- std::cout << "warning " << filename << " " << line << " " << column << " "
+ std::cerr << "warning " << filename << " " << line << " " << column << " "
<< message << std::endl;
}
@@ -79,62 +77,69 @@ class ErrorPrinter
ProtoFileParser* parser_; // not owned
};
-ProtoFileParser::ProtoFileParser(const grpc::string& proto_path,
- const grpc::string& file_name,
- const grpc::string& method)
+ProtoFileParser::ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
+ const grpc::string& proto_path,
+ const grpc::string& protofiles)
: has_error_(false) {
- source_tree_.MapPath("", proto_path);
- error_printer_.reset(new ErrorPrinter(this));
- importer_.reset(new google::protobuf::compiler::Importer(
- &source_tree_, error_printer_.get()));
- const auto* file_desc = importer_->Import(file_name);
- if (!file_desc) {
- LogError("");
- return;
+ std::vector<std::string> service_list;
+ if (channel) {
+ reflection_db_.reset(new grpc::ProtoReflectionDescriptorDatabase(channel));
+ reflection_db_->GetServices(&service_list);
}
- dynamic_factory_.reset(
- new google::protobuf::DynamicMessageFactory(importer_->pool()));
- std::vector<const google::protobuf::ServiceDescriptor*> service_desc_list;
- for (int i = 0; i < file_desc->service_count(); i++) {
- service_desc_list.push_back(file_desc->service(i));
- }
- InitProtoFileParser(method, service_desc_list);
-}
+ if (!protofiles.empty()) {
+ source_tree_.MapPath("", proto_path);
+ error_printer_.reset(new ErrorPrinter(this));
+ importer_.reset(
+ new protobuf::compiler::Importer(&source_tree_, error_printer_.get()));
-ProtoFileParser::ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
- const grpc::string& method)
- : has_error_(false),
- desc_db_(new grpc::ProtoReflectionDescriptorDatabase(channel)),
- desc_pool_(new google::protobuf::DescriptorPool(desc_db_.get())) {
- std::vector<std::string> service_list;
- if (!desc_db_->GetServices(&service_list)) {
- LogError(
- "Failed to get services from the server, "
- "it may not have the reflection service.\n"
- "Please try to use the --protofiles option to provide a proto file.");
+ grpc::string file_name;
+ std::stringstream ss(protofiles);
+ while (std::getline(ss, file_name, ',')) {
+ const auto* file_desc = importer_->Import(file_name);
+ if (file_desc) {
+ for (int i = 0; i < file_desc->service_count(); i++) {
+ service_desc_list_.push_back(file_desc->service(i));
+ }
+ } else {
+ std::cerr << file_name << " not found" << std::endl;
+ }
+ }
+
+ file_db_.reset(new protobuf::DescriptorPoolDatabase(*importer_->pool()));
}
- if (has_error_) {
+
+ if (!reflection_db_ && !file_db_) {
+ LogError("No available proto database");
return;
}
- dynamic_factory_.reset(
- new google::protobuf::DynamicMessageFactory(desc_pool_.get()));
- std::vector<const google::protobuf::ServiceDescriptor*> service_desc_list;
+ if (!reflection_db_) {
+ desc_db_ = std::move(file_db_);
+ } else if (!file_db_) {
+ desc_db_ = std::move(reflection_db_);
+ } else {
+ desc_db_.reset(new protobuf::MergedDescriptorDatabase(reflection_db_.get(),
+ file_db_.get()));
+ }
+
+ desc_pool_.reset(new protobuf::DescriptorPool(desc_db_.get()));
+ dynamic_factory_.reset(new protobuf::DynamicMessageFactory(desc_pool_.get()));
+
for (auto it = service_list.begin(); it != service_list.end(); it++) {
- service_desc_list.push_back(desc_pool_->FindServiceByName(*it));
+ if (const protobuf::ServiceDescriptor* service_desc =
+ desc_pool_->FindServiceByName(*it)) {
+ service_desc_list_.push_back(service_desc);
+ }
}
- InitProtoFileParser(method, service_desc_list);
}
ProtoFileParser::~ProtoFileParser() {}
-void ProtoFileParser::InitProtoFileParser(
- const grpc::string& method,
- const std::vector<const google::protobuf::ServiceDescriptor*>
- service_desc_list) {
- const google::protobuf::MethodDescriptor* method_descriptor = nullptr;
- for (auto it = service_desc_list.begin(); it != service_desc_list.end();
+grpc::string ProtoFileParser::GetFullMethodName(const grpc::string& method) {
+ has_error_ = false;
+ const protobuf::MethodDescriptor* method_descriptor = nullptr;
+ for (auto it = service_desc_list_.begin(); it != service_desc_list_.end();
it++) {
const auto* service_desc = *it;
for (int j = 0; j < service_desc->method_count(); j++) {
@@ -154,28 +159,82 @@ void ProtoFileParser::InitProtoFileParser(
LogError("Method name not found");
}
if (has_error_) {
- return;
+ return "";
+ }
+
+ return method_descriptor->full_name();
+}
+
+grpc::string ProtoFileParser::GetFormatedMethodName(
+ const grpc::string& method) {
+ has_error_ = false;
+ grpc::string formated_method_name = GetFullMethodName(method);
+ if (has_error_) {
+ return "";
}
- full_method_name_ = method_descriptor->full_name();
- size_t last_dot = full_method_name_.find_last_of('.');
+ size_t last_dot = formated_method_name.find_last_of('.');
if (last_dot != grpc::string::npos) {
- full_method_name_[last_dot] = '/';
+ formated_method_name[last_dot] = '/';
+ }
+ formated_method_name.insert(formated_method_name.begin(), '/');
+ return formated_method_name;
+}
+
+grpc::string ProtoFileParser::GetMessageTypeFromMethod(
+ const grpc::string& method, bool is_request) {
+ has_error_ = false;
+ grpc::string full_method_name = GetFullMethodName(method);
+ if (has_error_) {
+ return "";
+ }
+ const protobuf::MethodDescriptor* method_desc =
+ desc_pool_->FindMethodByName(full_method_name);
+ if (!method_desc) {
+ LogError("Method not found");
+ return "";
}
- full_method_name_.insert(full_method_name_.begin(), '/');
- request_prototype_.reset(
- dynamic_factory_->GetPrototype(method_descriptor->input_type())->New());
- response_prototype_.reset(
- dynamic_factory_->GetPrototype(method_descriptor->output_type())->New());
+ return is_request ? method_desc->input_type()->full_name()
+ : method_desc->output_type()->full_name();
}
-grpc::string ProtoFileParser::GetSerializedProto(
- const grpc::string& text_format_proto, bool is_request) {
+grpc::string ProtoFileParser::GetSerializedProtoFromMethod(
+ const grpc::string& method, const grpc::string& text_format_proto,
+ bool is_request) {
+ has_error_ = false;
+ grpc::string message_type_name = GetMessageTypeFromMethod(method, is_request);
+ if (has_error_) {
+ return "";
+ }
+ return GetSerializedProtoFromMessageType(message_type_name,
+ text_format_proto);
+}
+
+grpc::string ProtoFileParser::GetTextFormatFromMethod(
+ const grpc::string& method, const grpc::string& serialized_proto,
+ bool is_request) {
+ has_error_ = false;
+ grpc::string message_type_name = GetMessageTypeFromMethod(method, is_request);
+ if (has_error_) {
+ return "";
+ }
+ return GetTextFormatFromMessageType(message_type_name, serialized_proto);
+}
+
+grpc::string ProtoFileParser::GetSerializedProtoFromMessageType(
+ const grpc::string& message_type_name,
+ const grpc::string& text_format_proto) {
+ has_error_ = false;
grpc::string serialized;
- grpc::protobuf::Message* msg =
- is_request ? request_prototype_.get() : response_prototype_.get();
- bool ok =
- google::protobuf::TextFormat::ParseFromString(text_format_proto, msg);
+ const protobuf::Descriptor* desc =
+ desc_pool_->FindMessageTypeByName(message_type_name);
+ if (!desc) {
+ LogError("Message type not found");
+ return "";
+ }
+ std::unique_ptr<grpc::protobuf::Message> msg(
+ dynamic_factory_->GetPrototype(desc)->New());
+ bool ok = protobuf::TextFormat::ParseFromString(text_format_proto, msg.get());
if (!ok) {
LogError("Failed to parse text format to proto.");
return "";
@@ -188,16 +247,24 @@ grpc::string ProtoFileParser::GetSerializedProto(
return serialized;
}
-grpc::string ProtoFileParser::GetTextFormat(
- const grpc::string& serialized_proto, bool is_request) {
- grpc::protobuf::Message* msg =
- is_request ? request_prototype_.get() : response_prototype_.get();
+grpc::string ProtoFileParser::GetTextFormatFromMessageType(
+ const grpc::string& message_type_name,
+ const grpc::string& serialized_proto) {
+ has_error_ = false;
+ const protobuf::Descriptor* desc =
+ desc_pool_->FindMessageTypeByName(message_type_name);
+ if (!desc) {
+ LogError("Message type not found");
+ return "";
+ }
+ std::unique_ptr<grpc::protobuf::Message> msg(
+ dynamic_factory_->GetPrototype(desc)->New());
if (!msg->ParseFromString(serialized_proto)) {
LogError("Failed to deserialize proto.");
return "";
}
grpc::string text_format;
- if (!google::protobuf::TextFormat::PrintToString(*msg, &text_format)) {
+ if (!protobuf::TextFormat::PrintToString(*msg.get(), &text_format)) {
LogError("Failed to print proto message to text format");
return "";
}
@@ -206,7 +273,7 @@ grpc::string ProtoFileParser::GetTextFormat(
void ProtoFileParser::LogError(const grpc::string& error_msg) {
if (!error_msg.empty()) {
- std::cout << error_msg << std::endl;
+ std::cerr << error_msg << std::endl;
}
has_error_ = true;
}
diff --git a/test/cpp/util/proto_file_parser.h b/test/cpp/util/proto_file_parser.h
index b442d77db9..eda3991e72 100644
--- a/test/cpp/util/proto_file_parser.h
+++ b/test/cpp/util/proto_file_parser.h
@@ -36,11 +36,9 @@
#include <memory>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/dynamic_message.h>
#include <grpc++/channel.h>
-#include "src/compiler/config.h"
+#include "test/cpp/util/config_grpc_cli.h"
#include "test/cpp/util/proto_reflection_descriptor_database.h"
namespace grpc {
@@ -50,44 +48,63 @@ class ErrorPrinter;
// Find method and associated request/response types.
class ProtoFileParser {
public:
- // The given proto file_name will be searched in a source tree rooted from
- // proto_path. The method could be a partial string such as Service.Method or
- // even just Method. It will log an error if there is ambiguity.
- ProtoFileParser(const grpc::string& proto_path, const grpc::string& file_name,
- const grpc::string& method);
-
+ // The parser will search proto files using the server reflection service
+ // provided on the given channel. The given protofiles in a source tree rooted
+ // from proto_path will also be searched.
ProtoFileParser(std::shared_ptr<grpc::Channel> channel,
- const grpc::string& method);
+ const grpc::string& proto_path,
+ const grpc::string& protofiles);
+
~ProtoFileParser();
- grpc::string GetFullMethodName() const { return full_method_name_; }
+ // The input method name in the following four functions could be a partial
+ // string such as Service.Method or even just Method. It will log an error if
+ // there is ambiguity.
+ // Full method name is in the form of Service.Method, it's good to be used in
+ // descriptor database queries.
+ grpc::string GetFullMethodName(const grpc::string& method);
+
+ // Formated method name is in the form of /Service/Method, it's good to be
+ // used as the argument of Stub::Call()
+ grpc::string GetFormatedMethodName(const grpc::string& method);
+
+ grpc::string GetSerializedProtoFromMethod(
+ const grpc::string& method, const grpc::string& text_format_proto,
+ bool is_request);
+
+ grpc::string GetTextFormatFromMethod(const grpc::string& method,
+ const grpc::string& serialized_proto,
+ bool is_request);
- grpc::string GetSerializedProto(const grpc::string& text_format_proto,
- bool is_request);
+ grpc::string GetSerializedProtoFromMessageType(
+ const grpc::string& message_type_name,
+ const grpc::string& text_format_proto);
- grpc::string GetTextFormat(const grpc::string& serialized_proto,
- bool is_request);
+ grpc::string GetTextFormatFromMessageType(
+ const grpc::string& message_type_name,
+ const grpc::string& serialized_proto);
bool HasError() const { return has_error_; }
void LogError(const grpc::string& error_msg);
private:
- void InitProtoFileParser(
- const grpc::string& method,
- const std::vector<const google::protobuf::ServiceDescriptor*> services);
+ grpc::string GetMessageTypeFromMethod(const grpc::string& method,
+ bool is_request);
bool has_error_;
grpc::string request_text_;
- grpc::string full_method_name_;
- google::protobuf::compiler::DiskSourceTree source_tree_;
+ protobuf::compiler::DiskSourceTree source_tree_;
std::unique_ptr<ErrorPrinter> error_printer_;
- std::unique_ptr<google::protobuf::compiler::Importer> importer_;
- std::unique_ptr<grpc::ProtoReflectionDescriptorDatabase> desc_db_;
- std::unique_ptr<google::protobuf::DescriptorPool> desc_pool_;
- std::unique_ptr<google::protobuf::DynamicMessageFactory> dynamic_factory_;
+ std::unique_ptr<protobuf::compiler::Importer> importer_;
+ std::unique_ptr<grpc::ProtoReflectionDescriptorDatabase> reflection_db_;
+ std::unique_ptr<protobuf::DescriptorPoolDatabase> file_db_;
+ std::unique_ptr<protobuf::DescriptorDatabase> desc_db_;
+ std::unique_ptr<protobuf::DescriptorPool> desc_pool_;
+ std::unique_ptr<protobuf::DynamicMessageFactory> dynamic_factory_;
std::unique_ptr<grpc::protobuf::Message> request_prototype_;
std::unique_ptr<grpc::protobuf::Message> response_prototype_;
+ std::vector<const protobuf::ServiceDescriptor*> service_desc_list_;
};
} // namespace testing
diff --git a/test/cpp/util/proto_reflection_descriptor_database.cc b/test/cpp/util/proto_reflection_descriptor_database.cc
index 8fd466feb0..f0d14c686a 100644
--- a/test/cpp/util/proto_reflection_descriptor_database.cc
+++ b/test/cpp/util/proto_reflection_descriptor_database.cc
@@ -58,7 +58,7 @@ ProtoReflectionDescriptorDatabase::~ProtoReflectionDescriptorDatabase() {
stream_->WritesDone();
Status status = stream_->Finish();
if (!status.ok()) {
- gpr_log(GPR_ERROR,
+ gpr_log(GPR_INFO,
"ServerReflectionInfo rpc failed. Error code: %d, details: %s",
(int)status.error_code(), status.error_message().c_str());
}
diff --git a/test/distrib/csharp/DistribTest/App.config b/test/distrib/csharp/DistribTest/App.config
deleted file mode 100644
index 30d3e09472..0000000000
--- a/test/distrib/csharp/DistribTest/App.config
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
- <startup>
- <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
- </startup>
- <runtime>
- <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
- <dependentAssembly>
- <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
- <bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
- </dependentAssembly>
- </assemblyBinding>
- </runtime>
-</configuration> \ No newline at end of file
diff --git a/test/distrib/csharp/DistribTest/DistribTest.csproj b/test/distrib/csharp/DistribTest/DistribTest.csproj
index 1acb34d1b2..6ca03b2c80 100644
--- a/test/distrib/csharp/DistribTest/DistribTest.csproj
+++ b/test/distrib/csharp/DistribTest/DistribTest.csproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -41,6 +41,8 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
@@ -51,39 +53,15 @@
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
+ <WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BouncyCastle.Crypto">
- <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Auth">
- <HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Auth.PlatformServices">
- <HintPath>..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.PlatformServices.dll</HintPath>
- </Reference>
- <Reference Include="Google.Apis.Core">
- <HintPath>..\packages\Google.Apis.Core.1.9.3\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath>
- </Reference>
<Reference Include="Grpc.Auth">
<HintPath>..\packages\Grpc.Auth.__GRPC_NUGET_VERSION__\lib\net45\Grpc.Auth.dll</HintPath>
</Reference>
<Reference Include="Grpc.Core">
<HintPath>..\packages\Grpc.Core.__GRPC_NUGET_VERSION__\lib\net45\Grpc.Core.dll</HintPath>
</Reference>
- <Reference Include="Microsoft.Threading.Tasks">
- <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath>
- </Reference>
- <Reference Include="Microsoft.Threading.Tasks.Extensions">
- <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
- </Reference>
- <Reference Include="Microsoft.Threading.Tasks.Extensions.Desktop">
- <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll</HintPath>
- </Reference>
- <Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
- </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Interactive.Async">
@@ -91,25 +69,33 @@
</Reference>
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
- <Reference Include="System.Net.Http.Extensions">
- <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath>
- </Reference>
- <Reference Include="System.Net.Http.Primitives">
- <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath>
- </Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
+ <Reference Include="BouncyCastle.Crypto">
+ <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
+ </Reference>
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Apis.Core">
+ <HintPath>..\packages\Google.Apis.Core.1.15.0\lib\net45\Google.Apis.Core.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Apis.Auth">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Apis.Auth.PlatformServices">
+ <HintPath>..\packages\Google.Apis.Auth.1.15.0\lib\net45\Google.Apis.Auth.PlatformServices.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
- <None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
@@ -119,9 +105,7 @@
<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('..\packages\Grpc.Core.__GRPC_NUGET_VERSION__\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.__GRPC_NUGET_VERSION__\build\net45\Grpc.Core.targets'))" />
- <Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
</Target>
- <Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/test/distrib/csharp/DistribTest/packages.config b/test/distrib/csharp/DistribTest/packages.config
index 69630193d0..e5d2d9d383 100644
--- a/test/distrib/csharp/DistribTest/packages.config
+++ b/test/distrib/csharp/DistribTest/packages.config
@@ -1,15 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BouncyCastle" version="1.7.0" targetFramework="net45" />
- <package id="Google.Apis.Auth" version="1.9.3" targetFramework="net45" />
- <package id="Google.Apis.Core" version="1.9.3" targetFramework="net45" />
+ <package id="Google.Apis.Auth" version="1.15.0" targetFramework="net45" />
+ <package id="Google.Apis.Core" version="1.15.0" targetFramework="net45" />
<package id="Grpc" version="__GRPC_NUGET_VERSION__" targetFramework="net45" />
<package id="Grpc.Auth" version="__GRPC_NUGET_VERSION__" targetFramework="net45" />
<package id="Grpc.Core" version="__GRPC_NUGET_VERSION__" targetFramework="net45" />
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
- <package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" />
- <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="net45" />
- <package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net45" />
- <package id="Microsoft.Net.Http" version="2.2.29" targetFramework="net45" />
<package id="Newtonsoft.Json" version="7.0.1" targetFramework="net45" />
</packages>
diff --git a/test/distrib/python/distribtest.py b/test/distrib/python/distribtest.py
index dc20688140..0125ee6a56 100644
--- a/test/distrib/python/distribtest.py
+++ b/test/distrib/python/distribtest.py
@@ -27,10 +27,10 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-from grpc.beta import implementations
+import grpc
# This code doesn't do much but makes sure the native extension is loaded
# which is what we are testing here.
-channel = implementations.insecure_channel('localhost', 1000)
+channel = grpc.insecure_channel('localhost:1000')
del channel
print 'Success!'
diff --git a/third_party/thrift b/third_party/thrift
new file mode 160000
+Subproject bcad91771b7f0bff28a1cac1981d7ef2b9bcef3
diff --git a/tools/gce/create_linux_worker.sh b/tools/gce/create_linux_worker.sh
index 8a2df40859..7bf8b24081 100755
--- a/tools/gce/create_linux_worker.sh
+++ b/tools/gce/create_linux_worker.sh
@@ -43,8 +43,8 @@ gcloud compute instances create $INSTANCE_NAME \
--project="$CLOUD_PROJECT" \
--zone "$ZONE" \
--machine-type n1-standard-8 \
- --image-family=ubuntu-1510 \
- --image-project=ubuntu-os-cloud \
+ --image=ubuntu-1510 \
+ --image-project=grpc-testing \
--boot-disk-size 1000
echo 'Created GCE instance, waiting 60 seconds for it to come online.'
diff --git a/tools/gource/gen-all-logs.sh b/tools/gource/gen-all-logs.sh
index 85352c514e..ab60c3c1b1 100755
--- a/tools/gource/gen-all-logs.sh
+++ b/tools/gource/gen-all-logs.sh
@@ -41,7 +41,6 @@ do
git clone https://github.com/grpc/$repo.git
cd $repo
gource --output-custom-log $tmpdir/logs/$repo
- sed -i .backup "s,\|/,\|/$repo/,g" $tmpdir/logs/$repo
+ sed -i "s,|/,|/$repo/,g" $tmpdir/logs/$repo
done
-rm $tmpdir/logs/*.backup
cat $tmpdir/logs/* | sort -n > $outdir/all-logs.txt
diff --git a/tools/gource/gource.sh b/tools/gource/gource.sh
index b3dad5d7c7..5529b32bbd 100755
--- a/tools/gource/gource.sh
+++ b/tools/gource/gource.sh
@@ -34,7 +34,7 @@ gource \
--max-file-lag 0.05 \
--max-files 0 \
-e 0.01 \
- --hide filenames,dirnames \
+ --hide filenames,dirnames,mouse,progress \
--disable-auto-rotate \
--file-filter '/grpc/doc/ref' \
$*
diff --git a/tools/gource/make-video.sh b/tools/gource/make-video.sh
index 02d79df81b..cde0437255 100755
--- a/tools/gource/make-video.sh
+++ b/tools/gource/make-video.sh
@@ -37,7 +37,7 @@ $(dirname $0)/gource.sh \
--stop-at-end \
--output-ppm-stream - \
$@ | \
-ffmpeg \
+avconv \
-y \
-r 60 \
-f image2pipe \
diff --git a/tools/grift/Dockerfile b/tools/grift/Dockerfile
new file mode 100644
index 0000000000..223ee93992
--- /dev/null
+++ b/tools/grift/Dockerfile
@@ -0,0 +1,67 @@
+# 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.
+
+FROM ubuntu:14.04
+
+RUN apt-get update && \
+ apt-get install -y \
+ git build-essential \
+ pkg-config flex \
+ bison \
+ libkrb5-dev \
+ libsasl2-dev \
+ libnuma-dev \
+ pkg-config \
+ libssl-dev \
+ autoconf libtool \
+ cmake \
+ libiberty-dev \
+ g++ unzip \
+ curl make automake libtool libboost-dev
+
+# Configure git
+RUN git config --global user.name "Jenkins" && \
+ git config --global user.email "jenkins@grpc"
+
+# Clone gRPC
+RUN git clone https://github.com/grpc/grpc
+
+# Update Submodules
+RUN cd grpc && git submodule update --init
+
+# Install protobuf
+RUN cd grpc/third_party/protobuf && ./autogen.sh && ./configure && \
+ make -j && make check -j && make install && ldconfig
+
+# Install gRPC
+RUN cd grpc && make -j && make install
+
+# Install thrift
+RUN cd grpc/third_party/thrift && git am --signoff < ../../tools/grift/grpc_plugins_generator.patch && \
+ ./bootstrap.sh && ./configure && make -j && make install \ No newline at end of file
diff --git a/tools/grift/README.md b/tools/grift/README.md
new file mode 100644
index 0000000000..7cbbdc567b
--- /dev/null
+++ b/tools/grift/README.md
@@ -0,0 +1,26 @@
+Copyright 2016 Google Inc.
+
+#Documentation
+
+grift is integration of [Apache Thrift](https://github.com/apache/thrift.git) Serializer with gRPC.
+
+This integration allows you to use grpc to send thrift messages in C++ and java.
+
+grift uses Compact Protocol to serialize thrift messages.
+
+##generating grpc plugins for thrift services
+
+###CPP
+```sh
+ $ thrift --gen cpp <thrift-file>
+```
+
+###JAVA
+```sh
+ $ thrift --gen java <thrift-file>
+```
+
+#Installation
+
+Before Installing thrift make sure to apply this [patch](grpc_plugins_generator.patch) to third_party/thrift.
+Go to third_party/thrift and follow the [INSTALLATION](https://github.com/apache/thrift.git) instructions to install thrift with commit id bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c. \ No newline at end of file
diff --git a/tools/grift/grpc_plugins_generator.patch b/tools/grift/grpc_plugins_generator.patch
new file mode 100644
index 0000000000..de82a01f62
--- /dev/null
+++ b/tools/grift/grpc_plugins_generator.patch
@@ -0,0 +1,2505 @@
+From 0894590b5020c38106d4ebb2291994668c64f9dd Mon Sep 17 00:00:00 2001
+From: chedeti <chedeti@google.com>
+Date: Sun, 31 Jul 2016 15:47:47 -0700
+Subject: [PATCH 1/3] don't build tests
+
+---
+ Makefile.am | 7 ++-----
+ lib/cpp/Makefile.am | 7 ++-----
+ 2 files changed, 4 insertions(+), 10 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 10fe49a..d49caac 100755
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -21,10 +21,6 @@ ACLOCAL_AMFLAGS = -I ./aclocal
+
+ SUBDIRS = compiler/cpp lib
+
+-if WITH_TESTS
+-SUBDIRS += test
+-endif
+-
+ if WITH_TUTORIAL
+ SUBDIRS += tutorial
+ endif
+@@ -117,4 +113,5 @@ EXTRA_DIST = \
+ CHANGES \
+ NOTICE \
+ README.md \
+- Thrift.podspec
++ Thrift.podspec \
++ test
+diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am
+index 6fd15d2..7de1fad 100755
+--- a/lib/cpp/Makefile.am
++++ b/lib/cpp/Makefile.am
+@@ -27,10 +27,6 @@ moc__%.cpp: %.h
+
+ SUBDIRS = .
+
+-if WITH_TESTS
+-SUBDIRS += test
+-endif
+-
+ pkgconfigdir = $(libdir)/pkgconfig
+
+ lib_LTLIBRARIES = libthrift.la
+@@ -277,7 +273,8 @@ EXTRA_DIST = \
+ thrift-qt.pc.in \
+ thrift-qt5.pc.in \
+ src/thrift/qt/CMakeLists.txt \
+- $(WINDOWS_DIST)
++ $(WINDOWS_DIST) \
++ test
+
+ style-local:
+ $(CPPSTYLE_CMD)
+--
+2.8.0.rc3.226.g39d4020
+
+
+From 387e4300bc9d98176a92a7c010621443a538e7f2 Mon Sep 17 00:00:00 2001
+From: chedeti <chedeti@google.com>
+Date: Sun, 31 Jul 2016 16:16:40 -0700
+Subject: [PATCH 2/3] grpc cpp plugins generator with example
+
+---
+ compiler/cpp/src/generate/t_cpp_generator.cc | 489 +++++++++++++++++++++++----
+ tutorial/cpp/CMakeLists.txt | 53 ---
+ tutorial/cpp/CppClient.cpp | 80 -----
+ tutorial/cpp/CppServer.cpp | 181 ----------
+ tutorial/cpp/GriftClient.cpp | 93 +++++
+ tutorial/cpp/GriftServer.cpp | 93 +++++
+ tutorial/cpp/Makefile.am | 66 ++--
+ tutorial/cpp/test.thrift | 13 +
+ 8 files changed, 652 insertions(+), 416 deletions(-)
+ delete mode 100644 tutorial/cpp/CMakeLists.txt
+ delete mode 100644 tutorial/cpp/CppClient.cpp
+ delete mode 100644 tutorial/cpp/CppServer.cpp
+ create mode 100644 tutorial/cpp/GriftClient.cpp
+ create mode 100644 tutorial/cpp/GriftServer.cpp
+ create mode 100644 tutorial/cpp/test.thrift
+
+diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
+index 6c04899..1557241 100644
+--- a/compiler/cpp/src/generate/t_cpp_generator.cc
++++ b/compiler/cpp/src/generate/t_cpp_generator.cc
+@@ -162,6 +162,8 @@ public:
+ bool specialized = false);
+ void generate_function_helpers(t_service* tservice, t_function* tfunction);
+ void generate_service_async_skeleton(t_service* tservice);
++ void generate_service_stub_interface(t_service* tservice);
++ void generate_service_stub(t_service* tservice);
+
+ /**
+ * Serialization constructs
+@@ -883,10 +885,10 @@ void t_cpp_generator::generate_struct_declaration(ofstream& out,
+ bool is_user_struct) {
+ string extends = "";
+ if (is_exception) {
+- extends = " : public ::apache::thrift::TException";
++ extends = " : public apache::thrift::TException";
+ } else {
+- if (is_user_struct && !gen_templates_) {
+- extends = " : public virtual ::apache::thrift::TBase";
++ if (!gen_templates_) {
++ extends = " : public virtual apache::thrift::TBase";
+ }
+ }
+
+@@ -1130,9 +1132,15 @@ void t_cpp_generator::generate_struct_definition(ofstream& out,
+ vector<t_field*>::const_iterator m_iter;
+ const vector<t_field*>& members = tstruct->get_members();
+
++ string method_prefix = "";
++ if (service_name_ != "") {
++ method_prefix = service_name_ + "::";
++ }
++
+ // Destructor
+ if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) {
+- force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name()
++ force_cpp_out << endl << indent() << method_prefix <<
++ tstruct->get_name() << "::~" << tstruct->get_name()
+ << "() throw() {" << endl;
+ indent_up();
+
+@@ -1145,12 +1153,14 @@ void t_cpp_generator::generate_struct_definition(ofstream& out,
+ for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+ if (is_reference((*m_iter))) {
+ std::string type = type_name((*m_iter)->get_type());
+- out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
++ out << endl << indent() << "void " << method_prefix
++ << tstruct->get_name() << "::__set_"
+ << (*m_iter)->get_name() << "(boost::shared_ptr<"
+ << type_name((*m_iter)->get_type(), false, false) << ">";
+ out << " val) {" << endl;
+ } else {
+- out << endl << indent() << "void " << tstruct->get_name() << "::__set_"
++ out << endl << indent() << "void " << method_prefix
++ << tstruct->get_name() << "::__set_"
+ << (*m_iter)->get_name() << "(" << type_name((*m_iter)->get_type(), false, true);
+ out << " val) {" << endl;
+ }
+@@ -1177,11 +1187,16 @@ void t_cpp_generator::generate_struct_definition(ofstream& out,
+ * @param tstruct The struct
+ */
+ void t_cpp_generator::generate_struct_reader(ofstream& out, t_struct* tstruct, bool pointers) {
++ string method_prefix = "";
++ if (service_name_ != "") {
++ method_prefix = service_name_ + "::";
++ }
++
+ if (gen_templates_) {
+ out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+- << tstruct->get_name() << "::read(Protocol_* iprot) {" << endl;
++ << method_prefix << tstruct->get_name() << "::read(Protocol_* iprot) {" << endl;
+ } else {
+- indent(out) << "uint32_t " << tstruct->get_name()
++ indent(out) << "uint32_t " << method_prefix << tstruct->get_name()
+ << "::read(::apache::thrift::protocol::TProtocol* iprot) {" << endl;
+ }
+ indent_up();
+@@ -1301,14 +1316,18 @@ void t_cpp_generator::generate_struct_reader(ofstream& out, t_struct* tstruct, b
+ */
+ void t_cpp_generator::generate_struct_writer(ofstream& out, t_struct* tstruct, bool pointers) {
+ string name = tstruct->get_name();
++ string method_prefix = "";
++ if (service_name_ != "") {
++ method_prefix = service_name_ + "::";
++ }
+ const vector<t_field*>& fields = tstruct->get_sorted_members();
+ vector<t_field*>::const_iterator f_iter;
+
+ if (gen_templates_) {
+ out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+- << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
++ << method_prefix << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
+ } else {
+- indent(out) << "uint32_t " << tstruct->get_name()
++ indent(out) << "uint32_t " << method_prefix << tstruct->get_name()
+ << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl;
+ }
+ indent_up();
+@@ -1369,14 +1388,18 @@ void t_cpp_generator::generate_struct_result_writer(ofstream& out,
+ t_struct* tstruct,
+ bool pointers) {
+ string name = tstruct->get_name();
++ string method_prefix = "";
++ if (service_name_ != "") {
++ method_prefix = service_name_ + "::";
++ }
+ const vector<t_field*>& fields = tstruct->get_sorted_members();
+ vector<t_field*>::const_iterator f_iter;
+
+ if (gen_templates_) {
+ out << indent() << "template <class Protocol_>" << endl << indent() << "uint32_t "
+- << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
++ << method_prefix << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl;
+ } else {
+- indent(out) << "uint32_t " << tstruct->get_name()
++ indent(out) << "uint32_t " << method_prefix << tstruct->get_name()
+ << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl;
+ }
+ indent_up();
+@@ -1385,18 +1408,7 @@ void t_cpp_generator::generate_struct_result_writer(ofstream& out,
+
+ indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl;
+
+- bool first = true;
+ for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+- if (first) {
+- first = false;
+- out << endl << indent() << "if ";
+- } else {
+- out << " else if ";
+- }
+-
+- out << "(this->__isset." << (*f_iter)->get_name() << ") {" << endl;
+-
+- indent_up();
+
+ // Write field header
+ out << indent() << "xfer += oprot->writeFieldBegin("
+@@ -1410,9 +1422,6 @@ void t_cpp_generator::generate_struct_result_writer(ofstream& out,
+ }
+ // Write field closer
+ indent(out) << "xfer += oprot->writeFieldEnd();" << endl;
+-
+- indent_down();
+- indent(out) << "}";
+ }
+
+ // Write the struct map
+@@ -1478,9 +1487,13 @@ void t_cpp_generator::generate_struct_ostream_operator(std::ofstream& out, t_str
+ }
+
+ void t_cpp_generator::generate_struct_print_method_decl(std::ofstream& out, t_struct* tstruct) {
++ string method_prefix = "";
++ if (service_name_ != "") {
++ method_prefix = service_name_ + "::";
++ }
+ out << "void ";
+ if (tstruct) {
+- out << tstruct->get_name() << "::";
++ out << method_prefix << tstruct->get_name() << "::";
+ }
+ out << "printTo(std::ostream& out) const";
+ }
+@@ -1601,11 +1614,13 @@ void t_cpp_generator::generate_exception_what_method(std::ofstream& out, t_struc
+ */
+ void t_cpp_generator::generate_service(t_service* tservice) {
+ string svcname = tservice->get_name();
++ string ns = tservice->get_program()->get_namespace("cpp");
+
+ // Make output files
+- string f_header_name = get_out_dir() + svcname + ".h";
++ string f_header_name = get_out_dir() + svcname + ".grpc.thrift.h";
+ f_header_.open(f_header_name.c_str());
+
++
+ // Print header file includes
+ f_header_ << autogen_comment();
+ f_header_ << "#ifndef " << svcname << "_H" << endl << "#define " << svcname << "_H" << endl
+@@ -1621,15 +1636,38 @@ void t_cpp_generator::generate_service(t_service* tservice) {
+ f_header_ << "#include <thrift/async/TAsyncDispatchProcessor.h>" << endl;
+ }
+ f_header_ << "#include <thrift/async/TConcurrentClientSyncInfo.h>" << endl;
++
+ f_header_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\""
+ << endl;
+
+ t_service* extends_service = tservice->get_extends();
+- if (extends_service != NULL) {
++ if (extends_service) {
+ f_header_ << "#include \"" << get_include_prefix(*(extends_service->get_program()))
+- << extends_service->get_name() << ".h\"" << endl;
++ << extends_service->get_name() << ".grpc.thrift.h\"" << endl;
+ }
+
++
++ f_header_ <<
++ "#include <grpc++/impl/codegen/async_stream.h>" << endl <<
++ "#include <grpc++/impl/codegen/async_unary_call.h>" << endl <<
++ "#include <grpc++/impl/codegen/thrift_utils.h>" << endl <<
++ "#include <grpc++/impl/codegen/rpc_method.h>" << endl <<
++ "#include <grpc++/impl/codegen/service_type.h>" << endl <<
++ "#include <grpc++/impl/codegen/status.h>" << endl <<
++ "#include <grpc++/impl/codegen/stub_options.h>" << endl <<
++ "#include <grpc++/impl/codegen/sync_stream.h>" << endl;
++
++
++ f_header_ <<
++ endl <<
++ "namespace grpc {" << endl <<
++ "class CompletionQueue;" << endl <<
++ "class Channel;" << endl <<
++ "class RpcService;" << endl <<
++ "class ServerCompletionQueue;" << endl <<
++ "class ServerContext;" << endl <<
++ "}" << endl;
++
+ f_header_ << endl << ns_open_ << endl << endl;
+
+ f_header_ << "#ifdef _WIN32\n"
+@@ -1638,10 +1676,13 @@ void t_cpp_generator::generate_service(t_service* tservice) {
+ "#endif\n\n";
+
+ // Service implementation file includes
+- string f_service_name = get_out_dir() + svcname + ".cpp";
++ string f_service_name = get_out_dir() + svcname + ".grpc.thrift.cpp";
+ f_service_.open(f_service_name.c_str());
+ f_service_ << autogen_comment();
+- f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl;
++
++ f_service_ << "#include \"" <<
++ get_include_prefix(*get_program()) << svcname << ".grpc.thrift.h\"" << endl;
++
+ if (gen_cob_style_) {
+ f_service_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl;
+ }
+@@ -1652,7 +1693,7 @@ void t_cpp_generator::generate_service(t_service* tservice) {
+ string f_service_tcc_name = get_out_dir() + svcname + ".tcc";
+ f_service_tcc_.open(f_service_tcc_name.c_str());
+ f_service_tcc_ << autogen_comment();
+- f_service_tcc_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\""
++ f_service_tcc_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".grpc.thrift.h\""
+ << endl;
+
+ f_service_tcc_ << "#ifndef " << svcname << "_TCC" << endl << "#define " << svcname << "_TCC"
+@@ -1663,19 +1704,69 @@ void t_cpp_generator::generate_service(t_service* tservice) {
+ }
+ }
+
++ f_service_ <<
++ endl <<
++ "#include <grpc++/impl/codegen/async_stream.h>" << endl <<
++ "#include <grpc++/impl/codegen/async_unary_call.h>" << endl <<
++ "#include <grpc++/impl/codegen/channel_interface.h>" << endl <<
++ "#include <grpc++/impl/codegen/client_unary_call.h>" << endl <<
++ "#include <grpc++/impl/codegen/method_handler_impl.h>" << endl <<
++ "#include <grpc++/impl/codegen/rpc_service_method.h>" << endl <<
++ "#include <grpc++/impl/codegen/service_type.h>" << endl <<
++ "#include <grpc++/impl/codegen/sync_stream.h>" << endl <<
++ endl;
++
+ f_service_ << endl << ns_open_ << endl << endl;
+ f_service_tcc_ << endl << ns_open_ << endl << endl;
+
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++
++ f_service_ <<
++ "static const char* " << service_name_ << "_method_names[] = {" << endl;
++
++
++ indent_up();
++
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "\"/" << ns << "." << service_name_ << "/" << (*f_iter)->get_name() << "\"," << endl;
++ }
++
++
++ t_service* service_iter = extends_service;
++ while (service_iter) {
++ vector<t_function*> functions = service_iter->get_functions();
++ vector<t_function*>::iterator f_iter;
++
++ for ( f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "\"/" << service_iter->get_program()->get_namespace("cpp") <<
++ "." << service_iter->get_name() << "/" << (*f_iter)->get_name() << "\"," << endl;
++ }
++ service_iter = service_iter->get_extends();
++ }
++
++ indent_down();
++ f_service_ <<
++ "};" << endl;
++
++ // Generate service class
++ if ( extends_service) {
++ f_header_ << "class " << service_name_ << " : public " <<
++ type_name(extends_service) << " {" << endl <<
++ "public:" << endl;
++ }
++ else {
++ f_header_ << "class " << service_name_ << "{" << endl <<
++ "public:" << endl;
++ }
++
+ // Generate all the components
+- generate_service_interface(tservice, "");
+- generate_service_interface_factory(tservice, "");
+- generate_service_null(tservice, "");
+ generate_service_helpers(tservice);
+- generate_service_client(tservice, "");
+- generate_service_processor(tservice, "");
+- generate_service_multiface(tservice);
+- generate_service_skeleton(tservice);
+- generate_service_client(tservice, "Concurrent");
++ generate_service_interface(tservice, "");
++ generate_service_stub_interface(tservice);
++ generate_service_stub(tservice);
+
+ // Generate all the cob components
+ if (gen_cob_style_) {
+@@ -1688,10 +1779,14 @@ void t_cpp_generator::generate_service(t_service* tservice) {
+ generate_service_async_skeleton(tservice);
+ }
+
++ // Close service class
++ f_header_ << "};" << endl;
++
+ f_header_ << "#ifdef _WIN32\n"
+ " #pragma warning( pop )\n"
+ "#endif\n\n";
+
++
+ // Close the namespace
+ f_service_ << ns_close_ << endl << endl;
+ f_service_tcc_ << ns_close_ << endl << endl;
+@@ -1729,15 +1824,11 @@ void t_cpp_generator::generate_service_helpers(t_service* tservice) {
+ string name_orig = ts->get_name();
+
+ // TODO(dreiss): Why is this stuff not in generate_function_helpers?
+- ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args");
++ ts->set_name((*f_iter)->get_name() + "Req");
+ generate_struct_declaration(f_header_, ts, false);
+- generate_struct_definition(out, f_service_, ts, false);
++ generate_struct_definition(out, f_service_, ts, true);
+ generate_struct_reader(out, ts);
+ generate_struct_writer(out, ts);
+- ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs");
+- generate_struct_declaration(f_header_, ts, false, true, false, true);
+- generate_struct_definition(out, f_service_, ts, false);
+- generate_struct_writer(out, ts, true);
+ ts->set_name(name_orig);
+
+ generate_function_helpers(tservice, *f_iter);
+@@ -1745,13 +1836,218 @@ void t_cpp_generator::generate_service_helpers(t_service* tservice) {
+ }
+
+ /**
++ * Generates a service Stub Interface
++ *
++ * @param tservice The service to generate a stub for.
++ *
++ */
++void t_cpp_generator::generate_service_stub_interface(t_service* tservice) {
++
++ string extends = "";
++ if (tservice->get_extends()) {
++ extends = " : virtual public " + type_name(tservice->get_extends()) + "::StubInterface";
++ }
++
++ f_header_ <<
++ endl <<
++ "class StubInterface " << extends << " {" << endl;
++ indent_up();
++ f_header_ <<
++ " public:" << endl <<
++ indent() << "virtual ~StubInterface() {}" << endl;
++
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ string function_name = (*f_iter)->get_name();
++ f_header_ <<
++ indent() << "virtual ::grpc::Status " << function_name <<
++ "(::grpc::ClientContext* context, const " << function_name <<
++ "Req& request, " << function_name << "Resp* response) = 0;" << endl;
++ }
++ indent_down();
++ f_header_ <<
++ "};" << endl << endl;
++
++}
++void t_cpp_generator::generate_service_stub(t_service* tservice) {
++ f_header_ <<
++ endl <<
++ "class Stub : public StubInterface {" <<
++ endl;
++
++ indent_up();
++ f_header_ <<
++ " public:" << endl <<
++ indent() << "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);" <<
++ endl;
++
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ string function_name = (*f_iter)->get_name();
++ f_header_ <<
++ indent() << "::grpc::Status " << function_name <<
++ "(::grpc::ClientContext* context, const " << function_name <<
++ "Req& request, " << function_name << "Resp* response) override;" << endl;
++ }
++
++ t_service* extends_service = tservice->get_extends();
++ t_service* service_iter = extends_service;
++ while (service_iter) {
++ // generate inherited methods
++ vector<t_function*> functions = service_iter->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ string function_name = (*f_iter)->get_name();
++ f_header_ <<
++ indent() << "::grpc::Status " << function_name <<
++ "(::grpc::ClientContext* context, const " << function_name <<
++ "Req& request, " << function_name << "Resp* response) override;" << endl;
++ }
++ service_iter = service_iter->get_extends();
++ }
++
++ f_header_ <<
++ endl <<
++ " private:" << endl <<
++ indent() << "std::shared_ptr< ::grpc::ChannelInterface> channel_;" <<
++ endl;
++
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_header_ <<
++ indent() << "const ::grpc::RpcMethod rpcmethod_" << (*f_iter)->get_name() << "_;" << endl;
++ }
++
++ service_iter = extends_service;
++ while (service_iter) {
++ // generate inherited methods
++ vector<t_function*> functions = service_iter->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_header_ <<
++ indent() << "const ::grpc::RpcMethod rpcmethod_" << (*f_iter)->get_name() << "_;" << endl;
++ }
++ service_iter = service_iter->get_extends();
++ }
++
++ indent_down();
++ f_header_ <<
++ "};" << endl << endl;
++
++ // generate the implementaion of Stub
++ f_service_ <<
++ endl <<
++ service_name_ << "::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel)" << endl;
++
++ indent_up();
++ f_service_ <<
++ indent() << ": channel_(channel)" << endl;
++ int i=0;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter , ++i) {
++ f_service_ <<
++ indent() <<
++ ", rpcmethod_" << (*f_iter)->get_name() << "_(" <<
++ service_name_ << "_method_names[" << i << "], ::grpc::RpcMethod::NORMAL_RPC, channel)" << endl;
++ }
++
++ service_iter = extends_service;
++ while (service_iter) {
++ // generate inherited methods
++ vector<t_function*> functions = service_iter->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter, ++i) {
++ f_service_ <<
++ indent() <<
++ ", rpcmethod_" << (*f_iter)->get_name() << "_(" <<
++ service_name_ << "_method_names[" << i << "], ::grpc::RpcMethod::NORMAL_RPC, channel)" << endl;
++ }
++ service_iter = service_iter->get_extends();
++ }
++ f_service_ <<
++ indent() << "{}" << endl;
++ indent_down();
++
++ // generate NewStub
++ f_header_ <<
++ endl <<
++ "static std::unique_ptr<Stub> NewStub(const std::shared_ptr\
++ < ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions());" <<
++ endl;
++
++ // generate NewStub Implementation
++ f_service_ <<
++ endl <<
++ "std::unique_ptr< " << service_name_ << "::Stub> " << service_name_ << "::NewStub(const std::shared_ptr\
++ < ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) {" << endl;
++
++ indent_up();
++ f_service_ <<
++ indent() << "std::unique_ptr< " << service_name_ << "::Stub> stub(new " << service_name_ <<
++ "::Stub(channel));" << endl <<
++ indent() << "return stub;" << endl;
++ indent_down();
++ f_service_ <<
++ "}" << endl;
++
++ // generate stub methods
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ string function_name = (*f_iter)->get_name();
++ f_service_ <<
++ endl <<
++ "::grpc::Status " << service_name_ << "::Stub::" << function_name <<
++ "(::grpc::ClientContext* context, const " << service_name_ << "::" <<
++ function_name << "Req& request, " << service_name_ << "::" <<
++ function_name << "Resp* response) {" << endl;
++
++ indent_up();
++ f_service_ <<
++ indent() << "return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_" <<
++ function_name << "_, context, request, response);" << endl;
++ indent_down();
++
++ f_service_ <<
++ "}" << endl;
++
++ }
++
++ service_iter = extends_service;
++ while (service_iter) {
++ vector<t_function*> functions = service_iter->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ string function_name = (*f_iter)->get_name();
++ f_service_ <<
++ endl <<
++ "::grpc::Status " << service_name_ << "::Stub::" << function_name <<
++ "(::grpc::ClientContext* context, const " << service_name_ << "::" <<
++ function_name << "Req& request, " << service_name_ << "::" <<
++ function_name << "Resp* response) {" << endl;
++
++ indent_up();
++ f_service_ <<
++ indent() << "return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_" <<
++ function_name << "_, context, request, response);" << endl;
++ indent_down();
++
++ f_service_ <<
++ "}" << endl;
++
++ }
++ service_iter = service_iter->get_extends();
++ }
++
++}
++
++
++/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+ void t_cpp_generator::generate_service_interface(t_service* tservice, string style) {
+
+- string service_if_name = service_name_ + style + "If";
++ string service_if_name = "Service";
+ if (style == "CobCl") {
+ // Forward declare the client.
+ string client_name = service_name_ + "CobClient";
+@@ -1764,13 +2060,15 @@ void t_cpp_generator::generate_service_interface(t_service* tservice, string sty
+ }
+
+ string extends = "";
+- if (tservice->get_extends() != NULL) {
+- extends = " : virtual public " + type_name(tservice->get_extends()) + style + "If";
++ if (tservice->get_extends()) {
++ extends = " : virtual public " + type_name(tservice->get_extends()) + style + "::Service";
+ if (style == "CobCl" && gen_templates_) {
+ // TODO(simpkins): If gen_templates_ is enabled, we currently assume all
+ // parent services were also generated with templates enabled.
+ extends += "T<Protocol_>";
+ }
++ } else {
++ extends = " : public ::grpc::Service";
+ }
+
+ if (style == "CobCl" && gen_templates_) {
+@@ -1778,7 +2076,9 @@ void t_cpp_generator::generate_service_interface(t_service* tservice, string sty
+ }
+ f_header_ << "class " << service_if_name << extends << " {" << endl << " public:" << endl;
+ indent_up();
+- f_header_ << indent() << "virtual ~" << service_if_name << "() {}" << endl;
++
++ f_header_ << indent() << "Service();" << endl;
++ f_header_ << indent() << "virtual ~Service();" << endl;
+
+ vector<t_function*> functions = tservice->get_functions();
+ vector<t_function*>::iterator f_iter;
+@@ -1786,7 +2086,12 @@ void t_cpp_generator::generate_service_interface(t_service* tservice, string sty
+ if ((*f_iter)->has_doc())
+ f_header_ << endl;
+ generate_java_doc(f_header_, *f_iter);
+- f_header_ << indent() << "virtual " << function_signature(*f_iter, style) << " = 0;" << endl;
++
++ string function_name = (*f_iter)->get_name();
++ f_header_ <<
++ indent() << "virtual ::grpc::Status " << function_name <<
++ "(::grpc::ServerContext* context, const "<< function_name <<
++ "Req* request, "<< function_name << "Resp* response);" << endl;
+ }
+ indent_down();
+ f_header_ << "};" << endl << endl;
+@@ -1797,6 +2102,66 @@ void t_cpp_generator::generate_service_interface(t_service* tservice, string sty
+ f_header_ << "typedef " << service_if_name << "< ::apache::thrift::protocol::TProtocol> "
+ << service_name_ << style << "If;" << endl << endl;
+ }
++
++ // generate the service interface implementations
++
++ f_service_ <<
++ endl <<
++ service_name_ << "::Service::Service() {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "(void)" << service_name_ << "_method_names;" << endl;
++ uint32_t i=0;
++ for(i=0;i<functions.size(); i++) {
++ string function_name = functions[i]->get_name();
++ f_service_ <<
++ endl <<
++ indent() << "AddMethod(new ::grpc::RpcServiceMethod(" << endl;
++ indent_up();
++
++ f_service_ <<
++ indent() << service_name_ << "_method_names[" << i << "]," << endl <<
++ indent() << "::grpc::RpcMethod::NORMAL_RPC," << endl <<
++ indent() << "new ::grpc::RpcMethodHandler< " << service_name_ << "::Service, " <<
++ service_name_ << "::" << function_name << "Req, " << service_name_ << "::" <<
++ function_name << "Resp>(" << endl;
++
++ indent_up();
++ f_service_ <<
++ indent() << "std::mem_fn(&" << service_name_ << "::Service::" << function_name << "), this)));" << endl;
++
++ indent_down();
++ indent_down();
++ }
++
++ indent_down();
++ f_service_ <<
++ "}" << endl;
++
++ f_service_ <<
++ endl <<
++ service_name_ << "::Service::~Service() {" << endl <<
++ "}" << endl;
++
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ string function_name = (*f_iter)->get_name();
++ f_service_ <<
++ endl <<
++ "::grpc::Status " << service_name_ << "::Service::" << function_name <<
++ "(::grpc::ServerContext* context, const " << service_name_ << "::" << function_name <<
++ "Req* request, " << service_name_ << "::" << function_name << "Resp* response) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "(void) context;" << endl <<
++ indent() << "(void) request;" << endl <<
++ indent() << "(void) response;" << endl <<
++ indent() << "return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED,\"\");" << endl;
++ indent_down();
++
++ f_service_ <<
++ "}" << endl;
++ }
++
+ }
+
+ /**
+@@ -3095,7 +3460,7 @@ void t_cpp_generator::generate_function_helpers(t_service* tservice, t_function*
+
+ std::ofstream& out = (gen_templates_ ? f_service_tcc_ : f_service_);
+
+- t_struct result(program_, tservice->get_name() + "_" + tfunction->get_name() + "_result");
++ t_struct result(program_, tfunction->get_name() + "Resp");
+ t_field success(tfunction->get_returntype(), "success", 0);
+ if (!tfunction->get_returntype()->is_void()) {
+ result.append(&success);
+@@ -3109,17 +3474,9 @@ void t_cpp_generator::generate_function_helpers(t_service* tservice, t_function*
+ }
+
+ generate_struct_declaration(f_header_, &result, false);
+- generate_struct_definition(out, f_service_, &result, false);
++ generate_struct_definition(out, f_service_, &result, true);
+ generate_struct_reader(out, &result);
+ generate_struct_result_writer(out, &result);
+-
+- result.set_name(tservice->get_name() + "_" + tfunction->get_name() + "_presult");
+- generate_struct_declaration(f_header_, &result, false, true, true, gen_cob_style_);
+- generate_struct_definition(out, f_service_, &result, false);
+- generate_struct_reader(out, &result, true);
+- if (gen_cob_style_) {
+- generate_struct_writer(out, &result, true);
+- }
+ }
+
+ /**
+@@ -3162,8 +3519,8 @@ void t_cpp_generator::generate_process_function(t_service* tservice,
+ << endl;
+ scope_up(out);
+
+- string argsname = tservice->get_name() + "_" + tfunction->get_name() + "_args";
+- string resultname = tservice->get_name() + "_" + tfunction->get_name() + "_result";
++ string argsname = tfunction->get_name() + "Req";
++ string resultname = tfunction->get_name() + "Resp";
+
+ if (tfunction->is_oneway() && !unnamed_oprot_seqid) {
+ out << indent() << "(void) seqid;" << endl << indent() << "(void) oprot;" << endl;
+@@ -3320,7 +3677,7 @@ void t_cpp_generator::generate_process_function(t_service* tservice,
+ out << indent() << "(void) seqid;" << endl << indent() << "(void) oprot;" << endl;
+ }
+
+- out << indent() << tservice->get_name() + "_" + tfunction->get_name() << "_args args;" << endl
++ out << indent() << tfunction->get_name() << "Req args;" << endl
+ << indent() << "void* ctx = NULL;" << endl << indent()
+ << "if (this->eventHandler_.get() != NULL) {" << endl << indent()
+ << " ctx = this->eventHandler_->getContext(" << service_func_name << ", NULL);" << endl
+@@ -3487,7 +3844,7 @@ void t_cpp_generator::generate_process_function(t_service* tservice,
+ << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl;
+
+ // Throw the TDelayedException, and catch the result
+- out << indent() << tservice->get_name() << "_" << tfunction->get_name() << "_result result;"
++ out << indent() << tfunction->get_name() << "Resp result;"
+ << endl << endl << indent() << "try {" << endl;
+ indent_up();
+ out << indent() << "_throw->throw_it();" << endl << indent() << "return cob(false);"
+diff --git a/tutorial/cpp/CMakeLists.txt b/tutorial/cpp/CMakeLists.txt
+deleted file mode 100644
+index 8a3d085..0000000
+--- a/tutorial/cpp/CMakeLists.txt
++++ /dev/null
+@@ -1,53 +0,0 @@
+-#
+-# Licensed to the Apache Software Foundation (ASF) under one
+-# or more contributor license agreements. See the NOTICE file
+-# distributed with this work for additional information
+-# regarding copyright ownership. The ASF licenses this file
+-# to you under the Apache License, Version 2.0 (the
+-# "License"); you may not use this file except in compliance
+-# with the License. You may obtain a copy of the License at
+-#
+-# http://www.apache.org/licenses/LICENSE-2.0
+-#
+-# Unless required by applicable law or agreed to in writing,
+-# software distributed under the License is distributed on an
+-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-# KIND, either express or implied. See the License for the
+-# specific language governing permissions and limitations
+-# under the License.
+-#
+-
+-find_package(Boost 1.53.0 REQUIRED)
+-include_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
+-
+-#Make sure gen-cpp files can be included
+-include_directories("${CMAKE_CURRENT_BINARY_DIR}")
+-include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp")
+-include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src")
+-
+-include(ThriftMacros)
+-
+-set(tutorialgencpp_SOURCES
+- gen-cpp/Calculator.cpp
+- gen-cpp/SharedService.cpp
+- gen-cpp/shared_constants.cpp
+- gen-cpp/shared_types.cpp
+- gen-cpp/tutorial_constants.cpp
+- gen-cpp/tutorial_types.cpp
+-)
+-add_library(tutorialgencpp STATIC ${tutorialgencpp_SOURCES})
+-LINK_AGAINST_THRIFT_LIBRARY(tutorialgencpp thrift)
+-
+-add_custom_command(OUTPUT gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_constants.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp
+- COMMAND ${THRIFT_COMPILER} --gen cpp -r ${PROJECT_SOURCE_DIR}/tutorial/tutorial.thrift
+-)
+-
+-add_executable(TutorialServer CppServer.cpp)
+-target_link_libraries(TutorialServer tutorialgencpp)
+-LINK_AGAINST_THRIFT_LIBRARY(TutorialServer thrift)
+-target_link_libraries(TutorialServer ${ZLIB_LIBRARIES})
+-
+-add_executable(TutorialClient CppClient.cpp)
+-target_link_libraries(TutorialClient tutorialgencpp)
+-LINK_AGAINST_THRIFT_LIBRARY(TutorialClient thrift)
+-target_link_libraries(TutorialClient ${ZLIB_LIBRARIES})
+diff --git a/tutorial/cpp/CppClient.cpp b/tutorial/cpp/CppClient.cpp
+deleted file mode 100644
+index 2763fee..0000000
+--- a/tutorial/cpp/CppClient.cpp
++++ /dev/null
+@@ -1,80 +0,0 @@
+-/*
+- * Licensed to the Apache Software Foundation (ASF) under one
+- * or more contributor license agreements. See the NOTICE file
+- * distributed with this work for additional information
+- * regarding copyright ownership. The ASF licenses this file
+- * to you under the Apache License, Version 2.0 (the
+- * "License"); you may not use this file except in compliance
+- * with the License. You may obtain a copy of the License at
+- *
+- * http://www.apache.org/licenses/LICENSE-2.0
+- *
+- * Unless required by applicable law or agreed to in writing,
+- * software distributed under the License is distributed on an
+- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+- * KIND, either express or implied. See the License for the
+- * specific language governing permissions and limitations
+- * under the License.
+- */
+-
+-#include <iostream>
+-
+-#include <thrift/protocol/TBinaryProtocol.h>
+-#include <thrift/transport/TSocket.h>
+-#include <thrift/transport/TTransportUtils.h>
+-
+-#include "../gen-cpp/Calculator.h"
+-
+-using namespace std;
+-using namespace apache::thrift;
+-using namespace apache::thrift::protocol;
+-using namespace apache::thrift::transport;
+-
+-using namespace tutorial;
+-using namespace shared;
+-
+-int main() {
+- boost::shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
+- boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
+- boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
+- CalculatorClient client(protocol);
+-
+- try {
+- transport->open();
+-
+- client.ping();
+- cout << "ping()" << endl;
+-
+- cout << "1 + 1 = " << client.add(1, 1) << endl;
+-
+- Work work;
+- work.op = Operation::DIVIDE;
+- work.num1 = 1;
+- work.num2 = 0;
+-
+- try {
+- client.calculate(1, work);
+- cout << "Whoa? We can divide by zero!" << endl;
+- } catch (InvalidOperation& io) {
+- cout << "InvalidOperation: " << io.why << endl;
+- // or using generated operator<<: cout << io << endl;
+- // or by using std::exception native method what(): cout << io.what() << endl;
+- }
+-
+- work.op = Operation::SUBTRACT;
+- work.num1 = 15;
+- work.num2 = 10;
+- int32_t diff = client.calculate(1, work);
+- cout << "15 - 10 = " << diff << endl;
+-
+- // Note that C++ uses return by reference for complex types to avoid
+- // costly copy construction
+- SharedStruct ss;
+- client.getStruct(ss, 1);
+- cout << "Received log: " << ss << endl;
+-
+- transport->close();
+- } catch (TException& tx) {
+- cout << "ERROR: " << tx.what() << endl;
+- }
+-}
+diff --git a/tutorial/cpp/CppServer.cpp b/tutorial/cpp/CppServer.cpp
+deleted file mode 100644
+index eafffa9..0000000
+--- a/tutorial/cpp/CppServer.cpp
++++ /dev/null
+@@ -1,181 +0,0 @@
+-/*
+- * Licensed to the Apache Software Foundation (ASF) under one
+- * or more contributor license agreements. See the NOTICE file
+- * distributed with this work for additional information
+- * regarding copyright ownership. The ASF licenses this file
+- * to you under the Apache License, Version 2.0 (the
+- * "License"); you may not use this file except in compliance
+- * with the License. You may obtain a copy of the License at
+- *
+- * http://www.apache.org/licenses/LICENSE-2.0
+- *
+- * Unless required by applicable law or agreed to in writing,
+- * software distributed under the License is distributed on an
+- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+- * KIND, either express or implied. See the License for the
+- * specific language governing permissions and limitations
+- * under the License.
+- */
+-
+-#include <thrift/concurrency/ThreadManager.h>
+-#include <thrift/concurrency/PlatformThreadFactory.h>
+-#include <thrift/protocol/TBinaryProtocol.h>
+-#include <thrift/server/TSimpleServer.h>
+-#include <thrift/server/TThreadPoolServer.h>
+-#include <thrift/server/TThreadedServer.h>
+-#include <thrift/transport/TServerSocket.h>
+-#include <thrift/transport/TSocket.h>
+-#include <thrift/transport/TTransportUtils.h>
+-#include <thrift/TToString.h>
+-
+-#include <boost/make_shared.hpp>
+-
+-#include <iostream>
+-#include <stdexcept>
+-#include <sstream>
+-
+-#include "../gen-cpp/Calculator.h"
+-
+-using namespace std;
+-using namespace apache::thrift;
+-using namespace apache::thrift::concurrency;
+-using namespace apache::thrift::protocol;
+-using namespace apache::thrift::transport;
+-using namespace apache::thrift::server;
+-
+-using namespace tutorial;
+-using namespace shared;
+-
+-class CalculatorHandler : public CalculatorIf {
+-public:
+- CalculatorHandler() {}
+-
+- void ping() { cout << "ping()" << endl; }
+-
+- int32_t add(const int32_t n1, const int32_t n2) {
+- cout << "add(" << n1 << ", " << n2 << ")" << endl;
+- return n1 + n2;
+- }
+-
+- int32_t calculate(const int32_t logid, const Work& work) {
+- cout << "calculate(" << logid << ", " << work << ")" << endl;
+- int32_t val;
+-
+- switch (work.op) {
+- case Operation::ADD:
+- val = work.num1 + work.num2;
+- break;
+- case Operation::SUBTRACT:
+- val = work.num1 - work.num2;
+- break;
+- case Operation::MULTIPLY:
+- val = work.num1 * work.num2;
+- break;
+- case Operation::DIVIDE:
+- if (work.num2 == 0) {
+- InvalidOperation io;
+- io.whatOp = work.op;
+- io.why = "Cannot divide by 0";
+- throw io;
+- }
+- val = work.num1 / work.num2;
+- break;
+- default:
+- InvalidOperation io;
+- io.whatOp = work.op;
+- io.why = "Invalid Operation";
+- throw io;
+- }
+-
+- SharedStruct ss;
+- ss.key = logid;
+- ss.value = to_string(val);
+-
+- log[logid] = ss;
+-
+- return val;
+- }
+-
+- void getStruct(SharedStruct& ret, const int32_t logid) {
+- cout << "getStruct(" << logid << ")" << endl;
+- ret = log[logid];
+- }
+-
+- void zip() { cout << "zip()" << endl; }
+-
+-protected:
+- map<int32_t, SharedStruct> log;
+-};
+-
+-/*
+- CalculatorIfFactory is code generated.
+- CalculatorCloneFactory is useful for getting access to the server side of the
+- transport. It is also useful for making per-connection state. Without this
+- CloneFactory, all connections will end up sharing the same handler instance.
+-*/
+-class CalculatorCloneFactory : virtual public CalculatorIfFactory {
+- public:
+- virtual ~CalculatorCloneFactory() {}
+- virtual CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo)
+- {
+- boost::shared_ptr<TSocket> sock = boost::dynamic_pointer_cast<TSocket>(connInfo.transport);
+- cout << "Incoming connection\n";
+- cout << "\tSocketInfo: " << sock->getSocketInfo() << "\n";
+- cout << "\tPeerHost: " << sock->getPeerHost() << "\n";
+- cout << "\tPeerAddress: " << sock->getPeerAddress() << "\n";
+- cout << "\tPeerPort: " << sock->getPeerPort() << "\n";
+- return new CalculatorHandler;
+- }
+- virtual void releaseHandler( ::shared::SharedServiceIf* handler) {
+- delete handler;
+- }
+-};
+-
+-int main() {
+- TThreadedServer server(
+- boost::make_shared<CalculatorProcessorFactory>(boost::make_shared<CalculatorCloneFactory>()),
+- boost::make_shared<TServerSocket>(9090), //port
+- boost::make_shared<TBufferedTransportFactory>(),
+- boost::make_shared<TBinaryProtocolFactory>());
+-
+- /*
+- // if you don't need per-connection state, do the following instead
+- TThreadedServer server(
+- boost::make_shared<CalculatorProcessor>(boost::make_shared<CalculatorHandler>()),
+- boost::make_shared<TServerSocket>(9090), //port
+- boost::make_shared<TBufferedTransportFactory>(),
+- boost::make_shared<TBinaryProtocolFactory>());
+- */
+-
+- /**
+- * Here are some alternate server types...
+-
+- // This server only allows one connection at a time, but spawns no threads
+- TSimpleServer server(
+- boost::make_shared<CalculatorProcessor>(boost::make_shared<CalculatorHandler>()),
+- boost::make_shared<TServerSocket>(9090),
+- boost::make_shared<TBufferedTransportFactory>(),
+- boost::make_shared<TBinaryProtocolFactory>());
+-
+- const int workerCount = 4;
+-
+- boost::shared_ptr<ThreadManager> threadManager =
+- ThreadManager::newSimpleThreadManager(workerCount);
+- threadManager->threadFactory(
+- boost::make_shared<PlatformThreadFactory>());
+- threadManager->start();
+-
+- // This server allows "workerCount" connection at a time, and reuses threads
+- TThreadPoolServer server(
+- boost::make_shared<CalculatorProcessorFactory>(boost::make_shared<CalculatorCloneFactory>()),
+- boost::make_shared<TServerSocket>(9090),
+- boost::make_shared<TBufferedTransportFactory>(),
+- boost::make_shared<TBinaryProtocolFactory>(),
+- threadManager);
+- */
+-
+- cout << "Starting the server..." << endl;
+- server.serve();
+- cout << "Done." << endl;
+- return 0;
+-}
+diff --git a/tutorial/cpp/GriftClient.cpp b/tutorial/cpp/GriftClient.cpp
+new file mode 100644
+index 0000000..647a683
+--- /dev/null
++++ b/tutorial/cpp/GriftClient.cpp
+@@ -0,0 +1,93 @@
++/*
++ *
++ * 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 <iostream>
++#include <memory>
++#include <string>
++
++#include <grpc++/grpc++.h>
++
++#include "gen-cpp/Greeter.grpc.thrift.h"
++
++using grpc::Channel;
++using grpc::ClientContext;
++using grpc::Status;
++using test::Greeter;
++
++class GreeterClient {
++ public:
++ GreeterClient(std::shared_ptr<Channel> channel)
++ : stub_(Greeter::NewStub(channel)) {}
++
++ // Assembles the client's payload, sends it and presents the response back
++ // from the server.
++ std::string SayHello(const std::string& user) {
++ // Data we are sending to the server.
++ Greeter::SayHelloReq req;
++ req.request.name = user;
++
++ // Container for the data we expect from the server.
++ Greeter::SayHelloResp reply;
++
++ // Context for the client. It could be used to convey extra information to
++ // the server and/or tweak certain RPC behaviors.
++ ClientContext context;
++
++ // The actual RPC.
++ Status status = stub_->SayHello(&context, req, &reply);
++
++ // Act upon its status.
++ if (status.ok()) {
++ return reply.success.message;
++ } else {
++ return "RPC failed";
++ }
++ }
++
++ private:
++ std::unique_ptr<Greeter::Stub> stub_;
++};
++
++int main() {
++ // Instantiate the client. It requires a channel, out of which the actual RPCs
++ // are created. This channel models a connection to an endpoint (in this case,
++ // localhost at port 50051). We indicate that the channel isn't authenticated
++ // (use of InsecureChannelCredentials()).
++ GreeterClient greeter(grpc::CreateChannel(
++ "localhost:50051", grpc::InsecureChannelCredentials()));
++ std::string user("world");
++ std::string reply = greeter.SayHello(user);
++ std::cout << "Greeter received: " << reply << std::endl;
++
++ return 0;
++}
+diff --git a/tutorial/cpp/GriftServer.cpp b/tutorial/cpp/GriftServer.cpp
+new file mode 100644
+index 0000000..7c01606
+--- /dev/null
++++ b/tutorial/cpp/GriftServer.cpp
+@@ -0,0 +1,93 @@
++/*
++ *
++ * 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 <iostream>
++#include <memory>
++#include <string>
++
++#include <grpc++/grpc++.h>
++
++#include "gen-cpp/Greeter.grpc.thrift.h"
++#include <grpc++/server_builder.h>
++
++using grpc::Server;
++using grpc::ServerBuilder;
++using grpc::ServerContext;
++using grpc::Status;
++using test::Greeter;
++
++// Logic and data behind the server's behavior.
++class GreeterServiceImpl final : public Greeter::Service {
++ public:
++ ~GreeterServiceImpl() {
++ // shutdown server
++ server->Shutdown();
++ }
++
++ Status SayHello(ServerContext* context,const Greeter::SayHelloReq* request,
++ Greeter::SayHelloResp* reply) override {
++ std::string prefix("Hello ");
++
++ reply->success.message = prefix + request->request.name;
++
++ return Status::OK;
++ }
++
++ void RunServer() {
++ std::string server_address("0.0.0.0:50051");
++
++ ServerBuilder builder;
++ // Listen on the given address without any authentication mechanism.
++ builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
++ // Register "service" as the instance through which we'll communicate with
++ // clients. In this case it corresponds to an *synchronous* service.
++ builder.RegisterService(this);
++ // Finally assemble the server.
++ server = builder.BuildAndStart();
++ std::cout << "Server listening on " << server_address << std::endl;
++
++ // Wait for the server to shutdown. Note that some other thread must be
++ // responsible for shutting down the server for this call to ever return.
++ server->Wait();
++ }
++
++ private:
++ std::unique_ptr<Server> server;
++};
++
++int main() {
++ GreeterServiceImpl service;
++ service.RunServer();
++
++ return 0;
++}
+diff --git a/tutorial/cpp/Makefile.am b/tutorial/cpp/Makefile.am
+index 184a69d..6f91e28 100755
+--- a/tutorial/cpp/Makefile.am
++++ b/tutorial/cpp/Makefile.am
+@@ -18,44 +18,38 @@
+ #
+ AUTOMAKE_OPTIONS = subdir-objects serial-tests
+
+-BUILT_SOURCES = gen-cpp/shared_types.cpp \
+- gen-cpp/tutorial_types.cpp
++BUILT_SOURCES = gen-cpp/test_types.cpp
+
+-noinst_LTLIBRARIES = libtutorialgencpp.la
+-nodist_libtutorialgencpp_la_SOURCES = \
+- gen-cpp/Calculator.cpp \
+- gen-cpp/Calculator.h \
+- gen-cpp/SharedService.cpp \
+- gen-cpp/SharedService.h \
+- gen-cpp/shared_constants.cpp \
+- gen-cpp/shared_constants.h \
+- gen-cpp/shared_types.cpp \
+- gen-cpp/shared_types.h \
+- gen-cpp/tutorial_constants.cpp \
+- gen-cpp/tutorial_constants.h \
+- gen-cpp/tutorial_types.cpp \
+- gen-cpp/tutorial_types.h
++#noinst_LTLIBRARIES = libtutorialgencpp.la
++noinst_LTLIBRARIES = libtestgencpp.la
++nodist_libtestgencpp_la_SOURCES = \
++ gen-cpp/Greeter.grpc.thrift.cpp \
++ gen-cpp/Greeter.grpc.thrift.h \
++ gen-cpp/test_constants.cpp \
++ gen-cpp/test_constants.h \
++ gen-cpp/test_types.cpp \
++ gen-cpp/test_types.h
+
+
+
+-libtutorialgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la
++libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la
+
+ noinst_PROGRAMS = \
+- TutorialServer \
+- TutorialClient
++ TestServer \
++ TestClient
+
+-TutorialServer_SOURCES = \
+- CppServer.cpp
++TestServer_SOURCES = \
++ GriftServer.cpp
+
+-TutorialServer_LDADD = \
+- libtutorialgencpp.la \
++TestServer_LDADD = \
++ libtestgencpp.la \
+ $(top_builddir)/lib/cpp/libthrift.la
+
+-TutorialClient_SOURCES = \
+- CppClient.cpp
++TestClient_SOURCES = \
++ GriftClient.cpp
+
+-TutorialClient_LDADD = \
+- libtutorialgencpp.la \
++TestClient_LDADD = \
++ libtestgencpp.la \
+ $(top_builddir)/lib/cpp/libthrift.la
+
+ #
+@@ -63,26 +57,26 @@ TutorialClient_LDADD = \
+ #
+ THRIFT = $(top_builddir)/compiler/cpp/thrift
+
+-gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_constants.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp: $(top_srcdir)/tutorial/tutorial.thrift
++gen-cpp/Greeter.grpc.thrift.cpp gen-cpp/test_constants.cpp gen-cpp/test_types.cpp: $(top_srcdir)/tutorial/cpp/test.thrift
+ $(THRIFT) --gen cpp -r $<
+
+ AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp
+ AM_CXXFLAGS = -Wall -Wextra -pedantic
+-AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS)
++AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) `pkg-config --libs grpc++ grpc` -lpthread -ldl -lgrpc
+
+ clean-local:
+- $(RM) gen-cpp/*
++ $(RM) -r gen-cpp
+
+-tutorialserver: all
+- ./TutorialServer
++testserver: all
++ ./TestServer
+
+-tutorialclient: all
+- ./TutorialClient
++testclient: all
++ ./TestClient
+
+ style-local:
+ $(CPPSTYLE_CMD)
+
+ EXTRA_DIST = \
+ CMakeLists.txt \
+- CppClient.cpp \
+- CppServer.cpp
++ GriftClient.cpp \
++ GriftServer.cpp
+diff --git a/tutorial/cpp/test.thrift b/tutorial/cpp/test.thrift
+new file mode 100644
+index 0000000..de3c9a4
+--- /dev/null
++++ b/tutorial/cpp/test.thrift
+@@ -0,0 +1,13 @@
++namespace cpp test
++
++struct HelloRequest {
++ 1:string name
++}
++
++struct HelloResponse {
++ 1:string message
++}
++
++service Greeter {
++ HelloResponse SayHello(1:HelloRequest request);
++}
+\ No newline at end of file
+--
+2.8.0.rc3.226.g39d4020
+
+
+From 3e4d75a2e2c474ee7700e7c9acaf89fdb768bedc Mon Sep 17 00:00:00 2001
+From: chedeti <chedeti@google.com>
+Date: Sun, 31 Jul 2016 16:23:53 -0700
+Subject: [PATCH 3/3] grpc java plugins generator
+
+for examples refer to https://github.com/grpc/grpc-java/tree/master/examples/thrift
+---
+ compiler/cpp/src/generate/t_java_generator.cc | 906 +++++++++++++++++++++++++-
+ tutorial/Makefile.am | 8 +-
+ 2 files changed, 887 insertions(+), 27 deletions(-)
+
+diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
+index 2db8cb8..8b28fe2 100644
+--- a/compiler/cpp/src/generate/t_java_generator.cc
++++ b/compiler/cpp/src/generate/t_java_generator.cc
+@@ -97,10 +97,10 @@ public:
+ } else if(iter->second.compare("suppress") == 0) {
+ suppress_generated_annotations_ = true;
+ } else {
+- throw "unknown option java:" + iter->first + "=" + iter->second;
++ throw "unknown option java:" + iter->first + "=" + iter->second;
+ }
+ } else {
+- throw "unknown option java:" + iter->first;
++ throw "unknown option java:" + iter->first;
+ }
+ }
+
+@@ -195,6 +195,17 @@ public:
+ void generate_service_async_server(t_service* tservice);
+ void generate_process_function(t_service* tservice, t_function* tfunction);
+ void generate_process_async_function(t_service* tservice, t_function* tfunction);
++ void generate_service_impl_base(t_service* tservice);
++ void generate_method_descriptors(t_service* tservice);
++ void generate_stub(t_service* tservice);
++ void generate_blocking_stub(t_service* tservice);
++ void generate_future_stub(t_service* tservice);
++ void generate_method_ids(t_service* tservice);
++ void generate_method_handlers(t_service* tservice);
++ void generate_service_descriptors(t_service* tservice);
++ void generate_service_builder(t_service* tservice);
++ void generate_arg_ids(t_service* tservice);
++ void generate_message_factory(t_service* tservice);
+
+ void generate_java_union(t_struct* tstruct);
+ void generate_union_constructor(ofstream& out, t_struct* tstruct);
+@@ -307,6 +318,8 @@ public:
+ std::string java_package();
+ std::string java_type_imports();
+ std::string java_suppressions();
++ std::string grpc_imports();
++ std::string import_extended_service(t_service* tservice);
+ std::string type_name(t_type* ttype,
+ bool in_container = false,
+ bool in_init = false,
+@@ -368,7 +381,7 @@ private:
+ bool use_option_type_;
+ bool undated_generated_annotations_;
+ bool suppress_generated_annotations_;
+-
++
+ };
+
+ /**
+@@ -456,6 +469,35 @@ string t_java_generator::java_suppressions() {
+ return "@SuppressWarnings({\"cast\", \"rawtypes\", \"serial\", \"unchecked\", \"unused\"})\n";
+ }
+
++string t_java_generator::grpc_imports() {
++ return
++ string() +
++ "import static io.grpc.stub.ClientCalls.asyncUnaryCall;\n" +
++ "import static io.grpc.stub.ClientCalls.asyncServerStreamingCall;\n" +
++ "import static io.grpc.stub.ClientCalls.asyncClientStreamingCall;\n" +
++ "import static io.grpc.stub.ClientCalls.asyncBidiStreamingCall;\n" +
++ "import static io.grpc.stub.ClientCalls.blockingUnaryCall;\n" +
++ "import static io.grpc.stub.ClientCalls.blockingServerStreamingCall;\n" +
++ "import static io.grpc.stub.ClientCalls.futureUnaryCall;\n" +
++ "import static io.grpc.MethodDescriptor.generateFullMethodName;\n" +
++ "import static io.grpc.stub.ServerCalls.asyncUnaryCall;\n" +
++ "import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;\n" +
++ "import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;\n" +
++ "import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;\n" +
++ "import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n" +
++ "import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;\n" +
++ "import io.grpc.thrift.ThriftUtils;\n\n";
++}
++
++string t_java_generator::import_extended_service(t_service* tservice) {
++ if (!tservice) {
++ return string() + "\n";
++ }
++ string ns = tservice->get_program()->get_namespace("java");
++ string extend_service_name = tservice->get_name() + "Grpc";
++ return string() + "import " + ns + "." + extend_service_name + ";\n\n";
++}
++
+ /**
+ * Nothing in Java
+ */
+@@ -2772,25 +2814,51 @@ void t_java_generator::generate_field_value_meta_data(std::ofstream& out, t_type
+ */
+ void t_java_generator::generate_service(t_service* tservice) {
+ // Make output file
+- string f_service_name = package_dir_ + "/" + make_valid_java_filename(service_name_) + ".java";
++ string f_service_name = package_dir_ + "/" + make_valid_java_filename(service_name_) + "Grpc.java";
+ f_service_.open(f_service_name.c_str());
+
+- f_service_ << autogen_comment() << java_package() << java_type_imports() << java_suppressions();
++ f_service_ <<
++ autogen_comment() <<
++ java_package() <<
++ java_type_imports() <<
++ grpc_imports() <<
++ import_extended_service(tservice->get_extends());
++ java_suppressions();
++
++ f_service_ <<
++ "public class " << service_name_ << "Grpc {" << endl <<
++ endl;
+
+- if (!suppress_generated_annotations_) {
+- generate_javax_generated_annotation(f_service_);
+- }
+- f_service_ << "public class " << service_name_ << " {" << endl << endl;
+ indent_up();
+
++ // generate constructor
++ f_service_ <<
++ indent() << "private " << service_name_ <<
++ "Grpc() {}" << endl << endl;
++
++ f_service_ <<
++ indent() << "public static final String SERVICE_NAME = " <<
++ "\"" << package_name_ << "." << service_name_ << "\";" << endl << endl;
++
+ // Generate the three main parts of the service
+ generate_service_interface(tservice);
+- generate_service_async_interface(tservice);
+- generate_service_client(tservice);
+- generate_service_async_client(tservice);
+- generate_service_server(tservice);
+- generate_service_async_server(tservice);
++ generate_arg_ids(tservice);
++ generate_message_factory(tservice);
++ generate_service_impl_base(tservice);
++ //generate_service_async_interface(tservice);
++ //generate_service_client(tservice);
++ //generate_service_async_client(tservice);
++ //generate_service_server(tservice);
++ //generate_service_async_server(tservice);
+ generate_service_helpers(tservice);
++ generate_method_descriptors(tservice);
++ generate_stub(tservice);
++ generate_blocking_stub(tservice);
++ generate_future_stub(tservice);
++ generate_method_ids(tservice);
++ generate_method_handlers(tservice);
++ generate_service_descriptors(tservice);
++ generate_service_builder(tservice);
+
+ indent_down();
+ f_service_ << "}" << endl;
+@@ -2805,24 +2873,820 @@ void t_java_generator::generate_service(t_service* tservice) {
+ void t_java_generator::generate_service_interface(t_service* tservice) {
+ string extends = "";
+ string extends_iface = "";
+- if (tservice->get_extends() != NULL) {
+- extends = type_name(tservice->get_extends());
+- extends_iface = " extends " + extends + ".Iface";
+- }
+
+ generate_java_doc(f_service_, tservice);
+- f_service_ << indent() << "public interface Iface" << extends_iface << " {" << endl << endl;
++ f_service_ << indent() <<
++ "@java.lang.Deprecated public static interface " << service_name_;
++
++ if (tservice->get_extends()) {
++ f_service_ << " extends " << tservice->get_extends()->get_name() + "Grpc." <<
++ tservice->get_extends()->get_name() << endl;
++ }
++ f_service_ << " {" << endl;
++
++ indent_up();
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ //generate_java_doc(f_service_, *f_iter);
++ f_service_ <<
++ indent() << "public void " << (*f_iter)->get_name() << "(" << (*f_iter)->get_name() <<
++ "_args request," << endl <<
++ indent() << " io.grpc.stub.StreamObserver<" << (*f_iter)->get_name() <<
++ "_result> responseObserver);" << endl << endl;
++ }
++ indent_down();
++ f_service_ << indent() << "}" << endl << endl;
++}
++
++void t_java_generator::generate_arg_ids(t_service* tservice) {
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ int i=0;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ << indent() <<
++ "private static final int ARG_IN_METHOD_" <<
++ (*f_iter)->get_name() << " = " << ++i << ";" << endl;
++ f_service_ << indent() <<
++ "private static final int ARG_OUT_METHOD_" <<
++ (*f_iter)->get_name() << " = " << ++i << ";" << endl;
++ }
++ f_service_ << endl;
++
++ if (tservice->get_extends()) {
++ f_service_ << indent() << "// ARG IDs for extended service" << endl;
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ << indent() <<
++ "private static final int ARG_IN_METHOD_" <<
++ (*f_iter)->get_name() << " = " << ++i << ";" << endl;
++ f_service_ << indent() <<
++ "private static final int ARG_OUT_METHOD_" <<
++ (*f_iter)->get_name() << " = " << ++i << ";" << endl;
++ }
++ f_service_ << endl;
++ }
++}
++
++void t_java_generator::generate_message_factory(t_service* tservice) {
++ f_service_ << indent() <<
++ "private static final class ThriftMessageFactory<T extends " <<
++ "org.apache.thrift.TBase<T,?>>" << endl << indent() <<
++ " implements io.grpc.thrift.MessageFactory<T> {" << endl;
++ indent_up();
++ f_service_ << indent() <<
++ "private final int id;" << endl << endl;
++ f_service_ << endl;
++
++ f_service_ << indent() <<
++ "ThriftMessageFactory(int id) {" << endl <<
++ indent() << " this.id = id;" << endl <<
++ indent() << "}" << endl;
++
++ f_service_ << indent() <<
++ "@java.lang.Override" << endl <<
++ indent() << "public T newInstance() {" << endl;
++ indent_up();
++
++ f_service_ << indent() <<
++ "Object o;" << endl <<
++ indent() << "switch (id) {" << endl;
++
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ << indent() <<
++ "case ARG_IN_METHOD_" << (*f_iter)->get_name() << ":" << endl <<
++ indent() << " o = new " << (*f_iter)->get_name() << "_args();" <<
++ endl << indent() << " break;" << endl;
++ f_service_ << indent() <<
++ "case ARG_OUT_METHOD_" << (*f_iter)->get_name() << ":" << endl <<
++ indent() << " o = new " << (*f_iter)->get_name() << "_result();" <<
++ endl << indent() << " break;" << endl;
++ }
++
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc";
++ for (f_iter = functions.begin(); f_iter!= functions.end(); ++f_iter) {
++ f_service_ << indent() <<
++ "case ARG_IN_METHOD_" << (*f_iter)->get_name() << ":" << endl <<
++ indent() << " o = new " << extend_service_name << "." << (*f_iter)->get_name() << "_args();" <<
++ endl << indent() << " break;" << endl;
++ f_service_ << indent() <<
++ "case ARG_OUT_METHOD_" << (*f_iter)->get_name() << ":" << endl <<
++ indent() << " o = new " << extend_service_name << "." << (*f_iter)->get_name() << "_result();" <<
++ endl << indent() << " break;" << endl;
++ }
++ }
++
++ f_service_ << indent() <<
++ "default:" << endl << indent() <<
++ " throw new AssertionError();" << endl << indent() <<
++ "}" << endl;
++
++ f_service_ << indent() <<
++ "@java.lang.SuppressWarnings(\"unchecked\")" << endl <<
++ indent() << "T t = (T) o;" << endl << indent() <<
++ "return t;" << endl;
++
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl;
++
++ indent_down();
++ f_service_ << indent() << "}" << endl;
++}
++
++void t_java_generator::generate_service_impl_base(t_service* tservice) {
++ f_service_ <<
++ indent() << "public static abstract class " << service_name_ <<
++ "ImplBase implements " << service_name_ << ", io.grpc.BindableService {" << endl;
++ indent_up();
++
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "public void " << (*f_iter)->get_name() << "(" << (*f_iter)->get_name() <<
++ "_args request, " << endl <<
++ indent() << " io.grpc.stub.StreamObserver<" << (*f_iter)->get_name() <<
++ "_result> responseObserver) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "asyncUnimplementedUnaryCall(METHOD_" << (*f_iter)->get_name() <<
++ ", responseObserver);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++ }
++
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc" ;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "public void " << (*f_iter)->get_name() << "(" <<
++ extend_service_name << "." << (*f_iter)->get_name() <<
++ "_args request, " << endl <<
++ indent() << " io.grpc.stub.StreamObserver<" << extend_service_name
++ << "." << (*f_iter)->get_name() << "_result> responseObserver) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "asyncUnimplementedUnaryCall(METHOD_" << (*f_iter)->get_name() <<
++ ", responseObserver);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++ }
++ }
++
++ f_service_ <<
++ indent() << "@java.lang.Override" <<
++ " public io.grpc.ServerServiceDefinition bindService() {" << endl;
+ indent_up();
++ f_service_ <<
++ indent() << "return " << service_name_ << "Grpc.bindService(this);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ // generate Abstract Service
++ f_service_ <<
++ indent() << "@java.lang.Deprecated public static abstract class Abstract" << service_name_ <<
++ " extends " << service_name_ << "ImplBase {}" << endl << endl;
++}
++
++void t_java_generator::generate_method_descriptors(t_service* tservice) {
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for( f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "public static final io.grpc.MethodDescriptor<" <<
++ (*f_iter)->get_name() << "_args," << endl <<
++ indent() << " " << (*f_iter)->get_name() << "_result> METHOD_" << (*f_iter)->get_name() <<
++ " = " << endl << indent() << " io.grpc.MethodDescriptor.create(" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " io.grpc.MethodDescriptor.MethodType.UNARY," << endl <<
++ indent() << " generateFullMethodName(" << "\"" << package_name_ << "." <<
++ service_name_ << "\" , \"" << (*f_iter)->get_name() << "\")," << endl <<
++ indent() << " io.grpc.thrift.ThriftUtils.marshaller(" << endl <<
++ indent() << " new ThriftMessageFactory<" << (*f_iter)->get_name() <<
++ "_args>( ARG_IN_METHOD_" << (*f_iter)->get_name() << "))," << endl <<
++ indent() << " io.grpc.thrift.ThriftUtils.marshaller(" << endl <<
++ indent() << " new ThriftMessageFactory<" << (*f_iter)->get_name() <<
++ "_result>( ARG_OUT_METHOD_" << (*f_iter)->get_name() << ")));" << endl << endl;
++ indent_down();
++ }
++
++ if(tservice->get_extends()) {
++ t_service* extends_service = tservice->get_extends();
++ functions = extends_service->get_functions();
++ string extend_service_name = extends_service->get_name() + "Grpc";
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "public static final io.grpc.MethodDescriptor<" << extend_service_name << "." <<
++ (*f_iter)->get_name() << "_args," << endl <<
++ indent() << " " << extend_service_name << "." << (*f_iter)->get_name() << "_result> METHOD_"
++ << (*f_iter)->get_name() << " = " << endl << indent() <<
++ " io.grpc.MethodDescriptor.create(" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " io.grpc.MethodDescriptor.MethodType.UNARY," << endl <<
++ indent() << " generateFullMethodName(" << "\"" << package_name_ << "." <<
++ service_name_ << "\" , \"" << (*f_iter)->get_name() << "\")," << endl <<
++ indent() << " io.grpc.thrift.ThriftUtils.marshaller(" << endl <<
++ indent() << " new ThriftMessageFactory<" << extend_service_name << "." <<
++ (*f_iter)->get_name() << "_args>( ARG_IN_METHOD_" << (*f_iter)->get_name() << "))," << endl <<
++ indent() << " io.grpc.thrift.ThriftUtils.marshaller(" << endl <<
++ indent() << " new ThriftMessageFactory<" << extend_service_name << "." << (*f_iter)->get_name() <<
++ "_result>( ARG_OUT_METHOD_" << (*f_iter)->get_name() << ")));" << endl << endl;
++ indent_down();
++ }
++ }
++}
++
++void t_java_generator::generate_stub(t_service* tservice) {
++ f_service_ <<
++ indent() <<
++ "public static " << service_name_ <<
++ "Stub newStub(io.grpc.Channel channel) {" <<
++ endl;
++
++ indent_up();
++ f_service_ <<
++ indent() <<
++ "return new " << service_name_ << "Stub(channel);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ // generate Stub impl
++
++ f_service_ <<
++ indent() << "public static class " <<
++ service_name_ << "Stub extends io.grpc.stub.AbstractStub<" <<
++ service_name_ << "Stub>" << endl <<
++ indent() << " implements " << service_name_ << "{" << endl;
++ indent_up();
++
++ f_service_ <<
++ indent() << "private " << service_name_ << "Stub(io.grpc.Channel channel) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "super(channel);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ f_service_ <<
++ indent() << "private " << service_name_ << "Stub(io.grpc.Channel channel, " << endl <<
++ indent() << " io.grpc.CallOptions callOptions) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "super(channel, callOptions);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "protected " << service_name_ << "Stub build(io.grpc.Channel channel, " <<
++ endl << indent() << " io.grpc.CallOptions callOptions) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return new " << service_name_ << "Stub(channel, callOptions);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "public void " << (*f_iter)->get_name() << "(" <<
++ (*f_iter)->get_name() << "_args request," << endl << indent() <<
++ " io.grpc.stub.StreamObserver<" << (*f_iter)->get_name() <<
++ "_result> responseObserver) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "asyncUnaryCall(" << endl <<
++ indent() << " getChannel().newCall(METHOD_" << (*f_iter)->get_name() <<
++ ", getCallOptions()), request, responseObserver);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++ }
++
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc";
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "public void " << (*f_iter)->get_name() << "(" <<
++ extend_service_name << "." << (*f_iter)->get_name() << "_args request,"
++ << endl << indent() << " io.grpc.stub.StreamObserver<" <<
++ extend_service_name << "." << (*f_iter)->get_name() <<
++ "_result> responseObserver) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "asyncUnaryCall(" << endl <<
++ indent() << " getChannel().newCall(METHOD_" << (*f_iter)->get_name() <<
++ ", getCallOptions()), request, responseObserver);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++ }
++ }
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++}
++
++void t_java_generator::generate_blocking_stub(t_service* tservice) {
++ f_service_ <<
++ indent() << "public static " << service_name_ <<
++ "BlockingStub newBlockingStub(" << endl <<
++ indent() << " io.grpc.Channel channel) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return new " << service_name_ << "BlockingStub(channel);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ // generate Blocking Client
++ f_service_ <<
++ indent() << "@java.lang.Deprecated public static interface " << service_name_ <<
++ "BlockingClient " ;
++
++ if (tservice->get_extends()) {
++ string extend_service_name = tservice->get_extends()->get_name();
++ f_service_ << endl << indent() << " extends " << extend_service_name << "Grpc." <<
++ extend_service_name << "BlockingClient " ;
++ }
++
++ f_service_ << "{" << endl;
++
++ indent_up();
++
+ vector<t_function*> functions = tservice->get_functions();
+ vector<t_function*>::iterator f_iter;
+ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+- generate_java_doc(f_service_, *f_iter);
+- indent(f_service_) << "public " << function_signature(*f_iter) << ";" << endl << endl;
++ f_service_ <<
++ indent() << "public " << (*f_iter)->get_name() << "_result " <<
++ (*f_iter)->get_name() << "(" << (*f_iter)->get_name() << "_args request);" << endl << endl;
++ }
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ // generate Blocking Stub impl
++
++ f_service_ <<
++ indent() << "public static class " <<
++ service_name_ << "BlockingStub extends io.grpc.stub.AbstractStub<" <<
++ service_name_ << "BlockingStub>" << endl <<
++ indent() << " implements " << service_name_ << "BlockingClient {";
++
++ indent_up();
++
++ f_service_ <<
++ indent() << "private " << service_name_ << "BlockingStub(io.grpc.Channel channel) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "super(channel);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ f_service_ <<
++ indent() << "private " << service_name_ << "BlockingStub(io.grpc.Channel channel, " << endl <<
++ indent() << " io.grpc.CallOptions callOptions) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "super(channel, callOptions);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "protected " << service_name_ << "BlockingStub build(io.grpc.Channel channel, " <<
++ endl << indent() << " io.grpc.CallOptions callOptions) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return new " << service_name_ << "BlockingStub(channel, callOptions);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "public " << (*f_iter)->get_name() << "_result " << (*f_iter)->get_name() << "(" <<
++ (*f_iter)->get_name() << "_args request) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return blockingUnaryCall(" << endl <<
++ indent() << " getChannel(), METHOD_" << (*f_iter)->get_name() <<
++ ", getCallOptions(), request);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++ }
++
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc";
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "public " << extend_service_name << "." << (*f_iter)->get_name() <<
++ "_result " << (*f_iter)->get_name() << "(" << extend_service_name << "." <<
++ (*f_iter)->get_name() << "_args request) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return blockingUnaryCall(" << endl <<
++ indent() << " getChannel(), METHOD_" << (*f_iter)->get_name() <<
++ ", getCallOptions(), request);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++ }
++ }
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++}
++
++void t_java_generator::generate_future_stub(t_service* tservice) {
++ f_service_ <<
++ indent() << "public static " << service_name_ <<
++ "FutureStub newFutureStub(" << endl <<
++ indent() << " io.grpc.Channel channel) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return new " << service_name_ << "FutureStub(channel);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ // generate Future Client
++ f_service_ <<
++ indent() << "@java.lang.Deprecated public static interface " << service_name_ <<
++ "FutureClient " ;
++
++ if (tservice->get_extends()) {
++ string extend_service_name = tservice->get_extends()->get_name();
++ f_service_ << endl << indent() << " extends " << extend_service_name << "Grpc." <<
++ extend_service_name << "FutureClient " ;
++ }
++ f_service_ << "{" << endl;
++
++ indent_up();
++
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "public com.google.common.util.concurrent.ListenableFuture<" <<
++ (*f_iter)->get_name() << "_result> " << (*f_iter)->get_name() << "(" << endl <<
++ indent() << " " << (*f_iter)->get_name() << "_args request);" << endl << endl;
++ }
++
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc";
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "public com.google.common.util.concurrent.ListenableFuture<" <<
++ extend_service_name << "." << (*f_iter)->get_name() << "_result> " <<
++ (*f_iter)->get_name() << "(" << endl <<
++ indent() << " " << extend_service_name << "." << (*f_iter)->get_name() <<
++ "_args request);" << endl << endl;
++ }
++ }
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ // generate Stub impl
++
++ f_service_ <<
++ indent() << "public static class " <<
++ service_name_ << "FutureStub extends io.grpc.stub.AbstractStub<" <<
++ service_name_ << "FutureStub>" << endl <<
++ indent() << " implements " << service_name_ << "FutureClient {" << endl;
++ indent_up();
++
++ f_service_ <<
++ indent() << "private " << service_name_ << "FutureStub(io.grpc.Channel channel) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "super(channel);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ f_service_ <<
++ indent() << "private " << service_name_ << "FutureStub(io.grpc.Channel channel, " << endl <<
++ indent() << " io.grpc.CallOptions callOptions) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "super(channel, callOptions);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "protected " << service_name_ << "FutureStub build(io.grpc.Channel channel, " <<
++ endl << indent() << " io.grpc.CallOptions callOptions) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return new " << service_name_ << "FutureStub(channel, callOptions);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ functions = tservice->get_functions();
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "public com.google.common.util.concurrent.ListenableFuture<" <<
++ (*f_iter)->get_name() << "_result> " << (*f_iter)->get_name() << "(" <<
++ endl << indent() << " " << (*f_iter)->get_name() << "_args request) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return futureUnaryCall(" << endl <<
++ indent() << " getChannel().newCall(METHOD_" << (*f_iter)->get_name() <<
++ ", getCallOptions()), request);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++ }
++
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc";
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "public com.google.common.util.concurrent.ListenableFuture<" <<
++ extend_service_name << "." << (*f_iter)->get_name() << "_result> " <<
++ (*f_iter)->get_name() << "(" << endl << indent() << " " <<
++ extend_service_name << "." << (*f_iter)->get_name() << "_args request) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return futureUnaryCall(" << endl <<
++ indent() << " getChannel().newCall(METHOD_" << (*f_iter)->get_name() <<
++ ", getCallOptions()), request);" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++ }
++ }
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++}
++
++void t_java_generator::generate_method_ids(t_service* tservice) {
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ int i=0;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter, ++i) {
++ f_service_ <<
++ indent() << "private static final int METHODID_" <<
++ (*f_iter)->get_name() << " = " << i << ";" << endl;
++ }
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc";
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter, ++i) {
++ f_service_ <<
++ indent() << "private static final int METHODID_" <<
++ (*f_iter)->get_name() << " = " << i << ";" << endl;
++ }
++ }
++ f_service_ << endl;
++}
++
++void t_java_generator::generate_method_handlers(t_service* tservice) {
++ f_service_ <<
++ indent() << "private static class MethodHandlers<Req, Resp> implements" <<
++ endl << indent() << " io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>," <<
++ endl << indent() << " io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>," <<
++ endl << indent() << " io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>," <<
++ endl << indent() << " io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {" <<
++ endl;
++ indent_up();
++ f_service_ <<
++ indent() << "private final " << service_name_ << " serviceImpl;" << endl <<
++ indent() << "private final int methodId;" << endl << endl;
++
++ f_service_ <<
++ indent() << "public MethodHandlers(" << service_name_ << " serviceImpl, int " <<
++ "methodId) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "this.serviceImpl = serviceImpl;" << endl <<
++ indent() << "this.methodId = methodId;" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ // invoke
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "@java.lang.SuppressWarnings(\"unchecked\")" << endl <<
++ indent() << "public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {" <<
++ endl;
++ indent_up();
++ f_service_ <<
++ indent() << "switch (methodId) {" << endl;
++ indent_up();
++
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "case METHODID_" << (*f_iter)->get_name() << ":" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "serviceImpl." << (*f_iter)->get_name() << "((" << (*f_iter)->get_name() <<
++ "_args) request," << endl <<
++ indent() << " (io.grpc.stub.StreamObserver<" << (*f_iter)->get_name() << "_result>)" <<
++ " responseObserver);" << endl <<
++ indent() << "break;" << endl << endl;
++ indent_down();
++ }
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc";
++ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "case METHODID_" << (*f_iter)->get_name() << ":" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "serviceImpl." << (*f_iter)->get_name() << "((" << extend_service_name <<
++ "." << (*f_iter)->get_name() << "_args) request," << endl <<
++ indent() << " (io.grpc.stub.StreamObserver<" << extend_service_name << "." <<
++ (*f_iter)->get_name() << "_result>)" << " responseObserver);" << endl <<
++ indent() << "break;" << endl << endl;
++ indent_down();
++ }
+ }
++ f_service_ <<
++ indent() << "default:" << endl <<
++ indent() << " throw new AssertionError();" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl;
++ indent_down();
++ f_service_ <<
++ indent() << "}" << endl << endl;
++
++ // invoke
++ f_service_ <<
++ indent() << "@java.lang.Override" << endl <<
++ indent() << "@java.lang.SuppressWarnings(\"unchecked\")" << endl <<
++ indent() << "public io.grpc.stub.StreamObserver<Req> invoke(" << endl <<
++ indent() << " io.grpc.stub.StreamObserver<Resp> responseObserver) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "switch (methodId) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "default:" << endl;
++ f_service_ <<
++ indent() << " throw new AssertionError();" << endl;
++ indent_down();
++ f_service_ << indent() << "}" << endl;
+ indent_down();
+ f_service_ << indent() << "}" << endl << endl;
++ indent_down();
++ f_service_ << indent() << "}" << endl << endl;
++
+ }
+
++void t_java_generator::generate_service_descriptors(t_service* tservice) {
++ // generate service descriptor
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ f_service_ <<
++ indent() << "public static io.grpc.ServiceDescriptor getServiceDescriptor() {" <<
++ endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return new io.grpc.ServiceDescriptor(SERVICE_NAME";
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "," << endl <<
++ indent() << " METHOD_" << (*f_iter)->get_name();
++ }
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << "," << endl <<
++ indent() << " METHOD_" << (*f_iter)->get_name();
++ }
++ }
++ f_service_ << ");" << endl;
++ indent_down();
++ f_service_ << indent() << "}" << endl << endl;
++}
++
++void t_java_generator::generate_service_builder(t_service* tservice) {
++ // bind Service
++ vector<t_function*> functions = tservice->get_functions();
++ vector<t_function*>::iterator f_iter;
++ f_service_ <<
++ indent() << "@java.lang.Deprecated public static io.grpc.ServerServiceDefinition" <<
++ " bindService(" << endl <<
++ indent() << " final " << service_name_ << " serviceImpl) {" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << "return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())" <<
++ endl;
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << " .addMethod(" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " METHOD_" << (*f_iter)->get_name() << "," << endl <<
++ indent() << " asyncUnaryCall(" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " new MethodHandlers<" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " " << (*f_iter)->get_name() << "_args," << endl <<
++ indent() << " " << (*f_iter)->get_name() << "_result>(" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " serviceImpl, METHODID_" << (*f_iter)->get_name() << ")))" << endl;
++ indent_down();
++ indent_down();
++ indent_down();
++ indent_down();
++ }
++
++ if (tservice->get_extends()) {
++ t_service* extend_service = tservice->get_extends();
++ functions = extend_service->get_functions();
++ string extend_service_name = extend_service->get_name() + "Grpc";
++ for(f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
++ f_service_ <<
++ indent() << " .addMethod(" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " METHOD_" << (*f_iter)->get_name() << "," << endl <<
++ indent() << " asyncUnaryCall(" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " new MethodHandlers<" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " " << extend_service_name << "." << (*f_iter)->get_name() << "_args," << endl <<
++ indent() << " " << extend_service_name << "." << (*f_iter)->get_name() << "_result>(" << endl;
++ indent_up();
++ f_service_ <<
++ indent() << " serviceImpl, METHODID_" << (*f_iter)->get_name() << ")))" << endl;
++ indent_down();
++ indent_down();
++ indent_down();
++ indent_down();
++ }
++ }
++ f_service_ <<
++ indent() << " .build();" << endl;
++ indent_down();
++ f_service_ << indent() << "}" << endl << endl;
++}
++
++
+ void t_java_generator::generate_service_async_interface(t_service* tservice) {
+ string extends = "";
+ string extends_iface = "";
+diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am
+index 5865c54..1cffbe6 100755
+--- a/tutorial/Makefile.am
++++ b/tutorial/Makefile.am
+@@ -35,11 +35,6 @@ if WITH_D
+ SUBDIRS += d
+ endif
+
+-if WITH_JAVA
+-SUBDIRS += java
+-SUBDIRS += js
+-endif
+-
+ if WITH_PYTHON
+ SUBDIRS += py
+ SUBDIRS += py.twisted
+@@ -95,4 +90,5 @@ EXTRA_DIST = \
+ php \
+ shared.thrift \
+ tutorial.thrift \
+- README.md
++ README.md \
++ java
+--
+2.8.0.rc3.226.g39d4020
+
diff --git a/tools/run_tests/build_package_node.sh b/tools/run_tests/build_package_node.sh
index f20daeaea0..a5636cf87a 100755
--- a/tools/run_tests/build_package_node.sh
+++ b/tools/run_tests/build_package_node.sh
@@ -50,7 +50,6 @@ cp grpc-*.tgz $artifacts/grpc.tgz
mkdir -p bin
cd $base/src/node/health_check
-npm update
npm pack
cp grpc-health-check-*.tgz $artifacts/
diff --git a/tools/run_tests/package_targets.py b/tools/run_tests/package_targets.py
index ce3f08dfbc..5e6de2e317 100644
--- a/tools/run_tests/package_targets.py
+++ b/tools/run_tests/package_targets.py
@@ -81,7 +81,14 @@ class CSharpPackage:
self.labels += ['windows']
def pre_build_jobspecs(self):
- return []
+ if 'windows' in self.labels:
+ return [create_jobspec('prebuild_%s' % self.name,
+ ['tools\\run_tests\\pre_build_csharp.bat'],
+ shell=True,
+ flake_retries=5,
+ timeout_retries=2)]
+ else:
+ return []
def build_jobspec(self):
if self.use_coreclr:
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index 04123ee5d8..d2ab5b01cc 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -47,6 +47,7 @@ cat << EOF | awk '{ print $1 }' | sort > $want_submodules
f8ac463766281625ad710900479130c7fcb4d63b third_party/nanopb (nanopb-0.3.4-29-gf8ac463)
e8ae137c96444ea313485ed1118c5e43b2099cf1 third_party/protobuf (v3.0.0-beta-4-74-ge8ae137)
50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8)
+ bcad91771b7f0bff28a1cac1981d7ef2b9bcef3c third_party/thrift
EOF
diff -u $submodules $want_submodules
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 4071eba94d..e5946cc14a 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -2164,14 +2164,11 @@
{
"deps": [
"gpr",
- "gpr_test_util",
"grpc",
"grpc++",
"grpc++_reflection",
"grpc++_test_config",
- "grpc++_test_util",
- "grpc_cli_libs",
- "grpc_test_util"
+ "grpc_cli_libs"
],
"headers": [],
"language": "c++",
@@ -2262,6 +2259,35 @@
},
{
"deps": [
+ "gpr",
+ "gpr_test_util",
+ "grpc",
+ "grpc++",
+ "grpc++_codegen_proto",
+ "grpc++_config_proto",
+ "grpc++_reflection",
+ "grpc_cli_libs",
+ "grpc_test_util"
+ ],
+ "headers": [
+ "src/proto/grpc/testing/echo.grpc.pb.h",
+ "src/proto/grpc/testing/echo.pb.h",
+ "src/proto/grpc/testing/echo_messages.grpc.pb.h",
+ "src/proto/grpc/testing/echo_messages.pb.h",
+ "test/cpp/util/string_ref_helper.h"
+ ],
+ "language": "c++",
+ "name": "grpc_tool_test",
+ "src": [
+ "test/cpp/util/grpc_tool_test.cc",
+ "test/cpp/util/string_ref_helper.cc",
+ "test/cpp/util/string_ref_helper.h"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
"grpc",
"grpc++",
"grpc++_test_util",
@@ -4468,7 +4494,8 @@
"grpc++_codegen_base_src",
"grpc++_codegen_proto",
"grpc++_config_proto",
- "grpc_test_util"
+ "grpc_test_util",
+ "thrift_util"
],
"headers": [
"src/proto/grpc/testing/duplicate/echo_duplicate.grpc.pb.h",
@@ -4525,10 +4552,13 @@
"deps": [
"grpc++",
"grpc++_reflection",
- "grpc_plugin_support"
+ "grpc++_test_config"
],
"headers": [
"test/cpp/util/cli_call.h",
+ "test/cpp/util/cli_credentials.h",
+ "test/cpp/util/config_grpc_cli.h",
+ "test/cpp/util/grpc_tool.h",
"test/cpp/util/proto_file_parser.h",
"test/cpp/util/proto_reflection_descriptor_database.h"
],
@@ -4537,6 +4567,11 @@
"src": [
"test/cpp/util/cli_call.cc",
"test/cpp/util/cli_call.h",
+ "test/cpp/util/cli_credentials.cc",
+ "test/cpp/util/cli_credentials.h",
+ "test/cpp/util/config_grpc_cli.h",
+ "test/cpp/util/grpc_tool.cc",
+ "test/cpp/util/grpc_tool.h",
"test/cpp/util/proto_file_parser.cc",
"test/cpp/util/proto_file_parser.h",
"test/cpp/util/proto_reflection_descriptor_database.cc",
@@ -6870,5 +6905,22 @@
],
"third_party": false,
"type": "filegroup"
+ },
+ {
+ "deps": [
+ "grpc++_codegen_base"
+ ],
+ "headers": [
+ "include/grpc++/impl/codegen/thrift_serializer.h",
+ "include/grpc++/impl/codegen/thrift_utils.h"
+ ],
+ "language": "c++",
+ "name": "thrift_util",
+ "src": [
+ "include/grpc++/impl/codegen/thrift_serializer.h",
+ "include/grpc++/impl/codegen/thrift_utils.h"
+ ],
+ "third_party": false,
+ "type": "filegroup"
}
]
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index 11fb460dd5..b0c09ace5b 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -2324,6 +2324,27 @@
"flaky": false,
"gtest": true,
"language": "c++",
+ "name": "grpc_tool_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": "grpclb_api_test",
"platforms": [
"linux",
diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
index d0fca9ba65..c2c7d00a6d 100644
--- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
+++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj
@@ -200,6 +200,8 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_serializer.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_utils.h" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.h" />
diff --git a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
index cc98c60408..9b8c8ddfad 100644
--- a/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc++_test_util/grpc++_test_util.vcxproj.filters
@@ -192,6 +192,12 @@
<ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
<Filter>include\grpc++\impl\codegen</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_serializer.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\thrift_utils.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\end2end\test_service_impl.h">
diff --git a/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj b/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj
index d25c692e3e..425b66f155 100644
--- a/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj
+++ b/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj
@@ -148,12 +148,19 @@
<ItemGroup>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h" />
+ <ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_credentials.h" />
+ <ClInclude Include="$(SolutionDir)\..\test\cpp\util\config_grpc_cli.h" />
+ <ClInclude Include="$(SolutionDir)\..\test\cpp\util\grpc_tool.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h" />
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_call.cc">
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_credentials.cc">
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\util\grpc_tool.cc">
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_reflection_descriptor_database.cc">
@@ -166,8 +173,8 @@
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++\grpc++.vcxproj">
<Project>{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}</Project>
</ProjectReference>
- <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_plugin_support\grpc_plugin_support.vcxproj">
- <Project>{B6E81D84-2ACB-41B8-8781-493A944C7817}</Project>
+ <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" />
diff --git a/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters b/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters
index 4add8ed5e1..b2128c282b 100644
--- a/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_cli_libs/grpc_cli_libs.vcxproj.filters
@@ -4,6 +4,12 @@
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_call.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\util\cli_credentials.cc">
+ <Filter>test\cpp\util</Filter>
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\util\grpc_tool.cc">
+ <Filter>test\cpp\util</Filter>
+ </ClCompile>
<ClCompile Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.cc">
<Filter>test\cpp\util</Filter>
</ClCompile>
@@ -15,6 +21,15 @@
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_call.h">
<Filter>test\cpp\util</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\test\cpp\util\cli_credentials.h">
+ <Filter>test\cpp\util</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\test\cpp\util\config_grpc_cli.h">
+ <Filter>test\cpp\util</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\test\cpp\util\grpc_tool.h">
+ <Filter>test\cpp\util</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\test\cpp\util\proto_file_parser.h">
<Filter>test\cpp\util</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj b/vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj
index 9c8cdc54c2..78a0a63b5d 100644
--- a/vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj
+++ b/vsprojects/vcxproj/test/grpc_cli/grpc_cli.vcxproj
@@ -167,12 +167,6 @@
<ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_cli_libs\grpc_cli_libs.vcxproj">
<Project>{86E35862-43E8-F59E-F906-AFE0348AD3D2}</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++_reflection\grpc++_reflection.vcxproj">
<Project>{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}</Project>
</ProjectReference>
@@ -182,9 +176,6 @@
<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>
diff --git a/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj
new file mode 100644
index 0000000000..c6f65aa30b
--- /dev/null
+++ b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj
@@ -0,0 +1,286 @@
+<?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>{F00D82D4-E988-6D2F-F0B9-9E82BCC2A2B2}</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>grpc_tool_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>grpc_tool_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>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h" />
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.grpc.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo.grpc.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.grpc.pb.cc">
+ </ClCompile>
+ <ClInclude Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.grpc.pb.h">
+ </ClInclude>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\util\grpc_tool_test.cc">
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.cc">
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_cli_libs\grpc_cli_libs.vcxproj">
+ <Project>{86E35862-43E8-F59E-F906-AFE0348AD3D2}</Project>
+ </ProjectReference>
+ <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc++_reflection\grpc++_reflection.vcxproj">
+ <Project>{5F575402-3F89-5D1A-6910-9DB8BF5D2BAB}</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/grpc_tool_test/grpc_tool_test.vcxproj.filters b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters
new file mode 100644
index 0000000000..731eb2e6ff
--- /dev/null
+++ b/vsprojects/vcxproj/test/grpc_tool_test/grpc_tool_test.vcxproj.filters
@@ -0,0 +1,232 @@
+<?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\echo.proto">
+ <Filter>src\proto\grpc\testing</Filter>
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\src\proto\grpc\testing\echo_messages.proto">
+ <Filter>src\proto\grpc\testing</Filter>
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\util\grpc_tool_test.cc">
+ <Filter>test\cpp\util</Filter>
+ </ClCompile>
+ <ClCompile Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.cc">
+ <Filter>test\cpp\util</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\proto_utils.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_stream.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\async_unary_call.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\call_hook.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\channel_interface.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_context.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\client_unary_call.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\completion_queue_tag.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\core_codegen_interface.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\create_auth_context.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\grpc_library.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\method_handler_impl.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_method.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\rpc_service_method.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\security\auth_context.h">
+ <Filter>include\grpc++\impl\codegen\security</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\serialization_traits.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_context.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\server_interface.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\service_type.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\status_code_enum.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\string_ref.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\stub_options.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_cxx11.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_no_cxx11.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\sync_stream.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\time.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\byte_buffer_reader.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\compression_types.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\connectivity_state.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\grpc_types.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\propagation_bits.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\status.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\alloc.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_atomic.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_gcc_sync.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\atm_windows.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\log.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\port_platform.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\slice_buffer.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_generic.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_posix.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\sync_windows.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc\impl\codegen\time.h">
+ <Filter>include\grpc\impl\codegen</Filter>
+ </ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\include\grpc++\impl\codegen\config_protobuf.h">
+ <Filter>include\grpc++\impl\codegen</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="$(SolutionDir)\..\test\cpp\util\string_ref_helper.h">
+ <Filter>test\cpp\util</Filter>
+ </ClInclude>
+ </ItemGroup>
+
+ <ItemGroup>
+ <Filter Include="include">
+ <UniqueIdentifier>{89fed779-17c5-23da-c8a2-9e868ff34480}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\grpc">
+ <UniqueIdentifier>{96e4a1a8-0b91-1a6d-ae4d-ddf33abb93c0}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\grpc++">
+ <UniqueIdentifier>{1d9dcc6f-7c1b-cdc3-4c35-73d5968dfd92}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\grpc++\impl">
+ <UniqueIdentifier>{5eca7690-973a-c8ed-84d6-5325f8de43ac}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\grpc++\impl\codegen">
+ <UniqueIdentifier>{5789073e-5b84-0ec9-af06-47866647874d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\grpc++\impl\codegen\security">
+ <UniqueIdentifier>{d3f3293f-204f-7771-fcdf-de673f6b06b6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\grpc\impl">
+ <UniqueIdentifier>{7e90f37b-f9cc-0725-b2c1-12aa7d4809ba}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="include\grpc\impl\codegen">
+ <UniqueIdentifier>{7e4b71ef-8125-6446-bfc1-9bc90beed59c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src">
+ <UniqueIdentifier>{169774bd-5c6c-6827-66a4-326b4aef44d6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto">
+ <UniqueIdentifier>{1b609b37-ef2a-e5eb-e1ba-ad9e79c77438}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto\grpc">
+ <UniqueIdentifier>{cd1e35d8-8a61-62fe-6ce1-c8936872d1ef}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="src\proto\grpc\testing">
+ <UniqueIdentifier>{f7ee4df5-1f47-1e7f-c91e-350382c1b729}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test">
+ <UniqueIdentifier>{f2166b83-6b0b-d53b-b58b-627bd9efcad2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\cpp">
+ <UniqueIdentifier>{bbe36cbc-7fbe-2817-0bd0-d03726f323e6}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="test\cpp\util">
+ <UniqueIdentifier>{e106cd7b-cfa0-0645-f1a9-2acedc23afe7}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+</Project>
+