diff options
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 @@ -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> + |