diff options
author | Craig Tiller <craig.tiller@gmail.com> | 2015-09-01 08:04:29 -0700 |
---|---|---|
committer | Craig Tiller <craig.tiller@gmail.com> | 2015-09-01 08:04:29 -0700 |
commit | fb94111259b710bf067dfccf87fe882f1f25ab51 (patch) | |
tree | 4e588a618a52082364ce0877b2161f18ca632676 /src | |
parent | 9f80fcf8e79d71e99b28f152a7b8662d815a6ee2 (diff) | |
parent | 7bb3efdaf908ae0f0343adf1b942a4b10ed13fa0 (diff) |
Merge branch 'endpoints' into second-coming
Diffstat (limited to 'src')
189 files changed, 6812 insertions, 7074 deletions
diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 9432bdda96..7b497df7f4 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -33,12 +33,18 @@ #include <cctype> #include <map> +#include <sstream> #include <vector> +#include "src/compiler/csharp_generator.h" #include "src/compiler/config.h" #include "src/compiler/csharp_generator_helpers.h" #include "src/compiler/csharp_generator.h" + +using google::protobuf::compiler::csharp::GetFileNamespace; +using google::protobuf::compiler::csharp::GetClassName; +using google::protobuf::compiler::csharp::GetUmbrellaClassName; using grpc::protobuf::FileDescriptor; using grpc::protobuf::Descriptor; using grpc::protobuf::ServiceDescriptor; @@ -55,47 +61,10 @@ using grpc_generator::StringReplace; using std::map; using std::vector; + namespace grpc_csharp_generator { namespace { -// TODO(jtattermusch): make GetFileNamespace part of libprotoc public API. -// NOTE: Implementation needs to match exactly to GetFileNamespace -// defined in csharp_helpers.h in protoc csharp plugin. -// We cannot reference it directly because google3 protobufs -// don't have a csharp protoc plugin. -std::string GetFileNamespace(const FileDescriptor* file) { - if (file->options().has_csharp_namespace()) { - return file->options().csharp_namespace(); - } - return file->package(); -} - -std::string ToCSharpName(const std::string& name, const FileDescriptor* file) { - std::string result = GetFileNamespace(file); - if (result != "") { - result += '.'; - } - std::string classname; - if (file->package().empty()) { - classname = name; - } else { - // Strip the proto package from full_name since we've replaced it with - // the C# namespace. - classname = name.substr(file->package().size() + 1); - } - result += StringReplace(classname, ".", ".Types.", false); - return "global::" + result; -} - -// TODO(jtattermusch): make GetClassName part of libprotoc public API. -// NOTE: Implementation needs to match exactly to GetClassName -// defined in csharp_helpers.h in protoc csharp plugin. -// We cannot reference it directly because google3 protobufs -// don't have a csharp protoc plugin. -std::string GetClassName(const Descriptor* message) { - return ToCSharpName(message->full_name(), message->file()); -} - std::string GetServiceClassName(const ServiceDescriptor* service) { return service->name(); } @@ -229,7 +198,7 @@ void GenerateMarshallerFields(Printer* out, const ServiceDescriptor *service) { for (size_t i = 0; i < used_messages.size(); i++) { const Descriptor *message = used_messages[i]; out->Print( - "static readonly Marshaller<$type$> $fieldname$ = Marshallers.Create((arg) => arg.ToByteArray(), $type$.ParseFrom);\n", + "static readonly Marshaller<$type$> $fieldname$ = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), $type$.Parser.ParseFrom);\n", "fieldname", GetMarshallerFieldName(message), "type", GetClassName(message)); } @@ -258,6 +227,19 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) { out->Outdent(); } +void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *service) { + std::ostringstream index; + index << service->index(); + out->Print("// service descriptor\n"); + out->Print("public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor\n"); + out->Print("{\n"); + out->Print(" get { return $umbrella$.Descriptor.Services[$index$]; }\n", + "umbrella", GetUmbrellaClassName(service->file()), "index", + index.str()); + out->Print("}\n"); + out->Print("\n"); +} + void GenerateClientInterface(Printer* out, const ServiceDescriptor *service) { out->Print("// client interface\n"); out->Print("public interface $name$\n", "name", @@ -504,6 +486,7 @@ void GenerateService(Printer* out, const ServiceDescriptor *service) { for (int i = 0; i < service->method_count(); i++) { GenerateStaticMethodField(out, service->method(i)); } + GenerateServiceDescriptorProperty(out, service); GenerateClientInterface(out, service); GenerateServerInterface(out, service); GenerateClientStub(out, service); @@ -539,7 +522,6 @@ grpc::string GetServices(const FileDescriptor *file) { out.Print("using System.Threading;\n"); out.Print("using System.Threading.Tasks;\n"); out.Print("using Grpc.Core;\n"); - // TODO(jtattermusch): add using for protobuf message classes out.Print("\n"); out.Print("namespace $namespace$ {\n", "namespace", GetFileNamespace(file)); diff --git a/src/compiler/csharp_generator.h b/src/compiler/csharp_generator.h index ec537d3f1d..90eb7e2984 100644 --- a/src/compiler/csharp_generator.h +++ b/src/compiler/csharp_generator.h @@ -36,6 +36,8 @@ #include "src/compiler/config.h" +#include <google/protobuf/compiler/csharp/csharp_names.h> + namespace grpc_csharp_generator { grpc::string GetServices(const grpc::protobuf::FileDescriptor *file); diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index 72c457ac6b..fe2b9fad99 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -148,8 +148,8 @@ class IndentScope { // END FORMATTING BOILERPLATE // //////////////////////////////// -bool PrintServicer(const ServiceDescriptor* service, - Printer* out) { +bool PrintAlphaServicer(const ServiceDescriptor* service, + Printer* out) { grpc::string doc = "<fill me in later!>"; map<grpc::string, grpc::string> dict = ListToDict({ "Service", service->name(), @@ -176,7 +176,7 @@ bool PrintServicer(const ServiceDescriptor* service, return true; } -bool PrintServer(const ServiceDescriptor* service, Printer* out) { +bool PrintAlphaServer(const ServiceDescriptor* service, Printer* out) { grpc::string doc = "<fill me in later!>"; map<grpc::string, grpc::string> dict = ListToDict({ "Service", service->name(), @@ -204,8 +204,8 @@ bool PrintServer(const ServiceDescriptor* service, Printer* out) { return true; } -bool PrintStub(const ServiceDescriptor* service, - Printer* out) { +bool PrintAlphaStub(const ServiceDescriptor* service, + Printer* out) { grpc::string doc = "<fill me in later!>"; map<grpc::string, grpc::string> dict = ListToDict({ "Service", service->name(), @@ -268,8 +268,8 @@ bool GetModuleAndMessagePath(const Descriptor* type, return true; } -bool PrintServerFactory(const grpc::string& package_qualified_service_name, - const ServiceDescriptor* service, Printer* out) { +bool PrintAlphaServerFactory(const grpc::string& package_qualified_service_name, + const ServiceDescriptor* service, Printer* out) { out->Print("def early_adopter_create_$Service$_server(servicer, port, " "private_key=None, certificate_chain=None):\n", "Service", service->name()); @@ -320,7 +320,7 @@ bool PrintServerFactory(const grpc::string& package_qualified_service_name, input_message_modules_and_classes.find(method_name); auto output_message_module_and_class = output_message_modules_and_classes.find(method_name); - out->Print("\"$Method$\": utilities.$Constructor$(\n", "Method", + out->Print("\"$Method$\": alpha_utilities.$Constructor$(\n", "Method", method_name, "Constructor", name_and_description_constructor->second); { @@ -348,8 +348,8 @@ bool PrintServerFactory(const grpc::string& package_qualified_service_name, return true; } -bool PrintStubFactory(const grpc::string& package_qualified_service_name, - const ServiceDescriptor* service, Printer* out) { +bool PrintAlphaStubFactory(const grpc::string& package_qualified_service_name, + const ServiceDescriptor* service, Printer* out) { map<grpc::string, grpc::string> dict = ListToDict({ "Service", service->name(), }); @@ -404,7 +404,7 @@ bool PrintStubFactory(const grpc::string& package_qualified_service_name, input_message_modules_and_classes.find(method_name); auto output_message_module_and_class = output_message_modules_and_classes.find(method_name); - out->Print("\"$Method$\": utilities.$Constructor$(\n", "Method", + out->Print("\"$Method$\": alpha_utilities.$Constructor$(\n", "Method", method_name, "Constructor", name_and_description_constructor->second); { @@ -434,12 +434,280 @@ bool PrintStubFactory(const grpc::string& package_qualified_service_name, return true; } +bool PrintBetaServicer(const ServiceDescriptor* service, + Printer* out) { + grpc::string doc = "<fill me in later!>"; + map<grpc::string, grpc::string> dict = ListToDict({ + "Service", service->name(), + "Documentation", doc, + }); + out->Print("\n"); + out->Print(dict, "class Beta$Service$Servicer(object):\n"); + { + IndentScope raii_class_indent(out); + out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); + out->Print("__metaclass__ = abc.ABCMeta\n"); + for (int i = 0; i < service->method_count(); ++i) { + auto meth = service->method(i); + grpc::string arg_name = meth->client_streaming() ? + "request_iterator" : "request"; + out->Print("@abc.abstractmethod\n"); + out->Print("def $Method$(self, $ArgName$, context):\n", + "Method", meth->name(), "ArgName", arg_name); + { + IndentScope raii_method_indent(out); + out->Print("raise NotImplementedError()\n"); + } + } + } + return true; +} + +bool PrintBetaStub(const ServiceDescriptor* service, + Printer* out) { + grpc::string doc = "The interface to which stubs will conform."; + map<grpc::string, grpc::string> dict = ListToDict({ + "Service", service->name(), + "Documentation", doc, + }); + out->Print("\n"); + out->Print(dict, "class Beta$Service$Stub(object):\n"); + { + IndentScope raii_class_indent(out); + out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); + out->Print("__metaclass__ = abc.ABCMeta\n"); + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* meth = service->method(i); + grpc::string arg_name = meth->client_streaming() ? + "request_iterator" : "request"; + auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name}); + out->Print("@abc.abstractmethod\n"); + out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n"); + { + IndentScope raii_method_indent(out); + out->Print("raise NotImplementedError()\n"); + } + if (!meth->server_streaming()) { + out->Print(methdict, "$Method$.future = None\n"); + } + } + } + return true; +} + +bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name, + const ServiceDescriptor* service, Printer* out) { + out->Print("\n"); + out->Print("def beta_create_$Service$_server(servicer, pool=None, " + "pool_size=None, default_timeout=None, maximum_timeout=None):\n", + "Service", service->name()); + { + IndentScope raii_create_server_indent(out); + map<grpc::string, grpc::string> method_implementation_constructors; + map<grpc::string, pair<grpc::string, grpc::string>> + input_message_modules_and_classes; + map<grpc::string, pair<grpc::string, grpc::string>> + output_message_modules_and_classes; + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + const grpc::string method_implementation_constructor = + grpc::string(method->client_streaming() ? "stream_" : "unary_") + + grpc::string(method->server_streaming() ? "stream_" : "unary_") + + "inline"; + pair<grpc::string, grpc::string> input_message_module_and_class; + if (!GetModuleAndMessagePath(method->input_type(), + &input_message_module_and_class)) { + return false; + } + pair<grpc::string, grpc::string> output_message_module_and_class; + if (!GetModuleAndMessagePath(method->output_type(), + &output_message_module_and_class)) { + return false; + } + // Import the modules that define the messages used in RPCs. + out->Print("import $Module$\n", "Module", + input_message_module_and_class.first); + out->Print("import $Module$\n", "Module", + output_message_module_and_class.first); + method_implementation_constructors.insert( + make_pair(method->name(), method_implementation_constructor)); + input_message_modules_and_classes.insert( + make_pair(method->name(), input_message_module_and_class)); + output_message_modules_and_classes.insert( + make_pair(method->name(), output_message_module_and_class)); + } + out->Print("request_deserializers = {\n"); + for (auto name_and_input_module_class_pair = + input_message_modules_and_classes.begin(); + name_and_input_module_class_pair != + input_message_modules_and_classes.end(); + name_and_input_module_class_pair++) { + IndentScope raii_indent(out); + out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " + "$InputTypeModule$.$InputTypeClass$.FromString,\n", + "PackageQualifiedServiceName", package_qualified_service_name, + "MethodName", name_and_input_module_class_pair->first, + "InputTypeModule", + name_and_input_module_class_pair->second.first, + "InputTypeClass", + name_and_input_module_class_pair->second.second); + } + out->Print("}\n"); + out->Print("response_serializers = {\n"); + for (auto name_and_output_module_class_pair = + output_message_modules_and_classes.begin(); + name_and_output_module_class_pair != + output_message_modules_and_classes.end(); + name_and_output_module_class_pair++) { + IndentScope raii_indent(out); + out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " + "$OutputTypeModule$.$OutputTypeClass$.SerializeToString,\n", + "PackageQualifiedServiceName", package_qualified_service_name, + "MethodName", name_and_output_module_class_pair->first, + "OutputTypeModule", + name_and_output_module_class_pair->second.first, + "OutputTypeClass", + name_and_output_module_class_pair->second.second); + } + out->Print("}\n"); + out->Print("method_implementations = {\n"); + for (auto name_and_implementation_constructor = + method_implementation_constructors.begin(); + name_and_implementation_constructor != + method_implementation_constructors.end(); + name_and_implementation_constructor++) { + IndentScope raii_descriptions_indent(out); + const grpc::string method_name = + name_and_implementation_constructor->first; + out->Print("(\'$PackageQualifiedServiceName$\', \'$Method$\'): " + "face_utilities.$Constructor$(servicer.$Method$),\n", + "PackageQualifiedServiceName", package_qualified_service_name, + "Method", name_and_implementation_constructor->first, + "Constructor", name_and_implementation_constructor->second); + } + out->Print("}\n"); + out->Print("server_options = beta.server_options(" + "request_deserializers=request_deserializers, " + "response_serializers=response_serializers, " + "thread_pool=pool, thread_pool_size=pool_size, " + "default_timeout=default_timeout, " + "maximum_timeout=maximum_timeout)\n"); + out->Print("return beta.server(method_implementations, " + "options=server_options)\n"); + } + return true; +} + +bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name, + const ServiceDescriptor* service, Printer* out) { + map<grpc::string, grpc::string> dict = ListToDict({ + "Service", service->name(), + }); + out->Print("\n"); + out->Print(dict, "def beta_create_$Service$_stub(channel, host=None," + " metadata_transformer=None, pool=None, pool_size=None):\n"); + { + IndentScope raii_create_server_indent(out); + map<grpc::string, grpc::string> method_cardinalities; + map<grpc::string, pair<grpc::string, grpc::string>> + input_message_modules_and_classes; + map<grpc::string, pair<grpc::string, grpc::string>> + output_message_modules_and_classes; + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + const grpc::string method_cardinality = + grpc::string(method->client_streaming() ? "STREAM" : "UNARY") + + "_" + + grpc::string(method->server_streaming() ? "STREAM" : "UNARY"); + pair<grpc::string, grpc::string> input_message_module_and_class; + if (!GetModuleAndMessagePath(method->input_type(), + &input_message_module_and_class)) { + return false; + } + pair<grpc::string, grpc::string> output_message_module_and_class; + if (!GetModuleAndMessagePath(method->output_type(), + &output_message_module_and_class)) { + return false; + } + // Import the modules that define the messages used in RPCs. + out->Print("import $Module$\n", "Module", + input_message_module_and_class.first); + out->Print("import $Module$\n", "Module", + output_message_module_and_class.first); + method_cardinalities.insert( + make_pair(method->name(), method_cardinality)); + input_message_modules_and_classes.insert( + make_pair(method->name(), input_message_module_and_class)); + output_message_modules_and_classes.insert( + make_pair(method->name(), output_message_module_and_class)); + } + out->Print("request_serializers = {\n"); + for (auto name_and_input_module_class_pair = + input_message_modules_and_classes.begin(); + name_and_input_module_class_pair != + input_message_modules_and_classes.end(); + name_and_input_module_class_pair++) { + IndentScope raii_indent(out); + out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " + "$InputTypeModule$.$InputTypeClass$.SerializeToString,\n", + "PackageQualifiedServiceName", package_qualified_service_name, + "MethodName", name_and_input_module_class_pair->first, + "InputTypeModule", + name_and_input_module_class_pair->second.first, + "InputTypeClass", + name_and_input_module_class_pair->second.second); + } + out->Print("}\n"); + out->Print("response_deserializers = {\n"); + for (auto name_and_output_module_class_pair = + output_message_modules_and_classes.begin(); + name_and_output_module_class_pair != + output_message_modules_and_classes.end(); + name_and_output_module_class_pair++) { + IndentScope raii_indent(out); + out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " + "$OutputTypeModule$.$OutputTypeClass$.FromString,\n", + "PackageQualifiedServiceName", package_qualified_service_name, + "MethodName", name_and_output_module_class_pair->first, + "OutputTypeModule", + name_and_output_module_class_pair->second.first, + "OutputTypeClass", + name_and_output_module_class_pair->second.second); + } + out->Print("}\n"); + out->Print("cardinalities = {\n"); + for (auto name_and_cardinality = method_cardinalities.begin(); + name_and_cardinality != method_cardinalities.end(); + name_and_cardinality++) { + IndentScope raii_descriptions_indent(out); + out->Print("\'$Method$\': cardinality.Cardinality.$Cardinality$,\n", + "Method", name_and_cardinality->first, + "Cardinality", name_and_cardinality->second); + } + out->Print("}\n"); + out->Print("stub_options = beta.stub_options(" + "host=host, metadata_transformer=metadata_transformer, " + "request_serializers=request_serializers, " + "response_deserializers=response_deserializers, " + "thread_pool=pool, thread_pool_size=pool_size)\n"); + out->Print( + "return beta.dynamic_stub(channel, \'$PackageQualifiedServiceName$\', " + "cardinalities, options=stub_options)\n", + "PackageQualifiedServiceName", package_qualified_service_name); + } + return true; +} + bool PrintPreamble(const FileDescriptor* file, const GeneratorConfiguration& config, Printer* out) { out->Print("import abc\n"); + out->Print("from $Package$ import beta\n", + "Package", config.beta_package_root); out->Print("from $Package$ import implementations\n", - "Package", config.implementations_package_root); - out->Print("from grpc.framework.alpha import utilities\n"); + "Package", config.early_adopter_package_root); + out->Print("from grpc.framework.alpha import utilities as alpha_utilities\n"); + out->Print("from grpc.framework.common import cardinality\n"); + out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n"); return true; } @@ -462,11 +730,15 @@ pair<bool, grpc::string> GetServices(const FileDescriptor* file, for (int i = 0; i < file->service_count(); ++i) { auto service = file->service(i); auto package_qualified_service_name = package + service->name(); - if (!(PrintServicer(service, &out) && - PrintServer(service, &out) && - PrintStub(service, &out) && - PrintServerFactory(package_qualified_service_name, service, &out) && - PrintStubFactory(package_qualified_service_name, service, &out))) { + if (!(PrintAlphaServicer(service, &out) && + PrintAlphaServer(service, &out) && + PrintAlphaStub(service, &out) && + PrintAlphaServerFactory(package_qualified_service_name, service, &out) && + PrintAlphaStubFactory(package_qualified_service_name, service, &out) && + PrintBetaServicer(service, &out) && + PrintBetaStub(service, &out) && + PrintBetaServerFactory(package_qualified_service_name, service, &out) && + PrintBetaStubFactory(package_qualified_service_name, service, &out))) { return make_pair(false, ""); } } diff --git a/src/compiler/python_generator.h b/src/compiler/python_generator.h index b47f3c1243..44ed4b3f98 100644 --- a/src/compiler/python_generator.h +++ b/src/compiler/python_generator.h @@ -43,7 +43,8 @@ namespace grpc_python_generator { // Data pertaining to configuration of the generator with respect to anything // that may be used internally at Google. struct GeneratorConfiguration { - grpc::string implementations_package_root; + grpc::string early_adopter_package_root; + grpc::string beta_package_root; }; class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc index d1f49442da..c7cef54900 100644 --- a/src/compiler/python_plugin.cc +++ b/src/compiler/python_plugin.cc @@ -38,7 +38,8 @@ int main(int argc, char* argv[]) { grpc_python_generator::GeneratorConfiguration config; - config.implementations_package_root = "grpc.early_adopter"; + config.early_adopter_package_root = "grpc.early_adopter"; + config.beta_package_root = "grpc.beta"; grpc_python_generator::PythonGrpcGenerator generator(config); return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); } diff --git a/src/core/census/aggregation.h b/src/core/census/aggregation.h new file mode 100644 index 0000000000..e9bc6ada96 --- /dev/null +++ b/src/core/census/aggregation.h @@ -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. + * + */ + +#include <stddef.h> + +#ifndef GRPC_INTERNAL_CORE_CENSUS_AGGREGATION_H +#define GRPC_INTERNAL_CORE_CENSUS_AGGREGATION_H + +/** Structure used to describe an aggregation type. */ +struct census_aggregation_ops { + /* Create a new aggregation. The pointer returned can be used in future calls + to clone(), free(), record(), data() and reset(). */ + void *(*create)(const void *create_arg); + /* Make a copy of an aggregation created by create() */ + void *(*clone)(const void *aggregation); + /* Destroy an aggregation created by create() */ + void (*free)(void *aggregation); + /* Record a new value against aggregation. */ + void (*record)(void *aggregation, double value); + /* Return current aggregation data. The caller must cast this object into + the correct type for the aggregation result. The object returned can be + freed by using free_data(). */ + void *(*data)(const void *aggregation); + /* free data returned by data() */ + void (*free_data)(void *data); + /* Reset an aggregation to default (zero) values. */ + void (*reset)(void *aggregation); + /* Merge 'from' aggregation into 'to'. Both aggregations must be compatible */ + void (*merge)(void *to, const void *from); + /* Fill buffer with printable string version of aggregation contents. For + debugging only. Returns the number of bytes added to buffer (a value == n + implies the buffer was of insufficient size). */ + size_t (*print)(const void *aggregation, char *buffer, size_t n); +}; + +#endif /* GRPC_INTERNAL_CORE_CENSUS_AGGREGATION_H */ diff --git a/src/core/census/context.c b/src/core/census/context.c index df238ec98c..cab58b653c 100644 --- a/src/core/census/context.c +++ b/src/core/census/context.c @@ -44,16 +44,3 @@ size_t census_context_serialize(const census_context *context, char *buffer, /* TODO(aveitch): implement serialization */ return 0; } - -int census_context_deserialize(const char *buffer, census_context **context) { - int ret = 0; - if (buffer != NULL) { - /* TODO(aveitch): implement deserialization. */ - ret = 1; - } - *context = gpr_malloc(sizeof(census_context)); - memset(*context, 0, sizeof(census_context)); - return ret; -} - -void census_context_destroy(census_context *context) { gpr_free(context); } diff --git a/src/core/census/grpc_context.c b/src/core/census/grpc_context.c index 11f1eb3d5d..429f3ec9db 100644 --- a/src/core/census/grpc_context.c +++ b/src/core/census/grpc_context.c @@ -35,24 +35,11 @@ #include <grpc/grpc.h> #include "src/core/surface/call.h" -static void grpc_census_context_destroy(void *context) { - census_context_destroy((census_context *)context); -} - void grpc_census_call_set_context(grpc_call *call, census_context *context) { if (census_enabled() == CENSUS_FEATURE_NONE) { return; } - if (context == NULL) { - if (grpc_call_is_client(call)) { - census_context *context_ptr; - census_context_deserialize(NULL, &context_ptr); - grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context_ptr, - grpc_census_context_destroy); - } else { - /* TODO(aveitch): server side context code to be implemented. */ - } - } else { + if (context != NULL) { grpc_call_context_set(call, GRPC_CONTEXT_TRACING, context, NULL); } } diff --git a/src/core/census/grpc_filter.c b/src/core/census/grpc_filter.c index fbedb35661..e01c9a2ad4 100644 --- a/src/core/census/grpc_filter.c +++ b/src/core/census/grpc_filter.c @@ -37,11 +37,11 @@ #include <string.h> #include "include/grpc/census.h" -#include "src/core/census/rpc_stat_id.h" #include "src/core/channel/channel_stack.h" #include "src/core/channel/noop_filter.h" #include "src/core/statistics/census_interface.h" #include "src/core/statistics/census_rpc_stats.h" +#include <grpc/census.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/slice.h> @@ -173,25 +173,15 @@ static void destroy_channel_elem(grpc_channel_element* elem) { } const grpc_channel_filter grpc_client_census_filter = { - client_start_transport_op, - grpc_channel_next_op, - sizeof(call_data), - client_init_call_elem, - client_destroy_call_elem, - sizeof(channel_data), - init_channel_elem, - destroy_channel_elem, - grpc_call_next_get_peer, - "census-client"}; + client_start_transport_op, grpc_channel_next_op, + sizeof(call_data), client_init_call_elem, + client_destroy_call_elem, sizeof(channel_data), + init_channel_elem, destroy_channel_elem, + grpc_call_next_get_peer, "census-client"}; const grpc_channel_filter grpc_server_census_filter = { - server_start_transport_op, - grpc_channel_next_op, - sizeof(call_data), - server_init_call_elem, - server_destroy_call_elem, - sizeof(channel_data), - init_channel_elem, - destroy_channel_elem, - grpc_call_next_get_peer, - "census-server"}; + server_start_transport_op, grpc_channel_next_op, + sizeof(call_data), server_init_call_elem, + server_destroy_call_elem, sizeof(channel_data), + init_channel_elem, destroy_channel_elem, + grpc_call_next_get_peer, "census-server"}; diff --git a/src/core/census/grpc_filter.h b/src/core/census/grpc_filter.h index 1453c05d28..b3de3adc94 100644 --- a/src/core/census/grpc_filter.h +++ b/src/core/census/grpc_filter.h @@ -31,8 +31,8 @@ * */ -#ifndef GRPC_INTERNAL_CORE_CHANNEL_CENSUS_FILTER_H -#define GRPC_INTERNAL_CORE_CHANNEL_CENSUS_FILTER_H +#ifndef GRPC_INTERNAL_CORE_CENSUS_GRPC_FILTER_H +#define GRPC_INTERNAL_CORE_CENSUS_GRPC_FILTER_H #include "src/core/channel/channel_stack.h" @@ -41,4 +41,4 @@ extern const grpc_channel_filter grpc_client_census_filter; extern const grpc_channel_filter grpc_server_census_filter; -#endif /* GRPC_INTERNAL_CORE_CHANNEL_CENSUS_FILTER_H */ +#endif /* GRPC_INTERNAL_CORE_CENSUS_GRPC_FILTER_H */ diff --git a/src/core/census/operation.c b/src/core/census/operation.c new file mode 100644 index 0000000000..118eb0a47a --- /dev/null +++ b/src/core/census/operation.c @@ -0,0 +1,63 @@ +/* + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/census.h> + +/* TODO(aveitch): These are all placeholder implementations. */ + +census_timestamp census_start_rpc_op_timestamp(void) { + census_timestamp ct; + /* TODO(aveitch): assumes gpr_timespec implementation of census_timestamp. */ + ct.ts = gpr_now(GPR_CLOCK_MONOTONIC); + return ct; +} + +census_context *census_start_client_rpc_op( + const census_context *context, gpr_int64 rpc_name_id, + const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, + const census_timestamp *start_time) { + return NULL; +} + +census_context *census_start_server_rpc_op( + const char *buffer, gpr_int64 rpc_name_id, + const census_rpc_name_info *rpc_name_info, const char *peer, int trace_mask, + census_timestamp *start_time) { + return NULL; +} + +census_context *census_start_op(census_context *context, const char *family, + const char *name, int trace_mask) { + return NULL; +} + +void census_end_op(census_context *context, int status) {} diff --git a/src/core/census/rpc_stat_id.h b/src/core/census/rpc_metric_id.h index fc0aa6f43f..1d8e8806f5 100644 --- a/src/core/census/rpc_stat_id.h +++ b/src/core/census/rpc_metric_id.h @@ -31,16 +31,21 @@ * */ -#ifndef CENSUS_RPC_STAT_ID_H -#define CENSUS_RPC_STAT_ID_H +#ifndef CENSUS_RPC_METRIC_ID_H +#define CENSUS_RPC_METRIC_ID_H -/* Stats ID's used for RPC measurements. */ -#define CENSUS_INVALID_STAT_ID 0 /* ID 0 is always invalid */ -#define CENSUS_RPC_CLIENT_REQUESTS 1 /* Count of client requests sent. */ -#define CENSUS_RPC_SERVER_REQUESTS 2 /* Count of server requests sent. */ -#define CENSUS_RPC_CLIENT_ERRORS 3 /* Client error counts. */ -#define CENSUS_RPC_SERVER_ERRORS 4 /* Server error counts. */ -#define CENSUS_RPC_CLIENT_LATENCY 5 /* Client side request latency. */ -#define CENSUS_RPC_SERVER_LATENCY 6 /* Server side request latency. */ +/* Metric ID's used for RPC measurements. */ +/* Count of client requests sent. */ +#define CENSUS_METRIC_RPC_CLIENT_REQUESTS ((gpr_uint32)0) +/* Count of server requests sent. */ +#define CENSUS_METRIC_RPC_SERVER_REQUESTS ((gpr_uint32)1) +/* Client error counts. */ +#define CENSUS_METRIC_RPC_CLIENT_ERRORS ((gpr_uint32)2) +/* Server error counts. */ +#define CENSUS_METRIC_RPC_SERVER_ERRORS ((gpr_uint32)3) +/* Client side request latency. */ +#define CENSUS_METRIC_RPC_CLIENT_LATENCY ((gpr_uint32)4) +/* Server side request latency. */ +#define CENSUS_METRIC_RPC_SERVER_LATENCY ((gpr_uint32)5) -#endif /* CENSUS_RPC_STAT_ID_H */ +#endif /* CENSUS_RPC_METRIC_ID_H */ diff --git a/src/core/census/record_stat.c b/src/core/census/tracing.c index 3dd918618b..ae38773c0a 100644 --- a/src/core/census/record_stat.c +++ b/src/core/census/tracing.c @@ -32,7 +32,14 @@ */ #include <grpc/census.h> -#include "src/core/census/rpc_stat_id.h" -void census_record_stat(census_context *context, census_stat *stats, - size_t nstats) {} +/* TODO(aveitch): These are all placeholder implementations. */ + +int census_trace_mask(const census_context *context) { + return CENSUS_TRACE_MASK_NONE; +} + +void census_set_trace_mask(int trace_mask) {} + +void census_trace_print(census_context *context, gpr_uint32 type, + const char *buffer, size_t n) {} diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c index 8e63978b82..f3ecfd0e60 100644 --- a/src/core/security/client_auth_filter.c +++ b/src/core/security/client_auth_filter.c @@ -153,7 +153,8 @@ static void send_security_metadata(grpc_call_element *elem, } if (channel_creds_has_md && call_creds_has_md) { - calld->creds = grpc_composite_credentials_create(channel_creds, ctx->creds); + calld->creds = + grpc_composite_credentials_create(channel_creds, ctx->creds, NULL); if (calld->creds == NULL) { bubble_up_error(elem, GRPC_STATUS_INVALID_ARGUMENT, "Incompatible credentials set on channel and call."); diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 8852cab3e7..a764413300 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -87,7 +87,10 @@ grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) { void grpc_credentials_unref(grpc_credentials *creds) { if (creds == NULL) return; - if (gpr_unref(&creds->refcount)) creds->vtable->destroy(creds); + if (gpr_unref(&creds->refcount)) { + creds->vtable->destruct(creds); + gpr_free(creds); + } } void grpc_credentials_release(grpc_credentials *creds) { @@ -135,9 +138,26 @@ grpc_security_status grpc_credentials_create_security_connector( creds, target, args, request_metadata_creds, sc, new_args); } -void grpc_server_credentials_release(grpc_server_credentials *creds) { +grpc_server_credentials *grpc_server_credentials_ref( + grpc_server_credentials *creds) { + if (creds == NULL) return NULL; + gpr_ref(&creds->refcount); + return creds; +} + +void grpc_server_credentials_unref(grpc_server_credentials *creds) { if (creds == NULL) return; - creds->vtable->destroy(creds); + if (gpr_unref(&creds->refcount)) { + creds->vtable->destruct(creds); + if (creds->processor.destroy != NULL && creds->processor.state != NULL) { + creds->processor.destroy(creds->processor.state); + } + gpr_free(creds); + } +} + +void grpc_server_credentials_release(grpc_server_credentials *creds) { + grpc_server_credentials_unref(creds); } grpc_security_status grpc_server_credentials_create_security_connector( @@ -152,20 +172,22 @@ grpc_security_status grpc_server_credentials_create_security_connector( void grpc_server_credentials_set_auth_metadata_processor( grpc_server_credentials *creds, grpc_auth_metadata_processor processor) { if (creds == NULL) return; + if (creds->processor.destroy != NULL && creds->processor.state != NULL) { + creds->processor.destroy(creds->processor.state); + } creds->processor = processor; } /* -- Ssl credentials. -- */ -static void ssl_destroy(grpc_credentials *creds) { +static void ssl_destruct(grpc_credentials *creds) { grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds; if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key); if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain); - gpr_free(creds); } -static void ssl_server_destroy(grpc_server_credentials *creds) { +static void ssl_server_destruct(grpc_server_credentials *creds) { grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds; size_t i; for (i = 0; i < c->config.num_key_cert_pairs; i++) { @@ -185,7 +207,6 @@ static void ssl_server_destroy(grpc_server_credentials *creds) { gpr_free(c->config.pem_cert_chains_sizes); } if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs); - gpr_free(creds); } static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; } @@ -231,11 +252,11 @@ static grpc_security_status ssl_server_create_security_connector( } static grpc_credentials_vtable ssl_vtable = { - ssl_destroy, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL, + ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL, ssl_create_security_connector}; static grpc_server_credentials_vtable ssl_server_vtable = { - ssl_server_destroy, ssl_server_create_security_connector}; + ssl_server_destruct, ssl_server_create_security_connector}; static void ssl_copy_key_material(const char *input, unsigned char **output, size_t *output_size) { @@ -298,8 +319,10 @@ static void ssl_build_server_config( } grpc_credentials *grpc_ssl_credentials_create( - const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair) { + const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair, + void *reserved) { grpc_ssl_credentials *c = gpr_malloc(sizeof(grpc_ssl_credentials)); + GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_ssl_credentials)); c->base.type = GRPC_CREDENTIALS_TYPE_SSL; c->base.vtable = &ssl_vtable; @@ -310,11 +333,13 @@ grpc_credentials *grpc_ssl_credentials_create( grpc_server_credentials *grpc_ssl_server_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, - size_t num_key_cert_pairs, int force_client_auth) { + size_t num_key_cert_pairs, int force_client_auth, void *reserved) { grpc_ssl_server_credentials *c = gpr_malloc(sizeof(grpc_ssl_server_credentials)); + GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_ssl_server_credentials)); c->base.type = GRPC_CREDENTIALS_TYPE_SSL; + gpr_ref_init(&c->base.refcount, 1); c->base.vtable = &ssl_server_vtable; ssl_build_server_config(pem_root_certs, pem_key_cert_pairs, num_key_cert_pairs, force_client_auth, &c->config); @@ -335,13 +360,12 @@ static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) { c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); } -static void jwt_destroy(grpc_credentials *creds) { +static void jwt_destruct(grpc_credentials *creds) { grpc_service_account_jwt_access_credentials *c = (grpc_service_account_jwt_access_credentials *)creds; grpc_auth_json_key_destruct(&c->key); jwt_reset_cache(c); gpr_mu_destroy(&c->cache_mu); - gpr_free(c); } static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; } @@ -406,7 +430,7 @@ static void jwt_get_request_metadata(grpc_credentials *creds, } static grpc_credentials_vtable jwt_vtable = { - jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only, + jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only, jwt_get_request_metadata, NULL}; grpc_credentials * @@ -430,20 +454,20 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key( } grpc_credentials *grpc_service_account_jwt_access_credentials_create( - const char *json_key, gpr_timespec token_lifetime) { + const char *json_key, gpr_timespec token_lifetime, void *reserved) { + GPR_ASSERT(reserved == NULL); return grpc_service_account_jwt_access_credentials_create_from_auth_json_key( grpc_auth_json_key_create_from_string(json_key), token_lifetime); } /* -- Oauth2TokenFetcher credentials -- */ -static void oauth2_token_fetcher_destroy(grpc_credentials *creds) { +static void oauth2_token_fetcher_destruct(grpc_credentials *creds) { grpc_oauth2_token_fetcher_credentials *c = (grpc_oauth2_token_fetcher_credentials *)creds; grpc_credentials_md_store_unref(c->access_token_md); gpr_mu_destroy(&c->mu); grpc_httpcli_context_destroy(&c->httpcli_context); - gpr_free(c); } static int oauth2_token_fetcher_has_request_metadata( @@ -613,10 +637,10 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c, grpc_httpcli_context_init(&c->httpcli_context); } -/* -- ComputeEngine credentials. -- */ +/* -- GoogleComputeEngine credentials. -- */ static grpc_credentials_vtable compute_engine_vtable = { - oauth2_token_fetcher_destroy, oauth2_token_fetcher_has_request_metadata, + oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata, oauth2_token_fetcher_has_request_metadata_only, oauth2_token_fetcher_get_request_metadata, NULL}; @@ -635,94 +659,27 @@ static void compute_engine_fetch_oauth2( metadata_req); } -grpc_credentials *grpc_compute_engine_credentials_create(void) { +grpc_credentials *grpc_google_compute_engine_credentials_create( + void *reserved) { grpc_oauth2_token_fetcher_credentials *c = gpr_malloc(sizeof(grpc_oauth2_token_fetcher_credentials)); + GPR_ASSERT(reserved == NULL); init_oauth2_token_fetcher(c, compute_engine_fetch_oauth2); c->base.vtable = &compute_engine_vtable; return &c->base; } -/* -- ServiceAccount credentials. -- */ - -static void service_account_destroy(grpc_credentials *creds) { - grpc_service_account_credentials *c = - (grpc_service_account_credentials *)creds; - if (c->scope != NULL) gpr_free(c->scope); - grpc_auth_json_key_destruct(&c->key); - oauth2_token_fetcher_destroy(&c->base.base); -} - -static grpc_credentials_vtable service_account_vtable = { - service_account_destroy, oauth2_token_fetcher_has_request_metadata, - oauth2_token_fetcher_has_request_metadata_only, - oauth2_token_fetcher_get_request_metadata, NULL}; - -static void service_account_fetch_oauth2( - grpc_credentials_metadata_request *metadata_req, - grpc_httpcli_context *httpcli_context, grpc_pollset *pollset, - grpc_httpcli_response_cb response_cb, gpr_timespec deadline) { - grpc_service_account_credentials *c = - (grpc_service_account_credentials *)metadata_req->creds; - grpc_httpcli_header header = {"Content-Type", - "application/x-www-form-urlencoded"}; - grpc_httpcli_request request; - char *body = NULL; - char *jwt = grpc_jwt_encode_and_sign(&c->key, GRPC_JWT_OAUTH2_AUDIENCE, - c->token_lifetime, c->scope); - if (jwt == NULL) { - grpc_httpcli_response response; - memset(&response, 0, sizeof(grpc_httpcli_response)); - response.status = 400; /* Invalid request. */ - gpr_log(GPR_ERROR, "Could not create signed jwt."); - /* Do not even send the request, just call the response callback. */ - response_cb(metadata_req, &response); - return; - } - gpr_asprintf(&body, "%s%s", GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX, jwt); - memset(&request, 0, sizeof(grpc_httpcli_request)); - request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST; - request.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH; - request.hdr_count = 1; - request.hdrs = &header; - request.handshaker = &grpc_httpcli_ssl; - grpc_httpcli_post(httpcli_context, pollset, &request, body, strlen(body), - deadline, response_cb, metadata_req); - gpr_free(body); - gpr_free(jwt); -} - -grpc_credentials *grpc_service_account_credentials_create( - const char *json_key, const char *scope, gpr_timespec token_lifetime) { - grpc_service_account_credentials *c; - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key); +/* -- GoogleRefreshToken credentials. -- */ - if (scope == NULL || (strlen(scope) == 0) || - !grpc_auth_json_key_is_valid(&key)) { - gpr_log(GPR_ERROR, - "Invalid input for service account credentials creation"); - return NULL; - } - c = gpr_malloc(sizeof(grpc_service_account_credentials)); - memset(c, 0, sizeof(grpc_service_account_credentials)); - init_oauth2_token_fetcher(&c->base, service_account_fetch_oauth2); - c->base.base.vtable = &service_account_vtable; - c->scope = gpr_strdup(scope); - c->key = key; - c->token_lifetime = token_lifetime; - return &c->base.base; -} - -/* -- RefreshToken credentials. -- */ - -static void refresh_token_destroy(grpc_credentials *creds) { - grpc_refresh_token_credentials *c = (grpc_refresh_token_credentials *)creds; +static void refresh_token_destruct(grpc_credentials *creds) { + grpc_google_refresh_token_credentials *c = + (grpc_google_refresh_token_credentials *)creds; grpc_auth_refresh_token_destruct(&c->refresh_token); - oauth2_token_fetcher_destroy(&c->base.base); + oauth2_token_fetcher_destruct(&c->base.base); } static grpc_credentials_vtable refresh_token_vtable = { - refresh_token_destroy, oauth2_token_fetcher_has_request_metadata, + refresh_token_destruct, oauth2_token_fetcher_has_request_metadata, oauth2_token_fetcher_has_request_metadata_only, oauth2_token_fetcher_get_request_metadata, NULL}; @@ -730,8 +687,8 @@ static void refresh_token_fetch_oauth2( grpc_credentials_metadata_request *metadata_req, grpc_httpcli_context *httpcli_context, grpc_pollset *pollset, grpc_httpcli_response_cb response_cb, gpr_timespec deadline) { - grpc_refresh_token_credentials *c = - (grpc_refresh_token_credentials *)metadata_req->creds; + grpc_google_refresh_token_credentials *c = + (grpc_google_refresh_token_credentials *)metadata_req->creds; grpc_httpcli_header header = {"Content-Type", "application/x-www-form-urlencoded"}; grpc_httpcli_request request; @@ -750,33 +707,34 @@ static void refresh_token_fetch_oauth2( gpr_free(body); } -grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( +grpc_credentials * +grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token refresh_token) { - grpc_refresh_token_credentials *c; + grpc_google_refresh_token_credentials *c; if (!grpc_auth_refresh_token_is_valid(&refresh_token)) { gpr_log(GPR_ERROR, "Invalid input for refresh token credentials creation"); return NULL; } - c = gpr_malloc(sizeof(grpc_refresh_token_credentials)); - memset(c, 0, sizeof(grpc_refresh_token_credentials)); + c = gpr_malloc(sizeof(grpc_google_refresh_token_credentials)); + memset(c, 0, sizeof(grpc_google_refresh_token_credentials)); init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2); c->base.base.vtable = &refresh_token_vtable; c->refresh_token = refresh_token; return &c->base.base; } -grpc_credentials *grpc_refresh_token_credentials_create( - const char *json_refresh_token) { +grpc_credentials *grpc_google_refresh_token_credentials_create( + const char *json_refresh_token, void *reserved) { + GPR_ASSERT(reserved == NULL); return grpc_refresh_token_credentials_create_from_auth_refresh_token( grpc_auth_refresh_token_create_from_string(json_refresh_token)); } /* -- Metadata-only credentials. -- */ -static void md_only_test_destroy(grpc_credentials *creds) { +static void md_only_test_destruct(grpc_credentials *creds) { grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds; grpc_credentials_md_store_unref(c->md_store); - gpr_free(c); } static int md_only_test_has_request_metadata(const grpc_credentials *creds) { @@ -817,7 +775,7 @@ static void md_only_test_get_request_metadata(grpc_credentials *creds, } static grpc_credentials_vtable md_only_test_vtable = { - md_only_test_destroy, md_only_test_has_request_metadata, + md_only_test_destruct, md_only_test_has_request_metadata, md_only_test_has_request_metadata_only, md_only_test_get_request_metadata, NULL}; @@ -838,10 +796,9 @@ grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key, /* -- Oauth2 Access Token credentials. -- */ -static void access_token_destroy(grpc_credentials *creds) { +static void access_token_destruct(grpc_credentials *creds) { grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds; grpc_credentials_md_store_unref(c->access_token_md); - gpr_free(c); } static int access_token_has_request_metadata(const grpc_credentials *creds) { @@ -863,15 +820,16 @@ static void access_token_get_request_metadata(grpc_credentials *creds, } static grpc_credentials_vtable access_token_vtable = { - access_token_destroy, access_token_has_request_metadata, + access_token_destruct, access_token_has_request_metadata, access_token_has_request_metadata_only, access_token_get_request_metadata, NULL}; -grpc_credentials *grpc_access_token_credentials_create( - const char *access_token) { +grpc_credentials *grpc_access_token_credentials_create(const char *access_token, + void *reserved) { grpc_access_token_credentials *c = gpr_malloc(sizeof(grpc_access_token_credentials)); char *token_md_value; + GPR_ASSERT(reserved == NULL); memset(c, 0, sizeof(grpc_access_token_credentials)); c->base.type = GRPC_CREDENTIALS_TYPE_OAUTH2; c->base.vtable = &access_token_vtable; @@ -886,14 +844,14 @@ grpc_credentials *grpc_access_token_credentials_create( /* -- Fake transport security credentials. -- */ -static void fake_transport_security_credentials_destroy( +static void fake_transport_security_credentials_destruct( grpc_credentials *creds) { - gpr_free(creds); + /* Nothing to do here. */ } -static void fake_transport_security_server_credentials_destroy( +static void fake_transport_security_server_credentials_destruct( grpc_server_credentials *creds) { - gpr_free(creds); + /* Nothing to do here. */ } static int fake_transport_security_has_request_metadata( @@ -922,14 +880,14 @@ fake_transport_security_server_create_security_connector( } static grpc_credentials_vtable fake_transport_security_credentials_vtable = { - fake_transport_security_credentials_destroy, + fake_transport_security_credentials_destruct, fake_transport_security_has_request_metadata, fake_transport_security_has_request_metadata_only, NULL, fake_transport_security_create_security_connector}; static grpc_server_credentials_vtable fake_transport_security_server_credentials_vtable = { - fake_transport_security_server_credentials_destroy, + fake_transport_security_server_credentials_destruct, fake_transport_security_server_create_security_connector}; grpc_credentials *grpc_fake_transport_security_credentials_create(void) { @@ -946,6 +904,7 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create( grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials)); memset(c, 0, sizeof(grpc_server_credentials)); c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY; + gpr_ref_init(&c->refcount, 1); c->vtable = &fake_transport_security_server_credentials_vtable; return c; } @@ -962,14 +921,13 @@ typedef struct { grpc_credentials_metadata_cb cb; } grpc_composite_credentials_metadata_context; -static void composite_destroy(grpc_credentials *creds) { +static void composite_destruct(grpc_credentials *creds) { grpc_composite_credentials *c = (grpc_composite_credentials *)creds; size_t i; for (i = 0; i < c->inner.num_creds; i++) { grpc_credentials_unref(c->inner.creds_array[i]); } gpr_free(c->inner.creds_array); - gpr_free(creds); } static int composite_has_request_metadata(const grpc_credentials *creds) { @@ -1085,7 +1043,7 @@ static grpc_security_status composite_create_security_connector( } static grpc_credentials_vtable composite_credentials_vtable = { - composite_destroy, composite_has_request_metadata, + composite_destruct, composite_has_request_metadata, composite_has_request_metadata_only, composite_get_request_metadata, composite_create_security_connector}; @@ -1101,12 +1059,14 @@ static grpc_credentials_array get_creds_array(grpc_credentials **creds_addr) { } grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1, - grpc_credentials *creds2) { + grpc_credentials *creds2, + void *reserved) { size_t i; size_t creds_array_byte_size; grpc_credentials_array creds1_array; grpc_credentials_array creds2_array; grpc_composite_credentials *c; + GPR_ASSERT(reserved == NULL); GPR_ASSERT(creds1 != NULL); GPR_ASSERT(creds2 != NULL); c = gpr_malloc(sizeof(grpc_composite_credentials)); @@ -1182,10 +1142,9 @@ grpc_credentials *grpc_credentials_contains_type( /* -- IAM credentials. -- */ -static void iam_destroy(grpc_credentials *creds) { - grpc_iam_credentials *c = (grpc_iam_credentials *)creds; +static void iam_destruct(grpc_credentials *creds) { + grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; grpc_credentials_md_store_unref(c->iam_md); - gpr_free(c); } static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; } @@ -1199,22 +1158,23 @@ static void iam_get_request_metadata(grpc_credentials *creds, const char *service_url, grpc_credentials_metadata_cb cb, void *user_data) { - grpc_iam_credentials *c = (grpc_iam_credentials *)creds; + grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; cb(user_data, c->iam_md->entries, c->iam_md->num_entries, GRPC_CREDENTIALS_OK); } static grpc_credentials_vtable iam_vtable = { - iam_destroy, iam_has_request_metadata, iam_has_request_metadata_only, + iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only, iam_get_request_metadata, NULL}; -grpc_credentials *grpc_iam_credentials_create(const char *token, - const char *authority_selector) { - grpc_iam_credentials *c; +grpc_credentials *grpc_google_iam_credentials_create( + const char *token, const char *authority_selector, void *reserved) { + grpc_google_iam_credentials *c; + GPR_ASSERT(reserved == NULL); GPR_ASSERT(token != NULL); GPR_ASSERT(authority_selector != NULL); - c = gpr_malloc(sizeof(grpc_iam_credentials)); - memset(c, 0, sizeof(grpc_iam_credentials)); + c = gpr_malloc(sizeof(grpc_google_iam_credentials)); + memset(c, 0, sizeof(grpc_google_iam_credentials)); c->base.type = GRPC_CREDENTIALS_TYPE_IAM; c->base.vtable = &iam_vtable; gpr_ref_init(&c->base.refcount, 1); diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h index 29cd1ac87f..8e4fed7615 100644 --- a/src/core/security/credentials.h +++ b/src/core/security/credentials.h @@ -129,7 +129,7 @@ typedef void (*grpc_credentials_metadata_cb)(void *user_data, grpc_credentials_status status); typedef struct { - void (*destroy)(grpc_credentials *c); + void (*destruct)(grpc_credentials *c); int (*has_request_metadata)(const grpc_credentials *c); int (*has_request_metadata_only)(const grpc_credentials *c); void (*get_request_metadata)(grpc_credentials *c, grpc_pollset *pollset, @@ -210,20 +210,28 @@ grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( /* --- grpc_server_credentials. --- */ typedef struct { - void (*destroy)(grpc_server_credentials *c); + void (*destruct)(grpc_server_credentials *c); grpc_security_status (*create_security_connector)( grpc_server_credentials *c, grpc_security_connector **sc); } grpc_server_credentials_vtable; + +/* TODO(jboeuf): Add a refcount. */ struct grpc_server_credentials { const grpc_server_credentials_vtable *vtable; const char *type; + gpr_refcount refcount; grpc_auth_metadata_processor processor; }; grpc_security_status grpc_server_credentials_create_security_connector( grpc_server_credentials *creds, grpc_security_connector **sc); +grpc_server_credentials *grpc_server_credentials_ref( + grpc_server_credentials *creds); + +void grpc_server_credentials_unref(grpc_server_credentials *creds); + /* -- Ssl credentials. -- */ typedef struct { @@ -277,21 +285,12 @@ typedef struct { grpc_fetch_oauth2_func fetch_func; } grpc_oauth2_token_fetcher_credentials; -/* -- ServiceAccount credentials. -- */ - -typedef struct { - grpc_oauth2_token_fetcher_credentials base; - grpc_auth_json_key key; - char *scope; - gpr_timespec token_lifetime; -} grpc_service_account_credentials; - -/* -- RefreshToken credentials. -- */ +/* -- GoogleRefreshToken credentials. -- */ typedef struct { grpc_oauth2_token_fetcher_credentials base; grpc_auth_refresh_token refresh_token; -} grpc_refresh_token_credentials; +} grpc_google_refresh_token_credentials; /* -- Oauth2 Access Token credentials. -- */ @@ -308,12 +307,12 @@ typedef struct { int is_async; } grpc_md_only_test_credentials; -/* -- IAM credentials. -- */ +/* -- GoogleIAM credentials. -- */ typedef struct { grpc_credentials base; grpc_credentials_md_store *iam_md; -} grpc_iam_credentials; +} grpc_google_iam_credentials; /* -- Composite credentials. -- */ diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c index 3631de867a..874dd59e84 100644 --- a/src/core/security/google_default_credentials.c +++ b/src/core/security/google_default_credentials.c @@ -194,7 +194,7 @@ grpc_credentials *grpc_google_default_credentials_create(void) { int need_compute_engine_creds = is_stack_running_on_compute_engine(); compute_engine_detection_done = 1; if (need_compute_engine_creds) { - result = grpc_compute_engine_credentials_create(); + result = grpc_google_compute_engine_credentials_create(NULL); } } @@ -202,9 +202,9 @@ end: if (!serving_cached_credentials && result != NULL) { /* Blend with default ssl credentials and add a global reference so that it can be cached and re-served. */ - grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL); + grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); default_credentials = grpc_credentials_ref( - grpc_composite_credentials_create(ssl_creds, result)); + grpc_composite_credentials_create(ssl_creds, result, NULL)); GPR_ASSERT(default_credentials != NULL); grpc_credentials_unref(ssl_creds); grpc_credentials_unref(result); diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c index c1b434f302..95d80ba122 100644 --- a/src/core/security/security_context.c +++ b/src/core/security/security_context.c @@ -42,19 +42,6 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.h> -/* --- grpc_process_auth_metadata_func --- */ - -static grpc_auth_metadata_processor server_processor = {NULL, NULL}; - -grpc_auth_metadata_processor grpc_server_get_auth_metadata_processor(void) { - return server_processor; -} - -void grpc_server_register_auth_metadata_processor( - grpc_auth_metadata_processor processor) { - server_processor = processor; -} - /* --- grpc_call --- */ grpc_call_error grpc_call_set_credentials(grpc_call *call, diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c index 6e831431fa..b767f85498 100644 --- a/src/core/security/server_auth_filter.c +++ b/src/core/security/server_auth_filter.c @@ -50,6 +50,7 @@ typedef struct call_data { handling it. */ grpc_iomgr_closure auth_on_recv; grpc_transport_stream_op transport_op; + grpc_metadata_array md; const grpc_metadata *consumed_md; size_t num_consumed_md; grpc_stream_op *md_op; @@ -90,13 +91,17 @@ static grpc_mdelem *remove_consumed_md(void *user_data, grpc_mdelem *md) { call_data *calld = elem->call_data; size_t i; for (i = 0; i < calld->num_consumed_md; i++) { + const grpc_metadata *consumed_md = &calld->consumed_md[i]; /* Maybe we could do a pointer comparison but we do not have any guarantee that the metadata processor used the same pointers for consumed_md in the callback. */ - if (memcmp(GPR_SLICE_START_PTR(md->key->slice), calld->consumed_md[i].key, + if (GPR_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) || + GPR_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) { + continue; + } + if (memcmp(GPR_SLICE_START_PTR(md->key->slice), consumed_md->key, GPR_SLICE_LENGTH(md->key->slice)) == 0 && - memcmp(GPR_SLICE_START_PTR(md->value->slice), - calld->consumed_md[i].value, + memcmp(GPR_SLICE_START_PTR(md->value->slice), consumed_md->value, GPR_SLICE_LENGTH(md->value->slice)) == 0) { return NULL; /* Delete. */ } @@ -134,6 +139,7 @@ static void on_md_processing_done( grpc_transport_stream_op_add_close(&calld->transport_op, status, &message); grpc_call_next_op(elem, &calld->transport_op); } + grpc_metadata_array_destroy(&calld->md); } static void auth_on_recv(void *user_data, int success) { @@ -145,17 +151,15 @@ static void auth_on_recv(void *user_data, int success) { size_t nops = calld->recv_ops->nops; grpc_stream_op *ops = calld->recv_ops->ops; for (i = 0; i < nops; i++) { - grpc_metadata_array md_array; grpc_stream_op *op = &ops[i]; if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue; calld->got_client_metadata = 1; if (chand->processor.process == NULL) continue; calld->md_op = op; - md_array = metadata_batch_to_md_array(&op->data.metadata); + calld->md = metadata_batch_to_md_array(&op->data.metadata); chand->processor.process(chand->processor.state, calld->auth_context, - md_array.metadata, md_array.count, + calld->md.metadata, calld->md.count, on_md_processing_done, elem); - grpc_metadata_array_destroy(&md_array); return; } } diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c index 8d9d036d80..4749f5f516 100644 --- a/src/core/security/server_secure_chttp2.c +++ b/src/core/security/server_secure_chttp2.c @@ -61,7 +61,7 @@ typedef struct grpc_server_secure_state { grpc_server *server; grpc_tcp_server *tcp; grpc_security_connector *sc; - grpc_auth_metadata_processor processor; + grpc_server_credentials *creds; tcp_endpoint_list *handshaking_tcp_endpoints; int is_shutdown; gpr_mu mu; @@ -79,6 +79,7 @@ static void state_unref(grpc_server_secure_state *state) { gpr_mu_unlock(&state->mu); /* clean up */ GRPC_SECURITY_CONNECTOR_UNREF(state->sc, "server"); + grpc_server_credentials_unref(state->creds); gpr_free(state); } } @@ -91,7 +92,8 @@ static void setup_transport(void *statep, grpc_transport *transport, grpc_channel_args *args_copy; grpc_arg args_to_add[2]; args_to_add[0] = grpc_security_connector_to_arg(state->sc); - args_to_add[1] = grpc_auth_metadata_processor_to_arg(&state->processor); + args_to_add[1] = + grpc_auth_metadata_processor_to_arg(&state->creds->processor); args_copy = grpc_channel_args_copy_and_add( grpc_server_get_channel_args(state->server), args_to_add, GPR_ARRAY_SIZE(args_to_add)); @@ -262,7 +264,8 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, state->server = server; state->tcp = tcp; state->sc = sc; - state->processor = creds->processor; + state->creds = grpc_server_credentials_ref(creds); + state->handshaking_tcp_endpoints = NULL; state->is_shutdown = 0; gpr_mu_init(&state->mu); diff --git a/src/core/support/log_win32.c b/src/core/support/log_win32.c index 629781da8a..b68239f8f5 100644 --- a/src/core/support/log_win32.c +++ b/src/core/support/log_win32.c @@ -81,10 +81,18 @@ void gpr_log(const char *file, int line, gpr_log_severity severity, /* Simple starter implementation */ void gpr_default_log(gpr_log_func_args *args) { + char *final_slash; + const char *display_file; char time_buffer[64]; gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); struct tm tm; + final_slash = strrchr(args->file, '\\'); + if (final_slash == NULL) + display_file = args->file; + else + display_file = final_slash + 1; + if (localtime_s(&tm, &now.tv_sec)) { strcpy(time_buffer, "error:localtime"); } else if (0 == @@ -94,7 +102,7 @@ void gpr_default_log(gpr_log_func_args *args) { fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n", gpr_log_severity_string(args->severity), time_buffer, - (int)(now.tv_nsec), GetCurrentThreadId(), args->file, args->line, + (int)(now.tv_nsec), GetCurrentThreadId(), display_file, args->line, args->message); } diff --git a/src/core/surface/secure_channel_create.c b/src/core/surface/secure_channel_create.c index eccee24698..35b60bdbef 100644 --- a/src/core/surface/secure_channel_create.c +++ b/src/core/surface/secure_channel_create.c @@ -185,7 +185,8 @@ static const grpc_subchannel_factory_vtable subchannel_factory_vtable = { - perform handshakes */ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, const char *target, - const grpc_channel_args *args) { + const grpc_channel_args *args, + void *reserved) { grpc_channel *channel; grpc_arg connector_arg; grpc_channel_args *args_copy; @@ -198,6 +199,7 @@ grpc_channel *grpc_secure_channel_create(grpc_credentials *creds, const grpc_channel_filter *filters[MAX_FILTERS]; int n = 0; + GPR_ASSERT(reserved == NULL); if (grpc_find_security_connector_in_args(args) != NULL) { gpr_log(GPR_ERROR, "Cannot set security context in channel args."); return grpc_lame_client_channel_create( diff --git a/src/core/transport/chttp2/stream_lists.c b/src/core/transport/chttp2/stream_lists.c index 38c6052f9c..781db7b0d6 100644 --- a/src/core/transport/chttp2/stream_lists.c +++ b/src/core/transport/chttp2/stream_lists.c @@ -177,8 +177,10 @@ int grpc_chttp2_list_pop_writable_stream( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, GRPC_CHTTP2_LIST_WRITABLE); - *stream_global = &stream->global; - *stream_writing = &stream->writing; + if (r != 0) { + *stream_global = &stream->global; + *stream_writing = &stream->writing; + } return r; } @@ -210,7 +212,9 @@ int grpc_chttp2_list_pop_writing_stream( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream, GRPC_CHTTP2_LIST_WRITING); - *stream_writing = &stream->writing; + if (r != 0) { + *stream_writing = &stream->writing; + } return r; } @@ -230,8 +234,10 @@ int grpc_chttp2_list_pop_written_stream( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_WRITING(transport_writing), &stream, GRPC_CHTTP2_LIST_WRITTEN); - *stream_global = &stream->global; - *stream_writing = &stream->writing; + if (r != 0) { + *stream_global = &stream->global; + *stream_writing = &stream->writing; + } return r; } @@ -251,8 +257,10 @@ int grpc_chttp2_list_pop_parsing_seen_stream( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_PARSING(transport_parsing), &stream, GRPC_CHTTP2_LIST_PARSING_SEEN); - *stream_global = &stream->global; - *stream_parsing = &stream->parsing; + if (r != 0) { + *stream_global = &stream->global; + *stream_parsing = &stream->parsing; + } return r; } @@ -270,7 +278,9 @@ int grpc_chttp2_list_pop_waiting_for_concurrency( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY); - *stream_global = &stream->global; + if (r != 0) { + *stream_global = &stream->global; + } return r; } @@ -288,7 +298,9 @@ int grpc_chttp2_list_pop_closed_waiting_for_parsing( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, GRPC_CHTTP2_LIST_CLOSED_WAITING_FOR_PARSING); - *stream_global = &stream->global; + if (r != 0) { + *stream_global = &stream->global; + } return r; } @@ -306,7 +318,9 @@ int grpc_chttp2_list_pop_cancelled_waiting_for_writing( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, GRPC_CHTTP2_LIST_CANCELLED_WAITING_FOR_WRITING); - *stream_global = &stream->global; + if (r != 0) { + *stream_global = &stream->global; + } return r; } @@ -326,8 +340,10 @@ int grpc_chttp2_list_pop_incoming_window_updated( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, GRPC_CHTTP2_LIST_INCOMING_WINDOW_UPDATED); - *stream_global = &stream->global; - *stream_parsing = &stream->parsing; + if (r != 0) { + *stream_global = &stream->global; + *stream_parsing = &stream->parsing; + } return r; } @@ -353,7 +369,9 @@ int grpc_chttp2_list_pop_read_write_state_changed( grpc_chttp2_stream *stream; int r = stream_list_pop(TRANSPORT_FROM_GLOBAL(transport_global), &stream, GRPC_CHTTP2_LIST_READ_WRITE_STATE_CHANGED); - *stream_global = &stream->global; + if (r != 0) { + *stream_global = &stream->global; + } return r; } diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c index 3fd21a2f5d..61638764a6 100644 --- a/src/core/transport/metadata.c +++ b/src/core/transport/metadata.c @@ -703,7 +703,7 @@ int grpc_mdstr_is_legal_header(grpc_mdstr *s) { int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s) { static const gpr_uint8 legal_header_bits[256 / 8] = { - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; return conforms_to(s, legal_header_bits); diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index 8bf2e4687e..dc8e304664 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -40,7 +40,7 @@ #include <grpc/support/slice.h> #include <grpc++/client_context.h> #include <grpc++/completion_queue.h> -#include <grpc++/credentials.h> +#include <grpc++/security/credentials.h> #include <grpc++/impl/call.h> #include <grpc++/impl/rpc_method.h> #include <grpc++/support/channel_arguments.h> diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index c4d7cf2e51..574656a7e9 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -36,7 +36,7 @@ #include <grpc/grpc.h> #include <grpc/support/alloc.h> #include <grpc/support/string_util.h> -#include <grpc++/credentials.h> +#include <grpc++/security/credentials.h> #include <grpc++/server_context.h> #include <grpc++/support/time.h> diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 8c571cbbaa..d2b2d30126 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -44,8 +44,14 @@ namespace grpc { class ChannelArguments; std::shared_ptr<Channel> CreateChannel( + const grpc::string& target, const std::shared_ptr<Credentials>& creds) { + return CreateCustomChannel(target, creds, ChannelArguments()); +} + +std::shared_ptr<Channel> CreateCustomChannel( const grpc::string& target, const std::shared_ptr<Credentials>& creds, const ChannelArguments& args) { + GrpcLibrary init_lib; // We need to call init in case of a bad creds. ChannelArguments cp_args = args; std::ostringstream user_agent_prefix; user_agent_prefix << "grpc-c++/" << grpc_version_string(); @@ -57,4 +63,5 @@ std::shared_ptr<Channel> CreateChannel( NULL, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials.")); } + } // namespace grpc diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc index e806284988..7a8149e9c7 100644 --- a/src/cpp/client/credentials.cc +++ b/src/cpp/client/credentials.cc @@ -31,7 +31,7 @@ * */ -#include <grpc++/credentials.h> +#include <grpc++/security/credentials.h> namespace grpc { diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc index 4a4d2cb97d..c476f3ce95 100644 --- a/src/cpp/client/insecure_credentials.cc +++ b/src/cpp/client/insecure_credentials.cc @@ -31,7 +31,7 @@ * */ -#include <grpc++/credentials.h> +#include <grpc++/security/credentials.h> #include <grpc/grpc.h> #include <grpc/support/log.h> diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index f368f2590a..2260f6d33e 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -46,7 +46,8 @@ std::shared_ptr<grpc::Channel> SecureCredentials::CreateChannel( args.SetChannelArgs(&channel_args); return CreateChannelInternal( args.GetSslTargetNameOverride(), - grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args)); + grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args, + nullptr)); } bool SecureCredentials::ApplyToCall(grpc_call* call) { @@ -75,31 +76,15 @@ std::shared_ptr<Credentials> SslCredentials( grpc_credentials* c_creds = grpc_ssl_credentials_create( options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), - options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair); + options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr); return WrapCredentials(c_creds); } // Builds credentials for use when running in GCE -std::shared_ptr<Credentials> ComputeEngineCredentials() { +std::shared_ptr<Credentials> GoogleComputeEngineCredentials() { GrpcLibrary init; // To call grpc_init(). - return WrapCredentials(grpc_compute_engine_credentials_create()); -} - -// Builds service account credentials. -std::shared_ptr<Credentials> ServiceAccountCredentials( - const grpc::string& json_key, const grpc::string& scope, - long token_lifetime_seconds) { - GrpcLibrary init; // To call grpc_init(). - if (token_lifetime_seconds <= 0) { - gpr_log(GPR_ERROR, - "Trying to create ServiceAccountCredentials " - "with non-positive lifetime"); - return WrapCredentials(nullptr); - } - gpr_timespec lifetime = - gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN); - return WrapCredentials(grpc_service_account_credentials_create( - json_key.c_str(), scope.c_str(), lifetime)); + return WrapCredentials( + grpc_google_compute_engine_credentials_create(nullptr)); } // Builds JWT credentials. @@ -114,15 +99,15 @@ std::shared_ptr<Credentials> ServiceAccountJWTAccessCredentials( gpr_timespec lifetime = gpr_time_from_seconds(token_lifetime_seconds, GPR_TIMESPAN); return WrapCredentials(grpc_service_account_jwt_access_credentials_create( - json_key.c_str(), lifetime)); + json_key.c_str(), lifetime, nullptr)); } // Builds refresh token credentials. -std::shared_ptr<Credentials> RefreshTokenCredentials( +std::shared_ptr<Credentials> GoogleRefreshTokenCredentials( const grpc::string& json_refresh_token) { GrpcLibrary init; // To call grpc_init(). - return WrapCredentials( - grpc_refresh_token_credentials_create(json_refresh_token.c_str())); + return WrapCredentials(grpc_google_refresh_token_credentials_create( + json_refresh_token.c_str(), nullptr)); } // Builds access token credentials. @@ -130,16 +115,16 @@ std::shared_ptr<Credentials> AccessTokenCredentials( const grpc::string& access_token) { GrpcLibrary init; // To call grpc_init(). return WrapCredentials( - grpc_access_token_credentials_create(access_token.c_str())); + grpc_access_token_credentials_create(access_token.c_str(), nullptr)); } // Builds IAM credentials. -std::shared_ptr<Credentials> IAMCredentials( +std::shared_ptr<Credentials> GoogleIAMCredentials( const grpc::string& authorization_token, const grpc::string& authority_selector) { GrpcLibrary init; // To call grpc_init(). - return WrapCredentials(grpc_iam_credentials_create( - authorization_token.c_str(), authority_selector.c_str())); + return WrapCredentials(grpc_google_iam_credentials_create( + authorization_token.c_str(), authority_selector.c_str(), nullptr)); } // Combines two credentials objects into a composite credentials. @@ -154,7 +139,7 @@ std::shared_ptr<Credentials> CompositeCredentials( SecureCredentials* s2 = creds2->AsSecureCredentials(); if (s1 && s2) { return WrapCredentials(grpc_composite_credentials_create( - s1->GetRawCreds(), s2->GetRawCreds())); + s1->GetRawCreds(), s2->GetRawCreds(), nullptr)); } return nullptr; } diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h index 62d3185477..8deff856c4 100644 --- a/src/cpp/client/secure_credentials.h +++ b/src/cpp/client/secure_credentials.h @@ -37,7 +37,7 @@ #include <grpc/grpc_security.h> #include <grpc++/support/config.h> -#include <grpc++/credentials.h> +#include <grpc++/security/credentials.h> namespace grpc { diff --git a/src/cpp/common/auth_property_iterator.cc b/src/cpp/common/auth_property_iterator.cc index fa6da9d7a8..a47abaf4b8 100644 --- a/src/cpp/common/auth_property_iterator.cc +++ b/src/cpp/common/auth_property_iterator.cc @@ -31,7 +31,7 @@ * */ -#include <grpc++/support/auth_context.h> +#include <grpc++/security/auth_context.h> #include <grpc/grpc_security.h> diff --git a/src/cpp/common/create_auth_context.h b/src/cpp/common/create_auth_context.h index b4962bae4e..4f3da397ba 100644 --- a/src/cpp/common/create_auth_context.h +++ b/src/cpp/common/create_auth_context.h @@ -33,7 +33,7 @@ #include <memory> #include <grpc/grpc.h> -#include <grpc++/support/auth_context.h> +#include <grpc++/security/auth_context.h> namespace grpc { diff --git a/src/cpp/common/insecure_create_auth_context.cc b/src/cpp/common/insecure_create_auth_context.cc index fe80c1a80c..b2e153229a 100644 --- a/src/cpp/common/insecure_create_auth_context.cc +++ b/src/cpp/common/insecure_create_auth_context.cc @@ -33,7 +33,7 @@ #include <memory> #include <grpc/grpc.h> -#include <grpc++/support/auth_context.h> +#include <grpc++/security/auth_context.h> namespace grpc { diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc index b18a8537c9..8615ac8aeb 100644 --- a/src/cpp/common/secure_auth_context.cc +++ b/src/cpp/common/secure_auth_context.cc @@ -37,9 +37,13 @@ namespace grpc { -SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx) : ctx_(ctx) {} +SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx, + bool take_ownership) + : ctx_(ctx), take_ownership_(take_ownership) {} -SecureAuthContext::~SecureAuthContext() { grpc_auth_context_release(ctx_); } +SecureAuthContext::~SecureAuthContext() { + if (take_ownership_) grpc_auth_context_release(ctx_); +} std::vector<grpc::string_ref> SecureAuthContext::GetPeerIdentity() const { if (!ctx_) { @@ -94,4 +98,21 @@ AuthPropertyIterator SecureAuthContext::end() const { return AuthPropertyIterator(); } +void SecureAuthContext::AddProperty(const grpc::string& key, + const grpc::string_ref& value) { + if (!ctx_) return; + grpc_auth_context_add_property(ctx_, key.c_str(), value.data(), value.size()); +} + +bool SecureAuthContext::SetPeerIdentityPropertyName(const grpc::string& name) { + if (!ctx_) return false; + return grpc_auth_context_set_peer_identity_property_name(ctx_, + name.c_str()) != 0; +} + +bool SecureAuthContext::IsPeerAuthenticated() const { + if (!ctx_) return false; + return grpc_auth_context_peer_is_authenticated(ctx_) != 0; +} + } // namespace grpc diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h index 7f622b890b..c9f1dad131 100644 --- a/src/cpp/common/secure_auth_context.h +++ b/src/cpp/common/secure_auth_context.h @@ -34,7 +34,7 @@ #ifndef GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H #define GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H -#include <grpc++/support/auth_context.h> +#include <grpc++/security/auth_context.h> struct grpc_auth_context; @@ -42,10 +42,12 @@ namespace grpc { class SecureAuthContext GRPC_FINAL : public AuthContext { public: - SecureAuthContext(grpc_auth_context* ctx); + SecureAuthContext(grpc_auth_context* ctx, bool take_ownership); ~SecureAuthContext() GRPC_OVERRIDE; + bool IsPeerAuthenticated() const GRPC_OVERRIDE; + std::vector<grpc::string_ref> GetPeerIdentity() const GRPC_OVERRIDE; grpc::string GetPeerIdentityPropertyName() const GRPC_OVERRIDE; @@ -57,8 +59,15 @@ class SecureAuthContext GRPC_FINAL : public AuthContext { AuthPropertyIterator end() const GRPC_OVERRIDE; + void AddProperty(const grpc::string& key, + const grpc::string_ref& value) GRPC_OVERRIDE; + + virtual bool SetPeerIdentityPropertyName(const grpc::string& name) + GRPC_OVERRIDE; + private: grpc_auth_context* ctx_; + bool take_ownership_; }; } // namespace grpc diff --git a/src/cpp/common/secure_create_auth_context.cc b/src/cpp/common/secure_create_auth_context.cc index f13d25a1dd..40bc298b64 100644 --- a/src/cpp/common/secure_create_auth_context.cc +++ b/src/cpp/common/secure_create_auth_context.cc @@ -34,7 +34,7 @@ #include <grpc/grpc.h> #include <grpc/grpc_security.h> -#include <grpc++/support/auth_context.h> +#include <grpc++/security/auth_context.h> #include "src/cpp/common/secure_auth_context.h" namespace grpc { @@ -44,7 +44,7 @@ std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call) { return std::shared_ptr<const AuthContext>(); } return std::shared_ptr<const AuthContext>( - new SecureAuthContext(grpc_call_auth_context(call))); + new SecureAuthContext(grpc_call_auth_context(call), true)); } } // namespace grpc diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc index 800cd36caa..ef3cae5fd7 100644 --- a/src/cpp/server/insecure_server_credentials.cc +++ b/src/cpp/server/insecure_server_credentials.cc @@ -31,9 +31,10 @@ * */ -#include <grpc++/server_credentials.h> +#include <grpc++/security/server_credentials.h> #include <grpc/grpc.h> +#include <grpc/support/log.h> namespace grpc { namespace { @@ -43,6 +44,11 @@ class InsecureServerCredentialsImpl GRPC_FINAL : public ServerCredentials { grpc_server* server) GRPC_OVERRIDE { return grpc_server_add_insecure_http2_port(server, addr.c_str()); } + void SetAuthMetadataProcessor( + const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE { + (void)processor; + GPR_ASSERT(0); // Should not be called on InsecureServerCredentials. + } }; } // namespace diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index f203cf7f49..dfa9229c98 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -31,15 +31,94 @@ * */ +#include <functional> +#include <map> +#include <memory> + + +#include "src/cpp/common/secure_auth_context.h" #include "src/cpp/server/secure_server_credentials.h" +#include <grpc++/security/auth_metadata_processor.h> + namespace grpc { +void AuthMetadataProcessorAyncWrapper::Destroy(void *wrapper) { + auto* w = reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(wrapper); + delete w; +} + +void AuthMetadataProcessorAyncWrapper::Process( + void* wrapper, grpc_auth_context* context, const grpc_metadata* md, + size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data) { + auto* w = reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(wrapper); + if (w->processor_ == nullptr) { + // Early exit. + cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_OK, nullptr); + return; + } + if (w->processor_->IsBlocking()) { + w->thread_pool_->Add( + std::bind(&AuthMetadataProcessorAyncWrapper::InvokeProcessor, w, + context, md, num_md, cb, user_data)); + } else { + // invoke directly. + w->InvokeProcessor(context, md, num_md, cb, user_data); + } +} + +void AuthMetadataProcessorAyncWrapper::InvokeProcessor( + grpc_auth_context* ctx, + const grpc_metadata* md, size_t num_md, + grpc_process_auth_metadata_done_cb cb, void* user_data) { + AuthMetadataProcessor::InputMetadata metadata; + for (size_t i = 0; i < num_md; i++) { + metadata.insert(std::make_pair( + md[i].key, grpc::string_ref(md[i].value, md[i].value_length))); + } + SecureAuthContext context(ctx, false); + AuthMetadataProcessor::OutputMetadata consumed_metadata; + AuthMetadataProcessor::OutputMetadata response_metadata; + + Status status = processor_->Process(metadata, &context, &consumed_metadata, + &response_metadata); + + std::vector<grpc_metadata> consumed_md; + for (auto it = consumed_metadata.begin(); it != consumed_metadata.end(); + ++it) { + consumed_md.push_back({it->first.c_str(), + it->second.data(), + it->second.size(), + 0, + {{nullptr, nullptr, nullptr, nullptr}}}); + } + std::vector<grpc_metadata> response_md; + for (auto it = response_metadata.begin(); it != response_metadata.end(); + ++it) { + response_md.push_back({it->first.c_str(), + it->second.data(), + it->second.size(), + 0, + {{nullptr, nullptr, nullptr, nullptr}}}); + } + cb(user_data, &consumed_md[0], consumed_md.size(), &response_md[0], + response_md.size(), static_cast<grpc_status_code>(status.error_code()), + status.error_message().c_str()); +} + int SecureServerCredentials::AddPortToServer(const grpc::string& addr, grpc_server* server) { return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_); } +void SecureServerCredentials::SetAuthMetadataProcessor( + const std::shared_ptr<AuthMetadataProcessor>& processor) { + auto *wrapper = new AuthMetadataProcessorAyncWrapper(processor); + grpc_server_credentials_set_auth_metadata_processor( + creds_, {AuthMetadataProcessorAyncWrapper::Process, + AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); +} + std::shared_ptr<ServerCredentials> SslServerCredentials( const SslServerCredentialsOptions& options) { std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs; @@ -52,7 +131,7 @@ std::shared_ptr<ServerCredentials> SslServerCredentials( grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create( options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(), &pem_key_cert_pairs[0], pem_key_cert_pairs.size(), - options.force_client_auth); + options.force_client_auth, nullptr); return std::shared_ptr<ServerCredentials>( new SecureServerCredentials(c_creds)); } diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index d3d37b188d..4f003c6b7e 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -34,12 +34,36 @@ #ifndef GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H #define GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H -#include <grpc++/server_credentials.h> +#include <memory> + +#include <grpc++/security/server_credentials.h> #include <grpc/grpc_security.h> +#include "src/cpp/server/thread_pool_interface.h" + namespace grpc { +class AuthMetadataProcessorAyncWrapper GRPC_FINAL { + public: + static void Destroy(void *wrapper); + + static void Process(void* wrapper, grpc_auth_context* context, + const grpc_metadata* md, size_t num_md, + grpc_process_auth_metadata_done_cb cb, void* user_data); + + AuthMetadataProcessorAyncWrapper( + const std::shared_ptr<AuthMetadataProcessor>& processor) + : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {} + + private: + void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md, + size_t num_md, grpc_process_auth_metadata_done_cb cb, + void* user_data); + std::unique_ptr<ThreadPoolInterface> thread_pool_; + std::shared_ptr<AuthMetadataProcessor> processor_; +}; + class SecureServerCredentials GRPC_FINAL : public ServerCredentials { public: explicit SecureServerCredentials(grpc_server_credentials* creds) @@ -51,8 +75,12 @@ class SecureServerCredentials GRPC_FINAL : public ServerCredentials { int AddPortToServer(const grpc::string& addr, grpc_server* server) GRPC_OVERRIDE; + void SetAuthMetadataProcessor( + const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE; + private: - grpc_server_credentials* const creds_; + grpc_server_credentials* creds_; + std::unique_ptr<AuthMetadataProcessorAyncWrapper> processor_; }; } // namespace grpc diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index bb83c7d887..d67205e822 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -43,7 +43,7 @@ #include <grpc++/impl/rpc_service_method.h> #include <grpc++/impl/service_type.h> #include <grpc++/server_context.h> -#include <grpc++/server_credentials.h> +#include <grpc++/security/server_credentials.h> #include <grpc++/support/time.h> #include "src/core/profiling/timers.h" @@ -354,7 +354,7 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) { unknown_method_.reset(new RpcServiceMethod( "unknown", RpcMethod::BIDI_STREAMING, new UnknownMethodHandler)); // Use of emplace_back with just constructor arguments is not accepted - // here by gcc-4.4 because it can't match the anonymous nullptr with a + // here by gcc-4.4 because it can't match the anonymous nullptr with a // proper constructor implicitly. Construct the object and use push_back. sync_methods_->push_back(SyncRequest(unknown_method_.get(), nullptr)); } @@ -384,7 +384,7 @@ void Server::ShutdownInternal(gpr_timespec deadline) { // Spin, eating requests until the completion queue is completely shutdown. // If the deadline expires then cancel anything that's pending and keep // spinning forever until the work is actually drained. - // Since nothing else needs to touch state guarded by mu_, holding it + // Since nothing else needs to touch state guarded by mu_, holding it // through this loop is fine. SyncRequest* request; bool ok; diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc index be3a7425e0..8495916178 100644 --- a/src/cpp/server/server_credentials.cc +++ b/src/cpp/server/server_credentials.cc @@ -31,7 +31,7 @@ * */ -#include <grpc++/server_credentials.h> +#include <grpc++/security/server_credentials.h> namespace grpc { diff --git a/src/csharp/.gitignore b/src/csharp/.gitignore index 48365e32a5..deac55029e 100644 --- a/src/csharp/.gitignore +++ b/src/csharp/.gitignore @@ -4,6 +4,9 @@ StyleCop.Cache test-results packages Grpc.v12.suo +Grpc.sdf + TestResult.xml /TestResults +.vs/ *.nupkg diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj index b571fe9025..f730936062 100644 --- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj +++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj @@ -64,6 +64,7 @@ <Link>Version.cs</Link> </Compile> <Compile Include="ClientBaseTest.cs" /> + <Compile Include="MarshallingErrorsTest.cs" /> <Compile Include="ShutdownTest.cs" /> <Compile Include="Internal\AsyncCallTest.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> diff --git a/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs b/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs new file mode 100644 index 0000000000..83707e0c6d --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs @@ -0,0 +1,176 @@ +#region Copyright notice and license + +// 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. + +#endregion + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Tests +{ + public class MarshallingErrorsTest + { + const string Host = "127.0.0.1"; + + MockServiceHelper helper; + Server server; + Channel channel; + + [SetUp] + public void Init() + { + var marshaller = new Marshaller<string>( + (str) => + { + if (str == "UNSERIALIZABLE_VALUE") + { + // Google.Protobuf throws exception inherited from IOException + throw new IOException("Error serializing the message."); + } + return System.Text.Encoding.UTF8.GetBytes(str); + }, + (payload) => + { + var s = System.Text.Encoding.UTF8.GetString(payload); + if (s == "UNPARSEABLE_VALUE") + { + // Google.Protobuf throws exception inherited from IOException + throw new IOException("Error parsing the message."); + } + return s; + }); + helper = new MockServiceHelper(Host, marshaller); + server = helper.GetServer(); + server.Start(); + channel = helper.GetChannel(); + } + + [TearDown] + public void Cleanup() + { + channel.ShutdownAsync().Wait(); + server.ShutdownAsync().Wait(); + } + + [Test] + public void ResponseParsingError_UnaryResponse() + { + helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => + { + return Task.FromResult("UNPARSEABLE_VALUE"); + }); + + var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "REQUEST")); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + [Test] + public void ResponseParsingError_StreamingResponse() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod<string, string>(async (request, responseStream, context) => + { + await responseStream.WriteAsync("UNPARSEABLE_VALUE"); + await Task.Delay(10000); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "REQUEST"); + var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + [Test] + public void RequestParsingError_UnaryRequest() + { + helper.UnaryHandler = new UnaryServerMethod<string, string>((request, context) => + { + return Task.FromResult("RESPONSE"); + }); + + var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNPARSEABLE_VALUE")); + // Spec doesn't define the behavior. With the current implementation server handler throws exception which results in StatusCode.Unknown. + Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); + } + + [Test] + public async Task RequestParsingError_StreamingRequest() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) => + { + Assert.Throws<IOException>(async () => await requestStream.MoveNext()); + return "RESPONSE"; + }); + + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + await call.RequestStream.WriteAsync("UNPARSEABLE_VALUE"); + + Assert.AreEqual("RESPONSE", await call); + } + + [Test] + public void RequestSerializationError_BlockingUnary() + { + Assert.Throws<IOException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); + } + + [Test] + public void RequestSerializationError_AsyncUnary() + { + Assert.Throws<IOException>(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); + } + + [Test] + public async Task RequestSerializationError_ClientStreaming() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod<string, string>(async (requestStream, context) => + { + CollectionAssert.AreEqual(new [] {"A", "B"}, await requestStream.ToListAsync()); + return "RESPONSE"; + }); + var call = Calls.AsyncClientStreamingCall(helper.CreateClientStreamingCall()); + await call.RequestStream.WriteAsync("A"); + Assert.Throws<IOException>(async () => await call.RequestStream.WriteAsync("UNSERIALIZABLE_VALUE")); + await call.RequestStream.WriteAsync("B"); + await call.RequestStream.CompleteAsync(); + + Assert.AreEqual("RESPONSE", await call); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/MetadataTest.cs b/src/csharp/Grpc.Core.Tests/MetadataTest.cs index c00f945d6a..ddeb7d0926 100644 --- a/src/csharp/Grpc.Core.Tests/MetadataTest.cs +++ b/src/csharp/Grpc.Core.Tests/MetadataTest.cs @@ -75,6 +75,17 @@ namespace Grpc.Core.Tests } [Test] + public void AsciiEntry_KeyValidity() + { + new Metadata.Entry("ABC", "XYZ"); + new Metadata.Entry("0123456789abc", "XYZ"); + new Metadata.Entry("-abc", "XYZ"); + new Metadata.Entry("a_bc_", "XYZ"); + Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc[", "xyz")); + Assert.Throws(typeof(ArgumentException), () => new Metadata.Entry("abc/", "xyz")); + } + + [Test] public void Entry_ConstructionPreconditions() { Assert.Throws(typeof(ArgumentNullException), () => new Metadata.Entry(null, "xyz")); diff --git a/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs b/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs index bb69648d8b..765732c768 100644 --- a/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs +++ b/src/csharp/Grpc.Core.Tests/MockServiceHelper.cs @@ -50,37 +50,14 @@ namespace Grpc.Core.Tests { public const string ServiceName = "tests.Test"; - public static readonly Method<string, string> UnaryMethod = new Method<string, string>( - MethodType.Unary, - ServiceName, - "Unary", - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - - public static readonly Method<string, string> ClientStreamingMethod = new Method<string, string>( - MethodType.ClientStreaming, - ServiceName, - "ClientStreaming", - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - - public static readonly Method<string, string> ServerStreamingMethod = new Method<string, string>( - MethodType.ServerStreaming, - ServiceName, - "ServerStreaming", - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - - public static readonly Method<string, string> DuplexStreamingMethod = new Method<string, string>( - MethodType.DuplexStreaming, - ServiceName, - "DuplexStreaming", - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - readonly string host; readonly ServerServiceDefinition serviceDefinition; + readonly Method<string, string> unaryMethod; + readonly Method<string, string> clientStreamingMethod; + readonly Method<string, string> serverStreamingMethod; + readonly Method<string, string> duplexStreamingMethod; + UnaryServerMethod<string, string> unaryHandler; ClientStreamingServerMethod<string, string> clientStreamingHandler; ServerStreamingServerMethod<string, string> serverStreamingHandler; @@ -89,15 +66,44 @@ namespace Grpc.Core.Tests Server server; Channel channel; - public MockServiceHelper(string host = null) + public MockServiceHelper(string host = null, Marshaller<string> marshaller = null) { this.host = host ?? "localhost"; + marshaller = marshaller ?? Marshallers.StringMarshaller; + + unaryMethod = new Method<string, string>( + MethodType.Unary, + ServiceName, + "Unary", + marshaller, + marshaller); + + clientStreamingMethod = new Method<string, string>( + MethodType.ClientStreaming, + ServiceName, + "ClientStreaming", + marshaller, + marshaller); + + serverStreamingMethod = new Method<string, string>( + MethodType.ServerStreaming, + ServiceName, + "ServerStreaming", + marshaller, + marshaller); + + duplexStreamingMethod = new Method<string, string>( + MethodType.DuplexStreaming, + ServiceName, + "DuplexStreaming", + marshaller, + marshaller); serviceDefinition = ServerServiceDefinition.CreateBuilder(ServiceName) - .AddMethod(UnaryMethod, (request, context) => unaryHandler(request, context)) - .AddMethod(ClientStreamingMethod, (requestStream, context) => clientStreamingHandler(requestStream, context)) - .AddMethod(ServerStreamingMethod, (request, responseStream, context) => serverStreamingHandler(request, responseStream, context)) - .AddMethod(DuplexStreamingMethod, (requestStream, responseStream, context) => duplexStreamingHandler(requestStream, responseStream, context)) + .AddMethod(unaryMethod, (request, context) => unaryHandler(request, context)) + .AddMethod(clientStreamingMethod, (requestStream, context) => clientStreamingHandler(requestStream, context)) + .AddMethod(serverStreamingMethod, (request, responseStream, context) => serverStreamingHandler(request, responseStream, context)) + .AddMethod(duplexStreamingMethod, (requestStream, responseStream, context) => duplexStreamingHandler(requestStream, responseStream, context)) .Build(); var defaultStatus = new Status(StatusCode.Unknown, "Default mock implementation. Please provide your own."); @@ -155,22 +161,22 @@ namespace Grpc.Core.Tests public CallInvocationDetails<string, string> CreateUnaryCall(CallOptions options = default(CallOptions)) { - return new CallInvocationDetails<string, string>(channel, UnaryMethod, options); + return new CallInvocationDetails<string, string>(channel, unaryMethod, options); } public CallInvocationDetails<string, string> CreateClientStreamingCall(CallOptions options = default(CallOptions)) { - return new CallInvocationDetails<string, string>(channel, ClientStreamingMethod, options); + return new CallInvocationDetails<string, string>(channel, clientStreamingMethod, options); } public CallInvocationDetails<string, string> CreateServerStreamingCall(CallOptions options = default(CallOptions)) { - return new CallInvocationDetails<string, string>(channel, ServerStreamingMethod, options); + return new CallInvocationDetails<string, string>(channel, serverStreamingMethod, options); } public CallInvocationDetails<string, string> CreateDuplexStreamingCall(CallOptions options = default(CallOptions)) { - return new CallInvocationDetails<string, string>(channel, DuplexStreamingMethod, options); + return new CallInvocationDetails<string, string>(channel, duplexStreamingMethod, options); } public string Host diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec index fe49efc7ec..06de55c8c3 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.nuspec +++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec @@ -14,15 +14,16 @@ <releaseNotes>Release $version$ of gRPC C#</releaseNotes> <copyright>Copyright 2015, Google Inc.</copyright> <tags>gRPC RPC Protocol HTTP/2</tags> - <dependencies> - <dependency id="Ix-Async" version="1.2.3" /> - <dependency id="grpc.native.csharp_ext" version="$GrpcNativeCsharpExtVersion$" /> + <dependencies> + <dependency id="Ix-Async" version="1.2.3" /> + <dependency id="grpc.native.csharp_ext" version="$GrpcNativeCsharpExtVersion$" /> </dependencies> </metadata> <files> + <file src="..\..\..\etc\roots.pem" target="tools" /> <file src="bin/ReleaseSigned/Grpc.Core.dll" target="lib/net45" /> - <file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" /> - <file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" /> - <file src="**\*.cs" target="src" /> + <file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" /> + <file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" /> + <file src="**\*.cs" target="src" /> </files> </package> diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index be5d611a53..e3b00781c6 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -322,6 +322,11 @@ namespace Grpc.Core.Internal details.Channel.RemoveCallReference(this); } + protected override bool IsClient + { + get { return true; } + } + private void Initialize(CompletionQueueSafeHandle cq) { var call = CreateNativeCall(cq); @@ -376,9 +381,17 @@ namespace Grpc.Core.Internal /// </summary> private void HandleUnaryResponse(bool success, ClientSideStatus receivedStatus, byte[] receivedMessage, Metadata responseHeaders) { + TResponse msg = default(TResponse); + var deserializeException = success ? TryDeserialize(receivedMessage, out msg) : null; + lock (myLock) { finished = true; + + if (deserializeException != null && receivedStatus.Status.StatusCode == StatusCode.OK) + { + receivedStatus = new ClientSideStatus(DeserializeResponseFailureStatus, receivedStatus.Trailers); + } finishedStatus = receivedStatus; ReleaseResourcesIfPossible(); @@ -394,10 +407,6 @@ namespace Grpc.Core.Internal return; } - // TODO: handle deserialization error - TResponse msg; - TryDeserialize(receivedMessage, out msg); - unaryResponseTcs.SetResult(msg); } diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs index 4d20394644..3e2c57c9b5 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs @@ -33,10 +33,12 @@ using System; using System.Diagnostics; +using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; + using Grpc.Core.Internal; using Grpc.Core.Logging; using Grpc.Core.Utils; @@ -50,6 +52,7 @@ namespace Grpc.Core.Internal internal abstract class AsyncCallBase<TWrite, TRead> { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<AsyncCallBase<TWrite, TRead>>(); + protected static readonly Status DeserializeResponseFailureStatus = new Status(StatusCode.Internal, "Failed to deserialize response message."); readonly Func<TWrite, byte[]> serializer; readonly Func<byte[], TRead> deserializer; @@ -100,11 +103,10 @@ namespace Grpc.Core.Internal /// <summary> /// Requests cancelling the call with given status. /// </summary> - public void CancelWithStatus(Status status) + protected void CancelWithStatus(Status status) { lock (myLock) { - Preconditions.CheckState(started); cancelRequested = true; if (!disposed) @@ -177,6 +179,11 @@ namespace Grpc.Core.Internal return false; } + protected abstract bool IsClient + { + get; + } + private void ReleaseResources() { if (call != null) @@ -224,33 +231,31 @@ namespace Grpc.Core.Internal return serializer(msg); } - protected bool TrySerialize(TWrite msg, out byte[] payload) + protected Exception TrySerialize(TWrite msg, out byte[] payload) { try { payload = serializer(msg); - return true; + return null; } catch (Exception e) { - Logger.Error(e, "Exception occured while trying to serialize message"); payload = null; - return false; + return e; } } - protected bool TryDeserialize(byte[] payload, out TRead msg) + protected Exception TryDeserialize(byte[] payload, out TRead msg) { try { msg = deserializer(payload); - return true; + return null; } catch (Exception e) { - Logger.Error(e, "Exception occured while trying to deserialize message."); msg = default(TRead); - return false; + return e; } } @@ -319,6 +324,9 @@ namespace Grpc.Core.Internal /// </summary> protected void HandleReadFinished(bool success, byte[] receivedMessage) { + TRead msg = default(TRead); + var deserializeException = (success && receivedMessage != null) ? TryDeserialize(receivedMessage, out msg) : null; + AsyncCompletionDelegate<TRead> origCompletionDelegate = null; lock (myLock) { @@ -331,23 +339,23 @@ namespace Grpc.Core.Internal readingDone = true; } + if (deserializeException != null && IsClient) + { + readingDone = true; + CancelWithStatus(DeserializeResponseFailureStatus); + } + ReleaseResourcesIfPossible(); } - // TODO: handle the case when error occured... + // TODO: handle the case when success==false - if (receivedMessage != null) - { - // TODO: handle deserialization error - TRead msg; - TryDeserialize(receivedMessage, out msg); - - FireCompletion(origCompletionDelegate, msg, null); - } - else + if (deserializeException != null && !IsClient) { - FireCompletion(origCompletionDelegate, default(TRead), null); + FireCompletion(origCompletionDelegate, default(TRead), new IOException("Failed to deserialize request message.", deserializeException)); + return; } + FireCompletion(origCompletionDelegate, msg, null); } } }
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs index 5c47251030..46ca459349 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCallServer.cs @@ -169,6 +169,11 @@ namespace Grpc.Core.Internal } } + protected override bool IsClient + { + get { return false; } + } + protected override void CheckReadingAllowed() { base.CheckReadingAllowed(); diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs index f38cb0863f..3493d2d38f 100644 --- a/src/csharp/Grpc.Core/Marshaller.cs +++ b/src/csharp/Grpc.Core/Marshaller.cs @@ -39,7 +39,7 @@ namespace Grpc.Core /// <summary> /// Encapsulates the logic for serializing and deserializing messages. /// </summary> - public struct Marshaller<T> + public class Marshaller<T> { readonly Func<T, byte[]> serializer; readonly Func<byte[], T> deserializer; diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs index 99fe0b5478..21bdf4f114 100644 --- a/src/csharp/Grpc.Core/Metadata.cs +++ b/src/csharp/Grpc.Core/Metadata.cs @@ -33,8 +33,10 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; +using System.Globalization; using System.Runtime.InteropServices; using System.Text; +using System.Text.RegularExpressions; using Grpc.Core.Utils; @@ -188,6 +190,7 @@ namespace Grpc.Core public struct Entry { private static readonly Encoding Encoding = Encoding.ASCII; + private static readonly Regex ValidKeyRegex = new Regex("^[a-z0-9_-]+$"); readonly string key; readonly string value; @@ -320,7 +323,10 @@ namespace Grpc.Core private static string NormalizeKey(string key) { - return Preconditions.CheckNotNull(key, "key").ToLower(); + var normalized = Preconditions.CheckNotNull(key, "key").ToLower(CultureInfo.InvariantCulture); + Preconditions.CheckArgument(ValidKeyRegex.IsMatch(normalized), + "Metadata entry key not valid. Keys can only contain lowercase alphanumeric characters, underscores and hyphens."); + return normalized; } } } diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index b6dbd3b49c..eda821bc31 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -39,8 +39,8 @@ namespace Grpc.Core public static class VersionInfo { /// <summary> - /// Current version of gRPC + /// Current version of gRPC C# /// </summary> - public const string CurrentVersion = "0.6.1"; + public const string CurrentVersion = "0.7.0"; } } diff --git a/src/csharp/Grpc.Examples.MathClient/MathClient.cs b/src/csharp/Grpc.Examples.MathClient/MathClient.cs index abd95cb905..01e4a80bab 100644 --- a/src/csharp/Grpc.Examples.MathClient/MathClient.cs +++ b/src/csharp/Grpc.Examples.MathClient/MathClient.cs @@ -33,7 +33,7 @@ using System.Runtime.InteropServices; using System.Threading; using Grpc.Core; -namespace math +namespace Math { class MathClient { diff --git a/src/csharp/Grpc.Examples.MathServer/MathServer.cs b/src/csharp/Grpc.Examples.MathServer/MathServer.cs index 26bef646ec..6e974a0871 100644 --- a/src/csharp/Grpc.Examples.MathServer/MathServer.cs +++ b/src/csharp/Grpc.Examples.MathServer/MathServer.cs @@ -34,7 +34,7 @@ using System.Runtime.InteropServices; using System.Threading; using Grpc.Core; -namespace math +namespace Math { class MainClass { diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj index 9a8f780b24..c4c1ee6d00 100644 --- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj +++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj @@ -37,13 +37,14 @@ <AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile> </PropertyGroup> <ItemGroup> + <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath> + </Reference> <Reference Include="nunit.framework"> <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath> </Reference> <Reference Include="System" /> - <Reference Include="Google.ProtocolBuffers"> - <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath> - </Reference> <Reference Include="System.Interactive.Async, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath> diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs index 36c1c947bd..e2975b5da9 100644 --- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs +++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs @@ -40,7 +40,7 @@ using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; -namespace math.Tests +namespace Math.Tests { /// <summary> /// Math client talks to local math server. @@ -75,7 +75,7 @@ namespace math.Tests [Test] public void Div1() { - DivReply response = client.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build()); + DivReply response = client.Div(new DivArgs { Dividend = 10, Divisor = 3 }); Assert.AreEqual(3, response.Quotient); Assert.AreEqual(1, response.Remainder); } @@ -83,7 +83,7 @@ namespace math.Tests [Test] public void Div2() { - DivReply response = client.Div(new DivArgs.Builder { Dividend = 0, Divisor = 1 }.Build()); + DivReply response = client.Div(new DivArgs { Dividend = 0, Divisor = 1 }); Assert.AreEqual(0, response.Quotient); Assert.AreEqual(0, response.Remainder); } @@ -91,14 +91,14 @@ namespace math.Tests [Test] public void DivByZero() { - var ex = Assert.Throws<RpcException>(() => client.Div(new DivArgs.Builder { Dividend = 0, Divisor = 0 }.Build())); + var ex = Assert.Throws<RpcException>(() => client.Div(new DivArgs { Dividend = 0, Divisor = 0 })); Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode); } [Test] public async Task DivAsync() { - DivReply response = await client.DivAsync(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build()); + DivReply response = await client.DivAsync(new DivArgs { Dividend = 10, Divisor = 3 }); Assert.AreEqual(3, response.Quotient); Assert.AreEqual(1, response.Remainder); } @@ -106,7 +106,7 @@ namespace math.Tests [Test] public async Task Fib() { - using (var call = client.Fib(new FibArgs.Builder { Limit = 6 }.Build())) + using (var call = client.Fib(new FibArgs { Limit = 6 })) { var responses = await call.ResponseStream.ToListAsync(); CollectionAssert.AreEqual(new List<long> { 1, 1, 2, 3, 5, 8 }, @@ -119,8 +119,7 @@ namespace math.Tests { var cts = new CancellationTokenSource(); - using (var call = client.Fib(new FibArgs.Builder { Limit = 0 }.Build(), - cancellationToken: cts.Token)) + using (var call = client.Fib(new FibArgs { Limit = 0 }, cancellationToken: cts.Token)) { List<long> responses = new List<long>(); @@ -147,7 +146,7 @@ namespace math.Tests [Test] public async Task FibWithDeadline() { - using (var call = client.Fib(new FibArgs.Builder { Limit = 0 }.Build(), + using (var call = client.Fib(new FibArgs { Limit = 0 }, deadline: DateTime.UtcNow.AddMilliseconds(500))) { var ex = Assert.Throws<RpcException>(async () => await call.ResponseStream.ToListAsync()); @@ -163,8 +162,7 @@ namespace math.Tests { using (var call = client.Sum()) { - var numbers = new List<long> { 10, 20, 30 }.ConvertAll( - n => Num.CreateBuilder().SetNum_(n).Build()); + var numbers = new List<long> { 10, 20, 30 }.ConvertAll(n => new Num { Num_ = n }); await call.RequestStream.WriteAllAsync(numbers); var result = await call.ResponseAsync; @@ -177,9 +175,9 @@ namespace math.Tests { var divArgsList = new List<DivArgs> { - new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(), - new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(), - new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build() + new DivArgs { Dividend = 10, Divisor = 3 }, + new DivArgs { Dividend = 100, Divisor = 21 }, + new DivArgs { Dividend = 7, Divisor = 2 } }; using (var call = client.DivMany()) diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config index cc6e9af40f..7266fa1763 100644 --- a/src/csharp/Grpc.Examples.Tests/packages.config +++ b/src/csharp/Grpc.Examples.Tests/packages.config @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
+ <package id="Google.Protobuf" version="3.0.0-alpha4" targetFramework="net45" />
<package id="Ix-Async" version="1.2.3" targetFramework="net45" />
<package id="NUnit" version="2.6.4" targetFramework="net45" />
</packages>
\ No newline at end of file diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj index c1aa40500e..55462e02fd 100644 --- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj +++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj @@ -37,11 +37,12 @@ <AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile> </PropertyGroup> <ItemGroup> + <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath> + </Reference> <Reference Include="System" /> <Reference Include="System.Data.Linq" /> - <Reference Include="Google.ProtocolBuffers"> - <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath> - </Reference> <Reference Include="System.Interactive.Async"> <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath> </Reference> diff --git a/src/csharp/Grpc.Examples/Math.cs b/src/csharp/Grpc.Examples/Math.cs index 75b1e9dbc2..d0e1ee8aae 100644 --- a/src/csharp/Grpc.Examples/Math.cs +++ b/src/csharp/Grpc.Examples/Math.cs @@ -1,80 +1,46 @@ -// Generated by ProtoGen, Version=2.4.1.521, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48. DO NOT EDIT! +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: math.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code -using pb = global::Google.ProtocolBuffers; -using pbc = global::Google.ProtocolBuffers.Collections; -using pbd = global::Google.ProtocolBuffers.Descriptors; +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace math { +namespace Math { namespace Proto { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Math { - #region Extension registration - public static void RegisterAllExtensions(pb::ExtensionRegistry registry) { - } - #endregion - #region Static variables - internal static pbd::MessageDescriptor internal__static_math_DivArgs__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::math.DivArgs, global::math.DivArgs.Builder> internal__static_math_DivArgs__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_math_DivReply__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::math.DivReply, global::math.DivReply.Builder> internal__static_math_DivReply__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_math_FibArgs__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::math.FibArgs, global::math.FibArgs.Builder> internal__static_math_FibArgs__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_math_Num__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::math.Num, global::math.Num.Builder> internal__static_math_Num__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_math_FibReply__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::math.FibReply, global::math.FibReply.Builder> internal__static_math_FibReply__FieldAccessorTable; - #endregion #region Descriptor - public static pbd::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor { get { return descriptor; } } - private static pbd::FileDescriptor descriptor; + private static pbr::FileDescriptor descriptor; static Math() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "CgptYXRoLnByb3RvEgRtYXRoIiwKB0RpdkFyZ3MSEAoIZGl2aWRlbmQYASAB", - "KAMSDwoHZGl2aXNvchgCIAEoAyIvCghEaXZSZXBseRIQCghxdW90aWVudBgB", - "IAEoAxIRCglyZW1haW5kZXIYAiABKAMiGAoHRmliQXJncxINCgVsaW1pdBgB", - "IAEoAyISCgNOdW0SCwoDbnVtGAEgASgDIhkKCEZpYlJlcGx5Eg0KBWNvdW50", - "GAEgASgDMqQBCgRNYXRoEiYKA0RpdhINLm1hdGguRGl2QXJncxoOLm1hdGgu", - "RGl2UmVwbHkiABIuCgdEaXZNYW55Eg0ubWF0aC5EaXZBcmdzGg4ubWF0aC5E", - "aXZSZXBseSIAKAEwARIjCgNGaWISDS5tYXRoLkZpYkFyZ3MaCS5tYXRoLk51", - "bSIAMAESHwoDU3VtEgkubWF0aC5OdW0aCS5tYXRoLk51bSIAKAE=")); - pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { - descriptor = root; - internal__static_math_DivArgs__Descriptor = Descriptor.MessageTypes[0]; - internal__static_math_DivArgs__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::math.DivArgs, global::math.DivArgs.Builder>(internal__static_math_DivArgs__Descriptor, - new string[] { "Dividend", "Divisor", }); - internal__static_math_DivReply__Descriptor = Descriptor.MessageTypes[1]; - internal__static_math_DivReply__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::math.DivReply, global::math.DivReply.Builder>(internal__static_math_DivReply__Descriptor, - new string[] { "Quotient", "Remainder", }); - internal__static_math_FibArgs__Descriptor = Descriptor.MessageTypes[2]; - internal__static_math_FibArgs__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::math.FibArgs, global::math.FibArgs.Builder>(internal__static_math_FibArgs__Descriptor, - new string[] { "Limit", }); - internal__static_math_Num__Descriptor = Descriptor.MessageTypes[3]; - internal__static_math_Num__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::math.Num, global::math.Num.Builder>(internal__static_math_Num__Descriptor, - new string[] { "Num_", }); - internal__static_math_FibReply__Descriptor = Descriptor.MessageTypes[4]; - internal__static_math_FibReply__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::math.FibReply, global::math.FibReply.Builder>(internal__static_math_FibReply__Descriptor, - new string[] { "Count", }); - pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance(); - RegisterAllExtensions(registry); - return registry; - }; - pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, - new pbd::FileDescriptor[] { - }, assigner); + "CgptYXRoLnByb3RvEgRtYXRoIiwKB0RpdkFyZ3MSEAoIZGl2aWRlbmQYASAB", + "KAMSDwoHZGl2aXNvchgCIAEoAyIvCghEaXZSZXBseRIQCghxdW90aWVudBgB", + "IAEoAxIRCglyZW1haW5kZXIYAiABKAMiGAoHRmliQXJncxINCgVsaW1pdBgB", + "IAEoAyISCgNOdW0SCwoDbnVtGAEgASgDIhkKCEZpYlJlcGx5Eg0KBWNvdW50", + "GAEgASgDMqQBCgRNYXRoEiYKA0RpdhINLm1hdGguRGl2QXJncxoOLm1hdGgu", + "RGl2UmVwbHkiABIuCgdEaXZNYW55Eg0ubWF0aC5EaXZBcmdzGg4ubWF0aC5E", + "aXZSZXBseSIAKAEwARIjCgNGaWISDS5tYXRoLkZpYkFyZ3MaCS5tYXRoLk51", + "bSIAMAESHwoDU3VtEgkubWF0aC5OdW0aCS5tYXRoLk51bSIAKAFiBnByb3Rv", + "Mw==")); + descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { + new pbr::GeneratedCodeInfo(typeof(global::Math.DivArgs), new[]{ "Dividend", "Divisor" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Math.DivReply), new[]{ "Quotient", "Remainder" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Math.FibArgs), new[]{ "Limit" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Math.Num), new[]{ "Num_" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Math.FibReply), new[]{ "Count" }, null, null, null) + })); } #endregion @@ -82,1448 +48,567 @@ namespace math { } #region Messages [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class DivArgs : pb::GeneratedMessage<DivArgs, DivArgs.Builder> { - private DivArgs() { } - private static readonly DivArgs defaultInstance = new DivArgs().MakeReadOnly(); - private static readonly string[] _divArgsFieldNames = new string[] { "dividend", "divisor" }; - private static readonly uint[] _divArgsFieldTags = new uint[] { 8, 16 }; - public static DivArgs DefaultInstance { - get { return defaultInstance; } + public sealed partial class DivArgs : pb::IMessage<DivArgs> { + private static readonly pb::MessageParser<DivArgs> _parser = new pb::MessageParser<DivArgs>(() => new DivArgs()); + public static pb::MessageParser<DivArgs> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.Proto.Math.Descriptor.MessageTypes[0]; } } - public override DivArgs DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override DivArgs ThisMessage { - get { return this; } + public DivArgs() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::math.Proto.Math.internal__static_math_DivArgs__Descriptor; } + partial void OnConstruction(); + + public DivArgs(DivArgs other) : this() { + dividend_ = other.dividend_; + divisor_ = other.divisor_; } - protected override pb::FieldAccess.FieldAccessorTable<DivArgs, DivArgs.Builder> InternalFieldAccessors { - get { return global::math.Proto.Math.internal__static_math_DivArgs__FieldAccessorTable; } + public DivArgs Clone() { + return new DivArgs(this); } public const int DividendFieldNumber = 1; - private bool hasDividend; private long dividend_; - public bool HasDividend { - get { return hasDividend; } - } public long Dividend { get { return dividend_; } + set { + dividend_ = value; + } } public const int DivisorFieldNumber = 2; - private bool hasDivisor; private long divisor_; - public bool HasDivisor { - get { return hasDivisor; } - } public long Divisor { get { return divisor_; } + set { + divisor_ = value; + } } - public override bool IsInitialized { - get { - return true; - } + public override bool Equals(object other) { + return Equals(other as DivArgs); } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _divArgsFieldNames; - if (hasDividend) { - output.WriteInt64(1, field_names[0], Dividend); + public bool Equals(DivArgs other) { + if (ReferenceEquals(other, null)) { + return false; } - if (hasDivisor) { - output.WriteInt64(2, field_names[1], Divisor); + if (ReferenceEquals(other, this)) { + return true; } - UnknownFields.WriteTo(output); + if (Dividend != other.Dividend) return false; + if (Divisor != other.Divisor) return false; + return true; } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasDividend) { - size += pb::CodedOutputStream.ComputeInt64Size(1, Dividend); - } - if (hasDivisor) { - size += pb::CodedOutputStream.ComputeInt64Size(2, Divisor); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; - } + public override int GetHashCode() { + int hash = 1; + if (Dividend != 0L) hash ^= Dividend.GetHashCode(); + if (Divisor != 0L) hash ^= Divisor.GetHashCode(); + return hash; } - public static DivArgs ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static DivArgs ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static DivArgs ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static DivArgs ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static DivArgs ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static DivArgs ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - public static DivArgs ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static DivArgs ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static DivArgs ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static DivArgs ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private DivArgs MakeReadOnly() { - return this; - } - - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(DivArgs prototype) { - return new Builder(prototype); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<DivArgs, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(DivArgs cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private DivArgs result; - - private DivArgs PrepareBuilder() { - if (resultIsReadOnly) { - DivArgs original = result; - result = new DivArgs(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - public override bool IsInitialized { - get { return result.IsInitialized; } + public void WriteTo(pb::CodedOutputStream output) { + if (Dividend != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Dividend); } - - protected override DivArgs MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::math.DivArgs.Descriptor; } + if (Divisor != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Divisor); } + } - public override DivArgs DefaultInstanceForType { - get { return global::math.DivArgs.DefaultInstance; } + public int CalculateSize() { + int size = 0; + if (Dividend != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Dividend); } - - public override DivArgs BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + if (Divisor != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Divisor); } + return size; + } - public override Builder MergeFrom(pb::IMessage other) { - if (other is DivArgs) { - return MergeFrom((DivArgs) other); - } else { - base.MergeFrom(other); - return this; - } + public void MergeFrom(DivArgs other) { + if (other == null) { + return; } - - public override Builder MergeFrom(DivArgs other) { - if (other == global::math.DivArgs.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasDividend) { - Dividend = other.Dividend; - } - if (other.HasDivisor) { - Divisor = other.Divisor; - } - this.MergeUnknownFields(other.UnknownFields); - return this; + if (other.Dividend != 0L) { + Dividend = other.Dividend; } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); + if (other.Divisor != 0L) { + Divisor = other.Divisor; } + } - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_divArgsFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _divArgsFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Dividend = input.ReadInt64(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - result.hasDividend = input.ReadInt64(ref result.dividend_); - break; - } - case 16: { - result.hasDivisor = input.ReadInt64(ref result.divisor_); - break; - } + case 16: { + Divisor = input.ReadInt64(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasDividend { - get { return result.hasDividend; } - } - public long Dividend { - get { return result.Dividend; } - set { SetDividend(value); } } - public Builder SetDividend(long value) { - PrepareBuilder(); - result.hasDividend = true; - result.dividend_ = value; - return this; - } - public Builder ClearDividend() { - PrepareBuilder(); - result.hasDividend = false; - result.dividend_ = 0L; - return this; - } - - public bool HasDivisor { - get { return result.hasDivisor; } - } - public long Divisor { - get { return result.Divisor; } - set { SetDivisor(value); } - } - public Builder SetDivisor(long value) { - PrepareBuilder(); - result.hasDivisor = true; - result.divisor_ = value; - return this; - } - public Builder ClearDivisor() { - PrepareBuilder(); - result.hasDivisor = false; - result.divisor_ = 0L; - return this; - } - } - static DivArgs() { - object.ReferenceEquals(global::math.Proto.Math.Descriptor, null); } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class DivReply : pb::GeneratedMessage<DivReply, DivReply.Builder> { - private DivReply() { } - private static readonly DivReply defaultInstance = new DivReply().MakeReadOnly(); - private static readonly string[] _divReplyFieldNames = new string[] { "quotient", "remainder" }; - private static readonly uint[] _divReplyFieldTags = new uint[] { 8, 16 }; - public static DivReply DefaultInstance { - get { return defaultInstance; } + public sealed partial class DivReply : pb::IMessage<DivReply> { + private static readonly pb::MessageParser<DivReply> _parser = new pb::MessageParser<DivReply>(() => new DivReply()); + public static pb::MessageParser<DivReply> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.Proto.Math.Descriptor.MessageTypes[1]; } } - public override DivReply DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override DivReply ThisMessage { - get { return this; } + public DivReply() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::math.Proto.Math.internal__static_math_DivReply__Descriptor; } + partial void OnConstruction(); + + public DivReply(DivReply other) : this() { + quotient_ = other.quotient_; + remainder_ = other.remainder_; } - protected override pb::FieldAccess.FieldAccessorTable<DivReply, DivReply.Builder> InternalFieldAccessors { - get { return global::math.Proto.Math.internal__static_math_DivReply__FieldAccessorTable; } + public DivReply Clone() { + return new DivReply(this); } public const int QuotientFieldNumber = 1; - private bool hasQuotient; private long quotient_; - public bool HasQuotient { - get { return hasQuotient; } - } public long Quotient { get { return quotient_; } + set { + quotient_ = value; + } } public const int RemainderFieldNumber = 2; - private bool hasRemainder; private long remainder_; - public bool HasRemainder { - get { return hasRemainder; } - } public long Remainder { get { return remainder_; } - } - - public override bool IsInitialized { - get { - return true; + set { + remainder_ = value; } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _divReplyFieldNames; - if (hasQuotient) { - output.WriteInt64(1, field_names[0], Quotient); - } - if (hasRemainder) { - output.WriteInt64(2, field_names[1], Remainder); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as DivReply); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasQuotient) { - size += pb::CodedOutputStream.ComputeInt64Size(1, Quotient); - } - if (hasRemainder) { - size += pb::CodedOutputStream.ComputeInt64Size(2, Remainder); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(DivReply other) { + if (ReferenceEquals(other, null)) { + return false; } + if (ReferenceEquals(other, this)) { + return true; + } + if (Quotient != other.Quotient) return false; + if (Remainder != other.Remainder) return false; + return true; } - public static DivReply ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static DivReply ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static DivReply ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static DivReply ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static DivReply ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static DivReply ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static DivReply ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static DivReply ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static DivReply ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static DivReply ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private DivReply MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (Quotient != 0L) hash ^= Quotient.GetHashCode(); + if (Remainder != 0L) hash ^= Remainder.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(DivReply prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<DivReply, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(DivReply cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private DivReply result; - - private DivReply PrepareBuilder() { - if (resultIsReadOnly) { - DivReply original = result; - result = new DivReply(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override DivReply MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } + public void WriteTo(pb::CodedOutputStream output) { + if (Quotient != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Quotient); } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::math.DivReply.Descriptor; } + if (Remainder != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Remainder); } + } - public override DivReply DefaultInstanceForType { - get { return global::math.DivReply.DefaultInstance; } + public int CalculateSize() { + int size = 0; + if (Quotient != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Quotient); } - - public override DivReply BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + if (Remainder != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Remainder); } + return size; + } - public override Builder MergeFrom(pb::IMessage other) { - if (other is DivReply) { - return MergeFrom((DivReply) other); - } else { - base.MergeFrom(other); - return this; - } + public void MergeFrom(DivReply other) { + if (other == null) { + return; } - - public override Builder MergeFrom(DivReply other) { - if (other == global::math.DivReply.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasQuotient) { - Quotient = other.Quotient; - } - if (other.HasRemainder) { - Remainder = other.Remainder; - } - this.MergeUnknownFields(other.UnknownFields); - return this; + if (other.Quotient != 0L) { + Quotient = other.Quotient; } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); + if (other.Remainder != 0L) { + Remainder = other.Remainder; } + } - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_divReplyFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _divReplyFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Quotient = input.ReadInt64(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - result.hasQuotient = input.ReadInt64(ref result.quotient_); - break; - } - case 16: { - result.hasRemainder = input.ReadInt64(ref result.remainder_); - break; - } + case 16: { + Remainder = input.ReadInt64(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasQuotient { - get { return result.hasQuotient; } - } - public long Quotient { - get { return result.Quotient; } - set { SetQuotient(value); } - } - public Builder SetQuotient(long value) { - PrepareBuilder(); - result.hasQuotient = true; - result.quotient_ = value; - return this; - } - public Builder ClearQuotient() { - PrepareBuilder(); - result.hasQuotient = false; - result.quotient_ = 0L; - return this; - } - - public bool HasRemainder { - get { return result.hasRemainder; } - } - public long Remainder { - get { return result.Remainder; } - set { SetRemainder(value); } - } - public Builder SetRemainder(long value) { - PrepareBuilder(); - result.hasRemainder = true; - result.remainder_ = value; - return this; } - public Builder ClearRemainder() { - PrepareBuilder(); - result.hasRemainder = false; - result.remainder_ = 0L; - return this; - } - } - static DivReply() { - object.ReferenceEquals(global::math.Proto.Math.Descriptor, null); } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class FibArgs : pb::GeneratedMessage<FibArgs, FibArgs.Builder> { - private FibArgs() { } - private static readonly FibArgs defaultInstance = new FibArgs().MakeReadOnly(); - private static readonly string[] _fibArgsFieldNames = new string[] { "limit" }; - private static readonly uint[] _fibArgsFieldTags = new uint[] { 8 }; - public static FibArgs DefaultInstance { - get { return defaultInstance; } + public sealed partial class FibArgs : pb::IMessage<FibArgs> { + private static readonly pb::MessageParser<FibArgs> _parser = new pb::MessageParser<FibArgs>(() => new FibArgs()); + public static pb::MessageParser<FibArgs> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.Proto.Math.Descriptor.MessageTypes[2]; } } - public override FibArgs DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override FibArgs ThisMessage { - get { return this; } + public FibArgs() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::math.Proto.Math.internal__static_math_FibArgs__Descriptor; } + partial void OnConstruction(); + + public FibArgs(FibArgs other) : this() { + limit_ = other.limit_; } - protected override pb::FieldAccess.FieldAccessorTable<FibArgs, FibArgs.Builder> InternalFieldAccessors { - get { return global::math.Proto.Math.internal__static_math_FibArgs__FieldAccessorTable; } + public FibArgs Clone() { + return new FibArgs(this); } public const int LimitFieldNumber = 1; - private bool hasLimit; private long limit_; - public bool HasLimit { - get { return hasLimit; } - } public long Limit { get { return limit_; } - } - - public override bool IsInitialized { - get { - return true; + set { + limit_ = value; } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _fibArgsFieldNames; - if (hasLimit) { - output.WriteInt64(1, field_names[0], Limit); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as FibArgs); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasLimit) { - size += pb::CodedOutputStream.ComputeInt64Size(1, Limit); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(FibArgs other) { + if (ReferenceEquals(other, null)) { + return false; } + if (ReferenceEquals(other, this)) { + return true; + } + if (Limit != other.Limit) return false; + return true; } - public static FibArgs ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static FibArgs ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static FibArgs ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static FibArgs ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static FibArgs ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static FibArgs ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static FibArgs ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static FibArgs ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static FibArgs ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static FibArgs ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private FibArgs MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (Limit != 0L) hash ^= Limit.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(FibArgs prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<FibArgs, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(FibArgs cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private FibArgs result; - - private FibArgs PrepareBuilder() { - if (resultIsReadOnly) { - FibArgs original = result; - result = new FibArgs(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override FibArgs MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::math.FibArgs.Descriptor; } - } - - public override FibArgs DefaultInstanceForType { - get { return global::math.FibArgs.DefaultInstance; } + public void WriteTo(pb::CodedOutputStream output) { + if (Limit != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Limit); } + } - public override FibArgs BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); - } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is FibArgs) { - return MergeFrom((FibArgs) other); - } else { - base.MergeFrom(other); - return this; - } + public int CalculateSize() { + int size = 0; + if (Limit != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Limit); } + return size; + } - public override Builder MergeFrom(FibArgs other) { - if (other == global::math.FibArgs.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasLimit) { - Limit = other.Limit; - } - this.MergeUnknownFields(other.UnknownFields); - return this; + public void MergeFrom(FibArgs other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); + if (other.Limit != 0L) { + Limit = other.Limit; } + } - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_fibArgsFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _fibArgsFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Limit = input.ReadInt64(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - result.hasLimit = input.ReadInt64(ref result.limit_); - break; - } - } - } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); } - return this; - } - - - public bool HasLimit { - get { return result.hasLimit; } - } - public long Limit { - get { return result.Limit; } - set { SetLimit(value); } - } - public Builder SetLimit(long value) { - PrepareBuilder(); - result.hasLimit = true; - result.limit_ = value; - return this; } - public Builder ClearLimit() { - PrepareBuilder(); - result.hasLimit = false; - result.limit_ = 0L; - return this; - } - } - static FibArgs() { - object.ReferenceEquals(global::math.Proto.Math.Descriptor, null); } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Num : pb::GeneratedMessage<Num, Num.Builder> { - private Num() { } - private static readonly Num defaultInstance = new Num().MakeReadOnly(); - private static readonly string[] _numFieldNames = new string[] { "num" }; - private static readonly uint[] _numFieldTags = new uint[] { 8 }; - public static Num DefaultInstance { - get { return defaultInstance; } + public sealed partial class Num : pb::IMessage<Num> { + private static readonly pb::MessageParser<Num> _parser = new pb::MessageParser<Num>(() => new Num()); + public static pb::MessageParser<Num> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.Proto.Math.Descriptor.MessageTypes[3]; } } - public override Num DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override Num ThisMessage { - get { return this; } + public Num() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::math.Proto.Math.internal__static_math_Num__Descriptor; } + partial void OnConstruction(); + + public Num(Num other) : this() { + num_ = other.num_; } - protected override pb::FieldAccess.FieldAccessorTable<Num, Num.Builder> InternalFieldAccessors { - get { return global::math.Proto.Math.internal__static_math_Num__FieldAccessorTable; } + public Num Clone() { + return new Num(this); } public const int Num_FieldNumber = 1; - private bool hasNum_; private long num_; - public bool HasNum_ { - get { return hasNum_; } - } public long Num_ { get { return num_; } - } - - public override bool IsInitialized { - get { - return true; + set { + num_ = value; } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _numFieldNames; - if (hasNum_) { - output.WriteInt64(1, field_names[0], Num_); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as Num); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasNum_) { - size += pb::CodedOutputStream.ComputeInt64Size(1, Num_); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(Num other) { + if (ReferenceEquals(other, null)) { + return false; } + if (ReferenceEquals(other, this)) { + return true; + } + if (Num_ != other.Num_) return false; + return true; } - public static Num ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static Num ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static Num ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static Num ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static Num ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static Num ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static Num ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static Num ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static Num ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static Num ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private Num MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (Num_ != 0L) hash ^= Num_.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(Num prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<Num, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(Num cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private Num result; - - private Num PrepareBuilder() { - if (resultIsReadOnly) { - Num original = result; - result = new Num(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override Num MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::math.Num.Descriptor; } - } - - public override Num DefaultInstanceForType { - get { return global::math.Num.DefaultInstance; } - } - - public override Num BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public void WriteTo(pb::CodedOutputStream output) { + if (Num_ != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Num_); } + } - public override Builder MergeFrom(pb::IMessage other) { - if (other is Num) { - return MergeFrom((Num) other); - } else { - base.MergeFrom(other); - return this; - } + public int CalculateSize() { + int size = 0; + if (Num_ != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Num_); } + return size; + } - public override Builder MergeFrom(Num other) { - if (other == global::math.Num.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasNum_) { - Num_ = other.Num_; - } - this.MergeUnknownFields(other.UnknownFields); - return this; + public void MergeFrom(Num other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); + if (other.Num_ != 0L) { + Num_ = other.Num_; } + } - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_numFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _numFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } - } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - result.hasNum_ = input.ReadInt64(ref result.num_); - break; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Num_ = input.ReadInt64(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasNum_ { - get { return result.hasNum_; } - } - public long Num_ { - get { return result.Num_; } - set { SetNum_(value); } - } - public Builder SetNum_(long value) { - PrepareBuilder(); - result.hasNum_ = true; - result.num_ = value; - return this; - } - public Builder ClearNum_() { - PrepareBuilder(); - result.hasNum_ = false; - result.num_ = 0L; - return this; } } - static Num() { - object.ReferenceEquals(global::math.Proto.Math.Descriptor, null); - } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class FibReply : pb::GeneratedMessage<FibReply, FibReply.Builder> { - private FibReply() { } - private static readonly FibReply defaultInstance = new FibReply().MakeReadOnly(); - private static readonly string[] _fibReplyFieldNames = new string[] { "count" }; - private static readonly uint[] _fibReplyFieldTags = new uint[] { 8 }; - public static FibReply DefaultInstance { - get { return defaultInstance; } + public sealed partial class FibReply : pb::IMessage<FibReply> { + private static readonly pb::MessageParser<FibReply> _parser = new pb::MessageParser<FibReply>(() => new FibReply()); + public static pb::MessageParser<FibReply> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Math.Proto.Math.Descriptor.MessageTypes[4]; } } - public override FibReply DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override FibReply ThisMessage { - get { return this; } + public FibReply() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::math.Proto.Math.internal__static_math_FibReply__Descriptor; } + partial void OnConstruction(); + + public FibReply(FibReply other) : this() { + count_ = other.count_; } - protected override pb::FieldAccess.FieldAccessorTable<FibReply, FibReply.Builder> InternalFieldAccessors { - get { return global::math.Proto.Math.internal__static_math_FibReply__FieldAccessorTable; } + public FibReply Clone() { + return new FibReply(this); } public const int CountFieldNumber = 1; - private bool hasCount; private long count_; - public bool HasCount { - get { return hasCount; } - } public long Count { get { return count_; } - } - - public override bool IsInitialized { - get { - return true; + set { + count_ = value; } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _fibReplyFieldNames; - if (hasCount) { - output.WriteInt64(1, field_names[0], Count); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as FibReply); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasCount) { - size += pb::CodedOutputStream.ComputeInt64Size(1, Count); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(FibReply other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; } + if (Count != other.Count) return false; + return true; } - public static FibReply ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static FibReply ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static FibReply ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static FibReply ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static FibReply ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static FibReply ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static FibReply ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static FibReply ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static FibReply ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static FibReply ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private FibReply MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (Count != 0L) hash ^= Count.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(FibReply prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<FibReply, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(FibReply cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private FibReply result; - - private FibReply PrepareBuilder() { - if (resultIsReadOnly) { - FibReply original = result; - result = new FibReply(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override FibReply MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::math.FibReply.Descriptor; } - } - - public override FibReply DefaultInstanceForType { - get { return global::math.FibReply.DefaultInstance; } - } - - public override FibReply BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public void WriteTo(pb::CodedOutputStream output) { + if (Count != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Count); } + } - public override Builder MergeFrom(pb::IMessage other) { - if (other is FibReply) { - return MergeFrom((FibReply) other); - } else { - base.MergeFrom(other); - return this; - } + public int CalculateSize() { + int size = 0; + if (Count != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count); } + return size; + } - public override Builder MergeFrom(FibReply other) { - if (other == global::math.FibReply.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasCount) { - Count = other.Count; - } - this.MergeUnknownFields(other.UnknownFields); - return this; + public void MergeFrom(FibReply other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); + if (other.Count != 0L) { + Count = other.Count; } + } - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_fibReplyFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _fibReplyFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } - } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - result.hasCount = input.ReadInt64(ref result.count_); - break; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Count = input.ReadInt64(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; } - - - public bool HasCount { - get { return result.hasCount; } - } - public long Count { - get { return result.Count; } - set { SetCount(value); } - } - public Builder SetCount(long value) { - PrepareBuilder(); - result.hasCount = true; - result.count_ = value; - return this; - } - public Builder ClearCount() { - PrepareBuilder(); - result.hasCount = false; - result.count_ = 0L; - return this; - } - } - static FibReply() { - object.ReferenceEquals(global::math.Proto.Math.Descriptor, null); } - } - #endregion + } - #region Services - /* - * Service generation is now disabled by default, use the following option to enable: - * option (google.protobuf.csharp_file_options).service_generator_type = GENERIC; - */ #endregion } diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs index dc1bf43995..8009ccbbfa 100644 --- a/src/csharp/Grpc.Examples/MathExamples.cs +++ b/src/csharp/Grpc.Examples/MathExamples.cs @@ -34,25 +34,25 @@ using System.Collections.Generic; using System.Threading.Tasks; using Grpc.Core.Utils; -namespace math +namespace Math { public static class MathExamples { public static void DivExample(Math.IMathClient client) { - DivReply result = client.Div(new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build()); + DivReply result = client.Div(new DivArgs { Dividend = 10, Divisor = 3 }); Console.WriteLine("Div Result: " + result); } public static async Task DivAsyncExample(Math.IMathClient client) { - DivReply result = await client.DivAsync(new DivArgs.Builder { Dividend = 4, Divisor = 5 }.Build()); + DivReply result = await client.DivAsync(new DivArgs { Dividend = 4, Divisor = 5 }); Console.WriteLine("DivAsync Result: " + result); } public static async Task FibExample(Math.IMathClient client) { - using (var call = client.Fib(new FibArgs.Builder { Limit = 5 }.Build())) + using (var call = client.Fib(new FibArgs { Limit = 5 })) { List<Num> result = await call.ResponseStream.ToListAsync(); Console.WriteLine("Fib Result: " + string.Join("|", result)); @@ -63,9 +63,9 @@ namespace math { var numbers = new List<Num> { - new Num.Builder { Num_ = 1 }.Build(), - new Num.Builder { Num_ = 2 }.Build(), - new Num.Builder { Num_ = 3 }.Build() + new Num { Num_ = 1 }, + new Num { Num_ = 2 }, + new Num { Num_ = 3 } }; using (var call = client.Sum()) @@ -79,9 +79,9 @@ namespace math { var divArgsList = new List<DivArgs> { - new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(), - new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(), - new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build() + new DivArgs { Dividend = 10, Divisor = 3 }, + new DivArgs { Dividend = 100, Divisor = 21 }, + new DivArgs { Dividend = 7, Divisor = 2 } }; using (var call = client.DivMany()) { @@ -94,9 +94,9 @@ namespace math { var numbers = new List<Num> { - new Num.Builder { Num_ = 1 }.Build(), - new Num.Builder { Num_ = 2 }.Build(), - new Num.Builder { Num_ = 3 }.Build() + new Num { Num_ = 1 }, + new Num { Num_ = 2 }, + new Num { Num_ = 3 } }; Num sum; @@ -106,7 +106,7 @@ namespace math sum = await sumCall.ResponseAsync; } - DivReply result = await client.DivAsync(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numbers.Count }.Build()); + DivReply result = await client.DivAsync(new DivArgs { Dividend = sum.Num_, Divisor = numbers.Count }); Console.WriteLine("Avg Result: " + result); } } diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 4941ff35f7..175d110f76 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -7,66 +7,72 @@ using System.Threading; using System.Threading.Tasks; using Grpc.Core; -namespace math { +namespace Math { public static class Math { static readonly string __ServiceName = "math.Math"; - static readonly Marshaller<global::math.DivArgs> __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::math.DivArgs.ParseFrom); - static readonly Marshaller<global::math.DivReply> __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), global::math.DivReply.ParseFrom); - static readonly Marshaller<global::math.FibArgs> __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::math.FibArgs.ParseFrom); - static readonly Marshaller<global::math.Num> __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), global::math.Num.ParseFrom); + static readonly Marshaller<global::Math.DivArgs> __Marshaller_DivArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.DivArgs.Parser.ParseFrom); + static readonly Marshaller<global::Math.DivReply> __Marshaller_DivReply = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.DivReply.Parser.ParseFrom); + static readonly Marshaller<global::Math.FibArgs> __Marshaller_FibArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.FibArgs.Parser.ParseFrom); + static readonly Marshaller<global::Math.Num> __Marshaller_Num = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.Num.Parser.ParseFrom); - static readonly Method<global::math.DivArgs, global::math.DivReply> __Method_Div = new Method<global::math.DivArgs, global::math.DivReply>( + static readonly Method<global::Math.DivArgs, global::Math.DivReply> __Method_Div = new Method<global::Math.DivArgs, global::Math.DivReply>( MethodType.Unary, __ServiceName, "Div", __Marshaller_DivArgs, __Marshaller_DivReply); - static readonly Method<global::math.DivArgs, global::math.DivReply> __Method_DivMany = new Method<global::math.DivArgs, global::math.DivReply>( + static readonly Method<global::Math.DivArgs, global::Math.DivReply> __Method_DivMany = new Method<global::Math.DivArgs, global::Math.DivReply>( MethodType.DuplexStreaming, __ServiceName, "DivMany", __Marshaller_DivArgs, __Marshaller_DivReply); - static readonly Method<global::math.FibArgs, global::math.Num> __Method_Fib = new Method<global::math.FibArgs, global::math.Num>( + static readonly Method<global::Math.FibArgs, global::Math.Num> __Method_Fib = new Method<global::Math.FibArgs, global::Math.Num>( MethodType.ServerStreaming, __ServiceName, "Fib", __Marshaller_FibArgs, __Marshaller_Num); - static readonly Method<global::math.Num, global::math.Num> __Method_Sum = new Method<global::math.Num, global::math.Num>( + static readonly Method<global::Math.Num, global::Math.Num> __Method_Sum = new Method<global::Math.Num, global::Math.Num>( MethodType.ClientStreaming, __ServiceName, "Sum", __Marshaller_Num, __Marshaller_Num); + // service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Math.Proto.Math.Descriptor.Services[0]; } + } + // client interface public interface IMathClient { - global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - global::math.DivReply Div(global::math.DivArgs request, CallOptions options); - AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, CallOptions options); - AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(CallOptions options); - AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, CallOptions options); - AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(CallOptions options); + global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options); + AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options); + AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options); + AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options); + AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options); } // server-side interface public interface IMath { - Task<global::math.DivReply> Div(global::math.DivArgs request, ServerCallContext context); - Task DivMany(IAsyncStreamReader<global::math.DivArgs> requestStream, IServerStreamWriter<global::math.DivReply> responseStream, ServerCallContext context); - Task Fib(global::math.FibArgs request, IServerStreamWriter<global::math.Num> responseStream, ServerCallContext context); - Task<global::math.Num> Sum(IAsyncStreamReader<global::math.Num> requestStream, ServerCallContext context); + Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context); + Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context); + Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context); + Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context); } // client stub @@ -75,52 +81,52 @@ namespace math { public MathClient(Channel channel) : base(channel) { } - public global::math.DivReply Div(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken)); return Calls.BlockingUnaryCall(call, request); } - public global::math.DivReply Div(global::math.DivArgs request, CallOptions options) + public global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options) { var call = CreateCall(__Method_Div, options); return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncUnaryCall(call, request); } - public AsyncUnaryCall<global::math.DivReply> DivAsync(global::math.DivArgs request, CallOptions options) + public AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options) { var call = CreateCall(__Method_Div, options); return Calls.AsyncUnaryCall(call, request); } - public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_DivMany, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall<global::math.DivArgs, global::math.DivReply> DivMany(CallOptions options) + public AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options) { var call = CreateCall(__Method_DivMany, options); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_Fib, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncServerStreamingCall(call, request); } - public AsyncServerStreamingCall<global::math.Num> Fib(global::math.FibArgs request, CallOptions options) + public AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options) { var call = CreateCall(__Method_Fib, options); return Calls.AsyncServerStreamingCall(call, request); } - public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_Sum, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncClientStreamingCall(call); } - public AsyncClientStreamingCall<global::math.Num, global::math.Num> Sum(CallOptions options) + public AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options) { var call = CreateCall(__Method_Sum, options); return Calls.AsyncClientStreamingCall(call); diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs index 7b2684615c..71dc655e46 100644 --- a/src/csharp/Grpc.Examples/MathServiceImpl.cs +++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs @@ -38,7 +38,7 @@ using System.Threading.Tasks; using Grpc.Core; using Grpc.Core.Utils; -namespace math +namespace Math { /// <summary> /// Implementation of MathService server @@ -79,7 +79,7 @@ namespace math { sum += num.Num_; }); - return Num.CreateBuilder().SetNum_(sum).Build(); + return new Num { Num_ = sum }; } public async Task DivMany(IAsyncStreamReader<DivArgs> requestStream, IServerStreamWriter<DivReply> responseStream, ServerCallContext context) @@ -91,13 +91,13 @@ namespace math { long quotient = args.Dividend / args.Divisor; long remainder = args.Dividend % args.Divisor; - return new DivReply.Builder { Quotient = quotient, Remainder = remainder }.Build(); + return new DivReply { Quotient = quotient, Remainder = remainder }; } static IEnumerable<Num> FibInternal(long n) { long a = 1; - yield return new Num.Builder { Num_ = a }.Build(); + yield return new Num { Num_ = a }; long b = 1; for (long i = 0; i < n - 1; i++) @@ -105,7 +105,7 @@ namespace math long temp = a; a = b; b = temp + b; - yield return new Num.Builder { Num_ = a }.Build(); + yield return new Num { Num_ = a }; } } } diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config index 4c8d60fa62..adf8da2363 100644 --- a/src/csharp/Grpc.Examples/packages.config +++ b/src/csharp/Grpc.Examples/packages.config @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" /> + <package id="Google.Protobuf" version="3.0.0-alpha4" targetFramework="net45" /> <package id="Ix-Async" version="1.2.3" targetFramework="net45" /> <package id="NUnit" version="2.6.4" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/src/csharp/Grpc.Examples/proto/math.proto b/src/csharp/Grpc.Examples/proto/math.proto index 5485d580c3..311e148c02 100644 --- a/src/csharp/Grpc.Examples/proto/math.proto +++ b/src/csharp/Grpc.Examples/proto/math.proto @@ -28,30 +28,30 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -syntax = "proto2"; +syntax = "proto3"; package math; message DivArgs { - optional int64 dividend = 1; - optional int64 divisor = 2; + int64 dividend = 1; + int64 divisor = 2; } message DivReply { - optional int64 quotient = 1; - optional int64 remainder = 2; + int64 quotient = 1; + int64 remainder = 2; } message FibArgs { - optional int64 limit = 1; + int64 limit = 1; } message Num { - optional int64 num = 1; + int64 num = 1; } message FibReply { - optional int64 count = 1; + int64 count = 1; } service Math { diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj index c922ddfb9e..396dc43a02 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj +++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj @@ -37,11 +37,9 @@ <AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile> </PropertyGroup> <ItemGroup> - <Reference Include="Google.ProtocolBuffers"> - <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath> - </Reference> - <Reference Include="Google.ProtocolBuffers.Serialization"> - <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll</HintPath> + <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath> </Reference> <Reference Include="nunit.framework"> <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath> diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs index 80c35fb197..6c3a53bec0 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs +++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs @@ -81,14 +81,14 @@ namespace Grpc.HealthCheck.Tests { serviceImpl.SetStatus("", "", HealthCheckResponse.Types.ServingStatus.SERVING); - var response = client.Check(HealthCheckRequest.CreateBuilder().SetHost("").SetService("").Build()); + var response = client.Check(new HealthCheckRequest { Host = "", Service = "" }); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.SERVING, response.Status); } [Test] public void ServiceDoesntExist() { - Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => client.Check(HealthCheckRequest.CreateBuilder().SetHost("").SetService("nonexistent.service").Build())); + Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => client.Check(new HealthCheckRequest { Host = "", Service = "nonexistent.service" })); } // TODO(jtattermusch): add test with timeout once timeouts are supported diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs index c4caa3b57a..2097c0dc8c 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs +++ b/src/csharp/Grpc.HealthCheck.Tests/HealthServiceImplTest.cs @@ -101,7 +101,7 @@ namespace Grpc.HealthCheck.Tests private static HealthCheckResponse.Types.ServingStatus GetStatusHelper(HealthServiceImpl impl, string host, string service) { - return impl.Check(HealthCheckRequest.CreateBuilder().SetHost(host).SetService(service).Build(), null).Result.Status; + return impl.Check(new HealthCheckRequest { Host = host, Service = service }, null).Result.Status; } } } diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config index 050c4eaed6..40ffb85203 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/packages.config +++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="Google.ProtocolBuffers" version="2.4.1.555" targetFramework="net45" /> + <package id="Google.Protobuf" version="3.0.0-alpha4" targetFramework="net45" /> <package id="NUnit" version="2.6.4" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj index 0b7a7b91c6..8fce5d39aa 100644 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -38,11 +38,9 @@ <AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile> </PropertyGroup> <ItemGroup> - <Reference Include="Google.ProtocolBuffers"> - <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath> - </Reference> - <Reference Include="Google.ProtocolBuffers.Serialization"> - <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll</HintPath> + <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec index acdfba42c8..66386288df 100644 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec @@ -14,7 +14,7 @@ <copyright>Copyright 2015, Google Inc.</copyright> <tags>gRPC health check</tags> <dependencies> - <dependency id="Google.ProtocolBuffers" version="2.4.1.555" /> + <dependency id="Google.Protobuf" version="$ProtobufVersion$" /> <dependency id="Grpc.Core" version="$version$" /> <dependency id="Ix-Async" version="1.2.3" /> </dependencies> diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs index 361382d4bd..570e274544 100644 --- a/src/csharp/Grpc.HealthCheck/Health.cs +++ b/src/csharp/Grpc.HealthCheck/Health.cs @@ -3,9 +3,9 @@ #pragma warning disable 1591, 0612, 3021 #region Designer generated code -using pb = global::Google.ProtocolBuffers; -using pbc = global::Google.ProtocolBuffers.Collections; -using pbd = global::Google.ProtocolBuffers.Descriptors; +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; namespace Grpc.Health.V1Alpha { @@ -14,21 +14,11 @@ namespace Grpc.Health.V1Alpha { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Health { - #region Extension registration - public static void RegisterAllExtensions(pb::ExtensionRegistry registry) { - } - #endregion - #region Static variables - internal static pbd::MessageDescriptor internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckRequest.Builder> internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckResponse, global::Grpc.Health.V1Alpha.HealthCheckResponse.Builder> internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable; - #endregion #region Descriptor - public static pbd::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor { get { return descriptor; } } - private static pbd::FileDescriptor descriptor; + private static pbr::FileDescriptor descriptor; static Health() { byte[] descriptorData = global::System.Convert.FromBase64String( @@ -41,24 +31,13 @@ namespace Grpc.Health.V1Alpha { "EAESDwoLTk9UX1NFUlZJTkcQAjJkCgZIZWFsdGgSWgoFQ2hlY2sSJy5ncnBj", "LmhlYWx0aC52MWFscGhhLkhlYWx0aENoZWNrUmVxdWVzdBooLmdycGMuaGVh", "bHRoLnYxYWxwaGEuSGVhbHRoQ2hlY2tSZXNwb25zZUIWqgITR3JwYy5IZWFs", - "dGguVjFBbHBoYQ==")); - pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { - descriptor = root; - internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor = Descriptor.MessageTypes[0]; - internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckRequest.Builder>(internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor, - new string[] { "Host", "Service", }); - internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor = Descriptor.MessageTypes[1]; - internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::Grpc.Health.V1Alpha.HealthCheckResponse, global::Grpc.Health.V1Alpha.HealthCheckResponse.Builder>(internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor, - new string[] { "Status", }); - pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance(); - RegisterAllExtensions(registry); - return registry; - }; - pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, - new pbd::FileDescriptor[] { - }, assigner); + "dGguVjFBbHBoYWIGcHJvdG8z")); + descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Health.V1Alpha.HealthCheckRequest), new[]{ "Host", "Service" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Health.V1Alpha.HealthCheckResponse), new[]{ "Status" }, null, new[]{ typeof(global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus) }, null) + })); } #endregion @@ -66,618 +45,245 @@ namespace Grpc.Health.V1Alpha { } #region Messages [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class HealthCheckRequest : pb::GeneratedMessage<HealthCheckRequest, HealthCheckRequest.Builder> { - private HealthCheckRequest() { } - private static readonly HealthCheckRequest defaultInstance = new HealthCheckRequest().MakeReadOnly(); - private static readonly string[] _healthCheckRequestFieldNames = new string[] { "host", "service" }; - private static readonly uint[] _healthCheckRequestFieldTags = new uint[] { 10, 18 }; - public static HealthCheckRequest DefaultInstance { - get { return defaultInstance; } + public sealed partial class HealthCheckRequest : pb::IMessage<HealthCheckRequest> { + private static readonly pb::MessageParser<HealthCheckRequest> _parser = new pb::MessageParser<HealthCheckRequest>(() => new HealthCheckRequest()); + public static pb::MessageParser<HealthCheckRequest> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Health.V1Alpha.Proto.Health.Descriptor.MessageTypes[0]; } } - public override HealthCheckRequest DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override HealthCheckRequest ThisMessage { - get { return this; } + public HealthCheckRequest() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckRequest__Descriptor; } + partial void OnConstruction(); + + public HealthCheckRequest(HealthCheckRequest other) : this() { + host_ = other.host_; + service_ = other.service_; } - protected override pb::FieldAccess.FieldAccessorTable<HealthCheckRequest, HealthCheckRequest.Builder> InternalFieldAccessors { - get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable; } + public HealthCheckRequest Clone() { + return new HealthCheckRequest(this); } public const int HostFieldNumber = 1; - private bool hasHost; private string host_ = ""; - public bool HasHost { - get { return hasHost; } - } public string Host { get { return host_; } + set { + host_ = pb::Preconditions.CheckNotNull(value, "value"); + } } public const int ServiceFieldNumber = 2; - private bool hasService; private string service_ = ""; - public bool HasService { - get { return hasService; } - } public string Service { get { return service_; } - } - - public override bool IsInitialized { - get { - return true; - } - } - - public override void WriteTo(pb::ICodedOutputStream output) { - CalcSerializedSize(); - string[] field_names = _healthCheckRequestFieldNames; - if (hasHost) { - output.WriteString(1, field_names[0], Host); - } - if (hasService) { - output.WriteString(2, field_names[1], Service); + set { + service_ = pb::Preconditions.CheckNotNull(value, "value"); } - UnknownFields.WriteTo(output); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - return CalcSerializedSize(); - } + public override bool Equals(object other) { + return Equals(other as HealthCheckRequest); } - private int CalcSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasHost) { - size += pb::CodedOutputStream.ComputeStringSize(1, Host); + public bool Equals(HealthCheckRequest other) { + if (ReferenceEquals(other, null)) { + return false; } - if (hasService) { - size += pb::CodedOutputStream.ComputeStringSize(2, Service); + if (ReferenceEquals(other, this)) { + return true; } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; - } - public static HealthCheckRequest ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static HealthCheckRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static HealthCheckRequest ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static HealthCheckRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static HealthCheckRequest ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static HealthCheckRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static HealthCheckRequest ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static HealthCheckRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static HealthCheckRequest ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static HealthCheckRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private HealthCheckRequest MakeReadOnly() { - return this; + if (Host != other.Host) return false; + if (Service != other.Service) return false; + return true; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(HealthCheckRequest prototype) { - return new Builder(prototype); + public override int GetHashCode() { + int hash = 1; + if (Host.Length != 0) hash ^= Host.GetHashCode(); + if (Service.Length != 0) hash ^= Service.GetHashCode(); + return hash; } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<HealthCheckRequest, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(HealthCheckRequest cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private HealthCheckRequest result; - - private HealthCheckRequest PrepareBuilder() { - if (resultIsReadOnly) { - HealthCheckRequest original = result; - result = new HealthCheckRequest(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override HealthCheckRequest MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); + } - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } + public void WriteTo(pb::CodedOutputStream output) { + if (Host.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Host); } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::Grpc.Health.V1Alpha.HealthCheckRequest.Descriptor; } + if (Service.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Service); } + } - public override HealthCheckRequest DefaultInstanceForType { - get { return global::Grpc.Health.V1Alpha.HealthCheckRequest.DefaultInstance; } + public int CalculateSize() { + int size = 0; + if (Host.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Host); } - - public override HealthCheckRequest BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + if (Service.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Service); } + return size; + } - public override Builder MergeFrom(pb::IMessage other) { - if (other is HealthCheckRequest) { - return MergeFrom((HealthCheckRequest) other); - } else { - base.MergeFrom(other); - return this; - } + public void MergeFrom(HealthCheckRequest other) { + if (other == null) { + return; } - - public override Builder MergeFrom(HealthCheckRequest other) { - if (other == global::Grpc.Health.V1Alpha.HealthCheckRequest.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasHost) { - Host = other.Host; - } - if (other.HasService) { - Service = other.Service; - } - this.MergeUnknownFields(other.UnknownFields); - return this; + if (other.Host.Length != 0) { + Host = other.Host; } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); + if (other.Service.Length != 0) { + Service = other.Service; } + } - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_healthCheckRequestFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _healthCheckRequestFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + Host = input.ReadString(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 10: { - result.hasHost = input.ReadString(ref result.host_); - break; - } - case 18: { - result.hasService = input.ReadString(ref result.service_); - break; - } + case 18: { + Service = input.ReadString(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasHost { - get { return result.hasHost; } - } - public string Host { - get { return result.Host; } - set { SetHost(value); } - } - public Builder SetHost(string value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasHost = true; - result.host_ = value; - return this; - } - public Builder ClearHost() { - PrepareBuilder(); - result.hasHost = false; - result.host_ = ""; - return this; - } - - public bool HasService { - get { return result.hasService; } - } - public string Service { - get { return result.Service; } - set { SetService(value); } } - public Builder SetService(string value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasService = true; - result.service_ = value; - return this; - } - public Builder ClearService() { - PrepareBuilder(); - result.hasService = false; - result.service_ = ""; - return this; - } - } - static HealthCheckRequest() { - object.ReferenceEquals(global::Grpc.Health.V1Alpha.Proto.Health.Descriptor, null); } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class HealthCheckResponse : pb::GeneratedMessage<HealthCheckResponse, HealthCheckResponse.Builder> { - private HealthCheckResponse() { } - private static readonly HealthCheckResponse defaultInstance = new HealthCheckResponse().MakeReadOnly(); - private static readonly string[] _healthCheckResponseFieldNames = new string[] { "status" }; - private static readonly uint[] _healthCheckResponseFieldTags = new uint[] { 8 }; - public static HealthCheckResponse DefaultInstance { - get { return defaultInstance; } - } + public sealed partial class HealthCheckResponse : pb::IMessage<HealthCheckResponse> { + private static readonly pb::MessageParser<HealthCheckResponse> _parser = new pb::MessageParser<HealthCheckResponse>(() => new HealthCheckResponse()); + public static pb::MessageParser<HealthCheckResponse> Parser { get { return _parser; } } - public override HealthCheckResponse DefaultInstanceForType { - get { return DefaultInstance; } + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Health.V1Alpha.Proto.Health.Descriptor.MessageTypes[1]; } } - protected override HealthCheckResponse ThisMessage { - get { return this; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - public static pbd::MessageDescriptor Descriptor { - get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor; } + public HealthCheckResponse() { + OnConstruction(); } - protected override pb::FieldAccess.FieldAccessorTable<HealthCheckResponse, HealthCheckResponse.Builder> InternalFieldAccessors { - get { return global::Grpc.Health.V1Alpha.Proto.Health.internal__static_grpc_health_v1alpha_HealthCheckResponse__FieldAccessorTable; } - } + partial void OnConstruction(); - #region Nested types - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public static partial class Types { - public enum ServingStatus { - UNKNOWN = 0, - SERVING = 1, - NOT_SERVING = 2, - } + public HealthCheckResponse(HealthCheckResponse other) : this() { + status_ = other.status_; + } + public HealthCheckResponse Clone() { + return new HealthCheckResponse(this); } - #endregion public const int StatusFieldNumber = 1; - private bool hasStatus; private global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus status_ = global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN; - public bool HasStatus { - get { return hasStatus; } - } public global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus Status { get { return status_; } - } - - public override bool IsInitialized { - get { - return true; + set { + status_ = value; } } - public override void WriteTo(pb::ICodedOutputStream output) { - CalcSerializedSize(); - string[] field_names = _healthCheckResponseFieldNames; - if (hasStatus) { - output.WriteEnum(1, field_names[0], (int) Status, Status); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as HealthCheckResponse); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - return CalcSerializedSize(); + public bool Equals(HealthCheckResponse other) { + if (ReferenceEquals(other, null)) { + return false; } - } - - private int CalcSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasStatus) { - size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Status); + if (ReferenceEquals(other, this)) { + return true; } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; - } - public static HealthCheckResponse ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static HealthCheckResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static HealthCheckResponse ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static HealthCheckResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static HealthCheckResponse ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static HealthCheckResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static HealthCheckResponse ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static HealthCheckResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static HealthCheckResponse ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static HealthCheckResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private HealthCheckResponse MakeReadOnly() { - return this; + if (Status != other.Status) return false; + return true; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(HealthCheckResponse prototype) { - return new Builder(prototype); + public override int GetHashCode() { + int hash = 1; + if (Status != global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN) hash ^= Status.GetHashCode(); + return hash; } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<HealthCheckResponse, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(HealthCheckResponse cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private HealthCheckResponse result; - - private HealthCheckResponse PrepareBuilder() { - if (resultIsReadOnly) { - HealthCheckResponse original = result; - result = new HealthCheckResponse(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override HealthCheckResponse MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::Grpc.Health.V1Alpha.HealthCheckResponse.Descriptor; } - } - - public override HealthCheckResponse DefaultInstanceForType { - get { return global::Grpc.Health.V1Alpha.HealthCheckResponse.DefaultInstance; } - } + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); + } - public override HealthCheckResponse BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public void WriteTo(pb::CodedOutputStream output) { + if (Status != global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN) { + output.WriteRawTag(8); + output.WriteEnum((int) Status); } + } - public override Builder MergeFrom(pb::IMessage other) { - if (other is HealthCheckResponse) { - return MergeFrom((HealthCheckResponse) other); - } else { - base.MergeFrom(other); - return this; - } + public int CalculateSize() { + int size = 0; + if (Status != global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status); } + return size; + } - public override Builder MergeFrom(HealthCheckResponse other) { - if (other == global::Grpc.Health.V1Alpha.HealthCheckResponse.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasStatus) { - Status = other.Status; - } - this.MergeUnknownFields(other.UnknownFields); - return this; + public void MergeFrom(HealthCheckResponse other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); + if (other.Status != global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN) { + Status = other.Status; } + } - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_healthCheckResponseFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _healthCheckResponseFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + status_ = (global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus) input.ReadEnum(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - object unknown; - if(input.ReadEnum(ref result.status_, out unknown)) { - result.hasStatus = true; - } else if(unknown is int) { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - unknownFields.MergeVarintField(1, (ulong)(int)unknown); - } - break; - } - } - } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); } - return this; } + } - - public bool HasStatus { - get { return result.hasStatus; } - } - public global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus Status { - get { return result.Status; } - set { SetStatus(value); } - } - public Builder SetStatus(global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus value) { - PrepareBuilder(); - result.hasStatus = true; - result.status_ = value; - return this; - } - public Builder ClearStatus() { - PrepareBuilder(); - result.hasStatus = false; - result.status_ = global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus.UNKNOWN; - return this; + #region Nested types + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static partial class Types { + public enum ServingStatus { + UNKNOWN = 0, + SERVING = 1, + NOT_SERVING = 2, } + } - static HealthCheckResponse() { - object.ReferenceEquals(global::Grpc.Health.V1Alpha.Proto.Health.Descriptor, null); - } + #endregion + } #endregion diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 0dabc91f7c..da721ce5f6 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -12,8 +12,8 @@ namespace Grpc.Health.V1Alpha { { static readonly string __ServiceName = "grpc.health.v1alpha.Health"; - static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckRequest> __Marshaller_HealthCheckRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Health.V1Alpha.HealthCheckRequest.ParseFrom); - static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckResponse> __Marshaller_HealthCheckResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Health.V1Alpha.HealthCheckResponse.ParseFrom); + static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckRequest> __Marshaller_HealthCheckRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1Alpha.HealthCheckRequest.Parser.ParseFrom); + static readonly Marshaller<global::Grpc.Health.V1Alpha.HealthCheckResponse> __Marshaller_HealthCheckResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1Alpha.HealthCheckResponse.Parser.ParseFrom); static readonly Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse> __Method_Check = new Method<global::Grpc.Health.V1Alpha.HealthCheckRequest, global::Grpc.Health.V1Alpha.HealthCheckResponse>( MethodType.Unary, @@ -22,6 +22,12 @@ namespace Grpc.Health.V1Alpha { __Marshaller_HealthCheckRequest, __Marshaller_HealthCheckResponse); + // service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Health.V1Alpha.Proto.Health.Descriptor.Services[0]; } + } + // client interface public interface IHealthClient { diff --git a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs index 8c04b43a86..26c6445c35 100644 --- a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs +++ b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs @@ -105,8 +105,8 @@ namespace Grpc.HealthCheck { lock (myLock) { - var host = request.HasHost ? request.Host : ""; - var service = request.HasService ? request.Service : ""; + var host = request.Host; + var service = request.Service; HealthCheckResponse.Types.ServingStatus status; if (!statusMap.TryGetValue(CreateKey(host, service), out status)) @@ -114,7 +114,7 @@ namespace Grpc.HealthCheck // TODO(jtattermusch): returning specific status from server handler is not supported yet. throw new RpcException(new Status(StatusCode.NotFound, "")); } - return Task.FromResult(HealthCheckResponse.CreateBuilder().SetStatus(status).Build()); + return Task.FromResult(new HealthCheckResponse { Status = status }); } } diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config index 094a30981e..cafff6123a 100644 --- a/src/csharp/Grpc.HealthCheck/packages.config +++ b/src/csharp/Grpc.HealthCheck/packages.config @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="Google.ProtocolBuffers" version="2.4.1.555" targetFramework="net45" /> + <package id="Google.Protobuf" version="3.0.0-alpha4" targetFramework="net45" /> <package id="Ix-Async" version="1.2.3" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/src/csharp/Grpc.HealthCheck/proto/health.proto b/src/csharp/Grpc.HealthCheck/proto/health.proto index 08df7e104e..01aa3fcf57 100644 --- a/src/csharp/Grpc.HealthCheck/proto/health.proto +++ b/src/csharp/Grpc.HealthCheck/proto/health.proto @@ -28,14 +28,14 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // TODO(jtattermusch): switch to proto3 once C# supports that. -syntax = "proto2"; +syntax = "proto3"; package grpc.health.v1alpha; option csharp_namespace = "Grpc.Health.V1Alpha"; message HealthCheckRequest { - optional string host = 1; - optional string service = 2; + string host = 1; + string service = 2; } message HealthCheckResponse { @@ -44,7 +44,7 @@ message HealthCheckResponse { SERVING = 1; NOT_SERVING = 2; } - optional ServingStatus status = 1; + ServingStatus status = 1; } service Health { diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs index 7169ee2a4a..28c28c9afd 100644 --- a/src/csharp/Grpc.IntegrationTesting/Empty.cs +++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs @@ -1,47 +1,34 @@ -// Generated by ProtoGen, Version=2.4.1.521, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48. DO NOT EDIT! +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: empty.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code -using pb = global::Google.ProtocolBuffers; -using pbc = global::Google.ProtocolBuffers.Collections; -using pbd = global::Google.ProtocolBuffers.Descriptors; +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace grpc.testing { +namespace Grpc.Testing { namespace Proto { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Empty { - #region Extension registration - public static void RegisterAllExtensions(pb::ExtensionRegistry registry) { - } - #endregion - #region Static variables - internal static pbd::MessageDescriptor internal__static_grpc_testing_Empty__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.Empty, global::grpc.testing.Empty.Builder> internal__static_grpc_testing_Empty__FieldAccessorTable; - #endregion #region Descriptor - public static pbd::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor { get { return descriptor; } } - private static pbd::FileDescriptor descriptor; + private static pbr::FileDescriptor descriptor; static Empty() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "CgtlbXB0eS5wcm90bxIMZ3JwYy50ZXN0aW5nIgcKBUVtcHR5")); - pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { - descriptor = root; - internal__static_grpc_testing_Empty__Descriptor = Descriptor.MessageTypes[0]; - internal__static_grpc_testing_Empty__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.Empty, global::grpc.testing.Empty.Builder>(internal__static_grpc_testing_Empty__Descriptor, - new string[] { }); - return null; - }; - pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, - new pbd::FileDescriptor[] { - }, assigner); + "CgtlbXB0eS5wcm90bxIMZ3JwYy50ZXN0aW5nIgcKBUVtcHR5YgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedCodeInfo(null, new pbr::GeneratedCodeInfo[] { + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Empty), null, null, null, null) + })); } #endregion @@ -49,230 +36,79 @@ namespace grpc.testing { } #region Messages [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Empty : pb::GeneratedMessage<Empty, Empty.Builder> { - private Empty() { } - private static readonly Empty defaultInstance = new Empty().MakeReadOnly(); - private static readonly string[] _emptyFieldNames = new string[] { }; - private static readonly uint[] _emptyFieldTags = new uint[] { }; - public static Empty DefaultInstance { - get { return defaultInstance; } - } + public sealed partial class Empty : pb::IMessage<Empty> { + private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty()); + public static pb::MessageParser<Empty> Parser { get { return _parser; } } - public override Empty DefaultInstanceForType { - get { return DefaultInstance; } + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Proto.Empty.Descriptor.MessageTypes[0]; } } - protected override Empty ThisMessage { - get { return this; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Proto.Empty.internal__static_grpc_testing_Empty__Descriptor; } + public Empty() { + OnConstruction(); } - protected override pb::FieldAccess.FieldAccessorTable<Empty, Empty.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Proto.Empty.internal__static_grpc_testing_Empty__FieldAccessorTable; } - } + partial void OnConstruction(); - public override bool IsInitialized { - get { - return true; - } + public Empty(Empty other) : this() { } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _emptyFieldNames; - UnknownFields.WriteTo(output); + public Empty Clone() { + return new Empty(this); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; + public override bool Equals(object other) { + return Equals(other as Empty); + } - size = 0; - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(Empty other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; } + return true; } - public static Empty ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static Empty ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static Empty ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static Empty ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static Empty ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static Empty ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static Empty ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static Empty ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static Empty ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static Empty ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private Empty MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(Empty prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<Empty, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(Empty cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private Empty result; - - private Empty PrepareBuilder() { - if (resultIsReadOnly) { - Empty original = result; - result = new Empty(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override Empty MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.Empty.Descriptor; } - } - - public override Empty DefaultInstanceForType { - get { return global::grpc.testing.Empty.DefaultInstance; } - } - - public override Empty BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); - } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is Empty) { - return MergeFrom((Empty) other); - } else { - base.MergeFrom(other); - return this; - } - } + public void WriteTo(pb::CodedOutputStream output) { + } - public override Builder MergeFrom(Empty other) { - if (other == global::grpc.testing.Empty.DefaultInstance) return this; - PrepareBuilder(); - this.MergeUnknownFields(other.UnknownFields); - return this; - } + public int CalculateSize() { + int size = 0; + return size; + } - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); + public void MergeFrom(Empty other) { + if (other == null) { + return; } + } - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_emptyFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _emptyFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } - } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - } - } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; } - return this; } - - } - static Empty() { - object.ReferenceEquals(global::grpc.testing.Proto.Empty.Descriptor, null); } + } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 2020a76d39..a5945be922 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -54,6 +54,10 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\Google.Apis.Core.1.9.3\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll</HintPath> </Reference> + <Reference Include="Google.Protobuf, Version=3.0.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll</HintPath> + </Reference> <Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll</HintPath> @@ -74,22 +78,11 @@ <HintPath>..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath> </Reference> <Reference Include="System" /> - <Reference Include="Google.ProtocolBuffers"> - <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath> - </Reference> <Reference Include="System.Interactive.Async"> <HintPath>..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll</HintPath> </Reference> <Reference Include="System.Net" /> <Reference Include="System.Net.Http" /> - <Reference Include="System.Net.Http.Extensions, Version=2.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll</HintPath> - </Reference> - <Reference Include="System.Net.Http.Primitives, Version=4.2.29.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll</HintPath> - </Reference> <Reference Include="System.Net.Http.WebRequest" /> </ItemGroup> <ItemGroup> @@ -106,6 +99,7 @@ <Compile Include="TestCredentials.cs" /> <Compile Include="TestGrpc.cs" /> <Compile Include="SslCredentialsTest.cs" /> + <Compile Include="Test.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <ItemGroup> diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index 24c22273fb..8343e54122 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -38,13 +38,11 @@ using System.Threading; using System.Threading.Tasks; using Google.Apis.Auth.OAuth2; -using Google.ProtocolBuffers; - -using grpc.testing; +using Google.Protobuf; using Grpc.Auth; using Grpc.Core; using Grpc.Core.Utils; - +using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting @@ -183,7 +181,7 @@ namespace Grpc.IntegrationTesting public static void RunEmptyUnary(TestService.ITestServiceClient client) { Console.WriteLine("running empty_unary"); - var response = client.EmptyCall(Empty.DefaultInstance); + var response = client.EmptyCall(new Empty()); Assert.IsNotNull(response); Console.WriteLine("Passed!"); } @@ -191,11 +189,12 @@ namespace Grpc.IntegrationTesting public static void RunLargeUnary(TestService.ITestServiceClient client) { Console.WriteLine("running large_unary"); - var request = SimpleRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .SetResponseSize(314159) - .SetPayload(CreateZerosPayload(271828)) - .Build(); + var request = new SimpleRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseSize = 314159, + Payload = CreateZerosPayload(271828) + }; var response = client.UnaryCall(request); @@ -208,7 +207,7 @@ namespace Grpc.IntegrationTesting { Console.WriteLine("running client_streaming"); - var bodySizes = new List<int> { 27182, 8, 1828, 45904 }.ConvertAll((size) => StreamingInputCallRequest.CreateBuilder().SetPayload(CreateZerosPayload(size)).Build()); + var bodySizes = new List<int> { 27182, 8, 1828, 45904 }.ConvertAll((size) => new StreamingInputCallRequest { Payload = CreateZerosPayload(size) }); using (var call = client.StreamingInputCall()) { @@ -226,11 +225,11 @@ namespace Grpc.IntegrationTesting var bodySizes = new List<int> { 31415, 9, 2653, 58979 }; - var request = StreamingOutputCallRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .AddRangeResponseParameters(bodySizes.ConvertAll( - (size) => ResponseParameters.CreateBuilder().SetSize(size).Build())) - .Build(); + var request = new StreamingOutputCallRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseParameters = { bodySizes.ConvertAll((size) => new ResponseParameters { Size = size }) } + }; using (var call = client.StreamingOutputCall(request)) { @@ -250,37 +249,45 @@ namespace Grpc.IntegrationTesting using (var call = client.FullDuplexCall()) { - await call.RequestStream.WriteAsync(StreamingOutputCallRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(31415)) - .SetPayload(CreateZerosPayload(27182)).Build()); + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseParameters = { new ResponseParameters { Size = 31415 } }, + Payload = CreateZerosPayload(27182) + }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type); Assert.AreEqual(31415, call.ResponseStream.Current.Payload.Body.Length); - await call.RequestStream.WriteAsync(StreamingOutputCallRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(9)) - .SetPayload(CreateZerosPayload(8)).Build()); + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseParameters = { new ResponseParameters { Size = 9 } }, + Payload = CreateZerosPayload(8) + }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type); Assert.AreEqual(9, call.ResponseStream.Current.Payload.Body.Length); - await call.RequestStream.WriteAsync(StreamingOutputCallRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(2653)) - .SetPayload(CreateZerosPayload(1828)).Build()); + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseParameters = { new ResponseParameters { Size = 2653 } }, + Payload = CreateZerosPayload(1828) + }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type); Assert.AreEqual(2653, call.ResponseStream.Current.Payload.Body.Length); - await call.RequestStream.WriteAsync(StreamingOutputCallRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(58979)) - .SetPayload(CreateZerosPayload(45904)).Build()); + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseParameters = { new ResponseParameters { Size = 58979 } }, + Payload = CreateZerosPayload(45904) + }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type); @@ -313,13 +320,14 @@ namespace Grpc.IntegrationTesting credential = credential.CreateScoped(new[] { AuthScope }); client.HeaderInterceptor = AuthInterceptors.FromCredential(credential); - var request = SimpleRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .SetResponseSize(314159) - .SetPayload(CreateZerosPayload(271828)) - .SetFillUsername(true) - .SetFillOauthScope(true) - .Build(); + var request = new SimpleRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseSize = 314159, + Payload = CreateZerosPayload(271828), + FillUsername = true, + FillOauthScope = true + }; var response = client.UnaryCall(request); @@ -337,13 +345,14 @@ namespace Grpc.IntegrationTesting Assert.IsFalse(credential.IsCreateScopedRequired); client.HeaderInterceptor = AuthInterceptors.FromCredential(credential); - var request = SimpleRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .SetResponseSize(314159) - .SetPayload(CreateZerosPayload(271828)) - .SetFillUsername(true) - .SetFillOauthScope(true) - .Build(); + var request = new SimpleRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseSize = 314159, + Payload = CreateZerosPayload(271828), + FillUsername = true, + FillOauthScope = true + }; var response = client.UnaryCall(request); @@ -362,13 +371,14 @@ namespace Grpc.IntegrationTesting Assert.IsTrue(credential.IsCreateScopedRequired); client.HeaderInterceptor = AuthInterceptors.FromCredential(credential); - var request = SimpleRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .SetResponseSize(314159) - .SetPayload(CreateZerosPayload(271828)) - .SetFillUsername(true) - .SetFillOauthScope(true) - .Build(); + var request = new SimpleRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseSize = 314159, + Payload = CreateZerosPayload(271828), + FillUsername = true, + FillOauthScope = true + }; var response = client.UnaryCall(request); @@ -386,10 +396,11 @@ namespace Grpc.IntegrationTesting client.HeaderInterceptor = AuthInterceptors.FromAccessToken(oauth2Token); - var request = SimpleRequest.CreateBuilder() - .SetFillUsername(true) - .SetFillOauthScope(true) - .Build(); + var request = new SimpleRequest + { + FillUsername = true, + FillOauthScope = true + }; var response = client.UnaryCall(request); @@ -406,10 +417,11 @@ namespace Grpc.IntegrationTesting string oauth2Token = await credential.GetAccessTokenForRequestAsync(); var headerInterceptor = AuthInterceptors.FromAccessToken(oauth2Token); - var request = SimpleRequest.CreateBuilder() - .SetFillUsername(true) - .SetFillOauthScope(true) - .Build(); + var request = new SimpleRequest + { + FillUsername = true, + FillOauthScope = true + }; var headers = new Metadata(); headerInterceptor(null, "", headers); @@ -444,10 +456,12 @@ namespace Grpc.IntegrationTesting var cts = new CancellationTokenSource(); using (var call = client.FullDuplexCall(cancellationToken: cts.Token)) { - await call.RequestStream.WriteAsync(StreamingOutputCallRequest.CreateBuilder() - .SetResponseType(PayloadType.COMPRESSABLE) - .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(31415)) - .SetPayload(CreateZerosPayload(27182)).Build()); + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest + { + ResponseType = PayloadType.COMPRESSABLE, + ResponseParameters = { new ResponseParameters { Size = 31415 } }, + Payload = CreateZerosPayload(27182) + }); Assert.IsTrue(await call.ResponseStream.MoveNext()); Assert.AreEqual(PayloadType.COMPRESSABLE, call.ResponseStream.Current.Payload.Type); @@ -470,8 +484,7 @@ namespace Grpc.IntegrationTesting { try { - await call.RequestStream.WriteAsync(StreamingOutputCallRequest.CreateBuilder() - .SetPayload(CreateZerosPayload(27182)).Build()); + await call.RequestStream.WriteAsync(new StreamingOutputCallRequest { Payload = CreateZerosPayload(27182) }); } catch (InvalidOperationException) { @@ -488,12 +501,12 @@ namespace Grpc.IntegrationTesting public static void RunBenchmarkEmptyUnary(TestService.ITestServiceClient client) { BenchmarkUtil.RunBenchmark(10000, 10000, - () => { client.EmptyCall(Empty.DefaultInstance); }); + () => { client.EmptyCall(new Empty()); }); } private static Payload CreateZerosPayload(int size) { - return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build(); + return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } private static ClientOptions ParseArguments(string[] args) diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs index f3158aeb45..7bc17a207f 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs @@ -36,9 +36,9 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using grpc.testing; using Grpc.Core; using Grpc.Core.Utils; +using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs index 0cc8b2cde1..718278f30a 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs @@ -37,10 +37,9 @@ using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Google.ProtocolBuffers; -using grpc.testing; using Grpc.Core; using Grpc.Core.Utils; +using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs index 386f377f08..a3cbb7d76e 100644 --- a/src/csharp/Grpc.IntegrationTesting/Messages.cs +++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs @@ -1,106 +1,58 @@ -// Generated by ProtoGen, Version=2.4.1.521, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48. DO NOT EDIT! +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: messages.proto #pragma warning disable 1591, 0612, 3021 #region Designer generated code -using pb = global::Google.ProtocolBuffers; -using pbc = global::Google.ProtocolBuffers.Collections; -using pbd = global::Google.ProtocolBuffers.Descriptors; +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; using scg = global::System.Collections.Generic; -namespace grpc.testing { +namespace Grpc.Testing { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Messages { - #region Extension registration - public static void RegisterAllExtensions(pb::ExtensionRegistry registry) { - } - #endregion - #region Static variables - internal static pbd::MessageDescriptor internal__static_grpc_testing_Payload__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.Payload, global::grpc.testing.Payload.Builder> internal__static_grpc_testing_Payload__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_SimpleRequest__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleRequest.Builder> internal__static_grpc_testing_SimpleRequest__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_SimpleResponse__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.SimpleResponse, global::grpc.testing.SimpleResponse.Builder> internal__static_grpc_testing_SimpleResponse__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingInputCallRequest__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallRequest.Builder> internal__static_grpc_testing_StreamingInputCallRequest__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingInputCallResponse__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingInputCallResponse, global::grpc.testing.StreamingInputCallResponse.Builder> internal__static_grpc_testing_StreamingInputCallResponse__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_ResponseParameters__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.ResponseParameters, global::grpc.testing.ResponseParameters.Builder> internal__static_grpc_testing_ResponseParameters__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallRequest.Builder> internal__static_grpc_testing_StreamingOutputCallRequest__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingOutputCallResponse, global::grpc.testing.StreamingOutputCallResponse.Builder> internal__static_grpc_testing_StreamingOutputCallResponse__FieldAccessorTable; - #endregion #region Descriptor - public static pbd::FileDescriptor Descriptor { + public static pbr::FileDescriptor Descriptor { get { return descriptor; } } - private static pbd::FileDescriptor descriptor; + private static pbr::FileDescriptor descriptor; static Messages() { byte[] descriptorData = global::System.Convert.FromBase64String( string.Concat( - "Cg5tZXNzYWdlcy5wcm90bxIMZ3JwYy50ZXN0aW5nIkAKB1BheWxvYWQSJwoE", - "dHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlwZRIMCgRib2R5", - "GAIgASgMIrEBCg1TaW1wbGVSZXF1ZXN0EjAKDXJlc3BvbnNlX3R5cGUYASAB", - "KA4yGS5ncnBjLnRlc3RpbmcuUGF5bG9hZFR5cGUSFQoNcmVzcG9uc2Vfc2l6", - "ZRgCIAEoBRImCgdwYXlsb2FkGAMgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxv", - "YWQSFQoNZmlsbF91c2VybmFtZRgEIAEoCBIYChBmaWxsX29hdXRoX3Njb3Bl", - "GAUgASgIIl8KDlNpbXBsZVJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5n", - "cnBjLnRlc3RpbmcuUGF5bG9hZBIQCgh1c2VybmFtZRgCIAEoCRITCgtvYXV0", - "aF9zY29wZRgDIAEoCSJDChlTdHJlYW1pbmdJbnB1dENhbGxSZXF1ZXN0EiYK", - "B3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3RpbmcuUGF5bG9hZCI9ChpTdHJl", - "YW1pbmdJbnB1dENhbGxSZXNwb25zZRIfChdhZ2dyZWdhdGVkX3BheWxvYWRf", - "c2l6ZRgBIAEoBSI3ChJSZXNwb25zZVBhcmFtZXRlcnMSDAoEc2l6ZRgBIAEo", - "BRITCgtpbnRlcnZhbF91cxgCIAEoBSK1AQoaU3RyZWFtaW5nT3V0cHV0Q2Fs", - "bFJlcXVlc3QSMAoNcmVzcG9uc2VfdHlwZRgBIAEoDjIZLmdycGMudGVzdGlu", - "Zy5QYXlsb2FkVHlwZRI9ChNyZXNwb25zZV9wYXJhbWV0ZXJzGAIgAygLMiAu", - "Z3JwYy50ZXN0aW5nLlJlc3BvbnNlUGFyYW1ldGVycxImCgdwYXlsb2FkGAMg", - "ASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxvYWQiRQobU3RyZWFtaW5nT3V0cHV0", - "Q2FsbFJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3Rpbmcu", - "UGF5bG9hZCo/CgtQYXlsb2FkVHlwZRIQCgxDT01QUkVTU0FCTEUQABISCg5V", - "TkNPTVBSRVNTQUJMRRABEgoKBlJBTkRPTRAC")); - pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { - descriptor = root; - internal__static_grpc_testing_Payload__Descriptor = Descriptor.MessageTypes[0]; - internal__static_grpc_testing_Payload__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.Payload, global::grpc.testing.Payload.Builder>(internal__static_grpc_testing_Payload__Descriptor, - new string[] { "Type", "Body", }); - internal__static_grpc_testing_SimpleRequest__Descriptor = Descriptor.MessageTypes[1]; - internal__static_grpc_testing_SimpleRequest__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleRequest.Builder>(internal__static_grpc_testing_SimpleRequest__Descriptor, - new string[] { "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope", }); - internal__static_grpc_testing_SimpleResponse__Descriptor = Descriptor.MessageTypes[2]; - internal__static_grpc_testing_SimpleResponse__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.SimpleResponse, global::grpc.testing.SimpleResponse.Builder>(internal__static_grpc_testing_SimpleResponse__Descriptor, - new string[] { "Payload", "Username", "OauthScope", }); - internal__static_grpc_testing_StreamingInputCallRequest__Descriptor = Descriptor.MessageTypes[3]; - internal__static_grpc_testing_StreamingInputCallRequest__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallRequest.Builder>(internal__static_grpc_testing_StreamingInputCallRequest__Descriptor, - new string[] { "Payload", }); - internal__static_grpc_testing_StreamingInputCallResponse__Descriptor = Descriptor.MessageTypes[4]; - internal__static_grpc_testing_StreamingInputCallResponse__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingInputCallResponse, global::grpc.testing.StreamingInputCallResponse.Builder>(internal__static_grpc_testing_StreamingInputCallResponse__Descriptor, - new string[] { "AggregatedPayloadSize", }); - internal__static_grpc_testing_ResponseParameters__Descriptor = Descriptor.MessageTypes[5]; - internal__static_grpc_testing_ResponseParameters__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.ResponseParameters, global::grpc.testing.ResponseParameters.Builder>(internal__static_grpc_testing_ResponseParameters__Descriptor, - new string[] { "Size", "IntervalUs", }); - internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor = Descriptor.MessageTypes[6]; - internal__static_grpc_testing_StreamingOutputCallRequest__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallRequest.Builder>(internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor, - new string[] { "ResponseType", "ResponseParameters", "Payload", }); - internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor = Descriptor.MessageTypes[7]; - internal__static_grpc_testing_StreamingOutputCallResponse__FieldAccessorTable = - new pb::FieldAccess.FieldAccessorTable<global::grpc.testing.StreamingOutputCallResponse, global::grpc.testing.StreamingOutputCallResponse.Builder>(internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor, - new string[] { "Payload", }); - return null; - }; - pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, - new pbd::FileDescriptor[] { - }, assigner); + "Cg5tZXNzYWdlcy5wcm90bxIMZ3JwYy50ZXN0aW5nIkAKB1BheWxvYWQSJwoE", + "dHlwZRgBIAEoDjIZLmdycGMudGVzdGluZy5QYXlsb2FkVHlwZRIMCgRib2R5", + "GAIgASgMIrEBCg1TaW1wbGVSZXF1ZXN0EjAKDXJlc3BvbnNlX3R5cGUYASAB", + "KA4yGS5ncnBjLnRlc3RpbmcuUGF5bG9hZFR5cGUSFQoNcmVzcG9uc2Vfc2l6", + "ZRgCIAEoBRImCgdwYXlsb2FkGAMgASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxv", + "YWQSFQoNZmlsbF91c2VybmFtZRgEIAEoCBIYChBmaWxsX29hdXRoX3Njb3Bl", + "GAUgASgIIl8KDlNpbXBsZVJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5n", + "cnBjLnRlc3RpbmcuUGF5bG9hZBIQCgh1c2VybmFtZRgCIAEoCRITCgtvYXV0", + "aF9zY29wZRgDIAEoCSJDChlTdHJlYW1pbmdJbnB1dENhbGxSZXF1ZXN0EiYK", + "B3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3RpbmcuUGF5bG9hZCI9ChpTdHJl", + "YW1pbmdJbnB1dENhbGxSZXNwb25zZRIfChdhZ2dyZWdhdGVkX3BheWxvYWRf", + "c2l6ZRgBIAEoBSI3ChJSZXNwb25zZVBhcmFtZXRlcnMSDAoEc2l6ZRgBIAEo", + "BRITCgtpbnRlcnZhbF91cxgCIAEoBSK1AQoaU3RyZWFtaW5nT3V0cHV0Q2Fs", + "bFJlcXVlc3QSMAoNcmVzcG9uc2VfdHlwZRgBIAEoDjIZLmdycGMudGVzdGlu", + "Zy5QYXlsb2FkVHlwZRI9ChNyZXNwb25zZV9wYXJhbWV0ZXJzGAIgAygLMiAu", + "Z3JwYy50ZXN0aW5nLlJlc3BvbnNlUGFyYW1ldGVycxImCgdwYXlsb2FkGAMg", + "ASgLMhUuZ3JwYy50ZXN0aW5nLlBheWxvYWQiRQobU3RyZWFtaW5nT3V0cHV0", + "Q2FsbFJlc3BvbnNlEiYKB3BheWxvYWQYASABKAsyFS5ncnBjLnRlc3Rpbmcu", + "UGF5bG9hZCo/CgtQYXlsb2FkVHlwZRIQCgxDT01QUkVTU0FCTEUQABISCg5V", + "TkNPTVBSRVNTQUJMRRABEgoKBlJBTkRPTRACYgZwcm90bzM=")); + descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + new pbr::FileDescriptor[] { }, + new pbr::GeneratedCodeInfo(new[] {typeof(global::Grpc.Testing.PayloadType), }, new pbr::GeneratedCodeInfo[] { + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.Payload), new[]{ "Type", "Body" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleRequest), new[]{ "ResponseType", "ResponseSize", "Payload", "FillUsername", "FillOauthScope" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.SimpleResponse), new[]{ "Payload", "Username", "OauthScope" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallRequest), new[]{ "Payload" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingInputCallResponse), new[]{ "AggregatedPayloadSize" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.ResponseParameters), new[]{ "Size", "IntervalUs" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallRequest), new[]{ "ResponseType", "ResponseParameters", "Payload" }, null, null, null), + new pbr::GeneratedCodeInfo(typeof(global::Grpc.Testing.StreamingOutputCallResponse), new[]{ "Payload" }, null, null, null) + })); } #endregion @@ -116,2772 +68,1101 @@ namespace grpc.testing { #region Messages [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Payload : pb::GeneratedMessage<Payload, Payload.Builder> { - private Payload() { } - private static readonly Payload defaultInstance = new Payload().MakeReadOnly(); - private static readonly string[] _payloadFieldNames = new string[] { "body", "type" }; - private static readonly uint[] _payloadFieldTags = new uint[] { 18, 8 }; - public static Payload DefaultInstance { - get { return defaultInstance; } + public sealed partial class Payload : pb::IMessage<Payload> { + private static readonly pb::MessageParser<Payload> _parser = new pb::MessageParser<Payload>(() => new Payload()); + public static pb::MessageParser<Payload> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[0]; } } - public override Payload DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override Payload ThisMessage { - get { return this; } + public Payload() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_Payload__Descriptor; } + partial void OnConstruction(); + + public Payload(Payload other) : this() { + type_ = other.type_; + body_ = other.body_; } - protected override pb::FieldAccess.FieldAccessorTable<Payload, Payload.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_Payload__FieldAccessorTable; } + public Payload Clone() { + return new Payload(this); } public const int TypeFieldNumber = 1; - private bool hasType; - private global::grpc.testing.PayloadType type_ = global::grpc.testing.PayloadType.COMPRESSABLE; - public bool HasType { - get { return hasType; } - } - public global::grpc.testing.PayloadType Type { + private global::Grpc.Testing.PayloadType type_ = global::Grpc.Testing.PayloadType.COMPRESSABLE; + public global::Grpc.Testing.PayloadType Type { get { return type_; } + set { + type_ = value; + } } public const int BodyFieldNumber = 2; - private bool hasBody; private pb::ByteString body_ = pb::ByteString.Empty; - public bool HasBody { - get { return hasBody; } - } public pb::ByteString Body { get { return body_; } - } - - public override bool IsInitialized { - get { - return true; + set { + body_ = pb::Preconditions.CheckNotNull(value, "value"); } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _payloadFieldNames; - if (hasType) { - output.WriteEnum(1, field_names[1], (int) Type, Type); - } - if (hasBody) { - output.WriteBytes(2, field_names[0], Body); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as Payload); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasType) { - size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Type); - } - if (hasBody) { - size += pb::CodedOutputStream.ComputeBytesSize(2, Body); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(Payload other) { + if (ReferenceEquals(other, null)) { + return false; } + if (ReferenceEquals(other, this)) { + return true; + } + if (Type != other.Type) return false; + if (Body != other.Body) return false; + return true; } - public static Payload ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static Payload ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static Payload ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static Payload ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static Payload ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static Payload ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static Payload ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static Payload ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static Payload ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static Payload ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private Payload MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= Type.GetHashCode(); + if (Body.Length != 0) hash ^= Body.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(Payload prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<Payload, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(Payload cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private Payload result; - - private Payload PrepareBuilder() { - if (resultIsReadOnly) { - Payload original = result; - result = new Payload(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; + public void WriteTo(pb::CodedOutputStream output) { + if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + output.WriteRawTag(8); + output.WriteEnum((int) Type); } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override Payload MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; + if (Body.Length != 0) { + output.WriteRawTag(18); + output.WriteBytes(Body); } + } - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } + public int CalculateSize() { + int size = 0; + if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Type); } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.Payload.Descriptor; } + if (Body.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeBytesSize(Body); } + return size; + } - public override Payload DefaultInstanceForType { - get { return global::grpc.testing.Payload.DefaultInstance; } + public void MergeFrom(Payload other) { + if (other == null) { + return; } - - public override Payload BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + if (other.Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + Type = other.Type; } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is Payload) { - return MergeFrom((Payload) other); - } else { - base.MergeFrom(other); - return this; - } + if (other.Body.Length != 0) { + Body = other.Body; } + } - public override Builder MergeFrom(Payload other) { - if (other == global::grpc.testing.Payload.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasType) { - Type = other.Type; - } - if (other.HasBody) { - Body = other.Body; - } - this.MergeUnknownFields(other.UnknownFields); - return this; - } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); - } - - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_payloadFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _payloadFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + type_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - object unknown; - if(input.ReadEnum(ref result.type_, out unknown)) { - result.hasType = true; - } else if(unknown is int) { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - unknownFields.MergeVarintField(1, (ulong)(int)unknown); - } - break; - } - case 18: { - result.hasBody = input.ReadBytes(ref result.body_); - break; - } + case 18: { + Body = input.ReadBytes(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasType { - get { return result.hasType; } - } - public global::grpc.testing.PayloadType Type { - get { return result.Type; } - set { SetType(value); } - } - public Builder SetType(global::grpc.testing.PayloadType value) { - PrepareBuilder(); - result.hasType = true; - result.type_ = value; - return this; - } - public Builder ClearType() { - PrepareBuilder(); - result.hasType = false; - result.type_ = global::grpc.testing.PayloadType.COMPRESSABLE; - return this; - } - - public bool HasBody { - get { return result.hasBody; } - } - public pb::ByteString Body { - get { return result.Body; } - set { SetBody(value); } } - public Builder SetBody(pb::ByteString value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasBody = true; - result.body_ = value; - return this; - } - public Builder ClearBody() { - PrepareBuilder(); - result.hasBody = false; - result.body_ = pb::ByteString.Empty; - return this; - } - } - static Payload() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class SimpleRequest : pb::GeneratedMessage<SimpleRequest, SimpleRequest.Builder> { - private SimpleRequest() { } - private static readonly SimpleRequest defaultInstance = new SimpleRequest().MakeReadOnly(); - private static readonly string[] _simpleRequestFieldNames = new string[] { "fill_oauth_scope", "fill_username", "payload", "response_size", "response_type" }; - private static readonly uint[] _simpleRequestFieldTags = new uint[] { 40, 32, 26, 16, 8 }; - public static SimpleRequest DefaultInstance { - get { return defaultInstance; } + public sealed partial class SimpleRequest : pb::IMessage<SimpleRequest> { + private static readonly pb::MessageParser<SimpleRequest> _parser = new pb::MessageParser<SimpleRequest>(() => new SimpleRequest()); + public static pb::MessageParser<SimpleRequest> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[1]; } } - public override SimpleRequest DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override SimpleRequest ThisMessage { - get { return this; } + public SimpleRequest() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_SimpleRequest__Descriptor; } + partial void OnConstruction(); + + public SimpleRequest(SimpleRequest other) : this() { + responseType_ = other.responseType_; + responseSize_ = other.responseSize_; + Payload = other.payload_ != null ? other.Payload.Clone() : null; + fillUsername_ = other.fillUsername_; + fillOauthScope_ = other.fillOauthScope_; } - protected override pb::FieldAccess.FieldAccessorTable<SimpleRequest, SimpleRequest.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_SimpleRequest__FieldAccessorTable; } + public SimpleRequest Clone() { + return new SimpleRequest(this); } public const int ResponseTypeFieldNumber = 1; - private bool hasResponseType; - private global::grpc.testing.PayloadType responseType_ = global::grpc.testing.PayloadType.COMPRESSABLE; - public bool HasResponseType { - get { return hasResponseType; } - } - public global::grpc.testing.PayloadType ResponseType { + private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.COMPRESSABLE; + public global::Grpc.Testing.PayloadType ResponseType { get { return responseType_; } + set { + responseType_ = value; + } } public const int ResponseSizeFieldNumber = 2; - private bool hasResponseSize; private int responseSize_; - public bool HasResponseSize { - get { return hasResponseSize; } - } public int ResponseSize { get { return responseSize_; } + set { + responseSize_ = value; + } } public const int PayloadFieldNumber = 3; - private bool hasPayload; - private global::grpc.testing.Payload payload_; - public bool HasPayload { - get { return hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; } + private global::Grpc.Testing.Payload payload_; + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; + } } public const int FillUsernameFieldNumber = 4; - private bool hasFillUsername; private bool fillUsername_; - public bool HasFillUsername { - get { return hasFillUsername; } - } public bool FillUsername { get { return fillUsername_; } + set { + fillUsername_ = value; + } } public const int FillOauthScopeFieldNumber = 5; - private bool hasFillOauthScope; private bool fillOauthScope_; - public bool HasFillOauthScope { - get { return hasFillOauthScope; } - } public bool FillOauthScope { get { return fillOauthScope_; } + set { + fillOauthScope_ = value; + } } - public override bool IsInitialized { - get { - return true; - } + public override bool Equals(object other) { + return Equals(other as SimpleRequest); } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _simpleRequestFieldNames; - if (hasResponseType) { - output.WriteEnum(1, field_names[4], (int) ResponseType, ResponseType); - } - if (hasResponseSize) { - output.WriteInt32(2, field_names[3], ResponseSize); - } - if (hasPayload) { - output.WriteMessage(3, field_names[2], Payload); - } - if (hasFillUsername) { - output.WriteBool(4, field_names[1], FillUsername); + public bool Equals(SimpleRequest other) { + if (ReferenceEquals(other, null)) { + return false; } - if (hasFillOauthScope) { - output.WriteBool(5, field_names[0], FillOauthScope); + if (ReferenceEquals(other, this)) { + return true; } - UnknownFields.WriteTo(output); + if (ResponseType != other.ResponseType) return false; + if (ResponseSize != other.ResponseSize) return false; + if (!object.Equals(Payload, other.Payload)) return false; + if (FillUsername != other.FillUsername) return false; + if (FillOauthScope != other.FillOauthScope) return false; + return true; } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasResponseType) { - size += pb::CodedOutputStream.ComputeEnumSize(1, (int) ResponseType); - } - if (hasResponseSize) { - size += pb::CodedOutputStream.ComputeInt32Size(2, ResponseSize); - } - if (hasPayload) { - size += pb::CodedOutputStream.ComputeMessageSize(3, Payload); - } - if (hasFillUsername) { - size += pb::CodedOutputStream.ComputeBoolSize(4, FillUsername); - } - if (hasFillOauthScope) { - size += pb::CodedOutputStream.ComputeBoolSize(5, FillOauthScope); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; - } + public override int GetHashCode() { + int hash = 1; + if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= ResponseType.GetHashCode(); + if (ResponseSize != 0) hash ^= ResponseSize.GetHashCode(); + if (payload_ != null) hash ^= Payload.GetHashCode(); + if (FillUsername != false) hash ^= FillUsername.GetHashCode(); + if (FillOauthScope != false) hash ^= FillOauthScope.GetHashCode(); + return hash; } - public static SimpleRequest ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static SimpleRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static SimpleRequest ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static SimpleRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static SimpleRequest ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static SimpleRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static SimpleRequest ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static SimpleRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static SimpleRequest ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static SimpleRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private SimpleRequest MakeReadOnly() { - return this; - } - - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(SimpleRequest prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<SimpleRequest, Builder> { - protected override Builder ThisBuilder { - get { return this; } + public void WriteTo(pb::CodedOutputStream output) { + if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + output.WriteRawTag(8); + output.WriteEnum((int) ResponseType); } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; + if (ResponseSize != 0) { + output.WriteRawTag(16); + output.WriteInt32(ResponseSize); } - internal Builder(SimpleRequest cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; + if (payload_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Payload); } - - private bool resultIsReadOnly; - private SimpleRequest result; - - private SimpleRequest PrepareBuilder() { - if (resultIsReadOnly) { - SimpleRequest original = result; - result = new SimpleRequest(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; + if (FillUsername != false) { + output.WriteRawTag(32); + output.WriteBool(FillUsername); } - - public override bool IsInitialized { - get { return result.IsInitialized; } + if (FillOauthScope != false) { + output.WriteRawTag(40); + output.WriteBool(FillOauthScope); } + } - protected override SimpleRequest MessageBeingBuilt { - get { return PrepareBuilder(); } + public int CalculateSize() { + int size = 0; + if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType); } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; + if (ResponseSize != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(ResponseSize); } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.SimpleRequest.Descriptor; } + if (FillUsername != false) { + size += 1 + 1; } - - public override SimpleRequest DefaultInstanceForType { - get { return global::grpc.testing.SimpleRequest.DefaultInstance; } + if (FillOauthScope != false) { + size += 1 + 1; } + return size; + } - public override SimpleRequest BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public void MergeFrom(SimpleRequest other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is SimpleRequest) { - return MergeFrom((SimpleRequest) other); - } else { - base.MergeFrom(other); - return this; + if (other.ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + ResponseType = other.ResponseType; + } + if (other.ResponseSize != 0) { + ResponseSize = other.ResponseSize; + } + if (other.payload_ != null) { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + Payload.MergeFrom(other.Payload); + } + if (other.FillUsername != false) { + FillUsername = other.FillUsername; } + if (other.FillOauthScope != false) { + FillOauthScope = other.FillOauthScope; + } + } - public override Builder MergeFrom(SimpleRequest other) { - if (other == global::grpc.testing.SimpleRequest.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasResponseType) { - ResponseType = other.ResponseType; - } - if (other.HasResponseSize) { - ResponseSize = other.ResponseSize; - } - if (other.HasPayload) { - MergePayload(other.Payload); - } - if (other.HasFillUsername) { - FillUsername = other.FillUsername; - } - if (other.HasFillOauthScope) { - FillOauthScope = other.FillOauthScope; - } - this.MergeUnknownFields(other.UnknownFields); - return this; - } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); - } - - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_simpleRequestFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _simpleRequestFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - object unknown; - if(input.ReadEnum(ref result.responseType_, out unknown)) { - result.hasResponseType = true; - } else if(unknown is int) { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - unknownFields.MergeVarintField(1, (ulong)(int)unknown); - } - break; - } - case 16: { - result.hasResponseSize = input.ReadInt32(ref result.responseSize_); - break; - } - case 26: { - global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder(); - if (result.hasPayload) { - subBuilder.MergeFrom(Payload); - } - input.ReadMessage(subBuilder, extensionRegistry); - Payload = subBuilder.BuildPartial(); - break; - } - case 32: { - result.hasFillUsername = input.ReadBool(ref result.fillUsername_); - break; - } - case 40: { - result.hasFillOauthScope = input.ReadBool(ref result.fillOauthScope_); - break; + case 16: { + ResponseSize = input.ReadInt32(); + break; + } + case 26: { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + input.ReadMessage(payload_); + break; + } + case 32: { + FillUsername = input.ReadBool(); + break; + } + case 40: { + FillOauthScope = input.ReadBool(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasResponseType { - get { return result.hasResponseType; } - } - public global::grpc.testing.PayloadType ResponseType { - get { return result.ResponseType; } - set { SetResponseType(value); } - } - public Builder SetResponseType(global::grpc.testing.PayloadType value) { - PrepareBuilder(); - result.hasResponseType = true; - result.responseType_ = value; - return this; - } - public Builder ClearResponseType() { - PrepareBuilder(); - result.hasResponseType = false; - result.responseType_ = global::grpc.testing.PayloadType.COMPRESSABLE; - return this; - } - - public bool HasResponseSize { - get { return result.hasResponseSize; } - } - public int ResponseSize { - get { return result.ResponseSize; } - set { SetResponseSize(value); } - } - public Builder SetResponseSize(int value) { - PrepareBuilder(); - result.hasResponseSize = true; - result.responseSize_ = value; - return this; - } - public Builder ClearResponseSize() { - PrepareBuilder(); - result.hasResponseSize = false; - result.responseSize_ = 0; - return this; - } - - public bool HasPayload { - get { return result.hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return result.Payload; } - set { SetPayload(value); } - } - public Builder SetPayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = value; - return this; - } - public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) { - pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = builderForValue.Build(); - return this; - } - public Builder MergePayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - if (result.hasPayload && - result.payload_ != global::grpc.testing.Payload.DefaultInstance) { - result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial(); - } else { - result.payload_ = value; - } - result.hasPayload = true; - return this; - } - public Builder ClearPayload() { - PrepareBuilder(); - result.hasPayload = false; - result.payload_ = null; - return this; - } - - public bool HasFillUsername { - get { return result.hasFillUsername; } - } - public bool FillUsername { - get { return result.FillUsername; } - set { SetFillUsername(value); } - } - public Builder SetFillUsername(bool value) { - PrepareBuilder(); - result.hasFillUsername = true; - result.fillUsername_ = value; - return this; - } - public Builder ClearFillUsername() { - PrepareBuilder(); - result.hasFillUsername = false; - result.fillUsername_ = false; - return this; - } - - public bool HasFillOauthScope { - get { return result.hasFillOauthScope; } - } - public bool FillOauthScope { - get { return result.FillOauthScope; } - set { SetFillOauthScope(value); } - } - public Builder SetFillOauthScope(bool value) { - PrepareBuilder(); - result.hasFillOauthScope = true; - result.fillOauthScope_ = value; - return this; - } - public Builder ClearFillOauthScope() { - PrepareBuilder(); - result.hasFillOauthScope = false; - result.fillOauthScope_ = false; - return this; } } - static SimpleRequest() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); - } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class SimpleResponse : pb::GeneratedMessage<SimpleResponse, SimpleResponse.Builder> { - private SimpleResponse() { } - private static readonly SimpleResponse defaultInstance = new SimpleResponse().MakeReadOnly(); - private static readonly string[] _simpleResponseFieldNames = new string[] { "oauth_scope", "payload", "username" }; - private static readonly uint[] _simpleResponseFieldTags = new uint[] { 26, 10, 18 }; - public static SimpleResponse DefaultInstance { - get { return defaultInstance; } + public sealed partial class SimpleResponse : pb::IMessage<SimpleResponse> { + private static readonly pb::MessageParser<SimpleResponse> _parser = new pb::MessageParser<SimpleResponse>(() => new SimpleResponse()); + public static pb::MessageParser<SimpleResponse> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[2]; } } - public override SimpleResponse DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override SimpleResponse ThisMessage { - get { return this; } + public SimpleResponse() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_SimpleResponse__Descriptor; } + partial void OnConstruction(); + + public SimpleResponse(SimpleResponse other) : this() { + Payload = other.payload_ != null ? other.Payload.Clone() : null; + username_ = other.username_; + oauthScope_ = other.oauthScope_; } - protected override pb::FieldAccess.FieldAccessorTable<SimpleResponse, SimpleResponse.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_SimpleResponse__FieldAccessorTable; } + public SimpleResponse Clone() { + return new SimpleResponse(this); } public const int PayloadFieldNumber = 1; - private bool hasPayload; - private global::grpc.testing.Payload payload_; - public bool HasPayload { - get { return hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; } + private global::Grpc.Testing.Payload payload_; + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; + } } public const int UsernameFieldNumber = 2; - private bool hasUsername; private string username_ = ""; - public bool HasUsername { - get { return hasUsername; } - } public string Username { get { return username_; } + set { + username_ = pb::Preconditions.CheckNotNull(value, "value"); + } } public const int OauthScopeFieldNumber = 3; - private bool hasOauthScope; private string oauthScope_ = ""; - public bool HasOauthScope { - get { return hasOauthScope; } - } public string OauthScope { get { return oauthScope_; } - } - - public override bool IsInitialized { - get { - return true; + set { + oauthScope_ = pb::Preconditions.CheckNotNull(value, "value"); } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _simpleResponseFieldNames; - if (hasPayload) { - output.WriteMessage(1, field_names[1], Payload); - } - if (hasUsername) { - output.WriteString(2, field_names[2], Username); - } - if (hasOauthScope) { - output.WriteString(3, field_names[0], OauthScope); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as SimpleResponse); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasPayload) { - size += pb::CodedOutputStream.ComputeMessageSize(1, Payload); - } - if (hasUsername) { - size += pb::CodedOutputStream.ComputeStringSize(2, Username); - } - if (hasOauthScope) { - size += pb::CodedOutputStream.ComputeStringSize(3, OauthScope); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(SimpleResponse other) { + if (ReferenceEquals(other, null)) { + return false; } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Payload, other.Payload)) return false; + if (Username != other.Username) return false; + if (OauthScope != other.OauthScope) return false; + return true; } - public static SimpleResponse ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static SimpleResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static SimpleResponse ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static SimpleResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static SimpleResponse ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static SimpleResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static SimpleResponse ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static SimpleResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static SimpleResponse ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static SimpleResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private SimpleResponse MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (payload_ != null) hash ^= Payload.GetHashCode(); + if (Username.Length != 0) hash ^= Username.GetHashCode(); + if (OauthScope.Length != 0) hash ^= OauthScope.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(SimpleResponse prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<SimpleResponse, Builder> { - protected override Builder ThisBuilder { - get { return this; } + public void WriteTo(pb::CodedOutputStream output) { + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; + if (Username.Length != 0) { + output.WriteRawTag(18); + output.WriteString(Username); } - internal Builder(SimpleResponse cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; + if (OauthScope.Length != 0) { + output.WriteRawTag(26); + output.WriteString(OauthScope); } + } - private bool resultIsReadOnly; - private SimpleResponse result; - - private SimpleResponse PrepareBuilder() { - if (resultIsReadOnly) { - SimpleResponse original = result; - result = new SimpleResponse(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; + public int CalculateSize() { + int size = 0; + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } - - public override bool IsInitialized { - get { return result.IsInitialized; } + if (Username.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Username); } - - protected override SimpleResponse MessageBeingBuilt { - get { return PrepareBuilder(); } + if (OauthScope.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(OauthScope); } + return size; + } - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; + public void MergeFrom(SimpleResponse other) { + if (other == null) { + return; } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); + if (other.payload_ != null) { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + Payload.MergeFrom(other.Payload); } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.SimpleResponse.Descriptor; } - } - - public override SimpleResponse DefaultInstanceForType { - get { return global::grpc.testing.SimpleResponse.DefaultInstance; } + if (other.Username.Length != 0) { + Username = other.Username; } - - public override SimpleResponse BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); - } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is SimpleResponse) { - return MergeFrom((SimpleResponse) other); - } else { - base.MergeFrom(other); - return this; - } + if (other.OauthScope.Length != 0) { + OauthScope = other.OauthScope; } + } - public override Builder MergeFrom(SimpleResponse other) { - if (other == global::grpc.testing.SimpleResponse.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasPayload) { - MergePayload(other.Payload); - } - if (other.HasUsername) { - Username = other.Username; - } - if (other.HasOauthScope) { - OauthScope = other.OauthScope; - } - this.MergeUnknownFields(other.UnknownFields); - return this; - } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); - } - - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_simpleResponseFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _simpleResponseFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + input.ReadMessage(payload_); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 10: { - global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder(); - if (result.hasPayload) { - subBuilder.MergeFrom(Payload); - } - input.ReadMessage(subBuilder, extensionRegistry); - Payload = subBuilder.BuildPartial(); - break; - } - case 18: { - result.hasUsername = input.ReadString(ref result.username_); - break; - } - case 26: { - result.hasOauthScope = input.ReadString(ref result.oauthScope_); - break; - } + case 18: { + Username = input.ReadString(); + break; + } + case 26: { + OauthScope = input.ReadString(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasPayload { - get { return result.hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return result.Payload; } - set { SetPayload(value); } - } - public Builder SetPayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = value; - return this; - } - public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) { - pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = builderForValue.Build(); - return this; - } - public Builder MergePayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - if (result.hasPayload && - result.payload_ != global::grpc.testing.Payload.DefaultInstance) { - result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial(); - } else { - result.payload_ = value; - } - result.hasPayload = true; - return this; - } - public Builder ClearPayload() { - PrepareBuilder(); - result.hasPayload = false; - result.payload_ = null; - return this; - } - - public bool HasUsername { - get { return result.hasUsername; } - } - public string Username { - get { return result.Username; } - set { SetUsername(value); } - } - public Builder SetUsername(string value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasUsername = true; - result.username_ = value; - return this; - } - public Builder ClearUsername() { - PrepareBuilder(); - result.hasUsername = false; - result.username_ = ""; - return this; - } - - public bool HasOauthScope { - get { return result.hasOauthScope; } - } - public string OauthScope { - get { return result.OauthScope; } - set { SetOauthScope(value); } - } - public Builder SetOauthScope(string value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasOauthScope = true; - result.oauthScope_ = value; - return this; - } - public Builder ClearOauthScope() { - PrepareBuilder(); - result.hasOauthScope = false; - result.oauthScope_ = ""; - return this; } } - static SimpleResponse() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); - } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class StreamingInputCallRequest : pb::GeneratedMessage<StreamingInputCallRequest, StreamingInputCallRequest.Builder> { - private StreamingInputCallRequest() { } - private static readonly StreamingInputCallRequest defaultInstance = new StreamingInputCallRequest().MakeReadOnly(); - private static readonly string[] _streamingInputCallRequestFieldNames = new string[] { "payload" }; - private static readonly uint[] _streamingInputCallRequestFieldTags = new uint[] { 10 }; - public static StreamingInputCallRequest DefaultInstance { - get { return defaultInstance; } - } + public sealed partial class StreamingInputCallRequest : pb::IMessage<StreamingInputCallRequest> { + private static readonly pb::MessageParser<StreamingInputCallRequest> _parser = new pb::MessageParser<StreamingInputCallRequest>(() => new StreamingInputCallRequest()); + public static pb::MessageParser<StreamingInputCallRequest> Parser { get { return _parser; } } - public override StreamingInputCallRequest DefaultInstanceForType { - get { return DefaultInstance; } + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[3]; } } - protected override StreamingInputCallRequest ThisMessage { - get { return this; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallRequest__Descriptor; } + public StreamingInputCallRequest() { + OnConstruction(); } - protected override pb::FieldAccess.FieldAccessorTable<StreamingInputCallRequest, StreamingInputCallRequest.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallRequest__FieldAccessorTable; } - } + partial void OnConstruction(); - public const int PayloadFieldNumber = 1; - private bool hasPayload; - private global::grpc.testing.Payload payload_; - public bool HasPayload { - get { return hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; } + public StreamingInputCallRequest(StreamingInputCallRequest other) : this() { + Payload = other.payload_ != null ? other.Payload.Clone() : null; } - public override bool IsInitialized { - get { - return true; - } + public StreamingInputCallRequest Clone() { + return new StreamingInputCallRequest(this); } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _streamingInputCallRequestFieldNames; - if (hasPayload) { - output.WriteMessage(1, field_names[0], Payload); + public const int PayloadFieldNumber = 1; + private global::Grpc.Testing.Payload payload_; + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; } - UnknownFields.WriteTo(output); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; + public override bool Equals(object other) { + return Equals(other as StreamingInputCallRequest); + } - size = 0; - if (hasPayload) { - size += pb::CodedOutputStream.ComputeMessageSize(1, Payload); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(StreamingInputCallRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; } + if (!object.Equals(Payload, other.Payload)) return false; + return true; } - public static StreamingInputCallRequest ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static StreamingInputCallRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static StreamingInputCallRequest ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static StreamingInputCallRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static StreamingInputCallRequest ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static StreamingInputCallRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static StreamingInputCallRequest ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static StreamingInputCallRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static StreamingInputCallRequest ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static StreamingInputCallRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private StreamingInputCallRequest MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (payload_ != null) hash ^= Payload.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(StreamingInputCallRequest prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<StreamingInputCallRequest, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(StreamingInputCallRequest cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private StreamingInputCallRequest result; - - private StreamingInputCallRequest PrepareBuilder() { - if (resultIsReadOnly) { - StreamingInputCallRequest original = result; - result = new StreamingInputCallRequest(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override StreamingInputCallRequest MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.StreamingInputCallRequest.Descriptor; } + public void WriteTo(pb::CodedOutputStream output) { + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); } + } - public override StreamingInputCallRequest DefaultInstanceForType { - get { return global::grpc.testing.StreamingInputCallRequest.DefaultInstance; } + public int CalculateSize() { + int size = 0; + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } + return size; + } - public override StreamingInputCallRequest BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public void MergeFrom(StreamingInputCallRequest other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is StreamingInputCallRequest) { - return MergeFrom((StreamingInputCallRequest) other); - } else { - base.MergeFrom(other); - return this; + if (other.payload_ != null) { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + Payload.MergeFrom(other.Payload); } + } - public override Builder MergeFrom(StreamingInputCallRequest other) { - if (other == global::grpc.testing.StreamingInputCallRequest.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasPayload) { - MergePayload(other.Payload); - } - this.MergeUnknownFields(other.UnknownFields); - return this; - } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); - } - - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_streamingInputCallRequestFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _streamingInputCallRequestFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + input.ReadMessage(payload_); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 10: { - global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder(); - if (result.hasPayload) { - subBuilder.MergeFrom(Payload); - } - input.ReadMessage(subBuilder, extensionRegistry); - Payload = subBuilder.BuildPartial(); - break; - } - } - } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasPayload { - get { return result.hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return result.Payload; } - set { SetPayload(value); } - } - public Builder SetPayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = value; - return this; - } - public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) { - pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = builderForValue.Build(); - return this; - } - public Builder MergePayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - if (result.hasPayload && - result.payload_ != global::grpc.testing.Payload.DefaultInstance) { - result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial(); - } else { - result.payload_ = value; } - result.hasPayload = true; - return this; } - public Builder ClearPayload() { - PrepareBuilder(); - result.hasPayload = false; - result.payload_ = null; - return this; - } - } - static StreamingInputCallRequest() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class StreamingInputCallResponse : pb::GeneratedMessage<StreamingInputCallResponse, StreamingInputCallResponse.Builder> { - private StreamingInputCallResponse() { } - private static readonly StreamingInputCallResponse defaultInstance = new StreamingInputCallResponse().MakeReadOnly(); - private static readonly string[] _streamingInputCallResponseFieldNames = new string[] { "aggregated_payload_size" }; - private static readonly uint[] _streamingInputCallResponseFieldTags = new uint[] { 8 }; - public static StreamingInputCallResponse DefaultInstance { - get { return defaultInstance; } + public sealed partial class StreamingInputCallResponse : pb::IMessage<StreamingInputCallResponse> { + private static readonly pb::MessageParser<StreamingInputCallResponse> _parser = new pb::MessageParser<StreamingInputCallResponse>(() => new StreamingInputCallResponse()); + public static pb::MessageParser<StreamingInputCallResponse> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[4]; } } - public override StreamingInputCallResponse DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override StreamingInputCallResponse ThisMessage { - get { return this; } + public StreamingInputCallResponse() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallResponse__Descriptor; } + partial void OnConstruction(); + + public StreamingInputCallResponse(StreamingInputCallResponse other) : this() { + aggregatedPayloadSize_ = other.aggregatedPayloadSize_; } - protected override pb::FieldAccess.FieldAccessorTable<StreamingInputCallResponse, StreamingInputCallResponse.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallResponse__FieldAccessorTable; } + public StreamingInputCallResponse Clone() { + return new StreamingInputCallResponse(this); } public const int AggregatedPayloadSizeFieldNumber = 1; - private bool hasAggregatedPayloadSize; private int aggregatedPayloadSize_; - public bool HasAggregatedPayloadSize { - get { return hasAggregatedPayloadSize; } - } public int AggregatedPayloadSize { get { return aggregatedPayloadSize_; } - } - - public override bool IsInitialized { - get { - return true; + set { + aggregatedPayloadSize_ = value; } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _streamingInputCallResponseFieldNames; - if (hasAggregatedPayloadSize) { - output.WriteInt32(1, field_names[0], AggregatedPayloadSize); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as StreamingInputCallResponse); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasAggregatedPayloadSize) { - size += pb::CodedOutputStream.ComputeInt32Size(1, AggregatedPayloadSize); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(StreamingInputCallResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; } + if (AggregatedPayloadSize != other.AggregatedPayloadSize) return false; + return true; } - public static StreamingInputCallResponse ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static StreamingInputCallResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static StreamingInputCallResponse ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static StreamingInputCallResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static StreamingInputCallResponse ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static StreamingInputCallResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static StreamingInputCallResponse ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static StreamingInputCallResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static StreamingInputCallResponse ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static StreamingInputCallResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private StreamingInputCallResponse MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (AggregatedPayloadSize != 0) hash ^= AggregatedPayloadSize.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(StreamingInputCallResponse prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<StreamingInputCallResponse, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(StreamingInputCallResponse cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private StreamingInputCallResponse result; - - private StreamingInputCallResponse PrepareBuilder() { - if (resultIsReadOnly) { - StreamingInputCallResponse original = result; - result = new StreamingInputCallResponse(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override StreamingInputCallResponse MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.StreamingInputCallResponse.Descriptor; } + public void WriteTo(pb::CodedOutputStream output) { + if (AggregatedPayloadSize != 0) { + output.WriteRawTag(8); + output.WriteInt32(AggregatedPayloadSize); } + } - public override StreamingInputCallResponse DefaultInstanceForType { - get { return global::grpc.testing.StreamingInputCallResponse.DefaultInstance; } + public int CalculateSize() { + int size = 0; + if (AggregatedPayloadSize != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(AggregatedPayloadSize); } + return size; + } - public override StreamingInputCallResponse BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public void MergeFrom(StreamingInputCallResponse other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is StreamingInputCallResponse) { - return MergeFrom((StreamingInputCallResponse) other); - } else { - base.MergeFrom(other); - return this; - } + if (other.AggregatedPayloadSize != 0) { + AggregatedPayloadSize = other.AggregatedPayloadSize; } + } - public override Builder MergeFrom(StreamingInputCallResponse other) { - if (other == global::grpc.testing.StreamingInputCallResponse.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasAggregatedPayloadSize) { - AggregatedPayloadSize = other.AggregatedPayloadSize; - } - this.MergeUnknownFields(other.UnknownFields); - return this; - } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); - } - - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_streamingInputCallResponseFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _streamingInputCallResponseFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } - } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - result.hasAggregatedPayloadSize = input.ReadInt32(ref result.aggregatedPayloadSize_); - break; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + AggregatedPayloadSize = input.ReadInt32(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasAggregatedPayloadSize { - get { return result.hasAggregatedPayloadSize; } - } - public int AggregatedPayloadSize { - get { return result.AggregatedPayloadSize; } - set { SetAggregatedPayloadSize(value); } - } - public Builder SetAggregatedPayloadSize(int value) { - PrepareBuilder(); - result.hasAggregatedPayloadSize = true; - result.aggregatedPayloadSize_ = value; - return this; } - public Builder ClearAggregatedPayloadSize() { - PrepareBuilder(); - result.hasAggregatedPayloadSize = false; - result.aggregatedPayloadSize_ = 0; - return this; - } - } - static StreamingInputCallResponse() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class ResponseParameters : pb::GeneratedMessage<ResponseParameters, ResponseParameters.Builder> { - private ResponseParameters() { } - private static readonly ResponseParameters defaultInstance = new ResponseParameters().MakeReadOnly(); - private static readonly string[] _responseParametersFieldNames = new string[] { "interval_us", "size" }; - private static readonly uint[] _responseParametersFieldTags = new uint[] { 16, 8 }; - public static ResponseParameters DefaultInstance { - get { return defaultInstance; } + public sealed partial class ResponseParameters : pb::IMessage<ResponseParameters> { + private static readonly pb::MessageParser<ResponseParameters> _parser = new pb::MessageParser<ResponseParameters>(() => new ResponseParameters()); + public static pb::MessageParser<ResponseParameters> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[5]; } } - public override ResponseParameters DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override ResponseParameters ThisMessage { - get { return this; } + public ResponseParameters() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_ResponseParameters__Descriptor; } + partial void OnConstruction(); + + public ResponseParameters(ResponseParameters other) : this() { + size_ = other.size_; + intervalUs_ = other.intervalUs_; } - protected override pb::FieldAccess.FieldAccessorTable<ResponseParameters, ResponseParameters.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_ResponseParameters__FieldAccessorTable; } + public ResponseParameters Clone() { + return new ResponseParameters(this); } public const int SizeFieldNumber = 1; - private bool hasSize; private int size_; - public bool HasSize { - get { return hasSize; } - } public int Size { get { return size_; } + set { + size_ = value; + } } public const int IntervalUsFieldNumber = 2; - private bool hasIntervalUs; private int intervalUs_; - public bool HasIntervalUs { - get { return hasIntervalUs; } - } public int IntervalUs { get { return intervalUs_; } + set { + intervalUs_ = value; + } } - public override bool IsInitialized { - get { - return true; - } + public override bool Equals(object other) { + return Equals(other as ResponseParameters); } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _responseParametersFieldNames; - if (hasSize) { - output.WriteInt32(1, field_names[1], Size); + public bool Equals(ResponseParameters other) { + if (ReferenceEquals(other, null)) { + return false; } - if (hasIntervalUs) { - output.WriteInt32(2, field_names[0], IntervalUs); + if (ReferenceEquals(other, this)) { + return true; } - UnknownFields.WriteTo(output); + if (Size != other.Size) return false; + if (IntervalUs != other.IntervalUs) return false; + return true; } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasSize) { - size += pb::CodedOutputStream.ComputeInt32Size(1, Size); - } - if (hasIntervalUs) { - size += pb::CodedOutputStream.ComputeInt32Size(2, IntervalUs); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; - } + public override int GetHashCode() { + int hash = 1; + if (Size != 0) hash ^= Size.GetHashCode(); + if (IntervalUs != 0) hash ^= IntervalUs.GetHashCode(); + return hash; } - public static ResponseParameters ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static ResponseParameters ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static ResponseParameters ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static ResponseParameters ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static ResponseParameters ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static ResponseParameters ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static ResponseParameters ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static ResponseParameters ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static ResponseParameters ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - public static ResponseParameters ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private ResponseParameters MakeReadOnly() { - return this; - } - - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(ResponseParameters prototype) { - return new Builder(prototype); - } - - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<ResponseParameters, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(ResponseParameters cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - private bool resultIsReadOnly; - private ResponseParameters result; - - private ResponseParameters PrepareBuilder() { - if (resultIsReadOnly) { - ResponseParameters original = result; - result = new ResponseParameters(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } + public void WriteTo(pb::CodedOutputStream output) { + if (Size != 0) { + output.WriteRawTag(8); + output.WriteInt32(Size); } - - protected override ResponseParameters MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; + if (IntervalUs != 0) { + output.WriteRawTag(16); + output.WriteInt32(IntervalUs); } + } - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } + public int CalculateSize() { + int size = 0; + if (Size != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Size); } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.ResponseParameters.Descriptor; } + if (IntervalUs != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntervalUs); } + return size; + } - public override ResponseParameters DefaultInstanceForType { - get { return global::grpc.testing.ResponseParameters.DefaultInstance; } + public void MergeFrom(ResponseParameters other) { + if (other == null) { + return; } - - public override ResponseParameters BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + if (other.Size != 0) { + Size = other.Size; } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is ResponseParameters) { - return MergeFrom((ResponseParameters) other); - } else { - base.MergeFrom(other); - return this; - } + if (other.IntervalUs != 0) { + IntervalUs = other.IntervalUs; } + } - public override Builder MergeFrom(ResponseParameters other) { - if (other == global::grpc.testing.ResponseParameters.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasSize) { - Size = other.Size; - } - if (other.HasIntervalUs) { - IntervalUs = other.IntervalUs; - } - this.MergeUnknownFields(other.UnknownFields); - return this; - } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); - } - - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_responseParametersFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _responseParametersFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + Size = input.ReadInt32(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - result.hasSize = input.ReadInt32(ref result.size_); - break; - } - case 16: { - result.hasIntervalUs = input.ReadInt32(ref result.intervalUs_); - break; - } + case 16: { + IntervalUs = input.ReadInt32(); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasSize { - get { return result.hasSize; } - } - public int Size { - get { return result.Size; } - set { SetSize(value); } - } - public Builder SetSize(int value) { - PrepareBuilder(); - result.hasSize = true; - result.size_ = value; - return this; - } - public Builder ClearSize() { - PrepareBuilder(); - result.hasSize = false; - result.size_ = 0; - return this; - } - - public bool HasIntervalUs { - get { return result.hasIntervalUs; } } - public int IntervalUs { - get { return result.IntervalUs; } - set { SetIntervalUs(value); } - } - public Builder SetIntervalUs(int value) { - PrepareBuilder(); - result.hasIntervalUs = true; - result.intervalUs_ = value; - return this; - } - public Builder ClearIntervalUs() { - PrepareBuilder(); - result.hasIntervalUs = false; - result.intervalUs_ = 0; - return this; - } - } - static ResponseParameters() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class StreamingOutputCallRequest : pb::GeneratedMessage<StreamingOutputCallRequest, StreamingOutputCallRequest.Builder> { - private StreamingOutputCallRequest() { } - private static readonly StreamingOutputCallRequest defaultInstance = new StreamingOutputCallRequest().MakeReadOnly(); - private static readonly string[] _streamingOutputCallRequestFieldNames = new string[] { "payload", "response_parameters", "response_type" }; - private static readonly uint[] _streamingOutputCallRequestFieldTags = new uint[] { 26, 18, 8 }; - public static StreamingOutputCallRequest DefaultInstance { - get { return defaultInstance; } + public sealed partial class StreamingOutputCallRequest : pb::IMessage<StreamingOutputCallRequest> { + private static readonly pb::MessageParser<StreamingOutputCallRequest> _parser = new pb::MessageParser<StreamingOutputCallRequest>(() => new StreamingOutputCallRequest()); + public static pb::MessageParser<StreamingOutputCallRequest> Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[6]; } } - public override StreamingOutputCallRequest DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override StreamingOutputCallRequest ThisMessage { - get { return this; } + public StreamingOutputCallRequest() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor; } + partial void OnConstruction(); + + public StreamingOutputCallRequest(StreamingOutputCallRequest other) : this() { + responseType_ = other.responseType_; + responseParameters_ = other.responseParameters_.Clone(); + Payload = other.payload_ != null ? other.Payload.Clone() : null; } - protected override pb::FieldAccess.FieldAccessorTable<StreamingOutputCallRequest, StreamingOutputCallRequest.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingOutputCallRequest__FieldAccessorTable; } + public StreamingOutputCallRequest Clone() { + return new StreamingOutputCallRequest(this); } public const int ResponseTypeFieldNumber = 1; - private bool hasResponseType; - private global::grpc.testing.PayloadType responseType_ = global::grpc.testing.PayloadType.COMPRESSABLE; - public bool HasResponseType { - get { return hasResponseType; } - } - public global::grpc.testing.PayloadType ResponseType { + private global::Grpc.Testing.PayloadType responseType_ = global::Grpc.Testing.PayloadType.COMPRESSABLE; + public global::Grpc.Testing.PayloadType ResponseType { get { return responseType_; } + set { + responseType_ = value; + } } public const int ResponseParametersFieldNumber = 2; - private pbc::PopsicleList<global::grpc.testing.ResponseParameters> responseParameters_ = new pbc::PopsicleList<global::grpc.testing.ResponseParameters>(); - public scg::IList<global::grpc.testing.ResponseParameters> ResponseParametersList { + private static readonly pb::FieldCodec<global::Grpc.Testing.ResponseParameters> _repeated_responseParameters_codec + = pb::FieldCodec.ForMessage(18, global::Grpc.Testing.ResponseParameters.Parser); + private readonly pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> responseParameters_ = new pbc::RepeatedField<global::Grpc.Testing.ResponseParameters>(); + public pbc::RepeatedField<global::Grpc.Testing.ResponseParameters> ResponseParameters { get { return responseParameters_; } } - public int ResponseParametersCount { - get { return responseParameters_.Count; } - } - public global::grpc.testing.ResponseParameters GetResponseParameters(int index) { - return responseParameters_[index]; - } public const int PayloadFieldNumber = 3; - private bool hasPayload; - private global::grpc.testing.Payload payload_; - public bool HasPayload { - get { return hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; } - } - - public override bool IsInitialized { - get { - return true; + private global::Grpc.Testing.Payload payload_; + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _streamingOutputCallRequestFieldNames; - if (hasResponseType) { - output.WriteEnum(1, field_names[2], (int) ResponseType, ResponseType); - } - if (responseParameters_.Count > 0) { - output.WriteMessageArray(2, field_names[1], responseParameters_); - } - if (hasPayload) { - output.WriteMessage(3, field_names[0], Payload); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as StreamingOutputCallRequest); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (hasResponseType) { - size += pb::CodedOutputStream.ComputeEnumSize(1, (int) ResponseType); - } - foreach (global::grpc.testing.ResponseParameters element in ResponseParametersList) { - size += pb::CodedOutputStream.ComputeMessageSize(2, element); - } - if (hasPayload) { - size += pb::CodedOutputStream.ComputeMessageSize(3, Payload); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(StreamingOutputCallRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; } + if (ResponseType != other.ResponseType) return false; + if(!responseParameters_.Equals(other.responseParameters_)) return false; + if (!object.Equals(Payload, other.Payload)) return false; + return true; } - public static StreamingOutputCallRequest ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static StreamingOutputCallRequest ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static StreamingOutputCallRequest ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static StreamingOutputCallRequest ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static StreamingOutputCallRequest ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static StreamingOutputCallRequest ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static StreamingOutputCallRequest ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static StreamingOutputCallRequest ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static StreamingOutputCallRequest ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static StreamingOutputCallRequest ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private StreamingOutputCallRequest MakeReadOnly() { - responseParameters_.MakeReadOnly(); - return this; + public override int GetHashCode() { + int hash = 1; + if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) hash ^= ResponseType.GetHashCode(); + hash ^= responseParameters_.GetHashCode(); + if (payload_ != null) hash ^= Payload.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(StreamingOutputCallRequest prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<StreamingOutputCallRequest, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(StreamingOutputCallRequest cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private StreamingOutputCallRequest result; - - private StreamingOutputCallRequest PrepareBuilder() { - if (resultIsReadOnly) { - StreamingOutputCallRequest original = result; - result = new StreamingOutputCallRequest(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; + public void WriteTo(pb::CodedOutputStream output) { + if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + output.WriteRawTag(8); + output.WriteEnum((int) ResponseType); } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override StreamingOutputCallRequest MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; + responseParameters_.WriteTo(output, _repeated_responseParameters_codec); + if (payload_ != null) { + output.WriteRawTag(26); + output.WriteMessage(Payload); } + } - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } + public int CalculateSize() { + int size = 0; + if (ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) ResponseType); } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.StreamingOutputCallRequest.Descriptor; } + size += responseParameters_.CalculateSize(_repeated_responseParameters_codec); + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } + return size; + } - public override StreamingOutputCallRequest DefaultInstanceForType { - get { return global::grpc.testing.StreamingOutputCallRequest.DefaultInstance; } + public void MergeFrom(StreamingOutputCallRequest other) { + if (other == null) { + return; } - - public override StreamingOutputCallRequest BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + if (other.ResponseType != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + ResponseType = other.ResponseType; } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is StreamingOutputCallRequest) { - return MergeFrom((StreamingOutputCallRequest) other); - } else { - base.MergeFrom(other); - return this; + responseParameters_.Add(other.responseParameters_); + if (other.payload_ != null) { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + Payload.MergeFrom(other.Payload); } + } - public override Builder MergeFrom(StreamingOutputCallRequest other) { - if (other == global::grpc.testing.StreamingOutputCallRequest.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasResponseType) { - ResponseType = other.ResponseType; - } - if (other.responseParameters_.Count != 0) { - result.responseParameters_.Add(other.responseParameters_); - } - if (other.HasPayload) { - MergePayload(other.Payload); - } - this.MergeUnknownFields(other.UnknownFields); - return this; - } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); - } - - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_streamingOutputCallRequestFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _streamingOutputCallRequestFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 8: { + responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); + break; } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 8: { - object unknown; - if(input.ReadEnum(ref result.responseType_, out unknown)) { - result.hasResponseType = true; - } else if(unknown is int) { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - unknownFields.MergeVarintField(1, (ulong)(int)unknown); - } - break; - } - case 18: { - input.ReadMessageArray(tag, field_name, result.responseParameters_, global::grpc.testing.ResponseParameters.DefaultInstance, extensionRegistry); - break; - } - case 26: { - global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder(); - if (result.hasPayload) { - subBuilder.MergeFrom(Payload); - } - input.ReadMessage(subBuilder, extensionRegistry); - Payload = subBuilder.BuildPartial(); - break; + case 18: { + responseParameters_.AddEntriesFrom(input, _repeated_responseParameters_codec); + break; + } + case 26: { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + input.ReadMessage(payload_); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasResponseType { - get { return result.hasResponseType; } - } - public global::grpc.testing.PayloadType ResponseType { - get { return result.ResponseType; } - set { SetResponseType(value); } - } - public Builder SetResponseType(global::grpc.testing.PayloadType value) { - PrepareBuilder(); - result.hasResponseType = true; - result.responseType_ = value; - return this; - } - public Builder ClearResponseType() { - PrepareBuilder(); - result.hasResponseType = false; - result.responseType_ = global::grpc.testing.PayloadType.COMPRESSABLE; - return this; - } - - public pbc::IPopsicleList<global::grpc.testing.ResponseParameters> ResponseParametersList { - get { return PrepareBuilder().responseParameters_; } - } - public int ResponseParametersCount { - get { return result.ResponseParametersCount; } - } - public global::grpc.testing.ResponseParameters GetResponseParameters(int index) { - return result.GetResponseParameters(index); - } - public Builder SetResponseParameters(int index, global::grpc.testing.ResponseParameters value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.responseParameters_[index] = value; - return this; - } - public Builder SetResponseParameters(int index, global::grpc.testing.ResponseParameters.Builder builderForValue) { - pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); - PrepareBuilder(); - result.responseParameters_[index] = builderForValue.Build(); - return this; - } - public Builder AddResponseParameters(global::grpc.testing.ResponseParameters value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.responseParameters_.Add(value); - return this; - } - public Builder AddResponseParameters(global::grpc.testing.ResponseParameters.Builder builderForValue) { - pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); - PrepareBuilder(); - result.responseParameters_.Add(builderForValue.Build()); - return this; - } - public Builder AddRangeResponseParameters(scg::IEnumerable<global::grpc.testing.ResponseParameters> values) { - PrepareBuilder(); - result.responseParameters_.Add(values); - return this; - } - public Builder ClearResponseParameters() { - PrepareBuilder(); - result.responseParameters_.Clear(); - return this; - } - - public bool HasPayload { - get { return result.hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return result.Payload; } - set { SetPayload(value); } - } - public Builder SetPayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = value; - return this; - } - public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) { - pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = builderForValue.Build(); - return this; - } - public Builder MergePayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - if (result.hasPayload && - result.payload_ != global::grpc.testing.Payload.DefaultInstance) { - result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial(); - } else { - result.payload_ = value; - } - result.hasPayload = true; - return this; - } - public Builder ClearPayload() { - PrepareBuilder(); - result.hasPayload = false; - result.payload_ = null; - return this; } } - static StreamingOutputCallRequest() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); - } + } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class StreamingOutputCallResponse : pb::GeneratedMessage<StreamingOutputCallResponse, StreamingOutputCallResponse.Builder> { - private StreamingOutputCallResponse() { } - private static readonly StreamingOutputCallResponse defaultInstance = new StreamingOutputCallResponse().MakeReadOnly(); - private static readonly string[] _streamingOutputCallResponseFieldNames = new string[] { "payload" }; - private static readonly uint[] _streamingOutputCallResponseFieldTags = new uint[] { 10 }; - public static StreamingOutputCallResponse DefaultInstance { - get { return defaultInstance; } - } + public sealed partial class StreamingOutputCallResponse : pb::IMessage<StreamingOutputCallResponse> { + private static readonly pb::MessageParser<StreamingOutputCallResponse> _parser = new pb::MessageParser<StreamingOutputCallResponse>(() => new StreamingOutputCallResponse()); + public static pb::MessageParser<StreamingOutputCallResponse> Parser { get { return _parser; } } - public override StreamingOutputCallResponse DefaultInstanceForType { - get { return DefaultInstance; } + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[7]; } } - protected override StreamingOutputCallResponse ThisMessage { - get { return this; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor; } + public StreamingOutputCallResponse() { + OnConstruction(); } - protected override pb::FieldAccess.FieldAccessorTable<StreamingOutputCallResponse, StreamingOutputCallResponse.Builder> InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingOutputCallResponse__FieldAccessorTable; } - } + partial void OnConstruction(); - public const int PayloadFieldNumber = 1; - private bool hasPayload; - private global::grpc.testing.Payload payload_; - public bool HasPayload { - get { return hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; } + public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() { + Payload = other.payload_ != null ? other.Payload.Clone() : null; } - public override bool IsInitialized { - get { - return true; - } + public StreamingOutputCallResponse Clone() { + return new StreamingOutputCallResponse(this); } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _streamingOutputCallResponseFieldNames; - if (hasPayload) { - output.WriteMessage(1, field_names[0], Payload); + public const int PayloadFieldNumber = 1; + private global::Grpc.Testing.Payload payload_; + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; } - UnknownFields.WriteTo(output); } - private int memoizedSerializedSize = -1; - public override int SerializedSize { - get { - int size = memoizedSerializedSize; - if (size != -1) return size; + public override bool Equals(object other) { + return Equals(other as StreamingOutputCallResponse); + } - size = 0; - if (hasPayload) { - size += pb::CodedOutputStream.ComputeMessageSize(1, Payload); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; + public bool Equals(StreamingOutputCallResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; } + if (!object.Equals(Payload, other.Payload)) return false; + return true; } - public static StreamingOutputCallResponse ParseFrom(pb::ByteString data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static StreamingOutputCallResponse ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static StreamingOutputCallResponse ParseFrom(byte[] data) { - return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); - } - public static StreamingOutputCallResponse ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); - } - public static StreamingOutputCallResponse ParseFrom(global::System.IO.Stream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static StreamingOutputCallResponse ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - public static StreamingOutputCallResponse ParseDelimitedFrom(global::System.IO.Stream input) { - return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); - } - public static StreamingOutputCallResponse ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { - return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); - } - public static StreamingOutputCallResponse ParseFrom(pb::ICodedInputStream input) { - return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); - } - public static StreamingOutputCallResponse ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private StreamingOutputCallResponse MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (payload_ != null) hash ^= Payload.GetHashCode(); + return hash; } - public static Builder CreateBuilder() { return new Builder(); } - public override Builder ToBuilder() { return CreateBuilder(this); } - public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(StreamingOutputCallResponse prototype) { - return new Builder(prototype); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder<StreamingOutputCallResponse, Builder> { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(StreamingOutputCallResponse cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; - } - - private bool resultIsReadOnly; - private StreamingOutputCallResponse result; - - private StreamingOutputCallResponse PrepareBuilder() { - if (resultIsReadOnly) { - StreamingOutputCallResponse original = result; - result = new StreamingOutputCallResponse(); - resultIsReadOnly = false; - MergeFrom(original); - } - return result; - } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override StreamingOutputCallResponse MessageBeingBuilt { - get { return PrepareBuilder(); } - } - - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; - } - - public override Builder Clone() { - if (resultIsReadOnly) { - return new Builder(result); - } else { - return new Builder().MergeFrom(result); - } - } - - public override pbd::MessageDescriptor DescriptorForType { - get { return global::grpc.testing.StreamingOutputCallResponse.Descriptor; } + public void WriteTo(pb::CodedOutputStream output) { + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); } + } - public override StreamingOutputCallResponse DefaultInstanceForType { - get { return global::grpc.testing.StreamingOutputCallResponse.DefaultInstance; } + public int CalculateSize() { + int size = 0; + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); } + return size; + } - public override StreamingOutputCallResponse BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public void MergeFrom(StreamingOutputCallResponse other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is StreamingOutputCallResponse) { - return MergeFrom((StreamingOutputCallResponse) other); - } else { - base.MergeFrom(other); - return this; + if (other.payload_ != null) { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + Payload.MergeFrom(other.Payload); } + } - public override Builder MergeFrom(StreamingOutputCallResponse other) { - if (other == global::grpc.testing.StreamingOutputCallResponse.DefaultInstance) return this; - PrepareBuilder(); - if (other.HasPayload) { - MergePayload(other.Payload); - } - this.MergeUnknownFields(other.UnknownFields); - return this; - } - - public override Builder MergeFrom(pb::ICodedInputStream input) { - return MergeFrom(input, pb::ExtensionRegistry.Empty); - } - - public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - PrepareBuilder(); - pb::UnknownFieldSet.Builder unknownFields = null; - uint tag; - string field_name; - while (input.ReadTag(out tag, out field_name)) { - if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_streamingOutputCallResponseFieldNames, field_name, global::System.StringComparer.Ordinal); - if(field_ordinal >= 0) - tag = _streamingOutputCallResponseFieldTags[field_ordinal]; - else { - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - continue; - } - } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); - } - default: { - if (pb::WireFormat.IsEndGroupTag(tag)) { - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - if (unknownFields == null) { - unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); - } - ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); - break; - } - case 10: { - global::grpc.testing.Payload.Builder subBuilder = global::grpc.testing.Payload.CreateBuilder(); - if (result.hasPayload) { - subBuilder.MergeFrom(Payload); - } - input.ReadMessage(subBuilder, extensionRegistry); - Payload = subBuilder.BuildPartial(); - break; + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + input.SkipLastField(); + break; + case 10: { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + input.ReadMessage(payload_); + break; } } - - if (unknownFields != null) { - this.UnknownFields = unknownFields.Build(); - } - return this; - } - - - public bool HasPayload { - get { return result.hasPayload; } - } - public global::grpc.testing.Payload Payload { - get { return result.Payload; } - set { SetPayload(value); } - } - public Builder SetPayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = value; - return this; - } - public Builder SetPayload(global::grpc.testing.Payload.Builder builderForValue) { - pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); - PrepareBuilder(); - result.hasPayload = true; - result.payload_ = builderForValue.Build(); - return this; - } - public Builder MergePayload(global::grpc.testing.Payload value) { - pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - if (result.hasPayload && - result.payload_ != global::grpc.testing.Payload.DefaultInstance) { - result.payload_ = global::grpc.testing.Payload.CreateBuilder(result.payload_).MergeFrom(value).BuildPartial(); - } else { - result.payload_ = value; - } - result.hasPayload = true; - return this; - } - public Builder ClearPayload() { - PrepareBuilder(); - result.hasPayload = false; - result.payload_ = null; - return this; } } - static StreamingOutputCallResponse() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); - } + } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs index 842795374f..37b2518c21 100644 --- a/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs @@ -37,9 +37,9 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using grpc.testing; using Grpc.Core; using Grpc.Core.Utils; +using Grpc.Testing; using NUnit.Framework; namespace Grpc.IntegrationTesting @@ -92,7 +92,7 @@ namespace Grpc.IntegrationTesting [Test] public void AuthenticatedClientAndServer() { - var response = client.UnaryCall(SimpleRequest.CreateBuilder().SetResponseSize(10).Build()); + var response = client.UnaryCall(new SimpleRequest { ResponseSize = 10 }); Assert.AreEqual(10, response.Payload.Body.Length); } } diff --git a/src/csharp/Grpc.IntegrationTesting/Test.cs b/src/csharp/Grpc.IntegrationTesting/Test.cs new file mode 100644 index 0000000000..466ec57d3d --- /dev/null +++ b/src/csharp/Grpc.IntegrationTesting/Test.cs @@ -0,0 +1,48 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: test.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 Grpc.Testing { + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static partial class Test { + + #region Descriptor + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static Test() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "Cgp0ZXN0LnByb3RvEgxncnBjLnRlc3RpbmcaC2VtcHR5LnByb3RvGg5tZXNz", + "YWdlcy5wcm90bzK7BAoLVGVzdFNlcnZpY2USNQoJRW1wdHlDYWxsEhMuZ3Jw", + "Yy50ZXN0aW5nLkVtcHR5GhMuZ3JwYy50ZXN0aW5nLkVtcHR5EkYKCVVuYXJ5", + "Q2FsbBIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0", + "aW5nLlNpbXBsZVJlc3BvbnNlEmwKE1N0cmVhbWluZ091dHB1dENhbGwSKC5n", + "cnBjLnRlc3RpbmcuU3RyZWFtaW5nT3V0cHV0Q2FsbFJlcXVlc3QaKS5ncnBj", + "LnRlc3RpbmcuU3RyZWFtaW5nT3V0cHV0Q2FsbFJlc3BvbnNlMAESaQoSU3Ry", + "ZWFtaW5nSW5wdXRDYWxsEicuZ3JwYy50ZXN0aW5nLlN0cmVhbWluZ0lucHV0", + "Q2FsbFJlcXVlc3QaKC5ncnBjLnRlc3RpbmcuU3RyZWFtaW5nSW5wdXRDYWxs", + "UmVzcG9uc2UoARJpCg5GdWxsRHVwbGV4Q2FsbBIoLmdycGMudGVzdGluZy5T", + "dHJlYW1pbmdPdXRwdXRDYWxsUmVxdWVzdBopLmdycGMudGVzdGluZy5TdHJl", + "YW1pbmdPdXRwdXRDYWxsUmVzcG9uc2UoATABEmkKDkhhbGZEdXBsZXhDYWxs", + "EiguZ3JwYy50ZXN0aW5nLlN0cmVhbWluZ091dHB1dENhbGxSZXF1ZXN0Giku", + "Z3JwYy50ZXN0aW5nLlN0cmVhbWluZ091dHB1dENhbGxSZXNwb25zZSgBMAFi", + "BnByb3RvMw==")); + descriptor = pbr::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + new pbr::FileDescriptor[] { global::Grpc.Testing.Proto.Empty.Descriptor, global::Grpc.Testing.Messages.Descriptor, }, + new pbr::GeneratedCodeInfo(null, null)); + } + #endregion + + } +} + +#endregion Designer generated code diff --git a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs index da0b7fb910..7a48d6e92e 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs @@ -37,8 +37,6 @@ using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; -using Google.ProtocolBuffers; -using grpc.testing; using Grpc.Core; using Grpc.Core.Utils; using NUnit.Framework; diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index 697acb53d8..f63e148475 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -7,91 +7,97 @@ using System.Threading; using System.Threading.Tasks; using Grpc.Core; -namespace grpc.testing { +namespace Grpc.Testing { public static class TestService { static readonly string __ServiceName = "grpc.testing.TestService"; - static readonly Marshaller<global::grpc.testing.Empty> __Marshaller_Empty = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.Empty.ParseFrom); - static readonly Marshaller<global::grpc.testing.SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.SimpleRequest.ParseFrom); - static readonly Marshaller<global::grpc.testing.SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.SimpleResponse.ParseFrom); - static readonly Marshaller<global::grpc.testing.StreamingOutputCallRequest> __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.StreamingOutputCallRequest.ParseFrom); - static readonly Marshaller<global::grpc.testing.StreamingOutputCallResponse> __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.StreamingOutputCallResponse.ParseFrom); - static readonly Marshaller<global::grpc.testing.StreamingInputCallRequest> __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.StreamingInputCallRequest.ParseFrom); - static readonly Marshaller<global::grpc.testing.StreamingInputCallResponse> __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.StreamingInputCallResponse.ParseFrom); + static readonly Marshaller<global::Grpc.Testing.Empty> __Marshaller_Empty = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Empty.Parser.ParseFrom); + static readonly Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom); + static readonly Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom); + static readonly Marshaller<global::Grpc.Testing.StreamingOutputCallRequest> __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingOutputCallRequest.Parser.ParseFrom); + static readonly Marshaller<global::Grpc.Testing.StreamingOutputCallResponse> __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingOutputCallResponse.Parser.ParseFrom); + static readonly Marshaller<global::Grpc.Testing.StreamingInputCallRequest> __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingInputCallRequest.Parser.ParseFrom); + static readonly Marshaller<global::Grpc.Testing.StreamingInputCallResponse> __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingInputCallResponse.Parser.ParseFrom); - static readonly Method<global::grpc.testing.Empty, global::grpc.testing.Empty> __Method_EmptyCall = new Method<global::grpc.testing.Empty, global::grpc.testing.Empty>( + static readonly Method<global::Grpc.Testing.Empty, global::Grpc.Testing.Empty> __Method_EmptyCall = new Method<global::Grpc.Testing.Empty, global::Grpc.Testing.Empty>( MethodType.Unary, __ServiceName, "EmptyCall", __Marshaller_Empty, __Marshaller_Empty); - static readonly Method<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleResponse> __Method_UnaryCall = new Method<global::grpc.testing.SimpleRequest, global::grpc.testing.SimpleResponse>( + static readonly Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_UnaryCall = new Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>( MethodType.Unary, __ServiceName, "UnaryCall", __Marshaller_SimpleRequest, __Marshaller_SimpleResponse); - static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>( + static readonly Method<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> __Method_StreamingOutputCall = new Method<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse>( MethodType.ServerStreaming, __ServiceName, "StreamingOutputCall", __Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallResponse); - static readonly Method<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> __Method_StreamingInputCall = new Method<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse>( + static readonly Method<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> __Method_StreamingInputCall = new Method<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse>( MethodType.ClientStreaming, __ServiceName, "StreamingInputCall", __Marshaller_StreamingInputCallRequest, __Marshaller_StreamingInputCallResponse); - static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_FullDuplexCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>( + static readonly Method<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> __Method_FullDuplexCall = new Method<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse>( MethodType.DuplexStreaming, __ServiceName, "FullDuplexCall", __Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallResponse); - static readonly Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> __Method_HalfDuplexCall = new Method<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse>( + static readonly Method<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> __Method_HalfDuplexCall = new Method<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse>( MethodType.DuplexStreaming, __ServiceName, "HalfDuplexCall", __Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallResponse); + // service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Grpc.Testing.Test.Descriptor.Services[0]; } + } + // client interface public interface ITestServiceClient { - global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, CallOptions options); - AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, CallOptions options); - global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, CallOptions options); - AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, CallOptions options); - AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CallOptions options); - AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options); - AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options); - AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options); + global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options); + AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options); + global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options); + AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options); + AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options); + AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options); + AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options); + AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options); } // server-side interface public interface ITestService { - Task<global::grpc.testing.Empty> EmptyCall(global::grpc.testing.Empty request, ServerCallContext context); - Task<global::grpc.testing.SimpleResponse> UnaryCall(global::grpc.testing.SimpleRequest request, ServerCallContext context); - Task StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, IServerStreamWriter<global::grpc.testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); - Task<global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::grpc.testing.StreamingInputCallRequest> requestStream, ServerCallContext context); - Task FullDuplexCall(IAsyncStreamReader<global::grpc.testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::grpc.testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); - Task HalfDuplexCall(IAsyncStreamReader<global::grpc.testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::grpc.testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); + Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context); + Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); + Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); + Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context); + Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); + Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context); } // client stub @@ -100,82 +106,82 @@ namespace grpc.testing { public TestServiceClient(Channel channel) : base(channel) { } - public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.BlockingUnaryCall(call, request); } - public global::grpc.testing.Empty EmptyCall(global::grpc.testing.Empty request, CallOptions options) + public global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options) { var call = CreateCall(__Method_EmptyCall, options); return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncUnaryCall(call, request); } - public AsyncUnaryCall<global::grpc.testing.Empty> EmptyCallAsync(global::grpc.testing.Empty request, CallOptions options) + public AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options) { var call = CreateCall(__Method_EmptyCall, options); return Calls.AsyncUnaryCall(call, request); } - public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.BlockingUnaryCall(call, request); } - public global::grpc.testing.SimpleResponse UnaryCall(global::grpc.testing.SimpleRequest request, CallOptions options) + public global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options) { var call = CreateCall(__Method_UnaryCall, options); return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncUnaryCall(call, request); } - public AsyncUnaryCall<global::grpc.testing.SimpleResponse> UnaryCallAsync(global::grpc.testing.SimpleRequest request, CallOptions options) + public AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options) { var call = CreateCall(__Method_UnaryCall, options); return Calls.AsyncUnaryCall(call, request); } - public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_StreamingOutputCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncServerStreamingCall(call, request); } - public AsyncServerStreamingCall<global::grpc.testing.StreamingOutputCallResponse> StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CallOptions options) + public AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options) { var call = CreateCall(__Method_StreamingOutputCall, options); return Calls.AsyncServerStreamingCall(call, request); } - public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_StreamingInputCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncClientStreamingCall(call); } - public AsyncClientStreamingCall<global::grpc.testing.StreamingInputCallRequest, global::grpc.testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options) + public AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options) { var call = CreateCall(__Method_StreamingInputCall, options); return Calls.AsyncClientStreamingCall(call); } - public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_FullDuplexCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options) + public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options) { var call = CreateCall(__Method_FullDuplexCall, options); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) { var call = CreateCall(__Method_HalfDuplexCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall<global::grpc.testing.StreamingOutputCallRequest, global::grpc.testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options) + public AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options) { var call = CreateCall(__Method_HalfDuplexCall, options); return Calls.AsyncDuplexStreamingCall(call); diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs index ceebd5dd8c..c5bfcf08c0 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs @@ -35,11 +35,11 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Google.ProtocolBuffers; +using Google.Protobuf; using Grpc.Core; using Grpc.Core.Utils; -namespace grpc.testing +namespace Grpc.Testing { /// <summary> /// Implementation of TestService server @@ -48,22 +48,20 @@ namespace grpc.testing { public Task<Empty> EmptyCall(Empty request, ServerCallContext context) { - return Task.FromResult(Empty.DefaultInstance); + return Task.FromResult(new Empty()); } public Task<SimpleResponse> UnaryCall(SimpleRequest request, ServerCallContext context) { - var response = SimpleResponse.CreateBuilder() - .SetPayload(CreateZerosPayload(request.ResponseSize)).Build(); + var response = new SimpleResponse { Payload = CreateZerosPayload(request.ResponseSize) }; return Task.FromResult(response); } public async Task StreamingOutputCall(StreamingOutputCallRequest request, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) { - foreach (var responseParam in request.ResponseParametersList) + foreach (var responseParam in request.ResponseParameters) { - var response = StreamingOutputCallResponse.CreateBuilder() - .SetPayload(CreateZerosPayload(responseParam.Size)).Build(); + var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; await responseStream.WriteAsync(response); } } @@ -75,17 +73,16 @@ namespace grpc.testing { sum += request.Payload.Body.Length; }); - return StreamingInputCallResponse.CreateBuilder().SetAggregatedPayloadSize(sum).Build(); + return new StreamingInputCallResponse { AggregatedPayloadSize = sum }; } public async Task FullDuplexCall(IAsyncStreamReader<StreamingOutputCallRequest> requestStream, IServerStreamWriter<StreamingOutputCallResponse> responseStream, ServerCallContext context) { await requestStream.ForEachAsync(async request => { - foreach (var responseParam in request.ResponseParametersList) + foreach (var responseParam in request.ResponseParameters) { - var response = StreamingOutputCallResponse.CreateBuilder() - .SetPayload(CreateZerosPayload(responseParam.Size)).Build(); + var response = new StreamingOutputCallResponse { Payload = CreateZerosPayload(responseParam.Size) }; await responseStream.WriteAsync(response); } }); @@ -98,7 +95,7 @@ namespace grpc.testing private static Payload CreateZerosPayload(int size) { - return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build(); + return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } } } diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config index 0867b091b9..8dfded1964 100644 --- a/src/csharp/Grpc.IntegrationTesting/packages.config +++ b/src/csharp/Grpc.IntegrationTesting/packages.config @@ -3,6 +3,7 @@ <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.Protobuf" version="3.0.0-alpha4" targetFramework="net45" /> <package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" /> <package id="Ix-Async" version="1.2.3" targetFramework="net45" /> <package id="Microsoft.Bcl" version="1.1.10" targetFramework="net45" /> diff --git a/src/csharp/Grpc.IntegrationTesting/proto/empty.proto b/src/csharp/Grpc.IntegrationTesting/proto/empty.proto index 4295a0a960..6d0eb937d6 100644 --- a/src/csharp/Grpc.IntegrationTesting/proto/empty.proto +++ b/src/csharp/Grpc.IntegrationTesting/proto/empty.proto @@ -28,7 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -syntax = "proto2"; +syntax = "proto3"; package grpc.testing; diff --git a/src/csharp/Grpc.IntegrationTesting/proto/messages.proto b/src/csharp/Grpc.IntegrationTesting/proto/messages.proto index 65a8140465..7df85e3c13 100644 --- a/src/csharp/Grpc.IntegrationTesting/proto/messages.proto +++ b/src/csharp/Grpc.IntegrationTesting/proto/messages.proto @@ -30,7 +30,7 @@ // Message definitions to be used by integration test service definitions. -syntax = "proto2"; +syntax = "proto3"; package grpc.testing; @@ -49,46 +49,46 @@ enum PayloadType { // A block of data, to simply increase gRPC message size. message Payload { // The type of data in body. - optional PayloadType type = 1; + PayloadType type = 1; // Primary contents of payload. - optional bytes body = 2; + bytes body = 2; } // Unary request. message SimpleRequest { // Desired payload type in the response from the server. // If response_type is RANDOM, server randomly chooses one from other formats. - optional PayloadType response_type = 1; + PayloadType response_type = 1; // Desired payload size in the response from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. - optional int32 response_size = 2; + int32 response_size = 2; // Optional input payload sent along with the request. - optional Payload payload = 3; + Payload payload = 3; // Whether SimpleResponse should include username. - optional bool fill_username = 4; + bool fill_username = 4; // Whether SimpleResponse should include OAuth scope. - optional bool fill_oauth_scope = 5; + bool fill_oauth_scope = 5; } // Unary response, as configured by the request. message SimpleResponse { // Payload to increase message size. - optional Payload payload = 1; + Payload payload = 1; // The user the request came from, for verifying authentication was // successful when the client expected it. - optional string username = 2; + string username = 2; // OAuth scope. - optional string oauth_scope = 3; + string oauth_scope = 3; } // Client-streaming request. message StreamingInputCallRequest { // Optional input payload sent along with the request. - optional Payload payload = 1; + Payload payload = 1; // Not expecting any payload from the response. } @@ -96,18 +96,18 @@ message StreamingInputCallRequest { // Client-streaming response. message StreamingInputCallResponse { // Aggregated size of payloads received from the client. - optional int32 aggregated_payload_size = 1; + int32 aggregated_payload_size = 1; } // Configuration for a particular response. message ResponseParameters { // Desired payload sizes in responses from the server. // If response_type is COMPRESSABLE, this denotes the size before compression. - optional int32 size = 1; + int32 size = 1; // Desired interval between consecutive responses in the response stream in // microseconds. - optional int32 interval_us = 2; + int32 interval_us = 2; } // Server-streaming request. @@ -116,17 +116,17 @@ message StreamingOutputCallRequest { // If response_type is RANDOM, the payload from each response in the stream // might be of different types. This is to simulate a mixed type of payload // stream. - optional PayloadType response_type = 1; + PayloadType response_type = 1; // Configuration for each expected response message. repeated ResponseParameters response_parameters = 2; // Optional input payload sent along with the request. - optional Payload payload = 3; + Payload payload = 3; } // Server-streaming response, as configured by the request and parameters. message StreamingOutputCallResponse { // Payload to increase response size. - optional Payload payload = 1; + Payload payload = 1; } diff --git a/src/csharp/Grpc.IntegrationTesting/proto/test.proto b/src/csharp/Grpc.IntegrationTesting/proto/test.proto index 927a3a83aa..f9e0d2a039 100644 --- a/src/csharp/Grpc.IntegrationTesting/proto/test.proto +++ b/src/csharp/Grpc.IntegrationTesting/proto/test.proto @@ -30,7 +30,7 @@ // An integration test service that covers all the method signature permutations // of unary/streaming requests/responses. -syntax = "proto2"; +syntax = "proto3"; import "empty.proto"; import "messages.proto"; diff --git a/src/csharp/Grpc.Tools.nuspec b/src/csharp/Grpc.Tools.nuspec index eabf5dc7db..48a7b1f3af 100644 --- a/src/csharp/Grpc.Tools.nuspec +++ b/src/csharp/Grpc.Tools.nuspec @@ -4,19 +4,18 @@ <id>Grpc.Tools</id> <title>gRPC C# Tools</title> <summary>Tools for C# implementation of gRPC - an RPC library and framework</summary> - <description>Precompiled Windows binaries for generating protocol buffer messages and gRPC client/server code</description> + <description>Precompiled Windows binary for generating gRPC client/server code</description> <version>$version$</version> <authors>Google Inc.</authors> <owners>grpc-packages</owners> <licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl> <projectUrl>https://github.com/grpc/grpc</projectUrl> <requireLicenseAcceptance>false</requireLicenseAcceptance> - <releaseNotes>protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version $version$</releaseNotes> + <releaseNotes>grpc_csharp_plugin.exe - gRPC C# protoc plugin version $version$</releaseNotes> <copyright>Copyright 2015, Google Inc.</copyright> <tags>gRPC RPC Protocol HTTP/2</tags> </metadata> <files> - <file src="protoc.exe" target="tools" /> - <file src="grpc_csharp_plugin.exe" target="tools" /> + <file src="..\..\vsprojects\Release\grpc_csharp_plugin.exe" target="tools" /> </files> </package> diff --git a/src/csharp/README.md b/src/csharp/README.md index bb5e165986..3fbc1c5f05 100644 --- a/src/csharp/README.md +++ b/src/csharp/README.md @@ -19,7 +19,7 @@ Usage: Windows That will also pull all the transitive dependencies (including the native libraries that gRPC C# is internally using). -- Helloworld project example can be found in https://github.com/grpc/grpc-common/tree/master/csharp. +- Helloworld project example can be found in https://github.com/grpc/grpc/tree/master/examples/csharp. Usage: Linux (Mono) -------------- @@ -50,7 +50,7 @@ Usage: Linux (Mono) - Add NuGet package `Grpc` as a dependency (Project -> Add NuGet packages). -- Helloworld project example can be found in https://github.com/grpc/grpc-common/tree/master/csharp. +- Helloworld project example can be found in https://github.com/grpc/grpc/tree/master/examples/csharp. Usage: MacOS (Mono) -------------- @@ -73,7 +73,7 @@ Usage: MacOS (Mono) - *You will be able to build your project in Xamarin Studio, but to run or test it, you will need to run it under 64-bit version of Mono.* -- Helloworld project example can be found in https://github.com/grpc/grpc-common/tree/master/csharp. +- Helloworld project example can be found in https://github.com/grpc/grpc/tree/master/examples/csharp. Building: Windows ----------------- @@ -158,3 +158,20 @@ Contents An example client that sends some requests to math server. - Grpc.IntegrationTesting: Cross-language gRPC implementation testing (interop testing). + +Troubleshooting +--------------- + +### Problem: Unable to load DLL 'grpc_csharp_ext.dll' + +Internally, gRPC C# uses a native library written in C (gRPC C core) and invokes its functionality via P/Invoke. `grpc_csharp_ext` library is a native extension library that facilitates this by wrapping some C core API into a form that's more digestible for P/Invoke. If you get the above error, it means that the native dependencies could not be located by the C# runtime (or they are incompatible with the current runtime, so they could not be loaded). The solution to this is environment specific. + +- If you are developing on Windows in Visual Studio, the `grpc_csharp_ext.dll` that is shipped by gRPC nuget packages should be automatically copied to your build destination folder once you build. By adjusting project properties in your VS project file, you can influence which exact configuration of `grpc_csharp_ext.dll` will be used (based on VS version, bitness, debug/release configuration). + +- If you are running your application that is using gRPC on Windows machine that doesn't have Visual Studio installed, you might need to install [Visual C++ 2013 redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=40784) that contains some system .dll libraries that `grpc_csharp_ext.dll` depends on (see #905 for more details). + +- On Linux (or Docker), you need to first install gRPC C core and `libgrpc_csharp_ext.so` shared libraries. Currently, the libraries can be installed by `make install_grpc_csharp_ext` or using Linuxbrew (a Debian package is coming soon). Installation on a machine where your application is going to be deployed is no different. + +- On Mac, you need to first install gRPC C core and `libgrpc_csharp_ext.dylib` shared libraries using Homebrew. See above for installation instruction. Installation on a machine where your application is going to be deployed is no different. + +- Possible cause for the problem is that the `grpc_csharp_ext` library is installed, but it has different bitness (32/64bit) than your C# runtime (in case you are using mono) or C# application. diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 8a11d01430..255b7469ab 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -1,8 +1,9 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.6.1 -set CORE_VERSION=0.10.1 +set VERSION=0.7.0 +set CORE_VERSION=0.11.0 +set PROTOBUF_VERSION=3.0.0-alpha4 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe @@ -14,10 +15,12 @@ endlocal @call buildall.bat BUILD_SIGNED || goto :error +@call ..\..\vsprojects\build_plugins.bat || goto :error + %NUGET% pack ..\..\vsprojects\nuget_package\grpc.native.csharp_ext.nuspec -Version %CORE_VERSION% || goto :error %NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error %NUGET% pack Grpc.Core\Grpc.Core.nuspec -Symbols -Version %VERSION% -Properties GrpcNativeCsharpExtVersion=%CORE_VERSION% || goto :error -%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION% || goto :error +%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error %NUGET% pack Grpc.Tools.nuspec -Version %VERSION% || goto :error %NUGET% pack Grpc.nuspec -Version %VERSION% || goto :error diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 489e219c49..70c0fbcc50 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -837,11 +837,11 @@ grpcsharp_ssl_credentials_create(const char *pem_root_certs, if (key_cert_pair_cert_chain || key_cert_pair_private_key) { key_cert_pair.cert_chain = key_cert_pair_cert_chain; key_cert_pair.private_key = key_cert_pair_private_key; - return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair); + return grpc_ssl_credentials_create(pem_root_certs, &key_cert_pair, NULL); } else { GPR_ASSERT(!key_cert_pair_cert_chain); GPR_ASSERT(!key_cert_pair_private_key); - return grpc_ssl_credentials_create(pem_root_certs, NULL); + return grpc_ssl_credentials_create(pem_root_certs, NULL, NULL); } } @@ -852,7 +852,7 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_credentials_release(grpc_credentials *cre GPR_EXPORT grpc_channel *GPR_CALLTYPE grpcsharp_secure_channel_create(grpc_credentials *creds, const char *target, const grpc_channel_args *args) { - return grpc_secure_channel_create(creds, target, args); + return grpc_secure_channel_create(creds, target, args, NULL); } GPR_EXPORT grpc_server_credentials *GPR_CALLTYPE @@ -876,7 +876,7 @@ grpcsharp_ssl_server_credentials_create( } creds = grpc_ssl_server_credentials_create(pem_root_certs, key_cert_pairs, num_key_cert_pairs, - force_client_auth); + force_client_auth, NULL); gpr_free(key_cert_pairs); return creds; } diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh index 7c3ba70922..a17f45b587 100755 --- a/src/csharp/generate_proto_csharp.sh +++ b/src/csharp/generate_proto_csharp.sh @@ -38,11 +38,11 @@ EXAMPLES_DIR=Grpc.Examples INTEROP_DIR=Grpc.IntegrationTesting HEALTHCHECK_DIR=Grpc.HealthCheck -$PROTOC --plugin=$PLUGIN --grpc_out=$EXAMPLES_DIR \ +$PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \ -I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto -$PROTOC --plugin=$PLUGIN --grpc_out=$INTEROP_DIR \ - -I $INTEROP_DIR/proto $INTEROP_DIR/proto/test.proto +$PROTOC --plugin=$PLUGIN --csharp_out=$INTEROP_DIR --grpc_out=$INTEROP_DIR \ + -I $INTEROP_DIR/proto $INTEROP_DIR/proto/*.proto -$PROTOC --plugin=$PLUGIN --grpc_out=$HEALTHCHECK_DIR \ +$PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \ -I $HEALTHCHECK_DIR/proto $HEALTHCHECK_DIR/proto/health.proto diff --git a/src/node/README.md b/src/node/README.md index b6411537c7..0b97680feb 100644 --- a/src/node/README.md +++ b/src/node/README.md @@ -1,7 +1,7 @@ # Node.js gRPC Library ## Status -Alpha : Ready for early adopters +Beta ## PREREQUISITES - `node`: This requires `node` to be installed. If you instead have the `nodejs` executable on Debian, you should install the [`nodejs-legacy`](https://packages.debian.org/sid/nodejs-legacy) package. @@ -11,10 +11,10 @@ Alpha : Ready for early adopters **Linux (Debian):** -Add [Debian unstable][] to your `sources.list` file. Example: +Add [Debian testing][] to your `sources.list` file. Example: ```sh -echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" | \ +echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \ sudo tee -a /etc/apt/sources.list ``` @@ -113,4 +113,4 @@ An object with factory methods for creating credential objects for servers. [homebrew]:http://brew.sh [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install -[Debian unstable]:https://www.debian.org/releases/sid/ +[Debian testing]:https://www.debian.org/releases/stretch/ diff --git a/src/node/examples/route_guide.proto b/src/node/examples/route_guide.proto deleted file mode 100644 index fceb632a97..0000000000 --- a/src/node/examples/route_guide.proto +++ /dev/null @@ -1,120 +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. - -syntax = "proto3"; - -option java_package = "io.grpc.examples"; - -package examples; - -// Interface exported by the server. -service RouteGuide { - // A simple RPC. - // - // Obtains the feature at a given position. - rpc GetFeature(Point) returns (Feature) {} - - // A server-to-client streaming RPC. - // - // Obtains the Features available within the given Rectangle. Results are - // streamed rather than returned at once (e.g. in a response message with a - // repeated field), as the rectangle may cover a large area and contain a - // huge number of features. - rpc ListFeatures(Rectangle) returns (stream Feature) {} - - // A client-to-server streaming RPC. - // - // Accepts a stream of Points on a route being traversed, returning a - // RouteSummary when traversal is completed. - rpc RecordRoute(stream Point) returns (RouteSummary) {} - - // A Bidirectional streaming RPC. - // - // Accepts a stream of RouteNotes sent while a route is being traversed, - // while receiving other RouteNotes (e.g. from other users). - rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} -} - -// Points are represented as latitude-longitude pairs in the E7 representation -// (degrees multiplied by 10**7 and rounded to the nearest integer). -// Latitudes should be in the range +/- 90 degrees and longitude should be in -// the range +/- 180 degrees (inclusive). -message Point { - int32 latitude = 1; - int32 longitude = 2; -} - -// A latitude-longitude rectangle, represented as two diagonally opposite -// points "lo" and "hi". -message Rectangle { - // One corner of the rectangle. - Point lo = 1; - - // The other corner of the rectangle. - Point hi = 2; -} - -// A feature names something at a given point. -// -// If a feature could not be named, the name is empty. -message Feature { - // The name of the feature. - string name = 1; - - // The point where the feature is detected. - Point location = 2; -} - -// A RouteNote is a message sent while at a given point. -message RouteNote { - // The location from which the message is sent. - Point location = 1; - - // The message to be sent. - string message = 2; -} - -// A RouteSummary is received in response to a RecordRoute rpc. -// -// It contains the number of individual points received, the number of -// detected features, and the total distance covered as the cumulative sum of -// the distance between each point. -message RouteSummary { - // The number of points received. - int32 point_count = 1; - - // The number of known features passed while traversing the route. - int32 feature_count = 2; - - // The distance covered in metres. - int32 distance = 3; - - // The duration of the traversal in seconds. - int32 elapsed_time = 4; -} diff --git a/src/node/examples/route_guide_client.js b/src/node/examples/route_guide_client.js deleted file mode 100644 index 647f3ffaba..0000000000 --- a/src/node/examples/route_guide_client.js +++ /dev/null @@ -1,240 +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. - * - */ - -'use strict'; - -var async = require('async'); -var fs = require('fs'); -var parseArgs = require('minimist'); -var path = require('path'); -var _ = require('lodash'); -var grpc = require('..'); -var examples = grpc.load(__dirname + '/route_guide.proto').examples; -var client = new examples.RouteGuide('localhost:50051', - grpc.Credentials.createInsecure()); - -var COORD_FACTOR = 1e7; - -/** - * Run the getFeature demo. Calls getFeature with a point known to have a - * feature and a point known not to have a feature. - * @param {function} callback Called when this demo is complete - */ -function runGetFeature(callback) { - var next = _.after(2, callback); - function featureCallback(error, feature) { - if (error) { - callback(error); - } - if (feature.name === '') { - console.log('Found no feature at ' + - feature.location.latitude/COORD_FACTOR + ', ' + - feature.location.longitude/COORD_FACTOR); - } else { - console.log('Found feature called "' + feature.name + '" at ' + - feature.location.latitude/COORD_FACTOR + ', ' + - feature.location.longitude/COORD_FACTOR); - } - next(); - } - var point1 = { - latitude: 409146138, - longitude: -746188906 - }; - var point2 = { - latitude: 0, - longitude: 0 - }; - client.getFeature(point1, featureCallback); - client.getFeature(point2, featureCallback); -} - -/** - * Run the listFeatures demo. Calls listFeatures with a rectangle containing all - * of the features in the pre-generated database. Prints each response as it - * comes in. - * @param {function} callback Called when this demo is complete - */ -function runListFeatures(callback) { - var rectangle = { - lo: { - latitude: 400000000, - longitude: -750000000 - }, - hi: { - latitude: 420000000, - longitude: -730000000 - } - }; - console.log('Looking for features between 40, -75 and 42, -73'); - var call = client.listFeatures(rectangle); - call.on('data', function(feature) { - console.log('Found feature called "' + feature.name + '" at ' + - feature.location.latitude/COORD_FACTOR + ', ' + - feature.location.longitude/COORD_FACTOR); - }); - call.on('end', callback); -} - -/** - * Run the recordRoute demo. Sends several randomly chosen points from the - * pre-generated feature database with a variable delay in between. Prints the - * statistics when they are sent from the server. - * @param {function} callback Called when this demo is complete - */ -function runRecordRoute(callback) { - var argv = parseArgs(process.argv, { - string: 'db_path' - }); - fs.readFile(path.resolve(argv.db_path), function(err, data) { - if (err) { - callback(err); - } - var feature_list = JSON.parse(data); - - var num_points = 10; - var call = client.recordRoute(function(error, stats) { - if (error) { - callback(error); - } - console.log('Finished trip with', stats.point_count, 'points'); - console.log('Passed', stats.feature_count, 'features'); - console.log('Travelled', stats.distance, 'meters'); - console.log('It took', stats.elapsed_time, 'seconds'); - callback(); - }); - /** - * Constructs a function that asynchronously sends the given point and then - * delays sending its callback - * @param {number} lat The latitude to send - * @param {number} lng The longitude to send - * @return {function(function)} The function that sends the point - */ - function pointSender(lat, lng) { - /** - * Sends the point, then calls the callback after a delay - * @param {function} callback Called when complete - */ - return function(callback) { - console.log('Visiting point ' + lat/COORD_FACTOR + ', ' + - lng/COORD_FACTOR); - call.write({ - latitude: lat, - longitude: lng - }); - _.delay(callback, _.random(500, 1500)); - }; - } - var point_senders = []; - for (var i = 0; i < num_points; i++) { - var rand_point = feature_list[_.random(0, feature_list.length - 1)]; - point_senders[i] = pointSender(rand_point.location.latitude, - rand_point.location.longitude); - } - async.series(point_senders, function() { - call.end(); - }); - }); -} - -/** - * Run the routeChat demo. Send some chat messages, and print any chat messages - * that are sent from the server. - * @param {function} callback Called when the demo is complete - */ -function runRouteChat(callback) { - var call = client.routeChat(); - call.on('data', function(note) { - console.log('Got message "' + note.message + '" at ' + - note.location.latitude + ', ' + note.location.longitude); - }); - - call.on('end', callback); - - var notes = [{ - location: { - latitude: 0, - longitude: 0 - }, - message: 'First message' - }, { - location: { - latitude: 0, - longitude: 1 - }, - message: 'Second message' - }, { - location: { - latitude: 1, - longitude: 0 - }, - message: 'Third message' - }, { - location: { - latitude: 0, - longitude: 0 - }, - message: 'Fourth message' - }]; - for (var i = 0; i < notes.length; i++) { - var note = notes[i]; - console.log('Sending message "' + note.message + '" at ' + - note.location.latitude + ', ' + note.location.longitude); - call.write(note); - } - call.end(); -} - -/** - * Run all of the demos in order - */ -function main() { - async.series([ - runGetFeature, - runListFeatures, - runRecordRoute, - runRouteChat - ]); -} - -if (require.main === module) { - main(); -} - -exports.runGetFeature = runGetFeature; - -exports.runListFeatures = runListFeatures; - -exports.runRecordRoute = runRecordRoute; - -exports.runRouteChat = runRouteChat; diff --git a/src/node/examples/route_guide_db.json b/src/node/examples/route_guide_db.json deleted file mode 100644 index 9d6a980ab7..0000000000 --- a/src/node/examples/route_guide_db.json +++ /dev/null @@ -1,601 +0,0 @@ -[{ - "location": { - "latitude": 407838351, - "longitude": -746143763 - }, - "name": "Patriots Path, Mendham, NJ 07945, USA" -}, { - "location": { - "latitude": 408122808, - "longitude": -743999179 - }, - "name": "101 New Jersey 10, Whippany, NJ 07981, USA" -}, { - "location": { - "latitude": 413628156, - "longitude": -749015468 - }, - "name": "U.S. 6, Shohola, PA 18458, USA" -}, { - "location": { - "latitude": 419999544, - "longitude": -740371136 - }, - "name": "5 Conners Road, Kingston, NY 12401, USA" -}, { - "location": { - "latitude": 414008389, - "longitude": -743951297 - }, - "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" -}, { - "location": { - "latitude": 419611318, - "longitude": -746524769 - }, - "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" -}, { - "location": { - "latitude": 406109563, - "longitude": -742186778 - }, - "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" -}, { - "location": { - "latitude": 416802456, - "longitude": -742370183 - }, - "name": "352 South Mountain Road, Wallkill, NY 12589, USA" -}, { - "location": { - "latitude": 412950425, - "longitude": -741077389 - }, - "name": "Bailey Turn Road, Harriman, NY 10926, USA" -}, { - "location": { - "latitude": 412144655, - "longitude": -743949739 - }, - "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" -}, { - "location": { - "latitude": 415736605, - "longitude": -742847522 - }, - "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" -}, { - "location": { - "latitude": 413843930, - "longitude": -740501726 - }, - "name": "162 Merrill Road, Highland Mills, NY 10930, USA" -}, { - "location": { - "latitude": 410873075, - "longitude": -744459023 - }, - "name": "Clinton Road, West Milford, NJ 07480, USA" -}, { - "location": { - "latitude": 412346009, - "longitude": -744026814 - }, - "name": "16 Old Brook Lane, Warwick, NY 10990, USA" -}, { - "location": { - "latitude": 402948455, - "longitude": -747903913 - }, - "name": "3 Drake Lane, Pennington, NJ 08534, USA" -}, { - "location": { - "latitude": 406337092, - "longitude": -740122226 - }, - "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" -}, { - "location": { - "latitude": 406421967, - "longitude": -747727624 - }, - "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" -}, { - "location": { - "latitude": 416318082, - "longitude": -749677716 - }, - "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" -}, { - "location": { - "latitude": 415301720, - "longitude": -748416257 - }, - "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" -}, { - "location": { - "latitude": 402647019, - "longitude": -747071791 - }, - "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" -}, { - "location": { - "latitude": 412567807, - "longitude": -741058078 - }, - "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" -}, { - "location": { - "latitude": 416855156, - "longitude": -744420597 - }, - "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" -}, { - "location": { - "latitude": 404663628, - "longitude": -744820157 - }, - "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" -}, { - "location": { - "latitude": 407113723, - "longitude": -749746483 - }, - "name": "" -}, { - "location": { - "latitude": 402133926, - "longitude": -743613249 - }, - "name": "" -}, { - "location": { - "latitude": 400273442, - "longitude": -741220915 - }, - "name": "" -}, { - "location": { - "latitude": 411236786, - "longitude": -744070769 - }, - "name": "" -}, { - "location": { - "latitude": 411633782, - "longitude": -746784970 - }, - "name": "211-225 Plains Road, Augusta, NJ 07822, USA" -}, { - "location": { - "latitude": 415830701, - "longitude": -742952812 - }, - "name": "" -}, { - "location": { - "latitude": 413447164, - "longitude": -748712898 - }, - "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" -}, { - "location": { - "latitude": 405047245, - "longitude": -749800722 - }, - "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" -}, { - "location": { - "latitude": 418858923, - "longitude": -746156790 - }, - "name": "" -}, { - "location": { - "latitude": 417951888, - "longitude": -748484944 - }, - "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" -}, { - "location": { - "latitude": 407033786, - "longitude": -743977337 - }, - "name": "26 East 3rd Street, New Providence, NJ 07974, USA" -}, { - "location": { - "latitude": 417548014, - "longitude": -740075041 - }, - "name": "" -}, { - "location": { - "latitude": 410395868, - "longitude": -744972325 - }, - "name": "" -}, { - "location": { - "latitude": 404615353, - "longitude": -745129803 - }, - "name": "" -}, { - "location": { - "latitude": 406589790, - "longitude": -743560121 - }, - "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" -}, { - "location": { - "latitude": 414653148, - "longitude": -740477477 - }, - "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" -}, { - "location": { - "latitude": 405957808, - "longitude": -743255336 - }, - "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" -}, { - "location": { - "latitude": 411733589, - "longitude": -741648093 - }, - "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" -}, { - "location": { - "latitude": 412676291, - "longitude": -742606606 - }, - "name": "1270 Lakes Road, Monroe, NY 10950, USA" -}, { - "location": { - "latitude": 409224445, - "longitude": -748286738 - }, - "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" -}, { - "location": { - "latitude": 406523420, - "longitude": -742135517 - }, - "name": "652 Garden Street, Elizabeth, NJ 07202, USA" -}, { - "location": { - "latitude": 401827388, - "longitude": -740294537 - }, - "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" -}, { - "location": { - "latitude": 410564152, - "longitude": -743685054 - }, - "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" -}, { - "location": { - "latitude": 408472324, - "longitude": -740726046 - }, - "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" -}, { - "location": { - "latitude": 412452168, - "longitude": -740214052 - }, - "name": "5 White Oak Lane, Stony Point, NY 10980, USA" -}, { - "location": { - "latitude": 409146138, - "longitude": -746188906 - }, - "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" -}, { - "location": { - "latitude": 404701380, - "longitude": -744781745 - }, - "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" -}, { - "location": { - "latitude": 409642566, - "longitude": -746017679 - }, - "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" -}, { - "location": { - "latitude": 408031728, - "longitude": -748645385 - }, - "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" -}, { - "location": { - "latitude": 413700272, - "longitude": -742135189 - }, - "name": "367 Prospect Road, Chester, NY 10918, USA" -}, { - "location": { - "latitude": 404310607, - "longitude": -740282632 - }, - "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" -}, { - "location": { - "latitude": 409319800, - "longitude": -746201391 - }, - "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" -}, { - "location": { - "latitude": 406685311, - "longitude": -742108603 - }, - "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" -}, { - "location": { - "latitude": 419018117, - "longitude": -749142781 - }, - "name": "43 Dreher Road, Roscoe, NY 12776, USA" -}, { - "location": { - "latitude": 412856162, - "longitude": -745148837 - }, - "name": "Swan Street, Pine Island, NY 10969, USA" -}, { - "location": { - "latitude": 416560744, - "longitude": -746721964 - }, - "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" -}, { - "location": { - "latitude": 405314270, - "longitude": -749836354 - }, - "name": "" -}, { - "location": { - "latitude": 414219548, - "longitude": -743327440 - }, - "name": "" -}, { - "location": { - "latitude": 415534177, - "longitude": -742900616 - }, - "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" -}, { - "location": { - "latitude": 406898530, - "longitude": -749127080 - }, - "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" -}, { - "location": { - "latitude": 407586880, - "longitude": -741670168 - }, - "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" -}, { - "location": { - "latitude": 400106455, - "longitude": -742870190 - }, - "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" -}, { - "location": { - "latitude": 400066188, - "longitude": -746793294 - }, - "name": "" -}, { - "location": { - "latitude": 418803880, - "longitude": -744102673 - }, - "name": "40 Mountain Road, Napanoch, NY 12458, USA" -}, { - "location": { - "latitude": 414204288, - "longitude": -747895140 - }, - "name": "" -}, { - "location": { - "latitude": 414777405, - "longitude": -740615601 - }, - "name": "" -}, { - "location": { - "latitude": 415464475, - "longitude": -747175374 - }, - "name": "48 North Road, Forestburgh, NY 12777, USA" -}, { - "location": { - "latitude": 404062378, - "longitude": -746376177 - }, - "name": "" -}, { - "location": { - "latitude": 405688272, - "longitude": -749285130 - }, - "name": "" -}, { - "location": { - "latitude": 400342070, - "longitude": -748788996 - }, - "name": "" -}, { - "location": { - "latitude": 401809022, - "longitude": -744157964 - }, - "name": "" -}, { - "location": { - "latitude": 404226644, - "longitude": -740517141 - }, - "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" -}, { - "location": { - "latitude": 410322033, - "longitude": -747871659 - }, - "name": "" -}, { - "location": { - "latitude": 407100674, - "longitude": -747742727 - }, - "name": "" -}, { - "location": { - "latitude": 418811433, - "longitude": -741718005 - }, - "name": "213 Bush Road, Stone Ridge, NY 12484, USA" -}, { - "location": { - "latitude": 415034302, - "longitude": -743850945 - }, - "name": "" -}, { - "location": { - "latitude": 411349992, - "longitude": -743694161 - }, - "name": "" -}, { - "location": { - "latitude": 404839914, - "longitude": -744759616 - }, - "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" -}, { - "location": { - "latitude": 414638017, - "longitude": -745957854 - }, - "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" -}, { - "location": { - "latitude": 412127800, - "longitude": -740173578 - }, - "name": "" -}, { - "location": { - "latitude": 401263460, - "longitude": -747964303 - }, - "name": "" -}, { - "location": { - "latitude": 412843391, - "longitude": -749086026 - }, - "name": "" -}, { - "location": { - "latitude": 418512773, - "longitude": -743067823 - }, - "name": "" -}, { - "location": { - "latitude": 404318328, - "longitude": -740835638 - }, - "name": "42-102 Main Street, Belford, NJ 07718, USA" -}, { - "location": { - "latitude": 419020746, - "longitude": -741172328 - }, - "name": "" -}, { - "location": { - "latitude": 404080723, - "longitude": -746119569 - }, - "name": "" -}, { - "location": { - "latitude": 401012643, - "longitude": -744035134 - }, - "name": "" -}, { - "location": { - "latitude": 404306372, - "longitude": -741079661 - }, - "name": "" -}, { - "location": { - "latitude": 403966326, - "longitude": -748519297 - }, - "name": "" -}, { - "location": { - "latitude": 405002031, - "longitude": -748407866 - }, - "name": "" -}, { - "location": { - "latitude": 409532885, - "longitude": -742200683 - }, - "name": "" -}, { - "location": { - "latitude": 416851321, - "longitude": -742674555 - }, - "name": "" -}, { - "location": { - "latitude": 406411633, - "longitude": -741722051 - }, - "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" -}, { - "location": { - "latitude": 413069058, - "longitude": -744597778 - }, - "name": "261 Van Sickle Road, Goshen, NY 10924, USA" -}, { - "location": { - "latitude": 418465462, - "longitude": -746859398 - }, - "name": "" -}, { - "location": { - "latitude": 411733222, - "longitude": -744228360 - }, - "name": "" -}, { - "location": { - "latitude": 410248224, - "longitude": -747127767 - }, - "name": "3 Hasta Way, Newton, NJ 07860, USA" -}] diff --git a/src/node/examples/route_guide_server.js b/src/node/examples/route_guide_server.js deleted file mode 100644 index 465b32f54f..0000000000 --- a/src/node/examples/route_guide_server.js +++ /dev/null @@ -1,255 +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. - * - */ - -'use strict'; - -var fs = require('fs'); -var parseArgs = require('minimist'); -var path = require('path'); -var _ = require('lodash'); -var grpc = require('..'); -var examples = grpc.load(__dirname + '/route_guide.proto').examples; - -var COORD_FACTOR = 1e7; - -/** - * For simplicity, a point is a record type that looks like - * {latitude: number, longitude: number}, and a feature is a record type that - * looks like {name: string, location: point}. feature objects with name==='' - * are points with no feature. - */ - -/** - * List of feature objects at points that have been requested so far. - */ -var feature_list = []; - -/** - * Get a feature object at the given point. - * @param {point} point The point to check - * @return {feature} The feature object at the point. Note that an empty name - * indicates no feature - */ -function checkFeature(point) { - var feature; - // Check if there is already a feature object for the given point - for (var i = 0; i < feature_list.length; i++) { - feature = feature_list[i]; - if (feature.location.latitude === point.latitude && - feature.location.longitude === point.longitude) { - return feature; - } - } - var name = ''; - feature = { - name: name, - location: point - }; - return feature; -} - -/** - * getFeature request handler. Gets a request with a point, and responds with a - * feature object indicating whether there is a feature at that point. - * @param {EventEmitter} call Call object for the handler to process - * @param {function(Error, feature)} callback Response callback - */ -function getFeature(call, callback) { - callback(null, checkFeature(call.request)); -} - -/** - * listFeatures request handler. Gets a request with two points, and responds - * with a stream of all features in the bounding box defined by those points. - * @param {Writable} call Writable stream for responses with an additional - * request property for the request value. - */ -function listFeatures(call) { - var lo = call.request.lo; - var hi = call.request.hi; - var left = _.min([lo.longitude, hi.longitude]); - var right = _.max([lo.longitude, hi.longitude]); - var top = _.max([lo.latitude, hi.latitude]); - var bottom = _.min([lo.latitude, hi.latitude]); - // For each feature, check if it is in the given bounding box - _.each(feature_list, function(feature) { - if (feature.name === '') { - return; - } - if (feature.location.longitude >= left && - feature.location.longitude <= right && - feature.location.latitude >= bottom && - feature.location.latitude <= top) { - call.write(feature); - } - }); - call.end(); -} - -/** - * Calculate the distance between two points using the "haversine" formula. - * This code was taken from http://www.movable-type.co.uk/scripts/latlong.html. - * @param start The starting point - * @param end The end point - * @return The distance between the points in meters - */ -function getDistance(start, end) { - function toRadians(num) { - return num * Math.PI / 180; - } - var lat1 = start.latitude / COORD_FACTOR; - var lat2 = end.latitude / COORD_FACTOR; - var lon1 = start.longitude / COORD_FACTOR; - var lon2 = end.longitude / COORD_FACTOR; - var R = 6371000; // metres - var φ1 = toRadians(lat1); - var φ2 = toRadians(lat2); - var Δφ = toRadians(lat2-lat1); - var Δλ = toRadians(lon2-lon1); - - var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + - Math.cos(φ1) * Math.cos(φ2) * - Math.sin(Δλ/2) * Math.sin(Δλ/2); - var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); - - return R * c; -} - -/** - * recordRoute handler. Gets a stream of points, and responds with statistics - * about the "trip": number of points, number of known features visited, total - * distance traveled, and total time spent. - * @param {Readable} call The request point stream. - * @param {function(Error, routeSummary)} callback The callback to pass the - * response to - */ -function recordRoute(call, callback) { - var point_count = 0; - var feature_count = 0; - var distance = 0; - var previous = null; - // Start a timer - var start_time = process.hrtime(); - call.on('data', function(point) { - point_count += 1; - if (checkFeature(point).name !== '') { - feature_count += 1; - } - /* For each point after the first, add the incremental distance from the - * previous point to the total distance value */ - if (previous !== null) { - distance += getDistance(previous, point); - } - previous = point; - }); - call.on('end', function() { - callback(null, { - point_count: point_count, - feature_count: feature_count, - // Cast the distance to an integer - distance: Math.floor(distance), - // End the timer - elapsed_time: process.hrtime(start_time)[0] - }); - }); -} - -var route_notes = {}; - -/** - * Turn the point into a dictionary key. - * @param {point} point The point to use - * @return {string} The key for an object - */ -function pointKey(point) { - return point.latitude + ' ' + point.longitude; -} - -/** - * routeChat handler. Receives a stream of message/location pairs, and responds - * with a stream of all previous messages at each of those locations. - * @param {Duplex} call The stream for incoming and outgoing messages - */ -function routeChat(call) { - call.on('data', function(note) { - var key = pointKey(note.location); - /* For each note sent, respond with all previous notes that correspond to - * the same point */ - if (route_notes.hasOwnProperty(key)) { - _.each(route_notes[key], function(note) { - call.write(note); - }); - } else { - route_notes[key] = []; - } - // Then add the new note to the list - route_notes[key].push(JSON.parse(JSON.stringify(note))); - }); - call.on('end', function() { - call.end(); - }); -} - -/** - * Get a new server with the handler functions in this file bound to the methods - * it serves. - * @return {Server} The new server object - */ -function getServer() { - var server = new grpc.Server(); - server.addProtoService(examples.RouteGuide.service, { - getFeature: getFeature, - listFeatures: listFeatures, - recordRoute: recordRoute, - routeChat: routeChat - }); - return server; -} - -if (require.main === module) { - // If this is run as a script, start a server on an unused port - var routeServer = getServer(); - routeServer.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure()); - var argv = parseArgs(process.argv, { - string: 'db_path' - }); - fs.readFile(path.resolve(argv.db_path), function(err, data) { - if (err) { - throw err; - } - feature_list = JSON.parse(data); - routeServer.start(); - }); -} - -exports.getServer = getServer; diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 18858fa334..560869e6fa 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -111,17 +111,19 @@ bool CreateMetadataArray(Handle<Object> metadata, grpc_metadata_array *array, NanAssignPersistent(*handle, value); resources->handles.push_back(unique_ptr<PersistentHolder>( new PersistentHolder(handle))); - continue; + } else { + return false; } - } - if (value->IsString()) { - Handle<String> string_value = value->ToString(); - NanUtf8String *utf8_value = new NanUtf8String(string_value); - resources->strings.push_back(unique_ptr<NanUtf8String>(utf8_value)); - current->value = **utf8_value; - current->value_length = string_value->Length(); } else { - return false; + if (value->IsString()) { + Handle<String> string_value = value->ToString(); + NanUtf8String *utf8_value = new NanUtf8String(string_value); + resources->strings.push_back(unique_ptr<NanUtf8String>(utf8_value)); + current->value = **utf8_value; + current->value_length = string_value->Length(); + } else { + return false; + } } array->count += 1; } @@ -156,8 +158,7 @@ Handle<Value> ParseMetadata(const grpc_metadata_array *metadata_array) { } if (EndsWith(elem->key, "-bin")) { array->Set(index_map[elem->key], - MakeFastBuffer( - NanNewBufferHandle(elem->value, elem->value_length))); + NanNewBufferHandle(elem->value, elem->value_length)); } else { array->Set(index_map[elem->key], NanNew(elem->value)); } @@ -460,6 +461,9 @@ void Call::Init(Handle<Object> exports) { NanNew<FunctionTemplate>(StartBatch)->GetFunction()); NanSetPrototypeTemplate(tpl, "cancel", NanNew<FunctionTemplate>(Cancel)->GetFunction()); + NanSetPrototypeTemplate( + tpl, "cancelWithStatus", + NanNew<FunctionTemplate>(CancelWithStatus)->GetFunction()); NanSetPrototypeTemplate(tpl, "getPeer", NanNew<FunctionTemplate>(GetPeer)->GetFunction()); NanAssignPersistent(fun_tpl, tpl); @@ -642,6 +646,26 @@ NAN_METHOD(Call::Cancel) { NanReturnUndefined(); } +NAN_METHOD(Call::CancelWithStatus) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("cancel can only be called on Call objects"); + } + if (!args[0]->IsUint32()) { + return NanThrowTypeError( + "cancelWithStatus's first argument must be a status code"); + } + if (!args[1]->IsString()) { + return NanThrowTypeError( + "cancelWithStatus's second argument must be a string"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + grpc_status_code code = static_cast<grpc_status_code>(args[0]->Uint32Value()); + NanUtf8String details(args[0]); + grpc_call_cancel_with_status(call->wrapped_call, code, *details, NULL); + NanReturnUndefined(); +} + NAN_METHOD(Call::GetPeer) { NanScope(); if (!HasInstance(args.This())) { diff --git a/src/node/ext/call.h b/src/node/ext/call.h index ef6e5fcd21..89f81dcf4d 100644 --- a/src/node/ext/call.h +++ b/src/node/ext/call.h @@ -133,6 +133,7 @@ class Call : public ::node::ObjectWrap { static NAN_METHOD(New); static NAN_METHOD(StartBatch); static NAN_METHOD(Cancel); + static NAN_METHOD(CancelWithStatus); static NAN_METHOD(GetPeer); static NanCallback *constructor; // Used for typechecking instances of this javascript class diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc index a61c830099..9aed96bbf5 100644 --- a/src/node/ext/channel.cc +++ b/src/node/ext/channel.cc @@ -161,7 +161,7 @@ NAN_METHOD(Channel::New) { NULL); } else { wrapped_channel = - grpc_secure_channel_create(creds, *host, channel_args_ptr); + grpc_secure_channel_create(creds, *host, channel_args_ptr, NULL); } if (channel_args_ptr != NULL) { free(channel_args_ptr->args); diff --git a/src/node/ext/credentials.cc b/src/node/ext/credentials.cc index 21d61f1a7f..c3b04dcea7 100644 --- a/src/node/ext/credentials.cc +++ b/src/node/ext/credentials.cc @@ -156,7 +156,8 @@ NAN_METHOD(Credentials::CreateSsl) { "createSSl's third argument must be a Buffer if provided"); } grpc_credentials *creds = grpc_ssl_credentials_create( - root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair); + root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair, + NULL); if (creds == NULL) { NanReturnNull(); } @@ -176,7 +177,7 @@ NAN_METHOD(Credentials::CreateComposite) { Credentials *creds1 = ObjectWrap::Unwrap<Credentials>(args[0]->ToObject()); Credentials *creds2 = ObjectWrap::Unwrap<Credentials>(args[1]->ToObject()); grpc_credentials *creds = grpc_composite_credentials_create( - creds1->wrapped_credentials, creds2->wrapped_credentials); + creds1->wrapped_credentials, creds2->wrapped_credentials, NULL); if (creds == NULL) { NanReturnNull(); } @@ -185,7 +186,7 @@ NAN_METHOD(Credentials::CreateComposite) { NAN_METHOD(Credentials::CreateGce) { NanScope(); - grpc_credentials *creds = grpc_compute_engine_credentials_create(); + grpc_credentials *creds = grpc_google_compute_engine_credentials_create(NULL); if (creds == NULL) { NanReturnNull(); } @@ -202,8 +203,8 @@ NAN_METHOD(Credentials::CreateIam) { } NanUtf8String auth_token(args[0]); NanUtf8String auth_selector(args[1]); - grpc_credentials *creds = grpc_iam_credentials_create(*auth_token, - *auth_selector); + grpc_credentials *creds = + grpc_google_iam_credentials_create(*auth_token, *auth_selector, NULL); if (creds == NULL) { NanReturnNull(); } diff --git a/src/node/ext/server_credentials.cc b/src/node/ext/server_credentials.cc index 6e17197e16..b1201eb664 100644 --- a/src/node/ext/server_credentials.cc +++ b/src/node/ext/server_credentials.cc @@ -178,11 +178,8 @@ NAN_METHOD(ServerCredentials::CreateSsl) { key_cert_pairs[i].cert_chain = ::node::Buffer::Data( pair_obj->Get(cert_key)); } - grpc_server_credentials *creds = - grpc_ssl_server_credentials_create(root_certs, - key_cert_pairs, - key_cert_pair_count, - force_client_auth); + grpc_server_credentials *creds = grpc_ssl_server_credentials_create( + root_certs, key_cert_pairs, key_cert_pair_count, force_client_auth, NULL); delete key_cert_pairs; if (creds == NULL) { NanReturnNull(); diff --git a/src/node/index.js b/src/node/index.js index 889b0ac0e9..02b73f66ee 100644 --- a/src/node/index.js +++ b/src/node/index.js @@ -41,6 +41,8 @@ var client = require('./src/client.js'); var server = require('./src/server.js'); +var Metadata = require('./src/metadata.js'); + var grpc = require('bindings')('grpc'); /** @@ -107,18 +109,12 @@ exports.getGoogleAuthDelegate = function getGoogleAuthDelegate(credential) { * @param {function(Error, Object)} callback */ return function updateMetadata(authURI, metadata, callback) { - metadata = _.clone(metadata); - if (metadata.Authorization) { - metadata.Authorization = _.clone(metadata.Authorization); - } else { - metadata.Authorization = []; - } credential.getRequestMetadata(authURI, function(err, header) { if (err) { callback(err); return; } - metadata.Authorization.push(header.Authorization); + metadata.add('authorization', header.Authorization); callback(null, metadata); }); }; @@ -130,6 +126,11 @@ exports.getGoogleAuthDelegate = function getGoogleAuthDelegate(credential) { exports.Server = server.Server; /** + * @see module:src/metadata + */ +exports.Metadata = Metadata; + +/** * Status name to code number mapping */ exports.status = grpc.status; @@ -163,3 +164,13 @@ exports.ServerCredentials = grpc.ServerCredentials; * @see module:src/client.makeClientConstructor */ exports.makeGenericClientConstructor = client.makeClientConstructor; + +/** + * @see module:src/client.getClientChannel + */ +exports.getClientChannel = client.getClientChannel; + +/** + * @see module:src/client.waitForClientReady + */ +exports.waitForClientReady = client.waitForClientReady; diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js index 612dcf01f6..6a8d2633ca 100644 --- a/src/node/interop/interop_client.js +++ b/src/node/interop/interop_client.js @@ -285,7 +285,7 @@ function authTest(expected_user, scope, client, done) { if (credential.createScopedRequired() && scope) { credential = credential.createScoped(scope); } - client.updateMetadata = grpc.getGoogleAuthDelegate(credential); + client.$updateMetadata = grpc.getGoogleAuthDelegate(credential); var arg = { response_type: 'COMPRESSABLE', response_size: 314159, @@ -321,13 +321,7 @@ function oauth2Test(expected_user, scope, per_rpc, client, done) { credential.getAccessToken(function(err, token) { assert.ifError(err); var updateMetadata = function(authURI, metadata, callback) { - metadata = _.clone(metadata); - if (metadata.Authorization) { - metadata.Authorization = _.clone(metadata.Authorization); - } else { - metadata.Authorization = []; - } - metadata.Authorization.push('Bearer ' + token); + metadata.Add('authorization', 'Bearer ' + token); callback(null, metadata); }; var makeTestCall = function(error, client_metadata) { @@ -344,7 +338,7 @@ function oauth2Test(expected_user, scope, per_rpc, client, done) { if (per_rpc) { updateMetadata('', {}, makeTestCall); } else { - client.updateMetadata = updateMetadata; + client.$updateMetadata = updateMetadata; makeTestCall(null, {}); } }); diff --git a/src/node/package.json b/src/node/package.json index 756d41b0af..bb8987cc0d 100644 --- a/src/node/package.json +++ b/src/node/package.json @@ -1,6 +1,6 @@ { "name": "grpc", - "version": "0.10.0", + "version": "0.11.0", "author": "Google Inc.", "description": "gRPC Library for Node", "homepage": "http://www.grpc.io/", diff --git a/src/node/src/client.js b/src/node/src/client.js index 7b7eae51d2..b427297a8a 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -32,7 +32,7 @@ */ /** - * Server module + * Client module * @module */ @@ -42,7 +42,9 @@ var _ = require('lodash'); var grpc = require('bindings')('grpc.node'); -var common = require('./common.js'); +var common = require('./common'); + +var Metadata = require('./metadata'); var EventEmitter = require('events').EventEmitter; @@ -140,7 +142,14 @@ function _read(size) { return; } var data = event.read; - if (self.push(self.deserialize(data)) && data !== null) { + var deserialized; + try { + deserialized = self.deserialize(data); + } catch (e) { + self.call.cancelWithStatus(grpc.status.INTERNAL, + 'Failed to parse server response'); + } + if (self.push(deserialized) && data !== null) { var read_batch = {}; read_batch[grpc.opType.RECV_MESSAGE] = true; self.call.startBatch(read_batch, readCallback); @@ -254,17 +263,18 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { * serialize * @param {function(?Error, value=)} callback The callback to for when the * response is received - * @param {array=} metadata Array of metadata key/value pairs to add to the - * call + * @param {Metadata=} metadata Metadata to add to the call * @param {Object=} options Options map * @return {EventEmitter} An event emitter for stream related events */ function makeUnaryRequest(argument, callback, metadata, options) { /* jshint validthis: true */ var emitter = new EventEmitter(); - var call = getCall(this.channel, method, options); + var call = getCall(this.$channel, method, options); if (metadata === null || metadata === undefined) { - metadata = {}; + metadata = new Metadata(); + } else { + metadata = metadata.clone(); } emitter.cancel = function cancel() { call.cancel(); @@ -272,7 +282,7 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { emitter.getPeer = function getPeer() { return call.getPeer(); }; - this.updateMetadata(this.auth_uri, metadata, function(error, metadata) { + this.$updateMetadata(this.$auth_uri, metadata, function(error, metadata) { if (error) { call.cancel(); callback(error); @@ -283,29 +293,48 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { if (options) { message.grpcWriteFlags = options.flags; } - client_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + client_batch[grpc.opType.SEND_INITIAL_METADATA] = + metadata._getCoreRepresentation(); client_batch[grpc.opType.SEND_MESSAGE] = message; client_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; client_batch[grpc.opType.RECV_INITIAL_METADATA] = true; client_batch[grpc.opType.RECV_MESSAGE] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { - emitter.emit('status', response.status); - if (response.status.code !== grpc.status.OK) { - var error = new Error(response.status.details); - error.code = response.status.code; - error.metadata = response.status.metadata; - callback(error); - return; - } else { + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); + var status = response.status; + var error; + var deserialized; + if (status.code === grpc.status.OK) { if (err) { // Got a batch error, but OK status. Something went wrong callback(err); return; + } else { + try { + deserialized = deserialize(response.read); + } catch (e) { + /* Change status to indicate bad server response. This will result + * in passing an error to the callback */ + status = { + code: grpc.status.INTERNAL, + details: 'Failed to parse server response' + }; + } } } - emitter.emit('metadata', response.metadata); - callback(null, deserialize(response.read)); + if (status.code !== grpc.status.OK) { + error = new Error(response.status.details); + error.code = status.code; + error.metadata = status.metadata; + callback(error); + } else { + callback(null, deserialized); + } + emitter.emit('status', status); + emitter.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); }); }); return emitter; @@ -328,26 +357,29 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { * @this {Client} Client object. Must have a channel member. * @param {function(?Error, value=)} callback The callback to for when the * response is received - * @param {array=} metadata Array of metadata key/value pairs to add to the + * @param {Metadata=} metadata Array of metadata key/value pairs to add to the * call * @param {Object=} options Options map * @return {EventEmitter} An event emitter for stream related events */ function makeClientStreamRequest(callback, metadata, options) { /* jshint validthis: true */ - var call = getCall(this.channel, method, options); + var call = getCall(this.$channel, method, options); if (metadata === null || metadata === undefined) { - metadata = {}; + metadata = new Metadata(); + } else { + metadata = metadata.clone(); } var stream = new ClientWritableStream(call, serialize); - this.updateMetadata(this.auth_uri, metadata, function(error, metadata) { + this.$updateMetadata(this.$auth_uri, metadata, function(error, metadata) { if (error) { call.cancel(); callback(error); return; } var metadata_batch = {}; - metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + metadata_batch[grpc.opType.SEND_INITIAL_METADATA] = + metadata._getCoreRepresentation(); metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true; call.startBatch(metadata_batch, function(err, response) { if (err) { @@ -355,27 +387,45 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { // in the other batch. return; } - stream.emit('metadata', response.metadata); + stream.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); }); var client_batch = {}; client_batch[grpc.opType.RECV_MESSAGE] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { - stream.emit('status', response.status); - if (response.status.code !== grpc.status.OK) { - var error = new Error(response.status.details); - error.code = response.status.code; - error.metadata = response.status.metadata; - callback(error); - return; - } else { + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); + var status = response.status; + var error; + var deserialized; + if (status.code === grpc.status.OK) { if (err) { // Got a batch error, but OK status. Something went wrong callback(err); return; + } else { + try { + deserialized = deserialize(response.read); + } catch (e) { + /* Change status to indicate bad server response. This will result + * in passing an error to the callback */ + status = { + code: grpc.status.INTERNAL, + details: 'Failed to parse server response' + }; + } } } - callback(null, deserialize(response.read)); + if (status.code !== grpc.status.OK) { + error = new Error(response.status.details); + error.code = status.code; + error.metadata = status.metadata; + callback(error); + } else { + callback(null, deserialized); + } + stream.emit('status', status); }); }); return stream; @@ -398,19 +448,21 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { * @this {SurfaceClient} Client object. Must have a channel member. * @param {*} argument The argument to the call. Should be serializable with * serialize - * @param {array=} metadata Array of metadata key/value pairs to add to the + * @param {Metadata=} metadata Array of metadata key/value pairs to add to the * call * @param {Object} options Options map * @return {EventEmitter} An event emitter for stream related events */ function makeServerStreamRequest(argument, metadata, options) { /* jshint validthis: true */ - var call = getCall(this.channel, method, options); + var call = getCall(this.$channel, method, options); if (metadata === null || metadata === undefined) { - metadata = {}; + metadata = new Metadata(); + } else { + metadata = metadata.clone(); } var stream = new ClientReadableStream(call, deserialize); - this.updateMetadata(this.auth_uri, metadata, function(error, metadata) { + this.$updateMetadata(this.$auth_uri, metadata, function(error, metadata) { if (error) { call.cancel(); stream.emit('error', error); @@ -421,7 +473,8 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { if (options) { message.grpcWriteFlags = options.flags; } - start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + start_batch[grpc.opType.SEND_INITIAL_METADATA] = + metadata._getCoreRepresentation(); start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; start_batch[grpc.opType.SEND_MESSAGE] = message; start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true; @@ -431,11 +484,14 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { // in the other batch. return; } - stream.emit('metadata', response.metadata); + stream.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); }); var status_batch = {}; status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(status_batch, function(err, response) { + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); stream.emit('status', response.status); if (response.status.code !== grpc.status.OK) { var error = new Error(response.status.details); @@ -470,26 +526,29 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { /** * Make a bidirectional stream request with this method on the given channel. * @this {SurfaceClient} Client object. Must have a channel member. - * @param {array=} metadata Array of metadata key/value pairs to add to the + * @param {Metadata=} metadata Array of metadata key/value pairs to add to the * call * @param {Options} options Options map * @return {EventEmitter} An event emitter for stream related events */ function makeBidiStreamRequest(metadata, options) { /* jshint validthis: true */ - var call = getCall(this.channel, method, options); + var call = getCall(this.$channel, method, options); if (metadata === null || metadata === undefined) { - metadata = {}; + metadata = new Metadata(); + } else { + metadata = metadata.clone(); } var stream = new ClientDuplexStream(call, serialize, deserialize); - this.updateMetadata(this.auth_uri, metadata, function(error, metadata) { + this.$updateMetadata(this.$auth_uri, metadata, function(error, metadata) { if (error) { call.cancel(); stream.emit('error', error); return; } var start_batch = {}; - start_batch[grpc.opType.SEND_INITIAL_METADATA] = metadata; + start_batch[grpc.opType.SEND_INITIAL_METADATA] = + metadata._getCoreRepresentation(); start_batch[grpc.opType.RECV_INITIAL_METADATA] = true; call.startBatch(start_batch, function(err, response) { if (err) { @@ -497,11 +556,14 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { // in the other batch. return; } - stream.emit('metadata', response.metadata); + stream.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); }); var status_batch = {}; status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(status_batch, function(err, response) { + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); stream.emit('status', response.status); if (response.status.code !== grpc.status.OK) { var error = new Error(response.status.details); @@ -569,45 +631,21 @@ exports.makeClientConstructor = function(methods, serviceName) { options = {}; } options['grpc.primary_user_agent'] = 'grpc-node/' + version; - this.channel = new grpc.Channel(address, credentials, options); + /* Private fields use $ as a prefix instead of _ because it is an invalid + * prefix of a method name */ + this.$channel = new grpc.Channel(address, credentials, options); // Remove the optional DNS scheme, trailing port, and trailing backslash address = address.replace(/^(dns:\/{3})?([^:\/]+)(:\d+)?\/?$/, '$2'); - this.server_address = address; - this.auth_uri = 'https://' + this.server_address + '/' + serviceName; - this.updateMetadata = updateMetadata; + this.$server_address = address; + this.$auth_uri = 'https://' + this.server_address + '/' + serviceName; + this.$updateMetadata = updateMetadata; } - /** - * Wait for the client to be ready. The callback will be called when the - * client has successfully connected to the server, and it will be called - * with an error if the attempt to connect to the server has unrecoverablly - * failed or if the deadline expires. This function will make the channel - * start connecting if it has not already done so. - * @param {(Date|Number)} deadline When to stop waiting for a connection. Pass - * Infinity to wait forever. - * @param {function(Error)} callback The callback to call when done attempting - * to connect. - */ - Client.prototype.$waitForReady = function(deadline, callback) { - var self = this; - var checkState = function(err) { - if (err) { - callback(new Error('Failed to connect before the deadline')); - } - var new_state = self.channel.getConnectivityState(true); - if (new_state === grpc.connectivityState.READY) { - callback(); - } else if (new_state === grpc.connectivityState.FATAL_FAILURE) { - callback(new Error('Failed to connect to server')); - } else { - self.channel.watchConnectivityState(new_state, deadline, checkState); - } - }; - checkState(); - }; - _.each(methods, function(attrs, name) { var method_type; + if (_.startsWith(name, '$')) { + throw new Error('Method names cannot start with $'); + } if (attrs.requestStream) { if (attrs.responseStream) { method_type = 'bidi'; @@ -633,6 +671,44 @@ exports.makeClientConstructor = function(methods, serviceName) { }; /** + * Return the underlying channel object for the specified client + * @param {Client} client + * @return {Channel} The channel + */ +exports.getClientChannel = function(client) { + return client.$channel; +}; + +/** + * Wait for the client to be ready. The callback will be called when the + * client has successfully connected to the server, and it will be called + * with an error if the attempt to connect to the server has unrecoverablly + * failed or if the deadline expires. This function will make the channel + * start connecting if it has not already done so. + * @param {Client} client The client to wait on + * @param {(Date|Number)} deadline When to stop waiting for a connection. Pass + * Infinity to wait forever. + * @param {function(Error)} callback The callback to call when done attempting + * to connect. + */ +exports.waitForClientReady = function(client, deadline, callback) { + var checkState = function(err) { + if (err) { + callback(new Error('Failed to connect before the deadline')); + } + var new_state = client.$channel.getConnectivityState(true); + if (new_state === grpc.connectivityState.READY) { + callback(); + } else if (new_state === grpc.connectivityState.FATAL_FAILURE) { + callback(new Error('Failed to connect to server')); + } else { + client.$channel.watchConnectivityState(new_state, deadline, checkState); + } + }; + checkState(); +}; + +/** * Creates a constructor for clients for the given service * @param {ProtoBuf.Reflect.Service} service The service to generate a client * for diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js new file mode 100644 index 0000000000..c1da70b197 --- /dev/null +++ b/src/node/src/metadata.js @@ -0,0 +1,181 @@ +/* + * + * 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. + * + */ + +/** + * Metadata module + * @module + */ + +'use strict'; + +var _ = require('lodash'); + +/** + * Class for storing metadata. Keys are normalized to lowercase ASCII. + * @constructor + */ +function Metadata() { + this._internal_repr = {}; +} + +function normalizeKey(key) { + if (!(/^[A-Za-z\d_-]+$/.test(key))) { + throw new Error('Metadata keys must be nonempty strings containing only ' + + 'alphanumeric characters and hyphens'); + } + return key.toLowerCase(); +} + +function validate(key, value) { + if (_.endsWith(key, '-bin')) { + if (!(value instanceof Buffer)) { + throw new Error('keys that end with \'-bin\' must have Buffer values'); + } + } else { + if (!_.isString(value)) { + throw new Error( + 'keys that don\'t end with \'-bin\' must have String values'); + } + if (!(/^[\x20-\x7E]*$/.test(value))) { + throw new Error('Metadata string values can only contain printable ' + + 'ASCII characters and space'); + } + } +} + +/** + * Sets the given value for the given key, replacing any other values associated + * with that key. Normalizes the key. + * @param {String} key The key to set + * @param {String|Buffer} value The value to set. Must be a buffer if and only + * if the normalized key ends with '-bin' + */ +Metadata.prototype.set = function(key, value) { + key = normalizeKey(key); + validate(key, value); + this._internal_repr[key] = [value]; +}; + +/** + * Adds the given value for the given key. Normalizes the key. + * @param {String} key The key to add to. + * @param {String|Buffer} value The value to add. Must be a buffer if and only + * if the normalized key ends with '-bin' + */ +Metadata.prototype.add = function(key, value) { + key = normalizeKey(key); + validate(key, value); + if (!this._internal_repr[key]) { + this._internal_repr[key] = []; + } + this._internal_repr[key].push(value); +}; + +/** + * Remove the given key and any associated values. Normalizes the key. + * @param {String} key The key to remove + */ +Metadata.prototype.remove = function(key) { + key = normalizeKey(key); + if (Object.prototype.hasOwnProperty.call(this._internal_repr, key)) { + delete this._internal_repr[key]; + } +}; + +/** + * Gets a list of all values associated with the key. Normalizes the key. + * @param {String} key The key to get + * @return {Array.<String|Buffer>} The values associated with that key + */ +Metadata.prototype.get = function(key) { + key = normalizeKey(key); + if (Object.prototype.hasOwnProperty.call(this._internal_repr, key)) { + return this._internal_repr[key]; + } else { + return []; + } +}; + +/** + * Get a map of each key to a single associated value. This reflects the most + * common way that people will want to see metadata. + * @return {Object.<String,String|Buffer>} A key/value mapping of the metadata + */ +Metadata.prototype.getMap = function() { + var result = {}; + _.forOwn(this._internal_repr, function(values, key) { + if(values.length > 0) { + result[key] = values[0]; + } + }); + return result; +}; + +/** + * Clone the metadata object. + * @return {Metadata} The new cloned object + */ +Metadata.prototype.clone = function() { + var copy = new Metadata(); + _.forOwn(this._internal_repr, function(value, key) { + copy._internal_repr[key] = _.clone(value); + }); + return copy; +}; + +/** + * Gets the metadata in the format used by interal code. Intended for internal + * use only. API stability is not guaranteed. + * @private + * @return {Object.<String, Array.<String|Buffer>>} The metadata + */ +Metadata.prototype._getCoreRepresentation = function() { + return this._internal_repr; +}; + +/** + * Creates a Metadata object from a metadata map in the internal format. + * Intended for internal use only. API stability is not guaranteed. + * @private + * @param {Object.<String, Array.<String|Buffer>>} The metadata + * @return {Metadata} The new Metadata object + */ +Metadata._fromCoreRepresentation = function(metadata) { + var newMetadata = new Metadata(); + if (metadata) { + newMetadata._internal_repr = _.cloneDeep(metadata); + } + return newMetadata; +}; + +module.exports = Metadata; diff --git a/src/node/src/server.js b/src/node/src/server.js index 137f60ed12..b6f162adf8 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -44,6 +44,8 @@ var grpc = require('bindings')('grpc.node'); var common = require('./common'); +var Metadata = require('./metadata'); + var stream = require('stream'); var Readable = stream.Readable; @@ -60,10 +62,10 @@ var EventEmitter = require('events').EventEmitter; * @param {Object} error The error object */ function handleError(call, error) { + var statusMetadata = new Metadata(); var status = { code: grpc.status.UNKNOWN, - details: 'Unknown Error', - metadata: {} + details: 'Unknown Error' }; if (error.hasOwnProperty('message')) { status.details = error.message; @@ -75,11 +77,13 @@ function handleError(call, error) { } } if (error.hasOwnProperty('metadata')) { - status.metadata = error.metadata; + statusMetadata = error.metadata; } + status.metadata = statusMetadata._getCoreRepresentation(); var error_batch = {}; if (!call.metadataSent) { - error_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + error_batch[grpc.opType.SEND_INITIAL_METADATA] = + (new Metadata())._getCoreRepresentation(); } error_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = status; call.startBatch(error_batch, function(){}); @@ -114,22 +118,24 @@ function waitForCancel(call, emitter) { * @param {*} value The value to respond with * @param {function(*):Buffer=} serialize Serialization function for the * response - * @param {Object=} metadata Optional trailing metadata to send with status + * @param {Metadata=} metadata Optional trailing metadata to send with status * @param {number=} flags Flags for modifying how the message is sent. * Defaults to 0. */ function sendUnaryResponse(call, value, serialize, metadata, flags) { var end_batch = {}; + var statusMetadata = new Metadata(); var status = { code: grpc.status.OK, - details: 'OK', - metadata: {} + details: 'OK' }; if (metadata) { - status.metadata = metadata; + statusMetadata = metadata; } + status.metadata = statusMetadata._getCoreRepresentation(); if (!call.metadataSent) { - end_batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + end_batch[grpc.opType.SEND_INITIAL_METADATA] = + (new Metadata())._getCoreRepresentation(); call.metadataSent = true; } var message = serialize(value); @@ -151,14 +157,19 @@ function setUpWritable(stream, serialize) { stream.status = { code : grpc.status.OK, details : 'OK', - metadata : {} + metadata : new Metadata() }; stream.serialize = common.wrapIgnoreNull(serialize); function sendStatus() { var batch = {}; if (!stream.call.metadataSent) { stream.call.metadataSent = true; - batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = + (new Metadata())._getCoreRepresentation(); + } + + if (stream.status.metadata) { + stream.status.metadata = stream.status.metadata._getCoreRepresentation(); } batch[grpc.opType.SEND_STATUS_FROM_SERVER] = stream.status; stream.call.startBatch(batch, function(){}); @@ -173,7 +184,7 @@ function setUpWritable(stream, serialize) { function setStatus(err) { var code = grpc.status.UNKNOWN; var details = 'Unknown Error'; - var metadata = {}; + var metadata = new Metadata(); if (err.hasOwnProperty('message')) { details = err.message; } @@ -203,7 +214,7 @@ function setUpWritable(stream, serialize) { /** * Override of Writable#end method that allows for sending metadata with a * success status. - * @param {Object=} metadata Metadata to send with the status + * @param {Metadata=} metadata Metadata to send with the status */ stream.end = function(metadata) { if (metadata) { @@ -266,7 +277,8 @@ function _write(chunk, encoding, callback) { /* jshint validthis: true */ var batch = {}; if (!this.call.metadataSent) { - batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = + (new Metadata())._getCoreRepresentation(); this.call.metadataSent = true; } var message = this.serialize(chunk); @@ -289,15 +301,15 @@ ServerWritableStream.prototype._write = _write; /** * Send the initial metadata for a writable stream. - * @param {Object<String, Array<(String|Buffer)>>} responseMetadata Metadata - * to send + * @param {Metadata} responseMetadata Metadata to send */ function sendMetadata(responseMetadata) { /* jshint validthis: true */ if (!this.call.metadataSent) { this.call.metadataSent = true; var batch = []; - batch[grpc.opType.SEND_INITIAL_METADATA] = responseMetadata; + batch[grpc.opType.SEND_INITIAL_METADATA] = + responseMetadata._getCoreRepresentation(); this.call.startBatch(batch, function(err) { if (err) { this.emit('error', err); @@ -422,7 +434,7 @@ ServerDuplexStream.prototype.getPeer = getPeer; * @access private * @param {grpc.Call} call The call to handle * @param {Object} handler Request handler object for the method that was called - * @param {Object} metadata Metadata from the client + * @param {Metadata} metadata Metadata from the client */ function handleUnary(call, handler, metadata) { var emitter = new EventEmitter(); @@ -430,7 +442,8 @@ function handleUnary(call, handler, metadata) { if (!call.metadataSent) { call.metadataSent = true; var batch = {}; - batch[grpc.opType.SEND_INITIAL_METADATA] = responseMetadata; + batch[grpc.opType.SEND_INITIAL_METADATA] = + responseMetadata._getCoreRepresentation(); call.startBatch(batch, function() {}); } }; @@ -478,7 +491,7 @@ function handleUnary(call, handler, metadata) { * @access private * @param {grpc.Call} call The call to handle * @param {Object} handler Request handler object for the method that was called - * @param {Object} metadata Metadata from the client + * @param {Metadata} metadata Metadata from the client */ function handleServerStreaming(call, handler, metadata) { var stream = new ServerWritableStream(call, handler.serialize); @@ -507,7 +520,7 @@ function handleServerStreaming(call, handler, metadata) { * @access private * @param {grpc.Call} call The call to handle * @param {Object} handler Request handler object for the method that was called - * @param {Object} metadata Metadata from the client + * @param {Metadata} metadata Metadata from the client */ function handleClientStreaming(call, handler, metadata) { var stream = new ServerReadableStream(call, handler.deserialize); @@ -515,7 +528,8 @@ function handleClientStreaming(call, handler, metadata) { if (!call.metadataSent) { call.metadataSent = true; var batch = {}; - batch[grpc.opType.SEND_INITIAL_METADATA] = responseMetadata; + batch[grpc.opType.SEND_INITIAL_METADATA] = + responseMetadata._getCoreRepresentation(); call.startBatch(batch, function() {}); } }; @@ -542,7 +556,7 @@ function handleClientStreaming(call, handler, metadata) { * @access private * @param {grpc.Call} call The call to handle * @param {Object} handler Request handler object for the method that was called - * @param {Object} metadata Metadata from the client + * @param {Metadata} metadata Metadata from the client */ function handleBidiStreaming(call, handler, metadata) { var stream = new ServerDuplexStream(call, handler.serialize, @@ -599,7 +613,7 @@ function Server(options) { var details = event.new_call; var call = details.call; var method = details.method; - var metadata = details.metadata; + var metadata = Metadata._fromCoreRepresentation(details.metadata); if (method === null) { return; } @@ -609,7 +623,8 @@ function Server(options) { handler = handlers[method]; } else { var batch = {}; - batch[grpc.opType.SEND_INITIAL_METADATA] = {}; + batch[grpc.opType.SEND_INITIAL_METADATA] = + (new Metadata())._getCoreRepresentation(); batch[grpc.opType.SEND_STATUS_FROM_SERVER] = { code: grpc.status.UNIMPLEMENTED, details: 'This method is not available on this server.', diff --git a/src/node/test/metadata_test.js b/src/node/test/metadata_test.js new file mode 100644 index 0000000000..86383f1bad --- /dev/null +++ b/src/node/test/metadata_test.js @@ -0,0 +1,193 @@ +/* + * + * 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. + * + */ + +'use strict'; + +var Metadata = require('../src/metadata.js'); + +var assert = require('assert'); + +describe('Metadata', function() { + var metadata; + beforeEach(function() { + metadata = new Metadata(); + }); + describe('#set', function() { + it('Only accepts string values for non "-bin" keys', function() { + assert.throws(function() { + metadata.set('key', new Buffer('value')); + }); + assert.doesNotThrow(function() { + metadata.set('key', 'value'); + }); + }); + it('Only accepts Buffer values for "-bin" keys', function() { + assert.throws(function() { + metadata.set('key-bin', 'value'); + }); + assert.doesNotThrow(function() { + metadata.set('key-bin', new Buffer('value')); + }); + }); + it('Rejects invalid keys', function() { + assert.throws(function() { + metadata.set('key$', 'value'); + }); + assert.throws(function() { + metadata.set('', 'value'); + }); + }); + it('Rejects values with non-ASCII characters', function() { + assert.throws(function() { + metadata.set('key', 'résumé'); + }); + }); + it('Saves values that can be retrieved', function() { + metadata.set('key', 'value'); + assert.deepEqual(metadata.get('key'), ['value']); + }); + it('Overwrites previous values', function() { + metadata.set('key', 'value1'); + metadata.set('key', 'value2'); + assert.deepEqual(metadata.get('key'), ['value2']); + }); + it('Normalizes keys', function() { + metadata.set('Key', 'value1'); + assert.deepEqual(metadata.get('key'), ['value1']); + metadata.set('KEY', 'value2'); + assert.deepEqual(metadata.get('key'), ['value2']); + }); + }); + describe('#add', function() { + it('Only accepts string values for non "-bin" keys', function() { + assert.throws(function() { + metadata.add('key', new Buffer('value')); + }); + assert.doesNotThrow(function() { + metadata.add('key', 'value'); + }); + }); + it('Only accepts Buffer values for "-bin" keys', function() { + assert.throws(function() { + metadata.add('key-bin', 'value'); + }); + assert.doesNotThrow(function() { + metadata.add('key-bin', new Buffer('value')); + }); + }); + it('Rejects invalid keys', function() { + assert.throws(function() { + metadata.add('key$', 'value'); + }); + assert.throws(function() { + metadata.add('', 'value'); + }); + }); + it('Saves values that can be retrieved', function() { + metadata.add('key', 'value'); + assert.deepEqual(metadata.get('key'), ['value']); + }); + it('Combines with previous values', function() { + metadata.add('key', 'value1'); + metadata.add('key', 'value2'); + assert.deepEqual(metadata.get('key'), ['value1', 'value2']); + }); + it('Normalizes keys', function() { + metadata.add('Key', 'value1'); + assert.deepEqual(metadata.get('key'), ['value1']); + metadata.add('KEY', 'value2'); + assert.deepEqual(metadata.get('key'), ['value1', 'value2']); + }); + }); + describe('#remove', function() { + it('clears values from a key', function() { + metadata.add('key', 'value'); + metadata.remove('key'); + assert.deepEqual(metadata.get('key'), []); + }); + it('Normalizes keys', function() { + metadata.add('key', 'value'); + metadata.remove('KEY'); + assert.deepEqual(metadata.get('key'), []); + }); + }); + describe('#get', function() { + beforeEach(function() { + metadata.add('key', 'value1'); + metadata.add('key', 'value2'); + metadata.add('key-bin', new Buffer('value')); + }); + it('gets all values associated with a key', function() { + assert.deepEqual(metadata.get('key'), ['value1', 'value2']); + }); + it('Normalizes keys', function() { + assert.deepEqual(metadata.get('KEY'), ['value1', 'value2']); + }); + it('returns an empty list for non-existent keys', function() { + assert.deepEqual(metadata.get('non-existent-key'), []); + }); + it('returns Buffers for "-bin" keys', function() { + assert(metadata.get('key-bin')[0] instanceof Buffer); + }); + }); + describe('#getMap', function() { + it('gets a map of keys to values', function() { + metadata.add('key1', 'value1'); + metadata.add('Key2', 'value2'); + metadata.add('KEY3', 'value3'); + assert.deepEqual(metadata.getMap(), + {key1: 'value1', + key2: 'value2', + key3: 'value3'}); + }); + }); + describe('#clone', function() { + it('retains values from the original', function() { + metadata.add('key', 'value'); + var copy = metadata.clone(); + assert.deepEqual(copy.get('key'), ['value']); + }); + it('Does not see newly added values', function() { + metadata.add('key', 'value1'); + var copy = metadata.clone(); + metadata.add('key', 'value2'); + assert.deepEqual(copy.get('key'), ['value1']); + }); + it('Does not add new values to the original', function() { + metadata.add('key', 'value1'); + var copy = metadata.clone(); + copy.add('key', 'value2'); + assert.deepEqual(metadata.get('key'), ['value1']); + }); + }); +}); diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index 6e45871fc8..d917c7a171 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -133,7 +133,25 @@ describe('Server.prototype.addProtoService', function() { }); }); }); -describe('Client#$waitForReady', function() { +describe('Client constructor building', function() { + var illegal_service_attrs = { + $method : { + path: '/illegal/$method', + requestStream: false, + responseStream: false, + requestSerialize: _.identity, + requestDeserialize: _.identity, + responseSerialize: _.identity, + responseDeserialize: _.identity + } + }; + it('Should reject method names starting with $', function() { + assert.throws(function() { + grpc.makeGenericClientConstructor(illegal_service_attrs); + }, /\$/); + }); +}); +describe('waitForClientReady', function() { var server; var port; var Client; @@ -151,13 +169,13 @@ describe('Client#$waitForReady', function() { server.forceShutdown(); }); it('should complete when called alone', function(done) { - client.$waitForReady(Infinity, function(error) { + grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); }); it('should complete when a call is initiated', function(done) { - client.$waitForReady(Infinity, function(error) { + grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); @@ -166,19 +184,19 @@ describe('Client#$waitForReady', function() { }); it('should complete if called more than once', function(done) { done = multiDone(done, 2); - client.$waitForReady(Infinity, function(error) { + grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); - client.$waitForReady(Infinity, function(error) { + grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); }); it('should complete if called when already ready', function(done) { - client.$waitForReady(Infinity, function(error) { + grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); - client.$waitForReady(Infinity, function(error) { + grpc.waitForClientReady(client, Infinity, function(error) { assert.ifError(error); done(); }); @@ -262,6 +280,7 @@ describe('Generic client and server', function() { describe('Echo metadata', function() { var client; var server; + var metadata; before(function() { var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto'); var test_service = test_proto.lookup('TestService'); @@ -294,6 +313,8 @@ describe('Echo metadata', function() { var Client = surface_client.makeProtobufClientConstructor(test_service); client = new Client('localhost:' + port, grpc.Credentials.createInsecure()); server.start(); + metadata = new grpc.Metadata(); + metadata.set('key', 'value'); }); after(function() { server.forceShutdown(); @@ -301,35 +322,35 @@ describe('Echo metadata', function() { it('with unary call', function(done) { var call = client.unary({}, function(err, data) { assert.ifError(err); - }, {key: ['value']}); + }, metadata); call.on('metadata', function(metadata) { - assert.deepEqual(metadata.key, ['value']); + assert.deepEqual(metadata.get('key'), ['value']); done(); }); }); it('with client stream call', function(done) { var call = client.clientStream(function(err, data) { assert.ifError(err); - }, {key: ['value']}); + }, metadata); call.on('metadata', function(metadata) { - assert.deepEqual(metadata.key, ['value']); + assert.deepEqual(metadata.get('key'), ['value']); done(); }); call.end(); }); it('with server stream call', function(done) { - var call = client.serverStream({}, {key: ['value']}); + var call = client.serverStream({}, metadata); call.on('data', function() {}); call.on('metadata', function(metadata) { - assert.deepEqual(metadata.key, ['value']); + assert.deepEqual(metadata.get('key'), ['value']); done(); }); }); it('with bidi stream call', function(done) { - var call = client.bidiStream({key: ['value']}); + var call = client.bidiStream(metadata); call.on('data', function() {}); call.on('metadata', function(metadata) { - assert.deepEqual(metadata.key, ['value']); + assert.deepEqual(metadata.get('key'), ['value']); done(); }); call.end(); @@ -337,9 +358,10 @@ describe('Echo metadata', function() { it('shows the correct user-agent string', function(done) { var version = require('../package.json').version; var call = client.unary({}, function(err, data) { assert.ifError(err); }, - {key: ['value']}); + metadata); call.on('metadata', function(metadata) { - assert(_.startsWith(metadata['user-agent'], 'grpc-node/' + version)); + assert(_.startsWith(metadata.get('user-agent')[0], + 'grpc-node/' + version)); done(); }); }); @@ -354,13 +376,15 @@ describe('Other conditions', function() { var test_proto = ProtoBuf.loadProtoFile(__dirname + '/test_service.proto'); test_service = test_proto.lookup('TestService'); server = new grpc.Server(); + var trailer_metadata = new grpc.Metadata(); + trailer_metadata.add('trailer-present', 'yes'); server.addProtoService(test_service, { unary: function(call, cb) { var req = call.request; if (req.error) { - cb(new Error('Requested error'), null, {trailer_present: ['yes']}); + cb(new Error('Requested error'), null, trailer_metadata); } else { - cb(null, {count: 1}, {trailer_present: ['yes']}); + cb(null, {count: 1}, trailer_metadata); } }, clientStream: function(stream, cb){ @@ -369,14 +393,14 @@ describe('Other conditions', function() { stream.on('data', function(data) { if (data.error) { errored = true; - cb(new Error('Requested error'), null, {trailer_present: ['yes']}); + cb(new Error('Requested error'), null, trailer_metadata); } else { count += 1; } }); stream.on('end', function() { if (!errored) { - cb(null, {count: count}, {trailer_present: ['yes']}); + cb(null, {count: count}, trailer_metadata); } }); }, @@ -384,13 +408,13 @@ describe('Other conditions', function() { var req = stream.request; if (req.error) { var err = new Error('Requested error'); - err.metadata = {trailer_present: ['yes']}; + err.metadata = trailer_metadata; stream.emit('error', err); } else { for (var i = 0; i < 5; i++) { stream.write({count: i}); } - stream.end({trailer_present: ['yes']}); + stream.end(trailer_metadata); } }, bidiStream: function(stream) { @@ -398,10 +422,8 @@ describe('Other conditions', function() { stream.on('data', function(data) { if (data.error) { var err = new Error('Requested error'); - err.metadata = { - trailer_present: ['yes'], - count: ['' + count] - }; + err.metadata = trailer_metadata.clone(); + err.metadata.add('count', '' + count); stream.emit('error', err); } else { stream.write({count: count}); @@ -409,7 +431,7 @@ describe('Other conditions', function() { } }); stream.on('end', function() { - stream.end({trailer_present: ['yes']}); + stream.end(trailer_metadata); }); } }); @@ -422,7 +444,8 @@ describe('Other conditions', function() { server.forceShutdown(); }); it('channel.getTarget should be available', function() { - assert.strictEqual(typeof client.channel.getTarget(), 'string'); + assert.strictEqual(typeof grpc.getClientChannel(client).getTarget(), + 'string'); }); describe('Server recieving bad input', function() { var misbehavingClient; @@ -510,7 +533,7 @@ describe('Other conditions', function() { assert.ifError(err); }); call.on('status', function(status) { - assert.deepEqual(status.metadata.trailer_present, ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -519,7 +542,7 @@ describe('Other conditions', function() { assert(err); }); call.on('status', function(status) { - assert.deepEqual(status.metadata.trailer_present, ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -531,7 +554,7 @@ describe('Other conditions', function() { call.write({error: false}); call.end(); call.on('status', function(status) { - assert.deepEqual(status.metadata.trailer_present, ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -543,7 +566,7 @@ describe('Other conditions', function() { call.write({error: true}); call.end(); call.on('status', function(status) { - assert.deepEqual(status.metadata.trailer_present, ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -552,7 +575,7 @@ describe('Other conditions', function() { call.on('data', function(){}); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); - assert.deepEqual(status.metadata.trailer_present, ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -560,7 +583,7 @@ describe('Other conditions', function() { var call = client.serverStream({error: true}); call.on('data', function(){}); call.on('error', function(error) { - assert.deepEqual(error.metadata.trailer_present, ['yes']); + assert.deepEqual(error.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -572,7 +595,7 @@ describe('Other conditions', function() { call.on('data', function(){}); call.on('status', function(status) { assert.strictEqual(status.code, grpc.status.OK); - assert.deepEqual(status.metadata.trailer_present, ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -583,7 +606,7 @@ describe('Other conditions', function() { call.end(); call.on('data', function(){}); call.on('error', function(error) { - assert.deepEqual(error.metadata.trailer_present, ['yes']); + assert.deepEqual(error.metadata.get('trailer-present'), ['yes']); done(); }); }); diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index a7142d0f00..a8cd3a0e74 100644 --- a/src/objective-c/GRPCClient/private/GRPCHost.m +++ b/src/objective-c/GRPCClient/private/GRPCHost.m @@ -57,13 +57,16 @@ // Default initializer. - (instancetype)initWithAddress:(NSString *)address { + if (!address) { + return nil; + } // To provide a default port, we try to interpret the address. If it's just a host name without // scheme and without port, we'll use port 443. If it has a scheme, we pass it untouched to the C // gRPC library. // TODO(jcanizales): Add unit tests for the types of addresses we want to let pass untouched. NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]]; - if (hostURL && !hostURL.port) { + if (hostURL.host && !hostURL.port) { address = [hostURL.host stringByAppendingString:@":443"]; } diff --git a/src/objective-c/GRPCClient/private/GRPCSecureChannel.m b/src/objective-c/GRPCClient/private/GRPCSecureChannel.m index 0a54804bb2..ce16655330 100644 --- a/src/objective-c/GRPCClient/private/GRPCSecureChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCSecureChannel.m @@ -49,7 +49,7 @@ static grpc_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr) // Passing NULL to grpc_ssl_credentials_create produces behavior we don't want, so return. return NULL; } - return grpc_ssl_credentials_create(contentInASCII.bytes, NULL); + return grpc_ssl_credentials_create(contentInASCII.bytes, NULL, NULL); } @implementation GRPCSecureChannel @@ -101,8 +101,9 @@ static grpc_credentials *CertificatesAtPath(NSString *path, NSError **errorPtr) - (instancetype)initWithHost:(NSString *)host credentials:(grpc_credentials *)credentials args:(grpc_channel_args *)args { - return (self = - [super initWithChannel:grpc_secure_channel_create(credentials, host.UTF8String, args)]); + return (self = [super + initWithChannel:grpc_secure_channel_create( + credentials, host.UTF8String, args, NULL)]); } // TODO(jcanizales): GRPCSecureChannel and GRPCUnsecuredChannel are just convenience initializers diff --git a/src/objective-c/README.md b/src/objective-c/README.md index e997b76d14..6c27657def 100644 --- a/src/objective-c/README.md +++ b/src/objective-c/README.md @@ -30,7 +30,7 @@ proceed. ## Write your API declaration in proto format For this you can consult the [Protocol Buffers][]' official documentation, or learn from a quick -example [here](https://github.com/grpc/grpc-common#defining-a-service). +example [here](https://github.com/grpc/grpc/tree/master/examples#defining-a-service). <a name="cocoapods"></a> ## Integrate a proto library in your project diff --git a/src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto b/src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto index dace1a5d26..19592e2ebd 100644 --- a/src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto +++ b/src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto @@ -29,7 +29,7 @@ syntax = "proto3"; -package examples; +package routeguide; option objc_class_prefix = "RGD"; diff --git a/src/objective-c/tests/LocalClearTextTests.m b/src/objective-c/tests/LocalClearTextTests.m index 4317614dd9..976fff55bc 100644 --- a/src/objective-c/tests/LocalClearTextTests.m +++ b/src/objective-c/tests/LocalClearTextTests.m @@ -42,12 +42,12 @@ #import <RxLibrary/GRXWriter+Immediate.h> // These tests require a gRPC "RouteGuide" sample server to be running locally. You can compile and -// run one by following the instructions here: https://github.com/grpc/grpc-common/blob/master/cpp/cpptutorial.md#try-it-out +// run one by following the instructions here: https://github.com/grpc/grpc/blob/master/examples/cpp/cpptutorial.md#try-it-out // Be sure to have the C gRPC library installed in your system (for example, by having followed the // instructions at https://github.com/grpc/homebrew-grpc static NSString * const kRouteGuideHost = @"http://localhost:50051"; -static NSString * const kPackage = @"examples"; +static NSString * const kPackage = @"routeguide"; static NSString * const kService = @"RouteGuide"; @interface LocalClearTextTests : XCTestCase diff --git a/src/php/README.md b/src/php/README.md index f432935fde..afa09d79a1 100644 --- a/src/php/README.md +++ b/src/php/README.md @@ -32,10 +32,10 @@ $ sudo php -d detect_unicode=0 go-pear.phar **Linux (Debian):** -Add [Debian unstable][] to your `sources.list` file. Example: +Add [Debian testing][] to your `sources.list` file. Example: ```sh -echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" | \ +echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \ sudo tee -a /etc/apt/sources.list ``` @@ -73,29 +73,24 @@ This will download and run the [gRPC install script][] and compile the gRPC PHP Clone this repository -``` +```sh $ git clone https://github.com/grpc/grpc.git ``` -Build and install the Protocol Buffers compiler (protoc) +Build and install the gRPC C core libraries -``` +```sh $ cd grpc $ git pull --recurse-submodules && git submodule update --init --recursive -$ cd third_party/protobuf -$ ./autogen.sh -$ ./configure $ make -$ make check $ sudo make install ``` -Build and install the gRPC C core libraries +Note: you may encounter a warning about the Protobuf compiler `protoc` 3.0.0+ not being installed. The following might help, and will be useful later on when we need to compile the `protoc-gen-php` tool. ```sh -$ cd grpc -$ make -$ sudo make install +$ cd grpc/third_party/protobuf +$ sudo make install # 'make' should have been run by core grpc ``` Install the gRPC PHP extension @@ -172,4 +167,4 @@ $ ./bin/run_gen_code_test.sh [homebrew]:http://brew.sh [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install [Node]:https://github.com/grpc/grpc/tree/master/src/node/examples -[Debian unstable]:https://www.debian.org/releases/sid/ +[Debian testing]:https://www.debian.org/releases/stretch/ diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c index 7a981675de..a4313b6bd4 100644 --- a/src/php/ext/grpc/channel.c +++ b/src/php/ext/grpc/channel.c @@ -169,7 +169,7 @@ PHP_METHOD(Channel, __construct) { } else { gpr_log(GPR_DEBUG, "Initialized secure channel"); channel->wrapped = - grpc_secure_channel_create(creds->wrapped, target, &args); + grpc_secure_channel_create(creds->wrapped, target, &args, NULL); } efree(args.args); } diff --git a/src/php/ext/grpc/credentials.c b/src/php/ext/grpc/credentials.c index 01cb94e3aa..8e3b7ff212 100644 --- a/src/php/ext/grpc/credentials.c +++ b/src/php/ext/grpc/credentials.c @@ -130,7 +130,7 @@ PHP_METHOD(Credentials, createSsl) { } grpc_credentials *creds = grpc_ssl_credentials_create( pem_root_certs, - pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair); + pem_key_cert_pair.private_key == NULL ? NULL : &pem_key_cert_pair, NULL); zval *creds_object = grpc_php_wrap_credentials(creds); RETURN_DESTROY_ZVAL(creds_object); } @@ -160,7 +160,7 @@ PHP_METHOD(Credentials, createComposite) { (wrapped_grpc_credentials *)zend_object_store_get_object( cred2_obj TSRMLS_CC); grpc_credentials *creds = - grpc_composite_credentials_create(cred1->wrapped, cred2->wrapped); + grpc_composite_credentials_create(cred1->wrapped, cred2->wrapped, NULL); zval *creds_object = grpc_php_wrap_credentials(creds); RETURN_DESTROY_ZVAL(creds_object); } @@ -170,7 +170,7 @@ PHP_METHOD(Credentials, createComposite) { * @return Credentials The new GCE credentials object */ PHP_METHOD(Credentials, createGce) { - grpc_credentials *creds = grpc_compute_engine_credentials_create(); + grpc_credentials *creds = grpc_google_compute_engine_credentials_create(NULL); zval *creds_object = grpc_php_wrap_credentials(creds); RETURN_DESTROY_ZVAL(creds_object); } diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c index e9183c4598..79188246bc 100644 --- a/src/php/ext/grpc/server_credentials.c +++ b/src/php/ext/grpc/server_credentials.c @@ -118,7 +118,7 @@ PHP_METHOD(ServerCredentials, createSsl) { /* TODO: add a force_client_auth field in ServerCredentials and pass it as * the last parameter. */ grpc_server_credentials *creds = grpc_ssl_server_credentials_create( - pem_root_certs, &pem_key_cert_pair, 1, 0); + pem_root_certs, &pem_key_cert_pair, 1, 0, NULL); zval *creds_object = grpc_php_wrap_server_credentials(creds); RETURN_DESTROY_ZVAL(creds_object); } diff --git a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php index 287621d930..a368dd4ee0 100644 --- a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php +++ b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php @@ -47,6 +47,10 @@ abstract class AbstractGeneratedCodeTest extends PHPUnit_Framework_TestCase { $this->assertTrue(self::$client->waitForReady(250000)); } + public function testGetTarget() { + $this->assertTrue(is_string(self::$client->getTarget())); + } + public function testSimpleRequest() { $div_arg = new math\DivArgs(); $div_arg->setDividend(7); diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index 376d306da0..bd15ee4303 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -332,11 +332,7 @@ if (in_array($args['test_case'], array( $opts['update_metadata'] = $auth->getUpdateMetadataFunc(); } -$internal_stub = new Grpc\BaseStub($server_address, $opts); -hardAssert(is_string($internal_stub->getTarget()), - 'Unexpected target URI value'); - -$stub = new grpc\testing\TestServiceClient($internal_stub); +$stub = new grpc\testing\TestServiceClient($server_address, $opts); echo "Connecting to $server_address\n"; echo "Running test case $args[test_case]\n"; @@ -372,6 +368,11 @@ switch ($args['test_case']) { case 'jwt_token_creds': jwtTokenCreds($stub, $args); break; + case 'cancel_after_begin': + // Currently unimplementable with the current API design + // Specifically, in the ClientStreamingCall->start() method, the + // messages are sent immediately after metadata is sent. There is + // currently no way to cancel before messages are sent. default: exit(1); } diff --git a/src/python/README.md b/src/python/README.md index affce64884..a21deb33ef 100644 --- a/src/python/README.md +++ b/src/python/README.md @@ -16,10 +16,10 @@ INSTALLATION **Linux (Debian):** -Add [Debian unstable][] to your `sources.list` file. Example: +Add [Debian testing][] to your `sources.list` file. Example: ```sh -echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" | \ +echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \ sudo tee -a /etc/apt/sources.list ``` @@ -92,4 +92,4 @@ $ ../../tools/distrib/python/submit.py [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install [Quick Start]:http://www.grpc.io/docs/tutorials/basic/python.html [detailed example]:http://www.grpc.io/docs/installation/python.html -[Debian unstable]:https://www.debian.org/releases/sid/ +[Debian testing]:https://www.debian.org/releases/stretch/ diff --git a/src/python/grpcio/grpc/_adapter/_c/types.h b/src/python/grpcio/grpc/_adapter/_c/types.h index f6ff957baa..ec0687a9fd 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types.h +++ b/src/python/grpcio/grpc/_adapter/_c/types.h @@ -57,8 +57,6 @@ ClientCredentials *pygrpc_ClientCredentials_composite( PyTypeObject *type, PyObject *args, PyObject *kwargs); ClientCredentials *pygrpc_ClientCredentials_compute_engine( PyTypeObject *type, PyObject *ignored); -ClientCredentials *pygrpc_ClientCredentials_service_account( - PyTypeObject *type, PyObject *args, PyObject *kwargs); ClientCredentials *pygrpc_ClientCredentials_jwt( PyTypeObject *type, PyObject *args, PyObject *kwargs); ClientCredentials *pygrpc_ClientCredentials_refresh_token( diff --git a/src/python/grpcio/grpc/_adapter/_c/types/channel.c b/src/python/grpcio/grpc/_adapter/_c/types/channel.c index c577ac05eb..79d39c4391 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types/channel.c +++ b/src/python/grpcio/grpc/_adapter/_c/types/channel.c @@ -106,7 +106,8 @@ Channel *pygrpc_Channel_new( } self = (Channel *)type->tp_alloc(type, 0); if (creds) { - self->c_chan = grpc_secure_channel_create(creds->c_creds, target, &c_args); + self->c_chan = + grpc_secure_channel_create(creds->c_creds, target, &c_args, NULL); } else { self->c_chan = grpc_insecure_channel_create(target, &c_args, NULL); } @@ -164,7 +165,7 @@ PyObject *pygrpc_Channel_watch_connectivity_state( int last_observed_state; CompletionQueue *completion_queue; char *keywords[] = {"last_observed_state", "deadline", - "completion_queue", "tag"}; + "completion_queue", "tag", NULL}; if (!PyArg_ParseTupleAndKeywords( args, kwargs, "idO!O:watch_connectivity_state", keywords, &last_observed_state, &deadline, &pygrpc_CompletionQueue_type, diff --git a/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c b/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c index e314c15324..90652b7b47 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c +++ b/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c @@ -48,8 +48,6 @@ PyMethodDef pygrpc_ClientCredentials_methods[] = { METH_CLASS|METH_KEYWORDS, ""}, {"compute_engine", (PyCFunction)pygrpc_ClientCredentials_compute_engine, METH_CLASS|METH_NOARGS, ""}, - {"service_account", (PyCFunction)pygrpc_ClientCredentials_service_account, - METH_CLASS|METH_KEYWORDS, ""}, {"jwt", (PyCFunction)pygrpc_ClientCredentials_jwt, METH_CLASS|METH_KEYWORDS, ""}, {"refresh_token", (PyCFunction)pygrpc_ClientCredentials_refresh_token, @@ -135,9 +133,10 @@ ClientCredentials *pygrpc_ClientCredentials_ssl( if (private_key && cert_chain) { key_cert_pair.private_key = private_key; key_cert_pair.cert_chain = cert_chain; - self->c_creds = grpc_ssl_credentials_create(root_certs, &key_cert_pair); + self->c_creds = + grpc_ssl_credentials_create(root_certs, &key_cert_pair, NULL); } else { - self->c_creds = grpc_ssl_credentials_create(root_certs, NULL); + self->c_creds = grpc_ssl_credentials_create(root_certs, NULL, NULL); } if (!self->c_creds) { Py_DECREF(self); @@ -159,8 +158,8 @@ ClientCredentials *pygrpc_ClientCredentials_composite( return NULL; } self = (ClientCredentials *)type->tp_alloc(type, 0); - self->c_creds = grpc_composite_credentials_create( - creds1->c_creds, creds2->c_creds); + self->c_creds = + grpc_composite_credentials_create(creds1->c_creds, creds2->c_creds, NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, "couldn't create composite credentials"); @@ -172,7 +171,7 @@ ClientCredentials *pygrpc_ClientCredentials_composite( ClientCredentials *pygrpc_ClientCredentials_compute_engine( PyTypeObject *type, PyObject *ignored) { ClientCredentials *self = (ClientCredentials *)type->tp_alloc(type, 0); - self->c_creds = grpc_compute_engine_credentials_create(); + self->c_creds = grpc_google_compute_engine_credentials_create(NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, @@ -182,29 +181,6 @@ ClientCredentials *pygrpc_ClientCredentials_compute_engine( return self; } -ClientCredentials *pygrpc_ClientCredentials_service_account( - PyTypeObject *type, PyObject *args, PyObject *kwargs) { - ClientCredentials *self; - const char *json_key; - const char *scope; - double lifetime; - static char *keywords[] = {"json_key", "scope", "token_lifetime", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ssd:service_account", keywords, - &json_key, &scope, &lifetime)) { - return NULL; - } - self = (ClientCredentials *)type->tp_alloc(type, 0); - self->c_creds = grpc_service_account_credentials_create( - json_key, scope, pygrpc_cast_double_to_gpr_timespec(lifetime)); - if (!self->c_creds) { - Py_DECREF(self); - PyErr_SetString(PyExc_RuntimeError, - "couldn't create service account credentials"); - return NULL; - } - return self; -} - /* TODO: Rename this credentials to something like service_account_jwt_access */ ClientCredentials *pygrpc_ClientCredentials_jwt( PyTypeObject *type, PyObject *args, PyObject *kwargs) { @@ -218,7 +194,7 @@ ClientCredentials *pygrpc_ClientCredentials_jwt( } self = (ClientCredentials *)type->tp_alloc(type, 0); self->c_creds = grpc_service_account_jwt_access_credentials_create( - json_key, pygrpc_cast_double_to_gpr_timespec(lifetime)); + json_key, pygrpc_cast_double_to_gpr_timespec(lifetime), NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, "couldn't create JWT credentials"); @@ -237,7 +213,8 @@ ClientCredentials *pygrpc_ClientCredentials_refresh_token( return NULL; } self = (ClientCredentials *)type->tp_alloc(type, 0); - self->c_creds = grpc_refresh_token_credentials_create(json_refresh_token); + self->c_creds = + grpc_google_refresh_token_credentials_create(json_refresh_token, NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, @@ -258,8 +235,8 @@ ClientCredentials *pygrpc_ClientCredentials_iam( return NULL; } self = (ClientCredentials *)type->tp_alloc(type, 0); - self->c_creds = grpc_iam_credentials_create(authorization_token, - authority_selector); + self->c_creds = grpc_google_iam_credentials_create(authorization_token, + authority_selector, NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, "couldn't create IAM credentials"); diff --git a/src/python/grpcio/grpc/_adapter/_c/types/server_credentials.c b/src/python/grpcio/grpc/_adapter/_c/types/server_credentials.c index f6859b79d7..df51a99b6a 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types/server_credentials.c +++ b/src/python/grpcio/grpc/_adapter/_c/types/server_credentials.c @@ -99,11 +99,13 @@ ServerCredentials *pygrpc_ServerCredentials_ssl( const char *root_certs; PyObject *py_key_cert_pairs; grpc_ssl_pem_key_cert_pair *key_cert_pairs; + int force_client_auth; size_t num_key_cert_pairs; size_t i; - static char *keywords[] = {"root_certs", "key_cert_pairs", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zO:ssl", keywords, - &root_certs, &py_key_cert_pairs)) { + static char *keywords[] = { + "root_certs", "key_cert_pairs", "force_client_auth", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "zOi:ssl", keywords, + &root_certs, &py_key_cert_pairs, &force_client_auth)) { return NULL; } if (!PyList_Check(py_key_cert_pairs)) { @@ -128,11 +130,8 @@ ServerCredentials *pygrpc_ServerCredentials_ssl( } self = (ServerCredentials *)type->tp_alloc(type, 0); - /* TODO: Add a force_client_auth parameter in the python object and pass it - here as the last arg. */ self->c_creds = grpc_ssl_server_credentials_create( - root_certs, key_cert_pairs, num_key_cert_pairs, 0); + root_certs, key_cert_pairs, num_key_cert_pairs, force_client_auth, NULL); gpr_free(key_cert_pairs); return self; } - diff --git a/src/python/grpcio/grpc/_adapter/_intermediary_low.py b/src/python/grpcio/grpc/_adapter/_intermediary_low.py index e7bf9dc462..06358e72bc 100644 --- a/src/python/grpcio/grpc/_adapter/_intermediary_low.py +++ b/src/python/grpcio/grpc/_adapter/_intermediary_low.py @@ -255,5 +255,6 @@ class ClientCredentials(object): class ServerCredentials(object): """Adapter from old _low.ServerCredentials interface to new _low.ServerCredentials.""" - def __init__(self, root_credentials, pair_sequence): - self._internal = _low.ServerCredentials.ssl(root_credentials, list(pair_sequence)) + def __init__(self, root_credentials, pair_sequence, force_client_auth): + self._internal = _low.ServerCredentials.ssl( + root_credentials, list(pair_sequence), force_client_auth) diff --git a/src/python/grpcio/grpc/_adapter/fore.py b/src/python/grpcio/grpc/_adapter/fore.py index 7d88bda263..daa41e8bde 100644 --- a/src/python/grpcio/grpc/_adapter/fore.py +++ b/src/python/grpcio/grpc/_adapter/fore.py @@ -288,7 +288,7 @@ class ForeLink(base_interfaces.ForeLink, activated.Activated): self._port = self._server.add_http2_addr(address) else: server_credentials = _low.ServerCredentials( - self._root_certificates, self._key_chain_pairs) + self._root_certificates, self._key_chain_pairs, False) self._server = _low.Server(self._completion_queue) self._port = self._server.add_secure_http2_addr( address, server_credentials) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx index 2d74702fbd..dc40a7a611 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx +++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx @@ -106,26 +106,6 @@ def client_credentials_compute_engine(): credentials.c_credentials = grpc.grpc_compute_engine_credentials_create() return credentials -def client_credentials_service_account( - json_key, scope, records.Timespec token_lifetime not None): - if isinstance(json_key, bytes): - pass - elif isinstance(json_key, basestring): - json_key = json_key.encode() - else: - raise TypeError("expected json_key to be str or bytes") - if isinstance(scope, bytes): - pass - elif isinstance(scope, basestring): - scope = scope.encode() - else: - raise TypeError("expected scope to be str or bytes") - cdef ClientCredentials credentials = ClientCredentials() - credentials.c_credentials = grpc.grpc_service_account_credentials_create( - json_key, scope, token_lifetime.c_time) - credentials.references.extend([json_key, scope]) - return credentials - #TODO rename to something like client_credentials_service_account_jwt_access. def client_credentials_jwt(json_key, records.Timespec token_lifetime not None): if isinstance(json_key, bytes): diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd index d065383587..8b46972490 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd @@ -311,8 +311,6 @@ cdef extern from "grpc/grpc_security.h": grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1, grpc_credentials *creds2) grpc_credentials *grpc_compute_engine_credentials_create() - grpc_credentials *grpc_service_account_credentials_create( - const char *json_key, const char *scope, gpr_timespec token_lifetime) grpc_credentials *grpc_service_account_jwt_access_credentials_create(const char *json_key, gpr_timespec token_lifetime) grpc_credentials *grpc_refresh_token_credentials_create( @@ -332,7 +330,7 @@ cdef extern from "grpc/grpc_security.h": grpc_server_credentials *grpc_ssl_server_credentials_create( const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pairs, - size_t num_key_cert_pairs); + size_t num_key_cert_pairs) void grpc_server_credentials_release(grpc_server_credentials *creds) int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, diff --git a/src/python/grpcio/grpc/_cython/adapter_low.py b/src/python/grpcio/grpc/_cython/adapter_low.py index 2bb468eece..4f24da330f 100644 --- a/src/python/grpcio/grpc/_cython/adapter_low.py +++ b/src/python/grpcio/grpc/_cython/adapter_low.py @@ -60,10 +60,6 @@ class ClientCredentials(object): raise NotImplementedError() @staticmethod - def service_account(): - raise NotImplementedError() - - @staticmethod def jwt(): raise NotImplementedError() diff --git a/src/python/grpcio/grpc/_links/invocation.py b/src/python/grpcio/grpc/_links/invocation.py index ee3d72fdbc..1676fe7941 100644 --- a/src/python/grpcio/grpc/_links/invocation.py +++ b/src/python/grpcio/grpc/_links/invocation.py @@ -41,6 +41,15 @@ from grpc.framework.foundation import logging_pool from grpc.framework.foundation import relay from grpc.framework.interfaces.links import links +_IDENTITY = lambda x: x + +_STOP = _intermediary_low.Event.Kind.STOP +_WRITE = _intermediary_low.Event.Kind.WRITE_ACCEPTED +_COMPLETE = _intermediary_low.Event.Kind.COMPLETE_ACCEPTED +_READ = _intermediary_low.Event.Kind.READ_ACCEPTED +_METADATA = _intermediary_low.Event.Kind.METADATA_ACCEPTED +_FINISH = _intermediary_low.Event.Kind.FINISH + @enum.unique class _Read(enum.Enum): @@ -67,7 +76,7 @@ class _RPCState(object): def __init__( self, call, request_serializer, response_deserializer, sequence_number, - read, allowance, high_write, low_write): + read, allowance, high_write, low_write, due): self.call = call self.request_serializer = request_serializer self.response_deserializer = response_deserializer @@ -76,27 +85,37 @@ class _RPCState(object): self.allowance = allowance self.high_write = high_write self.low_write = low_write + self.due = due + + +def _no_longer_due(kind, rpc_state, key, rpc_states): + rpc_state.due.remove(kind) + if not rpc_state.due: + del rpc_states[key] class _Kernel(object): def __init__( - self, channel, host, request_serializers, response_deserializers, - ticket_relay): + self, channel, host, metadata_transformer, request_serializers, + response_deserializers, ticket_relay): self._lock = threading.Lock() self._channel = channel self._host = host + self._metadata_transformer = metadata_transformer self._request_serializers = request_serializers self._response_deserializers = response_deserializers self._relay = ticket_relay self._completion_queue = None - self._rpc_states = None + self._rpc_states = {} self._pool = None def _on_write_event(self, operation_id, unused_event, rpc_state): if rpc_state.high_write is _HighWrite.CLOSED: rpc_state.call.complete(operation_id) + rpc_state.due.add(_COMPLETE) + rpc_state.due.remove(_WRITE) rpc_state.low_write = _LowWrite.CLOSED else: ticket = links.Ticket( @@ -105,16 +124,19 @@ class _Kernel(object): rpc_state.sequence_number += 1 self._relay.add_value(ticket) rpc_state.low_write = _LowWrite.OPEN + _no_longer_due(_WRITE, rpc_state, operation_id, self._rpc_states) def _on_read_event(self, operation_id, event, rpc_state): - if event.bytes is None: + if event.bytes is None or _FINISH not in rpc_state.due: rpc_state.read = _Read.CLOSED + _no_longer_due(_READ, rpc_state, operation_id, self._rpc_states) else: if 0 < rpc_state.allowance: rpc_state.allowance -= 1 rpc_state.call.read(operation_id) else: rpc_state.read = _Read.AWAITING_ALLOWANCE + _no_longer_due(_READ, rpc_state, operation_id, self._rpc_states) ticket = links.Ticket( operation_id, rpc_state.sequence_number, None, None, None, None, None, None, rpc_state.response_deserializer(event.bytes), None, None, None, @@ -123,18 +145,23 @@ class _Kernel(object): self._relay.add_value(ticket) def _on_metadata_event(self, operation_id, event, rpc_state): - rpc_state.allowance -= 1 - rpc_state.call.read(operation_id) - rpc_state.read = _Read.READING - ticket = links.Ticket( - operation_id, rpc_state.sequence_number, None, None, - links.Ticket.Subscription.FULL, None, None, event.metadata, None, None, - None, None, None, None) - rpc_state.sequence_number += 1 - self._relay.add_value(ticket) + if _FINISH in rpc_state.due: + rpc_state.allowance -= 1 + rpc_state.call.read(operation_id) + rpc_state.read = _Read.READING + rpc_state.due.add(_READ) + rpc_state.due.remove(_METADATA) + ticket = links.Ticket( + operation_id, rpc_state.sequence_number, None, None, + links.Ticket.Subscription.FULL, None, None, event.metadata, None, + None, None, None, None, None) + rpc_state.sequence_number += 1 + self._relay.add_value(ticket) + else: + _no_longer_due(_METADATA, rpc_state, operation_id, self._rpc_states) def _on_finish_event(self, operation_id, event, rpc_state): - self._rpc_states.pop(operation_id, None) + _no_longer_due(_FINISH, rpc_state, operation_id, self._rpc_states) if event.status.code is _intermediary_low.Code.OK: termination = links.Ticket.Termination.COMPLETION elif event.status.code is _intermediary_low.Code.CANCELLED: @@ -155,26 +182,26 @@ class _Kernel(object): def _spin(self, completion_queue): while True: event = completion_queue.get(None) - if event.kind is _intermediary_low.Event.Kind.STOP: - return - operation_id = event.tag with self._lock: - if self._completion_queue is None: - continue - rpc_state = self._rpc_states.get(operation_id) - if rpc_state is not None: - if event.kind is _intermediary_low.Event.Kind.WRITE_ACCEPTED: - self._on_write_event(operation_id, event, rpc_state) - elif event.kind is _intermediary_low.Event.Kind.METADATA_ACCEPTED: - self._on_metadata_event(operation_id, event, rpc_state) - elif event.kind is _intermediary_low.Event.Kind.READ_ACCEPTED: - self._on_read_event(operation_id, event, rpc_state) - elif event.kind is _intermediary_low.Event.Kind.FINISH: - self._on_finish_event(operation_id, event, rpc_state) - elif event.kind is _intermediary_low.Event.Kind.COMPLETE_ACCEPTED: - pass - else: - logging.error('Illegal RPC event! %s', (event,)) + rpc_state = self._rpc_states.get(event.tag, None) + if event.kind is _STOP: + pass + elif event.kind is _WRITE: + self._on_write_event(event.tag, event, rpc_state) + elif event.kind is _METADATA: + self._on_metadata_event(event.tag, event, rpc_state) + elif event.kind is _READ: + self._on_read_event(event.tag, event, rpc_state) + elif event.kind is _FINISH: + self._on_finish_event(event.tag, event, rpc_state) + elif event.kind is _COMPLETE: + _no_longer_due(_COMPLETE, rpc_state, event.tag, self._rpc_states) + else: + logging.error('Illegal RPC event! %s', (event,)) + + if self._completion_queue is None and not self._rpc_states: + completion_queue.stop() + return def _invoke( self, operation_id, group, method, initial_metadata, payload, termination, @@ -201,46 +228,48 @@ class _Kernel(object): else: return - request_serializer = self._request_serializers.get((group, method)) - response_deserializer = self._response_deserializers.get((group, method)) - if request_serializer is None or response_deserializer is None: - cancellation_ticket = links.Ticket( - operation_id, 0, None, None, None, None, None, None, None, None, None, - None, links.Ticket.Termination.CANCELLATION) - self._relay.add_value(cancellation_ticket) - return + transformed_initial_metadata = self._metadata_transformer(initial_metadata) + request_serializer = self._request_serializers.get( + (group, method), _IDENTITY) + response_deserializer = self._response_deserializers.get( + (group, method), _IDENTITY) call = _intermediary_low.Call( self._channel, self._completion_queue, '/%s/%s' % (group, method), self._host, time.time() + timeout) - if initial_metadata is not None: - for metadata_key, metadata_value in initial_metadata: + if transformed_initial_metadata is not None: + for metadata_key, metadata_value in transformed_initial_metadata: call.add_metadata(metadata_key, metadata_value) call.invoke(self._completion_queue, operation_id, operation_id) if payload is None: if high_write is _HighWrite.CLOSED: call.complete(operation_id) low_write = _LowWrite.CLOSED + due = set((_METADATA, _COMPLETE, _FINISH,)) else: low_write = _LowWrite.OPEN + due = set((_METADATA, _FINISH,)) else: call.write(request_serializer(payload), operation_id) low_write = _LowWrite.ACTIVE + due = set((_WRITE, _METADATA, _FINISH,)) self._rpc_states[operation_id] = _RPCState( call, request_serializer, response_deserializer, 0, _Read.AWAITING_METADATA, 1 if allowance is None else (1 + allowance), - high_write, low_write) + high_write, low_write, due) def _advance(self, operation_id, rpc_state, payload, termination, allowance): if payload is not None: rpc_state.call.write(rpc_state.request_serializer(payload), operation_id) rpc_state.low_write = _LowWrite.ACTIVE + rpc_state.due.add(_WRITE) if allowance is not None: if rpc_state.read is _Read.AWAITING_ALLOWANCE: rpc_state.allowance += allowance - 1 rpc_state.call.read(operation_id) rpc_state.read = _Read.READING + rpc_state.due.add(_READ) else: rpc_state.allowance += allowance @@ -248,19 +277,21 @@ class _Kernel(object): rpc_state.high_write = _HighWrite.CLOSED if rpc_state.low_write is _LowWrite.OPEN: rpc_state.call.complete(operation_id) + rpc_state.due.add(_COMPLETE) rpc_state.low_write = _LowWrite.CLOSED elif termination is not None: rpc_state.call.cancel() def add_ticket(self, ticket): with self._lock: - if self._completion_queue is None: - return if ticket.sequence_number == 0: - self._invoke( - ticket.operation_id, ticket.group, ticket.method, - ticket.initial_metadata, ticket.payload, ticket.termination, - ticket.timeout, ticket.allowance) + if self._completion_queue is None: + logging.error('Received invocation ticket %s after stop!', ticket) + else: + self._invoke( + ticket.operation_id, ticket.group, ticket.method, + ticket.initial_metadata, ticket.payload, ticket.termination, + ticket.timeout, ticket.allowance) else: rpc_state = self._rpc_states.get(ticket.operation_id) if rpc_state is not None: @@ -276,7 +307,6 @@ class _Kernel(object): """ with self._lock: self._completion_queue = _intermediary_low.CompletionQueue() - self._rpc_states = {} self._pool = logging_pool.pool(1) self._pool.submit(self._spin, self._completion_queue) @@ -288,11 +318,10 @@ class _Kernel(object): has been called. """ with self._lock: - self._completion_queue.stop() + if not self._rpc_states: + self._completion_queue.stop() self._completion_queue = None pool = self._pool - self._pool = None - self._rpc_states = None pool.shutdown(wait=True) @@ -307,10 +336,15 @@ class InvocationLink(links.Link, activated.Activated): class _InvocationLink(InvocationLink): def __init__( - self, channel, host, request_serializers, response_deserializers): + self, channel, host, metadata_transformer, request_serializers, + response_deserializers): self._relay = relay.relay(None) self._kernel = _Kernel( - channel, host, request_serializers, response_deserializers, self._relay) + channel, host, + _IDENTITY if metadata_transformer is None else metadata_transformer, + {} if request_serializers is None else request_serializers, + {} if response_deserializers is None else response_deserializers, + self._relay) def _start(self): self._relay.start() @@ -347,12 +381,17 @@ class _InvocationLink(InvocationLink): self._stop() -def invocation_link(channel, host, request_serializers, response_deserializers): +def invocation_link( + channel, host, metadata_transformer, request_serializers, + response_deserializers): """Creates an InvocationLink. Args: channel: An _intermediary_low.Channel for use by the link. host: The host to specify when invoking RPCs. + metadata_transformer: A callable that takes an invocation-side initial + metadata value and returns another metadata value to send in its place. + May be None. request_serializers: A dict from group-method pair to request object serialization behavior. response_deserializers: A dict from group-method pair to response object @@ -362,4 +401,5 @@ def invocation_link(channel, host, request_serializers, response_deserializers): An InvocationLink. """ return _InvocationLink( - channel, host, request_serializers, response_deserializers) + channel, host, metadata_transformer, request_serializers, + response_deserializers) diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py index 43c4c0e80c..94e7cfc716 100644 --- a/src/python/grpcio/grpc/_links/service.py +++ b/src/python/grpcio/grpc/_links/service.py @@ -40,6 +40,8 @@ from grpc.framework.foundation import logging_pool from grpc.framework.foundation import relay from grpc.framework.interfaces.links import links +_IDENTITY = lambda x: x + _TERMINATION_KIND_TO_CODE = { links.Ticket.Termination.COMPLETION: _intermediary_low.Code.OK, links.Ticket.Termination.CANCELLATION: _intermediary_low.Code.CANCELLED, @@ -53,6 +55,13 @@ _TERMINATION_KIND_TO_CODE = { links.Ticket.Termination.REMOTE_FAILURE: _intermediary_low.Code.UNKNOWN, } +_STOP = _intermediary_low.Event.Kind.STOP +_WRITE = _intermediary_low.Event.Kind.WRITE_ACCEPTED +_COMPLETE = _intermediary_low.Event.Kind.COMPLETE_ACCEPTED +_SERVICE = _intermediary_low.Event.Kind.SERVICE_ACCEPTED +_READ = _intermediary_low.Event.Kind.READ_ACCEPTED +_FINISH = _intermediary_low.Event.Kind.FINISH + @enum.unique class _Read(enum.Enum): @@ -84,7 +93,7 @@ class _RPCState(object): def __init__( self, request_deserializer, response_serializer, sequence_number, read, early_read, allowance, high_write, low_write, premetadataed, - terminal_metadata, code, message): + terminal_metadata, code, message, due): self.request_deserializer = request_deserializer self.response_serializer = response_serializer self.sequence_number = sequence_number @@ -99,6 +108,13 @@ class _RPCState(object): self.terminal_metadata = terminal_metadata self.code = code self.message = message + self.due = due + + +def _no_longer_due(kind, rpc_state, key, rpc_states): + rpc_state.due.remove(kind) + if not rpc_state.due: + del rpc_states[key] def _metadatafy(call, metadata): @@ -124,6 +140,7 @@ class _Kernel(object): self._relay = ticket_relay self._completion_queue = None + self._due = set() self._server = None self._rpc_states = {} self._pool = None @@ -139,17 +156,16 @@ class _Kernel(object): except ValueError: logging.info('Illegal path "%s"!', service_acceptance.method) return - request_deserializer = self._request_deserializers.get((group, method)) - response_serializer = self._response_serializers.get((group, method)) - if request_deserializer is None or response_serializer is None: - # TODO(nathaniel): Terminate the RPC with code NOT_FOUND. - call.cancel() - return + request_deserializer = self._request_deserializers.get( + (group, method), _IDENTITY) + response_serializer = self._response_serializers.get( + (group, method), _IDENTITY) call.read(call) self._rpc_states[call] = _RPCState( request_deserializer, response_serializer, 1, _Read.READING, None, 1, - _HighWrite.OPEN, _LowWrite.OPEN, False, None, None, None) + _HighWrite.OPEN, _LowWrite.OPEN, False, None, None, None, + set((_READ, _FINISH,))) ticket = links.Ticket( call, 0, group, method, links.Ticket.Subscription.FULL, service_acceptance.deadline - time.time(), None, event.metadata, None, @@ -158,14 +174,13 @@ class _Kernel(object): def _on_read_event(self, event): call = event.tag - rpc_state = self._rpc_states.get(call, None) - if rpc_state is None: - return + rpc_state = self._rpc_states[call] if event.bytes is None: rpc_state.read = _Read.CLOSED payload = None termination = links.Ticket.Termination.COMPLETION + _no_longer_due(_READ, rpc_state, call, self._rpc_states) else: if 0 < rpc_state.allowance: payload = rpc_state.request_deserializer(event.bytes) @@ -174,6 +189,7 @@ class _Kernel(object): call.read(call) else: rpc_state.early_read = event.bytes + _no_longer_due(_READ, rpc_state, call, self._rpc_states) return # TODO(issue 2916): Instead of returning: # rpc_state.read = _Read.AWAITING_ALLOWANCE @@ -185,9 +201,7 @@ class _Kernel(object): def _on_write_event(self, event): call = event.tag - rpc_state = self._rpc_states.get(call, None) - if rpc_state is None: - return + rpc_state = self._rpc_states[call] if rpc_state.high_write is _HighWrite.CLOSED: if rpc_state.terminal_metadata is not None: @@ -197,6 +211,8 @@ class _Kernel(object): rpc_state.message) call.status(status, call) rpc_state.low_write = _LowWrite.CLOSED + rpc_state.due.add(_COMPLETE) + rpc_state.due.remove(_WRITE) else: ticket = links.Ticket( call, rpc_state.sequence_number, None, None, None, None, 1, None, @@ -204,12 +220,12 @@ class _Kernel(object): rpc_state.sequence_number += 1 self._relay.add_value(ticket) rpc_state.low_write = _LowWrite.OPEN + _no_longer_due(_WRITE, rpc_state, call, self._rpc_states) def _on_finish_event(self, event): call = event.tag - rpc_state = self._rpc_states.pop(call, None) - if rpc_state is None: - return + rpc_state = self._rpc_states[call] + _no_longer_due(_FINISH, rpc_state, call, self._rpc_states) code = event.status.code if code is _intermediary_low.Code.OK: return @@ -229,28 +245,33 @@ class _Kernel(object): def _spin(self, completion_queue, server): while True: event = completion_queue.get(None) - if event.kind is _intermediary_low.Event.Kind.STOP: - return with self._lock: - if self._server is None: - continue - elif event.kind is _intermediary_low.Event.Kind.SERVICE_ACCEPTED: - self._on_service_acceptance_event(event, server) - elif event.kind is _intermediary_low.Event.Kind.READ_ACCEPTED: + if event.kind is _STOP: + self._due.remove(_STOP) + elif event.kind is _READ: self._on_read_event(event) - elif event.kind is _intermediary_low.Event.Kind.WRITE_ACCEPTED: + elif event.kind is _WRITE: self._on_write_event(event) - elif event.kind is _intermediary_low.Event.Kind.COMPLETE_ACCEPTED: - pass + elif event.kind is _COMPLETE: + _no_longer_due( + _COMPLETE, self._rpc_states.get(event.tag), event.tag, + self._rpc_states) elif event.kind is _intermediary_low.Event.Kind.FINISH: self._on_finish_event(event) + elif event.kind is _SERVICE: + if self._server is None: + self._due.remove(_SERVICE) + else: + self._on_service_acceptance_event(event, server) else: logging.error('Illegal event! %s', (event,)) + if not self._due and not self._rpc_states: + completion_queue.stop() + return + def add_ticket(self, ticket): with self._lock: - if self._server is None: - return call = ticket.operation_id rpc_state = self._rpc_states.get(call) if rpc_state is None: @@ -278,6 +299,7 @@ class _Kernel(object): rpc_state.early_read = None if rpc_state.read is _Read.READING: call.read(call) + rpc_state.due.add(_READ) termination = None else: termination = links.Ticket.Termination.COMPLETION @@ -289,6 +311,7 @@ class _Kernel(object): if ticket.payload is not None: call.write(rpc_state.response_serializer(ticket.payload), call) + rpc_state.due.add(_WRITE) rpc_state.low_write = _LowWrite.ACTIVE if ticket.terminal_metadata is not None: @@ -307,6 +330,7 @@ class _Kernel(object): links.Ticket.Termination.COMPLETION, rpc_state.code, rpc_state.message) call.status(status, call) + rpc_state.due.add(_COMPLETE) rpc_state.low_write = _LowWrite.CLOSED elif ticket.termination is not None: if rpc_state.terminal_metadata is not None: @@ -314,11 +338,10 @@ class _Kernel(object): status = _status( ticket.termination, rpc_state.code, rpc_state.message) call.status(status, call) - self._rpc_states.pop(call, None) + rpc_state.due.add(_COMPLETE) - def add_port(self, port, server_credentials): + def add_port(self, address, server_credentials): with self._lock: - address = '[::]:%d' % port if self._server is None: self._completion_queue = _intermediary_low.CompletionQueue() self._server = _intermediary_low.Server(self._completion_queue) @@ -336,23 +359,19 @@ class _Kernel(object): self._pool.submit(self._spin, self._completion_queue, self._server) self._server.start() self._server.service(None) + self._due.add(_SERVICE) - def graceful_stop(self): + def begin_stop(self): with self._lock: self._server.stop() + self._due.add(_STOP) self._server = None - self._completion_queue.stop() - self._completion_queue = None + + def end_stop(self): + with self._lock: pool = self._pool - self._pool = None - self._rpc_states = None pool.shutdown(wait=True) - def immediate_stop(self): - # TODO(nathaniel): Implementation. - raise NotImplementedError( - 'TODO(nathaniel): after merge of rewritten lower layers') - class ServiceLink(links.Link): """A links.Link for use on the service-side of a gRPC connection. @@ -362,17 +381,20 @@ class ServiceLink(links.Link): """ @abc.abstractmethod - def add_port(self, port, server_credentials): + def add_port(self, address, server_credentials): """Adds a port on which to service RPCs after this link has been started. Args: - port: The port on which to service RPCs, or zero to request that a port be - automatically selected and used. - server_credentials: A ServerCredentials object, or None for insecure - service. + address: The address on which to service RPCs with a port number of zero + requesting that a port number be automatically selected and used. + server_credentials: An _intermediary_low.ServerCredentials object, or + None for insecure service. Returns: - A port on which RPCs will be serviced after this link has been started. + An integer port on which RPCs will be serviced after this link has been + started. This is typically the same number as the port number contained + in the passed address, but will likely be different if the port number + contained in the passed address was zero. """ raise NotImplementedError() @@ -386,18 +408,20 @@ class ServiceLink(links.Link): raise NotImplementedError() @abc.abstractmethod - def stop_gracefully(self): - """Stops this link. + def begin_stop(self): + """Indicate imminent link stop and immediate rejection of new RPCs. New RPCs will be rejected as soon as this method is called, but ongoing RPCs - will be allowed to continue until they terminate. This method blocks until - all RPCs have terminated. + will be allowed to continue until they terminate. This method does not + block. """ raise NotImplementedError() @abc.abstractmethod - def stop_immediately(self): - """Stops this link. + def end_stop(self): + """Finishes stopping this link. + + begin_stop must have been called exactly once before calling this method. All in-progress RPCs will be terminated immediately. """ @@ -409,7 +433,9 @@ class _ServiceLink(ServiceLink): def __init__(self, request_deserializers, response_serializers): self._relay = relay.relay(None) self._kernel = _Kernel( - request_deserializers, response_serializers, self._relay) + {} if request_deserializers is None else request_deserializers, + {} if response_serializers is None else response_serializers, + self._relay) def accept_ticket(self, ticket): self._kernel.add_ticket(ticket) @@ -417,19 +443,18 @@ class _ServiceLink(ServiceLink): def join_link(self, link): self._relay.set_behavior(link.accept_ticket) - def add_port(self, port, server_credentials): - return self._kernel.add_port(port, server_credentials) + def add_port(self, address, server_credentials): + return self._kernel.add_port(address, server_credentials) def start(self): self._relay.start() return self._kernel.start() - def stop_gracefully(self): - self._kernel.graceful_stop() - self._relay.stop() + def begin_stop(self): + self._kernel.begin_stop() - def stop_immediately(self): - self._kernel.immediate_stop() + def end_stop(self): + self._kernel.end_stop() self._relay.stop() diff --git a/src/python/grpcio/grpc/beta/__init__.py b/src/python/grpcio/grpc/beta/__init__.py new file mode 100644 index 0000000000..b89398809f --- /dev/null +++ b/src/python/grpcio/grpc/beta/__init__.py @@ -0,0 +1,28 @@ +# 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. diff --git a/src/python/grpcio/grpc/beta/_connectivity_channel.py b/src/python/grpcio/grpc/beta/_connectivity_channel.py new file mode 100644 index 0000000000..457ede79f2 --- /dev/null +++ b/src/python/grpcio/grpc/beta/_connectivity_channel.py @@ -0,0 +1,148 @@ +# 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. + +"""Affords a connectivity-state-listenable channel.""" + +import threading +import time + +from grpc._adapter import _low +from grpc.framework.foundation import callable_util + +_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = ( + 'Exception calling channel subscription callback!') + + +class ConnectivityChannel(object): + + def __init__(self, low_channel, mapping): + self._lock = threading.Lock() + self._low_channel = low_channel + self._mapping = mapping + + self._polling = False + self._connectivity = None + self._try_to_connect = False + self._callbacks_and_connectivities = [] + self._delivering = False + + def _deliveries(self, connectivity): + callbacks_needing_update = [] + for callback_and_connectivity in self._callbacks_and_connectivities: + callback, callback_connectivity = callback_and_connectivity + if callback_connectivity is not connectivity: + callbacks_needing_update.append(callback) + callback_and_connectivity[1] = connectivity + return callbacks_needing_update + + def _deliver(self, initial_connectivity, initial_callbacks): + connectivity = initial_connectivity + callbacks = initial_callbacks + while True: + for callback in callbacks: + callable_util.call_logging_exceptions( + callback, _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE, + connectivity) + with self._lock: + callbacks = self._deliveries(self._connectivity) + if callbacks: + connectivity = self._connectivity + else: + self._delivering = False + return + + def _spawn_delivery(self, connectivity, callbacks): + delivering_thread = threading.Thread( + target=self._deliver, args=(connectivity, callbacks,)) + delivering_thread.start() + self._delivering = True + + # TODO(issue 3064): Don't poll. + def _poll_connectivity(self, low_channel, initial_try_to_connect): + try_to_connect = initial_try_to_connect + low_connectivity = low_channel.check_connectivity_state(try_to_connect) + with self._lock: + self._connectivity = self._mapping[low_connectivity] + callbacks = tuple( + callback for callback, unused_but_known_to_be_none_connectivity + in self._callbacks_and_connectivities) + for callback_and_connectivity in self._callbacks_and_connectivities: + callback_and_connectivity[1] = self._connectivity + if callbacks: + self._spawn_delivery(self._connectivity, callbacks) + completion_queue = _low.CompletionQueue() + while True: + low_channel.watch_connectivity_state( + low_connectivity, time.time() + 0.2, completion_queue, None) + event = completion_queue.next() + with self._lock: + if not self._callbacks_and_connectivities and not self._try_to_connect: + self._polling = False + self._connectivity = None + completion_queue.shutdown() + break + try_to_connect = self._try_to_connect + self._try_to_connect = False + if event.success or try_to_connect: + low_connectivity = low_channel.check_connectivity_state(try_to_connect) + with self._lock: + self._connectivity = self._mapping[low_connectivity] + if not self._delivering: + callbacks = self._deliveries(self._connectivity) + if callbacks: + self._spawn_delivery(self._connectivity, callbacks) + + def subscribe(self, callback, try_to_connect): + with self._lock: + if not self._callbacks_and_connectivities and not self._polling: + polling_thread = threading.Thread( + target=self._poll_connectivity, + args=(self._low_channel, bool(try_to_connect))) + polling_thread.start() + self._polling = True + self._callbacks_and_connectivities.append([callback, None]) + elif not self._delivering and self._connectivity is not None: + self._spawn_delivery(self._connectivity, (callback,)) + self._try_to_connect |= bool(try_to_connect) + self._callbacks_and_connectivities.append( + [callback, self._connectivity]) + else: + self._try_to_connect |= bool(try_to_connect) + self._callbacks_and_connectivities.append([callback, None]) + + def unsubscribe(self, callback): + with self._lock: + for index, (subscribed_callback, unused_connectivity) in enumerate( + self._callbacks_and_connectivities): + if callback == subscribed_callback: + self._callbacks_and_connectivities.pop(index) + break + + def low_channel(self): + return self._low_channel diff --git a/src/python/grpcio/grpc/beta/_server.py b/src/python/grpcio/grpc/beta/_server.py new file mode 100644 index 0000000000..4e46ffd17f --- /dev/null +++ b/src/python/grpcio/grpc/beta/_server.py @@ -0,0 +1,112 @@ +# 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. + +"""Beta API server implementation.""" + +import threading + +from grpc._links import service +from grpc.framework.core import implementations as _core_implementations +from grpc.framework.crust import implementations as _crust_implementations +from grpc.framework.foundation import logging_pool +from grpc.framework.interfaces.links import utilities + +_DEFAULT_POOL_SIZE = 8 +_DEFAULT_TIMEOUT = 300 +_MAXIMUM_TIMEOUT = 24 * 60 * 60 + + +def _disassemble(grpc_link, end_link, pool, event, grace): + grpc_link.begin_stop() + end_link.stop(grace).wait() + grpc_link.end_stop() + grpc_link.join_link(utilities.NULL_LINK) + end_link.join_link(utilities.NULL_LINK) + if pool is not None: + pool.shutdown(wait=True) + event.set() + + +class Server(object): + + def __init__(self, grpc_link, end_link, pool): + self._grpc_link = grpc_link + self._end_link = end_link + self._pool = pool + + def add_insecure_port(self, address): + return self._grpc_link.add_port(address, None) + + def add_secure_port(self, address, intermediary_low_server_credentials): + return self._grpc_link.add_port( + address, intermediary_low_server_credentials) + + def start(self): + self._grpc_link.join_link(self._end_link) + self._end_link.join_link(self._grpc_link) + self._grpc_link.start() + self._end_link.start() + + def stop(self, grace): + stop_event = threading.Event() + if 0 < grace: + disassembly_thread = threading.Thread( + target=_disassemble, + args=( + self._grpc_link, self._end_link, self._pool, stop_event, grace,)) + disassembly_thread.start() + return stop_event + else: + _disassemble(self._grpc_link, self._end_link, self._pool, stop_event, 0) + return stop_event + + +def server( + implementations, multi_implementation, request_deserializers, + response_serializers, thread_pool, thread_pool_size, default_timeout, + maximum_timeout): + if thread_pool is None: + service_thread_pool = logging_pool.pool( + _DEFAULT_POOL_SIZE if thread_pool_size is None else thread_pool_size) + assembly_thread_pool = service_thread_pool + else: + service_thread_pool = thread_pool + assembly_thread_pool = None + + servicer = _crust_implementations.servicer( + implementations, multi_implementation, service_thread_pool) + + grpc_link = service.service_link(request_deserializers, response_serializers) + + end_link = _core_implementations.service_end_link( + servicer, + _DEFAULT_TIMEOUT if default_timeout is None else default_timeout, + _MAXIMUM_TIMEOUT if maximum_timeout is None else maximum_timeout) + + return Server(grpc_link, end_link, assembly_thread_pool) diff --git a/src/python/grpcio/grpc/beta/_stub.py b/src/python/grpcio/grpc/beta/_stub.py new file mode 100644 index 0000000000..cfbecb852b --- /dev/null +++ b/src/python/grpcio/grpc/beta/_stub.py @@ -0,0 +1,111 @@ +# 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. + +"""Beta API stub implementation.""" + +import threading + +from grpc._links import invocation +from grpc.framework.core import implementations as _core_implementations +from grpc.framework.crust import implementations as _crust_implementations +from grpc.framework.foundation import logging_pool +from grpc.framework.interfaces.links import utilities + +_DEFAULT_POOL_SIZE = 6 + + +class _AutoIntermediary(object): + + def __init__(self, delegate, on_deletion): + self._delegate = delegate + self._on_deletion = on_deletion + + def __getattr__(self, attr): + return getattr(self._delegate, attr) + + def __del__(self): + self._on_deletion() + + +def _assemble( + channel, host, metadata_transformer, request_serializers, + response_deserializers, thread_pool, thread_pool_size): + end_link = _core_implementations.invocation_end_link() + grpc_link = invocation.invocation_link( + channel, host, metadata_transformer, request_serializers, + response_deserializers) + if thread_pool is None: + invocation_pool = logging_pool.pool( + _DEFAULT_POOL_SIZE if thread_pool_size is None else thread_pool_size) + assembly_pool = invocation_pool + else: + invocation_pool = thread_pool + assembly_pool = None + end_link.join_link(grpc_link) + grpc_link.join_link(end_link) + end_link.start() + grpc_link.start() + return end_link, grpc_link, invocation_pool, assembly_pool + + +def _disassemble(end_link, grpc_link, pool): + end_link.stop(24 * 60 * 60).wait() + grpc_link.stop() + end_link.join_link(utilities.NULL_LINK) + grpc_link.join_link(utilities.NULL_LINK) + if pool is not None: + pool.shutdown(wait=True) + + +def _wrap_assembly(stub, end_link, grpc_link, assembly_pool): + disassembly_thread = threading.Thread( + target=_disassemble, args=(end_link, grpc_link, assembly_pool)) + return _AutoIntermediary(stub, disassembly_thread.start) + + +def generic_stub( + channel, host, metadata_transformer, request_serializers, + response_deserializers, thread_pool, thread_pool_size): + end_link, grpc_link, invocation_pool, assembly_pool = _assemble( + channel, host, metadata_transformer, request_serializers, + response_deserializers, thread_pool, thread_pool_size) + stub = _crust_implementations.generic_stub(end_link, invocation_pool) + return _wrap_assembly(stub, end_link, grpc_link, assembly_pool) + + +def dynamic_stub( + channel, host, service, cardinalities, metadata_transformer, + request_serializers, response_deserializers, thread_pool, + thread_pool_size): + end_link, grpc_link, invocation_pool, assembly_pool = _assemble( + channel, host, metadata_transformer, request_serializers, + response_deserializers, thread_pool, thread_pool_size) + stub = _crust_implementations.dynamic_stub( + end_link, service, cardinalities, invocation_pool) + return _wrap_assembly(stub, end_link, grpc_link, assembly_pool) diff --git a/src/python/grpcio/grpc/beta/beta.py b/src/python/grpcio/grpc/beta/beta.py new file mode 100644 index 0000000000..b3a161087f --- /dev/null +++ b/src/python/grpcio/grpc/beta/beta.py @@ -0,0 +1,491 @@ +# 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. + +"""Entry points into the Beta API of gRPC Python.""" + +# threading is referenced from specification in this module. +import abc +import enum +import threading # pylint: disable=unused-import + +# cardinality and face are referenced from specification in this module. +from grpc._adapter import _intermediary_low +from grpc._adapter import _types +from grpc.beta import _connectivity_channel +from grpc.beta import _server +from grpc.beta import _stub +from grpc.framework.common import cardinality # pylint: disable=unused-import +from grpc.framework.interfaces.face import face # pylint: disable=unused-import + +_CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = ( + 'Exception calling channel subscription callback!') + + +@enum.unique +class ChannelConnectivity(enum.Enum): + """Mirrors grpc_connectivity_state in the gRPC Core. + + Attributes: + IDLE: The channel is idle. + CONNECTING: The channel is connecting. + READY: The channel is ready to conduct RPCs. + TRANSIENT_FAILURE: The channel has seen a failure from which it expects to + recover. + FATAL_FAILURE: The channel has seen a failure from which it cannot recover. + """ + + IDLE = (_types.ConnectivityState.IDLE, 'idle',) + CONNECTING = (_types.ConnectivityState.CONNECTING, 'connecting',) + READY = (_types.ConnectivityState.READY, 'ready',) + TRANSIENT_FAILURE = ( + _types.ConnectivityState.TRANSIENT_FAILURE, 'transient failure',) + FATAL_FAILURE = (_types.ConnectivityState.FATAL_FAILURE, 'fatal failure',) + +_LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = { + state: connectivity for state, connectivity in zip( + _types.ConnectivityState, ChannelConnectivity) +} + + +class ClientCredentials(object): + """A value encapsulating the data required to create a secure Channel. + + This class and its instances have no supported interface - it exists to define + the type of its instances and its instances exist to be passed to other + functions. + """ + + def __init__(self, low_credentials, intermediary_low_credentials): + self._low_credentials = low_credentials + self._intermediary_low_credentials = intermediary_low_credentials + + +def ssl_client_credentials(root_certificates, private_key, certificate_chain): + """Creates a ClientCredentials for use with an SSL-enabled Channel. + + Args: + root_certificates: The PEM-encoded root certificates or None to ask for + them to be retrieved from a default location. + private_key: The PEM-encoded private key to use or None if no private key + should be used. + certificate_chain: The PEM-encoded certificate chain to use or None if no + certificate chain should be used. + + Returns: + A ClientCredentials for use with an SSL-enabled Channel. + """ + intermediary_low_credentials = _intermediary_low.ClientCredentials( + root_certificates, private_key, certificate_chain) + return ClientCredentials( + intermediary_low_credentials._internal, intermediary_low_credentials) # pylint: disable=protected-access + + +class Channel(object): + """A channel to a remote host through which RPCs may be conducted. + + Only the "subscribe" and "unsubscribe" methods are supported for application + use. This class' instance constructor and all other attributes are + unsupported. + """ + + def __init__(self, low_channel, intermediary_low_channel): + self._low_channel = low_channel + self._intermediary_low_channel = intermediary_low_channel + self._connectivity_channel = _connectivity_channel.ConnectivityChannel( + low_channel, _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY) + + def subscribe(self, callback, try_to_connect=None): + """Subscribes to this Channel's connectivity. + + Args: + callback: A callable to be invoked and passed this Channel's connectivity. + The callable will be invoked immediately upon subscription and again for + every change to this Channel's connectivity thereafter until it is + unsubscribed. + try_to_connect: A boolean indicating whether or not this Channel should + attempt to connect if it is not already connected and ready to conduct + RPCs. + """ + self._connectivity_channel.subscribe(callback, try_to_connect) + + def unsubscribe(self, callback): + """Unsubscribes a callback from this Channel's connectivity. + + Args: + callback: A callable previously registered with this Channel from having + been passed to its "subscribe" method. + """ + self._connectivity_channel.unsubscribe(callback) + + +def create_insecure_channel(host, port): + """Creates an insecure Channel to a remote host. + + Args: + host: The name of the remote host to which to connect. + port: The port of the remote host to which to connect. + + Returns: + A Channel to the remote host through which RPCs may be conducted. + """ + intermediary_low_channel = _intermediary_low.Channel( + '%s:%d' % (host, port), None) + return Channel(intermediary_low_channel._internal, intermediary_low_channel) # pylint: disable=protected-access + + +def create_secure_channel(host, port, client_credentials): + """Creates a secure Channel to a remote host. + + Args: + host: The name of the remote host to which to connect. + port: The port of the remote host to which to connect. + client_credentials: A ClientCredentials. + + Returns: + A secure Channel to the remote host through which RPCs may be conducted. + """ + intermediary_low_channel = _intermediary_low.Channel( + '%s:%d' % (host, port), client_credentials.intermediary_low_credentials) + return Channel(intermediary_low_channel._internal, intermediary_low_channel) # pylint: disable=protected-access + + +class StubOptions(object): + """A value encapsulating the various options for creation of a Stub. + + This class and its instances have no supported interface - it exists to define + the type of its instances and its instances exist to be passed to other + functions. + """ + + def __init__( + self, host, request_serializers, response_deserializers, + metadata_transformer, thread_pool, thread_pool_size): + self.host = host + self.request_serializers = request_serializers + self.response_deserializers = response_deserializers + self.metadata_transformer = metadata_transformer + self.thread_pool = thread_pool + self.thread_pool_size = thread_pool_size + +_EMPTY_STUB_OPTIONS = StubOptions( + None, None, None, None, None, None) + + +def stub_options( + host=None, request_serializers=None, response_deserializers=None, + metadata_transformer=None, thread_pool=None, thread_pool_size=None): + """Creates a StubOptions value to be passed at stub creation. + + All parameters are optional and should always be passed by keyword. + + Args: + host: A host string to set on RPC calls. + request_serializers: A dictionary from service name-method name pair to + request serialization behavior. + response_deserializers: A dictionary from service name-method name pair to + response deserialization behavior. + metadata_transformer: A callable that given a metadata object produces + another metadata object to be used in the underlying communication on the + wire. + thread_pool: A thread pool to use in stubs. + thread_pool_size: The size of thread pool to create for use in stubs; + ignored if thread_pool has been passed. + + Returns: + A StubOptions value created from the passed parameters. + """ + return StubOptions( + host, request_serializers, response_deserializers, + metadata_transformer, thread_pool, thread_pool_size) + + +def generic_stub(channel, options=None): + """Creates a face.GenericStub on which RPCs can be made. + + Args: + channel: A Channel for use by the created stub. + options: A StubOptions customizing the created stub. + + Returns: + A face.GenericStub on which RPCs can be made. + """ + effective_options = _EMPTY_STUB_OPTIONS if options is None else options + return _stub.generic_stub( + channel._intermediary_low_channel, effective_options.host, # pylint: disable=protected-access + effective_options.metadata_transformer, + effective_options.request_serializers, + effective_options.response_deserializers, effective_options.thread_pool, + effective_options.thread_pool_size) + + +def dynamic_stub(channel, service, cardinalities, options=None): + """Creates a face.DynamicStub with which RPCs can be invoked. + + Args: + channel: A Channel for the returned face.DynamicStub to use. + service: The package-qualified full name of the service. + cardinalities: A dictionary from RPC method name to cardinality.Cardinality + value identifying the cardinality of the RPC method. + options: An optional StubOptions value further customizing the functionality + of the returned face.DynamicStub. + + Returns: + A face.DynamicStub with which RPCs can be invoked. + """ + effective_options = StubOptions() if options is None else options + return _stub.dynamic_stub( + channel._intermediary_low_channel, effective_options.host, service, # pylint: disable=protected-access + cardinalities, effective_options.metadata_transformer, + effective_options.request_serializers, + effective_options.response_deserializers, effective_options.thread_pool, + effective_options.thread_pool_size) + + +class ServerCredentials(object): + """A value encapsulating the data required to open a secure port on a Server. + + This class and its instances have no supported interface - it exists to define + the type of its instances and its instances exist to be passed to other + functions. + """ + + def __init__(self, low_credentials, intermediary_low_credentials): + self._low_credentials = low_credentials + self._intermediary_low_credentials = intermediary_low_credentials + + +def ssl_server_credentials( + private_key_certificate_chain_pairs, root_certificates=None, + require_client_auth=False): + """Creates a ServerCredentials for use with an SSL-enabled Server. + + Args: + private_key_certificate_chain_pairs: A nonempty sequence each element of + which is a pair the first element of which is a PEM-encoded private key + and the second element of which is the corresponding PEM-encoded + certificate chain. + root_certificates: PEM-encoded client root certificates to be used for + verifying authenticated clients. If omitted, require_client_auth must also + be omitted or be False. + require_client_auth: A boolean indicating whether or not to require clients + to be authenticated. May only be True if root_certificates is not None. + + Returns: + A ServerCredentials for use with an SSL-enabled Server. + """ + if len(private_key_certificate_chain_pairs) == 0: + raise ValueError( + 'At least one private key-certificate chain pairis required!') + elif require_client_auth and root_certificates is None: + raise ValueError( + 'Illegal to require client auth without providing root certificates!') + else: + intermediary_low_credentials = _intermediary_low.ServerCredentials( + root_certificates, private_key_certificate_chain_pairs, + require_client_auth) + return ServerCredentials( + intermediary_low_credentials._internal, intermediary_low_credentials) # pylint: disable=protected-access + + +class Server(object): + """Services RPCs.""" + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def add_insecure_port(self, address): + """Reserves a port for insecure RPC service once this Server becomes active. + + This method may only be called before calling this Server's start method is + called. + + Args: + address: The address for which to open a port. + + Returns: + An integer port on which RPCs will be serviced after this link has been + started. This is typically the same number as the port number contained + in the passed address, but will likely be different if the port number + contained in the passed address was zero. + """ + raise NotImplementedError() + + @abc.abstractmethod + def add_secure_port(self, address, server_credentials): + """Reserves a port for secure RPC service after this Server becomes active. + + This method may only be called before calling this Server's start method is + called. + + Args: + address: The address for which to open a port. + server_credentials: A ServerCredentials. + + Returns: + An integer port on which RPCs will be serviced after this link has been + started. This is typically the same number as the port number contained + in the passed address, but will likely be different if the port number + contained in the passed address was zero. + """ + raise NotImplementedError() + + @abc.abstractmethod + def start(self): + """Starts this Server's service of RPCs. + + This method may only be called while the server is not serving RPCs (i.e. it + is not idempotent). + """ + raise NotImplementedError() + + @abc.abstractmethod + def stop(self, grace): + """Stops this Server's service of RPCs. + + All calls to this method immediately stop service of new RPCs. When existing + RPCs are aborted is controlled by the grace period parameter passed to this + method. + + This method may be called at any time and is idempotent. Passing a smaller + grace value than has been passed in a previous call will have the effect of + stopping the Server sooner. Passing a larger grace value than has been + passed in a previous call will not have the effect of stopping the sooner + later. + + Args: + grace: A duration of time in seconds to allow existing RPCs to complete + before being aborted by this Server's stopping. May be zero for + immediate abortion of all in-progress RPCs. + + Returns: + A threading.Event that will be set when this Server has completely + stopped. The returned event may not be set until after the full grace + period (if some ongoing RPC continues for the full length of the period) + of it may be set much sooner (such as if this Server had no RPCs underway + at the time it was stopped or if all RPCs that it had underway completed + very early in the grace period). + """ + raise NotImplementedError() + + +class ServerOptions(object): + """A value encapsulating the various options for creation of a Server. + + This class and its instances have no supported interface - it exists to define + the type of its instances and its instances exist to be passed to other + functions. + """ + + def __init__( + self, multi_method_implementation, request_deserializers, + response_serializers, thread_pool, thread_pool_size, default_timeout, + maximum_timeout): + self.multi_method_implementation = multi_method_implementation + self.request_deserializers = request_deserializers + self.response_serializers = response_serializers + self.thread_pool = thread_pool + self.thread_pool_size = thread_pool_size + self.default_timeout = default_timeout + self.maximum_timeout = maximum_timeout + +_EMPTY_SERVER_OPTIONS = ServerOptions( + None, None, None, None, None, None, None) + + +def server_options( + multi_method_implementation=None, request_deserializers=None, + response_serializers=None, thread_pool=None, thread_pool_size=None, + default_timeout=None, maximum_timeout=None): + """Creates a ServerOptions value to be passed at server creation. + + All parameters are optional and should always be passed by keyword. + + Args: + multi_method_implementation: A face.MultiMethodImplementation to be called + to service an RPC if the server has no specific method implementation for + the name of the RPC for which service was requested. + request_deserializers: A dictionary from service name-method name pair to + request deserialization behavior. + response_serializers: A dictionary from service name-method name pair to + response serialization behavior. + thread_pool: A thread pool to use in stubs. + thread_pool_size: The size of thread pool to create for use in stubs; + ignored if thread_pool has been passed. + default_timeout: A duration in seconds to allow for RPC service when + servicing RPCs that did not include a timeout value when invoked. + maximum_timeout: A duration in seconds to allow for RPC service when + servicing RPCs no matter what timeout value was passed when the RPC was + invoked. + + Returns: + A StubOptions value created from the passed parameters. + """ + return ServerOptions( + multi_method_implementation, request_deserializers, response_serializers, + thread_pool, thread_pool_size, default_timeout, maximum_timeout) + + +class _Server(Server): + + def __init__(self, underserver): + self._underserver = underserver + + def add_insecure_port(self, address): + return self._underserver.add_insecure_port(address) + + def add_secure_port(self, address, server_credentials): + return self._underserver.add_secure_port( + address, server_credentials._intermediary_low_credentials) # pylint: disable=protected-access + + def start(self): + self._underserver.start() + + def stop(self, grace): + return self._underserver.stop(grace) + + +def server(service_implementations, options=None): + """Creates a Server with which RPCs can be serviced. + + Args: + service_implementations: A dictionary from service name-method name pair to + face.MethodImplementation. + options: An optional ServerOptions value further customizing the + functionality of the returned Server. + + Returns: + A Server with which RPCs can be serviced. + """ + effective_options = _EMPTY_SERVER_OPTIONS if options is None else options + underserver = _server.server( + service_implementations, effective_options.multi_method_implementation, + effective_options.request_deserializers, + effective_options.response_serializers, effective_options.thread_pool, + effective_options.thread_pool_size, effective_options.default_timeout, + effective_options.maximum_timeout) + return _Server(underserver) diff --git a/src/python/grpcio/grpc/beta/utilities.py b/src/python/grpcio/grpc/beta/utilities.py new file mode 100644 index 0000000000..1b5356e3ad --- /dev/null +++ b/src/python/grpcio/grpc/beta/utilities.py @@ -0,0 +1,161 @@ +# 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. + +"""Utilities for the gRPC Python Beta API.""" + +import threading +import time + +from grpc.beta import beta +from grpc.framework.foundation import callable_util +from grpc.framework.foundation import future + +_DONE_CALLBACK_EXCEPTION_LOG_MESSAGE = ( + 'Exception calling connectivity future "done" callback!') + + +class _ChannelReadyFuture(future.Future): + + def __init__(self, channel): + self._condition = threading.Condition() + self._channel = channel + + self._matured = False + self._cancelled = False + self._done_callbacks = [] + + def _block(self, timeout): + until = None if timeout is None else time.time() + timeout + with self._condition: + while True: + if self._cancelled: + raise future.CancelledError() + elif self._matured: + return + else: + if until is None: + self._condition.wait() + else: + remaining = until - time.time() + if remaining < 0: + raise future.TimeoutError() + else: + self._condition.wait(timeout=remaining) + + def _update(self, connectivity): + with self._condition: + if not self._cancelled and connectivity is beta.ChannelConnectivity.READY: + self._matured = True + self._channel.unsubscribe(self._update) + self._condition.notify_all() + done_callbacks = tuple(self._done_callbacks) + self._done_callbacks = None + else: + return + + for done_callback in done_callbacks: + callable_util.call_logging_exceptions( + done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) + + def cancel(self): + with self._condition: + if not self._matured: + self._cancelled = True + self._channel.unsubscribe(self._update) + self._condition.notify_all() + done_callbacks = tuple(self._done_callbacks) + self._done_callbacks = None + else: + return False + + for done_callback in done_callbacks: + callable_util.call_logging_exceptions( + done_callback, _DONE_CALLBACK_EXCEPTION_LOG_MESSAGE, self) + + def cancelled(self): + with self._condition: + return self._cancelled + + def running(self): + with self._condition: + return not self._cancelled and not self._matured + + def done(self): + with self._condition: + return self._cancelled or self._matured + + def result(self, timeout=None): + self._block(timeout) + return None + + def exception(self, timeout=None): + self._block(timeout) + return None + + def traceback(self, timeout=None): + self._block(timeout) + return None + + def add_done_callback(self, fn): + with self._condition: + if not self._cancelled and not self._matured: + self._done_callbacks.append(fn) + return + + fn(self) + + def start(self): + with self._condition: + self._channel.subscribe(self._update, try_to_connect=True) + + def __del__(self): + with self._condition: + if not self._cancelled and not self._matured: + self._channel.unsubscribe(self._update) + + +def channel_ready_future(channel): + """Creates a future.Future that matures when a beta.Channel is ready. + + Cancelling the returned future.Future does not tell the given beta.Channel to + abandon attempts it may have been making to connect; cancelling merely + deactivates the return future.Future's subscription to the given + beta.Channel's connectivity. + + Args: + channel: A beta.Channel. + + Returns: + A future.Future that matures when the given Channel has connectivity + beta.ChannelConnectivity.READY. + """ + ready_future = _ChannelReadyFuture(channel) + ready_future.start() + return ready_future + diff --git a/src/python/grpcio/grpc/framework/core/_end.py b/src/python/grpcio/grpc/framework/core/_end.py index fb2c532df6..f57cde4e58 100644 --- a/src/python/grpcio/grpc/framework/core/_end.py +++ b/src/python/grpcio/grpc/framework/core/_end.py @@ -30,7 +30,6 @@ """Implementation of base.End.""" import abc -import enum import threading import uuid @@ -75,7 +74,7 @@ def _abort(operations): def _cancel_futures(futures): for future in futures: - futures.cancel() + future.cancel() def _future_shutdown(lock, cycle, event): @@ -83,8 +82,6 @@ def _future_shutdown(lock, cycle, event): with lock: _abort(cycle.operations.values()) _cancel_futures(cycle.futures) - pool = cycle.pool - cycle.pool.shutdown(wait=True) return in_future @@ -113,6 +110,7 @@ def _termination_action(lock, stats, operation_id, cycle): cycle.idle_actions = [] if cycle.grace: _cancel_futures(cycle.futures) + cycle.pool.shutdown(wait=False) return termination_action @@ -205,11 +203,11 @@ class _End(End): def accept_ticket(self, ticket): """See links.Link.accept_ticket for specification.""" with self._lock: - if self._cycle is not None and not self._cycle.grace: + if self._cycle is not None: operation = self._cycle.operations.get(ticket.operation_id) if operation is not None: operation.handle_ticket(ticket) - elif self._servicer_package is not None: + elif self._servicer_package is not None and not self._cycle.grace: termination_action = _termination_action( self._lock, self._stats, ticket.operation_id, self._cycle) operation = _operation.service_operate( diff --git a/src/python/grpcio_test/grpc_interop/client.py b/src/python/grpcio_test/grpc_interop/client.py index 2dd2103cbe..36afe6c096 100644 --- a/src/python/grpcio_test/grpc_interop/client.py +++ b/src/python/grpcio_test/grpc_interop/client.py @@ -70,7 +70,13 @@ def _oauth_access_token(args): def _stub(args): if args.oauth_scope: - metadata_transformer = lambda x: [('Authorization', 'Bearer %s' % _oauth_access_token(args))] + if args.test_case == 'oauth2_auth_token': + access_token = _oauth_access_token(args) + metadata_transformer = lambda x: [ + ('Authorization', 'Bearer %s' % access_token)] + else: + metadata_transformer = lambda x: [ + ('Authorization', 'Bearer %s' % _oauth_access_token(args))] else: metadata_transformer = lambda x: [] if args.use_tls: diff --git a/src/python/grpcio_test/grpc_interop/methods.py b/src/python/grpcio_test/grpc_interop/methods.py index 7a831f3cbd..52b800af7a 100644 --- a/src/python/grpcio_test/grpc_interop/methods.py +++ b/src/python/grpcio_test/grpc_interop/methods.py @@ -346,7 +346,7 @@ def _compute_engine_creds(stub, args): response.username)) -def _service_account_creds(stub, args): +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'] @@ -359,7 +359,6 @@ def _service_account_creds(stub, args): 'expected to find oauth scope "%s" in received "%s"' % (response.oauth_scope, args.oauth_scope)) - @enum.unique class TestCase(enum.Enum): EMPTY_UNARY = 'empty_unary' @@ -370,7 +369,7 @@ class TestCase(enum.Enum): CANCEL_AFTER_BEGIN = 'cancel_after_begin' CANCEL_AFTER_FIRST_RESPONSE = 'cancel_after_first_response' COMPUTE_ENGINE_CREDS = 'compute_engine_creds' - SERVICE_ACCOUNT_CREDS = 'service_account_creds' + OAUTH2_AUTH_TOKEN = 'oauth2_auth_token' TIMEOUT_ON_SLEEPING_SERVER = 'timeout_on_sleeping_server' def test_interoperability(self, stub, args): @@ -392,7 +391,7 @@ class TestCase(enum.Enum): _timeout_on_sleeping_server(stub) elif self is TestCase.COMPUTE_ENGINE_CREDS: _compute_engine_creds(stub, args) - elif self is TestCase.SERVICE_ACCOUNT_CREDS: - _service_account_creds(stub, args) + elif self is TestCase.OAUTH2_AUTH_TOKEN: + _oauth2_auth_token(stub, args) else: raise NotImplementedError('Test case "%s" not implemented!' % self.name) diff --git a/src/python/grpcio_test/grpc_protoc_plugin/alpha_python_plugin_test.py b/src/python/grpcio_test/grpc_protoc_plugin/alpha_python_plugin_test.py new file mode 100644 index 0000000000..b200d129a9 --- /dev/null +++ b/src/python/grpcio_test/grpc_protoc_plugin/alpha_python_plugin_test.py @@ -0,0 +1,541 @@ +# 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. + +import argparse +import contextlib +import distutils.spawn +import errno +import itertools +import os +import pkg_resources +import shutil +import subprocess +import sys +import tempfile +import threading +import time +import unittest + +from grpc.framework.alpha import exceptions +from grpc.framework.foundation import future + +# Identifiers of entities we expect to find in the generated module. +SERVICER_IDENTIFIER = 'EarlyAdopterTestServiceServicer' +SERVER_IDENTIFIER = 'EarlyAdopterTestServiceServer' +STUB_IDENTIFIER = 'EarlyAdopterTestServiceStub' +SERVER_FACTORY_IDENTIFIER = 'early_adopter_create_TestService_server' +STUB_FACTORY_IDENTIFIER = 'early_adopter_create_TestService_stub' + +# The timeout used in tests of RPCs that are supposed to expire. +SHORT_TIMEOUT = 2 +# The timeout used in tests of RPCs that are not supposed to expire. The +# absurdly large value doesn't matter since no passing execution of this test +# module will ever wait the duration. +LONG_TIMEOUT = 600 +NO_DELAY = 0 + + +class _ServicerMethods(object): + + def __init__(self, test_pb2, delay): + self._condition = threading.Condition() + self._delay = delay + self._paused = False + self._fail = False + self._test_pb2 = test_pb2 + + @contextlib.contextmanager + def pause(self): # pylint: disable=invalid-name + with self._condition: + self._paused = True + yield + with self._condition: + self._paused = False + self._condition.notify_all() + + @contextlib.contextmanager + def fail(self): # pylint: disable=invalid-name + with self._condition: + self._fail = True + yield + with self._condition: + self._fail = False + + def _control(self): # pylint: disable=invalid-name + with self._condition: + if self._fail: + raise ValueError() + while self._paused: + self._condition.wait() + time.sleep(self._delay) + + def UnaryCall(self, request, unused_rpc_context): + response = self._test_pb2.SimpleResponse() + response.payload.payload_type = self._test_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * request.response_size + self._control() + return response + + def StreamingOutputCall(self, request, unused_rpc_context): + for parameter in request.response_parameters: + response = self._test_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._test_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + yield response + + def StreamingInputCall(self, request_iter, unused_rpc_context): + response = self._test_pb2.StreamingInputCallResponse() + aggregated_payload_size = 0 + for request in request_iter: + aggregated_payload_size += len(request.payload.payload_compressable) + response.aggregated_payload_size = aggregated_payload_size + self._control() + return response + + def FullDuplexCall(self, request_iter, unused_rpc_context): + for request in request_iter: + for parameter in request.response_parameters: + response = self._test_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._test_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + yield response + + def HalfDuplexCall(self, request_iter, unused_rpc_context): + responses = [] + for request in request_iter: + for parameter in request.response_parameters: + response = self._test_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._test_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + responses.append(response) + for response in responses: + yield response + + +@contextlib.contextmanager +def _CreateService(test_pb2, delay): + """Provides a servicer backend and a stub. + + The servicer is just the implementation + of the actual servicer passed to the face player of the python RPC + implementation; the two are detached. + + Non-zero delay puts a delay on each call to the servicer, representative of + communication latency. Timeout is the default timeout for the stub while + waiting for the service. + + Args: + test_pb2: The test_pb2 module generated by this test. + delay: Delay in seconds per response from the servicer. + + Yields: + A (servicer_methods, servicer, stub) three-tuple where servicer_methods is + the back-end of the service bound to the stub and the server and stub + are both activated and ready for use. + """ + servicer_methods = _ServicerMethods(test_pb2, delay) + + class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)): + + def UnaryCall(self, request, context): + return servicer_methods.UnaryCall(request, context) + + def StreamingOutputCall(self, request, context): + return servicer_methods.StreamingOutputCall(request, context) + + def StreamingInputCall(self, request_iter, context): + return servicer_methods.StreamingInputCall(request_iter, context) + + def FullDuplexCall(self, request_iter, context): + return servicer_methods.FullDuplexCall(request_iter, context) + + def HalfDuplexCall(self, request_iter, context): + return servicer_methods.HalfDuplexCall(request_iter, context) + + servicer = Servicer() + server = getattr( + test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer, 0) + with server: + port = server.port() + stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)('localhost', port) + with stub: + yield servicer_methods, stub, server + + +def _streaming_input_request_iterator(test_pb2): + for _ in range(3): + request = test_pb2.StreamingInputCallRequest() + request.payload.payload_type = test_pb2.COMPRESSABLE + request.payload.payload_compressable = 'a' + yield request + + +def _streaming_output_request(test_pb2): + request = test_pb2.StreamingOutputCallRequest() + sizes = [1, 2, 3] + request.response_parameters.add(size=sizes[0], interval_us=0) + request.response_parameters.add(size=sizes[1], interval_us=0) + request.response_parameters.add(size=sizes[2], interval_us=0) + return request + + +def _full_duplex_request_iterator(test_pb2): + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=2, interval_us=0) + request.response_parameters.add(size=3, interval_us=0) + yield request + + +class PythonPluginTest(unittest.TestCase): + """Test case for the gRPC Python protoc-plugin. + + While reading these tests, remember that the futures API + (`stub.method.async()`) only gives futures for the *non-streaming* responses, + else it behaves like its blocking cousin. + """ + + def setUp(self): + # Assume that the appropriate protoc and grpc_python_plugins are on the + # path. + protoc_command = 'protoc' + protoc_plugin_filename = distutils.spawn.find_executable( + 'grpc_python_plugin') + test_proto_filename = pkg_resources.resource_filename( + 'grpc_protoc_plugin', 'test.proto') + if not os.path.isfile(protoc_command): + # Assume that if we haven't built protoc that it's on the system. + protoc_command = 'protoc' + + # Ensure that the output directory exists. + self.outdir = tempfile.mkdtemp() + + # Invoke protoc with the plugin. + cmd = [ + protoc_command, + '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename, + '-I .', + '--python_out=%s' % self.outdir, + '--python-grpc_out=%s' % self.outdir, + os.path.basename(test_proto_filename), + ] + subprocess.check_call(' '.join(cmd), shell=True, env=os.environ, + cwd=os.path.dirname(test_proto_filename)) + sys.path.append(self.outdir) + + def tearDown(self): + try: + shutil.rmtree(self.outdir) + except OSError as exc: + if exc.errno != errno.ENOENT: + raise + + # TODO(atash): Figure out which of these tests is hanging flakily with small + # probability. + + def testImportAttributes(self): + # check that we can access the generated module and its members. + import test_pb2 # pylint: disable=g-import-not-at-top + self.assertIsNotNone(getattr(test_pb2, SERVICER_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, SERVER_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, STUB_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, SERVER_FACTORY_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, STUB_FACTORY_IDENTIFIER, None)) + + def testUpDown(self): + import test_pb2 + with _CreateService( + test_pb2, NO_DELAY) as (servicer, stub, unused_server): + request = test_pb2.SimpleRequest(response_size=13) + + def testUnaryCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server): + timeout = 6 # TODO(issue 2039): LONG_TIMEOUT like the other methods. + request = test_pb2.SimpleRequest(response_size=13) + response = stub.UnaryCall(request, timeout) + expected_response = methods.UnaryCall(request, 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testUnaryCallAsync(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = test_pb2.SimpleRequest(response_size=13) + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + # Check that the call does not block waiting for the server to respond. + with methods.pause(): + response_future = stub.UnaryCall.async(request, LONG_TIMEOUT) + response = response_future.result() + expected_response = methods.UnaryCall(request, 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testUnaryCallAsyncExpired(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + request = test_pb2.SimpleRequest(response_size=13) + with methods.pause(): + response_future = stub.UnaryCall.async(request, SHORT_TIMEOUT) + with self.assertRaises(exceptions.ExpirationError): + response_future.result() + + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') + def testUnaryCallAsyncCancelled(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = test_pb2.SimpleRequest(response_size=13) + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.pause(): + response_future = stub.UnaryCall.async(request, 1) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + + def testUnaryCallAsyncFailed(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = test_pb2.SimpleRequest(response_size=13) + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.fail(): + response_future = stub.UnaryCall.async(request, LONG_TIMEOUT) + self.assertIsNotNone(response_future.exception()) + + def testStreamingOutputCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = _streaming_output_request(test_pb2) + with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server): + responses = stub.StreamingOutputCall(request, LONG_TIMEOUT) + expected_responses = methods.StreamingOutputCall( + request, 'not a real RpcContext!') + for expected_response, response in itertools.izip_longest( + expected_responses, responses): + self.assertEqual(expected_response, response) + + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') + def testStreamingOutputCallExpired(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = _streaming_output_request(test_pb2) + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.pause(): + responses = stub.StreamingOutputCall(request, SHORT_TIMEOUT) + with self.assertRaises(exceptions.ExpirationError): + list(responses) + + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') + def testStreamingOutputCallCancelled(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = _streaming_output_request(test_pb2) + with _CreateService(test_pb2, NO_DELAY) as ( + unused_methods, stub, unused_server): + responses = stub.StreamingOutputCall(request, SHORT_TIMEOUT) + next(responses) + responses.cancel() + with self.assertRaises(future.CancelledError): + next(responses) + + @unittest.skip('TODO(atash,nathaniel): figure out why this times out ' + 'instead of raising the proper error.') + def testStreamingOutputCallFailed(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = _streaming_output_request(test_pb2) + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.fail(): + responses = stub.StreamingOutputCall(request, 1) + self.assertIsNotNone(responses) + with self.assertRaises(exceptions.ServicerError): + next(responses) + + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') + def testStreamingInputCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server): + response = stub.StreamingInputCall( + _streaming_input_request_iterator(test_pb2), LONG_TIMEOUT) + expected_response = methods.StreamingInputCall( + _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testStreamingInputCallAsync(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.pause(): + response_future = stub.StreamingInputCall.async( + _streaming_input_request_iterator(test_pb2), LONG_TIMEOUT) + response = response_future.result() + expected_response = methods.StreamingInputCall( + _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testStreamingInputCallAsyncExpired(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.pause(): + response_future = stub.StreamingInputCall.async( + _streaming_input_request_iterator(test_pb2), SHORT_TIMEOUT) + with self.assertRaises(exceptions.ExpirationError): + response_future.result() + self.assertIsInstance( + response_future.exception(), exceptions.ExpirationError) + + def testStreamingInputCallAsyncCancelled(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.pause(): + timeout = 6 # TODO(issue 2039): LONG_TIMEOUT like the other methods. + response_future = stub.StreamingInputCall.async( + _streaming_input_request_iterator(test_pb2), timeout) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + with self.assertRaises(future.CancelledError): + response_future.result() + + def testStreamingInputCallAsyncFailed(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.fail(): + response_future = stub.StreamingInputCall.async( + _streaming_input_request_iterator(test_pb2), SHORT_TIMEOUT) + self.assertIsNotNone(response_future.exception()) + + def testFullDuplexCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server): + responses = stub.FullDuplexCall( + _full_duplex_request_iterator(test_pb2), LONG_TIMEOUT) + expected_responses = methods.FullDuplexCall( + _full_duplex_request_iterator(test_pb2), 'not a real RpcContext!') + for expected_response, response in itertools.izip_longest( + expected_responses, responses): + self.assertEqual(expected_response, response) + + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') + def testFullDuplexCallExpired(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request_iterator = _full_duplex_request_iterator(test_pb2) + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.pause(): + responses = stub.FullDuplexCall(request_iterator, SHORT_TIMEOUT) + with self.assertRaises(exceptions.ExpirationError): + list(responses) + + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') + def testFullDuplexCallCancelled(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server): + request_iterator = _full_duplex_request_iterator(test_pb2) + responses = stub.FullDuplexCall(request_iterator, LONG_TIMEOUT) + next(responses) + responses.cancel() + with self.assertRaises(future.CancelledError): + next(responses) + + @unittest.skip('TODO(atash,nathaniel): figure out why this hangs forever ' + 'and fix.') + def testFullDuplexCallFailed(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request_iterator = _full_duplex_request_iterator(test_pb2) + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + with methods.fail(): + responses = stub.FullDuplexCall(request_iterator, LONG_TIMEOUT) + self.assertIsNotNone(responses) + with self.assertRaises(exceptions.ServicerError): + next(responses) + + @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs ' + 'forever and fix.') + def testHalfDuplexCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2, NO_DELAY) as ( + methods, stub, unused_server): + def half_duplex_request_iterator(): + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=2, interval_us=0) + request.response_parameters.add(size=3, interval_us=0) + yield request + responses = stub.HalfDuplexCall( + half_duplex_request_iterator(), LONG_TIMEOUT) + expected_responses = methods.HalfDuplexCall( + half_duplex_request_iterator(), 'not a real RpcContext!') + for check in itertools.izip_longest(expected_responses, responses): + expected_response, response = check + self.assertEqual(expected_response, response) + + def testHalfDuplexCallWedged(self): + import test_pb2 # pylint: disable=g-import-not-at-top + condition = threading.Condition() + wait_cell = [False] + @contextlib.contextmanager + def wait(): # pylint: disable=invalid-name + # Where's Python 3's 'nonlocal' statement when you need it? + with condition: + wait_cell[0] = True + yield + with condition: + wait_cell[0] = False + condition.notify_all() + def half_duplex_request_iterator(): + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + with condition: + while wait_cell[0]: + condition.wait() + with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server): + with wait(): + responses = stub.HalfDuplexCall( + half_duplex_request_iterator(), SHORT_TIMEOUT) + # half-duplex waits for the client to send all info + with self.assertRaises(exceptions.ExpirationError): + next(responses) + + +if __name__ == '__main__': + os.chdir(os.path.dirname(sys.argv[0])) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_test/grpc_protoc_plugin/beta_python_plugin_test.py b/src/python/grpcio_test/grpc_protoc_plugin/beta_python_plugin_test.py new file mode 100644 index 0000000000..4c8c64b06d --- /dev/null +++ b/src/python/grpcio_test/grpc_protoc_plugin/beta_python_plugin_test.py @@ -0,0 +1,501 @@ +# 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. + +import argparse +import contextlib +import distutils.spawn +import errno +import itertools +import os +import pkg_resources +import shutil +import subprocess +import sys +import tempfile +import threading +import time +import unittest + +from grpc.beta import beta +from grpc.framework.foundation import future +from grpc.framework.interfaces.face import face +from grpc_test.framework.common import test_constants + +# Identifiers of entities we expect to find in the generated module. +SERVICER_IDENTIFIER = 'BetaTestServiceServicer' +STUB_IDENTIFIER = 'BetaTestServiceStub' +SERVER_FACTORY_IDENTIFIER = 'beta_create_TestService_server' +STUB_FACTORY_IDENTIFIER = 'beta_create_TestService_stub' + + +class _ServicerMethods(object): + + def __init__(self, test_pb2): + self._condition = threading.Condition() + self._paused = False + self._fail = False + self._test_pb2 = test_pb2 + + @contextlib.contextmanager + def pause(self): # pylint: disable=invalid-name + with self._condition: + self._paused = True + yield + with self._condition: + self._paused = False + self._condition.notify_all() + + @contextlib.contextmanager + def fail(self): # pylint: disable=invalid-name + with self._condition: + self._fail = True + yield + with self._condition: + self._fail = False + + def _control(self): # pylint: disable=invalid-name + with self._condition: + if self._fail: + raise ValueError() + while self._paused: + self._condition.wait() + + def UnaryCall(self, request, unused_rpc_context): + response = self._test_pb2.SimpleResponse() + response.payload.payload_type = self._test_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * request.response_size + self._control() + return response + + def StreamingOutputCall(self, request, unused_rpc_context): + for parameter in request.response_parameters: + response = self._test_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._test_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + yield response + + def StreamingInputCall(self, request_iter, unused_rpc_context): + response = self._test_pb2.StreamingInputCallResponse() + aggregated_payload_size = 0 + for request in request_iter: + aggregated_payload_size += len(request.payload.payload_compressable) + response.aggregated_payload_size = aggregated_payload_size + self._control() + return response + + def FullDuplexCall(self, request_iter, unused_rpc_context): + for request in request_iter: + for parameter in request.response_parameters: + response = self._test_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._test_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + yield response + + def HalfDuplexCall(self, request_iter, unused_rpc_context): + responses = [] + for request in request_iter: + for parameter in request.response_parameters: + response = self._test_pb2.StreamingOutputCallResponse() + response.payload.payload_type = self._test_pb2.COMPRESSABLE + response.payload.payload_compressable = 'a' * parameter.size + self._control() + responses.append(response) + for response in responses: + yield response + + +@contextlib.contextmanager +def _CreateService(test_pb2): + """Provides a servicer backend and a stub. + + The servicer is just the implementation of the actual servicer passed to the + face player of the python RPC implementation; the two are detached. + + Args: + test_pb2: The test_pb2 module generated by this test. + + Yields: + A (servicer_methods, stub) pair where servicer_methods is the back-end of + the service bound to the stub and and stub is the stub on which to invoke + RPCs. + """ + servicer_methods = _ServicerMethods(test_pb2) + + class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)): + + def UnaryCall(self, request, context): + return servicer_methods.UnaryCall(request, context) + + def StreamingOutputCall(self, request, context): + return servicer_methods.StreamingOutputCall(request, context) + + def StreamingInputCall(self, request_iter, context): + return servicer_methods.StreamingInputCall(request_iter, context) + + def FullDuplexCall(self, request_iter, context): + return servicer_methods.FullDuplexCall(request_iter, context) + + def HalfDuplexCall(self, request_iter, context): + return servicer_methods.HalfDuplexCall(request_iter, context) + + servicer = Servicer() + server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) + port = server.add_insecure_port('[::]:0') + server.start() + channel = beta.create_insecure_channel('localhost', port) + stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)(channel) + yield servicer_methods, stub + server.stop(0) + + +def _streaming_input_request_iterator(test_pb2): + for _ in range(3): + request = test_pb2.StreamingInputCallRequest() + request.payload.payload_type = test_pb2.COMPRESSABLE + request.payload.payload_compressable = 'a' + yield request + + +def _streaming_output_request(test_pb2): + request = test_pb2.StreamingOutputCallRequest() + sizes = [1, 2, 3] + request.response_parameters.add(size=sizes[0], interval_us=0) + request.response_parameters.add(size=sizes[1], interval_us=0) + request.response_parameters.add(size=sizes[2], interval_us=0) + return request + + +def _full_duplex_request_iterator(test_pb2): + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=2, interval_us=0) + request.response_parameters.add(size=3, interval_us=0) + yield request + + +class PythonPluginTest(unittest.TestCase): + """Test case for the gRPC Python protoc-plugin. + + While reading these tests, remember that the futures API + (`stub.method.future()`) only gives futures for the *response-unary* + methods and does not exist for response-streaming methods. + """ + + def setUp(self): + # Assume that the appropriate protoc and grpc_python_plugins are on the + # path. + protoc_command = 'protoc' + protoc_plugin_filename = distutils.spawn.find_executable( + 'grpc_python_plugin') + test_proto_filename = pkg_resources.resource_filename( + 'grpc_protoc_plugin', 'test.proto') + if not os.path.isfile(protoc_command): + # Assume that if we haven't built protoc that it's on the system. + protoc_command = 'protoc' + + # Ensure that the output directory exists. + self.outdir = tempfile.mkdtemp() + + # Invoke protoc with the plugin. + cmd = [ + protoc_command, + '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename, + '-I .', + '--python_out=%s' % self.outdir, + '--python-grpc_out=%s' % self.outdir, + os.path.basename(test_proto_filename), + ] + subprocess.check_call(' '.join(cmd), shell=True, env=os.environ, + cwd=os.path.dirname(test_proto_filename)) + sys.path.append(self.outdir) + + def tearDown(self): + try: + shutil.rmtree(self.outdir) + except OSError as exc: + if exc.errno != errno.ENOENT: + raise + + def testImportAttributes(self): + # check that we can access the generated module and its members. + import test_pb2 # pylint: disable=g-import-not-at-top + self.assertIsNotNone(getattr(test_pb2, SERVICER_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, STUB_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, SERVER_FACTORY_IDENTIFIER, None)) + self.assertIsNotNone(getattr(test_pb2, STUB_FACTORY_IDENTIFIER, None)) + + def testUpDown(self): + import test_pb2 + with _CreateService(test_pb2) as (servicer, stub): + request = test_pb2.SimpleRequest(response_size=13) + + def testUnaryCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + request = test_pb2.SimpleRequest(response_size=13) + response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT) + expected_response = methods.UnaryCall(request, 'not a real context!') + self.assertEqual(expected_response, response) + + def testUnaryCallFuture(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = test_pb2.SimpleRequest(response_size=13) + with _CreateService(test_pb2) as (methods, stub): + # Check that the call does not block waiting for the server to respond. + with methods.pause(): + response_future = stub.UnaryCall.future( + request, test_constants.LONG_TIMEOUT) + response = response_future.result() + expected_response = methods.UnaryCall(request, 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testUnaryCallFutureExpired(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + request = test_pb2.SimpleRequest(response_size=13) + with methods.pause(): + response_future = stub.UnaryCall.future( + request, test_constants.SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + response_future.result() + + def testUnaryCallFutureCancelled(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = test_pb2.SimpleRequest(response_size=13) + with _CreateService(test_pb2) as (methods, stub): + with methods.pause(): + response_future = stub.UnaryCall.future(request, 1) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + + def testUnaryCallFutureFailed(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = test_pb2.SimpleRequest(response_size=13) + with _CreateService(test_pb2) as (methods, stub): + with methods.fail(): + response_future = stub.UnaryCall.future( + request, test_constants.LONG_TIMEOUT) + self.assertIsNotNone(response_future.exception()) + + def testStreamingOutputCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = _streaming_output_request(test_pb2) + with _CreateService(test_pb2) as (methods, stub): + responses = stub.StreamingOutputCall( + request, test_constants.LONG_TIMEOUT) + expected_responses = methods.StreamingOutputCall( + request, 'not a real RpcContext!') + for expected_response, response in itertools.izip_longest( + expected_responses, responses): + self.assertEqual(expected_response, response) + + def testStreamingOutputCallExpired(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = _streaming_output_request(test_pb2) + with _CreateService(test_pb2) as (methods, stub): + with methods.pause(): + responses = stub.StreamingOutputCall( + request, test_constants.SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + list(responses) + + def testStreamingOutputCallCancelled(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = _streaming_output_request(test_pb2) + with _CreateService(test_pb2) as (unused_methods, stub): + responses = stub.StreamingOutputCall( + request, test_constants.LONG_TIMEOUT) + next(responses) + responses.cancel() + with self.assertRaises(face.CancellationError): + next(responses) + + def testStreamingOutputCallFailed(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request = _streaming_output_request(test_pb2) + with _CreateService(test_pb2) as (methods, stub): + with methods.fail(): + responses = stub.StreamingOutputCall(request, 1) + self.assertIsNotNone(responses) + with self.assertRaises(face.RemoteError): + next(responses) + + def testStreamingInputCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + response = stub.StreamingInputCall( + _streaming_input_request_iterator(test_pb2), + test_constants.LONG_TIMEOUT) + expected_response = methods.StreamingInputCall( + _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testStreamingInputCallFuture(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + with methods.pause(): + response_future = stub.StreamingInputCall.future( + _streaming_input_request_iterator(test_pb2), + test_constants.LONG_TIMEOUT) + response = response_future.result() + expected_response = methods.StreamingInputCall( + _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!') + self.assertEqual(expected_response, response) + + def testStreamingInputCallFutureExpired(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + with methods.pause(): + response_future = stub.StreamingInputCall.future( + _streaming_input_request_iterator(test_pb2), + test_constants.SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + response_future.result() + self.assertIsInstance( + response_future.exception(), face.ExpirationError) + + def testStreamingInputCallFutureCancelled(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + with methods.pause(): + response_future = stub.StreamingInputCall.future( + _streaming_input_request_iterator(test_pb2), + test_constants.LONG_TIMEOUT) + response_future.cancel() + self.assertTrue(response_future.cancelled()) + with self.assertRaises(future.CancelledError): + response_future.result() + + def testStreamingInputCallFutureFailed(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + with methods.fail(): + response_future = stub.StreamingInputCall.future( + _streaming_input_request_iterator(test_pb2), + test_constants.LONG_TIMEOUT) + self.assertIsNotNone(response_future.exception()) + + def testFullDuplexCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + responses = stub.FullDuplexCall( + _full_duplex_request_iterator(test_pb2), test_constants.LONG_TIMEOUT) + expected_responses = methods.FullDuplexCall( + _full_duplex_request_iterator(test_pb2), 'not a real RpcContext!') + for expected_response, response in itertools.izip_longest( + expected_responses, responses): + self.assertEqual(expected_response, response) + + def testFullDuplexCallExpired(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request_iterator = _full_duplex_request_iterator(test_pb2) + with _CreateService(test_pb2) as (methods, stub): + with methods.pause(): + responses = stub.FullDuplexCall( + request_iterator, test_constants.SHORT_TIMEOUT) + with self.assertRaises(face.ExpirationError): + list(responses) + + def testFullDuplexCallCancelled(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + request_iterator = _full_duplex_request_iterator(test_pb2) + responses = stub.FullDuplexCall( + request_iterator, test_constants.LONG_TIMEOUT) + next(responses) + responses.cancel() + with self.assertRaises(face.CancellationError): + next(responses) + + def testFullDuplexCallFailed(self): + import test_pb2 # pylint: disable=g-import-not-at-top + request_iterator = _full_duplex_request_iterator(test_pb2) + with _CreateService(test_pb2) as (methods, stub): + with methods.fail(): + responses = stub.FullDuplexCall( + request_iterator, test_constants.LONG_TIMEOUT) + self.assertIsNotNone(responses) + with self.assertRaises(face.RemoteError): + next(responses) + + def testHalfDuplexCall(self): + import test_pb2 # pylint: disable=g-import-not-at-top + with _CreateService(test_pb2) as (methods, stub): + def half_duplex_request_iterator(): + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=2, interval_us=0) + request.response_parameters.add(size=3, interval_us=0) + yield request + responses = stub.HalfDuplexCall( + half_duplex_request_iterator(), test_constants.LONG_TIMEOUT) + expected_responses = methods.HalfDuplexCall( + half_duplex_request_iterator(), 'not a real RpcContext!') + for check in itertools.izip_longest(expected_responses, responses): + expected_response, response = check + self.assertEqual(expected_response, response) + + def testHalfDuplexCallWedged(self): + import test_pb2 # pylint: disable=g-import-not-at-top + condition = threading.Condition() + wait_cell = [False] + @contextlib.contextmanager + def wait(): # pylint: disable=invalid-name + # Where's Python 3's 'nonlocal' statement when you need it? + with condition: + wait_cell[0] = True + yield + with condition: + wait_cell[0] = False + condition.notify_all() + def half_duplex_request_iterator(): + request = test_pb2.StreamingOutputCallRequest() + request.response_parameters.add(size=1, interval_us=0) + yield request + with condition: + while wait_cell[0]: + condition.wait() + with _CreateService(test_pb2) as (methods, stub): + with wait(): + responses = stub.HalfDuplexCall( + half_duplex_request_iterator(), test_constants.SHORT_TIMEOUT) + # half-duplex waits for the client to send all info + with self.assertRaises(face.ExpirationError): + next(responses) + + +if __name__ == '__main__': + os.chdir(os.path.dirname(sys.argv[0])) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_test/grpc_test/_core_over_links_base_interface_test.py b/src/python/grpcio_test/grpc_test/_core_over_links_base_interface_test.py index 7fa90fe35f..f0bd989ea6 100644 --- a/src/python/grpcio_test/grpc_test/_core_over_links_base_interface_test.py +++ b/src/python/grpcio_test/grpc_test/_core_over_links_base_interface_test.py @@ -45,11 +45,7 @@ from grpc_test.framework.common import test_constants from grpc_test.framework.interfaces.base import test_cases from grpc_test.framework.interfaces.base import test_interfaces -_INVOCATION_INITIAL_METADATA = ((b'0', b'abc'), (b'1', b'def'), (b'2', b'ghi'),) -_SERVICE_INITIAL_METADATA = ((b'3', b'jkl'), (b'4', b'mno'), (b'5', b'pqr'),) -_SERVICE_TERMINAL_METADATA = ((b'6', b'stu'), (b'7', b'vwx'), (b'8', b'yza'),) _CODE = _intermediary_low.Code.OK -_MESSAGE = b'test message' class _SerializationBehaviors( @@ -95,10 +91,10 @@ class _Implementation(test_interfaces.Implementation): service_grpc_link = service.service_link( serialization_behaviors.request_deserializers, serialization_behaviors.response_serializers) - port = service_grpc_link.add_port(0, None) + port = service_grpc_link.add_port('[::]:0', None) channel = _intermediary_low.Channel('localhost:%d' % port, None) invocation_grpc_link = invocation.invocation_link( - channel, b'localhost', + channel, b'localhost', None, serialization_behaviors.request_serializers, serialization_behaviors.response_deserializers) @@ -114,19 +110,22 @@ class _Implementation(test_interfaces.Implementation): def destantiate(self, memo): invocation_grpc_link, service_grpc_link = memo invocation_grpc_link.stop() - service_grpc_link.stop_gracefully() + service_grpc_link.begin_stop() + service_grpc_link.end_stop() def invocation_initial_metadata(self): - return _INVOCATION_INITIAL_METADATA + return grpc_test_common.INVOCATION_INITIAL_METADATA def service_initial_metadata(self): - return _SERVICE_INITIAL_METADATA + return grpc_test_common.SERVICE_INITIAL_METADATA def invocation_completion(self): return utilities.completion(None, None, None) def service_completion(self): - return utilities.completion(_SERVICE_TERMINAL_METADATA, _CODE, _MESSAGE) + return utilities.completion( + grpc_test_common.SERVICE_TERMINAL_METADATA, _CODE, + grpc_test_common.DETAILS) def metadata_transmitted(self, original_metadata, transmitted_metadata): return original_metadata is None or grpc_test_common.metadata_transmitted( @@ -146,14 +145,6 @@ class _Implementation(test_interfaces.Implementation): return True -def setUpModule(): - logging.warn('setUpModule!') - - -def tearDownModule(): - logging.warn('tearDownModule!') - - def load_tests(loader, tests, pattern): return unittest.TestSuite( tests=tuple( diff --git a/src/python/grpcio_test/grpc_test/_crust_over_core_over_links_face_interface_test.py b/src/python/grpcio_test/grpc_test/_crust_over_core_over_links_face_interface_test.py index 25b99cbbaf..28c0619f7c 100644 --- a/src/python/grpcio_test/grpc_test/_crust_over_core_over_links_face_interface_test.py +++ b/src/python/grpcio_test/grpc_test/_crust_over_core_over_links_face_interface_test.py @@ -39,11 +39,10 @@ from grpc.framework.core import implementations as core_implementations from grpc.framework.crust import implementations as crust_implementations from grpc.framework.foundation import logging_pool from grpc.framework.interfaces.links import utilities -from grpc_test import test_common +from grpc_test import test_common as grpc_test_common from grpc_test.framework.common import test_constants from grpc_test.framework.interfaces.face import test_cases from grpc_test.framework.interfaces.face import test_interfaces -from grpc_test.framework.interfaces.links import test_utilities class _SerializationBehaviors( @@ -85,10 +84,10 @@ class _Implementation(test_interfaces.Implementation): service_grpc_link = service.service_link( serialization_behaviors.request_deserializers, serialization_behaviors.response_serializers) - port = service_grpc_link.add_port(0, None) + port = service_grpc_link.add_port('[::]:0', None) channel = _intermediary_low.Channel('localhost:%d' % port, None) invocation_grpc_link = invocation.invocation_link( - channel, b'localhost', + channel, b'localhost', None, serialization_behaviors.request_serializers, serialization_behaviors.response_deserializers) @@ -121,8 +120,9 @@ class _Implementation(test_interfaces.Implementation): service_end_link, pool) = memo invocation_end_link.stop(0).wait() invocation_grpc_link.stop() - service_grpc_link.stop_gracefully() + service_grpc_link.begin_stop() service_end_link.stop(0).wait() + service_grpc_link.end_stop() invocation_end_link.join_link(utilities.NULL_LINK) invocation_grpc_link.join_link(utilities.NULL_LINK) service_grpc_link.join_link(utilities.NULL_LINK) @@ -130,19 +130,19 @@ class _Implementation(test_interfaces.Implementation): pool.shutdown(wait=True) def invocation_metadata(self): - return test_common.INVOCATION_INITIAL_METADATA + return grpc_test_common.INVOCATION_INITIAL_METADATA def initial_metadata(self): - return test_common.SERVICE_INITIAL_METADATA + return grpc_test_common.SERVICE_INITIAL_METADATA def terminal_metadata(self): - return test_common.SERVICE_TERMINAL_METADATA + return grpc_test_common.SERVICE_TERMINAL_METADATA def code(self): return _intermediary_low.Code.OK def details(self): - return test_common.DETAILS + return grpc_test_common.DETAILS def metadata_transmitted(self, original_metadata, transmitted_metadata): return original_metadata is None or grpc_test_common.metadata_transmitted( diff --git a/src/python/grpcio_test/grpc_test/_links/_lonely_invocation_link_test.py b/src/python/grpcio_test/grpc_test/_links/_lonely_invocation_link_test.py index 373a2b2a1f..8e12e8cc22 100644 --- a/src/python/grpcio_test/grpc_test/_links/_lonely_invocation_link_test.py +++ b/src/python/grpcio_test/grpc_test/_links/_lonely_invocation_link_test.py @@ -45,7 +45,8 @@ class LonelyInvocationLinkTest(unittest.TestCase): def testUpAndDown(self): channel = _intermediary_low.Channel('nonexistent:54321', None) - invocation_link = invocation.invocation_link(channel, 'nonexistent', {}, {}) + invocation_link = invocation.invocation_link( + channel, 'nonexistent', None, {}, {}) invocation_link.start() invocation_link.stop() @@ -58,8 +59,7 @@ class LonelyInvocationLinkTest(unittest.TestCase): channel = _intermediary_low.Channel('nonexistent:54321', None) invocation_link = invocation.invocation_link( - channel, 'nonexistent', {(test_group, test_method): _NULL_BEHAVIOR}, - {(test_group, test_method): _NULL_BEHAVIOR}) + channel, 'nonexistent', None, {}, {}) invocation_link.join_link(invocation_link_mate) invocation_link.start() diff --git a/src/python/grpcio_test/grpc_test/_links/_transmission_test.py b/src/python/grpcio_test/grpc_test/_links/_transmission_test.py index db011bca66..716323cc20 100644 --- a/src/python/grpcio_test/grpc_test/_links/_transmission_test.py +++ b/src/python/grpcio_test/grpc_test/_links/_transmission_test.py @@ -50,11 +50,11 @@ class TransmissionTest(test_cases.TransmissionTest, unittest.TestCase): service_link = service.service_link( {self.group_and_method(): self.deserialize_request}, {self.group_and_method(): self.serialize_response}) - port = service_link.add_port(0, None) + port = service_link.add_port('[::]:0', None) service_link.start() channel = _intermediary_low.Channel('localhost:%d' % port, None) invocation_link = invocation.invocation_link( - channel, 'localhost', + channel, 'localhost', None, {self.group_and_method(): self.serialize_request}, {self.group_and_method(): self.deserialize_response}) invocation_link.start() @@ -62,7 +62,8 @@ class TransmissionTest(test_cases.TransmissionTest, unittest.TestCase): def destroy_transmitting_links(self, invocation_side_link, service_side_link): invocation_side_link.stop() - service_side_link.stop_gracefully() + service_side_link.begin_stop() + service_side_link.end_stop() def create_invocation_initial_metadata(self): return ( @@ -116,11 +117,11 @@ class RoundTripTest(unittest.TestCase): identity_transformation, identity_transformation) service_mate = test_utilities.RecordingLink() service_link.join_link(service_mate) - port = service_link.add_port(0, None) + port = service_link.add_port('[::]:0', None) service_link.start() channel = _intermediary_low.Channel('localhost:%d' % port, None) invocation_link = invocation.invocation_link( - channel, 'localhost', identity_transformation, identity_transformation) + channel, None, None, identity_transformation, identity_transformation) invocation_mate = test_utilities.RecordingLink() invocation_link.join_link(invocation_mate) invocation_link.start() @@ -140,7 +141,8 @@ class RoundTripTest(unittest.TestCase): invocation_mate.block_until_tickets_satisfy(test_cases.terminated) invocation_link.stop() - service_link.stop_gracefully() + service_link.begin_stop() + service_link.end_stop() self.assertIs( service_mate.tickets()[-1].termination, @@ -160,11 +162,11 @@ class RoundTripTest(unittest.TestCase): {(test_group, test_method): scenario.serialize_response}) service_mate = test_utilities.RecordingLink() service_link.join_link(service_mate) - port = service_link.add_port(0, None) + port = service_link.add_port('[::]:0', None) service_link.start() channel = _intermediary_low.Channel('localhost:%d' % port, None) invocation_link = invocation.invocation_link( - channel, 'localhost', + channel, 'localhost', None, {(test_group, test_method): scenario.serialize_request}, {(test_group, test_method): scenario.deserialize_response}) invocation_mate = test_utilities.RecordingLink() @@ -206,7 +208,8 @@ class RoundTripTest(unittest.TestCase): invocation_mate.block_until_tickets_satisfy(test_cases.terminated) invocation_link.stop() - service_link.stop_gracefully() + service_link.begin_stop() + service_link.end_stop() observed_requests = tuple( ticket.payload for ticket in service_mate.tickets() diff --git a/src/python/grpcio_test/grpc_test/beta/__init__.py b/src/python/grpcio_test/grpc_test/beta/__init__.py new file mode 100644 index 0000000000..7086519106 --- /dev/null +++ b/src/python/grpcio_test/grpc_test/beta/__init__.py @@ -0,0 +1,30 @@ +# 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. + + diff --git a/src/python/grpcio_test/grpc_test/beta/_connectivity_channel_test.py b/src/python/grpcio_test/grpc_test/beta/_connectivity_channel_test.py new file mode 100644 index 0000000000..038464889d --- /dev/null +++ b/src/python/grpcio_test/grpc_test/beta/_connectivity_channel_test.py @@ -0,0 +1,180 @@ +# 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. + +"""Tests of grpc.beta._connectivity_channel.""" + +import threading +import time +import unittest + +from grpc._adapter import _low +from grpc._adapter import _types +from grpc.beta import _connectivity_channel +from grpc_test.framework.common import test_constants + +_MAPPING_FUNCTION = lambda integer: integer * 200 + 17 +_MAPPING = { + state: _MAPPING_FUNCTION(state) for state in _types.ConnectivityState} +_IDLE, _CONNECTING, _READY, _TRANSIENT_FAILURE, _FATAL_FAILURE = map( + _MAPPING_FUNCTION, _types.ConnectivityState) + + +def _drive_completion_queue(completion_queue): + while True: + event = completion_queue.next(time.time() + 24 * 60 * 60) + if event.type == _types.EventType.QUEUE_SHUTDOWN: + break + + +class _Callback(object): + + def __init__(self): + self._condition = threading.Condition() + self._connectivities = [] + + def update(self, connectivity): + with self._condition: + self._connectivities.append(connectivity) + self._condition.notify() + + def connectivities(self): + with self._condition: + return tuple(self._connectivities) + + def block_until_connectivities_satisfy(self, predicate): + with self._condition: + while True: + connectivities = tuple(self._connectivities) + if predicate(connectivities): + return connectivities + else: + self._condition.wait() + + +class ChannelConnectivityTest(unittest.TestCase): + + def test_lonely_channel_connectivity(self): + low_channel = _low.Channel('localhost:12345', ()) + callback = _Callback() + + connectivity_channel = _connectivity_channel.ConnectivityChannel( + low_channel, _MAPPING) + connectivity_channel.subscribe(callback.update, try_to_connect=False) + first_connectivities = callback.block_until_connectivities_satisfy(bool) + connectivity_channel.subscribe(callback.update, try_to_connect=True) + second_connectivities = callback.block_until_connectivities_satisfy( + lambda connectivities: 2 <= len(connectivities)) + # Wait for a connection that will never happen. + time.sleep(test_constants.SHORT_TIMEOUT) + third_connectivities = callback.connectivities() + connectivity_channel.unsubscribe(callback.update) + fourth_connectivities = callback.connectivities() + connectivity_channel.unsubscribe(callback.update) + fifth_connectivities = callback.connectivities() + + self.assertSequenceEqual((_IDLE,), first_connectivities) + self.assertNotIn(_READY, second_connectivities) + self.assertNotIn(_READY, third_connectivities) + self.assertNotIn(_READY, fourth_connectivities) + self.assertNotIn(_READY, fifth_connectivities) + + def test_immediately_connectable_channel_connectivity(self): + server_completion_queue = _low.CompletionQueue() + server = _low.Server(server_completion_queue, []) + port = server.add_http2_port('[::]:0') + server.start() + server_completion_queue_thread = threading.Thread( + target=_drive_completion_queue, args=(server_completion_queue,)) + server_completion_queue_thread.start() + low_channel = _low.Channel('localhost:%d' % port, ()) + first_callback = _Callback() + second_callback = _Callback() + + connectivity_channel = _connectivity_channel.ConnectivityChannel( + low_channel, _MAPPING) + connectivity_channel.subscribe(first_callback.update, try_to_connect=False) + first_connectivities = first_callback.block_until_connectivities_satisfy( + bool) + # Wait for a connection that will never happen because try_to_connect=True + # has not yet been passed. + time.sleep(test_constants.SHORT_TIMEOUT) + second_connectivities = first_callback.connectivities() + connectivity_channel.subscribe(second_callback.update, try_to_connect=True) + third_connectivities = first_callback.block_until_connectivities_satisfy( + lambda connectivities: 2 <= len(connectivities)) + fourth_connectivities = second_callback.block_until_connectivities_satisfy( + bool) + # Wait for a connection that will happen (or may already have happened). + first_callback.block_until_connectivities_satisfy( + lambda connectivities: _READY in connectivities) + second_callback.block_until_connectivities_satisfy( + lambda connectivities: _READY in connectivities) + connectivity_channel.unsubscribe(first_callback.update) + connectivity_channel.unsubscribe(second_callback.update) + + server.shutdown() + server_completion_queue.shutdown() + server_completion_queue_thread.join() + + self.assertSequenceEqual((_IDLE,), first_connectivities) + self.assertSequenceEqual((_IDLE,), second_connectivities) + self.assertNotIn(_TRANSIENT_FAILURE, third_connectivities) + self.assertNotIn(_FATAL_FAILURE, third_connectivities) + self.assertNotIn(_TRANSIENT_FAILURE, fourth_connectivities) + self.assertNotIn(_FATAL_FAILURE, fourth_connectivities) + + def test_reachable_then_unreachable_channel_connectivity(self): + server_completion_queue = _low.CompletionQueue() + server = _low.Server(server_completion_queue, []) + port = server.add_http2_port('[::]:0') + server.start() + server_completion_queue_thread = threading.Thread( + target=_drive_completion_queue, args=(server_completion_queue,)) + server_completion_queue_thread.start() + low_channel = _low.Channel('localhost:%d' % port, ()) + callback = _Callback() + + connectivity_channel = _connectivity_channel.ConnectivityChannel( + low_channel, _MAPPING) + connectivity_channel.subscribe(callback.update, try_to_connect=True) + callback.block_until_connectivities_satisfy( + lambda connectivities: _READY in connectivities) + # Now take down the server and confirm that channel readiness is repudiated. + server.shutdown() + callback.block_until_connectivities_satisfy( + lambda connectivities: connectivities[-1] is not _READY) + connectivity_channel.unsubscribe(callback.update) + + server.shutdown() + server_completion_queue.shutdown() + server_completion_queue_thread.join() + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/src/python/grpcio_test/grpc_test/beta/_face_interface_test.py b/src/python/grpcio_test/grpc_test/beta/_face_interface_test.py new file mode 100644 index 0000000000..ce4c59c0ee --- /dev/null +++ b/src/python/grpcio_test/grpc_test/beta/_face_interface_test.py @@ -0,0 +1,137 @@ +# 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. + +"""Tests Face interface compliance of the gRPC Python Beta API.""" + +import collections +import unittest + +from grpc._adapter import _intermediary_low +from grpc.beta import beta +from grpc_test import resources +from grpc_test import test_common as grpc_test_common +from grpc_test.beta import test_utilities +from grpc_test.framework.common import test_constants +from grpc_test.framework.interfaces.face import test_cases +from grpc_test.framework.interfaces.face import test_interfaces + +_SERVER_HOST_OVERRIDE = 'foo.test.google.fr' + + +class _SerializationBehaviors( + collections.namedtuple( + '_SerializationBehaviors', + ('request_serializers', 'request_deserializers', 'response_serializers', + 'response_deserializers',))): + pass + + +def _serialization_behaviors_from_test_methods(test_methods): + request_serializers = {} + request_deserializers = {} + response_serializers = {} + response_deserializers = {} + for (group, method), test_method in test_methods.iteritems(): + request_serializers[group, method] = test_method.serialize_request + request_deserializers[group, method] = test_method.deserialize_request + response_serializers[group, method] = test_method.serialize_response + response_deserializers[group, method] = test_method.deserialize_response + return _SerializationBehaviors( + request_serializers, request_deserializers, response_serializers, + response_deserializers) + + +class _Implementation(test_interfaces.Implementation): + + def instantiate( + self, methods, method_implementations, multi_method_implementation): + serialization_behaviors = _serialization_behaviors_from_test_methods( + methods) + # TODO(nathaniel): Add a "groups" attribute to _digest.TestServiceDigest. + service = next(iter(methods))[0] + # TODO(nathaniel): Add a "cardinalities_by_group" attribute to + # _digest.TestServiceDigest. + cardinalities = { + method: method_object.cardinality() + for (group, method), method_object in methods.iteritems()} + + server_options = beta.server_options( + request_deserializers=serialization_behaviors.request_deserializers, + response_serializers=serialization_behaviors.response_serializers, + thread_pool_size=test_constants.POOL_SIZE) + server = beta.server(method_implementations, options=server_options) + server_credentials = beta.ssl_server_credentials( + [(resources.private_key(), resources.certificate_chain(),),]) + port = server.add_secure_port('[::]:0', server_credentials) + server.start() + client_credentials = beta.ssl_client_credentials( + resources.test_root_certificates(), None, None) + channel = test_utilities.create_not_really_secure_channel( + 'localhost', port, client_credentials, _SERVER_HOST_OVERRIDE) + stub_options = beta.stub_options( + request_serializers=serialization_behaviors.request_serializers, + response_deserializers=serialization_behaviors.response_deserializers, + thread_pool_size=test_constants.POOL_SIZE) + generic_stub = beta.generic_stub(channel, options=stub_options) + dynamic_stub = beta.dynamic_stub( + channel, service, cardinalities, options=stub_options) + return generic_stub, {service: dynamic_stub}, server + + def destantiate(self, memo): + memo.stop(test_constants.SHORT_TIMEOUT).wait() + + def invocation_metadata(self): + return grpc_test_common.INVOCATION_INITIAL_METADATA + + def initial_metadata(self): + return grpc_test_common.SERVICE_INITIAL_METADATA + + def terminal_metadata(self): + return grpc_test_common.SERVICE_TERMINAL_METADATA + + def code(self): + return _intermediary_low.Code.OK + + def details(self): + return grpc_test_common.DETAILS + + def metadata_transmitted(self, original_metadata, transmitted_metadata): + return original_metadata is None or grpc_test_common.metadata_transmitted( + original_metadata, transmitted_metadata) + + +def load_tests(loader, tests, pattern): + return unittest.TestSuite( + tests=tuple( + loader.loadTestsFromTestCase(test_case_class) + for test_case_class in test_cases.test_cases(_Implementation()))) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/src/python/grpcio_test/grpc_test/beta/_utilities_test.py b/src/python/grpcio_test/grpc_test/beta/_utilities_test.py new file mode 100644 index 0000000000..998e74ccf4 --- /dev/null +++ b/src/python/grpcio_test/grpc_test/beta/_utilities_test.py @@ -0,0 +1,123 @@ +# 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. + +"""Tests of grpc.beta.utilities.""" + +import threading +import time +import unittest + +from grpc._adapter import _low +from grpc._adapter import _types +from grpc.beta import beta +from grpc.beta import utilities +from grpc.framework.foundation import future +from grpc_test.framework.common import test_constants + + +def _drive_completion_queue(completion_queue): + while True: + event = completion_queue.next(time.time() + 24 * 60 * 60) + if event.type == _types.EventType.QUEUE_SHUTDOWN: + break + + +class _Callback(object): + + def __init__(self): + self._condition = threading.Condition() + self._value = None + + def accept_value(self, value): + with self._condition: + self._value = value + self._condition.notify_all() + + def block_until_called(self): + with self._condition: + while self._value is None: + self._condition.wait() + return self._value + + +class ChannelConnectivityTest(unittest.TestCase): + + def test_lonely_channel_connectivity(self): + channel = beta.create_insecure_channel('localhost', 12345) + callback = _Callback() + + ready_future = utilities.channel_ready_future(channel) + ready_future.add_done_callback(callback.accept_value) + with self.assertRaises(future.TimeoutError): + ready_future.result(test_constants.SHORT_TIMEOUT) + self.assertFalse(ready_future.cancelled()) + self.assertFalse(ready_future.done()) + self.assertTrue(ready_future.running()) + ready_future.cancel() + value_passed_to_callback = callback.block_until_called() + self.assertIs(ready_future, value_passed_to_callback) + self.assertTrue(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + + def test_immediately_connectable_channel_connectivity(self): + server_completion_queue = _low.CompletionQueue() + server = _low.Server(server_completion_queue, []) + port = server.add_http2_port('[::]:0') + server.start() + server_completion_queue_thread = threading.Thread( + target=_drive_completion_queue, args=(server_completion_queue,)) + server_completion_queue_thread.start() + channel = beta.create_insecure_channel('localhost', port) + callback = _Callback() + + try: + ready_future = utilities.channel_ready_future(channel) + ready_future.add_done_callback(callback.accept_value) + self.assertIsNone( + ready_future.result(test_constants.SHORT_TIMEOUT)) + value_passed_to_callback = callback.block_until_called() + self.assertIs(ready_future, value_passed_to_callback) + self.assertFalse(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + # Cancellation after maturity has no effect. + ready_future.cancel() + self.assertFalse(ready_future.cancelled()) + self.assertTrue(ready_future.done()) + self.assertFalse(ready_future.running()) + finally: + ready_future.cancel() + server.shutdown() + server_completion_queue.shutdown() + server_completion_queue_thread.join() + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/src/python/grpcio_test/grpc_test/beta/test_utilities.py b/src/python/grpcio_test/grpc_test/beta/test_utilities.py new file mode 100644 index 0000000000..338670478d --- /dev/null +++ b/src/python/grpcio_test/grpc_test/beta/test_utilities.py @@ -0,0 +1,54 @@ +# 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. + +"""Test-appropriate entry points into the gRPC Python Beta API.""" + +from grpc._adapter import _intermediary_low +from grpc.beta import beta + + +def create_not_really_secure_channel( + host, port, client_credentials, server_host_override): + """Creates an insecure Channel to a remote host. + + Args: + host: The name of the remote host to which to connect. + port: The port of the remote host to which to connect. + client_credentials: The beta.ClientCredentials with which to connect. + server_host_override: The target name used for SSL host name checking. + + Returns: + A beta.Channel to the remote host through which RPCs may be conducted. + """ + hostport = '%s:%d' % (host, port) + intermediary_low_channel = _intermediary_low.Channel( + hostport, client_credentials._intermediary_low_credentials, + server_host_override=server_host_override) + return beta.Channel( + intermediary_low_channel._internal, intermediary_low_channel) diff --git a/src/python/grpcio_test/grpc_test/credentials/README b/src/python/grpcio_test/grpc_test/credentials/README new file mode 100644 index 0000000000..cb20dcb49f --- /dev/null +++ b/src/python/grpcio_test/grpc_test/credentials/README @@ -0,0 +1 @@ +These are test keys *NOT* to be used in production. diff --git a/src/python/grpcio_test/grpc_test/credentials/ca.pem b/src/python/grpcio_test/grpc_test/credentials/ca.pem new file mode 100755 index 0000000000..6c8511a73c --- /dev/null +++ b/src/python/grpcio_test/grpc_test/credentials/ca.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla +Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0 +YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT +BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7 ++L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu +g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd +Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau +sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m +oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG +Dfcog5wrJytaQ6UA0wE= +-----END CERTIFICATE----- diff --git a/src/python/grpcio_test/grpc_test/credentials/server1.key b/src/python/grpcio_test/grpc_test/credentials/server1.key new file mode 100755 index 0000000000..143a5b8765 --- /dev/null +++ b/src/python/grpcio_test/grpc_test/credentials/server1.key @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOHDFScoLCVJpYDD +M4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1BgzkWF+slf +3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd9N8YwbBY +AckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAECgYAn7qGnM2vbjJNBm0VZCkOkTIWm +V10okw7EPJrdL2mkre9NasghNXbE1y5zDshx5Nt3KsazKOxTT8d0Jwh/3KbaN+YY +tTCbKGW0pXDRBhwUHRcuRzScjli8Rih5UOCiZkhefUTcRb6xIhZJuQy71tjaSy0p +dHZRmYyBYO2YEQ8xoQJBAPrJPhMBkzmEYFtyIEqAxQ/o/A6E+E4w8i+KM7nQCK7q +K4JXzyXVAjLfyBZWHGM2uro/fjqPggGD6QH1qXCkI4MCQQDmdKeb2TrKRh5BY1LR +81aJGKcJ2XbcDu6wMZK4oqWbTX2KiYn9GB0woM6nSr/Y6iy1u145YzYxEV/iMwff +DJULAkB8B2MnyzOg0pNFJqBJuH29bKCcHa8gHJzqXhNO5lAlEbMK95p/P2Wi+4Hd +aiEIAF1BF326QJcvYKmwSmrORp85AkAlSNxRJ50OWrfMZnBgzVjDx3xG6KsFQVk2 +ol6VhqL6dFgKUORFUWBvnKSyhjJxurlPEahV6oo6+A+mPhFY8eUvAkAZQyTdupP3 +XEFQKctGz+9+gKkemDp7LBBMEMBXrGTLPhpEfcjv/7KPdnFHYmhYeBTBnuVmTVWe +F98XJ7tIFfJq +-----END PRIVATE KEY----- diff --git a/src/python/grpcio_test/grpc_test/credentials/server1.pem b/src/python/grpcio_test/grpc_test/credentials/server1.pem new file mode 100755 index 0000000000..8e582e571f --- /dev/null +++ b/src/python/grpcio_test/grpc_test/credentials/server1.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICmzCCAgSgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET +MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ +dHkgTHRkMQ8wDQYDVQQDDAZ0ZXN0Y2EwHhcNMTQwNzIyMDYwMDU3WhcNMjQwNzE5 +MDYwMDU3WjBkMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV +BAcTB0NoaWNhZ28xFDASBgNVBAoTC0dvb2dsZSBJbmMuMRowGAYDVQQDFBEqLnRl +c3QuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4cMVJygs +JUmlgMMzgdi0h1XoCR7+ww1pop04OMMyy7H/i0PJ2W6Y35+b4CM8QrkYeEafUGDO +RYX6yV/cHGGsD/x02ye6ey1UDtkGAD/mpDEx8YCrjAc1Vfvt8Fk6Cn1WVIxV/J30 +3xjBsFgByQ55RBp1OLZfVLo6AleBDSbcxaECAwEAAaNrMGkwCQYDVR0TBAIwADAL +BgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0Lmdvb2dsZS5mcoIYd2F0ZXJ6 +b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91dHViZS5jb22HBMCoAQMwDQYJ +KoZIhvcNAQEFBQADgYEAM2Ii0LgTGbJ1j4oqX9bxVcxm+/R5Yf8oi0aZqTJlnLYS +wXcBykxTx181s7WyfJ49WwrYXo78zTDAnf1ma0fPq3e4mpspvyndLh1a+OarHa1e +aT0DIIYk7qeEa1YcVljx2KyLd0r1BBAfrwyGaEPVeJQVYWaOJRU2we/KD4ojf9s= +-----END CERTIFICATE----- diff --git a/src/python/grpcio_test/grpc_test/framework/interfaces/face/_blocking_invocation_inline_service.py b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_blocking_invocation_inline_service.py index 8804f3f223..b7dd5d4d17 100644 --- a/src/python/grpcio_test/grpc_test/framework/interfaces/face/_blocking_invocation_inline_service.py +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_blocking_invocation_inline_service.py @@ -73,6 +73,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): Overriding implementations must call this implementation. """ + self._invoker = None self.implementation.destantiate(self._memo) def testSuccessfulUnaryRequestUnaryResponse(self): diff --git a/src/python/grpcio_test/grpc_test/framework/interfaces/face/_event_invocation_synchronous_event_service.py b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_event_invocation_synchronous_event_service.py index 5a78b4bed2..7cb273bf78 100644 --- a/src/python/grpcio_test/grpc_test/framework/interfaces/face/_event_invocation_synchronous_event_service.py +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_event_invocation_synchronous_event_service.py @@ -74,6 +74,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): Overriding implementations must call this implementation. """ + self._invoker = None self.implementation.destantiate(self._memo) def testSuccessfulUnaryRequestUnaryResponse(self): diff --git a/src/python/grpcio_test/grpc_test/framework/interfaces/face/_future_invocation_asynchronous_event_service.py b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_future_invocation_asynchronous_event_service.py index d1107e1576..272a37f15f 100644 --- a/src/python/grpcio_test/grpc_test/framework/interfaces/face/_future_invocation_asynchronous_event_service.py +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_future_invocation_asynchronous_event_service.py @@ -103,6 +103,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): Overriding implementations must call this implementation. """ + self._invoker = None self.implementation.destantiate(self._memo) self._digest_pool.shutdown(wait=True) diff --git a/src/python/grpcio_test/grpc_test/resources.py b/src/python/grpcio_test/grpc_test/resources.py new file mode 100644 index 0000000000..2c3045313d --- /dev/null +++ b/src/python/grpcio_test/grpc_test/resources.py @@ -0,0 +1,56 @@ +# 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. + +"""Constants and functions for data used in interoperability testing.""" + +import os + +import pkg_resources + +_ROOT_CERTIFICATES_RESOURCE_PATH = 'credentials/ca.pem' +_PRIVATE_KEY_RESOURCE_PATH = 'credentials/server1.key' +_CERTIFICATE_CHAIN_RESOURCE_PATH = 'credentials/server1.pem' + + +def test_root_certificates(): + return pkg_resources.resource_string( + __name__, _ROOT_CERTIFICATES_RESOURCE_PATH) + + +def prod_root_certificates(): + return open(os.environ['SSL_CERT_FILE'], mode='rb').read() + + +def private_key(): + return pkg_resources.resource_string(__name__, _PRIVATE_KEY_RESOURCE_PATH) + + +def certificate_chain(): + return pkg_resources.resource_string( + __name__, _CERTIFICATE_CHAIN_RESOURCE_PATH) diff --git a/src/python/grpcio_test/grpc_test/test_common.py b/src/python/grpcio_test/grpc_test/test_common.py index f8e1f1e43f..44284be88b 100644 --- a/src/python/grpcio_test/grpc_test/test_common.py +++ b/src/python/grpcio_test/grpc_test/test_common.py @@ -31,6 +31,11 @@ import collections +INVOCATION_INITIAL_METADATA = ((b'0', b'abc'), (b'1', b'def'), (b'2', b'ghi'),) +SERVICE_INITIAL_METADATA = ((b'3', b'jkl'), (b'4', b'mno'), (b'5', b'pqr'),) +SERVICE_TERMINAL_METADATA = ((b'6', b'stu'), (b'7', b'vwx'), (b'8', b'yza'),) +DETAILS = b'test details' + def metadata_transmitted(original_metadata, transmitted_metadata): """Judges whether or not metadata was acceptably transmitted. diff --git a/src/python/grpcio_test/setup.py b/src/python/grpcio_test/setup.py index 898ea204ac..802dd1e53a 100644 --- a/src/python/grpcio_test/setup.py +++ b/src/python/grpcio_test/setup.py @@ -55,6 +55,11 @@ _PACKAGE_DATA = { 'grpc_protoc_plugin': [ 'test.proto', ], + 'grpc_test': [ + 'credentials/ca.pem', + 'credentials/server1.key', + 'credentials/server1.pem', + ], } _SETUP_REQUIRES = ( diff --git a/src/ruby/.rspec b/src/ruby/.rspec index 2320752db4..efeee2c1d2 100755 --- a/src/ruby/.rspec +++ b/src/ruby/.rspec @@ -1,5 +1,6 @@ -I. -Ipb +--backtrace --require spec_helper --format documentation --color diff --git a/src/ruby/README.md b/src/ruby/README.md index f8902e34c5..7f75c0e313 100644 --- a/src/ruby/README.md +++ b/src/ruby/README.md @@ -19,10 +19,10 @@ INSTALLATION **Linux (Debian):** -Add [Debian unstable][] to your `sources.list` file. Example: +Add [Debian testing][] to your `sources.list` file. Example: ```sh -echo "deb http://ftp.us.debian.org/debian unstable main contrib non-free" | \ +echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \ sudo tee -a /etc/apt/sources.list ``` @@ -99,4 +99,4 @@ Directory structure is the layout for [ruby extensions][] [ruby extensions]:http://guides.rubygems.org/gems-with-extensions/ [rubydoc]: http://www.rubydoc.info/gems/grpc [grpc.io]: http://www.grpc.io/docs/installation/ruby.html -[Debian unstable]:https://www.debian.org/releases/sid/ +[Debian testing]:https://www.debian.org/releases/stretch/ diff --git a/src/ruby/bin/math_client.rb b/src/ruby/bin/math_client.rb index 6319cda309..0ebd26f780 100755 --- a/src/ruby/bin/math_client.rb +++ b/src/ruby/bin/math_client.rb @@ -50,7 +50,7 @@ def do_div(stub) GRPC.logger.info('----------------') req = Math::DivArgs.new(dividend: 7, divisor: 3) GRPC.logger.info("div(7/3): req=#{req.inspect}") - resp = stub.div(req, INFINITE_FUTURE) + resp = stub.div(req, timeout: INFINITE_FUTURE) GRPC.logger.info("Answer: #{resp.inspect}") GRPC.logger.info('----------------') end @@ -71,7 +71,7 @@ def do_fib(stub) GRPC.logger.info('----------------') req = Math::FibArgs.new(limit: 11) GRPC.logger.info("fib(11): req=#{req.inspect}") - resp = stub.fib(req, INFINITE_FUTURE) + resp = stub.fib(req, timeout: INFINITE_FUTURE) resp.each do |r| GRPC.logger.info("Answer: #{r.inspect}") end @@ -86,7 +86,7 @@ def do_div_many(stub) reqs << Math::DivArgs.new(dividend: 5, divisor: 2) reqs << Math::DivArgs.new(dividend: 7, divisor: 2) GRPC.logger.info("div(7/3), div(5/2), div(7/2): reqs=#{reqs.inspect}") - resp = stub.div_many(reqs, 10) + resp = stub.div_many(reqs, timeout: INFINITE_FUTURE) resp.each do |r| GRPC.logger.info("Answer: #{r.inspect}") end diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb index b41ccf6ce1..562f197317 100755 --- a/src/ruby/bin/math_server.rb +++ b/src/ruby/bin/math_server.rb @@ -41,9 +41,25 @@ $LOAD_PATH.unshift(this_dir) unless $LOAD_PATH.include?(this_dir) require 'forwardable' require 'grpc' +require 'logger' require 'math_services' require 'optparse' +# RubyLogger defines a logger for gRPC based on the standard ruby logger. +module RubyLogger + def logger + LOGGER + end + + LOGGER = Logger.new(STDOUT) +end + +# GRPC is the general RPC module +module GRPC + # Inject the noop #logger if no module-level logger method has been injected. + extend RubyLogger +end + # Holds state for a fibonacci series class Fibber def initialize(limit) @@ -155,7 +171,8 @@ end def test_server_creds certs = load_test_certs - GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) + GRPC::Core::ServerCredentials.new( + nil, [{ private_key: certs[1], cert_chain: certs[2] }], false) end def main diff --git a/src/ruby/bin/noproto_server.rb b/src/ruby/bin/noproto_server.rb index 90baaf9a2e..72a5762040 100755 --- a/src/ruby/bin/noproto_server.rb +++ b/src/ruby/bin/noproto_server.rb @@ -77,7 +77,8 @@ end def test_server_creds certs = load_test_certs - GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) + GRPC::Core::ServerCredentials.new( + nil, [{ private_key: certs[1], cert_chain: certs[2] }], false) end def main diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 6491aa4fb4..90afdc3fe1 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -150,7 +150,7 @@ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { ch = grpc_insecure_channel_create(target_chars, &args, NULL); } else { creds = grpc_rb_get_wrapped_credentials(credentials); - ch = grpc_secure_channel_create(creds, target_chars, &args); + ch = grpc_secure_channel_create(creds, target_chars, &args, NULL); } if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ diff --git a/src/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_credentials.c index a9dcdbce9f..ae757f6986 100644 --- a/src/ruby/ext/grpc/rb_credentials.c +++ b/src/ruby/ext/grpc/rb_credentials.c @@ -154,7 +154,7 @@ static VALUE grpc_rb_default_credentials_create(VALUE cls) { Creates the default credential instances. */ static VALUE grpc_rb_compute_engine_credentials_create(VALUE cls) { grpc_rb_credentials *wrapper = ALLOC(grpc_rb_credentials); - wrapper->wrapped = grpc_compute_engine_credentials_create(); + wrapper->wrapped = grpc_google_compute_engine_credentials_create(NULL); if (wrapper->wrapped == NULL) { rb_raise(rb_eRuntimeError, "could not create composite engine credentials, not sure why"); @@ -181,8 +181,8 @@ static VALUE grpc_rb_composite_credentials_create(VALUE self, VALUE other) { TypedData_Get_Struct(other, grpc_rb_credentials, &grpc_rb_credentials_data_type, other_wrapper); wrapper = ALLOC(grpc_rb_credentials); - wrapper->wrapped = grpc_composite_credentials_create(self_wrapper->wrapped, - other_wrapper->wrapped); + wrapper->wrapped = grpc_composite_credentials_create( + self_wrapper->wrapped, other_wrapper->wrapped, NULL); if (wrapper->wrapped == NULL) { rb_raise(rb_eRuntimeError, "could not create composite credentials, not sure why"); @@ -234,12 +234,13 @@ static VALUE grpc_rb_credentials_init(int argc, VALUE *argv, VALUE self) { return Qnil; } if (pem_private_key == Qnil && pem_cert_chain == Qnil) { - creds = grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs), NULL); + creds = + grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs), NULL, NULL); } else { key_cert_pair.private_key = RSTRING_PTR(pem_private_key); key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain); creds = grpc_ssl_credentials_create(RSTRING_PTR(pem_root_certs), - &key_cert_pair); + &key_cert_pair, NULL); } if (creds == NULL) { rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 7e76349d2e..4469658869 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -49,6 +49,9 @@ static VALUE grpc_rb_cServer = Qnil; /* id_at is the constructor method of the ruby standard Time class. */ static ID id_at; +/* id_insecure_server is used to indicate that a server is insecure */ +static VALUE id_insecure_server; + /* grpc_rb_server wraps a grpc_server. It provides a peer ruby object, 'mark' to minimize copying when a server is created from ruby. */ typedef struct grpc_rb_server { @@ -234,6 +237,7 @@ static VALUE grpc_rb_server_request_call(VALUE self, VALUE cqueue, grpc_call_error_detail_of(err), err); return Qnil; } + ev = grpc_rb_completion_queue_pluck_event(cqueue, tag_new, timeout); if (ev.type == GRPC_QUEUE_TIMEOUT) { grpc_request_call_stack_cleanup(&st); @@ -298,43 +302,22 @@ static VALUE grpc_rb_server_destroy(int argc, VALUE *argv, VALUE self) { if (s->wrapped != NULL) { grpc_server_shutdown_and_notify(s->wrapped, cq, NULL); ev = grpc_rb_completion_queue_pluck_event(cqueue, Qnil, timeout); - if (!ev.success) { - rb_warn("server shutdown failed, there will be a LEAKED object warning"); - return Qnil; - /* - TODO: renable the rb_raise below. - - At the moment if the timeout is INFINITE_FUTURE as recommended, the - pluck blocks forever, even though - - the outstanding server_request_calls correctly fail on the other - thread that they are running on. - - it's almost as if calls that fail on the other thread do not get - cleaned up by shutdown request, even though it caused htem to - terminate. - - rb_raise(rb_eRuntimeError, "grpc server shutdown did not succeed"); - return Qnil; - - The workaround is just to use a timeout and return without really - shutting down the server, and rely on the grpc core garbage collection - it down as a 'LEAKED OBJECT'. - - */ + rb_warn("server shutdown failed, cancelling the calls, objects may leak"); + grpc_server_cancel_all_calls(s->wrapped); + return Qfalse; } grpc_server_destroy(s->wrapped); s->wrapped = NULL; } - return Qnil; + return Qtrue; } /* call-seq: // insecure port insecure_server = Server.new(cq, {'arg1': 'value1'}) - insecure_server.add_http2_port('mydomain:50051') + insecure_server.add_http2_port('mydomain:50051', :this_port_is_insecure) // secure port server_creds = ... @@ -342,21 +325,22 @@ static VALUE grpc_rb_server_destroy(int argc, VALUE *argv, VALUE self) { secure_server.add_http_port('mydomain:50051', server_creds) Adds a http2 port to server */ -static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) { - VALUE port = Qnil; - VALUE rb_creds = Qnil; +static VALUE grpc_rb_server_add_http2_port(VALUE self, VALUE port, + VALUE rb_creds) { grpc_rb_server *s = NULL; grpc_server_credentials *creds = NULL; int recvd_port = 0; - /* "11" == 1 mandatory args, 1 (rb_creds) is optional */ - rb_scan_args(argc, argv, "11", &port, &rb_creds); - TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s); if (s->wrapped == NULL) { rb_raise(rb_eRuntimeError, "destroyed!"); return Qnil; - } else if (rb_creds == Qnil) { + } else if (TYPE(rb_creds) == T_SYMBOL) { + if (id_insecure_server != SYM2ID(rb_creds)) { + rb_raise(rb_eTypeError, + "bad creds symbol, want :this_port_is_insecure"); + return Qnil; + } recvd_port = grpc_server_add_insecure_http2_port(s->wrapped, StringValueCStr(port)); if (recvd_port == 0) { @@ -398,8 +382,9 @@ void Init_grpc_server() { rb_define_alias(grpc_rb_cServer, "close", "destroy"); rb_define_method(grpc_rb_cServer, "add_http2_port", grpc_rb_server_add_http2_port, - -1); + 2); id_at = rb_intern("at"); + id_insecure_server = rb_intern("this_port_is_insecure"); } /* Gets the wrapped server from the ruby wrapper */ diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c index 62c211d769..ea4d0d864e 100644 --- a/src/ruby/ext/grpc/rb_server_credentials.c +++ b/src/ruby/ext/grpc/rb_server_credentials.c @@ -135,62 +135,117 @@ static VALUE grpc_rb_server_credentials_init_copy(VALUE copy, VALUE orig) { return copy; } -/* The attribute used on the mark object to hold the pem_root_certs. */ +/* The attribute used on the mark object to preserve the pem_root_certs. */ static ID id_pem_root_certs; -/* The attribute used on the mark object to hold the pem_private_key. */ -static ID id_pem_private_key; +/* The attribute used on the mark object to preserve the pem_key_certs */ +static ID id_pem_key_certs; -/* The attribute used on the mark object to hold the pem_private_key. */ -static ID id_pem_cert_chain; +/* The key used to access the pem cert in a key_cert pair hash */ +static VALUE sym_cert_chain; + +/* The key used to access the pem private key in a key_cert pair hash */ +static VALUE sym_private_key; /* call-seq: - creds = ServerCredentials.new(pem_root_certs, pem_private_key, - pem_cert_chain) - creds = ServerCredentials.new(nil, pem_private_key, - pem_cert_chain) - - pem_root_certs: (required) PEM encoding of the server root certificate - pem_private_key: (optional) PEM encoding of the server's private key - pem_cert_chain: (optional) PEM encoding of the server's cert chain + creds = ServerCredentials.new(nil, + [{private_key: <pem_private_key1>, + {cert_chain: <pem_cert_chain1>}], + force_client_auth) + creds = ServerCredentials.new(pem_root_certs, + [{private_key: <pem_private_key1>, + {cert_chain: <pem_cert_chain1>}], + force_client_auth) + + pem_root_certs: (optional) PEM encoding of the server root certificate + pem_private_key: (required) PEM encoding of the server's private keys + force_client_auth: indicatees Initializes ServerCredential instances. */ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs, - VALUE pem_private_key, - VALUE pem_cert_chain) { - /* TODO support multiple key cert pairs in the ruby API. */ + VALUE pem_key_certs, + VALUE force_client_auth) { grpc_rb_server_credentials *wrapper = NULL; grpc_server_credentials *creds = NULL; - grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL}; - TypedData_Get_Struct(self, grpc_rb_server_credentials, - &grpc_rb_server_credentials_data_type, wrapper); - if (pem_cert_chain == Qnil) { - rb_raise(rb_eRuntimeError, - "could not create a server credential: nil pem_cert_chain"); + grpc_ssl_pem_key_cert_pair *key_cert_pairs = NULL; + VALUE cert = Qnil; + VALUE key = Qnil; + VALUE key_cert = Qnil; + int auth_client = 0; + int num_key_certs = 0; + int i; + + if (NIL_P(force_client_auth) || + !(force_client_auth == Qfalse || force_client_auth == Qtrue)) { + rb_raise(rb_eTypeError, + "bad force_client_auth: got:<%s> want: <True|False|nil>", + rb_obj_classname(force_client_auth)); return Qnil; - } else if (pem_private_key == Qnil) { - rb_raise(rb_eRuntimeError, - "could not create a server credential: nil pem_private_key"); + } + if (NIL_P(pem_key_certs) || TYPE(pem_key_certs) != T_ARRAY) { + rb_raise(rb_eTypeError, "bad pem_key_certs: got:<%s> want: <Array>", + rb_obj_classname(pem_key_certs)); + return Qnil; + } + num_key_certs = RARRAY_LEN(pem_key_certs); + if (num_key_certs == 0) { + rb_raise(rb_eTypeError, "bad pem_key_certs: it had no elements"); return Qnil; } - key_cert_pair.private_key = RSTRING_PTR(pem_private_key); - key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain); - /* TODO Add a force_client_auth parameter and pass it here. */ + for (i = 0; i < num_key_certs; i++) { + key_cert = rb_ary_entry(pem_key_certs, i); + if (key_cert == Qnil) { + rb_raise(rb_eTypeError, + "could not create a server credential: nil key_cert"); + return Qnil; + } else if (TYPE(key_cert) != T_HASH) { + rb_raise(rb_eTypeError, + "could not create a server credential: want <Hash>, got <%s>", + rb_obj_classname(key_cert)); + return Qnil; + } else if (rb_hash_aref(key_cert, sym_private_key) == Qnil) { + rb_raise(rb_eTypeError, + "could not create a server credential: want nil private key"); + return Qnil; + } else if (rb_hash_aref(key_cert, sym_cert_chain) == Qnil) { + rb_raise(rb_eTypeError, + "could not create a server credential: want nil cert chain"); + return Qnil; + } + } + + auth_client = TYPE(force_client_auth) == T_TRUE; + key_cert_pairs = ALLOC_N(grpc_ssl_pem_key_cert_pair, num_key_certs); + for (i = 0; i < num_key_certs; i++) { + key_cert = rb_ary_entry(pem_key_certs, i); + key = rb_hash_aref(key_cert, sym_private_key); + cert = rb_hash_aref(key_cert, sym_cert_chain); + key_cert_pairs[i].private_key = RSTRING_PTR(key); + key_cert_pairs[i].cert_chain = RSTRING_PTR(cert); + } + + TypedData_Get_Struct(self, grpc_rb_server_credentials, + &grpc_rb_server_credentials_data_type, wrapper); + if (pem_root_certs == Qnil) { - creds = grpc_ssl_server_credentials_create(NULL, &key_cert_pair, 1, 0); + creds = grpc_ssl_server_credentials_create(NULL, key_cert_pairs, + num_key_certs, + auth_client, NULL); } else { creds = grpc_ssl_server_credentials_create(RSTRING_PTR(pem_root_certs), - &key_cert_pair, 1, 0); + key_cert_pairs, num_key_certs, + auth_client, NULL); } + xfree(key_cert_pairs); if (creds == NULL) { rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); + return Qnil; } wrapper->wrapped = creds; /* Add the input objects as hidden fields to preserve them. */ - rb_ivar_set(self, id_pem_cert_chain, pem_cert_chain); - rb_ivar_set(self, id_pem_private_key, pem_private_key); + rb_ivar_set(self, id_pem_key_certs, pem_key_certs); rb_ivar_set(self, id_pem_root_certs, pem_root_certs); return self; @@ -210,9 +265,10 @@ void Init_grpc_server_credentials() { rb_define_method(grpc_rb_cServerCredentials, "initialize_copy", grpc_rb_server_credentials_init_copy, 1); - id_pem_cert_chain = rb_intern("__pem_cert_chain"); - id_pem_private_key = rb_intern("__pem_private_key"); + id_pem_key_certs = rb_intern("__pem_key_certs"); id_pem_root_certs = rb_intern("__pem_root_certs"); + sym_private_key = ID2SYM(rb_intern("private_key")); + sym_cert_chain = ID2SYM(rb_intern("cert_chain")); } /* Gets the wrapped grpc_server_credentials from the ruby wrapper */ diff --git a/src/ruby/grpc.gemspec b/src/ruby/grpc.gemspec index 20a6206e7e..093606bb8b 100755 --- a/src/ruby/grpc.gemspec +++ b/src/ruby/grpc.gemspec @@ -14,7 +14,7 @@ Gem::Specification.new do |s| s.license = 'BSD-3-Clause' s.required_ruby_version = '>= 2.0.0' - s.requirements << 'libgrpc ~> 0.10.0 needs to be installed' + s.requirements << 'libgrpc ~> 0.11.0 needs to be installed' s.files = %w( Rakefile ) s.files += Dir.glob('lib/**/*') diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 67bf35ce02..3740ac52da 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -277,10 +277,11 @@ module GRPC @stop_mutex.synchronize do @stopped = true end - @pool.stop deadline = from_relative_time(@poll_period) - + return if @server.close(@cq, deadline) + deadline = from_relative_time(@poll_period) @server.close(@cq, deadline) + @pool.stop end # determines if the server has been stopped @@ -383,7 +384,6 @@ module GRPC @pool.start @server.start loop_handle_server_calls - @running = false end # Sends UNAVAILABLE if there are too many unprocessed jobs @@ -414,23 +414,24 @@ module GRPC fail 'not running' unless @running loop_tag = Object.new until stopped? - deadline = from_relative_time(@poll_period) begin - an_rpc = @server.request_call(@cq, loop_tag, deadline) + an_rpc = @server.request_call(@cq, loop_tag, INFINITE_FUTURE) c = new_active_server_call(an_rpc) + unless c.nil? + mth = an_rpc.method.to_sym + @pool.schedule(c) do |call| + rpc_descs[mth].run_server_method(call, rpc_handlers[mth]) + end + end rescue Core::CallError, RuntimeError => e # these might happen for various reasonse. The correct behaviour of - # the server is to log them and continue. - GRPC.logger.warn("server call failed: #{e}") + # the server is to log them and continue, if it's not shutting down. + GRPC.logger.warn("server call failed: #{e}") unless stopped? next end - unless c.nil? - mth = an_rpc.method.to_sym - @pool.schedule(c) do |call| - rpc_descs[mth].run_server_method(call, rpc_handlers[mth]) - end - end end + @running = false + GRPC.logger.info("stopped: #{self}") end def new_active_server_call(an_rpc) diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 431e8774b5..108c22b25e 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -29,5 +29,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '0.10.0' + VERSION = '0.11.0' end diff --git a/src/ruby/pb/test/server.rb b/src/ruby/pb/test/server.rb index e2e1ecbd62..a311bb76e6 100755 --- a/src/ruby/pb/test/server.rb +++ b/src/ruby/pb/test/server.rb @@ -64,7 +64,8 @@ end # creates a ServerCredentials from the test certificates. def test_server_creds certs = load_test_certs - GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) + GRPC::Core::ServerCredentials.new( + nil, [{private_key: certs[1], cert_chain: certs[2]}], false) end # produces a string of null chars (\0) of length l. diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb index 2e673ff413..ad0fb26896 100644 --- a/src/ruby/spec/client_server_spec.rb +++ b/src/ruby/spec/client_server_spec.rb @@ -28,16 +28,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'grpc' -require 'spec_helper' include GRPC::Core -def load_test_certs - test_root = File.join(File.dirname(__FILE__), 'testdata') - files = ['ca.pem', 'server1.key', 'server1.pem'] - files.map { |f| File.open(File.join(test_root, f)).read } -end - shared_context 'setup: tags' do let(:sent_message) { 'sent message' } let(:reply_text) { 'the reply' } @@ -47,7 +40,7 @@ shared_context 'setup: tags' do end def deadline - Time.now + 2 + Time.now + 5 end def server_allows_client_to_proceed @@ -402,7 +395,7 @@ describe 'the http client/server' do @client_queue = GRPC::Core::CompletionQueue.new @server_queue = GRPC::Core::CompletionQueue.new @server = GRPC::Core::Server.new(@server_queue, nil) - server_port = @server.add_http2_port(server_host) + server_port = @server.add_http2_port(server_host, :this_port_is_insecure) @server.start @ch = Channel.new("0.0.0.0:#{server_port}", nil) end @@ -420,12 +413,19 @@ describe 'the http client/server' do end describe 'the secure http client/server' do + def load_test_certs + test_root = File.join(File.dirname(__FILE__), 'testdata') + files = ['ca.pem', 'server1.key', 'server1.pem'] + files.map { |f| File.open(File.join(test_root, f)).read } + end + before(:example) do certs = load_test_certs server_host = '0.0.0.0:0' @client_queue = GRPC::Core::CompletionQueue.new @server_queue = GRPC::Core::CompletionQueue.new - server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2]) + server_creds = GRPC::Core::ServerCredentials.new( + nil, [{ private_key: certs[1], cert_chain: certs[2] }], false) @server = GRPC::Core::Server.new(@server_queue, nil) server_port = @server.add_http2_port(server_host, server_creds) @server.start diff --git a/src/ruby/spec/credentials_spec.rb b/src/ruby/spec/credentials_spec.rb index 8e72e85d54..b02219dfdb 100644 --- a/src/ruby/spec/credentials_spec.rb +++ b/src/ruby/spec/credentials_spec.rb @@ -29,15 +29,15 @@ require 'grpc' -def load_test_certs - test_root = File.join(File.dirname(__FILE__), 'testdata') - files = ['ca.pem', 'server1.pem', 'server1.key'] - files.map { |f| File.open(File.join(test_root, f)).read } -end +describe GRPC::Core::Credentials do + Credentials = GRPC::Core::Credentials -Credentials = GRPC::Core::Credentials + def load_test_certs + test_root = File.join(File.dirname(__FILE__), 'testdata') + files = ['ca.pem', 'server1.pem', 'server1.key'] + files.map { |f| File.open(File.join(test_root, f)).read } + end -describe Credentials do describe '#new' do it 'can be constructed with fake inputs' do expect { Credentials.new('root_certs', 'key', 'cert') }.not_to raise_error diff --git a/src/ruby/spec/generic/active_call_spec.rb b/src/ruby/spec/generic/active_call_spec.rb index fcd7bd082f..b05e3284fe 100644 --- a/src/ruby/spec/generic/active_call_spec.rb +++ b/src/ruby/spec/generic/active_call_spec.rb @@ -46,7 +46,7 @@ describe GRPC::ActiveCall do @server_queue = GRPC::Core::CompletionQueue.new host = '0.0.0.0:0' @server = GRPC::Core::Server.new(@server_queue, nil) - server_port = @server.add_http2_port(host) + server_port = @server.add_http2_port(host, :this_port_is_insecure) @server.start @ch = GRPC::Core::Channel.new("0.0.0.0:#{server_port}", nil) end diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb index edcc962a7d..a05433df75 100644 --- a/src/ruby/spec/generic/client_stub_spec.rb +++ b/src/ruby/spec/generic/client_stub_spec.rb @@ -498,7 +498,7 @@ describe 'ClientStub' do def create_test_server @server_queue = GRPC::Core::CompletionQueue.new @server = GRPC::Core::Server.new(@server_queue, nil) - @server.add_http2_port('0.0.0.0:0') + @server.add_http2_port('0.0.0.0:0', :this_port_is_insecure) end def expect_server_to_be_invoked(notifier) diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb index 1295fd7fdd..e484a9ea50 100644 --- a/src/ruby/spec/generic/rpc_server_spec.rb +++ b/src/ruby/spec/generic/rpc_server_spec.rb @@ -139,7 +139,7 @@ describe GRPC::RpcServer do @server_queue = GRPC::Core::CompletionQueue.new server_host = '0.0.0.0:0' @server = GRPC::Core::Server.new(@server_queue, nil) - server_port = @server.add_http2_port(server_host) + server_port = @server.add_http2_port(server_host, :this_port_is_insecure) @host = "localhost:#{server_port}" @ch = GRPC::Core::Channel.new(@host, nil) end diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb index 6999a69105..9bc82638c7 100644 --- a/src/ruby/spec/pb/health/checker_spec.rb +++ b/src/ruby/spec/pb/health/checker_spec.rb @@ -179,14 +179,13 @@ describe Grpc::Health::Checker do describe 'running on RpcServer' do RpcServer = GRPC::RpcServer - StatusCodes = GRPC::Core::StatusCodes CheckerStub = Grpc::Health::Checker.rpc_stub_class before(:each) do @server_queue = GRPC::Core::CompletionQueue.new server_host = '0.0.0.0:0' @server = GRPC::Core::Server.new(@server_queue, nil) - server_port = @server.add_http2_port(server_host) + server_port = @server.add_http2_port(server_host, :this_port_is_insecure) @host = "localhost:#{server_port}" @ch = GRPC::Core::Channel.new(@host, nil) @client_opts = { channel_override: @ch } diff --git a/src/ruby/spec/server_credentials_spec.rb b/src/ruby/spec/server_credentials_spec.rb index 55598bc8df..8ae577009d 100644 --- a/src/ruby/spec/server_credentials_spec.rb +++ b/src/ruby/spec/server_credentials_spec.rb @@ -31,8 +31,9 @@ require 'grpc' def load_test_certs test_root = File.join(File.dirname(__FILE__), 'testdata') - files = ['ca.pem', 'server1.pem', 'server1.key'] - files.map { |f| File.open(File.join(test_root, f)).read } + files = ['ca.pem', 'server1.key', 'server1.pem'] + contents = files.map { |f| File.open(File.join(test_root, f)).read } + [contents[0], [{ private_key: contents[1], cert_chain: contents[2] }], false] end describe GRPC::Core::ServerCredentials do @@ -40,7 +41,8 @@ describe GRPC::Core::ServerCredentials do describe '#new' do it 'can be constructed from a fake CA PEM, server PEM and a server key' do - expect { Creds.new('a', 'b', 'c') }.not_to raise_error + creds = Creds.new('a', [{ private_key: 'a', cert_chain: 'b' }], false) + expect(creds).to_not be_nil end it 'can be constructed using the test certificates' do @@ -48,21 +50,44 @@ describe GRPC::Core::ServerCredentials do expect { Creds.new(*certs) }.not_to raise_error end + it 'cannot be constructed without a nil key_cert pair array' do + root_cert, _, _ = load_test_certs + blk = proc do + Creds.new(root_cert, nil, false) + end + expect(&blk).to raise_error + end + + it 'cannot be constructed without any key_cert pairs' do + root_cert, _, _ = load_test_certs + blk = proc do + Creds.new(root_cert, [], false) + end + expect(&blk).to raise_error + end + it 'cannot be constructed without a server cert chain' do root_cert, server_key, _ = load_test_certs - blk = proc { Creds.new(root_cert, server_key, nil) } + blk = proc do + Creds.new(root_cert, + [{ server_key: server_key, cert_chain: nil }], + false) + end expect(&blk).to raise_error end it 'cannot be constructed without a server key' do root_cert, _, _ = load_test_certs - blk = proc { Creds.new(root_cert, nil, cert_chain) } + blk = proc do + Creds.new(root_cert, + [{ server_key: nil, cert_chain: cert_chain }]) + end expect(&blk).to raise_error end it 'can be constructed without a root_cret' do - _, server_key, cert_chain = load_test_certs - blk = proc { Creds.new(nil, server_key, cert_chain) } + _, cert_pairs, _ = load_test_certs + blk = proc { Creds.new(nil, cert_pairs, false) } expect(&blk).to_not raise_error end end diff --git a/src/ruby/spec/server_spec.rb b/src/ruby/spec/server_spec.rb index 47fe575343..439b19fb8d 100644 --- a/src/ruby/spec/server_spec.rb +++ b/src/ruby/spec/server_spec.rb @@ -32,7 +32,8 @@ require 'grpc' def load_test_certs test_root = File.join(File.dirname(__FILE__), 'testdata') files = ['ca.pem', 'server1.key', 'server1.pem'] - files.map { |f| File.open(File.join(test_root, f)).read } + contents = files.map { |f| File.open(File.join(test_root, f)).read } + [contents[0], [{ private_key: contents[1], cert_chain: contents[2] }], false] end Server = GRPC::Core::Server @@ -104,7 +105,7 @@ describe Server do it 'runs without failing' do blk = proc do s = Server.new(@cq, nil) - s.add_http2_port('localhost:0') + s.add_http2_port('localhost:0', :this_port_is_insecure) s.close(@cq) end expect(&blk).to_not raise_error @@ -113,7 +114,10 @@ describe Server do it 'fails if the server is closed' do s = Server.new(@cq, nil) s.close(@cq) - expect { s.add_http2_port('localhost:0') }.to raise_error(RuntimeError) + blk = proc do + s.add_http2_port('localhost:0', :this_port_is_insecure) + end + expect(&blk).to raise_error(RuntimeError) end end @@ -198,7 +202,7 @@ describe Server do def start_a_server s = Server.new(@cq, nil) - s.add_http2_port('0.0.0.0:0') + s.add_http2_port('0.0.0.0:0', :this_port_is_insecure) s.start s end |