From e77da44eef9004ca995e82a7c3d33158ed0b13e5 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 29 Jul 2015 10:09:36 -0700 Subject: Ensure that client generated methods don't conflict with other properties --- src/node/src/client.js | 27 +++++++++++++++------------ src/node/test/surface_test.js | 20 +++++++++++++++++++- 2 files changed, 34 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/node/src/client.js b/src/node/src/client.js index f843669bd0..405e2be693 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -236,7 +236,7 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { deadline = Infinity; } var emitter = new EventEmitter(); - var call = new grpc.Call(this.channel, method, deadline); + var call = new grpc.Call(this.$channel, method, deadline); if (metadata === null || metadata === undefined) { metadata = {}; } @@ -246,7 +246,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); @@ -309,12 +309,12 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { if (deadline === undefined) { deadline = Infinity; } - var call = new grpc.Call(this.channel, method, deadline); + var call = new grpc.Call(this.$channel, method, deadline); if (metadata === null || metadata === undefined) { metadata = {}; } 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); @@ -383,12 +383,12 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { if (deadline === undefined) { deadline = Infinity; } - var call = new grpc.Call(this.channel, method, deadline); + var call = new grpc.Call(this.$channel, method, deadline); if (metadata === null || metadata === undefined) { metadata = {}; } 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); @@ -455,12 +455,12 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { if (deadline === undefined) { deadline = Infinity; } - var call = new grpc.Call(this.channel, method, deadline); + var call = new grpc.Call(this.$channel, method, deadline); if (metadata === null || metadata === undefined) { metadata = {}; } 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); @@ -545,14 +545,17 @@ exports.makeClientConstructor = function(methods, serviceName) { options = {}; } options['grpc.primary_user_agent'] = 'grpc-node/' + version; - this.channel = new grpc.Channel(address, options); - this.server_address = address.replace(/\/$/, ''); - this.auth_uri = this.server_address + '/' + serviceName; - this.updateMetadata = updateMetadata; + this.$channel = new grpc.Channel(address, options); + this.$server_address = address.replace(/\/$/, ''); + this.$auth_uri = this.$server_address + '/' + serviceName; + this.$updateMetadata = updateMetadata; } _.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'; diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index 98f9b15bfc..1afdb33089 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -110,6 +110,24 @@ describe('Server.prototype.addProtoService', 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('Echo service', function() { var server; var client; @@ -344,7 +362,7 @@ describe('Other conditions', function() { server.shutdown(); }); it('channel.getTarget should be available', function() { - assert.strictEqual(typeof client.channel.getTarget(), 'string'); + assert.strictEqual(typeof client.$channel.getTarget(), 'string'); }); describe('Server recieving bad input', function() { var misbehavingClient; -- cgit v1.2.3 From f685ae25b2e6817ccbddc54c8b4612f0d057a042 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 29 Jul 2015 15:25:57 -0700 Subject: Missed one --- src/node/interop/interop_client.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js index e810e68e45..953cbb1679 100644 --- a/src/node/interop/interop_client.js +++ b/src/node/interop/interop_client.js @@ -292,7 +292,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, @@ -355,7 +355,7 @@ function oauth2Test(expected_user, scope, per_rpc, client, done) { if (per_rpc) { updateMetadata('', {}, makeTestCall); } else { - client.updateMetadata = updateMetadata; + client.$updateMetadata = updateMetadata; makeTestCall(null, {}); } -- cgit v1.2.3 From 741e64c8721798a1daba28ae782c9c0e08064505 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 08:08:56 -0700 Subject: update compiler --- src/compiler/csharp_generator.cc | 45 ++++++---------------------------------- src/compiler/csharp_generator.h | 4 ++++ 2 files changed, 10 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 9432bdda96..5443cd4701 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -35,10 +35,15 @@ #include #include +#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 +60,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(); } @@ -539,7 +507,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..0610f5e9fb 100644 --- a/src/compiler/csharp_generator.h +++ b/src/compiler/csharp_generator.h @@ -36,6 +36,10 @@ #include "src/compiler/config.h" +using namespace std; + +#include + namespace grpc_csharp_generator { grpc::string GetServices(const grpc::protobuf::FileDescriptor *file); -- cgit v1.2.3 From 2c4f4ecb63ae2d3b5d62a10ce7eeb73eb3d75662 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 08:10:48 -0700 Subject: update generate script --- src/csharp/generate_proto_csharp.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh index 7c3ba70922..56c9418e39 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 \ +$PROTOC --plugin=$PLUGIN --csharp_out=$INTEROP_DIR --grpc_out=$INTEROP_DIR \ -I $INTEROP_DIR/proto $INTEROP_DIR/proto/test.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 -- cgit v1.2.3 From 85f24b5862d93ebfd312d648cafb072462b12135 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 08:11:40 -0700 Subject: update proto files --- src/csharp/Grpc.Examples/proto/math.proto | 16 +++++----- src/csharp/Grpc.HealthCheck/proto/health.proto | 8 ++--- .../Grpc.IntegrationTesting/proto/empty.proto | 2 +- .../Grpc.IntegrationTesting/proto/messages.proto | 36 +++++++++++----------- .../Grpc.IntegrationTesting/proto/test.proto | 2 +- 5 files changed, 32 insertions(+), 32 deletions(-) (limited to 'src') 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/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/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"; -- cgit v1.2.3 From 5c42d8daea5d35fb09323f78fc96c9ad4611902f Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 08:14:30 -0700 Subject: regenerate protos --- src/csharp/Grpc.Examples/Math.cs | 1661 +++++--------------- src/csharp/Grpc.Examples/MathGrpc.cs | 44 +- src/csharp/Grpc.Examples/MathServiceImpl.cs | 2 +- src/csharp/Grpc.HealthCheck/Health.cs | 720 ++------- .../Grpc.IntegrationTesting.csproj | 46 +- src/csharp/Grpc.IntegrationTesting/Test.cs | 48 + src/csharp/Grpc.IntegrationTesting/TestGrpc.cs | 67 +- 7 files changed, 686 insertions(+), 1902 deletions(-) create mode 100644 src/csharp/Grpc.IntegrationTesting/Test.cs (limited to 'src') diff --git a/src/csharp/Grpc.Examples/Math.cs b/src/csharp/Grpc.Examples/Math.cs index 75b1e9dbc2..953895e970 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 internal__static_math_DivArgs__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_math_DivReply__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_math_DivReply__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_math_FibArgs__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_math_FibArgs__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_math_Num__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_math_Num__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_math_FibReply__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable 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(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(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(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(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(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,587 @@ namespace math { } #region Messages [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class DivArgs : pb::GeneratedMessage { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DivArgs()); + public static pb::MessageParser 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 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 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); + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(DivArgs cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; + public void WriteTo(pb::CodedOutputStream output) { + if (Dividend != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Dividend); } - - 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; } - } - - 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); - } + if (Divisor != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Divisor); } + } - public override pbd::MessageDescriptor DescriptorForType { - get { return global::math.DivArgs.Descriptor; } + public int CalculateSize() { + int size = 0; + if (Dividend != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Dividend); } - - public override DivArgs DefaultInstanceForType { - get { return global::math.DivArgs.DefaultInstance; } + if (Divisor != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Divisor); } + return size; + } - public override DivArgs BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public void MergeFrom(DivArgs other) { + if (other == null) { + return; } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is DivArgs) { - return MergeFrom((DivArgs) other); - } else { - base.MergeFrom(other); - return this; - } + if (other.Dividend != 0L) { + Dividend = other.Dividend; } - - 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; - } - - 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new DivReply()); + public static pb::MessageParser 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 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 { - protected override Builder ThisBuilder { - get { return this; } - } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(DivReply cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; + public void WriteTo(pb::CodedOutputStream output) { + if (Quotient != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Quotient); } - - 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); - } + if (Remainder != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Remainder); } + } - public override pbd::MessageDescriptor DescriptorForType { - get { return global::math.DivReply.Descriptor; } + public int CalculateSize() { + int size = 0; + if (Quotient != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Quotient); } - - public override DivReply DefaultInstanceForType { - get { return global::math.DivReply.DefaultInstance; } - } - - 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FibArgs()); + public static pb::MessageParser 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 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 { - 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 void WriteTo(pb::CodedOutputStream output) { + if (Limit != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Limit); } + } - public override FibArgs DefaultInstanceForType { - get { return global::math.FibArgs.DefaultInstance; } - } - - public override FibArgs BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + public int CalculateSize() { + int size = 0; + if (Limit != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Limit); } + return size; + } - public override Builder MergeFrom(pb::IMessage other) { - if (other is FibArgs) { - return MergeFrom((FibArgs) other); - } else { - base.MergeFrom(other); - return this; - } + public void MergeFrom(FibArgs other) { + if (other == null) { + return; } - - 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 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Num()); + public static pb::MessageParser 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 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 { - 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new FibReply()); + public static pb::MessageParser 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 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 { - 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; + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + break; + case 8: { + Count = 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.hasCount = input.ReadInt64(ref result.count_); - 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/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 4941ff35f7..eb6b68849f 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -7,38 +7,38 @@ 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 __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::math.DivArgs.ParseFrom); - static readonly Marshaller __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), global::math.DivReply.ParseFrom); - static readonly Marshaller __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::math.FibArgs.ParseFrom); - static readonly Marshaller __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), global::math.Num.ParseFrom); + static readonly Marshaller __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivArgs.ParseFrom); + static readonly Marshaller __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivReply.ParseFrom); + static readonly Marshaller __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.FibArgs.ParseFrom); + static readonly Marshaller __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.Num.ParseFrom); - static readonly Method __Method_Div = new Method( + static readonly Method __Method_Div = new Method( MethodType.Unary, __ServiceName, "Div", __Marshaller_DivArgs, __Marshaller_DivReply); - static readonly Method __Method_DivMany = new Method( + static readonly Method __Method_DivMany = new Method( MethodType.DuplexStreaming, __ServiceName, "DivMany", __Marshaller_DivArgs, __Marshaller_DivReply); - static readonly Method __Method_Fib = new Method( + static readonly Method __Method_Fib = new Method( MethodType.ServerStreaming, __ServiceName, "Fib", __Marshaller_FibArgs, __Marshaller_Num); - static readonly Method __Method_Sum = new Method( + static readonly Method __Method_Sum = new Method( MethodType.ClientStreaming, __ServiceName, "Sum", @@ -48,6 +48,7 @@ namespace math { // client interface public interface IMathClient { +<<<<<<< HEAD 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 DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -58,15 +59,22 @@ namespace math { AsyncServerStreamingCall Fib(global::math.FibArgs request, CallOptions options); AsyncClientStreamingCall Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncClientStreamingCall Sum(CallOptions options); +======= + global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncDuplexStreamingCall DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncServerStreamingCall Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncClientStreamingCall Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); +>>>>>>> 708e8de... regenerate protos } // server-side interface public interface IMath { - Task Div(global::math.DivArgs request, ServerCallContext context); - Task DivMany(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); - Task Fib(global::math.FibArgs request, IServerStreamWriter responseStream, ServerCallContext context); - Task Sum(IAsyncStreamReader requestStream, ServerCallContext context); + Task Div(global::Math.DivArgs request, ServerCallContext context); + Task DivMany(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + Task Fib(global::Math.FibArgs request, IServerStreamWriter responseStream, ServerCallContext context); + Task Sum(IAsyncStreamReader requestStream, ServerCallContext context); } // client stub @@ -75,7 +83,7 @@ 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); @@ -85,7 +93,7 @@ namespace math { var call = CreateCall(__Method_Div, options); return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncUnaryCall 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); @@ -95,7 +103,7 @@ namespace math { var call = CreateCall(__Method_Div, options); return Calls.AsyncUnaryCall(call, request); } - public AsyncDuplexStreamingCall DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncDuplexStreamingCall 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); @@ -105,7 +113,7 @@ namespace math { var call = CreateCall(__Method_DivMany, options); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncServerStreamingCall Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncServerStreamingCall 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); @@ -115,7 +123,7 @@ namespace math { var call = CreateCall(__Method_Fib, options); return Calls.AsyncServerStreamingCall(call, request); } - public AsyncClientStreamingCall Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncClientStreamingCall 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); diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs index dd26b1d350..29181bc858 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 { /// /// Implementation of MathService server diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs index 361382d4bd..de65c1a9de 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 internal__static_grpc_health_v1alpha_HealthCheckRequest__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_health_v1alpha_HealthCheckResponse__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable 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(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(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,253 @@ namespace Grpc.Health.V1Alpha { } #region Messages [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class HealthCheckRequest : pb::GeneratedMessage { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HealthCheckRequest()); + public static pb::MessageParser 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 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; + set { + service_ = pb::Preconditions.CheckNotNull(value, "value"); } } - 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); - } - 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 { - 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new HealthCheckResponse()); + public static pb::MessageParser 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 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 { - 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; - } - } - 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; + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + break; + case 8: { + status_ = (global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus) input.ReadEnum(); + 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.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 06a75a3351..b307a0445c 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -41,22 +41,6 @@ ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll - - False - ..\packages\Google.Apis.Auth.1.9.2\lib\net40\Google.Apis.Auth.dll - - - False - ..\packages\Google.Apis.Auth.1.9.2\lib\net40\Google.Apis.Auth.PlatformServices.dll - - - False - ..\packages\Google.Apis.Core.1.9.2\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll - - - False - ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll - ..\packages\NUnit.2.6.4\lib\nunit.framework.dll @@ -69,14 +53,6 @@ - - False - ..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll - - - False - ..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll - ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll @@ -87,6 +63,27 @@ ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.Extensions.Desktop.dll + + ..\packages\System.Collections.Immutable.1.1.36\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + + ..\packages\Google.Apis.Auth.1.9.2\lib\net40\Google.Apis.Auth.dll + + + ..\packages\Google.Apis.Auth.1.9.2\lib\net40\Google.Apis.Auth.PlatformServices.dll + + + ..\packages\Google.Apis.Core.1.9.2\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll + + + ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Extensions.dll + + + ..\packages\Microsoft.Net.Http.2.2.29\lib\net45\System.Net.Http.Primitives.dll + @@ -102,6 +99,7 @@ + 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/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index 697acb53d8..522372582b 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -7,55 +7,55 @@ 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 __Marshaller_Empty = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.Empty.ParseFrom); - static readonly Marshaller __Marshaller_SimpleRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.SimpleRequest.ParseFrom); - static readonly Marshaller __Marshaller_SimpleResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.SimpleResponse.ParseFrom); - static readonly Marshaller __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.StreamingOutputCallRequest.ParseFrom); - static readonly Marshaller __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.StreamingOutputCallResponse.ParseFrom); - static readonly Marshaller __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.StreamingInputCallRequest.ParseFrom); - static readonly Marshaller __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::grpc.testing.StreamingInputCallResponse.ParseFrom); + static readonly Marshaller __Marshaller_Empty = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.Empty.ParseFrom); + static readonly Marshaller __Marshaller_SimpleRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.SimpleRequest.ParseFrom); + static readonly Marshaller __Marshaller_SimpleResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.SimpleResponse.ParseFrom); + static readonly Marshaller __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingOutputCallRequest.ParseFrom); + static readonly Marshaller __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingOutputCallResponse.ParseFrom); + static readonly Marshaller __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingInputCallRequest.ParseFrom); + static readonly Marshaller __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingInputCallResponse.ParseFrom); - static readonly Method __Method_EmptyCall = new Method( + static readonly Method __Method_EmptyCall = new Method( MethodType.Unary, __ServiceName, "EmptyCall", __Marshaller_Empty, __Marshaller_Empty); - static readonly Method __Method_UnaryCall = new Method( + static readonly Method __Method_UnaryCall = new Method( MethodType.Unary, __ServiceName, "UnaryCall", __Marshaller_SimpleRequest, __Marshaller_SimpleResponse); - static readonly Method __Method_StreamingOutputCall = new Method( + static readonly Method __Method_StreamingOutputCall = new Method( MethodType.ServerStreaming, __ServiceName, "StreamingOutputCall", __Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallResponse); - static readonly Method __Method_StreamingInputCall = new Method( + static readonly Method __Method_StreamingInputCall = new Method( MethodType.ClientStreaming, __ServiceName, "StreamingInputCall", __Marshaller_StreamingInputCallRequest, __Marshaller_StreamingInputCallResponse); - static readonly Method __Method_FullDuplexCall = new Method( + static readonly Method __Method_FullDuplexCall = new Method( MethodType.DuplexStreaming, __ServiceName, "FullDuplexCall", __Marshaller_StreamingOutputCallRequest, __Marshaller_StreamingOutputCallResponse); - static readonly Method __Method_HalfDuplexCall = new Method( + static readonly Method __Method_HalfDuplexCall = new Method( MethodType.DuplexStreaming, __ServiceName, "HalfDuplexCall", @@ -65,6 +65,7 @@ namespace grpc.testing { // client interface public interface ITestServiceClient { +<<<<<<< HEAD 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 EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); @@ -81,17 +82,27 @@ namespace grpc.testing { AsyncDuplexStreamingCall FullDuplexCall(CallOptions options); AsyncDuplexStreamingCall HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); AsyncDuplexStreamingCall HalfDuplexCall(CallOptions options); +======= + global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncServerStreamingCall StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncClientStreamingCall StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncDuplexStreamingCall FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncDuplexStreamingCall HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); +>>>>>>> 708e8de... regenerate protos } // server-side interface public interface ITestService { - Task EmptyCall(global::grpc.testing.Empty request, ServerCallContext context); - Task UnaryCall(global::grpc.testing.SimpleRequest request, ServerCallContext context); - Task StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context); - Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context); - Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); - Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + Task EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context); + Task UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context); + Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter responseStream, ServerCallContext context); + Task StreamingInputCall(IAsyncStreamReader requestStream, ServerCallContext context); + Task FullDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); + Task HalfDuplexCall(IAsyncStreamReader requestStream, IServerStreamWriter responseStream, ServerCallContext context); } // client stub @@ -100,7 +111,7 @@ 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); @@ -110,7 +121,7 @@ namespace grpc.testing { var call = CreateCall(__Method_EmptyCall, options); return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncUnaryCall 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); @@ -120,7 +131,7 @@ namespace grpc.testing { 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); @@ -130,7 +141,7 @@ namespace grpc.testing { var call = CreateCall(__Method_UnaryCall, options); return Calls.BlockingUnaryCall(call, request); } - public AsyncUnaryCall UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncUnaryCall 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); @@ -140,7 +151,7 @@ namespace grpc.testing { var call = CreateCall(__Method_UnaryCall, options); return Calls.AsyncUnaryCall(call, request); } - public AsyncServerStreamingCall StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncServerStreamingCall 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); @@ -150,7 +161,7 @@ namespace grpc.testing { var call = CreateCall(__Method_StreamingOutputCall, options); return Calls.AsyncServerStreamingCall(call, request); } - public AsyncClientStreamingCall StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncClientStreamingCall 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); @@ -160,7 +171,7 @@ namespace grpc.testing { var call = CreateCall(__Method_StreamingInputCall, options); return Calls.AsyncClientStreamingCall(call); } - public AsyncDuplexStreamingCall FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncDuplexStreamingCall 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); @@ -170,7 +181,7 @@ namespace grpc.testing { var call = CreateCall(__Method_FullDuplexCall, options); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)) + public AsyncDuplexStreamingCall 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); -- cgit v1.2.3 From 28526319e0dd6e575d349f05dcf06abdb69899f3 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 09:21:38 -0700 Subject: upgraded NuGet package --- src/csharp/Grpc.Examples.MathClient/MathClient.cs | 2 +- .../Grpc.Examples.Tests/Grpc.Examples.Tests.csproj | 6 ++--- .../Grpc.Examples.Tests/MathClientServerTests.cs | 2 +- src/csharp/Grpc.Examples.Tests/packages.config | 2 +- src/csharp/Grpc.Examples/Grpc.Examples.csproj | 6 ++--- src/csharp/Grpc.Examples/MathExamples.cs | 28 +++++++++++----------- src/csharp/Grpc.Examples/MathGrpc.cs | 9 +++---- src/csharp/Grpc.Examples/MathServiceImpl.cs | 8 +++---- src/csharp/Grpc.Examples/packages.config | 2 +- .../Grpc.HealthCheck.Tests.csproj | 7 ++---- src/csharp/Grpc.HealthCheck.Tests/packages.config | 2 +- .../Grpc.HealthCheck/Grpc.HealthCheck.csproj | 7 ++---- src/csharp/Grpc.HealthCheck/packages.config | 2 +- .../Grpc.IntegrationTesting.csproj | 6 ++--- src/csharp/Grpc.IntegrationTesting/packages.config | 2 +- 15 files changed, 43 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Examples.MathClient/MathClient.cs b/src/csharp/Grpc.Examples.MathClient/MathClient.cs index f9839d99f1..0df14984cb 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.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj index 9a8f780b24..7eea632f36 100644 --- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj +++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj @@ -37,13 +37,13 @@ C:\keys\Grpc.snk + + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + ..\packages\NUnit.2.6.4\lib\nunit.framework.dll - - ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - False ..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs index 08aece7ef2..205a1ae3a2 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 { /// /// Math client talks to local math server. 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 @@  - + \ 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..1ba1ed6081 100644 --- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj +++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj @@ -37,11 +37,11 @@ C:\keys\Grpc.snk + + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + - - ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - ..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs index 06d81a4d83..e25384766f 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 result = await call.ResponseStream.ToList(); Console.WriteLine("Fib Result: " + string.Join("|", result)); @@ -63,9 +63,9 @@ namespace math { var numbers = new List { - 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 { - 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 { - 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 eb6b68849f..f008a0d7f2 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -5,6 +5,7 @@ using System; using System.Threading; using System.Threading.Tasks; +using Google.Protobuf; using Grpc.Core; namespace Math { @@ -12,10 +13,10 @@ namespace Math { { static readonly string __ServiceName = "math.Math"; - static readonly Marshaller __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivArgs.ParseFrom); - static readonly Marshaller __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivReply.ParseFrom); - static readonly Marshaller __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.FibArgs.ParseFrom); - static readonly Marshaller __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.Num.ParseFrom); + static readonly Marshaller __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivArgs.Parser.ParseFrom); + static readonly Marshaller __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivReply.Parser.ParseFrom); + static readonly Marshaller __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.FibArgs.Parser.ParseFrom); + static readonly Marshaller __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.Num.Parser.ParseFrom); static readonly Method __Method_Div = new Method( MethodType.Unary, diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs index 29181bc858..788ce90343 100644 --- a/src/csharp/Grpc.Examples/MathServiceImpl.cs +++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs @@ -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 requestStream, IServerStreamWriter responseStream, ServerCallContext context) @@ -94,13 +94,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 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++) @@ -108,7 +108,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 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj index c922ddfb9e..ca24874d66 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj +++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj @@ -37,11 +37,8 @@ C:\keys\Grpc.snk - - ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll - - - ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll + + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll 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 @@  - + \ 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..c9eb862f48 100644 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -38,11 +38,8 @@ C:\keys\Grpc.snk - - ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll - - - ..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.Serialization.dll + + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll 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 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index b307a0445c..38a3961837 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -41,13 +41,13 @@ ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll + + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + ..\packages\NUnit.2.6.4\lib\nunit.framework.dll - - ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - ..\packages\Ix-Async.1.2.3\lib\net45\System.Interactive.Async.dll diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config index 7d1f84f303..7b7bc42ff4 100644 --- a/src/csharp/Grpc.IntegrationTesting/packages.config +++ b/src/csharp/Grpc.IntegrationTesting/packages.config @@ -3,7 +3,7 @@ - + -- cgit v1.2.3 From 7db46138d5fd835a38c1aabf79c961ef63ed13d6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 09:25:38 -0700 Subject: progress --- src/csharp/Grpc.Examples/MathGrpc.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index f008a0d7f2..1395a80010 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -5,7 +5,6 @@ using System; using System.Threading; using System.Threading.Tasks; -using Google.Protobuf; using Grpc.Core; namespace Math { @@ -13,7 +12,7 @@ namespace Math { { static readonly string __ServiceName = "math.Math"; - static readonly Marshaller __Marshaller_DivArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivArgs.Parser.ParseFrom); + static readonly Marshaller __Marshaller_DivArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.DivArgs.Parser.ParseFrom); static readonly Marshaller __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivReply.Parser.ParseFrom); static readonly Marshaller __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.FibArgs.Parser.ParseFrom); static readonly Marshaller __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.Num.Parser.ParseFrom); -- cgit v1.2.3 From ad75dd136111696dad44e370cc563de57bdd4785 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 09:43:07 -0700 Subject: fix generator --- src/compiler/csharp_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 5443cd4701..8a600904e7 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -197,7 +197,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)); } -- cgit v1.2.3 From 3030a92f3dc232e3db8a6098a4fddeac1a71df33 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 09:45:13 -0700 Subject: upgrade generate script --- src/csharp/generate_proto_csharp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh index 56c9418e39..a17f45b587 100755 --- a/src/csharp/generate_proto_csharp.sh +++ b/src/csharp/generate_proto_csharp.sh @@ -42,7 +42,7 @@ $PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \ -I $EXAMPLES_DIR/proto $EXAMPLES_DIR/proto/math.proto $PROTOC --plugin=$PLUGIN --csharp_out=$INTEROP_DIR --grpc_out=$INTEROP_DIR \ - -I $INTEROP_DIR/proto $INTEROP_DIR/proto/test.proto + -I $INTEROP_DIR/proto $INTEROP_DIR/proto/*.proto $PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \ -I $HEALTHCHECK_DIR/proto $HEALTHCHECK_DIR/proto/health.proto -- cgit v1.2.3 From 475f75a0deaa5a201feb9a5fb3a9b35d8cac9dd4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 09:46:04 -0700 Subject: regenerate --- src/csharp/Grpc.Examples/MathGrpc.cs | 6 +- src/csharp/Grpc.HealthCheck/HealthGrpc.cs | 4 +- src/csharp/Grpc.IntegrationTesting/Empty.cs | 286 +-- src/csharp/Grpc.IntegrationTesting/Messages.cs | 3233 ++++++------------------ src/csharp/Grpc.IntegrationTesting/TestGrpc.cs | 14 +- 5 files changed, 848 insertions(+), 2695 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 1395a80010..c0cab6e469 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -13,9 +13,9 @@ namespace Math { static readonly string __ServiceName = "math.Math"; static readonly Marshaller __Marshaller_DivArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.DivArgs.Parser.ParseFrom); - static readonly Marshaller __Marshaller_DivReply = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.DivReply.Parser.ParseFrom); - static readonly Marshaller __Marshaller_FibArgs = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.FibArgs.Parser.ParseFrom); - static readonly Marshaller __Marshaller_Num = Marshallers.Create((arg) => arg.ToByteArray(), global::Math.Num.Parser.ParseFrom); + static readonly Marshaller __Marshaller_DivReply = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.DivReply.Parser.ParseFrom); + static readonly Marshaller __Marshaller_FibArgs = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.FibArgs.Parser.ParseFrom); + static readonly Marshaller __Marshaller_Num = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Math.Num.Parser.ParseFrom); static readonly Method __Method_Div = new Method( MethodType.Unary, diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 0dabc91f7c..9d452b0732 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 __Marshaller_HealthCheckRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Health.V1Alpha.HealthCheckRequest.ParseFrom); - static readonly Marshaller __Marshaller_HealthCheckResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Health.V1Alpha.HealthCheckResponse.ParseFrom); + static readonly Marshaller __Marshaller_HealthCheckRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1Alpha.HealthCheckRequest.Parser.ParseFrom); + static readonly Marshaller __Marshaller_HealthCheckResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Health.V1Alpha.HealthCheckResponse.Parser.ParseFrom); static readonly Method __Method_Check = new Method( MethodType.Unary, diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs index 7169ee2a4a..fc8ea3889c 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 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(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,83 @@ namespace grpc.testing { } #region Messages [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Empty : pb::GeneratedMessage { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Empty()); + public static pb::MessageParser 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 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 { - 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; + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } - } - 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(); + break; } - return this; } - - } - static Empty() { - object.ReferenceEquals(global::grpc.testing.Proto.Empty.Descriptor, null); } + } #endregion diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs index 386f377f08..e5a9f382b6 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 internal__static_grpc_testing_Payload__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_SimpleRequest__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_grpc_testing_SimpleRequest__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_SimpleResponse__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_grpc_testing_SimpleResponse__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingInputCallRequest__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_grpc_testing_StreamingInputCallRequest__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingInputCallResponse__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_grpc_testing_StreamingInputCallResponse__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_ResponseParameters__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_grpc_testing_ResponseParameters__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingOutputCallRequest__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable internal__static_grpc_testing_StreamingOutputCallRequest__FieldAccessorTable; - internal static pbd::MessageDescriptor internal__static_grpc_testing_StreamingOutputCallResponse__Descriptor; - internal static pb::FieldAccess.FieldAccessorTable 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(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(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(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(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(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(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(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(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,1133 @@ namespace grpc.testing { #region Messages [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Payload : pb::GeneratedMessage { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Payload()); + public static pb::MessageParser 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 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 { - 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 override bool IsInitialized { - get { return result.IsInitialized; } + public void WriteTo(pb::CodedOutputStream output) { + if (Type != global::Grpc.Testing.PayloadType.COMPRESSABLE) { + output.WriteRawTag(8); + output.WriteEnum((int) Type); } - - 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SimpleRequest()); + public static pb::MessageParser 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 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_; } - } - - public override bool IsInitialized { - get { - return true; + set { + fillOauthScope_ = value; } } - 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); - } - if (hasFillOauthScope) { - output.WriteBool(5, field_names[0], FillOauthScope); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as SimpleRequest); } - 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 bool Equals(SimpleRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; } + 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; } - 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 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 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 { - 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new SimpleResponse()); + public static pb::MessageParser 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 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 { - 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; } - } - - public override SimpleResponse BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); + if (other.Username.Length != 0) { + Username = other.Username; } - - 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; - } - } - switch (tag) { - case 0: { - throw pb::InvalidProtocolBufferException.InvalidTag(); + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } - 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; + break; + case 10: { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); } + input.ReadMessage(payload_); + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingInputCallRequest()); + public static pb::MessageParser Parser { get { return _parser; } } + + public static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[3]; } } - public override StreamingInputCallRequest DefaultInstanceForType { - get { return DefaultInstance; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - protected override StreamingInputCallRequest ThisMessage { - get { return this; } + public StreamingInputCallRequest() { + OnConstruction(); } - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallRequest__Descriptor; } + partial void OnConstruction(); + + public StreamingInputCallRequest(StreamingInputCallRequest other) : this() { + Payload = other.payload_ != null ? other.Payload.Clone() : null; } - protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallRequest__FieldAccessorTable; } + public StreamingInputCallRequest Clone() { + return new StreamingInputCallRequest(this); } public const int PayloadFieldNumber = 1; - private bool hasPayload; - private global::grpc.testing.Payload payload_; - public bool HasPayload { - get { return hasPayload; } + private global::Grpc.Testing.Payload payload_; + public global::Grpc.Testing.Payload Payload { + get { return payload_; } + set { + payload_ = value; + } } - public global::grpc.testing.Payload Payload { - get { return payload_ ?? global::grpc.testing.Payload.DefaultInstance; } + + public override bool Equals(object other) { + return Equals(other as StreamingInputCallRequest); } - public override bool IsInitialized { - get { + 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 override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _streamingInputCallRequestFieldNames; - if (hasPayload) { - output.WriteMessage(1, field_names[0], Payload); - } - UnknownFields.WriteTo(output); + public override int GetHashCode() { + int hash = 1; + if (payload_ != null) hash ^= Payload.GetHashCode(); + return hash; } - 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); - } - size += UnknownFields.SerializedSize; - memoizedSerializedSize = size; - return size; - } + public override string ToString() { + return pb::JsonFormatter.Default.Format(this); } - 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 void WriteTo(pb::CodedOutputStream output) { + if (payload_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Payload); + } } - 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 int CalculateSize() { + int size = 0; + if (payload_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload); + } + return size; } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder { - protected override Builder ThisBuilder { - get { return this; } + public void MergeFrom(StreamingInputCallRequest other) { + if (other == null) { + return; } - public Builder() { - result = DefaultInstance; - resultIsReadOnly = true; - } - internal Builder(StreamingInputCallRequest cloneFrom) { - result = cloneFrom; - resultIsReadOnly = true; + if (other.payload_ != null) { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); + } + Payload.MergeFrom(other.Payload); } + } - private bool resultIsReadOnly; - private StreamingInputCallRequest result; - - private StreamingInputCallRequest PrepareBuilder() { - if (resultIsReadOnly) { - StreamingInputCallRequest original = result; - result = new StreamingInputCallRequest(); - resultIsReadOnly = false; - MergeFrom(original); + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; + } + break; + case 10: { + if (payload_ == null) { + payload_ = new global::Grpc.Testing.Payload(); + } + input.ReadMessage(payload_); + break; + } } - 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 override StreamingInputCallRequest DefaultInstanceForType { - get { return global::grpc.testing.StreamingInputCallRequest.DefaultInstance; } - } - - public override StreamingInputCallRequest BuildPartial() { - if (resultIsReadOnly) { - return result; - } - resultIsReadOnly = true; - return result.MakeReadOnly(); - } - - public override Builder MergeFrom(pb::IMessage other) { - if (other is StreamingInputCallRequest) { - return MergeFrom((StreamingInputCallRequest) other); - } else { - base.MergeFrom(other); - return this; - } - } - - 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; - } - } - 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; - } - } - } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class StreamingInputCallResponse : pb::IMessage { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingInputCallResponse()); + public static pb::MessageParser Parser { get { return _parser; } } - 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 static pbr::MessageDescriptor Descriptor { + get { return global::Grpc.Testing.Messages.Descriptor.MessageTypes[4]; } } - static StreamingInputCallRequest() { - object.ReferenceEquals(global::grpc.testing.Messages.Descriptor, null); - } - } - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class StreamingInputCallResponse : pb::GeneratedMessage { - 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; } + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } } - public override StreamingInputCallResponse DefaultInstanceForType { - get { return DefaultInstance; } + public StreamingInputCallResponse() { + OnConstruction(); } - protected override StreamingInputCallResponse ThisMessage { - get { return this; } - } + partial void OnConstruction(); - public static pbd::MessageDescriptor Descriptor { - get { return global::grpc.testing.Messages.internal__static_grpc_testing_StreamingInputCallResponse__Descriptor; } + public StreamingInputCallResponse(StreamingInputCallResponse other) : this() { + aggregatedPayloadSize_ = other.aggregatedPayloadSize_; } - protected override pb::FieldAccess.FieldAccessorTable 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 { - 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ResponseParameters()); + public static pb::MessageParser 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 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_; } - } - - public override bool IsInitialized { - get { - return true; + set { + intervalUs_ = value; } } - public override void WriteTo(pb::ICodedOutputStream output) { - int size = SerializedSize; - string[] field_names = _responseParametersFieldNames; - if (hasSize) { - output.WriteInt32(1, field_names[1], Size); - } - if (hasIntervalUs) { - output.WriteInt32(2, field_names[0], IntervalUs); - } - UnknownFields.WriteTo(output); + public override bool Equals(object other) { + return Equals(other as ResponseParameters); } - 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 bool Equals(ResponseParameters other) { + if (ReferenceEquals(other, null)) { + return false; } + if (ReferenceEquals(other, this)) { + return true; + } + if (Size != other.Size) return false; + if (IntervalUs != other.IntervalUs) return false; + return true; } - 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 static ResponseParameters ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { - return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); - } - private ResponseParameters MakeReadOnly() { - return this; + public override int GetHashCode() { + int hash = 1; + if (Size != 0) hash ^= Size.GetHashCode(); + if (IntervalUs != 0) hash ^= IntervalUs.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(ResponseParameters 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 { - 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 void WriteTo(pb::CodedOutputStream output) { + if (Size != 0) { + output.WriteRawTag(8); + output.WriteInt32(Size); } - - public override bool IsInitialized { - get { return result.IsInitialized; } - } - - protected override ResponseParameters MessageBeingBuilt { - get { return PrepareBuilder(); } + if (IntervalUs != 0) { + output.WriteRawTag(16); + output.WriteInt32(IntervalUs); } + } - public override Builder Clear() { - result = DefaultInstance; - resultIsReadOnly = true; - return this; + public int CalculateSize() { + int size = 0; + if (Size != 0) { + size += 1 + pb::CodedOutputStream.ComputeInt32Size(Size); } - - 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.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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingOutputCallRequest()); + public static pb::MessageParser 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 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 responseParameters_ = new pbc::PopsicleList(); - public scg::IList ResponseParametersList { + private static readonly pb::FieldCodec _repeated_responseParameters_codec + = pb::FieldCodec.ForMessage(18, global::Grpc.Testing.ResponseParameters.Parser); + private readonly pbc::RepeatedField responseParameters_ = new pbc::RepeatedField(); + public pbc::RepeatedField 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 { - 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 (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } + 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 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 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 { - 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 { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new StreamingOutputCallResponse()); + public static pb::MessageParser 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 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 { - 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; + public void MergeFrom(pb::CodedInputStream input) { + uint tag; + while (input.ReadTag(out tag)) { + switch(tag) { + case 0: + throw pb::InvalidProtocolBufferException.InvalidTag(); + default: + if (pb::WireFormat.IsEndGroupTag(tag)) { + return; } - } - 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; + 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/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index 522372582b..1b5a30d757 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -12,13 +12,13 @@ namespace Grpc.Testing { { static readonly string __ServiceName = "grpc.testing.TestService"; - static readonly Marshaller __Marshaller_Empty = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.Empty.ParseFrom); - static readonly Marshaller __Marshaller_SimpleRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.SimpleRequest.ParseFrom); - static readonly Marshaller __Marshaller_SimpleResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.SimpleResponse.ParseFrom); - static readonly Marshaller __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingOutputCallRequest.ParseFrom); - static readonly Marshaller __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingOutputCallResponse.ParseFrom); - static readonly Marshaller __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingInputCallRequest.ParseFrom); - static readonly Marshaller __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => arg.ToByteArray(), global::Grpc.Testing.StreamingInputCallResponse.ParseFrom); + static readonly Marshaller __Marshaller_Empty = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Empty.Parser.ParseFrom); + static readonly Marshaller __Marshaller_SimpleRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom); + static readonly Marshaller __Marshaller_SimpleResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom); + static readonly Marshaller __Marshaller_StreamingOutputCallRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingOutputCallRequest.Parser.ParseFrom); + static readonly Marshaller __Marshaller_StreamingOutputCallResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingOutputCallResponse.Parser.ParseFrom); + static readonly Marshaller __Marshaller_StreamingInputCallRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingInputCallRequest.Parser.ParseFrom); + static readonly Marshaller __Marshaller_StreamingInputCallResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.StreamingInputCallResponse.Parser.ParseFrom); static readonly Method __Method_EmptyCall = new Method( MethodType.Unary, -- cgit v1.2.3 From 8644aeaa71c5186e0dbef97fd0f1e044bf4d3b44 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 10:21:18 -0700 Subject: migrated code to proto3 --- src/csharp/Grpc.Examples.MathServer/MathServer.cs | 2 +- .../Grpc.Examples.Tests/MathClientServerTests.cs | 24 ++-- .../HealthClientServerTest.cs | 4 +- .../HealthServiceImplTest.cs | 2 +- src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs | 6 +- .../Grpc.IntegrationTesting/InteropClient.cs | 131 ++++++++++++--------- .../InteropClientServerTest.cs | 2 +- .../Grpc.IntegrationTesting/InteropServer.cs | 3 +- .../Grpc.IntegrationTesting/SslCredentialsTest.cs | 4 +- .../Grpc.IntegrationTesting/TestCredentials.cs | 2 - .../Grpc.IntegrationTesting/TestServiceImpl.cs | 23 ++-- 11 files changed, 105 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Examples.MathServer/MathServer.cs b/src/csharp/Grpc.Examples.MathServer/MathServer.cs index 5f7e717b0c..1b71c60141 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/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs index 205a1ae3a2..a2348defc3 100644 --- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs +++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs @@ -76,7 +76,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); } @@ -84,7 +84,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); } @@ -94,7 +94,7 @@ namespace Math.Tests { try { - DivReply response = client.Div(new DivArgs.Builder { Dividend = 0, Divisor = 0 }.Build()); + DivReply response = client.Div(new DivArgs { Dividend = 0, Divisor = 0 }); Assert.Fail(); } catch (RpcException e) @@ -106,7 +106,7 @@ namespace Math.Tests [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); } @@ -114,7 +114,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.ToList(); CollectionAssert.AreEqual(new List { 1, 1, 2, 3, 5, 8 }, @@ -127,8 +127,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 responses = new List(); @@ -155,7 +154,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))) { try @@ -176,8 +175,7 @@ namespace Math.Tests { using (var call = client.Sum()) { - var numbers = new List { 10, 20, 30 }.ConvertAll( - n => Num.CreateBuilder().SetNum_(n).Build()); + var numbers = new List { 10, 20, 30 }.ConvertAll(n => new Num{ Num_ = n }); await call.RequestStream.WriteAll(numbers); var result = await call.ResponseAsync; @@ -190,9 +188,9 @@ namespace Math.Tests { var divArgsList = new List { - 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.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs index 024377e216..98e24698f3 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs +++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs @@ -82,14 +82,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 7184415655..04660cd396 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/HealthServiceImpl.cs b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs index 3c3b9c35f1..0fad62d5f1 100644 --- a/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs +++ b/src/csharp/Grpc.HealthCheck/HealthServiceImpl.cs @@ -99,8 +99,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)) @@ -108,7 +108,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.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index 7411d91d5a..93d0bbe772 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -37,12 +37,12 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Google.ProtocolBuffers; -using grpc.testing; using Grpc.Auth; using Grpc.Core; using Grpc.Core.Utils; +using Grpc.Testing; using NUnit.Framework; +using Google.Protobuf; namespace Grpc.IntegrationTesting { @@ -186,7 +186,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!"); } @@ -194,11 +194,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); @@ -211,7 +212,7 @@ namespace Grpc.IntegrationTesting { Console.WriteLine("running client_streaming"); - var bodySizes = new List { 27182, 8, 1828, 45904 }.ConvertAll((size) => StreamingInputCallRequest.CreateBuilder().SetPayload(CreateZerosPayload(size)).Build()); + var bodySizes = new List { 27182, 8, 1828, 45904 }.ConvertAll((size) => new StreamingInputCallRequest { Payload = CreateZerosPayload(size) }); using (var call = client.StreamingInputCall()) { @@ -229,11 +230,11 @@ namespace Grpc.IntegrationTesting var bodySizes = new List { 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)) { @@ -253,37 +254,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); @@ -312,13 +321,14 @@ namespace Grpc.IntegrationTesting public static void RunServiceAccountCreds(TestService.ITestServiceClient client) { Console.WriteLine("running service_account_creds"); - 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); @@ -332,13 +342,14 @@ namespace Grpc.IntegrationTesting public static void RunComputeEngineCreds(TestService.ITestServiceClient client) { Console.WriteLine("running compute_engine_creds"); - 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); @@ -358,10 +369,11 @@ namespace Grpc.IntegrationTesting client.HeaderInterceptor = OAuth2Interceptors.FromAccessToken(oauth2Token); - var request = SimpleRequest.CreateBuilder() - .SetFillUsername(true) - .SetFillOauthScope(true) - .Build(); + var request = new SimpleRequest + { + FillUsername = true, + FillOauthScope = true + }; var response = client.UnaryCall(request); @@ -379,10 +391,11 @@ namespace Grpc.IntegrationTesting string oauth2Token = credential.Token.AccessToken; var headerInterceptor = OAuth2Interceptors.FromAccessToken(oauth2Token); - var request = SimpleRequest.CreateBuilder() - .SetFillUsername(true) - .SetFillOauthScope(true) - .Build(); + var request = new SimpleRequest + { + FillUsername = true, + FillOauthScope = true + }; var headers = new Metadata(); headerInterceptor(headers); @@ -424,10 +437,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); @@ -452,12 +467,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 6fa721bc1c..a827aedbdd 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 504fd11857..dea0ce752b 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/SslCredentialsTest.cs b/src/csharp/Grpc.IntegrationTesting/SslCredentialsTest.cs index 1c398eb84e..08a2d9b31c 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 @@ -93,7 +93,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/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/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs index ccf9fe6ced..4ab1266f25 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 { /// /// Implementation of TestService server @@ -48,22 +48,20 @@ namespace grpc.testing { public Task EmptyCall(Empty request, ServerCallContext context) { - return Task.FromResult(Empty.DefaultInstance); + return Task.FromResult(new Empty()); } public Task 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 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 requestStream, IServerStreamWriter responseStream, ServerCallContext context) { await requestStream.ForEach(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]) }; } } } -- cgit v1.2.3 From 9ee27e10bac6f2406dd49e376206c084febbd169 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 10:32:48 -0700 Subject: service descriptor --- src/csharp/Grpc.Examples/MathGrpc.cs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index c0cab6e469..42372d59a3 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -45,6 +45,12 @@ namespace Math { __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 { -- cgit v1.2.3 From e6af5d10ec7575645359db4b8a529f026815df16 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 3 Aug 2015 10:57:43 -0700 Subject: add service descriptor property to generated code --- src/compiler/csharp_generator.cc | 12 ++++++++++++ src/compiler/csharp_generator.h | 1 + src/csharp/Grpc.Examples/MathGrpc.cs | 2 +- src/csharp/Grpc.HealthCheck/HealthGrpc.cs | 6 ++++++ src/csharp/Grpc.IntegrationTesting/TestGrpc.cs | 6 ++++++ 5 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 8a600904e7..51d8d982e2 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -44,6 +44,7 @@ using google::protobuf::compiler::csharp::GetFileNamespace; using google::protobuf::compiler::csharp::GetClassName; using google::protobuf::compiler::csharp::GetUmbrellaClassName; +using google::protobuf::SimpleItoa; using grpc::protobuf::FileDescriptor; using grpc::protobuf::Descriptor; using grpc::protobuf::ServiceDescriptor; @@ -226,6 +227,16 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) { out->Outdent(); } +void GenerateServiceDescriptorProperty(Printer* out, const ServiceDescriptor *service) { + 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", SimpleItoa(service->index())); + 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", @@ -472,6 +483,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); diff --git a/src/compiler/csharp_generator.h b/src/compiler/csharp_generator.h index 0610f5e9fb..67e3ee30b5 100644 --- a/src/compiler/csharp_generator.h +++ b/src/compiler/csharp_generator.h @@ -39,6 +39,7 @@ using namespace std; #include +#include namespace grpc_csharp_generator { diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 42372d59a3..2e98f2166c 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -48,7 +48,7 @@ namespace Math { // service descriptor public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor { - get { return global::Math.Proto.Math.Descriptor.Services[0]; } + get { return global::Math.Proto.Math.Descriptor.Services[0]; } } // client interface diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs index 9d452b0732..da721ce5f6 100644 --- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs +++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs @@ -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.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index 1b5a30d757..71e701b624 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -62,6 +62,12 @@ namespace Grpc.Testing { __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 { -- cgit v1.2.3 From 38536a7c77b6edc9d02221d88163757e01714987 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sat, 8 Aug 2015 00:45:52 -0700 Subject: regenerate protos --- src/csharp/Grpc.Examples/Math.cs | 40 ++++------------ src/csharp/Grpc.Examples/MathGrpc.cs | 28 ++++------- src/csharp/Grpc.HealthCheck/Health.cs | 16 ++----- src/csharp/Grpc.IntegrationTesting/Empty.cs | 8 +--- src/csharp/Grpc.IntegrationTesting/Messages.cs | 64 +++++++------------------- src/csharp/Grpc.IntegrationTesting/TestGrpc.cs | 43 +++++++---------- 6 files changed, 58 insertions(+), 141 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Examples/Math.cs b/src/csharp/Grpc.Examples/Math.cs index 953895e970..d0e1ee8aae 100644 --- a/src/csharp/Grpc.Examples/Math.cs +++ b/src/csharp/Grpc.Examples/Math.cs @@ -156,14 +156,10 @@ namespace Math { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Dividend = input.ReadInt64(); @@ -288,14 +284,10 @@ namespace Math { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Quotient = input.ReadInt64(); @@ -398,14 +390,10 @@ namespace Math { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Limit = input.ReadInt64(); @@ -504,14 +492,10 @@ namespace Math { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Num_ = input.ReadInt64(); @@ -610,14 +594,10 @@ namespace Math { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Count = input.ReadInt64(); diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 2e98f2166c..175d110f76 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -54,24 +54,16 @@ namespace Math { // client interface public interface IMathClient { -<<<<<<< HEAD - 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 DivAsync(global::math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncUnaryCall DivAsync(global::math.DivArgs request, CallOptions options); - AsyncDuplexStreamingCall DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncDuplexStreamingCall DivMany(CallOptions options); - AsyncServerStreamingCall Fib(global::math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncServerStreamingCall Fib(global::math.FibArgs request, CallOptions options); - AsyncClientStreamingCall Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncClientStreamingCall 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 DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall DivAsync(global::Math.DivArgs request, CallOptions options); AsyncDuplexStreamingCall DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncDuplexStreamingCall DivMany(CallOptions options); AsyncServerStreamingCall Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncServerStreamingCall Fib(global::Math.FibArgs request, CallOptions options); AsyncClientStreamingCall Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); ->>>>>>> 708e8de... regenerate protos + AsyncClientStreamingCall Sum(CallOptions options); } // server-side interface @@ -94,7 +86,7 @@ namespace Math { 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); @@ -104,7 +96,7 @@ namespace Math { var call = CreateCall(__Method_Div, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncUnaryCall(call, request); } - public AsyncUnaryCall DivAsync(global::math.DivArgs request, CallOptions options) + public AsyncUnaryCall DivAsync(global::Math.DivArgs request, CallOptions options) { var call = CreateCall(__Method_Div, options); return Calls.AsyncUnaryCall(call, request); @@ -114,7 +106,7 @@ namespace Math { var call = CreateCall(__Method_DivMany, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall DivMany(CallOptions options) + public AsyncDuplexStreamingCall DivMany(CallOptions options) { var call = CreateCall(__Method_DivMany, options); return Calls.AsyncDuplexStreamingCall(call); @@ -124,7 +116,7 @@ namespace Math { var call = CreateCall(__Method_Fib, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncServerStreamingCall(call, request); } - public AsyncServerStreamingCall Fib(global::math.FibArgs request, CallOptions options) + public AsyncServerStreamingCall Fib(global::Math.FibArgs request, CallOptions options) { var call = CreateCall(__Method_Fib, options); return Calls.AsyncServerStreamingCall(call, request); @@ -134,7 +126,7 @@ namespace Math { var call = CreateCall(__Method_Sum, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncClientStreamingCall(call); } - public AsyncClientStreamingCall Sum(CallOptions options) + public AsyncClientStreamingCall Sum(CallOptions options) { var call = CreateCall(__Method_Sum, options); return Calls.AsyncClientStreamingCall(call); diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs index de65c1a9de..570e274544 100644 --- a/src/csharp/Grpc.HealthCheck/Health.cs +++ b/src/csharp/Grpc.HealthCheck/Health.cs @@ -153,14 +153,10 @@ namespace Grpc.Health.V1Alpha { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { Host = input.ReadString(); @@ -263,14 +259,10 @@ namespace Grpc.Health.V1Alpha { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { status_ = (global::Grpc.Health.V1Alpha.HealthCheckResponse.Types.ServingStatus) input.ReadEnum(); diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs index fc8ea3889c..28c28c9afd 100644 --- a/src/csharp/Grpc.IntegrationTesting/Empty.cs +++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs @@ -100,14 +100,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; } } diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs index e5a9f382b6..a3cbb7d76e 100644 --- a/src/csharp/Grpc.IntegrationTesting/Messages.cs +++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs @@ -176,14 +176,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { type_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); @@ -377,14 +373,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); @@ -549,14 +541,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (payload_ == null) { @@ -669,14 +657,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (payload_ == null) { @@ -778,14 +762,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { AggregatedPayloadSize = input.ReadInt32(); @@ -906,14 +886,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { Size = input.ReadInt32(); @@ -1055,14 +1031,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 8: { responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum(); @@ -1175,14 +1147,10 @@ namespace Grpc.Testing { public void MergeFrom(pb::CodedInputStream input) { uint tag; - while (input.ReadTag(out tag)) { + while ((tag = input.ReadTag()) != 0) { switch(tag) { - case 0: - throw pb::InvalidProtocolBufferException.InvalidTag(); default: - if (pb::WireFormat.IsEndGroupTag(tag)) { - return; - } + input.SkipLastField(); break; case 10: { if (payload_ == null) { diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs index 71e701b624..f63e148475 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs @@ -71,33 +71,22 @@ namespace Grpc.Testing { // client interface public interface ITestServiceClient { -<<<<<<< HEAD - 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 EmptyCallAsync(global::grpc.testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncUnaryCall 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 UnaryCallAsync(global::grpc.testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncUnaryCall UnaryCallAsync(global::grpc.testing.SimpleRequest request, CallOptions options); - AsyncServerStreamingCall StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncServerStreamingCall StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CallOptions options); - AsyncClientStreamingCall StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncClientStreamingCall StreamingInputCall(CallOptions options); - AsyncDuplexStreamingCall FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncDuplexStreamingCall FullDuplexCall(CallOptions options); - AsyncDuplexStreamingCall HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); - AsyncDuplexStreamingCall 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 EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall 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 UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options); AsyncServerStreamingCall StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncServerStreamingCall StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options); AsyncClientStreamingCall StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncClientStreamingCall StreamingInputCall(CallOptions options); AsyncDuplexStreamingCall FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); + AsyncDuplexStreamingCall FullDuplexCall(CallOptions options); AsyncDuplexStreamingCall HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken)); ->>>>>>> 708e8de... regenerate protos + AsyncDuplexStreamingCall HalfDuplexCall(CallOptions options); } // server-side interface @@ -122,7 +111,7 @@ namespace Grpc.Testing { 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); @@ -132,7 +121,7 @@ namespace Grpc.Testing { var call = CreateCall(__Method_EmptyCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncUnaryCall(call, request); } - public AsyncUnaryCall EmptyCallAsync(global::grpc.testing.Empty request, CallOptions options) + public AsyncUnaryCall EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options) { var call = CreateCall(__Method_EmptyCall, options); return Calls.AsyncUnaryCall(call, request); @@ -142,7 +131,7 @@ namespace Grpc.Testing { 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); @@ -152,7 +141,7 @@ namespace Grpc.Testing { var call = CreateCall(__Method_UnaryCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncUnaryCall(call, request); } - public AsyncUnaryCall UnaryCallAsync(global::grpc.testing.SimpleRequest request, CallOptions options) + public AsyncUnaryCall UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options) { var call = CreateCall(__Method_UnaryCall, options); return Calls.AsyncUnaryCall(call, request); @@ -162,7 +151,7 @@ namespace Grpc.Testing { var call = CreateCall(__Method_StreamingOutputCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncServerStreamingCall(call, request); } - public AsyncServerStreamingCall StreamingOutputCall(global::grpc.testing.StreamingOutputCallRequest request, CallOptions options) + public AsyncServerStreamingCall StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options) { var call = CreateCall(__Method_StreamingOutputCall, options); return Calls.AsyncServerStreamingCall(call, request); @@ -172,7 +161,7 @@ namespace Grpc.Testing { var call = CreateCall(__Method_StreamingInputCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncClientStreamingCall(call); } - public AsyncClientStreamingCall StreamingInputCall(CallOptions options) + public AsyncClientStreamingCall StreamingInputCall(CallOptions options) { var call = CreateCall(__Method_StreamingInputCall, options); return Calls.AsyncClientStreamingCall(call); @@ -182,7 +171,7 @@ namespace Grpc.Testing { var call = CreateCall(__Method_FullDuplexCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall FullDuplexCall(CallOptions options) + public AsyncDuplexStreamingCall FullDuplexCall(CallOptions options) { var call = CreateCall(__Method_FullDuplexCall, options); return Calls.AsyncDuplexStreamingCall(call); @@ -192,7 +181,7 @@ namespace Grpc.Testing { var call = CreateCall(__Method_HalfDuplexCall, new CallOptions(headers, deadline, cancellationToken)); return Calls.AsyncDuplexStreamingCall(call); } - public AsyncDuplexStreamingCall HalfDuplexCall(CallOptions options) + public AsyncDuplexStreamingCall HalfDuplexCall(CallOptions options) { var call = CreateCall(__Method_HalfDuplexCall, options); return Calls.AsyncDuplexStreamingCall(call); -- cgit v1.2.3 From 4ef39ce75b243aede42e06e3d549c15f837fa517 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sat, 8 Aug 2015 01:19:51 -0700 Subject: switched to protobuf from 20150808 --- src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj | 5 +++-- src/csharp/Grpc.Examples.Tests/packages.config | 2 +- src/csharp/Grpc.Examples/Grpc.Examples.csproj | 5 +++-- src/csharp/Grpc.Examples/packages.config | 2 +- src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj | 5 +++-- src/csharp/Grpc.HealthCheck.Tests/packages.config | 2 +- src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj | 5 +++-- src/csharp/Grpc.HealthCheck/packages.config | 2 +- src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj | 5 +++-- src/csharp/Grpc.IntegrationTesting/packages.config | 2 +- 10 files changed, 20 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj index 7eea632f36..cb5707a53a 100644 --- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj +++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj @@ -37,8 +37,9 @@ C:\keys\Grpc.snk - - ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config index 7266fa1763..ebcf575362 100644 --- a/src/csharp/Grpc.Examples.Tests/packages.config +++ b/src/csharp/Grpc.Examples.Tests/packages.config @@ -1,6 +1,6 @@  - + \ 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 1ba1ed6081..26df9c9223 100644 --- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj +++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj @@ -37,8 +37,9 @@ C:\keys\Grpc.snk - - ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config index adf8da2363..915995af40 100644 --- a/src/csharp/Grpc.Examples/packages.config +++ b/src/csharp/Grpc.Examples/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj index ca24874d66..3723dd3fb5 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj +++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj @@ -37,8 +37,9 @@ C:\keys\Grpc.snk - - ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config index 40ffb85203..a839c9d7dd 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/packages.config +++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config @@ -1,5 +1,5 @@  - + \ 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 c9eb862f48..2f54fb0844 100644 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -38,8 +38,9 @@ C:\keys\Grpc.snk - - ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config index cafff6123a..5d14012532 100644 --- a/src/csharp/Grpc.HealthCheck/packages.config +++ b/src/csharp/Grpc.HealthCheck/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 38a3961837..24a7d2e7eb 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -41,8 +41,9 @@ ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll - - ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config index 7b7bc42ff4..10612a1cbf 100644 --- a/src/csharp/Grpc.IntegrationTesting/packages.config +++ b/src/csharp/Grpc.IntegrationTesting/packages.config @@ -3,7 +3,7 @@ - + -- cgit v1.2.3 From a96167c0e2cbbd85e1712947d2ed32f7d34bcfc7 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sat, 8 Aug 2015 01:31:33 -0700 Subject: setup build packages to build preview version --- src/csharp/Grpc.Core/VersionInfo.cs | 2 +- src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec | 2 +- src/csharp/build_packages.bat | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs index 656a3d47bb..eb55af8a13 100644 --- a/src/csharp/Grpc.Core/VersionInfo.cs +++ b/src/csharp/Grpc.Core/VersionInfo.cs @@ -8,6 +8,6 @@ namespace Grpc.Core /// /// Current version of gRPC /// - public const string CurrentVersion = "0.6.0"; + public const string CurrentVersion = "0.7.0"; } } 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 2015, Google Inc. gRPC health check - + diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 9e1253bf0b..395fb43970 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.0 -set CORE_VERSION=0.10.0 +set VERSION=0.7.0-preview20150808 +set CORE_VERSION=0.11.0-preview20150808 +set PROTOBUF_VERSION=3.0.0-a20150808-e58cdbd214 @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe @@ -17,7 +18,7 @@ endlocal %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 -- cgit v1.2.3 From 012b2e9489bb6f36f05b9af35dd0ca70337cf428 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Sat, 8 Aug 2015 01:44:07 -0700 Subject: update Grpc.Tools.nuspec --- src/csharp/Grpc.Tools.nuspec | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Tools.nuspec b/src/csharp/Grpc.Tools.nuspec index eabf5dc7db..b6e116f537 100644 --- a/src/csharp/Grpc.Tools.nuspec +++ b/src/csharp/Grpc.Tools.nuspec @@ -4,19 +4,18 @@ Grpc.Tools gRPC C# Tools Tools for C# implementation of gRPC - an RPC library and framework - Precompiled Windows binaries for generating protocol buffer messages and gRPC client/server code + Precompiled Windows binary for generating gRPC client/server code $version$ Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE https://github.com/grpc/grpc false - protoc.exe - protocol buffer compiler v3.0.0-alpha-3; grpc_csharp_plugin.exe - gRPC C# protoc plugin version $version$ + grpc_csharp_plugin.exe - gRPC C# protoc plugin version $version$ Copyright 2015, Google Inc. gRPC RPC Protocol HTTP/2 - -- cgit v1.2.3 From d9d41fa898c14c3117d94f439ec5b5e23a0cadeb Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Sat, 8 Aug 2015 17:51:58 -0700 Subject: Prevent storing in the hosts cache with a nil key --- src/objective-c/GRPCClient/private/GRPCHost.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m index d902f95b51..e47375a866 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"]; } -- cgit v1.2.3 From e6d0ad317ed820b29f709c8273ed3fec7463db11 Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Thu, 13 Aug 2015 09:59:48 -0700 Subject: add all new content --- BUILD | 3 + Makefile | 3 +- build.json | 1 + gRPC.podspec | 1 + include/grpc/census.h | 220 +++++++++++---------- src/core/census/context.c | 13 -- src/core/census/grpc_context.c | 15 +- src/core/census/operation.c | 57 ++++++ src/core/census/tracing.c | 24 +-- tools/doxygen/Doxyfile.core.internal | 1 + tools/run_tests/sources_and_headers.json | 2 + vsprojects/grpc/grpc.vcxproj | 2 + vsprojects/grpc/grpc.vcxproj.filters | 3 + vsprojects/grpc_unsecure/grpc_unsecure.vcxproj | 2 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 3 + 15 files changed, 199 insertions(+), 151 deletions(-) create mode 100644 src/core/census/operation.c (limited to 'src') diff --git a/BUILD b/BUILD index 21da008dc8..bfad5b2518 100644 --- a/BUILD +++ b/BUILD @@ -386,6 +386,7 @@ cc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", "src/core/census/tracing.c", ], @@ -626,6 +627,7 @@ cc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", "src/core/census/tracing.c", ], @@ -1113,6 +1115,7 @@ objc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", "src/core/census/tracing.c", ], diff --git a/Makefile b/Makefile index 94e8155680..0f60fbd35b 100644 --- a/Makefile +++ b/Makefile @@ -3856,6 +3856,7 @@ LIBGRPC_SRC = \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ + src/core/census/operation.c \ src/core/census/record_stat.c \ src/core/census/tracing.c \ @@ -4125,6 +4126,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ + src/core/census/operation.c \ src/core/census/record_stat.c \ src/core/census/tracing.c \ @@ -18761,7 +18763,6 @@ test/cpp/qps/timer.cc: $(OPENSSL_DEP) test/cpp/util/benchmark_config.cc: $(OPENSSL_DEP) test/cpp/util/cli_call.cc: $(OPENSSL_DEP) test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP) -test/cpp/util/fake_credentials.cc: $(OPENSSL_DEP) test/cpp/util/subprocess.cc: $(OPENSSL_DEP) test/cpp/util/test_config.cc: $(OPENSSL_DEP) endif diff --git a/build.json b/build.json index a65932701e..93da5f1a8e 100644 --- a/build.json +++ b/build.json @@ -24,6 +24,7 @@ "src": [ "src/core/census/context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", "src/core/census/tracing.c" ] diff --git a/gRPC.podspec b/gRPC.podspec index 775fbfda5e..d02704c88e 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -395,6 +395,7 @@ Pod::Spec.new do |s| 'src/core/transport/transport_op_string.c', 'src/core/census/context.c', 'src/core/census/initialize.c', + 'src/core/census/operation.c', 'src/core/census/record_stat.c', 'src/core/census/tracing.c' diff --git a/include/grpc/census.h b/include/grpc/census.h index 9315a3ad8c..379d567343 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -69,12 +69,14 @@ int census_supported(void); /** Return the census features currently enabled. */ int census_enabled(void); -/* Internally, Census relies on a context, which should be propagated across - * RPC's. From the RPC subsystems viewpoint, this is an opaque data structure. - * A context must be used as the first argument to all other census - * functions. Conceptually, contexts should be thought of as specific to - * single RPC/thread. The context can be serialized for passing across the - * wire. */ +/** + Context is a handle used by census to represent the current tracing and + tagging information. Contexts should be propagated across RPC's. Contexts + are created by any of the census_start_*_op() functions. A context is + typically used as argument to most census functions. Conceptually, contexts + should be thought of as specific to single RPC/thread. The context can be + serialized for passing across the wire, via census_context_serialize(). +*/ typedef struct census_context census_context; /* This function is called by the RPC subsystem whenever it needs to get a @@ -91,19 +93,6 @@ typedef struct census_context census_context; size_t census_context_serialize(const census_context *context, char *buffer, size_t buf_size); -/* Create a new census context, possibly from a serialized buffer. If 'buffer' - * is non-NULL, it is assumed that it is a buffer encoded by - * census_context_serialize(). If `buffer` is NULL, a new, empty context is - * created. The decoded/new contest is returned in 'context'. - * - * Returns 0 if no errors, non-zero if buffer is incorrectly formatted, in - * which case a new empty context will be returned. */ -int census_context_deserialize(const char *buffer, census_context **context); - -/* The given context is destroyed. Once destroyed, using the context in - * future census calls will result in undefined behavior. */ -void census_context_destroy(census_context *context); - /* Distributed traces can have a number of options. */ enum census_trace_mask_values { CENSUS_TRACE_MASK_NONE = 0, /* Default, empty flags */ @@ -114,13 +103,15 @@ enum census_trace_mask_values { will be the logical or of census_trace_mask_values values. */ int census_trace_mask(const census_context *context); -/* The concept of "operation" is a fundamental concept for Census. An - operation is a logical representation of a action in a RPC-using system. It - is most typically used to represent a single RPC, or a significant sub-part - thereof (e.g. a single logical "read" RPC to a distributed storage system - might do several other actions in parallel, from looking up metadata +/** Set the trace mask associated with a context. */ +void census_set_trace_mask(int trace_mask); + +/* The concept of "operation" is a fundamental concept for Census. In an RPC + system, and operation typcially represents a single RPC, or a significant + sub-part thereof (e.g. a single logical "read" RPC to a distributed storage + system might do several other actions in parallel, from looking up metadata indices to making requests of other services - each of these could be a - sub-operation with the larger RPC operation. Census uses operations for the + sub-operation with the larger RPC operation). Census uses operations for the following: CPU accounting: If enabled, census will measure the thread CPU time @@ -131,123 +122,152 @@ int census_trace_mask(const census_context *context); Distributed tracing: Each operation serves as a logical trace span. - Stats collection: Stats are broken down operation (e.g. latency - breakdown for each service/method combination). + Stats collection: Stats are broken down by operation (e.g. latency + breakdown for each unique RPC path). The following functions serve to delineate the start and stop points for each logical operation. */ + +/** + This structure (opaquely) represents a timestamp as used by census to + record the time at which an RPC operation begins. +*/ +typedef struct census_timestamp census_timestamp; + +/** + Mark the beginning of an RPC operation. The information required to call the + functions to record the start of RPC operations (both client and server) may + not be callable at the true start time of the operation, due to information + not being available (e.g. the census context data will not be available in a + server RPC until at least initial metadata has been processed). To ensure + correct CPU accounting and latency recording, RPC systems can call this + function to get the timestamp of operation beginning. This can later be used + as an argument to census_start_{client,server}_rpc_op(). NB: for correct + CPU accounting, the system must guarantee that the same thread is used + for all request processing after this function is called. + + @return A timestamp representing the operation start time. +*/ +census_timestamp *census_start_rpc_op_timestamp(void); + +/** + Represent functions to map RPC name ID to service/method names. Census + breaks down all RPC stats by service and method names. We leave the + definition and format of these to the RPC system. For efficiency purposes, + we encode these as a single 64 bit identifier, and allow the RPC system to + provide a structure for functions that can convert these to service and + method strings. + + TODO(aveitch): Instead of providing this as an argument to the rpc_start_op() + functions, maybe it should be set once at census initialization. +*/ +typedef struct { + const char *(*get_rpc_service_name)(gpr_int64 id); + const char *(*get_rpc_method_name)(gpr_int64 id); +} census_rpc_name_info; + /** - Start a client rpc operation. This function will create a new context. If + Start a client rpc operation. This function should be called as early in the + client RPC path as possible. This function will create a new context. If the context argument is non-null, then the new context will inherit all its properties, with the following changes: - create a new operation ID for the new context, marking it as a child of the previous operation. - - use the new RPC service/method/peer information for tracing and stats + - use the new RPC path and peer information for tracing and stats collection purposes, rather than those from the original context - - if trace_mask is non-zero, update the trace mask entries associated with - the original context. - If the context argument is NULL, then a new root context is created. This + If the context argument is NULL, then a new root context is created. This is particularly important for tracing purposes (the trace spans generated will be unassociated with any other trace spans, except those - downstream). Whatever it's value, the trace_mask will be used for tracing - operations associated with the new context. - - @param context The base context. Can be NULL. - @param service RPC service name. On some systems, may include other - parts of RPC identification (e.g. host on gRPC systems). - @param method RPC method name - @param peer RPC peer - @param trace_mask An or of census_trace_mask_values values - @param start_time If NULL, the time of function call is used as the - start time for the operation. If non-NULL, then the time should be in the - past, when the operation was deemed to have started. This is used when - the other information used as arguments is not yet available. + downstream). The trace_mask will be used for tracing operations associated + with the new context. + + In some RPC systems (e.g. where load balancing is used), peer information + may not be available at the time the operation starts. In this case, use a + NULL value for peer, and set it later using the + census_set_rpc_client_peer() function. + + @param context The parent context. Can be NULL. + @param rpc_name_id The rpc name identifier to be associated with this RPC. + @param rpc_name_info Used to decode rpc_name_id. + @param peer RPC peer. If not available at the time, NULL can be used, + and a later census_set_rpc_client_peer() call made. + @param trace_mask An OR of census_trace_mask_values values. Only used in + the creation of a new root context (context == NULL). + @param start_time A timestamp returned from census_start_rpc_op_timestamp(). + Can be NULL. Used to set the true time the operation + begins. @return A new census context. */ -census_context *census_start_client_rpc_op(census_context *context, - const char *service, - const char *method, const char *peer, - int trace_mask, - gpr_timespec *start_time); +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); /** - Indicate the start of a server rpc operation, updating the current - context (which should have been created from census_context_deserialize() - (as passed from the client side of the RPC operation) or census_start_op(). - - if trace_mask is non-zero, update the trace mask entries associated with - the original context. - - @param context The base context. Cannot be NULL. - @param service RPC service name. On some systems, may include other - parts of RPC identification (e.g. host on gRPC systems). - @param method RPC method name - @param peer RPC peer - @param trace_mask An or of census_trace_mask_values values - @param start_time If NULL, the time of function call is used as the - start time for the operation. If non-NULL, then the time should be in the - past, when the operation was deemed to have started. This is used when - the other information used as arguments is not yet available. + Add peer information to a context representing a client RPC operation. +*/ +void census_set_rpc_client_peer(census_context *context, const char *peer); + +/** + Start a server RPC operation. Returns a new context to be used in future + census calls. If buffer is non-NULL, then the buffer contents should + represent the client context, as generated by census_context_serialize(). + If buffer is NULL, a new root context is created. + + @param buffer Buffer containing bytes output from census_context_serialize(). + @param rpc_name_id The rpc name identifier to be associated with this RPC. + @param rpc_name_info Used to decode rpc_name_id. + @param peer RPC peer. + @param trace_mask An OR of census_trace_mask_values values. Only used in + the creation of a new root context (buffer == NULL). + @param start_time A timestamp returned from census_start_rpc_op_timestamp(). + Can be NULL. Used to set the true time the operation + begins. + + @return A new census context. */ -void census_start_server_rpc_op(census_context *context, const char *service, - const char *method, const char *peer, - int trace_mask, gpr_timespec *start_time); +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); /** - Start a new, non-RPC census operation. In general, this function works very - similarly to census_start_client_rpc_op, with the primary differennce being - the abscence of peer information, and the replacement of service and method - names with the more general family/name. If the context argument is - non-null, then the new context will inherit all its properties, with the - following changes: + Start a new, non-RPC operation. In general, this function works very + similarly to census_start_client_rpc_op, with the primary difference being + the replacement of host/path information with the more generic family/name + tags. If the context argument is non-null, then the new context will + inherit all its properties, with the following changes: - create a new operation ID for the new context, marking it as a child of the previous operation. - use the family and name information for tracing and stats collection purposes, rather than those from the original context - - if trace_mask is non-zero, update the trace mask entries associated with - the original context. - If the context argument is NULL, then a new root context is created. This + If the context argument is NULL, then a new root context is created. This is particularly important for tracing purposes (the trace spans generated will be unassociated with any other trace spans, except those - downstream). Whatever it's value, the trace_mask will be used for tracing + downstream). The trace_mask will be used for tracing operations associated with the new context. @param context The base context. Can be NULL. @param family Family name to associate with the trace @param name Name within family to associated with traces/stats - @param trace_mask An or of census_trace_mask_values values - @param start_time If NULL, the time of function call is used as the - start time for the operation. If non-NULL, then the time should be in the - past, when the operation was deemed to have started. This is used when - the other information used as arguments is not yet available. + @param trace_mask An OR of census_trace_mask_values values. Only used if + context is NULL. @return A new census context. */ census_context *census_start_op(census_context *context, const char *family, - const char *name, int trace_mask, - gpr_timespec *start_time); + const char *name, int trace_mask); -/** End a tracing operation. Must be matched with an earlier - * census_start_*_op*() call. */ -void census_trace_end_op(census_context *context, int status); +/** End an operation started by any of the census_start_*_op*() calls. */ +void census_end_op(census_context *context, int status); /** Insert a trace record into the trace stream. The record consists of an * arbitrary size buffer, the size of which is provided in 'n'. */ void census_trace_print(census_context *context, const char *buffer, size_t n); -/** Retrieve active ops as a proto. Note that since we don't have proto - manipulation available in the grpc core yet, arguments etc. are left - unspecified for now. */ -void census_get_active_ops_as_proto(/* pointer to proto */); - -/** Retrieve all active trace records as a proto. Note that since we don't - have proto manipulation available in the grpc core yet, arguments etc. are - left unspecified for now. This function will clear existing trace - records. */ -void census_get_trace_as_proto(/* pointer to proto */); - /* A census statistic to be recorded comprises two parts: an ID for the * particular statistic and the value to be recorded against it. */ typedef struct { 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 #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/operation.c b/src/core/census/operation.c new file mode 100644 index 0000000000..a0196da614 --- /dev/null +++ b/src/core/census/operation.c @@ -0,0 +1,57 @@ +/* + * 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 + +/* TODO(aveitch): These are all placeholder implementations. */ + +census_timestamp *census_start_rpc_op_timestamp(void) { return NULL; } +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/tracing.c b/src/core/census/tracing.c index 83d46cc407..44db95653c 100644 --- a/src/core/census/tracing.c +++ b/src/core/census/tracing.c @@ -39,29 +39,7 @@ int census_trace_mask(const census_context *context) { return CENSUS_TRACE_MASK_NONE; } -census_context *census_start_client_rpc_op(census_context *context, - const char *service, - const char *method, const char *peer, - int trace_mask, - gpr_timespec *start_time) { - return NULL; -} - -void census_start_server_rpc_op(census_context *context, const char *service, - const char *method, const char *peer, - int trace_mask, gpr_timespec *start_time) {} - -census_context *census_start_op(census_context *context, const char *family, - const char *name, int trace_mask, - gpr_timespec *start_time) { - return NULL; -} - -void census_trace_end_op(census_context *context, int status) {} +void census_set_trace_mask(int trace_mask) {} void census_trace_print(census_context *context, const char *buffer, size_t n) { } - -void census_get_active_ops_as_proto(/* pointer to proto */) {} - -void census_get_trace_as_proto(/* pointer to proto */) {} diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index e5bf7fa220..8f937303a9 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -1021,6 +1021,7 @@ src/core/transport/transport.c \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ +src/core/census/operation.c \ src/core/census/record_stat.c \ src/core/census/tracing.c \ include/grpc/support/alloc.h \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 24dca9cc7f..6878705770 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -11056,6 +11056,7 @@ "src/core/census/context.h", "src/core/census/grpc_context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", "src/core/census/rpc_stat_id.h", "src/core/census/tracing.c", @@ -11509,6 +11510,7 @@ "src/core/census/context.h", "src/core/census/grpc_context.c", "src/core/census/initialize.c", + "src/core/census/operation.c", "src/core/census/record_stat.c", "src/core/census/rpc_stat_id.h", "src/core/census/tracing.c", diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj index add4a8fa7c..a0fca7aa89 100644 --- a/vsprojects/grpc/grpc.vcxproj +++ b/vsprojects/grpc/grpc.vcxproj @@ -623,6 +623,8 @@ + + diff --git a/vsprojects/grpc/grpc.vcxproj.filters b/vsprojects/grpc/grpc.vcxproj.filters index 41142651c2..e0c9519bb6 100644 --- a/vsprojects/grpc/grpc.vcxproj.filters +++ b/vsprojects/grpc/grpc.vcxproj.filters @@ -415,6 +415,9 @@ src\core\census + + src\core\census + src\core\census diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj index 395e3bc86f..99d1e7ff6f 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj @@ -556,6 +556,8 @@ + + diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters index 721bbd8310..049dbcf10d 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -346,6 +346,9 @@ src\core\census + + src\core\census + src\core\census -- cgit v1.2.3 From 58d637444187f36181d3662e85e42aa1d23af92a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 13 Aug 2015 10:17:09 -0700 Subject: upgrade to latest protobufs --- src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj | 5 ++--- src/csharp/Grpc.Examples.Tests/packages.config | 2 +- src/csharp/Grpc.Examples/Grpc.Examples.csproj | 5 ++--- src/csharp/Grpc.Examples/packages.config | 2 +- src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj | 5 ++--- src/csharp/Grpc.HealthCheck.Tests/packages.config | 2 +- src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj | 5 ++--- src/csharp/Grpc.HealthCheck/packages.config | 2 +- src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj | 5 ++--- src/csharp/Grpc.IntegrationTesting/packages.config | 2 +- src/csharp/build_packages.bat | 6 +++--- 11 files changed, 18 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj index cb5707a53a..8b05c9cad8 100644 --- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj +++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj @@ -37,9 +37,8 @@ C:\keys\Grpc.snk - - False - ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config index ebcf575362..d84b85822f 100644 --- a/src/csharp/Grpc.Examples.Tests/packages.config +++ b/src/csharp/Grpc.Examples.Tests/packages.config @@ -1,6 +1,6 @@  - + \ 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 26df9c9223..cb99c20079 100644 --- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj +++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj @@ -37,9 +37,8 @@ C:\keys\Grpc.snk - - False - ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config index 915995af40..27e9d2ce15 100644 --- a/src/csharp/Grpc.Examples/packages.config +++ b/src/csharp/Grpc.Examples/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj index 3723dd3fb5..7f0ff66fa1 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj +++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj @@ -37,9 +37,8 @@ C:\keys\Grpc.snk - - False - ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config index a839c9d7dd..228e0725c8 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/packages.config +++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config @@ -1,5 +1,5 @@  - + \ 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 2f54fb0844..dac8c21d70 100644 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -38,9 +38,8 @@ C:\keys\Grpc.snk - - False - ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config index 5d14012532..7f9cb2dd48 100644 --- a/src/csharp/Grpc.HealthCheck/packages.config +++ b/src/csharp/Grpc.HealthCheck/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 24a7d2e7eb..a8d85e4ef6 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -41,9 +41,8 @@ ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll - - False - ..\packages\Google.Protobuf.3.0.0-a20150808-e58cdbd214\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config index 10612a1cbf..b6ed3c8532 100644 --- a/src/csharp/Grpc.IntegrationTesting/packages.config +++ b/src/csharp/Grpc.IntegrationTesting/packages.config @@ -3,7 +3,7 @@ - + diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 395fb43970..6aa5e4b0b7 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -1,9 +1,9 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.7.0-preview20150808 -set CORE_VERSION=0.11.0-preview20150808 -set PROTOBUF_VERSION=3.0.0-a20150808-e58cdbd214 +set VERSION=0.7.0-preview20150813 +set CORE_VERSION=0.11.0-preview20150813 +set PROTOBUF_VERSION=3.0.0-a20150813-2093749ca @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe -- cgit v1.2.3 From c2274e706937c1742e72a20a889ce1283d12af52 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Mon, 10 Aug 2015 12:45:17 -0700 Subject: Adding C++ auth metadata processor. - We always do the processing asynchronously but maintain a synchronous API for the implementor of the processor. - there are a lot of string copies right now. Having a StringPiece object in grpc++ would really help with that (as we would use it for C++ metadata). - Please review the API carefully and if you're happy with it, I'll proceed with tests. --- include/grpc++/auth_context.h | 5 +++ include/grpc++/auth_metadata_processor.h | 60 +++++++++++++++++++++++++++ include/grpc++/server_credentials.h | 5 +++ src/cpp/common/secure_auth_context.cc | 12 ++++++ src/cpp/common/secure_auth_context.h | 6 +++ src/cpp/server/insecure_server_credentials.cc | 2 + src/cpp/server/secure_server_credentials.cc | 50 ++++++++++++++++++++++ src/cpp/server/secure_server_credentials.h | 27 +++++++++++- test/cpp/common/secure_auth_context_test.cc | 20 ++++----- 9 files changed, 176 insertions(+), 11 deletions(-) create mode 100644 include/grpc++/auth_metadata_processor.h (limited to 'src') diff --git a/include/grpc++/auth_context.h b/include/grpc++/auth_context.h index f8ea8ad6f4..0b5f856d3f 100644 --- a/include/grpc++/auth_context.h +++ b/include/grpc++/auth_context.h @@ -87,6 +87,11 @@ class AuthContext { // Iteration over all the properties. virtual AuthPropertyIterator begin() const = 0; virtual AuthPropertyIterator end() const = 0; + + // Mutation functions: should only be used by an AuthMetadataProcessor. + virtual void AddProperty(const grpc::string& key, + const grpc::string& value) = 0; + virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0; }; } // namespace grpc diff --git a/include/grpc++/auth_metadata_processor.h b/include/grpc++/auth_metadata_processor.h new file mode 100644 index 0000000000..e077ec0c60 --- /dev/null +++ b/include/grpc++/auth_metadata_processor.h @@ -0,0 +1,60 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPCXX_AUTH_METADATA_PROCESSOR_H_ +#define GRPCXX_AUTH_METADATA_PROCESSOR_H_ + +#include +#include + +#include + +namespace grpc { + +class AuthMetadataProcessor { + public: + virtual ~AuthMetadataProcessor() {} + + // context is read/write: it contains the properties of the channel peer and + // it is the job of the Process method to augment it with properties derived + // from the passed-in auth_metadata. + virtual bool Process( + std::multimap& auth_metadata, + AuthContext* context, + std::multimap* consumed_auth_metadata) = 0; +}; + +} // namespace grpc + +#endif // GRPCXX_AUTH_METADATA_PROCESSOR_H_ + diff --git a/include/grpc++/server_credentials.h b/include/grpc++/server_credentials.h index 11acd67e8a..d540b95e21 100644 --- a/include/grpc++/server_credentials.h +++ b/include/grpc++/server_credentials.h @@ -38,6 +38,7 @@ #include #include +#include struct grpc_server; @@ -54,6 +55,10 @@ class ServerCredentials { virtual int AddPortToServer(const grpc::string& addr, grpc_server* server) = 0; + + // Has to be called before the server is started. + virtual void SetAuthMetadataProcessor( + const std::shared_ptr& processor) = 0; }; // Options to create ServerCredentials with SSL diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc index 87d7bab75c..dc41083a48 100644 --- a/src/cpp/common/secure_auth_context.cc +++ b/src/cpp/common/secure_auth_context.cc @@ -93,4 +93,16 @@ AuthPropertyIterator SecureAuthContext::end() const { return AuthPropertyIterator(); } +void SecureAuthContext::AddProperty(const grpc::string& key, + const grpc::string& 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; +} + } // namespace grpc diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h index 264ed620a3..1b27bf5c32 100644 --- a/src/cpp/common/secure_auth_context.h +++ b/src/cpp/common/secure_auth_context.h @@ -57,6 +57,12 @@ class SecureAuthContext GRPC_FINAL : public AuthContext { AuthPropertyIterator end() const GRPC_OVERRIDE; + void AddProperty(const grpc::string& key, + const grpc::string& value) GRPC_OVERRIDE; + + virtual bool SetPeerIdentityPropertyName(const grpc::string& name) + GRPC_OVERRIDE; + private: grpc_auth_context* ctx_; }; diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc index 800cd36caa..96458477f0 100644 --- a/src/cpp/server/insecure_server_credentials.cc +++ b/src/cpp/server/insecure_server_credentials.cc @@ -43,6 +43,8 @@ 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& processor) GRPC_OVERRIDE {} }; } // namespace diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index 32c45e2280..bdb7ba6e48 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -31,15 +31,65 @@ * */ +#include +#include +#include + + +#include "src/cpp/common/secure_auth_context.h" #include "src/cpp/server/secure_server_credentials.h" +#include + namespace grpc { +void AuthMetadataProcessorAyncWrapper::Process( + void* self, grpc_auth_context* context, const grpc_metadata* md, + size_t md_count, grpc_process_auth_metadata_done_cb cb, void* user_data) { + AuthMetadataProcessorAyncWrapper* instance = + reinterpret_cast(self); + instance->thread_pool_->Add( + std::bind(&AuthMetadataProcessorAyncWrapper::ProcessAsync, instance, + context, md, md_count, cb, user_data)); +} + +void AuthMetadataProcessorAyncWrapper::ProcessAsync( + grpc_auth_context* ctx, const grpc_metadata* md, size_t md_count, + grpc_process_auth_metadata_done_cb cb, void* user_data) { + SecureAuthContext context(ctx); + std::multimap metadata; + for (size_t i = 0; i < md_count; i++) { + metadata.insert(std::make_pair( + md[i].key, grpc::string(md[i].value, md[i].value_length))); + } + std::multimap consumed_metadata; + bool ok = processor_->Process(metadata, &context, &consumed_metadata); + if (ok) { + std::vector consumed_md(consumed_metadata.size()); + for (const auto& entry : consumed_metadata) { + consumed_md.push_back({entry.first.c_str(), + entry.second.data(), + entry.second.size(), + {{nullptr, nullptr, nullptr}}}); + } + cb(user_data, &consumed_md[0], consumed_md.size(), 1); + } else { + cb(user_data, nullptr, 0, 0); + } +} + 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& processor) { + processor_.reset(new AuthMetadataProcessorAyncWrapper(processor)); + grpc_server_credentials_set_auth_metadata_processor( + creds_, {AuthMetadataProcessorAyncWrapper::Process, processor_.get()}); +} + std::shared_ptr SslServerCredentials( const SslServerCredentialsOptions& options) { std::vector pem_key_cert_pairs; diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index b9803f107e..2707336d7f 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -34,12 +34,33 @@ #ifndef GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H #define GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H +#include + #include #include +#include namespace grpc { +class AuthMetadataProcessorAyncWrapper GRPC_FINAL { + public: + static void Process(void* self, grpc_auth_context* context, + const grpc_metadata* md, size_t md_count, + grpc_process_auth_metadata_done_cb cb, void* user_data); + + AuthMetadataProcessorAyncWrapper( + const std::shared_ptr& processor) + : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {} + + private: + void ProcessAsync(grpc_auth_context* context, const grpc_metadata* md, + size_t md_count, grpc_process_auth_metadata_done_cb cb, + void* user_data); + std::unique_ptr thread_pool_; + std::shared_ptr processor_; +}; + class SecureServerCredentials GRPC_FINAL : public ServerCredentials { public: explicit SecureServerCredentials(grpc_server_credentials* creds) @@ -51,8 +72,12 @@ class SecureServerCredentials GRPC_FINAL : public ServerCredentials { int AddPortToServer(const grpc::string& addr, grpc_server* server) GRPC_OVERRIDE; + void SetAuthMetadataProcessor( + const std::shared_ptr& processor) GRPC_OVERRIDE; + private: - grpc_server_credentials* const creds_; + grpc_server_credentials* creds_; + std::unique_ptr processor_; }; } // namespace grpc diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc index 075d4ce8c9..e208189720 100644 --- a/test/cpp/common/secure_auth_context_test.cc +++ b/test/cpp/common/secure_auth_context_test.cc @@ -57,12 +57,12 @@ TEST_F(SecureAuthContextTest, EmptyContext) { TEST_F(SecureAuthContextTest, Properties) { grpc_auth_context* ctx = grpc_auth_context_create(NULL); - grpc_auth_context_add_cstring_property(ctx, "name", "chapi"); - grpc_auth_context_add_cstring_property(ctx, "name", "chapo"); - grpc_auth_context_add_cstring_property(ctx, "foo", "bar"); - EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name")); - SecureAuthContext context(ctx); + context.AddProperty("name", "chapi"); + context.AddProperty("name", "chapo"); + context.AddProperty("foo", "bar"); + EXPECT_TRUE(context.SetPeerIdentityPropertyName("name")); + std::vector peer_identity = context.GetPeerIdentity(); EXPECT_EQ(2u, peer_identity.size()); EXPECT_EQ("chapi", peer_identity[0]); @@ -75,12 +75,12 @@ TEST_F(SecureAuthContextTest, Properties) { TEST_F(SecureAuthContextTest, Iterators) { grpc_auth_context* ctx = grpc_auth_context_create(NULL); - grpc_auth_context_add_cstring_property(ctx, "name", "chapi"); - grpc_auth_context_add_cstring_property(ctx, "name", "chapo"); - grpc_auth_context_add_cstring_property(ctx, "foo", "bar"); - EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name")); - SecureAuthContext context(ctx); + context.AddProperty("name", "chapi"); + context.AddProperty("name", "chapo"); + context.AddProperty("foo", "bar"); + EXPECT_TRUE(context.SetPeerIdentityPropertyName("name")); + AuthPropertyIterator iter = context.begin(); EXPECT_TRUE(context.end() != iter); AuthProperty p0 = *iter; -- cgit v1.2.3 From 5941335be3700ea9bfe137b2eeccf9cba0540300 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Thu, 13 Aug 2015 22:03:56 -0700 Subject: Fixing lifetime of input metadata issue. --- src/cpp/server/secure_server_credentials.cc | 23 ++++++++++++----------- src/cpp/server/secure_server_credentials.h | 6 +++--- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index bdb7ba6e48..ecc8ae85b2 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -46,24 +46,25 @@ namespace grpc { void AuthMetadataProcessorAyncWrapper::Process( void* self, grpc_auth_context* context, const grpc_metadata* md, size_t md_count, grpc_process_auth_metadata_done_cb cb, void* user_data) { - AuthMetadataProcessorAyncWrapper* instance = - reinterpret_cast(self); + auto* instance = reinterpret_cast(self); + auto* metadata(new Metadata); + for (size_t i = 0; i < md_count; i++) { + metadata->insert(std::make_pair( + md[i].key, grpc::string(md[i].value, md[i].value_length))); + } instance->thread_pool_->Add( std::bind(&AuthMetadataProcessorAyncWrapper::ProcessAsync, instance, - context, md, md_count, cb, user_data)); + context, metadata, cb, user_data)); } void AuthMetadataProcessorAyncWrapper::ProcessAsync( - grpc_auth_context* ctx, const grpc_metadata* md, size_t md_count, + grpc_auth_context* ctx, + Metadata* metadata, grpc_process_auth_metadata_done_cb cb, void* user_data) { + std::unique_ptr metadata_deleter(metadata); SecureAuthContext context(ctx); - std::multimap metadata; - for (size_t i = 0; i < md_count; i++) { - metadata.insert(std::make_pair( - md[i].key, grpc::string(md[i].value, md[i].value_length))); - } - std::multimap consumed_metadata; - bool ok = processor_->Process(metadata, &context, &consumed_metadata); + Metadata consumed_metadata; + bool ok = processor_->Process(*metadata, &context, &consumed_metadata); if (ok) { std::vector consumed_md(consumed_metadata.size()); for (const auto& entry : consumed_metadata) { diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index 2707336d7f..22fd9e2cae 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -54,9 +54,9 @@ class AuthMetadataProcessorAyncWrapper GRPC_FINAL { : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {} private: - void ProcessAsync(grpc_auth_context* context, const grpc_metadata* md, - size_t md_count, grpc_process_auth_metadata_done_cb cb, - void* user_data); + typedef std::multimap Metadata; + void ProcessAsync(grpc_auth_context* context, Metadata* auth_metadata, + grpc_process_auth_metadata_done_cb cb, void* user_data); std::unique_ptr thread_pool_; std::shared_ptr processor_; }; -- cgit v1.2.3 From d3920a28c6c082d5bc247471d566473375a4eb9f Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Thu, 13 Aug 2015 22:33:58 -0700 Subject: Fixing build after sync with upstream master. --- src/cpp/server/secure_server_credentials.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index ecc8ae85b2..e5f5c3041c 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -71,7 +71,8 @@ void AuthMetadataProcessorAyncWrapper::ProcessAsync( consumed_md.push_back({entry.first.c_str(), entry.second.data(), entry.second.size(), - {{nullptr, nullptr, nullptr}}}); + 0, + {{nullptr, nullptr, nullptr, nullptr}}}); } cb(user_data, &consumed_md[0], consumed_md.size(), 1); } else { -- cgit v1.2.3 From bf25bb01bbed3c3a58649424bc08fd187d147645 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Fri, 14 Aug 2015 12:36:11 -0700 Subject: Few improvements: - Guarantee the lifetime of objects passed to the processor. - Add an option for implementers of the processor to make it non-blocking. --- include/grpc++/auth_metadata_processor.h | 4 ++++ include/grpc/grpc_security.h | 5 ++-- src/core/security/server_auth_filter.c | 8 +++---- src/cpp/server/secure_server_credentials.cc | 37 ++++++++++++++++++----------- src/cpp/server/secure_server_credentials.h | 5 ++-- 5 files changed, 37 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/include/grpc++/auth_metadata_processor.h b/include/grpc++/auth_metadata_processor.h index e077ec0c60..45030a6a45 100644 --- a/include/grpc++/auth_metadata_processor.h +++ b/include/grpc++/auth_metadata_processor.h @@ -45,6 +45,10 @@ class AuthMetadataProcessor { public: virtual ~AuthMetadataProcessor() {} + // If this method returns true, the Process function will be scheduled in + // a different thread as the one processing the call. + virtual bool IsBlocking() const { return true; } + // context is read/write: it contains the properties of the channel peer and // it is the job of the Process method to augment it with properties derived // from the passed-in auth_metadata. diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 640c1fda98..c1e5afd3a4 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -286,9 +286,10 @@ typedef void (*grpc_process_auth_metadata_done_cb)( typedef struct { /* The context object is read/write: it contains the properties of the channel peer and it is the job of the process function to augment it with - properties derived from the passed-in metadata. */ + properties derived from the passed-in metadata. + The lifetime of these objects is guaranteed until cb is invoked. */ void (*process)(void *state, grpc_auth_context *context, - const grpc_metadata *md, size_t md_count, + const grpc_metadata *md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void *user_data); void *state; } grpc_auth_metadata_processor; diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c index 2fc689caec..98d7788c83 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; @@ -124,6 +125,7 @@ static void on_md_processing_done(void *user_data, GRPC_STATUS_UNAUTHENTICATED, &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) { @@ -135,17 +137,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/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index e5f5c3041c..fab538f1c4 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -44,27 +44,36 @@ namespace grpc { void AuthMetadataProcessorAyncWrapper::Process( - void* self, grpc_auth_context* context, const grpc_metadata* md, - size_t md_count, grpc_process_auth_metadata_done_cb cb, void* user_data) { - auto* instance = reinterpret_cast(self); - auto* metadata(new Metadata); - for (size_t i = 0; i < md_count; i++) { - metadata->insert(std::make_pair( - md[i].key, grpc::string(md[i].value, md[i].value_length))); + 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(wrapper); + if (w->processor_ == nullptr) { + // Early exit. + cb(user_data, NULL, 0, 1); + 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); } - instance->thread_pool_->Add( - std::bind(&AuthMetadataProcessorAyncWrapper::ProcessAsync, instance, - context, metadata, cb, user_data)); } -void AuthMetadataProcessorAyncWrapper::ProcessAsync( +void AuthMetadataProcessorAyncWrapper::InvokeProcessor( grpc_auth_context* ctx, - Metadata* metadata, + const grpc_metadata* md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data) { - std::unique_ptr metadata_deleter(metadata); + Metadata metadata; + for (size_t i = 0; i < num_md; i++) { + metadata.insert(std::make_pair( + md[i].key, grpc::string(md[i].value, md[i].value_length))); + } SecureAuthContext context(ctx); Metadata consumed_metadata; - bool ok = processor_->Process(*metadata, &context, &consumed_metadata); + bool ok = processor_->Process(metadata, &context, &consumed_metadata); if (ok) { std::vector consumed_md(consumed_metadata.size()); for (const auto& entry : consumed_metadata) { diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index 22fd9e2cae..f2709637b1 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -55,8 +55,9 @@ class AuthMetadataProcessorAyncWrapper GRPC_FINAL { private: typedef std::multimap Metadata; - void ProcessAsync(grpc_auth_context* context, Metadata* auth_metadata, - grpc_process_auth_metadata_done_cb cb, void* user_data); + void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md, + size_t md_count, grpc_process_auth_metadata_done_cb cb, + void* user_data); std::unique_ptr thread_pool_; std::shared_ptr processor_; }; -- cgit v1.2.3 From 8da211f638ebe36abe79aa068229799a536e4243 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Fri, 14 Aug 2015 12:57:42 -0700 Subject: Forgot to commit this file... --- src/cpp/server/secure_server_credentials.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index f2709637b1..07d0f9374a 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -45,8 +45,8 @@ namespace grpc { class AuthMetadataProcessorAyncWrapper GRPC_FINAL { public: - static void Process(void* self, grpc_auth_context* context, - const grpc_metadata* md, size_t md_count, + 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( @@ -56,7 +56,7 @@ class AuthMetadataProcessorAyncWrapper GRPC_FINAL { private: typedef std::multimap Metadata; void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md, - size_t md_count, grpc_process_auth_metadata_done_cb cb, + size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data); std::unique_ptr thread_pool_; std::shared_ptr processor_; -- cgit v1.2.3 From bc265583d6a1810289568d08a577f213bedcb577 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Mon, 17 Aug 2015 13:23:05 -0700 Subject: Addressing comments. Thanks Yang! --- include/grpc++/auth_metadata_processor.h | 7 +++++-- include/grpc++/server_credentials.h | 3 ++- src/cpp/server/insecure_server_credentials.cc | 6 +++++- 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/include/grpc++/auth_metadata_processor.h b/include/grpc++/auth_metadata_processor.h index 45030a6a45..db4beafeff 100644 --- a/include/grpc++/auth_metadata_processor.h +++ b/include/grpc++/auth_metadata_processor.h @@ -46,14 +46,17 @@ class AuthMetadataProcessor { virtual ~AuthMetadataProcessor() {} // If this method returns true, the Process function will be scheduled in - // a different thread as the one processing the call. + // a different thread from the one processing the call. virtual bool IsBlocking() const { return true; } // context is read/write: it contains the properties of the channel peer and // it is the job of the Process method to augment it with properties derived // from the passed-in auth_metadata. + // consumed_auth_metadata needs to be filled with metadata that has been + // consumed by the processor and will be removed from the call. + // Returns true if successful. virtual bool Process( - std::multimap& auth_metadata, + const std::multimap& auth_metadata, AuthContext* context, std::multimap* consumed_auth_metadata) = 0; }; diff --git a/include/grpc++/server_credentials.h b/include/grpc++/server_credentials.h index d540b95e21..bcc335b7d5 100644 --- a/include/grpc++/server_credentials.h +++ b/include/grpc++/server_credentials.h @@ -56,7 +56,8 @@ class ServerCredentials { virtual int AddPortToServer(const grpc::string& addr, grpc_server* server) = 0; - // Has to be called before the server is started. + // This method is not thread-safe and has to be called before the server is + // started. The last call to this function wins. virtual void SetAuthMetadataProcessor( const std::shared_ptr& processor) = 0; }; diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc index 96458477f0..12807e70e7 100644 --- a/src/cpp/server/insecure_server_credentials.cc +++ b/src/cpp/server/insecure_server_credentials.cc @@ -34,6 +34,7 @@ #include #include +#include namespace grpc { namespace { @@ -44,7 +45,10 @@ class InsecureServerCredentialsImpl GRPC_FINAL : public ServerCredentials { return grpc_server_add_insecure_http2_port(server, addr.c_str()); } void SetAuthMetadataProcessor( - const std::shared_ptr& processor) GRPC_OVERRIDE {} + const std::shared_ptr& processor) GRPC_OVERRIDE { + (void)processor; + GPR_ASSERT(0); // Should not be called on InsecureServerCredentials. + } }; } // namespace -- cgit v1.2.3 From cb951f6c57c35d26ff8b643c4a498be397be6750 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 18 Aug 2015 17:38:11 -0700 Subject: Split server shutdown into tryShutdown and forceShutdown --- src/node/ext/server.cc | 50 +++++++++++++++++++----------------- src/node/ext/server.h | 3 ++- src/node/src/server.js | 21 ++++++++++++--- src/node/test/call_test.js | 2 +- src/node/test/end_to_end_test.js | 2 +- src/node/test/health_test.js | 2 +- src/node/test/interop_sanity_test.js | 2 +- src/node/test/math_client_test.js | 2 +- src/node/test/server_test.js | 27 ++++++++++++++++++- src/node/test/surface_test.js | 16 ++++++------ 10 files changed, 86 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index 8e39644846..c32e3ae918 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -139,8 +139,11 @@ void Server::Init(Handle exports) { NanSetPrototypeTemplate(tpl, "start", NanNew(Start)->GetFunction()); - NanSetPrototypeTemplate(tpl, "shutdown", - NanNew(Shutdown)->GetFunction()); + NanSetPrototypeTemplate(tpl, "tryShutdown", + NanNew(TryShutdown)->GetFunction()); + NanSetPrototypeTemplate( + tpl, "forceShutdown", + NanNew(ForceShutdown)->GetFunction()); NanAssignPersistent(fun_tpl, tpl); Handle ctr = tpl->GetFunction(); @@ -153,14 +156,13 @@ bool Server::HasInstance(Handle val) { } void Server::ShutdownServer() { - if (this->wrapped_server != NULL) { - grpc_server_shutdown_and_notify(this->wrapped_server, - this->shutdown_queue, - NULL); - grpc_completion_queue_pluck(this->shutdown_queue, NULL, - gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - this->wrapped_server = NULL; - } + grpc_server_shutdown_and_notify(this->wrapped_server, + this->shutdown_queue, + NULL); + grpc_server_cancel_all_calls(this->wrapped_server); + grpc_completion_queue_pluck(this->shutdown_queue, NULL, + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + this->wrapped_server = NULL; } NAN_METHOD(Server::New) { @@ -222,9 +224,6 @@ NAN_METHOD(Server::RequestCall) { return NanThrowTypeError("requestCall can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(args.This()); - if (server->wrapped_server == NULL) { - return NanThrowError("requestCall cannot be called on a shut down Server"); - } NewCallOp *op = new NewCallOp(); unique_ptr ops(new OpVec()); ops->push_back(unique_ptr(op)); @@ -256,10 +255,6 @@ NAN_METHOD(Server::AddHttp2Port) { "addHttp2Port's second argument must be ServerCredentials"); } Server *server = ObjectWrap::Unwrap(args.This()); - if (server->wrapped_server == NULL) { - return NanThrowError( - "addHttp2Port cannot be called on a shut down Server"); - } ServerCredentials *creds_object = ObjectWrap::Unwrap( args[1]->ToObject()); grpc_server_credentials *creds = creds_object->GetWrappedServerCredentials(); @@ -281,21 +276,30 @@ NAN_METHOD(Server::Start) { return NanThrowTypeError("start can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(args.This()); - if (server->wrapped_server == NULL) { - return NanThrowError("start cannot be called on a shut down Server"); - } grpc_server_start(server->wrapped_server); NanReturnUndefined(); } -NAN_METHOD(ShutdownCallback) { +NAN_METHOD(Server::TryShutdown) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("tryShutdown can only be called on a Server"); + } + Server *server = ObjectWrap::Unwrap(args.This()); + unique_ptr ops(new OpVec()); + grpc_server_shutdown_and_notify( + server->wrapped_server, + CompletionQueueAsyncWorker::GetQueue(), + new struct tag(new NanCallback(args[0].As()), ops.release(), + shared_ptr(nullptr))); + CompletionQueueAsyncWorker::Next(); NanReturnUndefined(); } -NAN_METHOD(Server::Shutdown) { +NAN_METHOD(Server::ForceShutdown) { NanScope(); if (!HasInstance(args.This())) { - return NanThrowTypeError("shutdown can only be called on a Server"); + return NanThrowTypeError("forceShutdown can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(args.This()); server->ShutdownServer(); diff --git a/src/node/ext/server.h b/src/node/ext/server.h index faab7e3418..e7d5c3fb11 100644 --- a/src/node/ext/server.h +++ b/src/node/ext/server.h @@ -67,7 +67,8 @@ class Server : public ::node::ObjectWrap { static NAN_METHOD(RequestCall); static NAN_METHOD(AddHttp2Port); static NAN_METHOD(Start); - static NAN_METHOD(Shutdown); + static NAN_METHOD(TryShutdown); + static NAN_METHOD(ForceShutdown); static NanCallback *constructor; static v8::Persistent fun_tpl; diff --git a/src/node/src/server.js b/src/node/src/server.js index 8b86173f08..f2520c3c97 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -613,11 +613,26 @@ function Server(options) { } server.requestCall(handleNewCall); }; + + /** + * Gracefully shuts down the server. The server will stop receiving new calls, + * and any pending calls will complete. The callback will be called when all + * pending calls have completed and the server is fully shut down. This method + * is idempotent with itself and forceShutdown. + * @param {function()} callback The shutdown complete callback + */ + this.tryShutdown = function(callback) { + server.tryShutdown(callback); + }; + /** - * Shuts down the server. + * Forcibly shuts down the server. The server will stop receiving new calls + * and cancel all pending calls. When it returns, the server has shut down. + * This method is idempotent with itself and tryShutdown, and it will trigger + * any outstanding tryShutdown callbacks. */ - this.shutdown = function() { - server.shutdown(); + this.forceShutdown = function() { + server.forceShutdown(); }; } diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js index 8d0f20b074..e7f071bcd5 100644 --- a/src/node/test/call_test.js +++ b/src/node/test/call_test.js @@ -61,7 +61,7 @@ describe('call', function() { channel = new grpc.Channel('localhost:' + port, insecureCreds); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); describe('constructor', function() { it('should reject anything less than 3 arguments', function() { diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js index 7574d98b8a..4b8da3bfb1 100644 --- a/src/node/test/end_to_end_test.js +++ b/src/node/test/end_to_end_test.js @@ -70,7 +70,7 @@ describe('end-to-end', function() { channel = new grpc.Channel('localhost:' + port_num, insecureCreds); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('should start and end a request without error', function(complete) { var done = multiDone(complete, 2); diff --git a/src/node/test/health_test.js b/src/node/test/health_test.js index be4ef1d251..22c58d3956 100644 --- a/src/node/test/health_test.js +++ b/src/node/test/health_test.js @@ -61,7 +61,7 @@ describe('Health Checking', function() { grpc.Credentials.createInsecure()); }); after(function() { - healthServer.shutdown(); + healthServer.forceShutdown(); }); it('should say an enabled service is SERVING', function(done) { healthClient.check({service: ''}, function(err, response) { diff --git a/src/node/test/interop_sanity_test.js b/src/node/test/interop_sanity_test.js index 0a5eb29c0c..2ca07c1d50 100644 --- a/src/node/test/interop_sanity_test.js +++ b/src/node/test/interop_sanity_test.js @@ -51,7 +51,7 @@ describe('Interop tests', function() { done(); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); // This depends on not using a binary stream it('should pass empty_unary', function(done) { diff --git a/src/node/test/math_client_test.js b/src/node/test/math_client_test.js index ef01870a4c..80b0c5ff2a 100644 --- a/src/node/test/math_client_test.js +++ b/src/node/test/math_client_test.js @@ -59,7 +59,7 @@ describe('Math client', function() { done(); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('should handle a single request', function(done) { var arg = {dividend: 7, divisor: 4}; diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js index 20c9a07ffa..4670a62efa 100644 --- a/src/node/test/server_test.js +++ b/src/node/test/server_test.js @@ -90,7 +90,7 @@ describe('server', function() { server.addHttp2Port('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('should start without error', function() { assert.doesNotThrow(function() { @@ -98,4 +98,29 @@ describe('server', function() { }); }); }); + describe('shutdown', function() { + var server; + beforeEach(function() { + server = new grpc.Server(); + server.addHttp2Port('0.0.0.0:0', grpc.ServerCredentials.createInsecure()); + server.start(); + }); + afterEach(function() { + server.forceShutdown(); + }); + it('tryShutdown should shutdown successfully', function(done) { + server.tryShutdown(done); + }); + it.only('forceShutdown should shutdown successfully', function() { + server.forceShutdown(); + }); + it('tryShutdown should be idempotent', function(done) { + server.tryShutdown(done); + server.tryShutdown(function() {}); + }); + it('forceShutdown should be idempotent', function() { + server.forceShutdown(); + server.forceShutdown(); + }); + }); }); diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index 52515cc8e7..d12ba0465e 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -104,7 +104,7 @@ describe('Server.prototype.addProtoService', function() { server = new grpc.Server(); }); afterEach(function() { - server.shutdown(); + server.forceShutdown(); }); it('Should succeed with a single service', function() { assert.doesNotThrow(function() { @@ -148,7 +148,7 @@ describe('Client#$waitForReady', function() { client = new Client('localhost:' + port, grpc.Credentials.createInsecure()); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('should complete when called alone', function(done) { client.$waitForReady(Infinity, function(error) { @@ -203,7 +203,7 @@ describe('Echo service', function() { server.start(); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('should echo the recieved message directly', function(done) { client.echo({value: 'test value', value2: 3}, function(error, response) { @@ -248,7 +248,7 @@ describe('Generic client and server', function() { grpc.Credentials.createInsecure()); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('Should respond with a capitalized string', function(done) { client.capitalize('abc', function(err, response) { @@ -296,7 +296,7 @@ describe('Echo metadata', function() { server.start(); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('with unary call', function(done) { var call = client.unary({}, function(err, data) { @@ -419,7 +419,7 @@ describe('Other conditions', function() { server.start(); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('channel.getTarget should be available', function() { assert.strictEqual(typeof client.channel.getTarget(), 'string'); @@ -681,7 +681,7 @@ describe('Other conditions', function() { }); afterEach(function() { console.log('Shutting down server'); - proxy.shutdown(); + proxy.forceShutdown(); }); describe('Cancellation', function() { it('With a unary call', function(done) { @@ -845,7 +845,7 @@ describe('Cancelling surface client', function() { server.start(); }); after(function() { - server.shutdown(); + server.forceShutdown(); }); it('Should correctly cancel a unary call', function(done) { var call = client.div({'divisor': 0, 'dividend': 0}, function(err, resp) { -- cgit v1.2.3 From 8a2ab3b249558f5bf4c6e4ef938c68b106750828 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 19 Aug 2015 10:34:59 -0700 Subject: Removed errant NULL setting --- src/node/ext/server.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index c32e3ae918..57c4310490 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -120,7 +120,7 @@ Server::Server(grpc_server *server) : wrapped_server(server) { Server::~Server() { this->ShutdownServer(); grpc_completion_queue_shutdown(this->shutdown_queue); - grpc_server_destroy(wrapped_server); + grpc_server_destroy(this->wrapped_server); grpc_completion_queue_destroy(this->shutdown_queue); } @@ -162,7 +162,6 @@ void Server::ShutdownServer() { grpc_server_cancel_all_calls(this->wrapped_server); grpc_completion_queue_pluck(this->shutdown_queue, NULL, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); - this->wrapped_server = NULL; } NAN_METHOD(Server::New) { -- cgit v1.2.3 From c5dac97bd3b1e87b228d0d130ce2cb457297fdd0 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Wed, 19 Aug 2015 11:49:53 -0700 Subject: Added a test, enabled other tests --- src/node/test/server_test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js index 4670a62efa..9574709f60 100644 --- a/src/node/test/server_test.js +++ b/src/node/test/server_test.js @@ -111,7 +111,7 @@ describe('server', function() { it('tryShutdown should shutdown successfully', function(done) { server.tryShutdown(done); }); - it.only('forceShutdown should shutdown successfully', function() { + it('forceShutdown should shutdown successfully', function() { server.forceShutdown(); }); it('tryShutdown should be idempotent', function(done) { @@ -122,5 +122,9 @@ describe('server', function() { server.forceShutdown(); server.forceShutdown(); }); + it('forceShutdown should trigger tryShutdown', function(done) { + server.tryShutdown(done); + server.forceShutdown(); + }); }); }); -- cgit v1.2.3 From 84e3cdeb970dae5840ab0453536a7a53428a8e65 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 20 Aug 2015 11:27:05 -0700 Subject: Added new Metadata class to abstract over internal representation and normalize keys --- src/node/index.js | 15 ++-- src/node/interop/interop_client.js | 8 +- src/node/src/client.js | 65 +++++++++----- src/node/src/metadata.js | 167 +++++++++++++++++++++++++++++++++++ src/node/src/server.js | 60 +++++++------ src/node/test/health_test.js | 2 +- src/node/test/metadata_test.js | 172 +++++++++++++++++++++++++++++++++++++ src/node/test/surface_test.js | 61 ++++++------- 8 files changed, 460 insertions(+), 90 deletions(-) create mode 100644 src/node/src/metadata.js create mode 100644 src/node/test/metadata_test.js (limited to 'src') diff --git a/src/node/index.js b/src/node/index.js index 889b0ac0e9..51d3fa590c 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); }); }; @@ -129,6 +125,11 @@ exports.getGoogleAuthDelegate = function getGoogleAuthDelegate(credential) { */ exports.Server = server.Server; +/** + * @see module:src/metadata + */ +exports.Metadata = Metadata; + /** * Status name to code number mapping */ diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js index 612dcf01f6..8fb8d66920 100644 --- a/src/node/interop/interop_client.js +++ b/src/node/interop/interop_client.js @@ -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) { diff --git a/src/node/src/client.js b/src/node/src/client.js index 48fe0dd3b7..6fafad251a 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -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; @@ -254,8 +256,7 @@ 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 */ @@ -264,7 +265,9 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { var emitter = new EventEmitter(); 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(); @@ -281,7 +284,8 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { var client_batch = {}; var message = serialize(argument); 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; @@ -292,7 +296,8 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { if (response.status.code !== grpc.status.OK) { var error = new Error(response.status.details); error.code = response.status.code; - error.metadata = response.status.metadata; + error.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); callback(error); return; } else { @@ -302,7 +307,8 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { return; } } - emitter.emit('metadata', response.metadata); + emitter.emit('metadata', Metadata._fromCoreRepresentation( + response.metadata)); callback(null, deserialize(response.read)); }); }); @@ -326,7 +332,7 @@ 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 @@ -335,7 +341,9 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { /* jshint validthis: true */ 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) { @@ -345,7 +353,8 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { 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) { @@ -353,7 +362,8 @@ 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; @@ -363,7 +373,8 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { if (response.status.code !== grpc.status.OK) { var error = new Error(response.status.details); error.code = response.status.code; - error.metadata = response.status.metadata; + error.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); callback(error); return; } else { @@ -396,7 +407,7 @@ 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 @@ -405,7 +416,9 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { /* jshint validthis: true */ 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) { @@ -417,7 +430,8 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { var start_batch = {}; var message = serialize(argument); 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; @@ -427,7 +441,8 @@ 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; @@ -436,7 +451,8 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { if (response.status.code !== grpc.status.OK) { var error = new Error(response.status.details); error.code = response.status.code; - error.metadata = response.status.metadata; + error.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); stream.emit('error', error); return; } else { @@ -466,7 +482,7 @@ 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 @@ -475,7 +491,9 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { /* jshint validthis: true */ 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) { @@ -485,7 +503,8 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { 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) { @@ -493,7 +512,8 @@ 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; @@ -502,7 +522,8 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { if (response.status.code !== grpc.status.OK) { var error = new Error(response.status.details); error.code = response.status.code; - error.metadata = response.status.metadata; + error.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); stream.emit('error', error); return; } else { diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js new file mode 100644 index 0000000000..ae7112f36e --- /dev/null +++ b/src/node/src/metadata.js @@ -0,0 +1,167 @@ +/* + * + * 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) { + return _.deburr(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'); + } + } +} + +/** + * 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. + * @param {String} key The key to remove + */ +Metadata.prototype.remove = function(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. + * @param {String} key The key to get + * @return {Array.} The values associated with that key + */ +Metadata.prototype.get = function(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.} 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(); + copy._internal_repr = _.cloneDeep(this._internal_repr); + 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.>} 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.>} The metadata + * @return {Metadata} The new Metadata object + */ +Metadata._fromCoreRepresentation = function(metadata) { + var newMetadata = new 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 5037abae43..5d76b31f15 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,15 +157,17 @@ 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(); } + stream.status.metadata = stream.status.metadata._getCoreRepresentation(); batch[grpc.opType.SEND_STATUS_FROM_SERVER] = stream.status; stream.call.startBatch(batch, function(){}); } @@ -203,7 +211,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 +274,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 +298,15 @@ ServerWritableStream.prototype._write = _write; /** * Send the initial metadata for a writable stream. - * @param {Object>} 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 +431,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 +439,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 +488,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 +517,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 +525,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 +553,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 +610,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 +620,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/health_test.js b/src/node/test/health_test.js index be4ef1d251..5e6a0ba467 100644 --- a/src/node/test/health_test.js +++ b/src/node/test/health_test.js @@ -39,7 +39,7 @@ var health = require('../health_check/health.js'); var grpc = require('../'); -describe('Health Checking', function() { +describe.only('Health Checking', function() { var statusMap = { '': { '': 'SERVING', diff --git a/src/node/test/metadata_test.js b/src/node/test/metadata_test.js new file mode 100644 index 0000000000..f1859b674d --- /dev/null +++ b/src/node/test/metadata_test.js @@ -0,0 +1,172 @@ +/* + * + * 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('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('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('does not normalize keys', function() { + metadata.add('key', 'value'); + metadata.remove('KEY'); + assert.deepEqual(metadata.get('key'), ['value']); + }); + }); + 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('does not normalize keys', function() { + assert.deepEqual(metadata.get('KEY'), []); + }); + 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 ec7ed87728..c3caa4d5a3 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -262,6 +262,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 +295,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.shutdown(); @@ -301,35 +304,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 +340,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 +358,14 @@ 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(); 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 +374,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 +389,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 +403,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 +412,7 @@ describe('Other conditions', function() { } }); stream.on('end', function() { - stream.end({trailer_present: ['yes']}); + stream.end(trailer_metadata); }); } }); @@ -510,7 +513,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 +522,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 +534,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 +546,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 +555,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 +563,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 +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(); }); }); @@ -583,7 +586,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(); }); }); -- cgit v1.2.3 From e796e1fd7c6a01825745a308309ad8621202e53a Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 20 Aug 2015 11:31:56 -0700 Subject: Re-enabled tests --- src/node/test/health_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/node/test/health_test.js b/src/node/test/health_test.js index 5e6a0ba467..be4ef1d251 100644 --- a/src/node/test/health_test.js +++ b/src/node/test/health_test.js @@ -39,7 +39,7 @@ var health = require('../health_check/health.js'); var grpc = require('../'); -describe.only('Health Checking', function() { +describe('Health Checking', function() { var statusMap = { '': { '': 'SERVING', -- cgit v1.2.3 From f441b3fdf2fb85076380502dd50025246e76130e Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 20 Aug 2015 11:44:52 -0700 Subject: Fixed test and lint errors --- src/node/src/client.js | 20 ++++++++++++-------- src/node/src/metadata.js | 6 ++++-- src/node/src/server.js | 7 +++++-- src/node/test/surface_test.js | 1 + 4 files changed, 22 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/node/src/client.js b/src/node/src/client.js index b90af42054..e1bed3512e 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -294,12 +294,13 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { client_batch[grpc.opType.RECV_MESSAGE] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_batch, function(err, response) { + response.status.metadata = Metadata._fromCoreRepresentation( + response.status.metadata); 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 = Metadata._fromCoreRepresentation( - response.status.metadata); + error.metadata = response.status.metadata; callback(error); return; } else { @@ -371,12 +372,13 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { client_batch[grpc.opType.RECV_MESSAGE] = true; client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true; call.startBatch(client_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); error.code = response.status.code; - error.metadata = Metadata._fromCoreRepresentation( - response.status.metadata); + error.metadata = response.status.metadata; callback(error); return; } else { @@ -451,12 +453,13 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { 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); error.code = response.status.code; - error.metadata = Metadata._fromCoreRepresentation( - response.status.metadata); + error.metadata = response.status.metadata; stream.emit('error', error); return; } else { @@ -522,12 +525,13 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { 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); error.code = response.status.code; - error.metadata = Metadata._fromCoreRepresentation( - response.status.metadata); + error.metadata = response.status.metadata; stream.emit('error', error); return; } else { diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index ae7112f36e..39514b2547 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -139,7 +139,7 @@ Metadata.prototype.clone = function() { var copy = new Metadata(); copy._internal_repr = _.cloneDeep(this._internal_repr); return copy; -} +}; /** * Gets the metadata in the format used by interal code. Intended for internal @@ -160,7 +160,9 @@ Metadata.prototype._getCoreRepresentation = function() { */ Metadata._fromCoreRepresentation = function(metadata) { var newMetadata = new Metadata(); - newMetadata._internal_repr = _.cloneDeep(metadata); + if (metadata) { + newMetadata._internal_repr = _.cloneDeep(metadata); + } return newMetadata; }; diff --git a/src/node/src/server.js b/src/node/src/server.js index 7ef28428b4..b6f162adf8 100644 --- a/src/node/src/server.js +++ b/src/node/src/server.js @@ -167,7 +167,10 @@ function setUpWritable(stream, serialize) { batch[grpc.opType.SEND_INITIAL_METADATA] = (new Metadata())._getCoreRepresentation(); } - stream.status.metadata = stream.status.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(){}); } @@ -181,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; } diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index f000983a4a..c7e63e9814 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -359,6 +359,7 @@ describe('Other conditions', function() { 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; -- cgit v1.2.3 From cc248a27f2e87c0cbc649c78f6db323982a6c7ba Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 20 Aug 2015 14:47:15 -0700 Subject: Added string value validation, modified key normalization and validation --- src/node/src/metadata.js | 10 +++++++++- src/node/test/metadata_test.js | 21 +++++++++++++++++++++ src/node/test/surface_test.js | 18 +++++++++--------- 3 files changed, 39 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index 39514b2547..8e0884acea 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -49,10 +49,14 @@ function Metadata() { } function normalizeKey(key) { - return _.deburr(key).toLowerCase(); + return key.toLowerCase(); } function validate(key, value) { + if (!(/^[a-z\d-]+$/.test(key))) { + throw new Error('Metadata keys must be nonempty strings containing only ' + + 'alphanumeric characters and hyphens'); + } if (_.endsWith(key, '-bin')) { if (!(value instanceof Buffer)) { throw new Error('keys that end with \'-bin\' must have Buffer values'); @@ -62,6 +66,10 @@ function validate(key, 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'); + } } } diff --git a/src/node/test/metadata_test.js b/src/node/test/metadata_test.js index f1859b674d..227fa9c994 100644 --- a/src/node/test/metadata_test.js +++ b/src/node/test/metadata_test.js @@ -59,6 +59,19 @@ describe('Metadata', 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']); @@ -92,6 +105,14 @@ describe('Metadata', 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']); diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index c7e63e9814..7c2a8d7258 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -359,7 +359,7 @@ describe('Other conditions', function() { test_service = test_proto.lookup('TestService'); server = new grpc.Server(); var trailer_metadata = new grpc.Metadata(); - trailer_metadata.add('trailer_present', 'yes'); + trailer_metadata.add('trailer-present', 'yes'); server.addProtoService(test_service, { unary: function(call, cb) { var req = call.request; @@ -514,7 +514,7 @@ describe('Other conditions', function() { assert.ifError(err); }); call.on('status', function(status) { - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -523,7 +523,7 @@ describe('Other conditions', function() { assert(err); }); call.on('status', function(status) { - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -535,7 +535,7 @@ describe('Other conditions', function() { call.write({error: false}); call.end(); call.on('status', function(status) { - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -547,7 +547,7 @@ describe('Other conditions', function() { call.write({error: true}); call.end(); call.on('status', function(status) { - assert.deepEqual(status.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -556,7 +556,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.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -564,7 +564,7 @@ describe('Other conditions', function() { var call = client.serverStream({error: true}); call.on('data', function(){}); call.on('error', function(error) { - assert.deepEqual(error.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(error.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -576,7 +576,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.get('trailer_present'), ['yes']); + assert.deepEqual(status.metadata.get('trailer-present'), ['yes']); done(); }); }); @@ -587,7 +587,7 @@ describe('Other conditions', function() { call.end(); call.on('data', function(){}); call.on('error', function(error) { - assert.deepEqual(error.metadata.get('trailer_present'), ['yes']); + assert.deepEqual(error.metadata.get('trailer-present'), ['yes']); done(); }); }); -- cgit v1.2.3 From 6b8a3a74f27a81940023ba3a8c822078d51621ee Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 20 Aug 2015 14:51:59 -0700 Subject: Normalize keys when getting and removing metadata items --- src/node/src/metadata.js | 6 ++++-- src/node/test/metadata_test.js | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index 8e0884acea..a7b1ee3810 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -102,21 +102,23 @@ Metadata.prototype.add = function(key, value) { }; /** - * Remove the given key and any associated values. + * 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. + * Gets a list of all values associated with the key. Normalizes the key. * @param {String} key The key to get * @return {Array.} 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 { diff --git a/src/node/test/metadata_test.js b/src/node/test/metadata_test.js index 227fa9c994..86383f1bad 100644 --- a/src/node/test/metadata_test.js +++ b/src/node/test/metadata_test.js @@ -135,10 +135,10 @@ describe('Metadata', function() { metadata.remove('key'); assert.deepEqual(metadata.get('key'), []); }); - it('does not normalize keys', function() { + it('Normalizes keys', function() { metadata.add('key', 'value'); metadata.remove('KEY'); - assert.deepEqual(metadata.get('key'), ['value']); + assert.deepEqual(metadata.get('key'), []); }); }); describe('#get', function() { @@ -150,8 +150,8 @@ describe('Metadata', function() { it('gets all values associated with a key', function() { assert.deepEqual(metadata.get('key'), ['value1', 'value2']); }); - it('does not normalize keys', function() { - assert.deepEqual(metadata.get('KEY'), []); + 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'), []); -- cgit v1.2.3 From 01a772028041577099e406019b731b3540a6fb2f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 20 Aug 2015 15:40:03 -0700 Subject: Moved key character check to before key transformation --- src/node/src/metadata.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index a7b1ee3810..d4a8b2669f 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -49,14 +49,14 @@ function Metadata() { } 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 (!(/^[a-z\d-]+$/.test(key))) { - throw new Error('Metadata keys must be nonempty strings containing only ' + - 'alphanumeric characters and hyphens'); - } if (_.endsWith(key, '-bin')) { if (!(value instanceof Buffer)) { throw new Error('keys that end with \'-bin\' must have Buffer values'); -- cgit v1.2.3 From 5df6ebd0c585756467c128dc20b60be515163f5e Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 20 Aug 2015 15:52:57 -0700 Subject: Replaced toLowerCase with local-insensitive downcasing function --- src/node/src/metadata.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index d4a8b2669f..77ababb65d 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -48,12 +48,19 @@ function Metadata() { this._internal_repr = {}; } +function downcaseString(str) { + var capitals = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + var lowercase = 'abcdefghijklmnopqrstuvwxyz'; + var charMap = _.zipObject(capitals, lowercase); + return str.replace(/[A-Z]/g, _.curry(_.get)(charMap)); +} + 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(); + return downcaseString(key); } function validate(key, value) { -- cgit v1.2.3 From 61bb21ab2c18fb7db403ae4c762c719d42c11680 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 21 Aug 2015 09:15:19 -0700 Subject: Reversed toLowerCase removal --- src/node/src/metadata.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'src') diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index 77ababb65d..d4a8b2669f 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -48,19 +48,12 @@ function Metadata() { this._internal_repr = {}; } -function downcaseString(str) { - var capitals = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; - var lowercase = 'abcdefghijklmnopqrstuvwxyz'; - var charMap = _.zipObject(capitals, lowercase); - return str.replace(/[A-Z]/g, _.curry(_.get)(charMap)); -} - 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 downcaseString(key); + return key.toLowerCase(); } function validate(key, value) { -- cgit v1.2.3 From dde19d835e024aa39a778990b5efffef58b4fb8d Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 21 Aug 2015 09:24:33 -0700 Subject: Allowed underscore in metadata keys --- src/node/src/metadata.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index d4a8b2669f..65fd91f367 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -49,7 +49,7 @@ function Metadata() { } function normalizeKey(key) { - if (!(/^[A-Za-z\d-]+$/.test(key))) { + if (!(/^[A-Za-z\d_-]+$/.test(key))) { throw new Error('Metadata keys must be nonempty strings containing only ' + 'alphanumeric characters and hyphens'); } -- cgit v1.2.3 From 592e7f2dd0c059468de6377e8d6bc0d61fe2dd2c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 21 Aug 2015 10:45:48 -0700 Subject: Refactor Endpoint API - Allow reads to complete immediately - Unify read/write signatures - Simplify memory management to allow future optimization work --- include/grpc/support/slice_buffer.h | 2 + src/core/httpcli/httpcli.c | 95 +++--- src/core/iomgr/endpoint.c | 17 +- src/core/iomgr/endpoint.h | 51 ++- src/core/iomgr/tcp_posix.c | 520 ++++++++++------------------- src/core/security/secure_endpoint.c | 188 ++++++----- src/core/security/secure_transport_setup.c | 119 ++++--- src/core/support/slice_buffer.c | 22 ++ src/core/transport/chttp2/internal.h | 10 +- src/core/transport/chttp2/writing.c | 21 +- src/core/transport/chttp2_transport.c | 125 +++---- test/core/bad_client/bad_client.c | 17 +- test/core/iomgr/endpoint_tests.c | 204 ++++++----- test/core/iomgr/tcp_posix_test.c | 147 ++++---- test/core/security/secure_endpoint_test.c | 55 +-- 15 files changed, 734 insertions(+), 859 deletions(-) (limited to 'src') diff --git a/include/grpc/support/slice_buffer.h b/include/grpc/support/slice_buffer.h index ec048e8c91..04db003ac5 100644 --- a/include/grpc/support/slice_buffer.h +++ b/include/grpc/support/slice_buffer.h @@ -86,6 +86,8 @@ void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb); void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b); /* move all of the elements of src into dst */ void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst); +/* remove n bytes from the end of a slice buffer */ +void gpr_slice_buffer_trim_end(gpr_slice_buffer *src, size_t n); #ifdef __cplusplus } diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c index 9012070e8e..1e38479eb1 100644 --- a/src/core/httpcli/httpcli.c +++ b/src/core/httpcli/httpcli.c @@ -61,6 +61,10 @@ typedef struct { grpc_httpcli_context *context; grpc_pollset *pollset; grpc_iomgr_object iomgr_obj; + gpr_slice_buffer incoming; + gpr_slice_buffer outgoing; + grpc_iomgr_closure on_read; + grpc_iomgr_closure done_write; } internal_request; static grpc_httpcli_get_override g_get_override = NULL; @@ -99,73 +103,70 @@ static void finish(internal_request *req, int success) { gpr_slice_unref(req->request_text); gpr_free(req->host); grpc_iomgr_unregister_object(&req->iomgr_obj); + gpr_slice_buffer_destroy(&req->incoming); + gpr_slice_buffer_destroy(&req->outgoing); gpr_free(req); } -static void on_read(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status status) { +static void on_read(void *user_data, int success); + +static void do_read(internal_request *req) { + switch (grpc_endpoint_read(req->ep, &req->incoming, &req->on_read)) { + case GRPC_ENDPOINT_DONE: + on_read(req, 1); + break; + case GRPC_ENDPOINT_PENDING: + break; + case GRPC_ENDPOINT_ERROR: + on_read(req, 0); + break; + } +} + +static void on_read(void *user_data, int success) { internal_request *req = user_data; size_t i; - for (i = 0; i < nslices; i++) { - if (GPR_SLICE_LENGTH(slices[i])) { + for (i = 0; i < req->incoming.count; i++) { + if (GPR_SLICE_LENGTH(req->incoming.slices[i])) { req->have_read_byte = 1; - if (!grpc_httpcli_parser_parse(&req->parser, slices[i])) { + if (!grpc_httpcli_parser_parse(&req->parser, req->incoming.slices[i])) { finish(req, 0); - goto done; + return; } } } - switch (status) { - case GRPC_ENDPOINT_CB_OK: - grpc_endpoint_notify_on_read(req->ep, on_read, req); - break; - case GRPC_ENDPOINT_CB_EOF: - case GRPC_ENDPOINT_CB_ERROR: - case GRPC_ENDPOINT_CB_SHUTDOWN: - if (!req->have_read_byte) { - next_address(req); - } else { - finish(req, grpc_httpcli_parser_eof(&req->parser)); - } - break; - } - -done: - for (i = 0; i < nslices; i++) { - gpr_slice_unref(slices[i]); + if (success) { + do_read(req); + } else if (!req->have_read_byte) { + next_address(req); + } else { + finish(req, grpc_httpcli_parser_eof(&req->parser)); } } -static void on_written(internal_request *req) { - grpc_endpoint_notify_on_read(req->ep, on_read, req); -} +static void on_written(internal_request *req) { do_read(req); } -static void done_write(void *arg, grpc_endpoint_cb_status status) { +static void done_write(void *arg, int success) { internal_request *req = arg; - switch (status) { - case GRPC_ENDPOINT_CB_OK: - on_written(req); - break; - case GRPC_ENDPOINT_CB_EOF: - case GRPC_ENDPOINT_CB_SHUTDOWN: - case GRPC_ENDPOINT_CB_ERROR: - next_address(req); - break; + if (success) { + on_written(req); + } else { + next_address(req); } } static void start_write(internal_request *req) { gpr_slice_ref(req->request_text); - switch ( - grpc_endpoint_write(req->ep, &req->request_text, 1, done_write, req)) { - case GRPC_ENDPOINT_WRITE_DONE: + gpr_slice_buffer_add(&req->outgoing, req->request_text); + switch (grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write)) { + case GRPC_ENDPOINT_DONE: on_written(req); break; - case GRPC_ENDPOINT_WRITE_PENDING: + case GRPC_ENDPOINT_PENDING: break; - case GRPC_ENDPOINT_WRITE_ERROR: + case GRPC_ENDPOINT_ERROR: finish(req, 0); break; } @@ -237,6 +238,10 @@ void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset, request->handshaker ? request->handshaker : &grpc_httpcli_plaintext; req->context = context; req->pollset = pollset; + grpc_iomgr_closure_init(&req->on_read, on_read, req); + grpc_iomgr_closure_init(&req->done_write, done_write, req); + gpr_slice_buffer_init(&req->incoming); + gpr_slice_buffer_init(&req->outgoing); gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path); grpc_iomgr_register_object(&req->iomgr_obj, name); gpr_free(name); @@ -270,7 +275,11 @@ void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset, request->handshaker ? request->handshaker : &grpc_httpcli_plaintext; req->context = context; req->pollset = pollset; - gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path); + grpc_iomgr_closure_init(&req->on_read, on_read, req); + grpc_iomgr_closure_init(&req->done_write, done_write, req); + gpr_slice_buffer_init(&req->incoming); + gpr_slice_buffer_init(&req->outgoing); + gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->path); grpc_iomgr_register_object(&req->iomgr_obj, name); gpr_free(name); req->host = gpr_strdup(request->host); diff --git a/src/core/iomgr/endpoint.c b/src/core/iomgr/endpoint.c index 8ee14bce9b..a7878e31dd 100644 --- a/src/core/iomgr/endpoint.c +++ b/src/core/iomgr/endpoint.c @@ -33,17 +33,16 @@ #include "src/core/iomgr/endpoint.h" -void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data) { - ep->vtable->notify_on_read(ep, cb, user_data); +grpc_endpoint_op_status grpc_endpoint_read(grpc_endpoint *ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { + return ep->vtable->read(ep, slices, cb); } -grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { - return ep->vtable->write(ep, slices, nslices, cb, user_data); +grpc_endpoint_op_status grpc_endpoint_write(grpc_endpoint *ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { + return ep->vtable->write(ep, slices, cb); } void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { diff --git a/src/core/iomgr/endpoint.h b/src/core/iomgr/endpoint.h index ea92a500e8..38f1e46d67 100644 --- a/src/core/iomgr/endpoint.h +++ b/src/core/iomgr/endpoint.h @@ -37,6 +37,7 @@ #include "src/core/iomgr/pollset.h" #include "src/core/iomgr/pollset_set.h" #include +#include #include /* An endpoint caps a streaming channel between two communicating processes. @@ -45,31 +46,17 @@ typedef struct grpc_endpoint grpc_endpoint; typedef struct grpc_endpoint_vtable grpc_endpoint_vtable; -typedef enum grpc_endpoint_cb_status { - GRPC_ENDPOINT_CB_OK = 0, /* Call completed successfully */ - GRPC_ENDPOINT_CB_EOF, /* Call completed successfully, end of file reached */ - GRPC_ENDPOINT_CB_SHUTDOWN, /* Call interrupted by shutdown */ - GRPC_ENDPOINT_CB_ERROR /* Call interrupted by socket error */ -} grpc_endpoint_cb_status; - -typedef enum grpc_endpoint_write_status { - GRPC_ENDPOINT_WRITE_DONE, /* completed immediately, cb won't be called */ - GRPC_ENDPOINT_WRITE_PENDING, /* cb will be called when completed */ - GRPC_ENDPOINT_WRITE_ERROR /* write errored out, cb won't be called */ -} grpc_endpoint_write_status; - -typedef void (*grpc_endpoint_read_cb)(void *user_data, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error); -typedef void (*grpc_endpoint_write_cb)(void *user_data, - grpc_endpoint_cb_status error); +typedef enum grpc_endpoint_op_status { + GRPC_ENDPOINT_DONE, /* completed immediately, cb won't be called */ + GRPC_ENDPOINT_PENDING, /* cb will be called when completed */ + GRPC_ENDPOINT_ERROR /* write errored out, cb won't be called */ +} grpc_endpoint_op_status; struct grpc_endpoint_vtable { - void (*notify_on_read)(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data); - grpc_endpoint_write_status (*write)(grpc_endpoint *ep, gpr_slice *slices, - size_t nslices, grpc_endpoint_write_cb cb, - void *user_data); + grpc_endpoint_op_status (*read)(grpc_endpoint *ep, gpr_slice_buffer *slices, + grpc_iomgr_closure *cb); + grpc_endpoint_op_status (*write)(grpc_endpoint *ep, gpr_slice_buffer *slices, + grpc_iomgr_closure *cb); void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset); void (*add_to_pollset_set)(grpc_endpoint *ep, grpc_pollset_set *pollset); void (*shutdown)(grpc_endpoint *ep); @@ -77,9 +64,13 @@ struct grpc_endpoint_vtable { char *(*get_peer)(grpc_endpoint *ep); }; -/* When data is available on the connection, calls the callback with slices. */ -void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data); +/* When data is available on the connection, calls the callback with slices. + Callback success indicates that the endpoint can accept more reads, failure + indicates the endpoint is closed. + Valid slices may be placed into \a slices even on callback success == 0. */ +grpc_endpoint_op_status grpc_endpoint_read( + grpc_endpoint *ep, gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT; char *grpc_endpoint_get_peer(grpc_endpoint *ep); @@ -89,11 +80,9 @@ char *grpc_endpoint_get_peer(grpc_endpoint *ep); returns GRPC_ENDPOINT_WRITE_DONE. Otherwise it returns GRPC_ENDPOINT_WRITE_PENDING and calls cb when the connection is ready for more data. */ -grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data); +grpc_endpoint_op_status grpc_endpoint_write( + grpc_endpoint *ep, gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT; /* Causes any pending read/write callbacks to run immediately with GRPC_ENDPOINT_CB_SHUTDOWN status */ diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index 360e6ebd8c..36ba3a7606 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -61,209 +61,8 @@ #define SENDMSG_FLAGS 0 #endif -/* Holds a slice array and associated state. */ -typedef struct grpc_tcp_slice_state { - gpr_slice *slices; /* Array of slices */ - size_t nslices; /* Size of slices array. */ - ssize_t first_slice; /* First valid slice in array */ - ssize_t last_slice; /* Last valid slice in array */ - gpr_slice working_slice; /* pointer to original final slice */ - int working_slice_valid; /* True if there is a working slice */ - int memory_owned; /* True if slices array is owned */ -} grpc_tcp_slice_state; - int grpc_tcp_trace = 0; -static void slice_state_init(grpc_tcp_slice_state *state, gpr_slice *slices, - size_t nslices, size_t valid_slices) { - state->slices = slices; - state->nslices = nslices; - if (valid_slices == 0) { - state->first_slice = -1; - } else { - state->first_slice = 0; - } - state->last_slice = valid_slices - 1; - state->working_slice_valid = 0; - state->memory_owned = 0; -} - -/* Returns true if there is still available data */ -static int slice_state_has_available(grpc_tcp_slice_state *state) { - return state->first_slice != -1 && state->last_slice >= state->first_slice; -} - -static ssize_t slice_state_slices_allocated(grpc_tcp_slice_state *state) { - if (state->first_slice == -1) { - return 0; - } else { - return state->last_slice - state->first_slice + 1; - } -} - -static void slice_state_realloc(grpc_tcp_slice_state *state, size_t new_size) { - /* TODO(klempner): use realloc instead when first_slice is 0 */ - /* TODO(klempner): Avoid a realloc in cases where it is unnecessary */ - gpr_slice *slices = state->slices; - size_t original_size = slice_state_slices_allocated(state); - size_t i; - gpr_slice *new_slices = gpr_malloc(sizeof(gpr_slice) * new_size); - - for (i = 0; i < original_size; ++i) { - new_slices[i] = slices[i + state->first_slice]; - } - - state->slices = new_slices; - state->last_slice = original_size - 1; - if (original_size > 0) { - state->first_slice = 0; - } else { - state->first_slice = -1; - } - state->nslices = new_size; - - if (state->memory_owned) { - gpr_free(slices); - } - state->memory_owned = 1; -} - -static void slice_state_remove_prefix(grpc_tcp_slice_state *state, - size_t prefix_bytes) { - gpr_slice *current_slice = &state->slices[state->first_slice]; - size_t current_slice_size; - - while (slice_state_has_available(state)) { - current_slice_size = GPR_SLICE_LENGTH(*current_slice); - if (current_slice_size > prefix_bytes) { - /* TODO(klempner): Get rid of the extra refcount created here by adding a - native "trim the first N bytes" operation to splice */ - /* TODO(klempner): This really shouldn't be modifying the current slice - unless we own the slices array. */ - gpr_slice tail; - tail = gpr_slice_split_tail(current_slice, prefix_bytes); - gpr_slice_unref(*current_slice); - *current_slice = tail; - return; - } else { - gpr_slice_unref(*current_slice); - ++state->first_slice; - ++current_slice; - prefix_bytes -= current_slice_size; - } - } -} - -static void slice_state_destroy(grpc_tcp_slice_state *state) { - while (slice_state_has_available(state)) { - gpr_slice_unref(state->slices[state->first_slice]); - ++state->first_slice; - } - - if (state->memory_owned) { - gpr_free(state->slices); - state->memory_owned = 0; - } -} - -void slice_state_transfer_ownership(grpc_tcp_slice_state *state, - gpr_slice **slices, size_t *nslices) { - *slices = state->slices + state->first_slice; - *nslices = state->last_slice - state->first_slice + 1; - - state->first_slice = -1; - state->last_slice = -1; -} - -/* Fills iov with the first min(iov_size, available) slices, returns number - filled */ -static size_t slice_state_to_iovec(grpc_tcp_slice_state *state, - struct iovec *iov, size_t iov_size) { - size_t nslices = state->last_slice - state->first_slice + 1; - gpr_slice *slices = state->slices + state->first_slice; - size_t i; - if (nslices < iov_size) { - iov_size = nslices; - } - - for (i = 0; i < iov_size; ++i) { - iov[i].iov_base = GPR_SLICE_START_PTR(slices[i]); - iov[i].iov_len = GPR_SLICE_LENGTH(slices[i]); - } - return iov_size; -} - -/* Makes n blocks available at the end of state, writes them into iov, and - returns the number of bytes allocated */ -static size_t slice_state_append_blocks_into_iovec(grpc_tcp_slice_state *state, - struct iovec *iov, size_t n, - size_t slice_size) { - size_t target_size; - size_t i; - size_t allocated_bytes; - ssize_t allocated_slices = slice_state_slices_allocated(state); - - if (n - state->working_slice_valid >= state->nslices - state->last_slice) { - /* Need to grow the slice array */ - target_size = state->nslices; - do { - target_size = target_size * 2; - } while (target_size < allocated_slices + n - state->working_slice_valid); - /* TODO(klempner): If this ever needs to support both prefix removal and - append, we should be smarter about the growth logic here */ - slice_state_realloc(state, target_size); - } - - i = 0; - allocated_bytes = 0; - - if (state->working_slice_valid) { - iov[0].iov_base = GPR_SLICE_END_PTR(state->slices[state->last_slice]); - iov[0].iov_len = GPR_SLICE_LENGTH(state->working_slice) - - GPR_SLICE_LENGTH(state->slices[state->last_slice]); - allocated_bytes += iov[0].iov_len; - ++i; - state->slices[state->last_slice] = state->working_slice; - state->working_slice_valid = 0; - } - - for (; i < n; ++i) { - ++state->last_slice; - state->slices[state->last_slice] = gpr_slice_malloc(slice_size); - iov[i].iov_base = GPR_SLICE_START_PTR(state->slices[state->last_slice]); - iov[i].iov_len = slice_size; - allocated_bytes += slice_size; - } - if (state->first_slice == -1) { - state->first_slice = 0; - } - return allocated_bytes; -} - -/* Remove the last n bytes from state */ -/* TODO(klempner): Consider having this defer actual deletion until later */ -static void slice_state_remove_last(grpc_tcp_slice_state *state, size_t bytes) { - while (bytes > 0 && slice_state_has_available(state)) { - if (GPR_SLICE_LENGTH(state->slices[state->last_slice]) > bytes) { - state->working_slice = state->slices[state->last_slice]; - state->working_slice_valid = 1; - /* TODO(klempner): Combine these into a single operation that doesn't need - to refcount */ - gpr_slice_unref(gpr_slice_split_tail( - &state->slices[state->last_slice], - GPR_SLICE_LENGTH(state->slices[state->last_slice]) - bytes)); - bytes = 0; - } else { - bytes -= GPR_SLICE_LENGTH(state->slices[state->last_slice]); - gpr_slice_unref(state->slices[state->last_slice]); - --state->last_slice; - if (state->last_slice == -1) { - state->first_slice = -1; - } - } - } -} - typedef struct { grpc_endpoint base; grpc_fd *em_fd; @@ -273,12 +72,15 @@ typedef struct { size_t slice_size; gpr_refcount refcount; - grpc_endpoint_read_cb read_cb; - void *read_user_data; - grpc_endpoint_write_cb write_cb; - void *write_user_data; + gpr_slice_buffer *incoming_buffer; + gpr_slice_buffer *outgoing_buffer; + /** slice within outgoing_buffer to write next */ + size_t outgoing_slice_idx; + /** byte within outgoing_buffer->slices[outgoing_slice_idx] to write next */ + size_t outgoing_byte_idx; - grpc_tcp_slice_state write_state; + grpc_iomgr_closure *read_cb; + grpc_iomgr_closure *write_cb; grpc_iomgr_closure read_closure; grpc_iomgr_closure write_closure; @@ -288,65 +90,95 @@ typedef struct { char *peer_string; } grpc_tcp; -static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); -static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success); +static void tcp_handle_read(void *arg /* grpc_tcp */, int success); +static void tcp_handle_write(void *arg /* grpc_tcp */, int success); -static void grpc_tcp_shutdown(grpc_endpoint *ep) { +static void tcp_shutdown(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_fd_shutdown(tcp->em_fd); } -static void grpc_tcp_unref(grpc_tcp *tcp) { - int refcount_zero = gpr_unref(&tcp->refcount); - if (refcount_zero) { - grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan"); - gpr_free(tcp->peer_string); - gpr_free(tcp); +static void tcp_free(grpc_tcp *tcp) { + grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan"); + gpr_free(tcp->peer_string); + gpr_free(tcp); +} + +#define GRPC_TCP_REFCOUNT_DEBUG +#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) +#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) +static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, + reason, tcp->refcount.count, tcp->refcount.count - 1); + if (gpr_unref(&tcp->refcount)) { + tcp_free(tcp); + } +} + +static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, + reason, tcp->refcount.count, tcp->refcount.count + 1); + gpr_ref(&tcp->refcount); +} +#ifdef GRPC_TCP_REFCOUNT_DEBUG +#else +#define TCP_UNREF(tcp, reason) tcp_unref((tcp)) +#define TCP_REF(tcp, reason) tcp_ref((tcp)) +static void tcp_unref(grpc_tcp *tcp) { + if (gpr_unref(&tcp->refcount)) { + tcp_free(tcp); } } -static void grpc_tcp_destroy(grpc_endpoint *ep) { +static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } +#endif + +static void tcp_destroy(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_tcp_unref(tcp); + TCP_UNREF(tcp, "destroy"); } -static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status status) { - grpc_endpoint_read_cb cb = tcp->read_cb; +static void call_read_cb(grpc_tcp *tcp, int success) { + grpc_iomgr_closure *cb = tcp->read_cb; if (grpc_tcp_trace) { size_t i; - gpr_log(GPR_DEBUG, "read: status=%d", status); - for (i = 0; i < nslices; i++) { - char *dump = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "read: success=%d", success); + for (i = 0; i < tcp->incoming_buffer->count; i++) { + char *dump = gpr_dump_slice(tcp->incoming_buffer->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump); gpr_free(dump); } } tcp->read_cb = NULL; - cb(tcp->read_user_data, slices, nslices, status); + tcp->incoming_buffer = NULL; + cb->cb(cb->cb_arg, success); } -#define INLINE_SLICE_BUFFER_SIZE 8 #define MAX_READ_IOVEC 4 -static void grpc_tcp_continue_read(grpc_tcp *tcp) { - gpr_slice static_read_slices[INLINE_SLICE_BUFFER_SIZE]; +static void tcp_continue_read(grpc_tcp *tcp) { struct msghdr msg; struct iovec iov[MAX_READ_IOVEC]; ssize_t read_bytes; - ssize_t allocated_bytes; - struct grpc_tcp_slice_state read_state; - gpr_slice *final_slices; - size_t final_nslices; + size_t i; GPR_ASSERT(!tcp->finished_edge); + GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC); + GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC); GRPC_TIMER_BEGIN(GRPC_PTAG_HANDLE_READ, 0); - slice_state_init(&read_state, static_read_slices, INLINE_SLICE_BUFFER_SIZE, - 0); - allocated_bytes = slice_state_append_blocks_into_iovec( - &read_state, iov, tcp->iov_size, tcp->slice_size); + while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) { + gpr_slice_buffer_add_indexed(tcp->incoming_buffer, + gpr_slice_malloc(tcp->slice_size)); + } + for (i = 0; i < tcp->incoming_buffer->count; i++) { + iov[i].iov_base = GPR_SLICE_START_PTR(tcp->incoming_buffer->slices[i]); + iov[i].iov_len = GPR_SLICE_LENGTH(tcp->incoming_buffer->slices[i]); + } msg.msg_name = NULL; msg.msg_namelen = 0; @@ -362,87 +194,63 @@ static void grpc_tcp_continue_read(grpc_tcp *tcp) { } while (read_bytes < 0 && errno == EINTR); GRPC_TIMER_END(GRPC_PTAG_RECVMSG, 0); - if (read_bytes < allocated_bytes) { - /* TODO(klempner): Consider a second read first, in hopes of getting a - * quick EAGAIN and saving a bunch of allocations. */ - slice_state_remove_last(&read_state, read_bytes < 0 - ? allocated_bytes - : allocated_bytes - read_bytes); - } - if (read_bytes < 0) { - /* NB: After calling the user_cb a parallel call of the read handler may + /* NB: After calling call_read_cb a parallel call of the read handler may * be running. */ if (errno == EAGAIN) { if (tcp->iov_size > 1) { tcp->iov_size /= 2; } - if (slice_state_has_available(&read_state)) { - /* TODO(klempner): We should probably do the call into the application - without all this junk on the stack */ - /* FIXME(klempner): Refcount properly */ - slice_state_transfer_ownership(&read_state, &final_slices, - &final_nslices); - tcp->finished_edge = 1; - call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_OK); - slice_state_destroy(&read_state); - grpc_tcp_unref(tcp); - } else { - /* We've consumed the edge, request a new one */ - slice_state_destroy(&read_state); - grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); - } + /* We've consumed the edge, request a new one */ + grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); } else { /* TODO(klempner): Log interesting errors */ - call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_ERROR); - slice_state_destroy(&read_state); - grpc_tcp_unref(tcp); + gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); + call_read_cb(tcp, 0); + TCP_UNREF(tcp, "read"); } } else if (read_bytes == 0) { /* 0 read size ==> end of stream */ - if (slice_state_has_available(&read_state)) { - /* there were bytes already read: pass them up to the application */ - slice_state_transfer_ownership(&read_state, &final_slices, - &final_nslices); - call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_EOF); - } else { - call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_EOF); - } - slice_state_destroy(&read_state); - grpc_tcp_unref(tcp); + gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); + call_read_cb(tcp, 0); + TCP_UNREF(tcp, "read"); } else { - if (tcp->iov_size < MAX_READ_IOVEC) { + GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length); + if ((size_t)read_bytes < tcp->incoming_buffer->length) { + gpr_slice_buffer_trim_end(tcp->incoming_buffer, + tcp->incoming_buffer->length - read_bytes); + } else if (tcp->iov_size < MAX_READ_IOVEC) { ++tcp->iov_size; } - GPR_ASSERT(slice_state_has_available(&read_state)); - slice_state_transfer_ownership(&read_state, &final_slices, &final_nslices); - call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_OK); - slice_state_destroy(&read_state); - grpc_tcp_unref(tcp); + GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length); + call_read_cb(tcp, 1); + TCP_UNREF(tcp, "read"); } GRPC_TIMER_END(GRPC_PTAG_HANDLE_READ, 0); } -static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { +static void tcp_handle_read(void *arg /* grpc_tcp */, int success) { grpc_tcp *tcp = (grpc_tcp *)arg; GPR_ASSERT(!tcp->finished_edge); if (!success) { - call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); - grpc_tcp_unref(tcp); + call_read_cb(tcp, 0); + TCP_UNREF(tcp, "read"); } else { - grpc_tcp_continue_read(tcp); + tcp_continue_read(tcp); } } -static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data) { +static grpc_endpoint_op_status tcp_read(grpc_endpoint *ep, + gpr_slice_buffer *incoming_buffer, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; GPR_ASSERT(tcp->read_cb == NULL); tcp->read_cb = cb; - tcp->read_user_data = user_data; - gpr_ref(&tcp->refcount); + tcp->incoming_buffer = incoming_buffer; + gpr_slice_buffer_reset_and_unref(incoming_buffer); + TCP_REF(tcp, "read"); if (tcp->finished_edge) { tcp->finished_edge = 0; grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); @@ -450,18 +258,41 @@ static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, tcp->handle_read_closure.cb_arg = tcp; grpc_iomgr_add_delayed_callback(&tcp->handle_read_closure, 1); } + /* TODO(ctiller): immediate return */ + return GRPC_ENDPOINT_PENDING; } #define MAX_WRITE_IOVEC 16 -static grpc_endpoint_write_status grpc_tcp_flush(grpc_tcp *tcp) { +static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; int iov_size; ssize_t sent_length; - grpc_tcp_slice_state *state = &tcp->write_state; + ssize_t sending_length; + ssize_t trailing; + ssize_t unwind_slice_idx; + ssize_t unwind_byte_idx; for (;;) { - iov_size = slice_state_to_iovec(state, iov, MAX_WRITE_IOVEC); + sending_length = 0; + unwind_slice_idx = tcp->outgoing_slice_idx; + unwind_byte_idx = tcp->outgoing_byte_idx; + for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count && + iov_size != MAX_WRITE_IOVEC; + iov_size++) { + iov[iov_size].iov_base = + GPR_SLICE_START_PTR( + tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) + + tcp->outgoing_byte_idx; + iov[iov_size].iov_len = + GPR_SLICE_LENGTH( + tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) - + tcp->outgoing_byte_idx; + sending_length += iov[iov_size].iov_len; + tcp->outgoing_slice_idx++; + tcp->outgoing_byte_idx = 0; + } + GPR_ASSERT(iov_size > 0); msg.msg_name = NULL; msg.msg_namelen = 0; @@ -480,70 +311,75 @@ static grpc_endpoint_write_status grpc_tcp_flush(grpc_tcp *tcp) { if (sent_length < 0) { if (errno == EAGAIN) { - return GRPC_ENDPOINT_WRITE_PENDING; + tcp->outgoing_slice_idx = unwind_slice_idx; + tcp->outgoing_byte_idx = unwind_byte_idx; + return GRPC_ENDPOINT_PENDING; } else { /* TODO(klempner): Log some of these */ - slice_state_destroy(state); - return GRPC_ENDPOINT_WRITE_ERROR; + return GRPC_ENDPOINT_ERROR; } } - /* TODO(klempner): Probably better to batch this after we finish flushing */ - slice_state_remove_prefix(state, sent_length); + GPR_ASSERT(tcp->outgoing_byte_idx == 0); + trailing = sending_length - sent_length; + while (trailing > 0) { + ssize_t slice_length; + + tcp->outgoing_slice_idx--; + slice_length = GPR_SLICE_LENGTH( + tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]); + if (slice_length > trailing) { + tcp->outgoing_byte_idx = slice_length - trailing; + break; + } else { + trailing -= slice_length; + } + } - if (!slice_state_has_available(state)) { - return GRPC_ENDPOINT_WRITE_DONE; + if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) { + return GRPC_ENDPOINT_DONE; } }; } -static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) { +static void tcp_handle_write(void *arg /* grpc_tcp */, int success) { grpc_tcp *tcp = (grpc_tcp *)arg; - grpc_endpoint_write_status write_status; - grpc_endpoint_cb_status cb_status; - grpc_endpoint_write_cb cb; + grpc_endpoint_op_status status; + grpc_iomgr_closure *cb; if (!success) { - slice_state_destroy(&tcp->write_state); cb = tcp->write_cb; tcp->write_cb = NULL; - cb(tcp->write_user_data, GRPC_ENDPOINT_CB_SHUTDOWN); - grpc_tcp_unref(tcp); + cb->cb(cb->cb_arg, 0); + TCP_UNREF(tcp, "write"); return; } GRPC_TIMER_BEGIN(GRPC_PTAG_TCP_CB_WRITE, 0); - write_status = grpc_tcp_flush(tcp); - if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { + status = tcp_flush(tcp); + if (status == GRPC_ENDPOINT_PENDING) { grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure); } else { - slice_state_destroy(&tcp->write_state); - if (write_status == GRPC_ENDPOINT_WRITE_DONE) { - cb_status = GRPC_ENDPOINT_CB_OK; - } else { - cb_status = GRPC_ENDPOINT_CB_ERROR; - } cb = tcp->write_cb; tcp->write_cb = NULL; - cb(tcp->write_user_data, cb_status); - grpc_tcp_unref(tcp); + cb->cb(cb->cb_arg, status == GRPC_ENDPOINT_DONE); + TCP_UNREF(tcp, "write"); } GRPC_TIMER_END(GRPC_PTAG_TCP_CB_WRITE, 0); } -static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { +static grpc_endpoint_op_status tcp_write(grpc_endpoint *ep, + gpr_slice_buffer *buf, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_endpoint_write_status status; + grpc_endpoint_op_status status; if (grpc_tcp_trace) { size_t i; - for (i = 0; i < nslices; i++) { - char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < buf->count; i++) { + char *data = + gpr_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data); gpr_free(data); } @@ -551,15 +387,19 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, GRPC_TIMER_BEGIN(GRPC_PTAG_TCP_WRITE, 0); GPR_ASSERT(tcp->write_cb == NULL); - slice_state_init(&tcp->write_state, slices, nslices, nslices); - status = grpc_tcp_flush(tcp); - if (status == GRPC_ENDPOINT_WRITE_PENDING) { - /* TODO(klempner): Consider inlining rather than malloc for small nslices */ - slice_state_realloc(&tcp->write_state, nslices); - gpr_ref(&tcp->refcount); + if (buf->length == 0) { + GRPC_TIMER_END(GRPC_PTAG_TCP_WRITE, 0); + return GRPC_ENDPOINT_DONE; + } + tcp->outgoing_buffer = buf; + tcp->outgoing_slice_idx = 0; + tcp->outgoing_byte_idx = 0; + + status = tcp_flush(tcp); + if (status == GRPC_ENDPOINT_PENDING) { + TCP_REF(tcp, "write"); tcp->write_cb = cb; - tcp->write_user_data = user_data; grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure); } @@ -567,27 +407,25 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, return status; } -static void grpc_tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { +static void tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_pollset_add_fd(pollset, tcp->em_fd); } -static void grpc_tcp_add_to_pollset_set(grpc_endpoint *ep, - grpc_pollset_set *pollset_set) { +static void tcp_add_to_pollset_set(grpc_endpoint *ep, + grpc_pollset_set *pollset_set) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_pollset_set_add_fd(pollset_set, tcp->em_fd); } -static char *grpc_tcp_get_peer(grpc_endpoint *ep) { +static char *tcp_get_peer(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return gpr_strdup(tcp->peer_string); } static const grpc_endpoint_vtable vtable = { - grpc_tcp_notify_on_read, grpc_tcp_write, - grpc_tcp_add_to_pollset, grpc_tcp_add_to_pollset_set, - grpc_tcp_shutdown, grpc_tcp_destroy, - grpc_tcp_get_peer}; + tcp_read, tcp_write, tcp_add_to_pollset, tcp_add_to_pollset_set, + tcp_shutdown, tcp_destroy, tcp_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, const char *peer_string) { @@ -597,21 +435,19 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, tcp->fd = em_fd->fd; tcp->read_cb = NULL; tcp->write_cb = NULL; - tcp->read_user_data = NULL; - tcp->write_user_data = NULL; + tcp->incoming_buffer = NULL; tcp->slice_size = slice_size; tcp->iov_size = 1; tcp->finished_edge = 1; - slice_state_init(&tcp->write_state, NULL, 0, 0); /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); tcp->em_fd = em_fd; - tcp->read_closure.cb = grpc_tcp_handle_read; + tcp->read_closure.cb = tcp_handle_read; tcp->read_closure.cb_arg = tcp; - tcp->write_closure.cb = grpc_tcp_handle_write; + tcp->write_closure.cb = tcp_handle_write; tcp->write_closure.cb_arg = tcp; - tcp->handle_read_closure.cb = grpc_tcp_handle_read; + tcp->handle_read_closure.cb = tcp_handle_read; return &tcp->base; } diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c index 81b3e33cb2..4206c39318 100644 --- a/src/core/security/secure_endpoint.c +++ b/src/core/security/secure_endpoint.c @@ -49,15 +49,15 @@ typedef struct { struct tsi_frame_protector *protector; gpr_mu protector_mu; /* saved upper level callbacks and user_data. */ - grpc_endpoint_read_cb read_cb; - void *read_user_data; - grpc_endpoint_write_cb write_cb; - void *write_user_data; + grpc_iomgr_closure *read_cb; + grpc_iomgr_closure *write_cb; + grpc_iomgr_closure on_read; + gpr_slice_buffer *read_buffer; + gpr_slice_buffer source_buffer; /* saved handshaker leftover data to unprotect. */ gpr_slice_buffer leftover_bytes; /* buffers for read and write */ gpr_slice read_staging_buffer; - gpr_slice_buffer input_buffer; gpr_slice write_staging_buffer; gpr_slice_buffer output_buffer; @@ -67,62 +67,91 @@ typedef struct { int grpc_trace_secure_endpoint = 0; -static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } - static void destroy(secure_endpoint *secure_ep) { secure_endpoint *ep = secure_ep; grpc_endpoint_destroy(ep->wrapped_ep); tsi_frame_protector_destroy(ep->protector); gpr_slice_buffer_destroy(&ep->leftover_bytes); gpr_slice_unref(ep->read_staging_buffer); - gpr_slice_buffer_destroy(&ep->input_buffer); gpr_slice_unref(ep->write_staging_buffer); gpr_slice_buffer_destroy(&ep->output_buffer); + gpr_slice_buffer_destroy(&ep->source_buffer); gpr_mu_destroy(&ep->protector_mu); gpr_free(ep); } +#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG +#define SECURE_ENDPOINT_UNREF(ep, reason) \ + secure_endpoint_unref((ep), (reason), __FILE__, __LINE__) +#define SECURE_ENDPOINT_REF(ep, reason) \ + secure_endpoint_ref((ep), (reason), __FILE__, __LINE__) +static void secure_endpoint_unref(secure_endpoint *ep, const char *reason, + const char *file, int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d", + ep, reason, ep->ref.count, ep->ref.count - 1); + if (gpr_unref(&ep->ref)) { + destroy(ep); + } +} + +static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, + const char *file, int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d", + ep, reason, ep->ref.count, ep->ref.count + 1); + gpr_ref(&ep->ref); +} +#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG +#else +#define SECURE_ENDPOINT_UNREF(ep, reason) secure_endpoint_unref((ep)) +#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep)) static void secure_endpoint_unref(secure_endpoint *ep) { if (gpr_unref(&ep->ref)) { destroy(ep); } } +static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } +#endif + static void flush_read_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, gpr_uint8 **end) { - gpr_slice_buffer_add(&ep->input_buffer, ep->read_staging_buffer); + gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer); ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); } -static void call_read_cb(secure_endpoint *ep, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static void call_read_cb(secure_endpoint *ep, int success) { if (grpc_trace_secure_endpoint) { size_t i; - for (i = 0; i < nslices; i++) { - char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < ep->read_buffer->count; i++) { + char *data = gpr_dump_slice(ep->read_buffer->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p: %s", ep, data); gpr_free(data); } } - ep->read_cb(ep->read_user_data, slices, nslices, error); - secure_endpoint_unref(ep); + ep->read_buffer = NULL; + ep->read_cb->cb(ep->read_cb->cb_arg, success); + SECURE_ENDPOINT_UNREF(ep, "read"); } -static void on_read(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static int on_read(void *user_data, int success) { unsigned i; gpr_uint8 keep_looping = 0; - size_t input_buffer_count = 0; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)user_data; gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); gpr_uint8 *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); + if (!success) { + gpr_slice_buffer_reset_and_unref(ep->read_buffer); + return 0; + } + /* TODO(yangg) check error, maybe bail out early */ - for (i = 0; i < nslices; i++) { - gpr_slice encrypted = slices[i]; + for (i = 0; i < ep->source_buffer.count; i++) { + gpr_slice encrypted = ep->source_buffer.slices[i]; gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(encrypted); size_t message_size = GPR_SLICE_LENGTH(encrypted); @@ -161,7 +190,7 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices, if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) { gpr_slice_buffer_add( - &ep->input_buffer, + ep->read_buffer, gpr_slice_split_head( &ep->read_staging_buffer, (size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer)))); @@ -169,38 +198,53 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices, /* TODO(yangg) experiment with moving this block after read_cb to see if it helps latency */ - for (i = 0; i < nslices; i++) { - gpr_slice_unref(slices[i]); - } + gpr_slice_buffer_reset_and_unref(&ep->source_buffer); if (result != TSI_OK) { - gpr_slice_buffer_reset_and_unref(&ep->input_buffer); - call_read_cb(ep, NULL, 0, GRPC_ENDPOINT_CB_ERROR); - return; + gpr_slice_buffer_reset_and_unref(ep->read_buffer); + return 0; } - /* The upper level will unref the slices. */ - input_buffer_count = ep->input_buffer.count; - ep->input_buffer.count = 0; - call_read_cb(ep, ep->input_buffer.slices, input_buffer_count, error); + + return 1; +} + +static void on_read_cb(void *user_data, int success) { + call_read_cb(user_data, on_read(user_data, success)); } -static void endpoint_notify_on_read(grpc_endpoint *secure_ep, - grpc_endpoint_read_cb cb, void *user_data) { +static grpc_endpoint_op_status endpoint_read(grpc_endpoint *secure_ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { secure_endpoint *ep = (secure_endpoint *)secure_ep; + int immediate_read_success = -1; ep->read_cb = cb; - ep->read_user_data = user_data; - - secure_endpoint_ref(ep); + ep->read_buffer = slices; + gpr_slice_buffer_reset_and_unref(ep->read_buffer); if (ep->leftover_bytes.count) { - size_t leftover_nslices = ep->leftover_bytes.count; - ep->leftover_bytes.count = 0; - on_read(ep, ep->leftover_bytes.slices, leftover_nslices, - GRPC_ENDPOINT_CB_OK); - return; + gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer); + GPR_ASSERT(ep->leftover_bytes.count == 0); + return on_read(ep, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } - grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep); + SECURE_ENDPOINT_REF(ep, "read"); + + switch ( + grpc_endpoint_read(ep->wrapped_ep, &ep->source_buffer, &ep->on_read)) { + case GRPC_ENDPOINT_DONE: + immediate_read_success = on_read(ep, 1); + break; + case GRPC_ENDPOINT_PENDING: + return GRPC_ENDPOINT_PENDING; + case GRPC_ENDPOINT_ERROR: + immediate_read_success = on_read(ep, 0); + break; + } + + GPR_ASSERT(immediate_read_success != -1); + SECURE_ENDPOINT_UNREF(ep, "read"); + + return immediate_read_success ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, @@ -211,36 +255,28 @@ static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); } -static void on_write(void *data, grpc_endpoint_cb_status error) { - secure_endpoint *ep = data; - ep->write_cb(ep->write_user_data, error); - secure_endpoint_unref(ep); -} - -static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { +static grpc_endpoint_op_status endpoint_write(grpc_endpoint *secure_ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { unsigned i; - size_t output_buffer_count = 0; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)secure_ep; gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer); gpr_uint8 *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); - grpc_endpoint_write_status status; - GPR_ASSERT(ep->output_buffer.count == 0); + + gpr_slice_buffer_reset_and_unref(&ep->output_buffer); if (grpc_trace_secure_endpoint) { - for (i = 0; i < nslices; i++) { - char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < slices->count; i++) { + char *data = + gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data); gpr_free(data); } } - for (i = 0; i < nslices; i++) { - gpr_slice plain = slices[i]; + for (i = 0; i < slices->count; i++) { + gpr_slice plain = slices->slices[i]; gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(plain); size_t message_size = GPR_SLICE_LENGTH(plain); while (message_size > 0) { @@ -290,29 +326,13 @@ static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, } } - for (i = 0; i < nslices; i++) { - gpr_slice_unref(slices[i]); - } - if (result != TSI_OK) { /* TODO(yangg) do different things according to the error type? */ gpr_slice_buffer_reset_and_unref(&ep->output_buffer); - return GRPC_ENDPOINT_WRITE_ERROR; + return GRPC_ENDPOINT_ERROR; } - /* clear output_buffer and let the lower level handle its slices. */ - output_buffer_count = ep->output_buffer.count; - ep->output_buffer.count = 0; - ep->write_cb = cb; - ep->write_user_data = user_data; - /* Need to keep the endpoint alive across a transport */ - secure_endpoint_ref(ep); - status = grpc_endpoint_write(ep->wrapped_ep, ep->output_buffer.slices, - output_buffer_count, on_write, ep); - if (status != GRPC_ENDPOINT_WRITE_PENDING) { - secure_endpoint_unref(ep); - } - return status; + return grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb); } static void endpoint_shutdown(grpc_endpoint *secure_ep) { @@ -320,9 +340,9 @@ static void endpoint_shutdown(grpc_endpoint *secure_ep) { grpc_endpoint_shutdown(ep->wrapped_ep); } -static void endpoint_unref(grpc_endpoint *secure_ep) { +static void endpoint_destroy(grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; - secure_endpoint_unref(ep); + SECURE_ENDPOINT_UNREF(ep, "destroy"); } static void endpoint_add_to_pollset(grpc_endpoint *secure_ep, @@ -343,9 +363,9 @@ static char *endpoint_get_peer(grpc_endpoint *secure_ep) { } static const grpc_endpoint_vtable vtable = { - endpoint_notify_on_read, endpoint_write, + endpoint_read, endpoint_write, endpoint_add_to_pollset, endpoint_add_to_pollset_set, - endpoint_shutdown, endpoint_unref, + endpoint_shutdown, endpoint_destroy, endpoint_get_peer}; grpc_endpoint *grpc_secure_endpoint_create( @@ -363,8 +383,10 @@ grpc_endpoint *grpc_secure_endpoint_create( } ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); - gpr_slice_buffer_init(&ep->input_buffer); gpr_slice_buffer_init(&ep->output_buffer); + gpr_slice_buffer_init(&ep->source_buffer); + ep->read_buffer = NULL; + grpc_iomgr_closure_init(&ep->on_read, on_read_cb, ep); gpr_mu_init(&ep->protector_mu); gpr_ref_init(&ep->ref, 1); return &ep->base; diff --git a/src/core/security/secure_transport_setup.c b/src/core/security/secure_transport_setup.c index 0c3572b53c..bf0079577e 100644 --- a/src/core/security/secure_transport_setup.c +++ b/src/core/security/secure_transport_setup.c @@ -50,16 +50,17 @@ typedef struct { grpc_endpoint *wrapped_endpoint; grpc_endpoint *secure_endpoint; gpr_slice_buffer left_overs; + gpr_slice_buffer incoming; + gpr_slice_buffer outgoing; grpc_secure_transport_setup_done_cb cb; void *user_data; + grpc_iomgr_closure on_handshake_data_sent_to_peer; + grpc_iomgr_closure on_handshake_data_received_from_peer; } grpc_secure_transport_setup; -static void on_handshake_data_received_from_peer(void *setup, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error); +static void on_handshake_data_received_from_peer(void *setup, int success); -static void on_handshake_data_sent_to_peer(void *setup, - grpc_endpoint_cb_status error); +static void on_handshake_data_sent_to_peer(void *setup, int success); static void secure_transport_setup_done(grpc_secure_transport_setup *s, int is_success) { @@ -78,6 +79,8 @@ static void secure_transport_setup_done(grpc_secure_transport_setup *s, if (s->handshaker != NULL) tsi_handshaker_destroy(s->handshaker); if (s->handshake_buffer != NULL) gpr_free(s->handshake_buffer); gpr_slice_buffer_destroy(&s->left_overs); + gpr_slice_buffer_destroy(&s->outgoing); + gpr_slice_buffer_destroy(&s->incoming); GRPC_SECURITY_CONNECTOR_UNREF(s->connector, "secure_transport_setup"); gpr_free(s); } @@ -102,6 +105,8 @@ static void on_peer_checked(void *user_data, grpc_security_status status) { s->secure_endpoint = grpc_secure_endpoint_create(protector, s->wrapped_endpoint, s->left_overs.slices, s->left_overs.count); + s->left_overs.count = 0; + s->left_overs.length = 0; secure_transport_setup_done(s, 1); return; } @@ -132,7 +137,6 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) { size_t offset = 0; tsi_result result = TSI_OK; gpr_slice to_send; - grpc_endpoint_write_status write_status; do { size_t to_send_size = s->handshake_buffer_size - offset; @@ -155,28 +159,25 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) { to_send = gpr_slice_from_copied_buffer((const char *)s->handshake_buffer, offset); + gpr_slice_buffer_reset_and_unref(&s->outgoing); + gpr_slice_buffer_add(&s->outgoing, to_send); /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ - write_status = grpc_endpoint_write(s->wrapped_endpoint, &to_send, 1, - on_handshake_data_sent_to_peer, s); - if (write_status == GRPC_ENDPOINT_WRITE_ERROR) { - gpr_log(GPR_ERROR, "Could not send handshake data to peer."); - secure_transport_setup_done(s, 0); - } else if (write_status == GRPC_ENDPOINT_WRITE_DONE) { - on_handshake_data_sent_to_peer(s, GRPC_ENDPOINT_CB_OK); - } -} - -static void cleanup_slices(gpr_slice *slices, size_t num_slices) { - size_t i; - for (i = 0; i < num_slices; i++) { - gpr_slice_unref(slices[i]); + switch (grpc_endpoint_write(s->wrapped_endpoint, &s->outgoing, + &s->on_handshake_data_sent_to_peer)) { + case GRPC_ENDPOINT_ERROR: + gpr_log(GPR_ERROR, "Could not send handshake data to peer."); + secure_transport_setup_done(s, 0); + break; + case GRPC_ENDPOINT_DONE: + on_handshake_data_sent_to_peer(s, 1); + break; + case GRPC_ENDPOINT_PENDING: + break; } } -static void on_handshake_data_received_from_peer( - void *setup, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static void on_handshake_data_received_from_peer(void *setup, int success) { grpc_secure_transport_setup *s = setup; size_t consumed_slice_size = 0; tsi_result result = TSI_OK; @@ -184,32 +185,37 @@ static void on_handshake_data_received_from_peer( size_t num_left_overs; int has_left_overs_in_current_slice = 0; - if (error != GRPC_ENDPOINT_CB_OK) { + if (!success) { gpr_log(GPR_ERROR, "Read failed."); - cleanup_slices(slices, nslices); secure_transport_setup_done(s, 0); return; } - for (i = 0; i < nslices; i++) { - consumed_slice_size = GPR_SLICE_LENGTH(slices[i]); + for (i = 0; i < s->incoming.count; i++) { + consumed_slice_size = GPR_SLICE_LENGTH(s->incoming.slices[i]); result = tsi_handshaker_process_bytes_from_peer( - s->handshaker, GPR_SLICE_START_PTR(slices[i]), &consumed_slice_size); + s->handshaker, GPR_SLICE_START_PTR(s->incoming.slices[i]), + &consumed_slice_size); if (!tsi_handshaker_is_in_progress(s->handshaker)) break; } if (tsi_handshaker_is_in_progress(s->handshaker)) { /* We may need more data. */ if (result == TSI_INCOMPLETE_DATA) { - /* TODO(klempner,jboeuf): This should probably use the client setup - deadline */ - grpc_endpoint_notify_on_read(s->wrapped_endpoint, - on_handshake_data_received_from_peer, setup); - cleanup_slices(slices, nslices); + switch (grpc_endpoint_read(s->wrapped_endpoint, &s->incoming, + &s->on_handshake_data_received_from_peer)) { + case GRPC_ENDPOINT_DONE: + on_handshake_data_received_from_peer(s, 1); + break; + case GRPC_ENDPOINT_ERROR: + on_handshake_data_received_from_peer(s, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + } return; } else { send_handshake_bytes_to_peer(s); - cleanup_slices(slices, nslices); return; } } @@ -217,42 +223,40 @@ static void on_handshake_data_received_from_peer( if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshake failed with error %s", tsi_result_to_string(result)); - cleanup_slices(slices, nslices); secure_transport_setup_done(s, 0); return; } /* Handshake is done and successful this point. */ has_left_overs_in_current_slice = - (consumed_slice_size < GPR_SLICE_LENGTH(slices[i])); - num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) + nslices - i - 1; + (consumed_slice_size < GPR_SLICE_LENGTH(s->incoming.slices[i])); + num_left_overs = + (has_left_overs_in_current_slice ? 1 : 0) + s->incoming.count - i - 1; if (num_left_overs == 0) { - cleanup_slices(slices, nslices); check_peer(s); return; } - cleanup_slices(slices, nslices - num_left_overs); - /* Put the leftovers in our buffer (ownership transfered). */ if (has_left_overs_in_current_slice) { - gpr_slice_buffer_add(&s->left_overs, - gpr_slice_split_tail(&slices[i], consumed_slice_size)); - gpr_slice_unref(slices[i]); /* split_tail above increments refcount. */ + gpr_slice_buffer_add( + &s->left_overs, + gpr_slice_split_tail(&s->incoming.slices[i], consumed_slice_size)); + gpr_slice_unref( + s->incoming.slices[i]); /* split_tail above increments refcount. */ } gpr_slice_buffer_addn( - &s->left_overs, &slices[i + 1], + &s->left_overs, &s->incoming.slices[i + 1], num_left_overs - (size_t)has_left_overs_in_current_slice); check_peer(s); } /* If setup is NULL, the setup is done. */ -static void on_handshake_data_sent_to_peer(void *setup, - grpc_endpoint_cb_status error) { +static void on_handshake_data_sent_to_peer(void *setup, int success) { grpc_secure_transport_setup *s = setup; /* Make sure that write is OK. */ - if (error != GRPC_ENDPOINT_CB_OK) { - gpr_log(GPR_ERROR, "Write failed with error %d.", error); + if (!success) { + gpr_log(GPR_ERROR, "Write failed."); if (setup != NULL) secure_transport_setup_done(s, 0); return; } @@ -261,8 +265,17 @@ static void on_handshake_data_sent_to_peer(void *setup, if (tsi_handshaker_is_in_progress(s->handshaker)) { /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ - grpc_endpoint_notify_on_read(s->wrapped_endpoint, - on_handshake_data_received_from_peer, setup); + switch (grpc_endpoint_read(s->wrapped_endpoint, &s->incoming, + &s->on_handshake_data_received_from_peer)) { + case GRPC_ENDPOINT_ERROR: + on_handshake_data_received_from_peer(s, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + case GRPC_ENDPOINT_DONE: + on_handshake_data_received_from_peer(s, 1); + break; + } } else { check_peer(s); } @@ -288,6 +301,12 @@ void grpc_setup_secure_transport(grpc_security_connector *connector, s->wrapped_endpoint = nonsecure_endpoint; s->user_data = user_data; s->cb = cb; + grpc_iomgr_closure_init(&s->on_handshake_data_sent_to_peer, + on_handshake_data_sent_to_peer, s); + grpc_iomgr_closure_init(&s->on_handshake_data_received_from_peer, + on_handshake_data_received_from_peer, s); gpr_slice_buffer_init(&s->left_overs); + gpr_slice_buffer_init(&s->outgoing); + gpr_slice_buffer_init(&s->incoming); send_handshake_bytes_to_peer(s); } diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c index 987d5cb9b5..6482ef9c9f 100644 --- a/src/core/support/slice_buffer.c +++ b/src/core/support/slice_buffer.c @@ -207,3 +207,25 @@ void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst) { src->count = 0; src->length = 0; } + +void gpr_slice_buffer_trim_end(gpr_slice_buffer *sb, size_t n) { + GPR_ASSERT(n <= sb->length); + sb->length -= n; + for (;;) { + size_t idx = sb->count - 1; + gpr_slice slice = sb->slices[idx]; + size_t slice_len = GPR_SLICE_LENGTH(slice); + if (slice_len > n) { + sb->slices[idx] = gpr_slice_sub_no_ref(slice, 0, slice_len - n); + return; + } else if (slice_len == n) { + gpr_slice_unref(slice); + sb->count = idx; + return; + } else { + gpr_slice_unref(slice); + n -= slice_len; + sb->count = idx; + } + } +} diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h index 42cf0ecd5b..0e7f94be38 100644 --- a/src/core/transport/chttp2/internal.h +++ b/src/core/transport/chttp2/internal.h @@ -214,6 +214,8 @@ typedef struct { grpc_chttp2_hpack_compressor hpack_compressor; /** is this a client? */ gpr_uint8 is_client; + /** callback for when writing is done */ + grpc_iomgr_closure done_cb; } grpc_chttp2_transport_writing; struct grpc_chttp2_transport_parsing { @@ -331,6 +333,11 @@ struct grpc_chttp2_transport { grpc_iomgr_closure writing_action; /** closure to start reading from the endpoint */ grpc_iomgr_closure reading_action; + /** closure to finish reading from the endpoint */ + grpc_iomgr_closure recv_data; + + /** incoming read bytes */ + gpr_slice_buffer read_buffer; /** address to place a newly accepted stream - set and unset by grpc_chttp2_parsing_accept_stream; used by init_stream to @@ -463,8 +470,7 @@ int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global, grpc_chttp2_transport_writing *writing); void grpc_chttp2_perform_writes( grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint); -void grpc_chttp2_terminate_writing( - grpc_chttp2_transport_writing *transport_writing, int success); +void grpc_chttp2_terminate_writing(void *transport_writing, int success); void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global, grpc_chttp2_transport_writing *writing); diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c index 123061b3fc..2c8c48f47b 100644 --- a/src/core/transport/chttp2/writing.c +++ b/src/core/transport/chttp2/writing.c @@ -37,7 +37,6 @@ #include static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing); -static void finish_write_cb(void *tw, grpc_endpoint_cb_status write_status); int grpc_chttp2_unlocking_check_writes( grpc_chttp2_transport_global *transport_global, @@ -165,16 +164,15 @@ void grpc_chttp2_perform_writes( GPR_ASSERT(transport_writing->outbuf.count > 0); GPR_ASSERT(endpoint); - switch (grpc_endpoint_write(endpoint, transport_writing->outbuf.slices, - transport_writing->outbuf.count, finish_write_cb, - transport_writing)) { - case GRPC_ENDPOINT_WRITE_DONE: + switch (grpc_endpoint_write(endpoint, &transport_writing->outbuf, + &transport_writing->done_cb)) { + case GRPC_ENDPOINT_DONE: grpc_chttp2_terminate_writing(transport_writing, 1); break; - case GRPC_ENDPOINT_WRITE_ERROR: + case GRPC_ENDPOINT_ERROR: grpc_chttp2_terminate_writing(transport_writing, 0); break; - case GRPC_ENDPOINT_WRITE_PENDING: + case GRPC_ENDPOINT_PENDING: break; } } @@ -209,12 +207,6 @@ static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) { } } -static void finish_write_cb(void *tw, grpc_endpoint_cb_status write_status) { - grpc_chttp2_transport_writing *transport_writing = tw; - grpc_chttp2_terminate_writing(transport_writing, - write_status == GRPC_ENDPOINT_CB_OK); -} - void grpc_chttp2_cleanup_writing( grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_writing *transport_writing) { @@ -243,6 +235,5 @@ void grpc_chttp2_cleanup_writing( grpc_chttp2_list_add_read_write_state_changed(transport_global, stream_global); } - transport_writing->outbuf.count = 0; - transport_writing->outbuf.length = 0; + gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf); } diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 1bbd210e46..3d3d708e2f 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -91,8 +91,7 @@ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, gpr_uint32 value); /** Endpoint callback to process incoming data */ -static void recv_data(void *tp, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error); +static void recv_data(void *tp, int success); /** Start disconnection chain */ static void drop_connection(grpc_chttp2_transport *t); @@ -143,6 +142,7 @@ static void destruct_transport(grpc_chttp2_transport *t) { grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor); gpr_slice_buffer_destroy(&t->parsing.qbuf); + gpr_slice_buffer_destroy(&t->read_buffer); grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser); grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser); @@ -255,6 +255,11 @@ static void init_transport(grpc_chttp2_transport *t, grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser, t->metadata_context); + grpc_iomgr_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, + &t->writing); + grpc_iomgr_closure_init(&t->recv_data, recv_data, t); + gpr_slice_buffer_init(&t->read_buffer); + if (is_client) { gpr_slice_buffer_add( &t->global.qbuf, @@ -502,8 +507,8 @@ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, } } -void grpc_chttp2_terminate_writing( - grpc_chttp2_transport_writing *transport_writing, int success) { +void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { + grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr; grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); lock(t); @@ -1060,66 +1065,56 @@ static void read_error_locked(grpc_chttp2_transport *t) { } /* tcp read callback */ -static void recv_data(void *tp, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static void recv_data(void *tp, int success) { grpc_chttp2_transport *t = tp; size_t i; int unref = 0; - switch (error) { - case GRPC_ENDPOINT_CB_SHUTDOWN: - case GRPC_ENDPOINT_CB_EOF: - case GRPC_ENDPOINT_CB_ERROR: - lock(t); + lock(t); + i = 0; + GPR_ASSERT(!t->parsing_active); + if (!t->closed) { + t->parsing_active = 1; + /* merge stream lists */ + grpc_chttp2_stream_map_move_into(&t->new_stream_map, + &t->parsing_stream_map); + grpc_chttp2_prepare_to_read(&t->global, &t->parsing); + gpr_mu_unlock(&t->mu); + for (; i < t->read_buffer.count && + grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]); + i++) + ; + gpr_mu_lock(&t->mu); + if (i != t->read_buffer.count) { drop_connection(t); - read_error_locked(t); - unlock(t); - unref = 1; - for (i = 0; i < nslices; i++) gpr_slice_unref(slices[i]); - break; - case GRPC_ENDPOINT_CB_OK: - lock(t); - i = 0; - GPR_ASSERT(!t->parsing_active); - if (!t->closed) { - t->parsing_active = 1; - /* merge stream lists */ - grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); - grpc_chttp2_prepare_to_read(&t->global, &t->parsing); - gpr_mu_unlock(&t->mu); - for (; i < nslices && grpc_chttp2_perform_read(&t->parsing, slices[i]); - i++) { - gpr_slice_unref(slices[i]); - } - gpr_mu_lock(&t->mu); - if (i != nslices) { - drop_connection(t); - } - /* merge stream lists */ - grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); - t->global.concurrent_stream_count = - grpc_chttp2_stream_map_size(&t->parsing_stream_map); - if (t->parsing.initial_window_update != 0) { - grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, - update_global_window, t); - t->parsing.initial_window_update = 0; - } - /* handle higher level things */ - grpc_chttp2_publish_reads(&t->global, &t->parsing); - t->parsing_active = 0; - } - if (i == nslices) { - grpc_chttp2_schedule_closure(&t->global, &t->reading_action, 1); - } else { - read_error_locked(t); - unref = 1; - } - unlock(t); - for (; i < nslices; i++) gpr_slice_unref(slices[i]); - break; + } + /* merge stream lists */ + grpc_chttp2_stream_map_move_into(&t->new_stream_map, + &t->parsing_stream_map); + t->global.concurrent_stream_count = + grpc_chttp2_stream_map_size(&t->parsing_stream_map); + if (t->parsing.initial_window_update != 0) { + grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, + update_global_window, t); + t->parsing.initial_window_update = 0; + } + /* handle higher level things */ + grpc_chttp2_publish_reads(&t->global, &t->parsing); + t->parsing_active = 0; + } + if (!success) { + drop_connection(t); + read_error_locked(t); + unref = 1; + } else if (i == t->read_buffer.count) { + grpc_chttp2_schedule_closure(&t->global, &t->reading_action, 1); + } else { + read_error_locked(t); + unref = 1; } + gpr_slice_buffer_reset_and_unref(&t->read_buffer); + unlock(t); + if (unref) { UNREF_TRANSPORT(t, "recv_data"); } @@ -1127,7 +1122,16 @@ static void recv_data(void *tp, gpr_slice *slices, size_t nslices, static void reading_action(void *pt, int iomgr_success_ignored) { grpc_chttp2_transport *t = pt; - grpc_endpoint_notify_on_read(t->ep, recv_data, t); + switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { + case GRPC_ENDPOINT_DONE: + recv_data(t, 1); + break; + case GRPC_ENDPOINT_ERROR: + recv_data(t, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + } } /* @@ -1240,5 +1244,6 @@ void grpc_chttp2_transport_start_reading(grpc_transport *transport, gpr_slice *slices, size_t nslices) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport; REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */ - recv_data(t, slices, nslices, GRPC_ENDPOINT_CB_OK); + gpr_slice_buffer_addn(&t->read_buffer, slices, nslices); + recv_data(t, 1); } diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index 24bf5d3625..1d98879662 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -59,7 +59,7 @@ static void thd_func(void *arg) { gpr_event_set(&a->done_thd, (void *)1); } -static void done_write(void *arg, grpc_endpoint_cb_status status) { +static void done_write(void *arg, int success) { thd_args *a = arg; gpr_event_set(&a->done_write, (void *)1); } @@ -85,6 +85,8 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, grpc_mdctx *mdctx = grpc_mdctx_create(); gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); + gpr_slice_buffer outgoing; + grpc_iomgr_closure done_write_closure; hex = gpr_dump(client_payload, client_payload_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); @@ -122,14 +124,18 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, /* Start validator */ gpr_thd_new(&id, thd_func, &a, NULL); + gpr_slice_buffer_init(&outgoing); + gpr_slice_buffer_add(&outgoing, slice); + grpc_iomgr_closure_init(&done_write_closure, done_write, &a); + /* Write data */ - switch (grpc_endpoint_write(sfd.client, &slice, 1, done_write, &a)) { - case GRPC_ENDPOINT_WRITE_DONE: + switch (grpc_endpoint_write(sfd.client, &outgoing, &done_write_closure)) { + case GRPC_ENDPOINT_DONE: done_write(&a, 1); break; - case GRPC_ENDPOINT_WRITE_PENDING: + case GRPC_ENDPOINT_PENDING: break; - case GRPC_ENDPOINT_WRITE_ERROR: + case GRPC_ENDPOINT_ERROR: done_write(&a, 0); break; } @@ -155,6 +161,7 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, .type == GRPC_OP_COMPLETE); grpc_server_destroy(a.server); grpc_completion_queue_destroy(a.cq); + gpr_slice_buffer_destroy(&outgoing); grpc_shutdown(); } diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c index 8186c96da1..b4f170cfbe 100644 --- a/test/core/iomgr/endpoint_tests.c +++ b/test/core/iomgr/endpoint_tests.c @@ -59,8 +59,7 @@ static grpc_pollset *g_pollset; -size_t count_and_unref_slices(gpr_slice *slices, size_t nslices, - int *current_data) { +size_t count_slices(gpr_slice *slices, size_t nslices, int *current_data) { size_t num_bytes = 0; size_t i; size_t j; @@ -72,7 +71,6 @@ size_t count_and_unref_slices(gpr_slice *slices, size_t nslices, *current_data = (*current_data + 1) % 256; } num_bytes += GPR_SLICE_LENGTH(slices[i]); - gpr_slice_unref(slices[i]); } return num_bytes; } @@ -121,86 +119,76 @@ struct read_and_write_test_state { int current_write_data; int read_done; int write_done; + gpr_slice_buffer incoming; + gpr_slice_buffer outgoing; + grpc_iomgr_closure done_read; + grpc_iomgr_closure done_write; }; -static void read_and_write_test_read_handler(void *data, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error) { +static void read_and_write_test_read_handler(void *data, int success) { struct read_and_write_test_state *state = data; - GPR_ASSERT(error != GRPC_ENDPOINT_CB_ERROR); - if (error == GRPC_ENDPOINT_CB_SHUTDOWN) { - gpr_log(GPR_INFO, "Read handler shutdown"); - gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->read_done = 1; - grpc_pollset_kick(g_pollset, NULL); - gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - return; - } - state->bytes_read += - count_and_unref_slices(slices, nslices, &state->current_read_data); - if (state->bytes_read == state->target_bytes) { + state->bytes_read += count_slices( + state->incoming.slices, state->incoming.count, &state->current_read_data); + if (state->bytes_read == state->target_bytes || !success) { gpr_log(GPR_INFO, "Read handler done"); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->read_done = 1; + state->read_done = 1 + success; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - } else { - grpc_endpoint_notify_on_read(state->read_ep, - read_and_write_test_read_handler, data); + } else if (success) { + switch (grpc_endpoint_read(state->read_ep, &state->incoming, + &state->done_read)) { + case GRPC_ENDPOINT_ERROR: + read_and_write_test_read_handler(data, 0); + break; + case GRPC_ENDPOINT_DONE: + read_and_write_test_read_handler(data, 1); + break; + case GRPC_ENDPOINT_PENDING: + break; + } } } -static void read_and_write_test_write_handler(void *data, - grpc_endpoint_cb_status error) { +static void read_and_write_test_write_handler(void *data, int success) { struct read_and_write_test_state *state = data; gpr_slice *slices = NULL; size_t nslices; - grpc_endpoint_write_status write_status; - - GPR_ASSERT(error != GRPC_ENDPOINT_CB_ERROR); - - gpr_log(GPR_DEBUG, "%s: error=%d", "read_and_write_test_write_handler", - error); - - if (error == GRPC_ENDPOINT_CB_SHUTDOWN) { - gpr_log(GPR_INFO, "Write handler shutdown"); - gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->write_done = 1; - grpc_pollset_kick(g_pollset, NULL); - gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - return; - } - - for (;;) { - /* Need to do inline writes until they don't succeed synchronously or we - finish writing */ - state->bytes_written += state->current_write_size; - if (state->target_bytes - state->bytes_written < - state->current_write_size) { - state->current_write_size = state->target_bytes - state->bytes_written; - } - if (state->current_write_size == 0) { - break; - } - - slices = allocate_blocks(state->current_write_size, 8192, &nslices, - &state->current_write_data); - write_status = - grpc_endpoint_write(state->write_ep, slices, nslices, - read_and_write_test_write_handler, state); - gpr_log(GPR_DEBUG, "write_status=%d", write_status); - GPR_ASSERT(write_status != GRPC_ENDPOINT_WRITE_ERROR); - free(slices); - if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { - return; + grpc_endpoint_op_status write_status; + + if (success) { + for (;;) { + /* Need to do inline writes until they don't succeed synchronously or we + finish writing */ + state->bytes_written += state->current_write_size; + if (state->target_bytes - state->bytes_written < + state->current_write_size) { + state->current_write_size = state->target_bytes - state->bytes_written; + } + if (state->current_write_size == 0) { + break; + } + + slices = allocate_blocks(state->current_write_size, 8192, &nslices, + &state->current_write_data); + gpr_slice_buffer_reset_and_unref(&state->outgoing); + gpr_slice_buffer_addn(&state->outgoing, slices, nslices); + write_status = grpc_endpoint_write(state->write_ep, &state->outgoing, + &state->done_write); + gpr_log(GPR_DEBUG, "write_status=%d", write_status); + GPR_ASSERT(write_status != GRPC_ENDPOINT_ERROR); + free(slices); + if (write_status == GRPC_ENDPOINT_PENDING) { + return; + } } + GPR_ASSERT(state->bytes_written == state->target_bytes); } - GPR_ASSERT(state->bytes_written == state->target_bytes); gpr_log(GPR_INFO, "Write handler done"); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->write_done = 1; + state->write_done = 1 + success; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); } @@ -234,16 +222,31 @@ static void read_and_write_test(grpc_endpoint_test_config config, state.write_done = 0; state.current_read_data = 0; state.current_write_data = 0; + grpc_iomgr_closure_init(&state.done_read, read_and_write_test_read_handler, + &state); + grpc_iomgr_closure_init(&state.done_write, read_and_write_test_write_handler, + &state); + gpr_slice_buffer_init(&state.outgoing); + gpr_slice_buffer_init(&state.incoming); /* Get started by pretending an initial write completed */ /* NOTE: Sets up initial conditions so we can have the same write handler for the first iteration as for later iterations. It does the right thing even when bytes_written is unsigned. */ state.bytes_written -= state.current_write_size; - read_and_write_test_write_handler(&state, GRPC_ENDPOINT_CB_OK); + read_and_write_test_write_handler(&state, 1); - grpc_endpoint_notify_on_read(state.read_ep, read_and_write_test_read_handler, - &state); + switch ( + grpc_endpoint_read(state.read_ep, &state.incoming, &state.done_read)) { + case GRPC_ENDPOINT_PENDING: + break; + case GRPC_ENDPOINT_ERROR: + read_and_write_test_read_handler(&state, 0); + break; + case GRPC_ENDPOINT_DONE: + read_and_write_test_read_handler(&state, 1); + break; + } if (shutdown) { gpr_log(GPR_DEBUG, "shutdown read"); @@ -262,6 +265,8 @@ static void read_and_write_test(grpc_endpoint_test_config config, grpc_endpoint_destroy(state.read_ep); grpc_endpoint_destroy(state.write_ep); + gpr_slice_buffer_destroy(&state.outgoing); + gpr_slice_buffer_destroy(&state.incoming); end_test(config); } @@ -272,36 +277,40 @@ struct timeout_test_state { typedef struct { int done; grpc_endpoint *ep; + gpr_slice_buffer incoming; + grpc_iomgr_closure done_read; } shutdown_during_write_test_state; -static void shutdown_during_write_test_read_handler( - void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { - size_t i; +static void shutdown_during_write_test_read_handler(void *user_data, + int success) { shutdown_during_write_test_state *st = user_data; - for (i = 0; i < nslices; i++) { - gpr_slice_unref(slices[i]); - } - - if (error != GRPC_ENDPOINT_CB_OK) { + if (!success) { grpc_endpoint_destroy(st->ep); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - st->done = error; + st->done = 1; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); } else { - grpc_endpoint_notify_on_read( - st->ep, shutdown_during_write_test_read_handler, user_data); + switch (grpc_endpoint_read(st->ep, &st->incoming, &st->done_read)) { + case GRPC_ENDPOINT_PENDING: + break; + case GRPC_ENDPOINT_ERROR: + shutdown_during_write_test_read_handler(user_data, 0); + break; + case GRPC_ENDPOINT_DONE: + shutdown_during_write_test_read_handler(user_data, 1); + break; + } } } -static void shutdown_during_write_test_write_handler( - void *user_data, grpc_endpoint_cb_status error) { +static void shutdown_during_write_test_write_handler(void *user_data, + int success) { shutdown_during_write_test_state *st = user_data; - gpr_log(GPR_INFO, "shutdown_during_write_test_write_handler: error = %d", - error); - if (error == 0) { + gpr_log(GPR_INFO, "shutdown_during_write_test_write_handler: success = %d", + success); + if (success) { /* This happens about 0.5% of the time when run under TSAN, and is entirely legitimate, but means we aren't testing the path we think we are. */ /* TODO(klempner): Change this test to retry the write in that case */ @@ -324,6 +333,8 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, shutdown_during_write_test_state read_st; shutdown_during_write_test_state write_st; gpr_slice *slices; + gpr_slice_buffer outgoing; + grpc_iomgr_closure done_write; grpc_endpoint_test_fixture f = begin_test(config, "shutdown_during_write_test", slice_size); @@ -334,19 +345,26 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, read_st.done = 0; write_st.done = 0; - grpc_endpoint_notify_on_read( - read_st.ep, shutdown_during_write_test_read_handler, &read_st); + grpc_iomgr_closure_init(&done_write, shutdown_during_write_test_write_handler, + &write_st); + grpc_iomgr_closure_init(&read_st.done_read, + shutdown_during_write_test_read_handler, &read_st); + gpr_slice_buffer_init(&read_st.incoming); + gpr_slice_buffer_init(&outgoing); + + GPR_ASSERT(grpc_endpoint_read(read_st.ep, &read_st.incoming, + &read_st.done_read) == GRPC_ENDPOINT_PENDING); for (size = 1;; size *= 2) { slices = allocate_blocks(size, 1, &nblocks, ¤t_data); - switch (grpc_endpoint_write(write_st.ep, slices, nblocks, - shutdown_during_write_test_write_handler, - &write_st)) { - case GRPC_ENDPOINT_WRITE_DONE: + gpr_slice_buffer_reset_and_unref(&outgoing); + gpr_slice_buffer_addn(&outgoing, slices, nblocks); + switch (grpc_endpoint_write(write_st.ep, &outgoing, &done_write)) { + case GRPC_ENDPOINT_DONE: break; - case GRPC_ENDPOINT_WRITE_ERROR: + case GRPC_ENDPOINT_ERROR: gpr_log(GPR_ERROR, "error writing"); abort(); - case GRPC_ENDPOINT_WRITE_PENDING: + case GRPC_ENDPOINT_PENDING: grpc_endpoint_shutdown(write_st.ep); deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); @@ -365,6 +383,8 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, } gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); gpr_free(slices); + gpr_slice_buffer_destroy(&read_st.incoming); + gpr_slice_buffer_destroy(&outgoing); end_test(config); return; } diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 17a85ceaec..a2e3adcf29 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -118,10 +118,12 @@ struct read_socket_state { grpc_endpoint *ep; ssize_t read_bytes; ssize_t target_read_bytes; + gpr_slice_buffer incoming; + grpc_iomgr_closure read_cb; }; -static ssize_t count_and_unref_slices(gpr_slice *slices, size_t nslices, - int *current_data) { +static ssize_t count_slices(gpr_slice *slices, size_t nslices, + int *current_data) { ssize_t num_bytes = 0; unsigned i, j; unsigned char *buf; @@ -132,31 +134,41 @@ static ssize_t count_and_unref_slices(gpr_slice *slices, size_t nslices, *current_data = (*current_data + 1) % 256; } num_bytes += GPR_SLICE_LENGTH(slices[i]); - gpr_slice_unref(slices[i]); } return num_bytes; } -static void read_cb(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static void read_cb(void *user_data, int success) { struct read_socket_state *state = (struct read_socket_state *)user_data; ssize_t read_bytes; int current_data; - GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); + GPR_ASSERT(success); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); current_data = state->read_bytes % 256; - read_bytes = count_and_unref_slices(slices, nslices, ¤t_data); + read_bytes = count_slices(state->incoming.slices, state->incoming.count, + ¤t_data); state->read_bytes += read_bytes; gpr_log(GPR_INFO, "Read %d bytes of %d", read_bytes, state->target_read_bytes); if (state->read_bytes >= state->target_read_bytes) { - /* empty */ + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); } else { - grpc_endpoint_notify_on_read(state->ep, read_cb, state); + switch (grpc_endpoint_read(state->ep, &state->incoming, &state->read_cb)) { + case GRPC_ENDPOINT_DONE: + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + read_cb(user_data, 1); + break; + case GRPC_ENDPOINT_ERROR: + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + read_cb(user_data, 0); + break; + case GRPC_ENDPOINT_PENDING: + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + break; + } } - gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); } /* Write to a socket, then read from it using the grpc_tcp API. */ @@ -181,8 +193,19 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { state.ep = ep; state.read_bytes = 0; state.target_read_bytes = written_bytes; + gpr_slice_buffer_init(&state.incoming); + grpc_iomgr_closure_init(&state.read_cb, read_cb, &state); - grpc_endpoint_notify_on_read(ep, read_cb, &state); + switch (grpc_endpoint_read(ep, &state.incoming, &state.read_cb)) { + case GRPC_ENDPOINT_DONE: + read_cb(&state, 1); + break; + case GRPC_ENDPOINT_ERROR: + read_cb(&state, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + } gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (state.read_bytes < state.target_read_bytes) { @@ -192,6 +215,7 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { GPR_ASSERT(state.read_bytes == state.target_read_bytes); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + gpr_slice_buffer_destroy(&state.incoming); grpc_endpoint_destroy(ep); } @@ -218,8 +242,19 @@ static void large_read_test(ssize_t slice_size) { state.ep = ep; state.read_bytes = 0; state.target_read_bytes = written_bytes; + gpr_slice_buffer_init(&state.incoming); + grpc_iomgr_closure_init(&state.read_cb, read_cb, &state); - grpc_endpoint_notify_on_read(ep, read_cb, &state); + switch (grpc_endpoint_read(ep, &state.incoming, &state.read_cb)) { + case GRPC_ENDPOINT_DONE: + read_cb(&state, 1); + break; + case GRPC_ENDPOINT_ERROR: + read_cb(&state, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + } gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (state.read_bytes < state.target_read_bytes) { @@ -229,6 +264,7 @@ static void large_read_test(ssize_t slice_size) { GPR_ASSERT(state.read_bytes == state.target_read_bytes); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + gpr_slice_buffer_destroy(&state.incoming); grpc_endpoint_destroy(ep); } @@ -260,8 +296,7 @@ static gpr_slice *allocate_blocks(ssize_t num_bytes, ssize_t slice_size, return slices; } -static void write_done(void *user_data /* write_socket_state */, - grpc_endpoint_cb_status error) { +static void write_done(void *user_data /* write_socket_state */, int success) { struct write_socket_state *state = (struct write_socket_state *)user_data; gpr_log(GPR_INFO, "Write done callback called"); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); @@ -336,6 +371,8 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { size_t num_blocks; gpr_slice *slices; int current_data = 0; + gpr_slice_buffer outgoing; + grpc_iomgr_closure write_done_closure; gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20); gpr_log(GPR_INFO, "Start write test with %d bytes, slice size %d", num_bytes, @@ -352,73 +389,21 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - if (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state) == - GRPC_ENDPOINT_WRITE_DONE) { - /* Write completed immediately */ - read_bytes = drain_socket(sv[0]); - GPR_ASSERT(read_bytes == num_bytes); - } else { - drain_socket_blocking(sv[0], num_bytes, num_bytes); - gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); - for (;;) { - grpc_pollset_worker worker; - if (state.write_done) { - break; - } - grpc_pollset_work(&g_pollset, &worker, deadline); - } - gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); - } - - grpc_endpoint_destroy(ep); - gpr_free(slices); -} - -static void read_done_for_write_error(void *ud, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error) { - GPR_ASSERT(error != GRPC_ENDPOINT_CB_OK); - GPR_ASSERT(nslices == 0); -} - -/* Write to a socket using the grpc_tcp API, then drain it directly. - Note that if the write does not complete immediately we need to drain the - socket in parallel with the read. */ -static void write_error_test(ssize_t num_bytes, ssize_t slice_size) { - int sv[2]; - grpc_endpoint *ep; - struct write_socket_state state; - size_t num_blocks; - gpr_slice *slices; - int current_data = 0; - grpc_pollset_worker worker; - gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20); - - gpr_log(GPR_INFO, "Start write error test with %d bytes, slice size %d", - num_bytes, slice_size); - - create_sockets(sv); + gpr_slice_buffer_init(&outgoing); + gpr_slice_buffer_addn(&outgoing, slices, num_blocks); + grpc_iomgr_closure_init(&write_done_closure, write_done, &state); - ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_error_test"), - GRPC_TCP_DEFAULT_READ_SLICE_SIZE, "test"); - grpc_endpoint_add_to_pollset(ep, &g_pollset); - - close(sv[0]); - - state.ep = ep; - state.write_done = 0; - - slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - - switch (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state)) { - case GRPC_ENDPOINT_WRITE_DONE: - case GRPC_ENDPOINT_WRITE_ERROR: + switch (grpc_endpoint_write(ep, &outgoing, &write_done_closure)) { + case GRPC_ENDPOINT_DONE: /* Write completed immediately */ + read_bytes = drain_socket(sv[0]); + GPR_ASSERT(read_bytes == num_bytes); break; - case GRPC_ENDPOINT_WRITE_PENDING: - grpc_endpoint_notify_on_read(ep, read_done_for_write_error, NULL); + case GRPC_ENDPOINT_PENDING: + drain_socket_blocking(sv[0], num_bytes, num_bytes); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); for (;;) { + grpc_pollset_worker worker; if (state.write_done) { break; } @@ -426,10 +411,14 @@ static void write_error_test(ssize_t num_bytes, ssize_t slice_size) { } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); break; + case GRPC_ENDPOINT_ERROR: + gpr_log(GPR_ERROR, "endpoint got error"); + abort(); } + gpr_slice_buffer_destroy(&outgoing); grpc_endpoint_destroy(ep); - free(slices); + gpr_free(slices); } void run_tests(void) { @@ -448,10 +437,6 @@ void run_tests(void) { write_test(100000, 1); write_test(100000, 137); - for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { - write_error_test(40320, i); - } - for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { write_test(40320, i); } diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index a8368fc842..c76ddcd194 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -135,62 +135,26 @@ static grpc_endpoint_test_config configs[] = { secure_endpoint_create_fixture_tcp_socketpair_leftover, clean_up}, }; -static void verify_leftover(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { - gpr_slice s = - gpr_slice_from_copied_string("hello world 12345678900987654321"); - - GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); - GPR_ASSERT(nslices == 1); - - GPR_ASSERT(0 == gpr_slice_cmp(s, slices[0])); - gpr_slice_unref(slices[0]); - gpr_slice_unref(s); - *(int *)user_data = 1; -} - static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { grpc_endpoint_test_fixture f = config.create_fixture(slice_size); - int verified = 0; + gpr_slice_buffer incoming; + gpr_slice s = + gpr_slice_from_copied_string("hello world 12345678900987654321"); gpr_log(GPR_INFO, "Start test left over"); - grpc_endpoint_notify_on_read(f.client_ep, verify_leftover, &verified); - GPR_ASSERT(verified == 1); + gpr_slice_buffer_init(&incoming); + GPR_ASSERT(grpc_endpoint_read(f.client_ep, &incoming, NULL) == + GRPC_ENDPOINT_DONE); + GPR_ASSERT(incoming.count == 1); + GPR_ASSERT(0 == gpr_slice_cmp(s, incoming.slices[0])); grpc_endpoint_shutdown(f.client_ep); grpc_endpoint_shutdown(f.server_ep); grpc_endpoint_destroy(f.client_ep); grpc_endpoint_destroy(f.server_ep); - clean_up(); -} - -static void destroy_early(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { - grpc_endpoint_test_fixture *f = user_data; - gpr_slice s = - gpr_slice_from_copied_string("hello world 12345678900987654321"); - - GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); - GPR_ASSERT(nslices == 1); - - grpc_endpoint_shutdown(f->client_ep); - grpc_endpoint_destroy(f->client_ep); - - GPR_ASSERT(0 == gpr_slice_cmp(s, slices[0])); - gpr_slice_unref(slices[0]); gpr_slice_unref(s); -} + gpr_slice_buffer_destroy(&incoming); -/* test which destroys the ep before finishing reading */ -static void test_destroy_ep_early(grpc_endpoint_test_config config, - size_t slice_size) { - grpc_endpoint_test_fixture f = config.create_fixture(slice_size); - gpr_log(GPR_INFO, "Start test destroy early"); - - grpc_endpoint_notify_on_read(f.client_ep, destroy_early, &f); - - grpc_endpoint_shutdown(f.server_ep); - grpc_endpoint_destroy(f.server_ep); clean_up(); } @@ -203,7 +167,6 @@ int main(int argc, char **argv) { grpc_pollset_init(&g_pollset); grpc_endpoint_tests(configs[0], &g_pollset); test_leftover(configs[1], 1); - test_destroy_ep_early(configs[1], 1); grpc_pollset_shutdown(&g_pollset, destroy_pollset, &g_pollset); grpc_iomgr_shutdown(); -- cgit v1.2.3 From ec9acabb4f197c8da4de4b7d5109c38611c23be0 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 21 Aug 2015 13:06:00 -0700 Subject: Update Windows to new endpoint API Also solve an infinite recursion in chttp2_transport --- src/core/iomgr/tcp_windows.c | 124 ++++++++++++++++------------------ src/core/transport/chttp2/internal.h | 2 - src/core/transport/chttp2_transport.c | 64 +++++++++--------- 3 files changed, 90 insertions(+), 100 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index 123f46d71d..a63123c6c9 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -82,13 +82,11 @@ typedef struct grpc_tcp { /* Refcounting how many operations are in progress. */ gpr_refcount refcount; - grpc_endpoint_read_cb read_cb; - void *read_user_data; + grpc_iomgr_closure *read_cb; + grpc_iomgr_closure *write_cb; gpr_slice read_slice; - - grpc_endpoint_write_cb write_cb; - void *write_user_data; - gpr_slice_buffer write_slices; + gpr_slice_buffer *write_slices; + gpr_slice_buffer *read_slices; /* The IO Completion Port runs from another thread. We need some mechanism to protect ourselves when requesting a shutdown. */ @@ -102,7 +100,6 @@ static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } static void tcp_unref(grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { - gpr_slice_buffer_destroy(&tcp->write_slices); grpc_winsocket_orphan(tcp->socket); gpr_mu_destroy(&tcp->mu); gpr_free(tcp->peer_string); @@ -111,21 +108,16 @@ static void tcp_unref(grpc_tcp *tcp) { } /* Asynchronous callback from the IOCP, or the background thread. */ -static void on_read(void *tcpp, int from_iocp) { - grpc_tcp *tcp = (grpc_tcp *)tcpp; +static int on_read(grpc_tcp *tcp, int from_iocp) { grpc_winsocket *socket = tcp->socket; gpr_slice sub; gpr_slice *slice = NULL; size_t nslices = 0; - grpc_endpoint_cb_status status; - grpc_endpoint_read_cb cb; + int success; grpc_winsocket_callback_info *info = &socket->read_info; - void *opaque = tcp->read_user_data; int do_abort = 0; gpr_mu_lock(&tcp->mu); - cb = tcp->read_cb; - tcp->read_cb = NULL; if (!from_iocp || tcp->shutting_down) { /* If we are here with from_iocp set to true, it means we got raced to shutting down the endpoint. No actual abort callback will happen @@ -140,8 +132,7 @@ static void on_read(void *tcpp, int from_iocp) { gpr_slice_unref(tcp->read_slice); } tcp_unref(tcp); - if (cb) cb(opaque, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); - return; + return 0; } GPR_ASSERT(tcp->socket->read_info.outstanding); @@ -152,27 +143,33 @@ static void on_read(void *tcpp, int from_iocp) { gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); gpr_free(utf8_message); } - status = GRPC_ENDPOINT_CB_ERROR; + success = 0; } else { if (info->bytes_transfered != 0) { sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); - status = GRPC_ENDPOINT_CB_OK; - slice = ⊂ - nslices = 1; + gpr_slice_buffer_add(tcp->read_slices, sub); + success = 1; } else { gpr_slice_unref(tcp->read_slice); - status = GRPC_ENDPOINT_CB_EOF; + success = 0; } } tcp->socket->read_info.outstanding = 0; + return success; +} + +static void on_read_cb(void *tcpp, int from_iocp) { + grpc_tcp *tcp = tcpp; + grpc_iomgr_closure *cb = tcp->read_cb; + int success = on_read(tcp, from_iocp); + tcp->read_cb = NULL; tcp_unref(tcp); - cb(opaque, slice, nslices, status); + cb->cb(cb->cb_arg, success); } -static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *arg) { +static grpc_endpoint_op_status win_read(grpc_endpoint *ep, gpr_slice_buffer *read_slices, grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->read_info; @@ -183,13 +180,11 @@ static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, GPR_ASSERT(!tcp->socket->read_info.outstanding); if (tcp->shutting_down) { - cb(arg, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); - return; + return GRPC_ENDPOINT_ERROR; } - tcp_ref(tcp); tcp->socket->read_info.outstanding = 1; tcp->read_cb = cb; - tcp->read_user_data = arg; + tcp->read_slices = read_slices; tcp->read_slice = gpr_slice_malloc(8192); @@ -204,9 +199,8 @@ static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, /* Did we get data immediately ? Yay. */ if (info->wsa_error != WSAEWOULDBLOCK) { info->bytes_transfered = bytes_read; - /* This might heavily recurse. */ - on_read(tcp, 1); - return; + gpr_log(GPR_DEBUG, "immread: %d bytes", bytes_read); + return on_read(tcp, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } /* Otherwise, let's retry, by queuing a read. */ @@ -218,12 +212,14 @@ static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { info->wsa_error = wsa_error; - on_read(tcp, 1); - return; + gpr_log(GPR_DEBUG, "immread: err=%d", wsa_error); + return on_read(tcp, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } } - grpc_socket_notify_on_read(tcp->socket, on_read, tcp); + tcp_ref(tcp); + grpc_socket_notify_on_read(tcp->socket, on_read_cb, tcp); + return GRPC_ENDPOINT_PENDING; } /* Asynchronous callback from the IOCP, or the background thread. */ @@ -231,9 +227,8 @@ static void on_write(void *tcpp, int from_iocp) { grpc_tcp *tcp = (grpc_tcp *)tcpp; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->write_info; - grpc_endpoint_cb_status status = GRPC_ENDPOINT_CB_OK; - grpc_endpoint_write_cb cb; - void *opaque = tcp->write_user_data; + grpc_iomgr_closure *cb; + int success; int do_abort = 0; gpr_mu_lock(&tcp->mu); @@ -250,10 +245,11 @@ static void on_write(void *tcpp, int from_iocp) { if (do_abort) { if (from_iocp) { tcp->socket->write_info.outstanding = 0; - gpr_slice_buffer_reset_and_unref(&tcp->write_slices); } tcp_unref(tcp); - if (cb) cb(opaque, GRPC_ENDPOINT_CB_SHUTDOWN); + if (cb) { + cb->cb(cb->cb_arg, 0); + } return; } @@ -265,23 +261,22 @@ static void on_write(void *tcpp, int from_iocp) { gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); gpr_free(utf8_message); } - status = GRPC_ENDPOINT_CB_ERROR; + success = 0; } else { - GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length); + GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length); + success = 1; } - gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; tcp_unref(tcp); - cb(opaque, status); + cb->cb(cb->cb_arg, success); } /* Initiates a write. */ -static grpc_endpoint_write_status win_write(grpc_endpoint *ep, - gpr_slice *slices, size_t nslices, - grpc_endpoint_write_cb cb, - void *arg) { +static grpc_endpoint_op_status win_write(grpc_endpoint *ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *socket = tcp->socket; grpc_winsocket_callback_info *info = &socket->write_info; @@ -294,28 +289,26 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, GPR_ASSERT(!tcp->socket->write_info.outstanding); if (tcp->shutting_down) { - return GRPC_ENDPOINT_WRITE_ERROR; + return GRPC_ENDPOINT_ERROR; } tcp_ref(tcp); tcp->socket->write_info.outstanding = 1; tcp->write_cb = cb; - tcp->write_user_data = arg; - - gpr_slice_buffer_addn(&tcp->write_slices, slices, nslices); + tcp->write_slices = slices; - if (tcp->write_slices.count > GPR_ARRAY_SIZE(local_buffers)) { - buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices.count); + if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) { + buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count); allocated = buffers; } - for (i = 0; i < tcp->write_slices.count; i++) { - buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices.slices[i]); - buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices.slices[i]); + for (i = 0; i < tcp->write_slices->count; i++) { + buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]); + buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]); } /* First, let's try a synchronous, non-blocking write. */ - status = WSASend(socket->socket, buffers, tcp->write_slices.count, + status = WSASend(socket->socket, buffers, tcp->write_slices->count, &bytes_sent, 0, NULL, NULL); info->wsa_error = status == 0 ? 0 : WSAGetLastError(); @@ -323,10 +316,10 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, connection that has its send queue filled up. But if we don't, then we can avoid doing an async write operation at all. */ if (info->wsa_error != WSAEWOULDBLOCK) { - grpc_endpoint_write_status ret = GRPC_ENDPOINT_WRITE_ERROR; + grpc_endpoint_op_status ret = GRPC_ENDPOINT_ERROR; if (status == 0) { - ret = GRPC_ENDPOINT_WRITE_DONE; - GPR_ASSERT(bytes_sent == tcp->write_slices.length); + ret = GRPC_ENDPOINT_DONE; + GPR_ASSERT(bytes_sent == tcp->write_slices->length); } else { if (socket->read_info.wsa_error != WSAECONNRESET) { char *utf8_message = gpr_format_message(info->wsa_error); @@ -335,7 +328,6 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, } } if (allocated) gpr_free(allocated); - gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; tcp_unref(tcp); return ret; @@ -344,24 +336,23 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same operation, this time asynchronously. */ memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED)); - status = WSASend(socket->socket, buffers, tcp->write_slices.count, + status = WSASend(socket->socket, buffers, tcp->write_slices->count, &bytes_sent, 0, &socket->write_info.overlapped, NULL); if (allocated) gpr_free(allocated); if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { - gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; tcp_unref(tcp); - return GRPC_ENDPOINT_WRITE_ERROR; + return GRPC_ENDPOINT_ERROR; } } /* As all is now setup, we can now ask for the IOCP notification. It may trigger the callback immediately however, but no matter. */ grpc_socket_notify_on_write(socket, on_write, tcp); - return GRPC_ENDPOINT_WRITE_PENDING; + return GRPC_ENDPOINT_PENDING; } static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *ps) { @@ -407,7 +398,7 @@ static char *win_get_peer(grpc_endpoint *ep) { } static grpc_endpoint_vtable vtable = { - win_notify_on_read, win_write, win_add_to_pollset, win_add_to_pollset_set, + win_read, win_write, win_add_to_pollset, win_add_to_pollset_set, win_shutdown, win_destroy, win_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { @@ -416,7 +407,6 @@ grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { tcp->base.vtable = &vtable; tcp->socket = socket; gpr_mu_init(&tcp->mu); - gpr_slice_buffer_init(&tcp->write_slices); gpr_ref_init(&tcp->refcount, 1); tcp->peer_string = gpr_strdup(peer_string); return &tcp->base; diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h index 0e7f94be38..a1b773b1ca 100644 --- a/src/core/transport/chttp2/internal.h +++ b/src/core/transport/chttp2/internal.h @@ -331,8 +331,6 @@ struct grpc_chttp2_transport { /** closure to execute writing */ grpc_iomgr_closure writing_action; - /** closure to start reading from the endpoint */ - grpc_iomgr_closure reading_action; /** closure to finish reading from the endpoint */ grpc_iomgr_closure recv_data; diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 3d3d708e2f..46ab0a585f 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -84,7 +84,6 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t); /* forward declarations of various callbacks that we'll build closures around */ static void writing_action(void *t, int iomgr_success_ignored); -static void reading_action(void *t, int iomgr_success_ignored); /** Set a transport level setting, and push it to our peer */ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, @@ -249,7 +248,6 @@ static void init_transport(grpc_chttp2_transport *t, gpr_slice_buffer_init(&t->writing.outbuf); grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor, mdctx); grpc_iomgr_closure_init(&t->writing_action, writing_action, t); - grpc_iomgr_closure_init(&t->reading_action, reading_action, t); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); @@ -1065,10 +1063,9 @@ static void read_error_locked(grpc_chttp2_transport *t) { } /* tcp read callback */ -static void recv_data(void *tp, int success) { - grpc_chttp2_transport *t = tp; +static int recv_data_loop(grpc_chttp2_transport *t, int *success) { size_t i; - int unref = 0; + int keep_reading = 0; lock(t); i = 0; @@ -1077,12 +1074,12 @@ static void recv_data(void *tp, int success) { t->parsing_active = 1; /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); + &t->parsing_stream_map); grpc_chttp2_prepare_to_read(&t->global, &t->parsing); gpr_mu_unlock(&t->mu); for (; i < t->read_buffer.count && - grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]); - i++) + grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]); + i++) ; gpr_mu_lock(&t->mu); if (i != t->read_buffer.count) { @@ -1090,48 +1087,53 @@ static void recv_data(void *tp, int success) { } /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); + &t->parsing_stream_map); t->global.concurrent_stream_count = - grpc_chttp2_stream_map_size(&t->parsing_stream_map); + grpc_chttp2_stream_map_size(&t->parsing_stream_map); if (t->parsing.initial_window_update != 0) { grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, - update_global_window, t); + update_global_window, t); t->parsing.initial_window_update = 0; } /* handle higher level things */ grpc_chttp2_publish_reads(&t->global, &t->parsing); t->parsing_active = 0; } - if (!success) { + if (!*success || i != t->read_buffer.count) { drop_connection(t); read_error_locked(t); - unref = 1; - } else if (i == t->read_buffer.count) { - grpc_chttp2_schedule_closure(&t->global, &t->reading_action, 1); - } else { - read_error_locked(t); - unref = 1; + } + else { + keep_reading = 1; } gpr_slice_buffer_reset_and_unref(&t->read_buffer); unlock(t); - if (unref) { - UNREF_TRANSPORT(t, "recv_data"); - } -} - -static void reading_action(void *pt, int iomgr_success_ignored) { - grpc_chttp2_transport *t = pt; - switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { + if (keep_reading) { + switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { case GRPC_ENDPOINT_DONE: - recv_data(t, 1); - break; + *success = 1; + return 1; case GRPC_ENDPOINT_ERROR: - recv_data(t, 0); - break; + *success = 0; + return 1; case GRPC_ENDPOINT_PENDING: - break; + return 0; + } + } + else { + UNREF_TRANSPORT(t, "recv_data"); + return 0; } + + gpr_log(GPR_ERROR, "should never reach here"); + abort(); +} + +static void recv_data(void *tp, int success) { + grpc_chttp2_transport *t = tp; + + while (recv_data_loop(t, &success)); } /* -- cgit v1.2.3 From 1c090699da0ba779e001cc9bc13af42d7716f7ce Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 21 Aug 2015 13:07:01 -0700 Subject: clang-format --- src/core/iomgr/tcp_windows.c | 12 +++++++----- src/core/transport/chttp2_transport.c | 37 +++++++++++++++++------------------ 2 files changed, 25 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index a63123c6c9..1cf2ca2131 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -169,7 +169,9 @@ static void on_read_cb(void *tcpp, int from_iocp) { cb->cb(cb->cb_arg, success); } -static grpc_endpoint_op_status win_read(grpc_endpoint *ep, gpr_slice_buffer *read_slices, grpc_iomgr_closure *cb) { +static grpc_endpoint_op_status win_read(grpc_endpoint *ep, + gpr_slice_buffer *read_slices, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->read_info; @@ -275,8 +277,8 @@ static void on_write(void *tcpp, int from_iocp) { /* Initiates a write. */ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, - gpr_slice_buffer *slices, - grpc_iomgr_closure *cb) { + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *socket = tcp->socket; grpc_winsocket_callback_info *info = &socket->write_info; @@ -398,8 +400,8 @@ static char *win_get_peer(grpc_endpoint *ep) { } static grpc_endpoint_vtable vtable = { - win_read, win_write, win_add_to_pollset, win_add_to_pollset_set, - win_shutdown, win_destroy, win_get_peer}; + win_read, win_write, win_add_to_pollset, win_add_to_pollset_set, + win_shutdown, win_destroy, win_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 46ab0a585f..8caa10c938 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -1074,12 +1074,12 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { t->parsing_active = 1; /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); + &t->parsing_stream_map); grpc_chttp2_prepare_to_read(&t->global, &t->parsing); gpr_mu_unlock(&t->mu); for (; i < t->read_buffer.count && - grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]); - i++) + grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]); + i++) ; gpr_mu_lock(&t->mu); if (i != t->read_buffer.count) { @@ -1087,12 +1087,12 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { } /* merge stream lists */ grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); + &t->parsing_stream_map); t->global.concurrent_stream_count = - grpc_chttp2_stream_map_size(&t->parsing_stream_map); + grpc_chttp2_stream_map_size(&t->parsing_stream_map); if (t->parsing.initial_window_update != 0) { grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, - update_global_window, t); + update_global_window, t); t->parsing.initial_window_update = 0; } /* handle higher level things */ @@ -1102,8 +1102,7 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { if (!*success || i != t->read_buffer.count) { drop_connection(t); read_error_locked(t); - } - else { + } else { keep_reading = 1; } gpr_slice_buffer_reset_and_unref(&t->read_buffer); @@ -1111,17 +1110,16 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { if (keep_reading) { switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { - case GRPC_ENDPOINT_DONE: - *success = 1; - return 1; - case GRPC_ENDPOINT_ERROR: - *success = 0; - return 1; - case GRPC_ENDPOINT_PENDING: - return 0; + case GRPC_ENDPOINT_DONE: + *success = 1; + return 1; + case GRPC_ENDPOINT_ERROR: + *success = 0; + return 1; + case GRPC_ENDPOINT_PENDING: + return 0; } - } - else { + } else { UNREF_TRANSPORT(t, "recv_data"); return 0; } @@ -1133,7 +1131,8 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { static void recv_data(void *tp, int success) { grpc_chttp2_transport *t = tp; - while (recv_data_loop(t, &success)); + while (recv_data_loop(t, &success)) + ; } /* -- cgit v1.2.3 From 4e53265f6470a8736967f9cbc2e0797ad04755ca Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 21 Aug 2015 14:01:47 -0700 Subject: Changed prefixed Client properties to distinguish private and public properties --- src/node/interop/interop_client.js | 4 ++-- src/node/src/client.js | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js index 9100edf243..2f8eaea41d 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, @@ -344,7 +344,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/src/client.js b/src/node/src/client.js index f288104e2b..ddd28e37b8 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -32,7 +32,7 @@ */ /** - * Server module + * Client module * @module */ @@ -272,7 +272,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); @@ -340,7 +340,7 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { metadata = {}; } 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); @@ -410,7 +410,7 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { metadata = {}; } 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); @@ -482,7 +482,7 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { metadata = {}; } 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); @@ -572,9 +572,9 @@ exports.makeClientConstructor = function(methods, serviceName) { 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; } /** -- cgit v1.2.3 From eb95b11bc1ce2a9ef6fd6fee728c7af43cf5536e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 24 Aug 2015 07:51:35 -0700 Subject: Turn off refcount debugging --- src/core/iomgr/tcp_posix.c | 4 ++-- src/core/security/secure_endpoint.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index 36ba3a7606..03be462960 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -104,7 +104,8 @@ static void tcp_free(grpc_tcp *tcp) { gpr_free(tcp); } -#define GRPC_TCP_REFCOUNT_DEBUG +/*#define GRPC_TCP_REFCOUNT_DEBUG*/ +#ifdef GRPC_TCP_REFCOUNT_DEBUG #define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, @@ -122,7 +123,6 @@ static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, reason, tcp->refcount.count, tcp->refcount.count + 1); gpr_ref(&tcp->refcount); } -#ifdef GRPC_TCP_REFCOUNT_DEBUG #else #define TCP_UNREF(tcp, reason) tcp_unref((tcp)) #define TCP_REF(tcp, reason) tcp_ref((tcp)) diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c index 4206c39318..b696e384fc 100644 --- a/src/core/security/secure_endpoint.c +++ b/src/core/security/secure_endpoint.c @@ -80,7 +80,8 @@ static void destroy(secure_endpoint *secure_ep) { gpr_free(ep); } -#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG +/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/ +#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG #define SECURE_ENDPOINT_UNREF(ep, reason) \ secure_endpoint_unref((ep), (reason), __FILE__, __LINE__) #define SECURE_ENDPOINT_REF(ep, reason) \ @@ -100,7 +101,6 @@ static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, ep, reason, ep->ref.count, ep->ref.count + 1); gpr_ref(&ep->ref); } -#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG #else #define SECURE_ENDPOINT_UNREF(ep, reason) secure_endpoint_unref((ep)) #define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep)) -- cgit v1.2.3 From d1ed567866e600955b49bfe87d5ee03570aad85a Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 24 Aug 2015 14:29:54 -0700 Subject: Update comments --- src/core/iomgr/endpoint.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/endpoint.h b/src/core/iomgr/endpoint.h index 38f1e46d67..d14d52d561 100644 --- a/src/core/iomgr/endpoint.h +++ b/src/core/iomgr/endpoint.h @@ -77,15 +77,19 @@ char *grpc_endpoint_get_peer(grpc_endpoint *ep); /* Write slices out to the socket. If the connection is ready for more data after the end of the call, it - returns GRPC_ENDPOINT_WRITE_DONE. - Otherwise it returns GRPC_ENDPOINT_WRITE_PENDING and calls cb when the - connection is ready for more data. */ + returns GRPC_ENDPOINT_DONE. + Otherwise it returns GRPC_ENDPOINT_PENDING and calls cb when the + connection is ready for more data. + \a slices may be mutated at will by the endpoint until cb is called. + No guarantee is made to the content of slices after a write EXCEPT that + it is a valid slice buffer. + */ grpc_endpoint_op_status grpc_endpoint_write( grpc_endpoint *ep, gpr_slice_buffer *slices, grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT; /* Causes any pending read/write callbacks to run immediately with - GRPC_ENDPOINT_CB_SHUTDOWN status */ + success==0 */ void grpc_endpoint_shutdown(grpc_endpoint *ep); void grpc_endpoint_destroy(grpc_endpoint *ep); -- cgit v1.2.3 From 1dc323b45e1a109c860806cb25e7eca21c29a3c0 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 25 Aug 2015 11:33:26 -0700 Subject: Spam cleanup --- src/core/iomgr/tcp_windows.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index 1cf2ca2131..469c382218 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -201,7 +201,6 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, /* Did we get data immediately ? Yay. */ if (info->wsa_error != WSAEWOULDBLOCK) { info->bytes_transfered = bytes_read; - gpr_log(GPR_DEBUG, "immread: %d bytes", bytes_read); return on_read(tcp, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } @@ -214,7 +213,6 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { info->wsa_error = wsa_error; - gpr_log(GPR_DEBUG, "immread: err=%d", wsa_error); return on_read(tcp, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } } -- cgit v1.2.3 From 4c8288ec010ed79bb50659fb6010b92a385e24ad Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Tue, 25 Aug 2015 01:51:49 +0000 Subject: The RPC Framework crust package --- src/python/grpcio/grpc/framework/crust/__init__.py | 30 ++ src/python/grpcio/grpc/framework/crust/_calls.py | 204 ++++++++ src/python/grpcio/grpc/framework/crust/_control.py | 545 +++++++++++++++++++++ src/python/grpcio/grpc/framework/crust/_service.py | 166 +++++++ .../grpcio/grpc/framework/crust/implementations.py | 352 +++++++++++++ .../_core_over_links_base_interface_test.py | 2 +- ...ust_over_core_over_links_face_interface_test.py | 160 ++++++ .../_crust_over_core_face_interface_test.py | 111 +++++ .../interfaces/face/_3069_test_constant.py | 37 ++ .../face/_blocking_invocation_inline_service.py | 9 +- .../_event_invocation_synchronous_event_service.py | 11 +- ...future_invocation_asynchronous_event_service.py | 17 +- .../framework/interfaces/face/_stock_service.py | 2 +- tools/run_tests/run_python.sh | 2 + 14 files changed, 1630 insertions(+), 18 deletions(-) create mode 100644 src/python/grpcio/grpc/framework/crust/__init__.py create mode 100644 src/python/grpcio/grpc/framework/crust/_calls.py create mode 100644 src/python/grpcio/grpc/framework/crust/_control.py create mode 100644 src/python/grpcio/grpc/framework/crust/_service.py create mode 100644 src/python/grpcio/grpc/framework/crust/implementations.py create mode 100644 src/python/grpcio_test/grpc_test/_crust_over_core_over_links_face_interface_test.py create mode 100644 src/python/grpcio_test/grpc_test/framework/_crust_over_core_face_interface_test.py create mode 100644 src/python/grpcio_test/grpc_test/framework/interfaces/face/_3069_test_constant.py (limited to 'src') diff --git a/src/python/grpcio/grpc/framework/crust/__init__.py b/src/python/grpcio/grpc/framework/crust/__init__.py new file mode 100644 index 0000000000..7086519106 --- /dev/null +++ b/src/python/grpcio/grpc/framework/crust/__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/grpc/framework/crust/_calls.py b/src/python/grpcio/grpc/framework/crust/_calls.py new file mode 100644 index 0000000000..f9077bedfe --- /dev/null +++ b/src/python/grpcio/grpc/framework/crust/_calls.py @@ -0,0 +1,204 @@ +# 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. + +"""Utility functions for invoking RPCs.""" + +from grpc.framework.crust import _control +from grpc.framework.interfaces.base import utilities +from grpc.framework.interfaces.face import face + +_ITERATOR_EXCEPTION_LOG_MESSAGE = 'Exception iterating over requests!' + +_EMPTY_COMPLETION = utilities.completion(None, None, None) + + +def _invoke(end, group, method, timeout, initial_metadata, payload, complete): + rendezvous = _control.Rendezvous(None, None) + operation_context, operator = end.operate( + group, method, utilities.full_subscription(rendezvous), timeout, + initial_metadata=initial_metadata, payload=payload, + completion=_EMPTY_COMPLETION if complete else None) + rendezvous.set_operator_and_context(operator, operation_context) + outcome = operation_context.add_termination_callback(rendezvous.set_outcome) + if outcome is not None: + rendezvous.set_outcome(outcome) + return rendezvous, operation_context, outcome + + +def _event_return_unary( + receiver, abortion_callback, rendezvous, operation_context, outcome, pool): + if outcome is None: + def in_pool(): + abortion = rendezvous.add_abortion_callback(abortion_callback) + if abortion is None: + try: + receiver.initial_metadata(rendezvous.initial_metadata()) + receiver.response(next(rendezvous)) + receiver.complete( + rendezvous.terminal_metadata(), rendezvous.code(), + rendezvous.details()) + except face.AbortionError: + pass + else: + abortion_callback(abortion) + pool.submit(_control.pool_wrap(in_pool, operation_context)) + return rendezvous + + +def _event_return_stream( + receiver, abortion_callback, rendezvous, operation_context, outcome, pool): + if outcome is None: + def in_pool(): + abortion = rendezvous.add_abortion_callback(abortion_callback) + if abortion is None: + try: + receiver.initial_metadata(rendezvous.initial_metadata()) + for response in rendezvous: + receiver.response(response) + receiver.complete( + rendezvous.terminal_metadata(), rendezvous.code(), + rendezvous.details()) + except face.AbortionError: + pass + else: + abortion_callback(abortion) + pool.submit(_control.pool_wrap(in_pool, operation_context)) + return rendezvous + + +def blocking_unary_unary( + end, group, method, timeout, with_call, initial_metadata, payload): + """Services in a blocking fashion a unary-unary servicer method.""" + rendezvous, unused_operation_context, unused_outcome = _invoke( + end, group, method, timeout, initial_metadata, payload, True) + if with_call: + return next(rendezvous, rendezvous) + else: + return next(rendezvous) + + +def future_unary_unary(end, group, method, timeout, initial_metadata, payload): + """Services a value-in value-out servicer method by returning a Future.""" + rendezvous, unused_operation_context, unused_outcome = _invoke( + end, group, method, timeout, initial_metadata, payload, True) + return rendezvous + + +def inline_unary_stream(end, group, method, timeout, initial_metadata, payload): + """Services a value-in stream-out servicer method.""" + rendezvous, unused_operation_context, unused_outcome = _invoke( + end, group, method, timeout, initial_metadata, payload, True) + return rendezvous + + +def blocking_stream_unary( + end, group, method, timeout, with_call, initial_metadata, payload_iterator, + pool): + """Services in a blocking fashion a stream-in value-out servicer method.""" + rendezvous, operation_context, outcome = _invoke( + end, group, method, timeout, initial_metadata, None, False) + if outcome is None: + def in_pool(): + for payload in payload_iterator: + rendezvous.consume(payload) + rendezvous.terminate() + pool.submit(_control.pool_wrap(in_pool, operation_context)) + if with_call: + return next(rendezvous), rendezvous + else: + return next(rendezvous) + else: + if with_call: + return next(rendezvous), rendezvous + else: + return next(rendezvous) + + +def future_stream_unary( + end, group, method, timeout, initial_metadata, payload_iterator, pool): + """Services a stream-in value-out servicer method by returning a Future.""" + rendezvous, operation_context, outcome = _invoke( + end, group, method, timeout, initial_metadata, None, False) + if outcome is None: + def in_pool(): + for payload in payload_iterator: + rendezvous.consume(payload) + rendezvous.terminate() + pool.submit(_control.pool_wrap(in_pool, operation_context)) + return rendezvous + + +def inline_stream_stream( + end, group, method, timeout, initial_metadata, payload_iterator, pool): + """Services a stream-in stream-out servicer method.""" + rendezvous, operation_context, outcome = _invoke( + end, group, method, timeout, initial_metadata, None, False) + if outcome is None: + def in_pool(): + for payload in payload_iterator: + rendezvous.consume(payload) + rendezvous.terminate() + pool.submit(_control.pool_wrap(in_pool, operation_context)) + return rendezvous + + +def event_unary_unary( + end, group, method, timeout, initial_metadata, payload, receiver, + abortion_callback, pool): + rendezvous, operation_context, outcome = _invoke( + end, group, method, timeout, initial_metadata, payload, True) + return _event_return_unary( + receiver, abortion_callback, rendezvous, operation_context, outcome, pool) + + +def event_unary_stream( + end, group, method, timeout, initial_metadata, payload, + receiver, abortion_callback, pool): + rendezvous, operation_context, outcome = _invoke( + end, group, method, timeout, initial_metadata, payload, True) + return _event_return_stream( + receiver, abortion_callback, rendezvous, operation_context, outcome, pool) + + +def event_stream_unary( + end, group, method, timeout, initial_metadata, receiver, abortion_callback, + pool): + rendezvous, operation_context, outcome = _invoke( + end, group, method, timeout, initial_metadata, None, False) + return _event_return_unary( + receiver, abortion_callback, rendezvous, operation_context, outcome, pool) + + +def event_stream_stream( + end, group, method, timeout, initial_metadata, receiver, abortion_callback, + pool): + rendezvous, operation_context, outcome = _invoke( + end, group, method, timeout, initial_metadata, None, False) + return _event_return_stream( + receiver, abortion_callback, rendezvous, operation_context, outcome, pool) diff --git a/src/python/grpcio/grpc/framework/crust/_control.py b/src/python/grpcio/grpc/framework/crust/_control.py new file mode 100644 index 0000000000..01de3c15bd --- /dev/null +++ b/src/python/grpcio/grpc/framework/crust/_control.py @@ -0,0 +1,545 @@ +# 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. + +"""State and behavior for translating between sync and async control flow.""" + +import collections +import enum +import sys +import threading +import time + +from grpc.framework.foundation import abandonment +from grpc.framework.foundation import callable_util +from grpc.framework.foundation import future +from grpc.framework.foundation import stream +from grpc.framework.interfaces.base import base +from grpc.framework.interfaces.base import utilities +from grpc.framework.interfaces.face import face + +_DONE_CALLBACK_LOG_MESSAGE = 'Exception calling Future "done" callback!' +_INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Crust) Internal Error! )-:' + +_CANNOT_SET_INITIAL_METADATA = ( + 'Could not set initial metadata - has it already been set, or has a ' + + 'payload already been sent?') +_CANNOT_SET_TERMINAL_METADATA = ( + 'Could not set terminal metadata - has it already been set, or has RPC ' + + 'completion already been indicated?') +_CANNOT_SET_CODE = ( + 'Could not set code - has it already been set, or has RPC completion ' + + 'already been indicated?') +_CANNOT_SET_DETAILS = ( + 'Could not set details - has it already been set, or has RPC completion ' + + 'already been indicated?') + + +class _DummyOperator(base.Operator): + + def advance( + self, initial_metadata=None, payload=None, completion=None, + allowance=None): + pass + +_DUMMY_OPERATOR = _DummyOperator() + + +class _Awaited( + collections.namedtuple('_Awaited', ('kind', 'value',))): + + @enum.unique + class Kind(enum.Enum): + NOT_YET_ARRIVED = 'not yet arrived' + ARRIVED = 'arrived' + +_NOT_YET_ARRIVED = _Awaited(_Awaited.Kind.NOT_YET_ARRIVED, None) +_ARRIVED_AND_NONE = _Awaited(_Awaited.Kind.ARRIVED, None) + + +class _Transitory( + collections.namedtuple('_Transitory', ('kind', 'value',))): + + @enum.unique + class Kind(enum.Enum): + NOT_YET_SEEN = 'not yet seen' + PRESENT = 'present' + GONE = 'gone' + +_NOT_YET_SEEN = _Transitory(_Transitory.Kind.NOT_YET_SEEN, None) +_GONE = _Transitory(_Transitory.Kind.GONE, None) + + +class _Termination( + collections.namedtuple( + '_Termination', ('terminated', 'abortion', 'abortion_error',))): + """Values indicating whether and how an RPC has terminated. + + Attributes: + terminated: A boolean indicating whether or not the RPC has terminated. + abortion: A face.Abortion value describing the RPC's abortion or None if the + RPC did not abort. + abortion_error: A face.AbortionError describing the RPC's abortion or None + if the RPC did not abort. + """ + +_NOT_TERMINATED = _Termination(False, None, None) + +_OPERATION_OUTCOME_TO_TERMINATION_CONSTRUCTOR = { + base.Outcome.COMPLETED: lambda *unused_args: _Termination(True, None, None), + base.Outcome.CANCELLED: lambda *args: _Termination( + True, face.Abortion(face.Abortion.Kind.CANCELLED, *args), + face.CancellationError(*args)), + base.Outcome.EXPIRED: lambda *args: _Termination( + True, face.Abortion(face.Abortion.Kind.EXPIRED, *args), + face.ExpirationError(*args)), + base.Outcome.LOCAL_SHUTDOWN: lambda *args: _Termination( + True, face.Abortion(face.Abortion.Kind.LOCAL_SHUTDOWN, *args), + face.LocalShutdownError(*args)), + base.Outcome.REMOTE_SHUTDOWN: lambda *args: _Termination( + True, face.Abortion(face.Abortion.Kind.REMOTE_SHUTDOWN, *args), + face.RemoteShutdownError(*args)), + base.Outcome.RECEPTION_FAILURE: lambda *args: _Termination( + True, face.Abortion(face.Abortion.Kind.NETWORK_FAILURE, *args), + face.NetworkError(*args)), + base.Outcome.TRANSMISSION_FAILURE: lambda *args: _Termination( + True, face.Abortion(face.Abortion.Kind.NETWORK_FAILURE, *args), + face.NetworkError(*args)), + base.Outcome.LOCAL_FAILURE: lambda *args: _Termination( + True, face.Abortion(face.Abortion.Kind.LOCAL_FAILURE, *args), + face.LocalError(*args)), + base.Outcome.REMOTE_FAILURE: lambda *args: _Termination( + True, face.Abortion(face.Abortion.Kind.REMOTE_FAILURE, *args), + face.RemoteError(*args)), +} + + +def _wait_once_until(condition, until): + if until is None: + condition.wait() + else: + remaining = until - time.time() + if remaining < 0: + raise future.TimeoutError() + else: + condition.wait(timeout=remaining) + + +def _done_callback_as_operation_termination_callback( + done_callback, rendezvous): + def operation_termination_callback(operation_outcome): + rendezvous.set_outcome(operation_outcome) + done_callback(rendezvous) + return operation_termination_callback + + +def _abortion_callback_as_operation_termination_callback( + rpc_abortion_callback, rendezvous_set_outcome): + def operation_termination_callback(operation_outcome): + termination = rendezvous_set_outcome(operation_outcome) + if termination.abortion is not None: + rpc_abortion_callback(termination.abortion) + return operation_termination_callback + + +class Rendezvous(base.Operator, future.Future, stream.Consumer, face.Call): + """A rendez-vous for the threads of an operation. + + Instances of this object present iterator and stream.Consumer interfaces for + interacting with application code and present a base.Operator interface and + maintain a base.Operator internally for interacting with base interface code. + """ + + def __init__(self, operator, operation_context): + self._condition = threading.Condition() + + self._operator = operator + self._operation_context = operation_context + + self._up_initial_metadata = _NOT_YET_ARRIVED + self._up_payload = None + self._up_allowance = 1 + self._up_completion = _NOT_YET_ARRIVED + self._down_initial_metadata = _NOT_YET_SEEN + self._down_payload = None + self._down_allowance = 1 + self._down_terminal_metadata = _NOT_YET_SEEN + self._down_code = _NOT_YET_SEEN + self._down_details = _NOT_YET_SEEN + + self._termination = _NOT_TERMINATED + + # The semantics of future.Future.cancel and future.Future.cancelled are + # slightly wonky, so they have to be tracked separately from the rest of the + # result of the RPC. This field tracks whether cancellation was requested + # prior to termination of the RPC + self._cancelled = False + + def set_operator_and_context(self, operator, operation_context): + with self._condition: + self._operator = operator + self._operation_context = operation_context + + def _down_completion(self): + if self._down_terminal_metadata.kind is _Transitory.Kind.NOT_YET_SEEN: + terminal_metadata = None + self._down_terminal_metadata = _GONE + elif self._down_terminal_metadata.kind is _Transitory.Kind.PRESENT: + terminal_metadata = self._down_terminal_metadata.value + self._down_terminal_metadata = _GONE + else: + terminal_metadata = None + if self._down_code.kind is _Transitory.Kind.NOT_YET_SEEN: + code = None + self._down_code = _GONE + elif self._down_code.kind is _Transitory.Kind.PRESENT: + code = self._down_code.value + self._down_code = _GONE + else: + code = None + if self._down_details.kind is _Transitory.Kind.NOT_YET_SEEN: + details = None + self._down_details = _GONE + elif self._down_details.kind is _Transitory.Kind.PRESENT: + details = self._down_details.value + self._down_details = _GONE + else: + details = None + return utilities.completion(terminal_metadata, code, details) + + def _set_outcome(self, outcome): + if not self._termination.terminated: + self._operator = _DUMMY_OPERATOR + self._operation_context = None + self._down_initial_metadata = _GONE + self._down_payload = None + self._down_terminal_metadata = _GONE + self._down_code = _GONE + self._down_details = _GONE + + if self._up_initial_metadata.kind is _Awaited.Kind.NOT_YET_ARRIVED: + initial_metadata = None + else: + initial_metadata = self._up_initial_metadata.value + if self._up_completion.kind is _Awaited.Kind.NOT_YET_ARRIVED: + terminal_metadata, code, details = None, None, None + else: + terminal_metadata = self._up_completion.value.terminal_metadata + code = self._up_completion.value.code + details = self._up_completion.value.message + self._termination = _OPERATION_OUTCOME_TO_TERMINATION_CONSTRUCTOR[ + outcome](initial_metadata, terminal_metadata, code, details) + + self._condition.notify_all() + + return self._termination + + def advance( + self, initial_metadata=None, payload=None, completion=None, + allowance=None): + with self._condition: + if initial_metadata is not None: + self._up_initial_metadata = _Awaited( + _Awaited.Kind.ARRIVED, initial_metadata) + if payload is not None: + if self._up_initial_metadata.kind is _Awaited.Kind.NOT_YET_ARRIVED: + self._up_initial_metadata = _ARRIVED_AND_NONE + self._up_payload = payload + self._up_allowance -= 1 + if completion is not None: + if self._up_initial_metadata.kind is _Awaited.Kind.NOT_YET_ARRIVED: + self._up_initial_metadata = _ARRIVED_AND_NONE + self._up_completion = _Awaited( + _Awaited.Kind.ARRIVED, completion) + if allowance is not None: + if self._down_payload is not None: + self._operator.advance(payload=self._down_payload) + self._down_payload = None + self._down_allowance += allowance - 1 + else: + self._down_allowance += allowance + self._condition.notify_all() + + def cancel(self): + with self._condition: + if self._operation_context is not None: + self._operation_context.cancel() + self._cancelled = True + return False + + def cancelled(self): + with self._condition: + return self._cancelled + + def running(self): + with self._condition: + return not self._termination.terminated + + def done(self): + with self._condition: + return self._termination.terminated + + def result(self, timeout=None): + until = None if timeout is None else time.time() + timeout + with self._condition: + while True: + if self._termination.terminated: + if self._termination.abortion is None: + return self._up_payload + elif self._termination.abortion.kind is face.Abortion.Kind.CANCELLED: + raise future.CancelledError() + else: + raise self._termination.abortion_error # pylint: disable=raising-bad-type + else: + _wait_once_until(self._condition, until) + + def exception(self, timeout=None): + until = None if timeout is None else time.time() + timeout + with self._condition: + while True: + if self._termination.terminated: + if self._termination.abortion is None: + return None + else: + return self._termination.abortion_error + else: + _wait_once_until(self._condition, until) + + def traceback(self, timeout=None): + until = None if timeout is None else time.time() + timeout + with self._condition: + while True: + if self._termination.terminated: + if self._termination.abortion_error is None: + return None + else: + abortion_error = self._termination.abortion_error + break + else: + _wait_once_until(self._condition, until) + + try: + raise abortion_error + except face.AbortionError: + return sys.exc_info()[2] + + def add_done_callback(self, fn): + with self._condition: + if self._operation_context is not None: + outcome = self._operation_context.add_termination_callback( + _done_callback_as_operation_termination_callback(fn, self)) + if outcome is None: + return + else: + self._set_outcome(outcome) + + fn(self) + + def consume(self, value): + with self._condition: + while True: + if self._termination.terminated: + return + elif 0 < self._down_allowance: + self._operator.advance(payload=value) + self._down_allowance -= 1 + return + else: + self._condition.wait() + + def terminate(self): + with self._condition: + if self._termination.terminated: + return + elif self._down_code.kind is _Transitory.Kind.GONE: + # Conform to specified idempotence of terminate by ignoring extra calls. + return + else: + completion = self._down_completion() + self._operator.advance(completion=completion) + + def consume_and_terminate(self, value): + with self._condition: + while True: + if self._termination.terminated: + return + elif 0 < self._down_allowance: + completion = self._down_completion() + self._operator.advance(payload=value, completion=completion) + return + else: + self._condition.wait() + + def __iter__(self): + return self + + def next(self): + with self._condition: + while True: + if self._termination.abortion_error is not None: + raise self._termination.abortion_error + elif self._up_payload is not None: + payload = self._up_payload + self._up_payload = None + if self._up_completion.kind is _Awaited.Kind.NOT_YET_ARRIVED: + self._operator.advance(allowance=1) + return payload + elif self._up_completion.kind is _Awaited.Kind.ARRIVED: + raise StopIteration() + else: + self._condition.wait() + + def is_active(self): + with self._condition: + return not self._termination.terminated + + def time_remaining(self): + if self._operation_context is None: + return 0 + else: + return self._operation_context.time_remaining() + + def add_abortion_callback(self, abortion_callback): + with self._condition: + if self._operation_context is None: + return self._termination.abortion + else: + outcome = self._operation_context.add_termination_callback( + _abortion_callback_as_operation_termination_callback( + abortion_callback, self.set_outcome)) + if outcome is not None: + return self._set_outcome(outcome).abortion + else: + return self._termination.abortion + + def initial_metadata(self): + with self._condition: + while True: + if self._up_initial_metadata.kind is _Awaited.Kind.ARRIVED: + return self._up_initial_metadata.value + elif self._termination.terminated: + return None + else: + self._condition.wait() + + def terminal_metadata(self): + with self._condition: + while True: + if self._up_completion.kind is _Awaited.Kind.ARRIVED: + return self._up_completion.value.terminal_metadata + elif self._termination.terminated: + return None + else: + self._condition.wait() + + def code(self): + with self._condition: + while True: + if self._up_completion.kind is _Awaited.Kind.ARRIVED: + return self._up_completion.value.code + elif self._termination.terminated: + return None + else: + self._condition.wait() + + def details(self): + with self._condition: + while True: + if self._up_completion.kind is _Awaited.Kind.ARRIVED: + return self._up_completion.value.message + elif self._termination.terminated: + return None + else: + self._condition.wait() + + def set_initial_metadata(self, initial_metadata): + with self._condition: + if (self._down_initial_metadata.kind is not + _Transitory.Kind.NOT_YET_SEEN): + raise ValueError(_CANNOT_SET_INITIAL_METADATA) + else: + self._down_initial_metadata = _GONE + self._operator.advance(initial_metadata=initial_metadata) + + def set_terminal_metadata(self, terminal_metadata): + with self._condition: + if (self._down_terminal_metadata.kind is not + _Transitory.Kind.NOT_YET_SEEN): + raise ValueError(_CANNOT_SET_TERMINAL_METADATA) + else: + self._down_terminal_metadata = _Transitory( + _Transitory.Kind.PRESENT, terminal_metadata) + + def set_code(self, code): + with self._condition: + if self._down_code.kind is not _Transitory.Kind.NOT_YET_SEEN: + raise ValueError(_CANNOT_SET_CODE) + else: + self._down_code = _Transitory(_Transitory.Kind.PRESENT, code) + + def set_details(self, details): + with self._condition: + if self._down_details.kind is not _Transitory.Kind.NOT_YET_SEEN: + raise ValueError(_CANNOT_SET_DETAILS) + else: + self._down_details = _Transitory(_Transitory.Kind.PRESENT, details) + + def set_outcome(self, outcome): + with self._condition: + return self._set_outcome(outcome) + + +def pool_wrap(behavior, operation_context): + """Wraps an operation-related behavior so that it may be called in a pool. + + Args: + behavior: A callable related to carrying out an operation. + operation_context: A base_interfaces.OperationContext for the operation. + + Returns: + A callable that when called carries out the behavior of the given callable + and handles whatever exceptions it raises appropriately. + """ + def translation(*args): + try: + behavior(*args) + except ( + abandonment.Abandoned, + face.CancellationError, + face.ExpirationError, + face.LocalShutdownError, + face.RemoteShutdownError, + face.NetworkError, + face.RemoteError, + ) as e: + if operation_context.outcome() is None: + operation_context.fail(e) + except Exception as e: + operation_context.fail(e) + return callable_util.with_exceptions_logged( + translation, _INTERNAL_ERROR_LOG_MESSAGE) diff --git a/src/python/grpcio/grpc/framework/crust/_service.py b/src/python/grpcio/grpc/framework/crust/_service.py new file mode 100644 index 0000000000..2455a58f59 --- /dev/null +++ b/src/python/grpcio/grpc/framework/crust/_service.py @@ -0,0 +1,166 @@ +# 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. + +"""Behaviors for servicing RPCs.""" + +from grpc.framework.crust import _control +from grpc.framework.foundation import abandonment +from grpc.framework.interfaces.base import utilities +from grpc.framework.interfaces.face import face + + +class _ServicerContext(face.ServicerContext): + + def __init__(self, rendezvous): + self._rendezvous = rendezvous + + def is_active(self): + return self._rendezvous.is_active() + + def time_remaining(self): + return self._rendezvous.time_remaining() + + def add_abortion_callback(self, abortion_callback): + return self._rendezvous.add_abortion_callback(abortion_callback) + + def cancel(self): + self._rendezvous.cancel() + + def invocation_metadata(self): + return self._rendezvous.initial_metadata() + + def initial_metadata(self, initial_metadata): + self._rendezvous.set_initial_metadata(initial_metadata) + + def terminal_metadata(self, terminal_metadata): + self._rendezvous.set_terminal_metadata(terminal_metadata) + + def code(self, code): + self._rendezvous.set_code(code) + + def details(self, details): + self._rendezvous.set_details(details) + + +def _adaptation(pool, in_pool): + def adaptation(operator, operation_context): + rendezvous = _control.Rendezvous(operator, operation_context) + outcome = operation_context.add_termination_callback(rendezvous.set_outcome) + if outcome is None: + pool.submit(_control.pool_wrap(in_pool, operation_context), rendezvous) + return utilities.full_subscription(rendezvous) + else: + raise abandonment.Abandoned() + return adaptation + + +def adapt_inline_unary_unary(method, pool): + def in_pool(rendezvous): + request = next(rendezvous) + response = method(request, _ServicerContext(rendezvous)) + rendezvous.consume_and_terminate(response) + return _adaptation(pool, in_pool) + + +def adapt_inline_unary_stream(method, pool): + def in_pool(rendezvous): + request = next(rendezvous) + response_iterator = method(request, _ServicerContext(rendezvous)) + for response in response_iterator: + rendezvous.consume(response) + rendezvous.terminate() + return _adaptation(pool, in_pool) + + +def adapt_inline_stream_unary(method, pool): + def in_pool(rendezvous): + response = method(rendezvous, _ServicerContext(rendezvous)) + rendezvous.consume_and_terminate(response) + return _adaptation(pool, in_pool) + + +def adapt_inline_stream_stream(method, pool): + def in_pool(rendezvous): + response_iterator = method(rendezvous, _ServicerContext(rendezvous)) + for response in response_iterator: + rendezvous.consume(response) + rendezvous.terminate() + return _adaptation(pool, in_pool) + + +def adapt_event_unary_unary(method, pool): + def in_pool(rendezvous): + request = next(rendezvous) + method( + request, rendezvous.consume_and_terminate, _ServicerContext(rendezvous)) + return _adaptation(pool, in_pool) + + +def adapt_event_unary_stream(method, pool): + def in_pool(rendezvous): + request = next(rendezvous) + method(request, rendezvous, _ServicerContext(rendezvous)) + return _adaptation(pool, in_pool) + + +def adapt_event_stream_unary(method, pool): + def in_pool(rendezvous): + request_consumer = method( + rendezvous.consume_and_terminate, _ServicerContext(rendezvous)) + for request in rendezvous: + request_consumer.consume(request) + request_consumer.terminate() + return _adaptation(pool, in_pool) + + +def adapt_event_stream_stream(method, pool): + def in_pool(rendezvous): + request_consumer = method(rendezvous, _ServicerContext(rendezvous)) + for request in rendezvous: + request_consumer.consume(request) + request_consumer.terminate() + return _adaptation(pool, in_pool) + + +def adapt_multi_method(multi_method, pool): + def adaptation(group, method, operator, operation_context): + rendezvous = _control.Rendezvous(operator, operation_context) + outcome = operation_context.add_termination_callback(rendezvous.set_outcome) + if outcome is None: + def in_pool(): + request_consumer = multi_method( + group, method, rendezvous, _ServicerContext(rendezvous)) + for request in rendezvous: + request_consumer.consume(request) + request_consumer.terminate() + pool.submit(_control.pool_wrap(in_pool, operation_context), rendezvous) + return utilities.full_subscription(rendezvous) + else: + raise abandonment.Abandoned() + return adaptation diff --git a/src/python/grpcio/grpc/framework/crust/implementations.py b/src/python/grpcio/grpc/framework/crust/implementations.py new file mode 100644 index 0000000000..12f7e79641 --- /dev/null +++ b/src/python/grpcio/grpc/framework/crust/implementations.py @@ -0,0 +1,352 @@ +# 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 Crust layer of RPC Framework.""" + +from grpc.framework.common import cardinality +from grpc.framework.common import style +from grpc.framework.crust import _calls +from grpc.framework.crust import _service +from grpc.framework.interfaces.base import base +from grpc.framework.interfaces.face import face + + +class _BaseServicer(base.Servicer): + + def __init__(self, adapted_methods, adapted_multi_method): + self._adapted_methods = adapted_methods + self._adapted_multi_method = adapted_multi_method + + def service(self, group, method, context, output_operator): + adapted_method = self._adapted_methods.get((group, method), None) + if adapted_method is not None: + return adapted_method(output_operator, context) + elif self._adapted_multi_method is not None: + try: + return self._adapted_multi_method.service( + group, method, output_operator, context) + except face.NoSuchMethodError: + raise base.NoSuchMethodError() + else: + raise base.NoSuchMethodError() + + +class _UnaryUnaryMultiCallable(face.UnaryUnaryMultiCallable): + + def __init__(self, end, group, method, pool): + self._end = end + self._group = group + self._method = method + self._pool = pool + + def __call__( + self, request, timeout, metadata=None, with_call=False): + return _calls.blocking_unary_unary( + self._end, self._group, self._method, timeout, with_call, + metadata, request) + + def future(self, request, timeout, metadata=None): + return _calls.future_unary_unary( + self._end, self._group, self._method, timeout, metadata, + request) + + def event( + self, request, receiver, abortion_callback, timeout, + metadata=None): + return _calls.event_unary_unary( + self._end, self._group, self._method, timeout, metadata, + request, receiver, abortion_callback, self._pool) + + +class _UnaryStreamMultiCallable(face.UnaryStreamMultiCallable): + + def __init__(self, end, group, method, pool): + self._end = end + self._group = group + self._method = method + self._pool = pool + + def __call__(self, request, timeout, metadata=None): + return _calls.inline_unary_stream( + self._end, self._group, self._method, timeout, metadata, + request) + + def event( + self, request, receiver, abortion_callback, timeout, + metadata=None): + return _calls.event_unary_stream( + self._end, self._group, self._method, timeout, metadata, + request, receiver, abortion_callback, self._pool) + + +class _StreamUnaryMultiCallable(face.StreamUnaryMultiCallable): + + def __init__(self, end, group, method, pool): + self._end = end + self._group = group + self._method = method + self._pool = pool + + def __call__( + self, request_iterator, timeout, metadata=None, + with_call=False): + return _calls.blocking_stream_unary( + self._end, self._group, self._method, timeout, with_call, + metadata, request_iterator, self._pool) + + def future(self, request_iterator, timeout, metadata=None): + return _calls.future_stream_unary( + self._end, self._group, self._method, timeout, metadata, + request_iterator, self._pool) + + def event( + self, receiver, abortion_callback, timeout, metadata=None): + return _calls.event_stream_unary( + self._end, self._group, self._method, timeout, metadata, + receiver, abortion_callback, self._pool) + + +class _StreamStreamMultiCallable(face.StreamStreamMultiCallable): + + def __init__(self, end, group, method, pool): + self._end = end + self._group = group + self._method = method + self._pool = pool + + def __call__(self, request_iterator, timeout, metadata=None): + return _calls.inline_stream_stream( + self._end, self._group, self._method, timeout, metadata, + request_iterator, self._pool) + + def event( + self, receiver, abortion_callback, timeout, metadata=None): + return _calls.event_stream_stream( + self._end, self._group, self._method, timeout, metadata, + receiver, abortion_callback, self._pool) + + +class _GenericStub(face.GenericStub): + """An face.GenericStub implementation.""" + + def __init__(self, end, pool): + self._end = end + self._pool = pool + + def blocking_unary_unary( + self, group, method, request, timeout, metadata=None, + with_call=None): + return _calls.blocking_unary_unary( + self._end, group, method, timeout, with_call, metadata, + request) + + def future_unary_unary( + self, group, method, request, timeout, metadata=None): + return _calls.future_unary_unary( + self._end, group, method, timeout, metadata, request) + + def inline_unary_stream( + self, group, method, request, timeout, metadata=None): + return _calls.inline_unary_stream( + self._end, group, method, timeout, metadata, request) + + def blocking_stream_unary( + self, group, method, request_iterator, timeout, metadata=None, + with_call=None): + return _calls.blocking_stream_unary( + self._end, group, method, timeout, with_call, metadata, + request_iterator, self._pool) + + def future_stream_unary( + self, group, method, request_iterator, timeout, metadata=None): + return _calls.future_stream_unary( + self._end, group, method, timeout, metadata, + request_iterator, self._pool) + + def inline_stream_stream( + self, group, method, request_iterator, timeout, metadata=None): + return _calls.inline_stream_stream( + self._end, group, method, timeout, metadata, + request_iterator, self._pool) + + def event_unary_unary( + self, group, method, request, receiver, abortion_callback, timeout, + metadata=None): + return _calls.event_unary_unary( + self._end, group, method, timeout, metadata, request, + receiver, abortion_callback, self._pool) + + def event_unary_stream( + self, group, method, request, receiver, abortion_callback, timeout, + metadata=None): + return _calls.event_unary_stream( + self._end, group, method, timeout, metadata, request, + receiver, abortion_callback, self._pool) + + def event_stream_unary( + self, group, method, receiver, abortion_callback, timeout, + metadata=None): + return _calls.event_stream_unary( + self._end, group, method, timeout, metadata, receiver, + abortion_callback, self._pool) + + def event_stream_stream( + self, group, method, receiver, abortion_callback, timeout, + metadata=None): + return _calls.event_stream_stream( + self._end, group, method, timeout, metadata, receiver, + abortion_callback, self._pool) + + def unary_unary(self, group, method): + return _UnaryUnaryMultiCallable(self._end, group, method, self._pool) + + def unary_stream(self, group, method): + return _UnaryStreamMultiCallable(self._end, group, method, self._pool) + + def stream_unary(self, group, method): + return _StreamUnaryMultiCallable(self._end, group, method, self._pool) + + def stream_stream(self, group, method): + return _StreamStreamMultiCallable(self._end, group, method, self._pool) + + +class _DynamicStub(face.DynamicStub): + """An face.DynamicStub implementation.""" + + def __init__(self, end, group, cardinalities, pool): + self._end = end + self._group = group + self._cardinalities = cardinalities + self._pool = pool + + def __getattr__(self, attr): + method_cardinality = self._cardinalities.get(attr) + if method_cardinality is cardinality.Cardinality.UNARY_UNARY: + return _UnaryUnaryMultiCallable(self._end, self._group, attr, self._pool) + elif method_cardinality is cardinality.Cardinality.UNARY_STREAM: + return _UnaryStreamMultiCallable(self._end, self._group, attr, self._pool) + elif method_cardinality is cardinality.Cardinality.STREAM_UNARY: + return _StreamUnaryMultiCallable(self._end, self._group, attr, self._pool) + elif method_cardinality is cardinality.Cardinality.STREAM_STREAM: + return _StreamStreamMultiCallable( + self._end, self._group, attr, self._pool) + else: + raise AttributeError('_DynamicStub object has no attribute "%s"!' % attr) + + +def _adapt_method_implementations(method_implementations, pool): + adapted_implementations = {} + for name, method_implementation in method_implementations.iteritems(): + if method_implementation.style is style.Service.INLINE: + if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: + adapted_implementations[name] = _service.adapt_inline_unary_unary( + method_implementation.unary_unary_inline, pool) + elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: + adapted_implementations[name] = _service.adapt_inline_unary_stream( + method_implementation.unary_stream_inline, pool) + elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: + adapted_implementations[name] = _service.adapt_inline_stream_unary( + method_implementation.stream_unary_inline, pool) + elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: + adapted_implementations[name] = _service.adapt_inline_stream_stream( + method_implementation.stream_stream_inline, pool) + elif method_implementation.style is style.Service.EVENT: + if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY: + adapted_implementations[name] = _service.adapt_event_unary_unary( + method_implementation.unary_unary_event, pool) + elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM: + adapted_implementations[name] = _service.adapt_event_unary_stream( + method_implementation.unary_stream_event, pool) + elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY: + adapted_implementations[name] = _service.adapt_event_stream_unary( + method_implementation.stream_unary_event, pool) + elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM: + adapted_implementations[name] = _service.adapt_event_stream_stream( + method_implementation.stream_stream_event, pool) + return adapted_implementations + + +def servicer(method_implementations, multi_method_implementation, pool): + """Creates a base.Servicer. + + It is guaranteed that any passed face.MultiMethodImplementation will + only be called to service an RPC if there is no + face.MethodImplementation for the RPC method in the passed + method_implementations dictionary. + + Args: + method_implementations: A dictionary from RPC method name to + face.MethodImplementation object to be used to service the named + RPC method. + multi_method_implementation: An face.MultiMethodImplementation to be + used to service any RPCs not serviced by the + face.MethodImplementations given in the method_implementations + dictionary, or None. + pool: A thread pool. + + Returns: + A base.Servicer that services RPCs via the given implementations. + """ + adapted_implementations = _adapt_method_implementations( + method_implementations, pool) + adapted_multi_method_implementation = _service.adapt_multi_method( + multi_method_implementation, pool) + return _BaseServicer( + adapted_implementations, adapted_multi_method_implementation) + + +def generic_stub(end, pool): + """Creates an face.GenericStub. + + Args: + end: A base.End. + pool: A futures.ThreadPoolExecutor. + + Returns: + A face.GenericStub that performs RPCs via the given base.End. + """ + return _GenericStub(end, pool) + + +def dynamic_stub(end, group, cardinalities, pool): + """Creates an face.DynamicStub. + + Args: + end: A base.End. + group: The group identifier for all RPCs to be made with the created + face.DynamicStub. + cardinalities: A dict from method identifier to cardinality.Cardinality + value identifying the cardinality of every RPC method to be supported by + the created face.DynamicStub. + pool: A futures.ThreadPoolExecutor. + + Returns: + A face.DynamicStub that performs RPCs via the given base.End. + """ + return _DynamicStub(end, group, cardinalities, pool) 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 72b1ae5642..7fa90fe35f 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 @@ -27,7 +27,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. -"""Tests the RPC Framework Core's implementation of the Base interface.""" +"""Tests Base interface compliance of the core-over-gRPC-links stack.""" import collections import logging 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 new file mode 100644 index 0000000000..25b99cbbaf --- /dev/null +++ b/src/python/grpcio_test/grpc_test/_crust_over_core_over_links_face_interface_test.py @@ -0,0 +1,160 @@ +# 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 compliance of the crust-over-core-over-gRPC-links stack.""" + +import collections +import unittest + +from grpc._adapter import _intermediary_low +from grpc._links import invocation +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 +from grpc_test import 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( + 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): + pool = logging_pool.pool(test_constants.POOL_SIZE) + servicer = crust_implementations.servicer( + method_implementations, multi_method_implementation, pool) + serialization_behaviors = _serialization_behaviors_from_test_methods( + methods) + invocation_end_link = core_implementations.invocation_end_link() + service_end_link = core_implementations.service_end_link( + servicer, test_constants.DEFAULT_TIMEOUT, + test_constants.MAXIMUM_TIMEOUT) + service_grpc_link = service.service_link( + serialization_behaviors.request_deserializers, + serialization_behaviors.response_serializers) + 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', + serialization_behaviors.request_serializers, + serialization_behaviors.response_deserializers) + + invocation_end_link.join_link(invocation_grpc_link) + invocation_grpc_link.join_link(invocation_end_link) + service_grpc_link.join_link(service_end_link) + service_end_link.join_link(service_grpc_link) + service_end_link.start() + invocation_end_link.start() + invocation_grpc_link.start() + service_grpc_link.start() + + generic_stub = crust_implementations.generic_stub(invocation_end_link, pool) + # TODO(nathaniel): Add a "groups" attribute to _digest.TestServiceDigest. + group = 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()} + dynamic_stub = crust_implementations.dynamic_stub( + invocation_end_link, group, cardinalities, pool) + + return generic_stub, {group: dynamic_stub}, ( + invocation_end_link, invocation_grpc_link, service_grpc_link, + service_end_link, pool) + + def destantiate(self, memo): + (invocation_end_link, invocation_grpc_link, service_grpc_link, + service_end_link, pool) = memo + invocation_end_link.stop(0).wait() + invocation_grpc_link.stop() + service_grpc_link.stop_gracefully() + service_end_link.stop(0).wait() + invocation_end_link.join_link(utilities.NULL_LINK) + invocation_grpc_link.join_link(utilities.NULL_LINK) + service_grpc_link.join_link(utilities.NULL_LINK) + service_end_link.join_link(utilities.NULL_LINK) + pool.shutdown(wait=True) + + def invocation_metadata(self): + return test_common.INVOCATION_INITIAL_METADATA + + def initial_metadata(self): + return test_common.SERVICE_INITIAL_METADATA + + def terminal_metadata(self): + return test_common.SERVICE_TERMINAL_METADATA + + def code(self): + return _intermediary_low.Code.OK + + def details(self): + return 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/framework/_crust_over_core_face_interface_test.py b/src/python/grpcio_test/grpc_test/framework/_crust_over_core_face_interface_test.py new file mode 100644 index 0000000000..30bb85f6c3 --- /dev/null +++ b/src/python/grpcio_test/grpc_test/framework/_crust_over_core_face_interface_test.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. + +"""Tests Face interface compliance of the crust-over-core stack.""" + +import collections +import unittest + +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.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 _Implementation(test_interfaces.Implementation): + + def instantiate( + self, methods, method_implementations, multi_method_implementation): + pool = logging_pool.pool(test_constants.POOL_SIZE) + servicer = crust_implementations.servicer( + method_implementations, multi_method_implementation, pool) + + service_end_link = core_implementations.service_end_link( + servicer, test_constants.DEFAULT_TIMEOUT, + test_constants.MAXIMUM_TIMEOUT) + invocation_end_link = core_implementations.invocation_end_link() + invocation_end_link.join_link(service_end_link) + service_end_link.join_link(invocation_end_link) + service_end_link.start() + invocation_end_link.start() + + generic_stub = crust_implementations.generic_stub(invocation_end_link, pool) + # TODO(nathaniel): Add a "groups" attribute to _digest.TestServiceDigest. + group = 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()} + dynamic_stub = crust_implementations.dynamic_stub( + invocation_end_link, group, cardinalities, pool) + + return generic_stub, {group: dynamic_stub}, ( + invocation_end_link, service_end_link, pool) + + def destantiate(self, memo): + invocation_end_link, service_end_link, pool = memo + invocation_end_link.stop(0).wait() + service_end_link.stop(0).wait() + invocation_end_link.join_link(utilities.NULL_LINK) + service_end_link.join_link(utilities.NULL_LINK) + pool.shutdown(wait=True) + + def invocation_metadata(self): + return object() + + def initial_metadata(self): + return object() + + def terminal_metadata(self): + return object() + + def code(self): + return object() + + def details(self): + return object() + + def metadata_transmitted(self, original_metadata, transmitted_metadata): + return original_metadata is 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/framework/interfaces/face/_3069_test_constant.py b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_3069_test_constant.py new file mode 100644 index 0000000000..363d9ce8f1 --- /dev/null +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_3069_test_constant.py @@ -0,0 +1,37 @@ +# 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. + +"""A test constant working around issue 3069.""" + +# test_constants is referenced from specification in this module. +from grpc_test.framework.common import test_constants # pylint: disable=unused-import + +# TODO(issue 3069): Replace uses of this constant with +# test_constants.SHORT_TIMEOUT. +REALLY_SHORT_TIMEOUT = 0.1 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 857ad5cf3e..8804f3f223 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 @@ -37,6 +37,7 @@ from grpc.framework.interfaces.face import face from grpc_test.framework.common import test_constants from grpc_test.framework.common import test_control from grpc_test.framework.common import test_coverage +from grpc_test.framework.interfaces.face import _3069_test_constant from grpc_test.framework.interfaces.face import _digest from grpc_test.framework.interfaces.face import _stock_service from grpc_test.framework.interfaces.face import test_interfaces # pylint: disable=unused-import @@ -170,7 +171,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(), self.assertRaises( face.ExpirationError): self._invoker.blocking(group, method)( - request, test_constants.SHORT_TIMEOUT) + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) def testExpiredUnaryRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -181,7 +182,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(), self.assertRaises( face.ExpirationError): response_iterator = self._invoker.blocking(group, method)( - request, test_constants.SHORT_TIMEOUT) + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) list(response_iterator) def testExpiredStreamRequestUnaryResponse(self): @@ -193,7 +194,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(), self.assertRaises( face.ExpirationError): self._invoker.blocking(group, method)( - iter(requests), test_constants.SHORT_TIMEOUT) + iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) def testExpiredStreamRequestStreamResponse(self): for (group, method), test_messages_sequence in ( @@ -204,7 +205,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(), self.assertRaises( face.ExpirationError): response_iterator = self._invoker.blocking(group, method)( - iter(requests), test_constants.SHORT_TIMEOUT) + iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) list(response_iterator) def testFailedUnaryRequestUnaryResponse(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 ea5cdeaea3..5a78b4bed2 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 @@ -37,6 +37,7 @@ from grpc.framework.interfaces.face import face from grpc_test.framework.common import test_constants from grpc_test.framework.common import test_control from grpc_test.framework.common import test_coverage +from grpc_test.framework.interfaces.face import _3069_test_constant from grpc_test.framework.interfaces.face import _digest from grpc_test.framework.interfaces.face import _receiver from grpc_test.framework.interfaces.face import _stock_service @@ -264,7 +265,8 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(): self._invoker.event(group, method)( - request, receiver, receiver.abort, test_constants.SHORT_TIMEOUT) + request, receiver, receiver.abort, + _3069_test_constant.REALLY_SHORT_TIMEOUT) receiver.block_until_terminated() self.assertIs(face.Abortion.Kind.EXPIRED, receiver.abortion().kind) @@ -278,7 +280,8 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(): self._invoker.event(group, method)( - request, receiver, receiver.abort, test_constants.SHORT_TIMEOUT) + request, receiver, receiver.abort, + _3069_test_constant.REALLY_SHORT_TIMEOUT) receiver.block_until_terminated() self.assertIs(face.Abortion.Kind.EXPIRED, receiver.abortion().kind) @@ -290,7 +293,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): receiver = _receiver.Receiver() self._invoker.event(group, method)( - receiver, receiver.abort, test_constants.SHORT_TIMEOUT) + receiver, receiver.abort, _3069_test_constant.REALLY_SHORT_TIMEOUT) receiver.block_until_terminated() self.assertIs(face.Abortion.Kind.EXPIRED, receiver.abortion().kind) @@ -303,7 +306,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): receiver = _receiver.Receiver() call_consumer = self._invoker.event(group, method)( - receiver, receiver.abort, test_constants.SHORT_TIMEOUT) + receiver, receiver.abort, _3069_test_constant.REALLY_SHORT_TIMEOUT) for request in requests: call_consumer.consume(request) receiver.block_until_terminated() 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 a649362cef..d1107e1576 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 @@ -40,6 +40,7 @@ from grpc.framework.interfaces.face import face from grpc_test.framework.common import test_constants from grpc_test.framework.common import test_control from grpc_test.framework.common import test_coverage +from grpc_test.framework.interfaces.face import _3069_test_constant from grpc_test.framework.interfaces.face import _digest from grpc_test.framework.interfaces.face import _stock_service from grpc_test.framework.interfaces.face import test_interfaces # pylint: disable=unused-import @@ -265,7 +266,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(): response_future = self._invoker.future( - group, method)(request, test_constants.SHORT_TIMEOUT) + group, method)(request, _3069_test_constant.REALLY_SHORT_TIMEOUT) self.assertIsInstance( response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): @@ -279,7 +280,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(): response_iterator = self._invoker.future(group, method)( - request, test_constants.SHORT_TIMEOUT) + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): list(response_iterator) @@ -291,7 +292,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(): response_future = self._invoker.future(group, method)( - iter(requests), test_constants.SHORT_TIMEOUT) + iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) self.assertIsInstance( response_future.exception(), face.ExpirationError) with self.assertRaises(face.ExpirationError): @@ -305,7 +306,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.pause(): response_iterator = self._invoker.future(group, method)( - iter(requests), test_constants.SHORT_TIMEOUT) + iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) with self.assertRaises(face.ExpirationError): list(response_iterator) @@ -317,7 +318,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.fail(): response_future = self._invoker.future(group, method)( - request, test_constants.SHORT_TIMEOUT) + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) # Because the servicer fails outside of the thread from which the # servicer-side runtime called into it its failure is @@ -340,7 +341,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): # expiration of the RPC. with self._control.fail(), self.assertRaises(face.ExpirationError): response_iterator = self._invoker.future(group, method)( - request, test_constants.SHORT_TIMEOUT) + request, _3069_test_constant.REALLY_SHORT_TIMEOUT) list(response_iterator) def testFailedStreamRequestUnaryResponse(self): @@ -351,7 +352,7 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): with self._control.fail(): response_future = self._invoker.future(group, method)( - iter(requests), test_constants.SHORT_TIMEOUT) + iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) # Because the servicer fails outside of the thread from which the # servicer-side runtime called into it its failure is @@ -374,5 +375,5 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): # expiration of the RPC. with self._control.fail(), self.assertRaises(face.ExpirationError): response_iterator = self._invoker.future(group, method)( - iter(requests), test_constants.SHORT_TIMEOUT) + iter(requests), _3069_test_constant.REALLY_SHORT_TIMEOUT) list(response_iterator) diff --git a/src/python/grpcio_test/grpc_test/framework/interfaces/face/_stock_service.py b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_stock_service.py index 1dd2ec3633..808e2c4e36 100644 --- a/src/python/grpcio_test/grpc_test/framework/interfaces/face/_stock_service.py +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/face/_stock_service.py @@ -1,4 +1,4 @@ -B# Copyright 2015, Google Inc. +# Copyright 2015, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh index 6fdca93fd5..8a11126853 100755 --- a/tools/run_tests/run_python.sh +++ b/tools/run_tests/run_python.sh @@ -45,6 +45,8 @@ source "python"$PYVER"_virtual_environment"/bin/activate # py.test (or find another tool or *something*) that's acceptable to the rest of # the team... "python"$PYVER -m grpc_test._core_over_links_base_interface_test +"python"$PYVER -m grpc_test._crust_over_core_over_links_face_interface_test +"python"$PYVER -m grpc_test.framework._crust_over_core_face_interface_test "python"$PYVER -m grpc_test.framework.core._base_interface_test "python"$PYVER $GRPCIO_TEST/setup.py test -a "-n8 --cov=grpc --junitxml=./report.xml" -- cgit v1.2.3 From f886985d2c775d480079ea979323ae22efc0afc6 Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Tue, 25 Aug 2015 15:24:49 -0700 Subject: refactor census_timestamp --- include/grpc/census.h | 12 ++++++++---- src/core/census/operation.c | 8 +++++++- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/include/grpc/census.h b/include/grpc/census.h index 591d0dc52b..ef6275fe58 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -129,10 +129,14 @@ void census_set_trace_mask(int trace_mask); each logical operation. */ /** - This structure (opaquely) represents a timestamp as used by census to - record the time at which an RPC operation begins. + This structure represents a timestamp as used by census to record the time + at which an operation begins. */ -typedef struct census_timestamp census_timestamp; +typedef struct { + /* Use gpr_timespec for default implementation. High performance + * implementations should use a cycle-counter based timestamp. */ + gpr_timespec ts; +} census_timestamp; /** Mark the beginning of an RPC operation. The information required to call the @@ -148,7 +152,7 @@ typedef struct census_timestamp census_timestamp; @return A timestamp representing the operation start time. */ -census_timestamp *census_start_rpc_op_timestamp(void); +census_timestamp census_start_rpc_op_timestamp(void); /** Represent functions to map RPC name ID to service/method names. Census diff --git a/src/core/census/operation.c b/src/core/census/operation.c index a0196da614..118eb0a47a 100644 --- a/src/core/census/operation.c +++ b/src/core/census/operation.c @@ -34,7 +34,13 @@ /* TODO(aveitch): These are all placeholder implementations. */ -census_timestamp *census_start_rpc_op_timestamp(void) { return NULL; } +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, -- cgit v1.2.3 From d17fcc320367cd2c16f0c25a5a58dbf2ddbba412 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 25 Aug 2015 15:45:44 -0700 Subject: Make C core log output readable --- src/core/support/log_win32.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') 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); } -- cgit v1.2.3 From d090fe1379932d7d785fa805339110e70b96bd87 Mon Sep 17 00:00:00 2001 From: yang-g Date: Tue, 25 Aug 2015 16:53:07 -0700 Subject: auth context api change for string_ref --- Makefile | 12 ++++++------ build.json | 6 ++++++ include/grpc++/support/auth_context.h | 7 ++++--- src/cpp/common/auth_property_iterator.cc | 6 +++--- src/cpp/common/secure_auth_context.cc | 17 +++++++++-------- src/cpp/common/secure_auth_context.h | 6 +++--- test/cpp/common/auth_property_iterator_test.cc | 15 +++++++++------ test/cpp/common/secure_auth_context_test.cc | 25 ++++++++++++++----------- test/cpp/end2end/end2end_test.cc | 15 ++++++++------- tools/run_tests/sources_and_headers.json | 10 ++++++++-- vsprojects/Grpc.mak | 8 ++++---- 11 files changed, 74 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index 77cb62086b..e872da981b 100644 --- a/Makefile +++ b/Makefile @@ -8945,16 +8945,16 @@ $(BINDIR)/$(CONFIG)/auth_property_iterator_test: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/auth_property_iterator_test: $(PROTOBUF_DEP) $(AUTH_PROPERTY_ITERATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/auth_property_iterator_test: $(PROTOBUF_DEP) $(AUTH_PROPERTY_ITERATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(AUTH_PROPERTY_ITERATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/auth_property_iterator_test + $(Q) $(LDXX) $(LDFLAGS) $(AUTH_PROPERTY_ITERATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/auth_property_iterator_test endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/common/auth_property_iterator_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/common/auth_property_iterator_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_auth_property_iterator_test: $(AUTH_PROPERTY_ITERATOR_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) @@ -10155,16 +10155,16 @@ $(BINDIR)/$(CONFIG)/secure_auth_context_test: protobuf_dep_error else -$(BINDIR)/$(CONFIG)/secure_auth_context_test: $(PROTOBUF_DEP) $(SECURE_AUTH_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(BINDIR)/$(CONFIG)/secure_auth_context_test: $(PROTOBUF_DEP) $(SECURE_AUTH_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(SECURE_AUTH_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/secure_auth_context_test + $(Q) $(LDXX) $(LDFLAGS) $(SECURE_AUTH_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/secure_auth_context_test endif endif -$(OBJDIR)/$(CONFIG)/test/cpp/common/secure_auth_context_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/cpp/common/secure_auth_context_test.o: $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a deps_secure_auth_context_test: $(SECURE_AUTH_CONTEXT_TEST_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) diff --git a/build.json b/build.json index c974250d7c..56f14c6590 100644 --- a/build.json +++ b/build.json @@ -2020,8 +2020,11 @@ "test/cpp/common/auth_property_iterator_test.cc" ], "deps": [ + "grpc++_test_util", + "grpc_test_util", "grpc++", "grpc", + "gpr_test_util", "gpr" ] }, @@ -2572,8 +2575,11 @@ "test/cpp/common/secure_auth_context_test.cc" ], "deps": [ + "grpc++_test_util", + "grpc_test_util", "grpc++", "grpc", + "gpr_test_util", "gpr" ] }, diff --git a/include/grpc++/support/auth_context.h b/include/grpc++/support/auth_context.h index f4f2dcf5bb..67e3e66c05 100644 --- a/include/grpc++/support/auth_context.h +++ b/include/grpc++/support/auth_context.h @@ -38,6 +38,7 @@ #include #include +#include struct grpc_auth_context; struct grpc_auth_property; @@ -46,7 +47,7 @@ struct grpc_auth_property_iterator; namespace grpc { class SecureAuthContext; -typedef std::pair AuthProperty; +typedef std::pair AuthProperty; class AuthPropertyIterator : public std::iterator { @@ -78,11 +79,11 @@ class AuthContext { // A peer identity, in general is one or more properties (in which case they // have the same name). - virtual std::vector GetPeerIdentity() const = 0; + virtual std::vector GetPeerIdentity() const = 0; virtual grpc::string GetPeerIdentityPropertyName() const = 0; // Returns all the property values with the given name. - virtual std::vector FindPropertyValues( + virtual std::vector FindPropertyValues( const grpc::string& name) const = 0; // Iteration over all the properties. diff --git a/src/cpp/common/auth_property_iterator.cc b/src/cpp/common/auth_property_iterator.cc index 5ccf8cf72c..fa6da9d7a8 100644 --- a/src/cpp/common/auth_property_iterator.cc +++ b/src/cpp/common/auth_property_iterator.cc @@ -77,9 +77,9 @@ bool AuthPropertyIterator::operator!=(const AuthPropertyIterator& rhs) const { } const AuthProperty AuthPropertyIterator::operator*() { - return std::make_pair( - grpc::string(property_->name), - grpc::string(property_->value, property_->value_length)); + return std::pair( + property_->name, + grpc::string_ref(property_->value, property_->value_length)); } } // namespace grpc diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc index 87d7bab75c..b18a8537c9 100644 --- a/src/cpp/common/secure_auth_context.cc +++ b/src/cpp/common/secure_auth_context.cc @@ -41,15 +41,16 @@ SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx) : ctx_(ctx) {} SecureAuthContext::~SecureAuthContext() { grpc_auth_context_release(ctx_); } -std::vector SecureAuthContext::GetPeerIdentity() const { +std::vector SecureAuthContext::GetPeerIdentity() const { if (!ctx_) { - return std::vector(); + return std::vector(); } grpc_auth_property_iterator iter = grpc_auth_context_peer_identity(ctx_); - std::vector identity; + std::vector identity; const grpc_auth_property* property = nullptr; while ((property = grpc_auth_property_iterator_next(&iter))) { - identity.push_back(grpc::string(property->value, property->value_length)); + identity.push_back( + grpc::string_ref(property->value, property->value_length)); } return identity; } @@ -62,17 +63,17 @@ grpc::string SecureAuthContext::GetPeerIdentityPropertyName() const { return name == nullptr ? "" : name; } -std::vector SecureAuthContext::FindPropertyValues( +std::vector SecureAuthContext::FindPropertyValues( const grpc::string& name) const { if (!ctx_) { - return std::vector(); + return std::vector(); } grpc_auth_property_iterator iter = grpc_auth_context_find_properties_by_name(ctx_, name.c_str()); const grpc_auth_property* property = nullptr; - std::vector values; + std::vector values; while ((property = grpc_auth_property_iterator_next(&iter))) { - values.push_back(grpc::string(property->value, property->value_length)); + values.push_back(grpc::string_ref(property->value, property->value_length)); } return values; } diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h index 01b7126189..7f622b890b 100644 --- a/src/cpp/common/secure_auth_context.h +++ b/src/cpp/common/secure_auth_context.h @@ -46,12 +46,12 @@ class SecureAuthContext GRPC_FINAL : public AuthContext { ~SecureAuthContext() GRPC_OVERRIDE; - std::vector GetPeerIdentity() const GRPC_OVERRIDE; + std::vector GetPeerIdentity() const GRPC_OVERRIDE; grpc::string GetPeerIdentityPropertyName() const GRPC_OVERRIDE; - std::vector FindPropertyValues(const grpc::string& name) const - GRPC_OVERRIDE; + std::vector FindPropertyValues( + const grpc::string& name) const GRPC_OVERRIDE; AuthPropertyIterator begin() const GRPC_OVERRIDE; diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc index 630c38c7f6..e6226d6a09 100644 --- a/test/cpp/common/auth_property_iterator_test.cc +++ b/test/cpp/common/auth_property_iterator_test.cc @@ -35,11 +35,14 @@ #include #include #include "src/cpp/common/secure_auth_context.h" +#include "test/cpp/util/string_ref_helper.h" extern "C" { #include "src/core/security/security_context.h" } +using ::grpc::testing::ToString; + namespace grpc { namespace { @@ -84,12 +87,12 @@ TEST_F(AuthPropertyIteratorTest, GeneralTest) { AuthProperty p1 = *iter; iter++; AuthProperty p2 = *iter; - EXPECT_EQ("name", p0.first); - EXPECT_EQ("chapi", p0.second); - EXPECT_EQ("name", p1.first); - EXPECT_EQ("chapo", p1.second); - EXPECT_EQ("foo", p2.first); - EXPECT_EQ("bar", p2.second); + EXPECT_EQ("name", ToString(p0.first)); + EXPECT_EQ("chapi", ToString(p0.second)); + EXPECT_EQ("name", ToString(p1.first)); + EXPECT_EQ("chapo", ToString(p1.second)); + EXPECT_EQ("foo", ToString(p2.first)); + EXPECT_EQ("bar", ToString(p2.second)); ++iter; EXPECT_EQ(empty_iter, iter); } diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc index c71ef58023..25538c1853 100644 --- a/test/cpp/common/secure_auth_context_test.cc +++ b/test/cpp/common/secure_auth_context_test.cc @@ -35,11 +35,14 @@ #include #include #include "src/cpp/common/secure_auth_context.h" +#include "test/cpp/util/string_ref_helper.h" extern "C" { #include "src/core/security/security_context.h" } +using grpc::testing::ToString; + namespace grpc { namespace { @@ -63,14 +66,14 @@ TEST_F(SecureAuthContextTest, Properties) { EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name")); SecureAuthContext context(ctx); - std::vector peer_identity = context.GetPeerIdentity(); + std::vector peer_identity = context.GetPeerIdentity(); EXPECT_EQ(2u, peer_identity.size()); - EXPECT_EQ("chapi", peer_identity[0]); - EXPECT_EQ("chapo", peer_identity[1]); + EXPECT_EQ("chapi", ToString(peer_identity[0])); + EXPECT_EQ("chapo", ToString(peer_identity[1])); EXPECT_EQ("name", context.GetPeerIdentityPropertyName()); - std::vector bar = context.FindPropertyValues("foo"); + std::vector bar = context.FindPropertyValues("foo"); EXPECT_EQ(1u, bar.size()); - EXPECT_EQ("bar", bar[0]); + EXPECT_EQ("bar", ToString(bar[0])); } TEST_F(SecureAuthContextTest, Iterators) { @@ -88,12 +91,12 @@ TEST_F(SecureAuthContextTest, Iterators) { AuthProperty p1 = *iter; iter++; AuthProperty p2 = *iter; - EXPECT_EQ("name", p0.first); - EXPECT_EQ("chapi", p0.second); - EXPECT_EQ("name", p1.first); - EXPECT_EQ("chapo", p1.second); - EXPECT_EQ("foo", p2.first); - EXPECT_EQ("bar", p2.second); + EXPECT_EQ("name", ToString(p0.first)); + EXPECT_EQ("chapi", ToString(p0.second)); + EXPECT_EQ("name", ToString(p1.first)); + EXPECT_EQ("chapo", ToString(p1.second)); + EXPECT_EQ("foo", ToString(p2.first)); + EXPECT_EQ("bar", ToString(p2.second)); ++iter; EXPECT_EQ(context.end(), iter); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 0d5bf36df7..9826837c60 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -81,10 +81,10 @@ void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request, void CheckServerAuthContext(const ServerContext* context) { std::shared_ptr auth_ctx = context->auth_context(); - std::vector ssl = + std::vector ssl = auth_ctx->FindPropertyValues("transport_security_type"); EXPECT_EQ(1u, ssl.size()); - EXPECT_EQ("ssl", ssl[0]); + EXPECT_EQ("ssl", ToString(ssl[0])); EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty()); EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty()); } @@ -840,16 +840,17 @@ TEST_F(End2endTest, ClientAuthContext) { EXPECT_TRUE(s.ok()); std::shared_ptr auth_ctx = context.auth_context(); - std::vector ssl = + std::vector ssl = auth_ctx->FindPropertyValues("transport_security_type"); EXPECT_EQ(1u, ssl.size()); - EXPECT_EQ("ssl", ssl[0]); + EXPECT_EQ("ssl", ToString(ssl[0])); EXPECT_EQ("x509_subject_alternative_name", auth_ctx->GetPeerIdentityPropertyName()); EXPECT_EQ(3u, auth_ctx->GetPeerIdentity().size()); - EXPECT_EQ("*.test.google.fr", auth_ctx->GetPeerIdentity()[0]); - EXPECT_EQ("waterzooi.test.google.be", auth_ctx->GetPeerIdentity()[1]); - EXPECT_EQ("*.test.youtube.com", auth_ctx->GetPeerIdentity()[2]); + EXPECT_EQ("*.test.google.fr", ToString(auth_ctx->GetPeerIdentity()[0])); + EXPECT_EQ("waterzooi.test.google.be", + ToString(auth_ctx->GetPeerIdentity()[1])); + EXPECT_EQ("*.test.youtube.com", ToString(auth_ctx->GetPeerIdentity()[2])); } // Make the response larger than the flow control window. diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index a89e5340ed..5facf582ce 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -1068,8 +1068,11 @@ { "deps": [ "gpr", + "gpr_test_util", "grpc", - "grpc++" + "grpc++", + "grpc++_test_util", + "grpc_test_util" ], "headers": [], "language": "c++", @@ -1573,8 +1576,11 @@ { "deps": [ "gpr", + "gpr_test_util", "grpc", - "grpc++" + "grpc++", + "grpc++_test_util", + "grpc_test_util" ], "headers": [], "language": "c++", diff --git a/vsprojects/Grpc.mak b/vsprojects/Grpc.mak index 19cb39741e..ad390e7cda 100644 --- a/vsprojects/Grpc.mak +++ b/vsprojects/Grpc.mak @@ -615,10 +615,10 @@ async_end2end_test: async_end2end_test.exe echo Running async_end2end_test $(OUT_DIR)\async_end2end_test.exe -auth_property_iterator_test.exe: build_grpc++ build_grpc build_gpr $(OUT_DIR) +auth_property_iterator_test.exe: Debug\grpc++_test_util.lib build_grpc_test_util build_grpc++ build_grpc build_gpr_test_util build_gpr $(OUT_DIR) echo Building auth_property_iterator_test $(CC) $(CXXFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\cpp\common\auth_property_iterator_test.cc - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\auth_property_iterator_test.exe" Debug\grpc++.lib Debug\grpc.lib Debug\gpr.lib $(CXX_LIBS) $(LIBS) $(OUT_DIR)\auth_property_iterator_test.obj + $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\auth_property_iterator_test.exe" Debug\grpc++_test_util.lib Debug\grpc_test_util.lib Debug\grpc++.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(CXX_LIBS) $(LIBS) $(OUT_DIR)\auth_property_iterator_test.obj auth_property_iterator_test: auth_property_iterator_test.exe echo Running auth_property_iterator_test $(OUT_DIR)\auth_property_iterator_test.exe @@ -751,10 +751,10 @@ reconnect_interop_server: reconnect_interop_server.exe echo Running reconnect_interop_server $(OUT_DIR)\reconnect_interop_server.exe -secure_auth_context_test.exe: build_grpc++ build_grpc build_gpr $(OUT_DIR) +secure_auth_context_test.exe: Debug\grpc++_test_util.lib build_grpc_test_util build_grpc++ build_grpc build_gpr_test_util build_gpr $(OUT_DIR) echo Building secure_auth_context_test $(CC) $(CXXFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\cpp\common\secure_auth_context_test.cc - $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\secure_auth_context_test.exe" Debug\grpc++.lib Debug\grpc.lib Debug\gpr.lib $(CXX_LIBS) $(LIBS) $(OUT_DIR)\secure_auth_context_test.obj + $(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\secure_auth_context_test.exe" Debug\grpc++_test_util.lib Debug\grpc_test_util.lib Debug\grpc++.lib Debug\grpc.lib Debug\gpr_test_util.lib Debug\gpr.lib $(CXX_LIBS) $(LIBS) $(OUT_DIR)\secure_auth_context_test.obj secure_auth_context_test: secure_auth_context_test.exe echo Running secure_auth_context_test $(OUT_DIR)\secure_auth_context_test.exe -- cgit v1.2.3 From c5b570f97efb29db5b624e2dc360aa7e6b03780f Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 25 Aug 2015 17:47:55 -0700 Subject: Adding void* at then end of security related method in order to have a stable ABI. --- src/core/security/client_auth_filter.c | 3 +- src/core/security/credentials.c | 35 +++++++++++++++------- src/core/security/google_default_credentials.c | 6 ++-- src/core/surface/secure_channel_create.c | 4 ++- src/cpp/client/secure_credentials.cc | 21 ++++++------- src/cpp/server/secure_server_credentials.cc | 2 +- src/csharp/ext/grpc_csharp_ext.c | 8 ++--- src/node/ext/channel.cc | 2 +- src/node/ext/credentials.cc | 11 +++---- src/node/ext/server_credentials.cc | 7 ++--- .../GRPCClient/private/GRPCSecureChannel.m | 7 +++-- src/php/ext/grpc/channel.c | 2 +- src/php/ext/grpc/credentials.c | 6 ++-- src/php/ext/grpc/server_credentials.c | 2 +- src/python/grpcio/grpc/_adapter/_c/types/channel.c | 3 +- .../grpc/_adapter/_c/types/client_credentials.c | 20 +++++++------ .../grpc/_adapter/_c/types/server_credentials.c | 2 +- src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd | 2 +- src/ruby/ext/grpc/rb_channel.c | 2 +- src/ruby/ext/grpc/rb_credentials.c | 11 +++---- src/ruby/ext/grpc/rb_server_credentials.c | 5 ++-- 21 files changed, 91 insertions(+), 70 deletions(-) (limited to 'src') 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..362d5f4b6f 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -298,8 +298,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,9 +312,11 @@ 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_credentials)); memset(c, 0, sizeof(grpc_ssl_server_credentials)); c->base.type = GRPC_CREDENTIALS_TYPE_SSL; c->base.vtable = &ssl_server_vtable; @@ -430,7 +434,8 @@ 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); } @@ -635,9 +640,10 @@ static void compute_engine_fetch_oauth2( metadata_req); } -grpc_credentials *grpc_compute_engine_credentials_create(void) { +grpc_credentials *grpc_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; @@ -693,10 +699,11 @@ static void service_account_fetch_oauth2( } grpc_credentials *grpc_service_account_credentials_create( - const char *json_key, const char *scope, gpr_timespec token_lifetime) { + const char *json_key, const char *scope, gpr_timespec token_lifetime, + void *reserved) { grpc_service_account_credentials *c; grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key); - + GPR_ASSERT(reserved == NULL); if (scope == NULL || (strlen(scope) == 0) || !grpc_auth_json_key_is_valid(&key)) { gpr_log(GPR_ERROR, @@ -766,7 +773,8 @@ grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token( } grpc_credentials *grpc_refresh_token_credentials_create( - const char *json_refresh_token) { + 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)); } @@ -867,11 +875,12 @@ static grpc_credentials_vtable access_token_vtable = { 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; @@ -1101,12 +1110,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)); @@ -1209,8 +1220,10 @@ static grpc_credentials_vtable iam_vtable = { iam_get_request_metadata, NULL}; grpc_credentials *grpc_iam_credentials_create(const char *token, - const char *authority_selector) { + const char *authority_selector, + void *reserved) { grpc_iam_credentials *c; + GPR_ASSERT(reserved == NULL); GPR_ASSERT(token != NULL); GPR_ASSERT(authority_selector != NULL); c = gpr_malloc(sizeof(grpc_iam_credentials)); diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c index 3631de867a..f9aa5187ce 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_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/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/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index f368f2590a..e0642469b4 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -46,7 +46,8 @@ std::shared_ptr 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,14 +76,14 @@ std::shared_ptr 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 ComputeEngineCredentials() { GrpcLibrary init; // To call grpc_init(). - return WrapCredentials(grpc_compute_engine_credentials_create()); + return WrapCredentials(grpc_compute_engine_credentials_create(nullptr)); } // Builds service account credentials. @@ -99,7 +100,7 @@ std::shared_ptr ServiceAccountCredentials( 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)); + json_key.c_str(), scope.c_str(), lifetime, nullptr)); } // Builds JWT credentials. @@ -114,15 +115,15 @@ std::shared_ptr 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 RefreshTokenCredentials( 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_refresh_token_credentials_create( + json_refresh_token.c_str(), nullptr)); } // Builds access token credentials. @@ -130,7 +131,7 @@ std::shared_ptr 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. @@ -139,7 +140,7 @@ std::shared_ptr IAMCredentials( 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())); + authorization_token.c_str(), authority_selector.c_str(), nullptr)); } // Combines two credentials objects into a composite credentials. @@ -154,7 +155,7 @@ std::shared_ptr 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/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index f203cf7f49..5bce9ca8b2 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -52,7 +52,7 @@ std::shared_ptr 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( new SecureServerCredentials(c_creds)); } 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/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..85a823a108 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(args[0]->ToObject()); Credentials *creds2 = ObjectWrap::Unwrap(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_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_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/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/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c index 7a981675de..c92edaff6e 100644 --- a/src/php/ext/grpc/channel.c +++ b/src/php/ext/grpc/channel.c @@ -148,7 +148,7 @@ PHP_METHOD(Channel, __construct) { return; } if (args_array == NULL) { - channel->wrapped = grpc_insecure_channel_create(target, NULL, NULL); + channel->wrapped = grpc_insecure_channel_create(target, NULL, NULL, NULL); } else { array_hash = Z_ARRVAL_P(args_array); if (zend_hash_find(array_hash, "credentials", sizeof("credentials"), diff --git a/src/php/ext/grpc/credentials.c b/src/php/ext/grpc/credentials.c index 01cb94e3aa..0eba6608bb 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_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/python/grpcio/grpc/_adapter/_c/types/channel.c b/src/python/grpcio/grpc/_adapter/_c/types/channel.c index c577ac05eb..35715e81d4 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); } 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..36fd207464 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c +++ b/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c @@ -135,9 +135,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 +160,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 +173,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_compute_engine_credentials_create(NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, @@ -195,7 +196,7 @@ ClientCredentials *pygrpc_ClientCredentials_service_account( } 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)); + json_key, scope, pygrpc_cast_double_to_gpr_timespec(lifetime), NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, @@ -218,7 +219,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 +238,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_refresh_token_credentials_create(json_refresh_token, NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, @@ -259,7 +261,7 @@ ClientCredentials *pygrpc_ClientCredentials_iam( } self = (ClientCredentials *)type->tp_alloc(type, 0); self->c_creds = grpc_iam_credentials_create(authorization_token, - authority_selector); + 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..2ba855e76c 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types/server_credentials.c +++ b/src/python/grpcio/grpc/_adapter/_c/types/server_credentials.c @@ -131,7 +131,7 @@ ServerCredentials *pygrpc_ServerCredentials_ssl( /* 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, 0, NULL); gpr_free(key_cert_pairs); return self; } diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd index d065383587..c793774c8d 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd @@ -332,7 +332,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/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..ac3804df6f 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_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_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c index 62c211d769..6af4c86c45 100644 --- a/src/ruby/ext/grpc/rb_server_credentials.c +++ b/src/ruby/ext/grpc/rb_server_credentials.c @@ -178,10 +178,11 @@ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs, key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain); /* TODO Add a force_client_auth parameter and pass it here. */ 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_pair, 1, 0, NULL); } else { creds = grpc_ssl_server_credentials_create(RSTRING_PTR(pem_root_certs), - &key_cert_pair, 1, 0); + &key_cert_pair, 1, 0, NULL); } if (creds == NULL) { rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); -- cgit v1.2.3 From c17fecd224fa2da3d2b0fc27c1236431fc1bf193 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 25 Aug 2015 19:41:20 -0700 Subject: Fixing tests. --- src/php/ext/grpc/channel.c | 2 +- test/core/end2end/fixtures/chttp2_fake_security.c | 3 +- .../end2end/fixtures/chttp2_simple_ssl_fullstack.c | 7 ++-- .../chttp2_simple_ssl_fullstack_with_poll.c | 7 ++-- .../chttp2_simple_ssl_fullstack_with_proxy.c | 13 +++---- .../chttp2_simple_ssl_with_oauth2_fullstack.c | 9 ++--- .../request_response_with_payload_and_call_creds.c | 6 ++-- test/core/fling/server.c | 4 +-- test/core/security/credentials_test.c | 42 +++++++++++----------- test/core/security/fetch_oauth2.c | 6 ++-- 10 files changed, 52 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c index c92edaff6e..080a939662 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/test/core/end2end/fixtures/chttp2_fake_security.c b/test/core/end2end/fixtures/chttp2_fake_security.c index a0a67939a2..b4a248fb52 100644 --- a/test/core/end2end/fixtures/chttp2_fake_security.c +++ b/test/core/end2end/fixtures/chttp2_fake_security.c @@ -77,7 +77,8 @@ static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args, grpc_credentials *creds) { fullstack_secure_fixture_data *ffd = f->fixture_data; - f->client = grpc_secure_channel_create(creds, ffd->localaddr, client_args); + f->client = + grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); GPR_ASSERT(f->client != NULL); grpc_credentials_release(creds); } diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c index beae24136c..201d202dff 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c @@ -80,7 +80,8 @@ static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args, grpc_credentials *creds) { fullstack_secure_fixture_data *ffd = f->fixture_data; - f->client = grpc_secure_channel_create(creds, ffd->localaddr, client_args); + f->client = + grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); GPR_ASSERT(f->client != NULL); grpc_credentials_release(creds); } @@ -108,7 +109,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { static void chttp2_init_client_simple_ssl_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { - grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL); + grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, {"foo.test.google.fr"}}; @@ -135,7 +136,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0); + grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); if (fail_server_auth_check(server_args)) { grpc_auth_metadata_processor processor = {process_auth_failure, NULL}; grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c index c8971be596..e7375f15e6 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c @@ -80,7 +80,8 @@ static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args, grpc_credentials *creds) { fullstack_secure_fixture_data *ffd = f->fixture_data; - f->client = grpc_secure_channel_create(creds, ffd->localaddr, client_args); + f->client = + grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); GPR_ASSERT(f->client != NULL); grpc_credentials_release(creds); } @@ -108,7 +109,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { static void chttp2_init_client_simple_ssl_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { - grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL); + grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, {"foo.test.google.fr"}}; @@ -135,7 +136,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0); + grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); if (fail_server_auth_check(server_args)) { grpc_auth_metadata_processor processor = {process_auth_failure, NULL}; grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c index a518a7da15..be0dda25a6 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c @@ -58,7 +58,7 @@ static grpc_server *create_proxy_server(const char *port) { grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0); + grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); GPR_ASSERT(grpc_server_add_secure_http2_port(s, port, ssl_creds)); grpc_server_credentials_release(ssl_creds); return s; @@ -66,14 +66,14 @@ static grpc_server *create_proxy_server(const char *port) { static grpc_channel *create_proxy_client(const char *target) { grpc_channel *channel; - grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL); + grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, {"foo.test.google.fr"}}; grpc_channel_args client_args; client_args.num_args = 1; client_args.args = &ssl_name_override; - channel = grpc_secure_channel_create(ssl_creds, target, &client_args); + channel = grpc_secure_channel_create(ssl_creds, target, &client_args, NULL); grpc_credentials_release(ssl_creds); return channel; } @@ -109,7 +109,8 @@ static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f, grpc_credentials *creds) { fullstack_secure_fixture_data *ffd = f->fixture_data; f->client = grpc_secure_channel_create( - creds, grpc_end2end_proxy_get_client_target(ffd->proxy), client_args); + creds, grpc_end2end_proxy_get_client_target(ffd->proxy), client_args, + NULL); GPR_ASSERT(f->client != NULL); grpc_credentials_release(creds); } @@ -137,7 +138,7 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { static void chttp2_init_client_simple_ssl_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { - grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL); + grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, {"foo.test.google.fr"}}; @@ -164,7 +165,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0); + grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); if (fail_server_auth_check(server_args)) { grpc_auth_metadata_processor processor = {process_auth_failure, NULL}; grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c index 7f11028cb5..9a545b1e3d 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c @@ -113,7 +113,8 @@ static void chttp2_init_client_secure_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args, grpc_credentials *creds) { fullstack_secure_fixture_data *ffd = f->fixture_data; - f->client = grpc_secure_channel_create(creds, ffd->localaddr, client_args); + f->client = + grpc_secure_channel_create(creds, ffd->localaddr, client_args, NULL); GPR_ASSERT(f->client != NULL); grpc_credentials_release(creds); } @@ -142,11 +143,11 @@ void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { static void chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { grpc_credentials *ssl_creds = - grpc_ssl_credentials_create(test_root_cert, NULL); + grpc_ssl_credentials_create(test_root_cert, NULL, NULL); grpc_credentials *oauth2_creds = grpc_md_only_test_credentials_create("Authorization", oauth2_md, 1); grpc_credentials *ssl_oauth2_creds = - grpc_composite_credentials_create(ssl_creds, oauth2_creds); + grpc_composite_credentials_create(ssl_creds, oauth2_creds, NULL); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, {"foo.test.google.fr"}}; @@ -175,7 +176,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0); + grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0, NULL); grpc_auth_metadata_processor processor; processor.state = NULL; if (fail_server_auth_check(server_args)) { diff --git a/test/core/end2end/tests/request_response_with_payload_and_call_creds.c b/test/core/end2end/tests/request_response_with_payload_and_call_creds.c index d862274fe3..48dd0aa2ce 100644 --- a/test/core/end2end/tests/request_response_with_payload_and_call_creds.c +++ b/test/core/end2end/tests/request_response_with_payload_and_call_creds.c @@ -190,7 +190,7 @@ static void request_response_with_payload_and_call_creds( c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", "foo.test.google.fr", deadline, NULL); GPR_ASSERT(c); - creds = grpc_iam_credentials_create(iam_token, iam_selector); + creds = grpc_iam_credentials_create(iam_token, iam_selector, NULL); GPR_ASSERT(creds != NULL); GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); switch (mode) { @@ -199,7 +199,7 @@ static void request_response_with_payload_and_call_creds( case OVERRIDE: grpc_credentials_release(creds); creds = grpc_iam_credentials_create(overridden_iam_token, - overridden_iam_selector); + overridden_iam_selector, NULL); GPR_ASSERT(creds != NULL); GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); break; @@ -421,7 +421,7 @@ static void test_request_with_server_rejecting_client_creds( "/foo", "foo.test.google.fr", deadline, NULL); GPR_ASSERT(c); - creds = grpc_iam_credentials_create(iam_token, iam_selector); + creds = grpc_iam_credentials_create(iam_token, iam_selector, NULL); GPR_ASSERT(creds != NULL); GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); grpc_credentials_release(creds); diff --git a/test/core/fling/server.c b/test/core/fling/server.c index 010217939d..0430ff9ab7 100644 --- a/test/core/fling/server.c +++ b/test/core/fling/server.c @@ -215,8 +215,8 @@ int main(int argc, char **argv) { if (secure) { grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, test_server1_cert}; - grpc_server_credentials *ssl_creds = - grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0); + grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create( + NULL, &pem_key_cert_pair, 1, 0, NULL); server = grpc_server_create(NULL, NULL); GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); grpc_server_credentials_release(ssl_creds); diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index e4a8144eaf..880fc5da1e 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -329,7 +329,7 @@ static void check_iam_metadata(void *user_data, grpc_credentials_md *md_elems, static void test_iam_creds(void) { grpc_credentials *creds = grpc_iam_credentials_create( - test_iam_authorization_token, test_iam_authority_selector); + test_iam_authorization_token, test_iam_authority_selector, NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds)); grpc_credentials_get_request_metadata(creds, NULL, test_service_url, @@ -349,7 +349,7 @@ static void check_access_token_metadata(void *user_data, } static void test_access_token_creds(void) { - grpc_credentials *creds = grpc_access_token_credentials_create("blah"); + grpc_credentials *creds = grpc_access_token_credentials_create("blah", NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds)); GPR_ASSERT(strcmp(creds->type, GRPC_CREDENTIALS_TYPE_OAUTH2) == 0); @@ -371,12 +371,12 @@ static void check_ssl_oauth2_composite_metadata( static void test_ssl_oauth2_composite_creds(void) { grpc_credentials *ssl_creds = - grpc_ssl_credentials_create(test_root_cert, NULL); + grpc_ssl_credentials_create(test_root_cert, NULL, NULL); const grpc_credentials_array *creds_array; grpc_credentials *oauth2_creds = grpc_md_only_test_credentials_create( "Authorization", test_oauth2_bearer_token, 0); grpc_credentials *composite_creds = - grpc_composite_credentials_create(ssl_creds, oauth2_creds); + grpc_composite_credentials_create(ssl_creds, oauth2_creds, NULL); grpc_credentials_unref(ssl_creds); grpc_credentials_unref(oauth2_creds); GPR_ASSERT(strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == @@ -395,13 +395,13 @@ static void test_ssl_oauth2_composite_creds(void) { } void test_ssl_fake_transport_security_composite_creds_failure(void) { - grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL); + grpc_credentials *ssl_creds = grpc_ssl_credentials_create(NULL, NULL, NULL); grpc_credentials *fake_transport_security_creds = grpc_fake_transport_security_credentials_create(); /* 2 connector credentials: should not work. */ GPR_ASSERT(grpc_composite_credentials_create( - ssl_creds, fake_transport_security_creds) == NULL); + ssl_creds, fake_transport_security_creds, NULL) == NULL); grpc_credentials_unref(ssl_creds); grpc_credentials_unref(fake_transport_security_creds); } @@ -422,16 +422,16 @@ static void check_ssl_oauth2_iam_composite_metadata( static void test_ssl_oauth2_iam_composite_creds(void) { grpc_credentials *ssl_creds = - grpc_ssl_credentials_create(test_root_cert, NULL); + grpc_ssl_credentials_create(test_root_cert, NULL, NULL); const grpc_credentials_array *creds_array; grpc_credentials *oauth2_creds = grpc_md_only_test_credentials_create( "Authorization", test_oauth2_bearer_token, 0); grpc_credentials *aux_creds = - grpc_composite_credentials_create(ssl_creds, oauth2_creds); + grpc_composite_credentials_create(ssl_creds, oauth2_creds, NULL); grpc_credentials *iam_creds = grpc_iam_credentials_create( - test_iam_authorization_token, test_iam_authority_selector); + test_iam_authorization_token, test_iam_authority_selector, NULL); grpc_credentials *composite_creds = - grpc_composite_credentials_create(aux_creds, iam_creds); + grpc_composite_credentials_create(aux_creds, iam_creds, NULL); grpc_credentials_unref(ssl_creds); grpc_credentials_unref(oauth2_creds); grpc_credentials_unref(aux_creds); @@ -524,7 +524,7 @@ static int httpcli_get_should_not_be_called( static void test_compute_engine_creds_success(void) { grpc_credentials *compute_engine_creds = - grpc_compute_engine_credentials_create(); + grpc_compute_engine_credentials_create(NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(compute_engine_creds)); @@ -548,7 +548,7 @@ static void test_compute_engine_creds_success(void) { static void test_compute_engine_creds_failure(void) { grpc_credentials *compute_engine_creds = - grpc_compute_engine_credentials_create(); + grpc_compute_engine_credentials_create(NULL); grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override, httpcli_post_should_not_be_called); GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds)); @@ -605,7 +605,7 @@ static int refresh_token_httpcli_post_failure( static void test_refresh_token_creds_success(void) { grpc_credentials *refresh_token_creds = - grpc_refresh_token_credentials_create(test_refresh_token_str); + grpc_refresh_token_credentials_create(test_refresh_token_str, NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(refresh_token_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds)); @@ -629,7 +629,7 @@ static void test_refresh_token_creds_success(void) { static void test_refresh_token_creds_failure(void) { grpc_credentials *refresh_token_creds = - grpc_refresh_token_credentials_create(test_refresh_token_str); + grpc_refresh_token_credentials_create(test_refresh_token_str, NULL); grpc_httpcli_set_override(httpcli_get_should_not_be_called, refresh_token_httpcli_post_failure); GPR_ASSERT(grpc_credentials_has_request_metadata(refresh_token_creds)); @@ -731,7 +731,7 @@ static void test_service_account_creds_success(void) { char *json_key_string = test_json_key_str(); grpc_credentials *service_account_creds = grpc_service_account_credentials_create(json_key_string, test_scope, - grpc_max_auth_token_lifetime); + grpc_max_auth_token_lifetime, NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(service_account_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(service_account_creds)); @@ -761,8 +761,8 @@ static void test_service_account_creds_success(void) { static void test_service_account_creds_http_failure(void) { char *json_key_string = test_json_key_str(); grpc_credentials *service_account_creds = - grpc_service_account_credentials_create(json_key_string, test_scope, - grpc_max_auth_token_lifetime); + grpc_service_account_credentials_create( + json_key_string, test_scope, grpc_max_auth_token_lifetime, NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(service_account_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(service_account_creds)); @@ -781,8 +781,8 @@ static void test_service_account_creds_http_failure(void) { static void test_service_account_creds_signing_failure(void) { char *json_key_string = test_json_key_str(); grpc_credentials *service_account_creds = - grpc_service_account_credentials_create(json_key_string, test_scope, - grpc_max_auth_token_lifetime); + grpc_service_account_credentials_create( + json_key_string, test_scope, grpc_max_auth_token_lifetime, NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(service_account_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(service_account_creds)); @@ -828,7 +828,7 @@ static void test_jwt_creds_success(void) { char *json_key_string = test_json_key_str(); grpc_credentials *jwt_creds = grpc_service_account_jwt_access_credentials_create( - json_key_string, grpc_max_auth_token_lifetime); + json_key_string, grpc_max_auth_token_lifetime, NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(jwt_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(jwt_creds)); @@ -861,7 +861,7 @@ static void test_jwt_creds_signing_failure(void) { char *json_key_string = test_json_key_str(); grpc_credentials *jwt_creds = grpc_service_account_jwt_access_credentials_create( - json_key_string, grpc_max_auth_token_lifetime); + json_key_string, grpc_max_auth_token_lifetime, NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(jwt_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(jwt_creds)); diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c index 64c4dde5d9..7354a9f8f7 100644 --- a/test/core/security/fetch_oauth2.c +++ b/test/core/security/fetch_oauth2.c @@ -56,7 +56,7 @@ static grpc_credentials *create_service_account_creds( } return grpc_service_account_credentials_create( (const char *)GPR_SLICE_START_PTR(json_key), scope, - grpc_max_auth_token_lifetime); + grpc_max_auth_token_lifetime, NULL); } static grpc_credentials *create_refresh_token_creds( @@ -69,7 +69,7 @@ static grpc_credentials *create_refresh_token_creds( exit(1); } return grpc_refresh_token_credentials_create( - (const char *)GPR_SLICE_START_PTR(refresh_token)); + (const char *)GPR_SLICE_START_PTR(refresh_token), NULL); } int main(int argc, char **argv) { @@ -112,7 +112,7 @@ int main(int argc, char **argv) { "Ignoring json key and scope to get a token from the GCE " "metadata server."); } - creds = grpc_compute_engine_credentials_create(); + creds = grpc_compute_engine_credentials_create(NULL); if (creds == NULL) { gpr_log(GPR_ERROR, "Could not create gce credentials."); exit(1); -- cgit v1.2.3 From 510a920c753213df46587decb2ec87d2d1101e5d Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 25 Aug 2015 21:51:07 -0700 Subject: Credentials cleanup: - Removing service_accounts credentials. These credentials just have drawbacks compared to service_account_jwt_access credentials, notably in terms for security. - Renaming Google specific credentials with a Google prefix for C and C++. This should be done as well for wrapped languages. --- include/grpc++/credentials.h | 16 +- include/grpc/grpc_security.h | 31 +--- src/core/security/credentials.c | 111 +++---------- src/core/security/credentials.h | 17 +- src/core/security/google_default_credentials.c | 2 +- src/cpp/client/secure_credentials.cc | 30 +--- src/node/ext/credentials.cc | 4 +- src/php/ext/grpc/credentials.c | 2 +- .../grpc/_adapter/_c/types/client_credentials.c | 31 +--- src/ruby/ext/grpc/rb_credentials.c | 2 +- .../request_response_with_payload_and_call_creds.c | 8 +- test/core/security/credentials_test.c | 185 +++++---------------- test/core/security/fetch_oauth2.c | 47 +----- test/cpp/client/credentials_test.cc | 4 +- test/cpp/end2end/end2end_test.cc | 8 +- test/cpp/interop/client_helper.cc | 20 +-- 16 files changed, 110 insertions(+), 408 deletions(-) (limited to 'src') diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h index 71e1f00f15..a1488add1e 100644 --- a/include/grpc++/credentials.h +++ b/include/grpc++/credentials.h @@ -94,17 +94,7 @@ std::shared_ptr SslCredentials( const SslCredentialsOptions& options); // Builds credentials for use when running in GCE -std::shared_ptr ComputeEngineCredentials(); - -// Builds service account credentials. -// json_key is the JSON key string containing the client's private key. -// scope is a space-delimited list of the requested permissions. -// token_lifetime_seconds is the lifetime in seconds of each token acquired -// through this service account credentials. It should be positive and should -// not exceed grpc_max_auth_token_lifetime or will be cropped to this value. -std::shared_ptr ServiceAccountCredentials( - const grpc::string& json_key, const grpc::string& scope, - long token_lifetime_seconds); +std::shared_ptr GoogleComputeEngineCredentials(); // Builds Service Account JWT Access credentials. // json_key is the JSON key string containing the client's private key. @@ -117,7 +107,7 @@ std::shared_ptr ServiceAccountJWTAccessCredentials( // Builds refresh token credentials. // json_refresh_token is the JSON string containing the refresh token along // with a client_id and client_secret. -std::shared_ptr RefreshTokenCredentials( +std::shared_ptr GoogleRefreshTokenCredentials( const grpc::string& json_refresh_token); // Builds access token credentials. @@ -127,7 +117,7 @@ std::shared_ptr AccessTokenCredentials( const grpc::string& access_token); // Builds IAM credentials. -std::shared_ptr IAMCredentials( +std::shared_ptr GoogleIAMCredentials( const grpc::string& authorization_token, const grpc::string& authority_selector); diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index 0bc36c059c..8647078233 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -97,26 +97,13 @@ grpc_credentials *grpc_composite_credentials_create(grpc_credentials *creds1, grpc_credentials *creds2, void *reserved); -/* Creates a compute engine credentials object. +/* Creates a compute engine credentials object for connecting to Google. WARNING: Do NOT use this credentials to connect to a non-google service as this could result in an oauth2 token leak. */ -grpc_credentials *grpc_compute_engine_credentials_create(void *reserved); +grpc_credentials *grpc_google_compute_engine_credentials_create(void *reserved); extern const gpr_timespec grpc_max_auth_token_lifetime; -/* Creates a service account credentials object. May return NULL if the input is - invalid. - WARNING: Do NOT use this credentials to connect to a non-google service as - this could result in an oauth2 token leak. - - json_key is the JSON key string containing the client's private key. - - scope is a space-delimited list of the requested permissions. - - token_lifetime is the lifetime of each token acquired through this service - account credentials. It should not exceed grpc_max_auth_token_lifetime - or will be cropped to this value. */ -grpc_credentials *grpc_service_account_credentials_create( - const char *json_key, const char *scope, gpr_timespec token_lifetime, - void *reserved); - /* Creates a JWT credentials object. May return NULL if the input is invalid. - json_key is the JSON key string containing the client's private key. - token_lifetime is the lifetime of each Json Web Token (JWT) created with @@ -125,13 +112,13 @@ grpc_credentials *grpc_service_account_credentials_create( grpc_credentials *grpc_service_account_jwt_access_credentials_create( const char *json_key, gpr_timespec token_lifetime, void *reserved); -/* Creates an Oauth2 Refresh Token credentials object. May return NULL if the - input is invalid. +/* Creates an Oauth2 Refresh Token credentials object for connecting to Google. + May return NULL if the input is invalid. WARNING: Do NOT use this credentials to connect to a non-google service as this could result in an oauth2 token leak. - json_refresh_token is the JSON string containing the refresh token itself along with a client_id and client_secret. */ -grpc_credentials *grpc_refresh_token_credentials_create( +grpc_credentials *grpc_google_refresh_token_credentials_create( const char *json_refresh_token, void *reserved); /* Creates an Oauth2 Access Token credentials with an access token that was @@ -139,10 +126,10 @@ grpc_credentials *grpc_refresh_token_credentials_create( grpc_credentials *grpc_access_token_credentials_create( const char *access_token, void *reserved); -/* Creates an IAM credentials object. */ -grpc_credentials *grpc_iam_credentials_create(const char *authorization_token, - const char *authority_selector, - void *reserved); +/* Creates an IAM credentials object for connecting to Google. */ +grpc_credentials *grpc_google_iam_credentials_create( + const char *authorization_token, const char *authority_selector, + void *reserved); /* --- Secure channel creation. --- */ diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 362d5f4b6f..1c665f1ede 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -618,7 +618,7 @@ 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, @@ -640,7 +640,8 @@ static void compute_engine_fetch_oauth2( metadata_req); } -grpc_credentials *grpc_compute_engine_credentials_create(void *reserved) { +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); @@ -649,81 +650,11 @@ grpc_credentials *grpc_compute_engine_credentials_create(void *reserved) { 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, - void *reserved) { - grpc_service_account_credentials *c; - grpc_auth_json_key key = grpc_auth_json_key_create_from_string(json_key); - GPR_ASSERT(reserved == NULL); - 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. -- */ +/* -- GoogleRefreshToken credentials. -- */ static void refresh_token_destroy(grpc_credentials *creds) { - grpc_refresh_token_credentials *c = (grpc_refresh_token_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); } @@ -737,8 +668,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; @@ -757,22 +688,23 @@ 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( +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( @@ -1194,7 +1126,7 @@ grpc_credentials *grpc_credentials_contains_type( /* -- IAM credentials. -- */ static void iam_destroy(grpc_credentials *creds) { - grpc_iam_credentials *c = (grpc_iam_credentials *)creds; + grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds; grpc_credentials_md_store_unref(c->iam_md); gpr_free(c); } @@ -1210,7 +1142,7 @@ 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); } @@ -1219,15 +1151,14 @@ static grpc_credentials_vtable iam_vtable = { iam_destroy, 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, - void *reserved) { - 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..d9bd53adc2 100644 --- a/src/core/security/credentials.h +++ b/src/core/security/credentials.h @@ -277,21 +277,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 +299,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 f9aa5187ce..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(NULL); + result = grpc_google_compute_engine_credentials_create(NULL); } } diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index e0642469b4..2260f6d33e 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -81,26 +81,10 @@ std::shared_ptr SslCredentials( } // Builds credentials for use when running in GCE -std::shared_ptr ComputeEngineCredentials() { +std::shared_ptr GoogleComputeEngineCredentials() { GrpcLibrary init; // To call grpc_init(). - return WrapCredentials(grpc_compute_engine_credentials_create(nullptr)); -} - -// Builds service account credentials. -std::shared_ptr 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, nullptr)); + return WrapCredentials( + grpc_google_compute_engine_credentials_create(nullptr)); } // Builds JWT credentials. @@ -119,10 +103,10 @@ std::shared_ptr ServiceAccountJWTAccessCredentials( } // Builds refresh token credentials. -std::shared_ptr RefreshTokenCredentials( +std::shared_ptr GoogleRefreshTokenCredentials( const grpc::string& json_refresh_token) { GrpcLibrary init; // To call grpc_init(). - return WrapCredentials(grpc_refresh_token_credentials_create( + return WrapCredentials(grpc_google_refresh_token_credentials_create( json_refresh_token.c_str(), nullptr)); } @@ -135,11 +119,11 @@ std::shared_ptr AccessTokenCredentials( } // Builds IAM credentials. -std::shared_ptr IAMCredentials( +std::shared_ptr GoogleIAMCredentials( const grpc::string& authorization_token, const grpc::string& authority_selector) { GrpcLibrary init; // To call grpc_init(). - return WrapCredentials(grpc_iam_credentials_create( + return WrapCredentials(grpc_google_iam_credentials_create( authorization_token.c_str(), authority_selector.c_str(), nullptr)); } diff --git a/src/node/ext/credentials.cc b/src/node/ext/credentials.cc index 85a823a108..c3b04dcea7 100644 --- a/src/node/ext/credentials.cc +++ b/src/node/ext/credentials.cc @@ -186,7 +186,7 @@ NAN_METHOD(Credentials::CreateComposite) { NAN_METHOD(Credentials::CreateGce) { NanScope(); - grpc_credentials *creds = grpc_compute_engine_credentials_create(NULL); + grpc_credentials *creds = grpc_google_compute_engine_credentials_create(NULL); if (creds == NULL) { NanReturnNull(); } @@ -204,7 +204,7 @@ 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, NULL); + grpc_google_iam_credentials_create(*auth_token, *auth_selector, NULL); if (creds == NULL) { NanReturnNull(); } diff --git a/src/php/ext/grpc/credentials.c b/src/php/ext/grpc/credentials.c index 0eba6608bb..8e3b7ff212 100644 --- a/src/php/ext/grpc/credentials.c +++ b/src/php/ext/grpc/credentials.c @@ -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(NULL); + 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/python/grpcio/grpc/_adapter/_c/types/client_credentials.c b/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c index 36fd207464..9554796631 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c +++ b/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c @@ -173,7 +173,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(NULL); + self->c_creds = grpc_google_compute_engine_credentials_create(NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, @@ -183,29 +183,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), NULL); - 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) { @@ -239,7 +216,7 @@ ClientCredentials *pygrpc_ClientCredentials_refresh_token( } self = (ClientCredentials *)type->tp_alloc(type, 0); self->c_creds = - grpc_refresh_token_credentials_create(json_refresh_token, NULL); + grpc_google_refresh_token_credentials_create(json_refresh_token, NULL); if (!self->c_creds) { Py_DECREF(self); PyErr_SetString(PyExc_RuntimeError, @@ -260,8 +237,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, NULL); + 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/ruby/ext/grpc/rb_credentials.c b/src/ruby/ext/grpc/rb_credentials.c index ac3804df6f..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(NULL); + 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"); diff --git a/test/core/end2end/tests/request_response_with_payload_and_call_creds.c b/test/core/end2end/tests/request_response_with_payload_and_call_creds.c index 48dd0aa2ce..75c5bba5bd 100644 --- a/test/core/end2end/tests/request_response_with_payload_and_call_creds.c +++ b/test/core/end2end/tests/request_response_with_payload_and_call_creds.c @@ -190,7 +190,7 @@ static void request_response_with_payload_and_call_creds( c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", "foo.test.google.fr", deadline, NULL); GPR_ASSERT(c); - creds = grpc_iam_credentials_create(iam_token, iam_selector, NULL); + creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL); GPR_ASSERT(creds != NULL); GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); switch (mode) { @@ -198,8 +198,8 @@ static void request_response_with_payload_and_call_creds( break; case OVERRIDE: grpc_credentials_release(creds); - creds = grpc_iam_credentials_create(overridden_iam_token, - overridden_iam_selector, NULL); + creds = grpc_google_iam_credentials_create(overridden_iam_token, + overridden_iam_selector, NULL); GPR_ASSERT(creds != NULL); GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); break; @@ -421,7 +421,7 @@ static void test_request_with_server_rejecting_client_creds( "/foo", "foo.test.google.fr", deadline, NULL); GPR_ASSERT(c); - creds = grpc_iam_credentials_create(iam_token, iam_selector, NULL); + creds = grpc_google_iam_credentials_create(iam_token, iam_selector, NULL); GPR_ASSERT(creds != NULL); GPR_ASSERT(grpc_call_set_credentials(c, creds) == GRPC_CALL_OK); grpc_credentials_release(creds); diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c index 880fc5da1e..97ebaa0570 100644 --- a/test/core/security/credentials_test.c +++ b/test/core/security/credentials_test.c @@ -50,8 +50,8 @@ #include -static const char test_iam_authorization_token[] = "blahblahblhahb"; -static const char test_iam_authority_selector[] = "respectmyauthoritah"; +static const char test_google_iam_authorization_token[] = "blahblahblhahb"; +static const char test_google_iam_authority_selector[] = "respectmyauthoritah"; static const char test_oauth2_bearer_token[] = "Bearer blaaslkdjfaslkdfasdsfasf"; static const char test_root_cert[] = "I am the root!"; @@ -315,25 +315,29 @@ static void check_metadata(expected_md *expected, grpc_credentials_md *md_elems, } } -static void check_iam_metadata(void *user_data, grpc_credentials_md *md_elems, - size_t num_md, grpc_credentials_status status) { +static void check_google_iam_metadata(void *user_data, + grpc_credentials_md *md_elems, + size_t num_md, + grpc_credentials_status status) { grpc_credentials *c = (grpc_credentials *)user_data; - expected_md emd[] = { - {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, test_iam_authorization_token}, - {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, test_iam_authority_selector}}; + expected_md emd[] = {{GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + test_google_iam_authorization_token}, + {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + test_google_iam_authority_selector}}; GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(num_md == 2); check_metadata(emd, md_elems, num_md); grpc_credentials_unref(c); } -static void test_iam_creds(void) { - grpc_credentials *creds = grpc_iam_credentials_create( - test_iam_authorization_token, test_iam_authority_selector, NULL); +static void test_google_iam_creds(void) { + grpc_credentials *creds = grpc_google_iam_credentials_create( + test_google_iam_authorization_token, test_google_iam_authority_selector, + NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(creds)); grpc_credentials_get_request_metadata(creds, NULL, test_service_url, - check_iam_metadata, creds); + check_google_iam_metadata, creds); } static void check_access_token_metadata(void *user_data, @@ -406,21 +410,23 @@ void test_ssl_fake_transport_security_composite_creds_failure(void) { grpc_credentials_unref(fake_transport_security_creds); } -static void check_ssl_oauth2_iam_composite_metadata( +static void check_ssl_oauth2_google_iam_composite_metadata( void *user_data, grpc_credentials_md *md_elems, size_t num_md, grpc_credentials_status status) { grpc_credentials *c = (grpc_credentials *)user_data; expected_md emd[] = { {GRPC_AUTHORIZATION_METADATA_KEY, test_oauth2_bearer_token}, - {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, test_iam_authorization_token}, - {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, test_iam_authority_selector}}; + {GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY, + test_google_iam_authorization_token}, + {GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY, + test_google_iam_authority_selector}}; GPR_ASSERT(status == GRPC_CREDENTIALS_OK); GPR_ASSERT(num_md == 3); check_metadata(emd, md_elems, num_md); grpc_credentials_unref(c); } -static void test_ssl_oauth2_iam_composite_creds(void) { +static void test_ssl_oauth2_google_iam_composite_creds(void) { grpc_credentials *ssl_creds = grpc_ssl_credentials_create(test_root_cert, NULL, NULL); const grpc_credentials_array *creds_array; @@ -428,14 +434,15 @@ static void test_ssl_oauth2_iam_composite_creds(void) { "Authorization", test_oauth2_bearer_token, 0); grpc_credentials *aux_creds = grpc_composite_credentials_create(ssl_creds, oauth2_creds, NULL); - grpc_credentials *iam_creds = grpc_iam_credentials_create( - test_iam_authorization_token, test_iam_authority_selector, NULL); + grpc_credentials *google_iam_creds = grpc_google_iam_credentials_create( + test_google_iam_authorization_token, test_google_iam_authority_selector, + NULL); grpc_credentials *composite_creds = - grpc_composite_credentials_create(aux_creds, iam_creds, NULL); + grpc_composite_credentials_create(aux_creds, google_iam_creds, NULL); grpc_credentials_unref(ssl_creds); grpc_credentials_unref(oauth2_creds); grpc_credentials_unref(aux_creds); - grpc_credentials_unref(iam_creds); + grpc_credentials_unref(google_iam_creds); GPR_ASSERT(strcmp(composite_creds->type, GRPC_CREDENTIALS_TYPE_COMPOSITE) == 0); GPR_ASSERT(grpc_credentials_has_request_metadata(composite_creds)); @@ -448,9 +455,9 @@ static void test_ssl_oauth2_iam_composite_creds(void) { GRPC_CREDENTIALS_TYPE_OAUTH2) == 0); GPR_ASSERT(strcmp(creds_array->creds_array[2]->type, GRPC_CREDENTIALS_TYPE_IAM) == 0); - grpc_credentials_get_request_metadata(composite_creds, NULL, test_service_url, - check_ssl_oauth2_iam_composite_metadata, - composite_creds); + grpc_credentials_get_request_metadata( + composite_creds, NULL, test_service_url, + check_ssl_oauth2_google_iam_composite_metadata, composite_creds); } static void on_oauth2_creds_get_metadata_success( @@ -524,7 +531,7 @@ static int httpcli_get_should_not_be_called( static void test_compute_engine_creds_success(void) { grpc_credentials *compute_engine_creds = - grpc_compute_engine_credentials_create(NULL); + grpc_google_compute_engine_credentials_create(NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(compute_engine_creds)); @@ -548,7 +555,7 @@ static void test_compute_engine_creds_success(void) { static void test_compute_engine_creds_failure(void) { grpc_credentials *compute_engine_creds = - grpc_compute_engine_credentials_create(NULL); + grpc_google_compute_engine_credentials_create(NULL); grpc_httpcli_set_override(compute_engine_httpcli_get_failure_override, httpcli_post_should_not_be_called); GPR_ASSERT(grpc_credentials_has_request_metadata(compute_engine_creds)); @@ -605,7 +612,8 @@ static int refresh_token_httpcli_post_failure( static void test_refresh_token_creds_success(void) { grpc_credentials *refresh_token_creds = - grpc_refresh_token_credentials_create(test_refresh_token_str, NULL); + grpc_google_refresh_token_credentials_create(test_refresh_token_str, + NULL); GPR_ASSERT(grpc_credentials_has_request_metadata(refresh_token_creds)); GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds)); @@ -629,7 +637,8 @@ static void test_refresh_token_creds_success(void) { static void test_refresh_token_creds_failure(void) { grpc_credentials *refresh_token_creds = - grpc_refresh_token_credentials_create(test_refresh_token_str, NULL); + grpc_google_refresh_token_credentials_create(test_refresh_token_str, + NULL); grpc_httpcli_set_override(httpcli_get_should_not_be_called, refresh_token_httpcli_post_failure); GPR_ASSERT(grpc_credentials_has_request_metadata(refresh_token_creds)); @@ -686,119 +695,6 @@ static char *encode_and_sign_jwt_should_not_be_called( GPR_ASSERT("grpc_jwt_encode_and_sign should not be called" == NULL); } -static void validate_service_account_http_request( - const grpc_httpcli_request *request, const char *body, size_t body_size) { - /* The content of the assertion is tested extensively in json_token_test. */ - char *expected_body = NULL; - GPR_ASSERT(body != NULL); - GPR_ASSERT(body_size != 0); - gpr_asprintf(&expected_body, "%s%s", GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX, - test_signed_jwt); - GPR_ASSERT(strlen(expected_body) == body_size); - GPR_ASSERT(memcmp(expected_body, body, body_size) == 0); - gpr_free(expected_body); - GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); - GPR_ASSERT(strcmp(request->host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0); - GPR_ASSERT(strcmp(request->path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0); - GPR_ASSERT(request->hdr_count == 1); - GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0); - GPR_ASSERT( - strcmp(request->hdrs[0].value, "application/x-www-form-urlencoded") == 0); -} - -static int service_account_httpcli_post_success( - const grpc_httpcli_request *request, const char *body, size_t body_size, - gpr_timespec deadline, grpc_httpcli_response_cb on_response, - void *user_data) { - grpc_httpcli_response response = - http_response(200, valid_oauth2_json_response); - validate_service_account_http_request(request, body, body_size); - on_response(user_data, &response); - return 1; -} - -static int service_account_httpcli_post_failure( - const grpc_httpcli_request *request, const char *body, size_t body_size, - gpr_timespec deadline, grpc_httpcli_response_cb on_response, - void *user_data) { - grpc_httpcli_response response = http_response(403, "Not Authorized."); - validate_service_account_http_request(request, body, body_size); - on_response(user_data, &response); - return 1; -} - -static void test_service_account_creds_success(void) { - char *json_key_string = test_json_key_str(); - grpc_credentials *service_account_creds = - grpc_service_account_credentials_create(json_key_string, test_scope, - grpc_max_auth_token_lifetime, NULL); - GPR_ASSERT(grpc_credentials_has_request_metadata(service_account_creds)); - GPR_ASSERT(grpc_credentials_has_request_metadata_only(service_account_creds)); - - /* First request: http get should be called. */ - grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - service_account_httpcli_post_success); - grpc_credentials_get_request_metadata( - service_account_creds, NULL, test_service_url, - on_oauth2_creds_get_metadata_success, (void *)test_user_data); - - /* Second request: the cached token should be served directly. */ - grpc_jwt_encode_and_sign_set_override( - encode_and_sign_jwt_should_not_be_called); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - httpcli_post_should_not_be_called); - grpc_credentials_get_request_metadata( - service_account_creds, NULL, test_service_url, - on_oauth2_creds_get_metadata_success, (void *)test_user_data); - - gpr_free(json_key_string); - grpc_credentials_unref(service_account_creds); - grpc_jwt_encode_and_sign_set_override(NULL); - grpc_httpcli_set_override(NULL, NULL); -} - -static void test_service_account_creds_http_failure(void) { - char *json_key_string = test_json_key_str(); - grpc_credentials *service_account_creds = - grpc_service_account_credentials_create( - json_key_string, test_scope, grpc_max_auth_token_lifetime, NULL); - GPR_ASSERT(grpc_credentials_has_request_metadata(service_account_creds)); - GPR_ASSERT(grpc_credentials_has_request_metadata_only(service_account_creds)); - - grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_success); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - service_account_httpcli_post_failure); - grpc_credentials_get_request_metadata( - service_account_creds, NULL, test_service_url, - on_oauth2_creds_get_metadata_failure, (void *)test_user_data); - - gpr_free(json_key_string); - grpc_credentials_unref(service_account_creds); - grpc_httpcli_set_override(NULL, NULL); -} - -static void test_service_account_creds_signing_failure(void) { - char *json_key_string = test_json_key_str(); - grpc_credentials *service_account_creds = - grpc_service_account_credentials_create( - json_key_string, test_scope, grpc_max_auth_token_lifetime, NULL); - GPR_ASSERT(grpc_credentials_has_request_metadata(service_account_creds)); - GPR_ASSERT(grpc_credentials_has_request_metadata_only(service_account_creds)); - - grpc_jwt_encode_and_sign_set_override(encode_and_sign_jwt_failure); - grpc_httpcli_set_override(httpcli_get_should_not_be_called, - httpcli_post_should_not_be_called); - grpc_credentials_get_request_metadata( - service_account_creds, NULL, test_service_url, - on_oauth2_creds_get_metadata_failure, (void *)test_user_data); - - gpr_free(json_key_string); - grpc_credentials_unref(service_account_creds); - grpc_httpcli_set_override(NULL, NULL); - grpc_jwt_encode_and_sign_set_override(NULL); -} - static void on_jwt_creds_get_metadata_success(void *user_data, grpc_credentials_md *md_elems, size_t num_md, @@ -922,14 +818,14 @@ static void test_google_default_creds_auth_key(void) { } static void test_google_default_creds_access_token(void) { - grpc_refresh_token_credentials *refresh; + grpc_google_refresh_token_credentials *refresh; grpc_credentials *creds; grpc_flush_cached_google_default_credentials(); set_google_default_creds_env_var_with_file_contents( "refresh_token_google_default_creds", test_refresh_token_str); creds = grpc_google_default_credentials_create(); GPR_ASSERT(creds != NULL); - refresh = (grpc_refresh_token_credentials *)composite_inner_creds( + refresh = (grpc_google_refresh_token_credentials *)composite_inner_creds( creds, GRPC_CREDENTIALS_TYPE_OAUTH2); GPR_ASSERT(strcmp(refresh->refresh_token.client_id, "32555999999.apps.googleusercontent.com") == 0); @@ -952,17 +848,14 @@ int main(int argc, char **argv) { test_oauth2_token_fetcher_creds_parsing_missing_token(); test_oauth2_token_fetcher_creds_parsing_missing_token_type(); test_oauth2_token_fetcher_creds_parsing_missing_token_lifetime(); - test_iam_creds(); + test_google_iam_creds(); test_access_token_creds(); test_ssl_oauth2_composite_creds(); - test_ssl_oauth2_iam_composite_creds(); + test_ssl_oauth2_google_iam_composite_creds(); test_compute_engine_creds_success(); test_compute_engine_creds_failure(); test_refresh_token_creds_success(); test_refresh_token_creds_failure(); - test_service_account_creds_success(); - test_service_account_creds_http_failure(); - test_service_account_creds_signing_failure(); test_jwt_creds_success(); test_jwt_creds_signing_failure(); test_google_default_creds_auth_key(); diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c index 7354a9f8f7..764d8da9b6 100644 --- a/test/core/security/fetch_oauth2.c +++ b/test/core/security/fetch_oauth2.c @@ -46,19 +46,6 @@ #include "src/core/support/file.h" #include "test/core/security/oauth2_utils.h" -static grpc_credentials *create_service_account_creds( - const char *json_key_file_path, const char *scope) { - int success; - gpr_slice json_key = gpr_load_file(json_key_file_path, 1, &success); - if (!success) { - gpr_log(GPR_ERROR, "Could not read file %s.", json_key_file_path); - exit(1); - } - return grpc_service_account_credentials_create( - (const char *)GPR_SLICE_START_PTR(json_key), scope, - grpc_max_auth_token_lifetime, NULL); -} - static grpc_credentials *create_refresh_token_creds( const char *json_refresh_token_file_path) { int success; @@ -68,7 +55,7 @@ static grpc_credentials *create_refresh_token_creds( gpr_log(GPR_ERROR, "Could not read file %s.", json_refresh_token_file_path); exit(1); } - return grpc_refresh_token_credentials_create( + return grpc_google_refresh_token_credentials_create( (const char *)GPR_SLICE_START_PTR(refresh_token), NULL); } @@ -80,18 +67,9 @@ int main(int argc, char **argv) { int use_gce = 0; char *scope = NULL; gpr_cmdline *cl = gpr_cmdline_create("fetch_oauth2"); - gpr_cmdline_add_string(cl, "json_key", - "File path of the json key. Mutually exclusive with " - "--json_refresh_token.", - &json_key_file_path); gpr_cmdline_add_string(cl, "json_refresh_token", - "File path of the json refresh token. Mutually " - "exclusive with --json_key.", + "File path of the json refresh token.", &json_refresh_token_file_path); - gpr_cmdline_add_string(cl, "scope", - "Space delimited permissions. Only used for " - "--json_key, ignored otherwise.", - &scope); gpr_cmdline_add_flag( cl, "gce", "Get a token from the GCE metadata server (only works in GCE).", @@ -112,7 +90,7 @@ int main(int argc, char **argv) { "Ignoring json key and scope to get a token from the GCE " "metadata server."); } - creds = grpc_compute_engine_credentials_create(NULL); + creds = grpc_google_compute_engine_credentials_create(NULL); if (creds == NULL) { gpr_log(GPR_ERROR, "Could not create gce credentials."); exit(1); @@ -127,23 +105,8 @@ int main(int argc, char **argv) { exit(1); } } else { - if (json_key_file_path == NULL) { - gpr_log(GPR_ERROR, "Missing --json_key option."); - exit(1); - } - if (scope == NULL) { - gpr_log(GPR_ERROR, "Missing --scope option."); - exit(1); - } - - creds = create_service_account_creds(json_key_file_path, scope); - if (creds == NULL) { - gpr_log(GPR_ERROR, - "Could not create service account creds. %s does probably not " - "contain a valid json key.", - json_key_file_path); - exit(1); - } + gpr_log(GPR_ERROR, "Missing --gce or --json_refresh_token option."); + exit(1); } GPR_ASSERT(creds != NULL); diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index 6fb24d71e5..18fcffe7cd 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -45,8 +45,8 @@ class CredentialsTest : public ::testing::Test { protected: }; -TEST_F(CredentialsTest, InvalidServiceAccountCreds) { - std::shared_ptr bad1 = ServiceAccountCredentials("", "", 1); +TEST_F(CredentialsTest, InvalidGoogleRefreshToken) { + std::shared_ptr bad1 = GoogleRefreshTokenCredentials(""); EXPECT_EQ(static_cast(nullptr), bad1.get()); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 2728dce07e..b6f156a24a 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -561,7 +561,7 @@ TEST_F(End2endTest, DiffPackageServices) { // rpc and stream should fail on bad credentials. TEST_F(End2endTest, BadCredentials) { - std::shared_ptr bad_creds = ServiceAccountCredentials("", "", 1); + std::shared_ptr bad_creds = GoogleRefreshTokenCredentials(""); EXPECT_EQ(static_cast(nullptr), bad_creds.get()); std::shared_ptr channel = CreateChannel(server_address_.str(), bad_creds, ChannelArguments()); @@ -741,7 +741,7 @@ TEST_F(End2endTest, SetPerCallCredentials) { EchoResponse response; ClientContext context; std::shared_ptr creds = - IAMCredentials("fake_token", "fake_selector"); + GoogleIAMCredentials("fake_token", "fake_selector"); context.set_credentials(creds); request.set_message("Hello"); request.mutable_param()->set_echo_metadata(true); @@ -778,10 +778,10 @@ TEST_F(End2endTest, OverridePerCallCredentials) { EchoResponse response; ClientContext context; std::shared_ptr creds1 = - IAMCredentials("fake_token1", "fake_selector1"); + GoogleIAMCredentials("fake_token1", "fake_selector1"); context.set_credentials(creds1); std::shared_ptr creds2 = - IAMCredentials("fake_token2", "fake_selector2"); + GoogleIAMCredentials("fake_token2", "fake_selector2"); context.set_credentials(creds2); request.set_message("Hello"); request.mutable_param()->set_echo_metadata(true); diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc index abc14aeb98..7093463fa8 100644 --- a/test/cpp/interop/client_helper.cc +++ b/test/cpp/interop/client_helper.cc @@ -64,16 +64,6 @@ DECLARE_string(oauth_scope); namespace grpc { namespace testing { -namespace { -std::shared_ptr CreateServiceAccountCredentials() { - GPR_ASSERT(FLAGS_enable_ssl); - grpc::string json_key = GetServiceAccountJsonKey(); - std::chrono::seconds token_lifetime = std::chrono::hours(1); - return ServiceAccountCredentials(json_key, FLAGS_oauth_scope, - token_lifetime.count()); -} -} // namespace - grpc::string GetServiceAccountJsonKey() { static grpc::string json_key; if (json_key.empty()) { @@ -86,7 +76,7 @@ grpc::string GetServiceAccountJsonKey() { } grpc::string GetOauth2AccessToken() { - std::shared_ptr creds = CreateServiceAccountCredentials(); + std::shared_ptr creds = GoogleComputeEngineCredentials(); SecureCredentials* secure_creds = dynamic_cast(creds.get()); GPR_ASSERT(secure_creds != nullptr); @@ -107,14 +97,10 @@ std::shared_ptr CreateChannelForTestCase( snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(), FLAGS_server_port); - if (test_case == "service_account_creds") { - std::shared_ptr creds = CreateServiceAccountCredentials(); - return CreateTestChannel(host_port, FLAGS_server_host_override, - FLAGS_enable_ssl, FLAGS_use_prod_roots, creds); - } else if (test_case == "compute_engine_creds") { + if (test_case == "compute_engine_creds") { std::shared_ptr creds; GPR_ASSERT(FLAGS_enable_ssl); - creds = ComputeEngineCredentials(); + creds = GoogleComputeEngineCredentials(); return CreateTestChannel(host_port, FLAGS_server_host_override, FLAGS_enable_ssl, FLAGS_use_prod_roots, creds); } else if (test_case == "jwt_token_creds") { -- cgit v1.2.3 From 5cc1e2ec4b0e6a100dab285c74aed8233add8776 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 25 Aug 2015 22:07:58 -0700 Subject: Fixing PHP. --- src/php/ext/grpc/channel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c index 080a939662..a4313b6bd4 100644 --- a/src/php/ext/grpc/channel.c +++ b/src/php/ext/grpc/channel.c @@ -148,7 +148,7 @@ PHP_METHOD(Channel, __construct) { return; } if (args_array == NULL) { - channel->wrapped = grpc_insecure_channel_create(target, NULL, NULL, NULL); + channel->wrapped = grpc_insecure_channel_create(target, NULL, NULL); } else { array_hash = Z_ARRVAL_P(args_array); if (zend_hash_find(array_hash, "credentials", sizeof("credentials"), -- cgit v1.2.3 From c9ab6a022d6acde3dea311e9c65cf02dc44bf09f Mon Sep 17 00:00:00 2001 From: David Garcia Quintas Date: Wed, 26 Aug 2015 13:11:48 -0700 Subject: Protect against dereferencing a null ptr. 'stream' may be left nullptr after a pop, so don't try to dereference it. (via nlewycky@google.com). --- src/core/transport/chttp2/stream_lists.c | 44 ++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'src') 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; } -- cgit v1.2.3 From 0882a353d54e99276e7f63d49c43743e6a38d4d2 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 26 Aug 2015 13:21:14 -0700 Subject: Fix refcounting --- src/core/iomgr/tcp_windows.c | 73 ++++++++++++++++++++++++++++++++------------ 1 file changed, 53 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index e3abe1bebc..60c1ab3edd 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -96,17 +96,44 @@ typedef struct grpc_tcp { char *peer_string; } grpc_tcp; -static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } +static void tcp_free(grpc_tcp *tcp) { + grpc_winsocket_orphan(tcp->socket); + gpr_mu_destroy(&tcp->mu); + gpr_free(tcp->peer_string); + gpr_free(tcp); +} +#define GRPC_TCP_REFCOUNT_DEBUG +#ifdef GRPC_TCP_REFCOUNT_DEBUG +#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) +#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) +static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, + reason, tcp->refcount.count, tcp->refcount.count - 1); + if (gpr_unref(&tcp->refcount)) { + tcp_free(tcp); + } +} + +static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, + reason, tcp->refcount.count, tcp->refcount.count + 1); + gpr_ref(&tcp->refcount); +} +#else +#define TCP_UNREF(tcp, reason) tcp_unref((tcp)) +#define TCP_REF(tcp, reason) tcp_ref((tcp)) static void tcp_unref(grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { - grpc_winsocket_orphan(tcp->socket); - gpr_mu_destroy(&tcp->mu); - gpr_free(tcp->peer_string); - gpr_free(tcp); + tcp_free(tcp); } } +static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } +#endif + /* Asynchronous callback from the IOCP, or the background thread. */ static int on_read(grpc_tcp *tcp, int from_iocp) { grpc_winsocket *socket = tcp->socket; @@ -131,7 +158,6 @@ static int on_read(grpc_tcp *tcp, int from_iocp) { tcp->socket->read_info.outstanding = 0; gpr_slice_unref(tcp->read_slice); } - tcp_unref(tcp); return 0; } @@ -166,8 +192,10 @@ static void on_read_cb(void *tcpp, int from_iocp) { grpc_iomgr_closure *cb = tcp->read_cb; int success = on_read(tcp, from_iocp); tcp->read_cb = NULL; - tcp_unref(tcp); - cb->cb(cb->cb_arg, success); + TCP_UNREF(tcp, "read"); + if (cb) { + cb->cb(cb->cb_arg, success); + } } static grpc_endpoint_op_status win_read(grpc_endpoint *ep, @@ -185,6 +213,9 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, if (tcp->shutting_down) { return GRPC_ENDPOINT_ERROR; } + + TCP_REF(tcp, "read"); + tcp->socket->read_info.outstanding = 1; tcp->read_cb = cb; tcp->read_slices = read_slices; @@ -201,8 +232,11 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, /* Did we get data immediately ? Yay. */ if (info->wsa_error != WSAEWOULDBLOCK) { + int ok; info->bytes_transfered = bytes_read; - return on_read(tcp, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; + ok = on_read(tcp, 1); + TCP_UNREF(tcp, "read"); + return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } /* Otherwise, let's retry, by queuing a read. */ @@ -213,12 +247,13 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { + int ok; info->wsa_error = wsa_error; - return on_read(tcp, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; + ok = on_read(tcp, 1); + return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } } - tcp_ref(tcp); grpc_socket_notify_on_read(tcp->socket, on_read_cb, tcp); return GRPC_ENDPOINT_PENDING; } @@ -247,7 +282,7 @@ static void on_write(void *tcpp, int from_iocp) { if (from_iocp) { tcp->socket->write_info.outstanding = 0; } - tcp_unref(tcp); + TCP_UNREF(tcp, "write"); if (cb) { cb->cb(cb->cb_arg, 0); } @@ -270,7 +305,7 @@ static void on_write(void *tcpp, int from_iocp) { tcp->socket->write_info.outstanding = 0; - tcp_unref(tcp); + TCP_UNREF(tcp, "write"); cb->cb(cb->cb_arg, success); } @@ -292,7 +327,7 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, if (tcp->shutting_down) { return GRPC_ENDPOINT_ERROR; } - tcp_ref(tcp); + TCP_REF(tcp, "write"); tcp->socket->write_info.outstanding = 1; tcp->write_cb = cb; @@ -330,7 +365,7 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, } if (allocated) gpr_free(allocated); tcp->socket->write_info.outstanding = 0; - tcp_unref(tcp); + TCP_UNREF(tcp, "write"); return ret; } @@ -345,7 +380,7 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { tcp->socket->write_info.outstanding = 0; - tcp_unref(tcp); + TCP_UNREF(tcp, "write"); return GRPC_ENDPOINT_ERROR; } } @@ -378,19 +413,17 @@ static void win_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pss) { concurrent access of the data structure in that regard. */ static void win_shutdown(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; - int extra_refs = 0; gpr_mu_lock(&tcp->mu); /* At that point, what may happen is that we're already inside the IOCP callback. See the comments in on_read and on_write. */ tcp->shutting_down = 1; - extra_refs = grpc_winsocket_shutdown(tcp->socket); - while (extra_refs--) tcp_ref(tcp); + grpc_winsocket_shutdown(tcp->socket); gpr_mu_unlock(&tcp->mu); } static void win_destroy(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; - tcp_unref(tcp); + TCP_UNREF(tcp, "destroy"); } static char *win_get_peer(grpc_endpoint *ep) { -- cgit v1.2.3 From 57c48c6845a1b7d9f708bb0e24c45c30fa8668ef Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 26 Aug 2015 13:21:48 -0700 Subject: Turn off debug --- src/core/iomgr/tcp_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index 60c1ab3edd..cd2d95d482 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -103,7 +103,7 @@ static void tcp_free(grpc_tcp *tcp) { gpr_free(tcp); } -#define GRPC_TCP_REFCOUNT_DEBUG +/*#define GRPC_TCP_REFCOUNT_DEBUG*/ #ifdef GRPC_TCP_REFCOUNT_DEBUG #define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) #define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) -- cgit v1.2.3 From 8bf34083e2cf7336a75e39bc97d7aaeb26299512 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 26 Aug 2015 15:37:47 -0700 Subject: Fix uninitialized data --- src/core/iomgr/tcp_posix.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index 03be462960..0db7cd9f0e 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -85,8 +85,6 @@ typedef struct { grpc_iomgr_closure read_closure; grpc_iomgr_closure write_closure; - grpc_iomgr_closure handle_read_closure; - char *peer_string; } grpc_tcp; @@ -235,6 +233,7 @@ static void tcp_handle_read(void *arg /* grpc_tcp */, int success) { GPR_ASSERT(!tcp->finished_edge); if (!success) { + gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); call_read_cb(tcp, 0); TCP_UNREF(tcp, "read"); } else { @@ -255,8 +254,7 @@ static grpc_endpoint_op_status tcp_read(grpc_endpoint *ep, tcp->finished_edge = 0; grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); } else { - tcp->handle_read_closure.cb_arg = tcp; - grpc_iomgr_add_delayed_callback(&tcp->handle_read_closure, 1); + grpc_iomgr_add_delayed_callback(&tcp->read_closure, 1); } /* TODO(ctiller): immediate return */ return GRPC_ENDPOINT_PENDING; @@ -447,7 +445,6 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, tcp->write_closure.cb = tcp_handle_write; tcp->write_closure.cb_arg = tcp; - tcp->handle_read_closure.cb = tcp_handle_read; return &tcp->base; } -- cgit v1.2.3 From 70964fca29eaace42a63619c211803f8891f9d87 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 26 Aug 2015 15:41:53 -0700 Subject: Properly reset incoming buffer --- src/core/iomgr/tcp_windows.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index cd2d95d482..58f9160ef9 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -219,6 +219,7 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, tcp->socket->read_info.outstanding = 1; tcp->read_cb = cb; tcp->read_slices = read_slices; + gpr_slice_buffer_reset_and_unref(read_slices); tcp->read_slice = gpr_slice_malloc(8192); -- cgit v1.2.3 From d36ed20b7dccaec61cd9a84aa0b0f1e5306f9aac Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 26 Aug 2015 17:25:59 -0700 Subject: Trace window announcements --- src/core/transport/chttp2/writing.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c index 123061b3fc..bf0700c410 100644 --- a/src/core/transport/chttp2/writing.c +++ b/src/core/transport/chttp2/writing.c @@ -114,6 +114,10 @@ int grpc_chttp2_unlocking_check_writes( if (!stream_global->read_closed && stream_global->unannounced_incoming_window > 0) { + GPR_ASSERT(stream_writing->announce_window == 0); + GRPC_CHTTP2_FLOWCTL_TRACE_STREAM( + "write", transport_writing, stream_writing, announce_window, + stream_global->unannounced_incoming_window); stream_writing->announce_window = stream_global->unannounced_incoming_window; GRPC_CHTTP2_FLOWCTL_TRACE_STREAM( @@ -198,6 +202,9 @@ static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) { &transport_writing->outbuf, grpc_chttp2_window_update_create(stream_writing->id, stream_writing->announce_window)); + GRPC_CHTTP2_FLOWCTL_TRACE_STREAM( + "write", transport_writing, stream_writing, announce_window, + -(gpr_int64)stream_writing->announce_window); stream_writing->announce_window = 0; } if (stream_writing->send_closed == GRPC_SEND_CLOSED_WITH_RST_STREAM) { -- cgit v1.2.3 From a0461e52f3b90afa6054f48a32a654a9c7d28f6f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 26 Aug 2015 17:26:09 -0700 Subject: Fix an edge case in call.c If we get a full incoming buffer, we'll issue a read with max_recv_bytes==0, deadlocking the flow control code. Instead, hold off on advertising reading until the buffer gets a little more clear, then start pulling. --- src/core/surface/call.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 4426bbbce9..f25ef74a92 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -630,9 +630,6 @@ static void unlock(grpc_call *call) { call->cancel_alarm = 0; if (!call->receiving && need_more_data(call)) { - op.recv_ops = &call->recv_ops; - op.recv_state = &call->recv_state; - op.on_done_recv = &call->on_done_recv; if (grpc_bbq_empty(&call->incoming_queue) && call->reading_message) { op.max_recv_bytes = call->incoming_message_length - call->incoming_message.length + MAX_RECV_PEEK_AHEAD; @@ -644,9 +641,14 @@ static void unlock(grpc_call *call) { op.max_recv_bytes = MAX_RECV_PEEK_AHEAD - buffered_bytes; } } - call->receiving = 1; - GRPC_CALL_INTERNAL_REF(call, "receiving"); - start_op = 1; + if (op.max_recv_bytes != 0) { + op.recv_ops = &call->recv_ops; + op.recv_state = &call->recv_state; + op.on_done_recv = &call->on_done_recv; + call->receiving = 1; + GRPC_CALL_INTERNAL_REF(call, "receiving"); + start_op = 1; + } } if (!call->sending) { -- cgit v1.2.3 From 2845c86958fbb2a30b06f88106583fb1e1131cc3 Mon Sep 17 00:00:00 2001 From: Hongyu Chen Date: Wed, 26 Aug 2015 18:06:52 -0700 Subject: Fix include guard of census/grpc_filter.h --- src/core/census/grpc_filter.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') 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 */ -- cgit v1.2.3 From 8e3dc00d93232b8cc4f3760fa252320fe1ded860 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Thu, 27 Aug 2015 03:13:41 +0000 Subject: The Beta API Channel --- src/python/grpcio/grpc/_adapter/_c/types/channel.c | 2 +- src/python/grpcio/grpc/beta/__init__.py | 28 ++++ .../grpcio/grpc/beta/_connectivity_channel.py | 148 +++++++++++++++++ src/python/grpcio/grpc/beta/beta.py | 114 +++++++++++++ src/python/grpcio/grpc/beta/utilities.py | 161 ++++++++++++++++++ src/python/grpcio_test/grpc_test/beta/__init__.py | 30 ++++ .../grpc_test/beta/_connectivity_channel_test.py | 180 +++++++++++++++++++++ .../grpcio_test/grpc_test/beta/_utilities_test.py | 123 ++++++++++++++ 8 files changed, 785 insertions(+), 1 deletion(-) create mode 100644 src/python/grpcio/grpc/beta/__init__.py create mode 100644 src/python/grpcio/grpc/beta/_connectivity_channel.py create mode 100644 src/python/grpcio/grpc/beta/beta.py create mode 100644 src/python/grpcio/grpc/beta/utilities.py create mode 100644 src/python/grpcio_test/grpc_test/beta/__init__.py create mode 100644 src/python/grpcio_test/grpc_test/beta/_connectivity_channel_test.py create mode 100644 src/python/grpcio_test/grpc_test/beta/_utilities_test.py (limited to 'src') diff --git a/src/python/grpcio/grpc/_adapter/_c/types/channel.c b/src/python/grpcio/grpc/_adapter/_c/types/channel.c index c577ac05eb..cf866dd80c 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types/channel.c +++ b/src/python/grpcio/grpc/_adapter/_c/types/channel.c @@ -164,7 +164,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/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/beta.py b/src/python/grpcio/grpc/beta/beta.py new file mode 100644 index 0000000000..40cad5e486 --- /dev/null +++ b/src/python/grpcio/grpc/beta/beta.py @@ -0,0 +1,114 @@ +# 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 gRPC Python Beta.""" + +import enum + +from grpc._adapter import _low +from grpc._adapter import _types +from grpc.beta import _connectivity_channel + +_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 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): + 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. + """ + return Channel(_low.Channel('%s:%d' % (host, port), ())) 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_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/_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) -- cgit v1.2.3 From 0d9f81f741b33e23941db435b9ba7a9ed37adaec Mon Sep 17 00:00:00 2001 From: yang-g Date: Wed, 26 Aug 2015 22:04:30 -0700 Subject: minor fixes --- include/grpc++/support/string_ref.h | 10 +++++----- src/cpp/util/string_ref.cc | 2 +- test/cpp/util/string_ref_test.cc | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/include/grpc++/support/string_ref.h b/include/grpc++/support/string_ref.h index fd2b3ad8e7..2bc1fecefe 100644 --- a/include/grpc++/support/string_ref.h +++ b/include/grpc++/support/string_ref.h @@ -31,8 +31,8 @@ * */ -#ifndef GRPCXX_STRING_REF_H -#define GRPCXX_STRING_REF_H +#ifndef GRPCXX_SUPPORT_STRING_REF_H +#define GRPCXX_SUPPORT_STRING_REF_H #include #include @@ -44,6 +44,8 @@ namespace grpc { // This class is a non owning reference to a string. // It should be a strict subset of the upcoming std::string_ref. See: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html +// The constexpr is dropped or replaced with const for legacy compiler +// compatibility. class string_ref { public: // types @@ -115,6 +117,4 @@ std::ostream& operator<<(std::ostream& stream, const string_ref& string); } // namespace grpc -#endif // GRPCXX_STRING_REF_H - - +#endif // GRPCXX_SUPPORT_STRING_REF_H diff --git a/src/cpp/util/string_ref.cc b/src/cpp/util/string_ref.cc index eb54f65e3a..9adc092013 100644 --- a/src/cpp/util/string_ref.cc +++ b/src/cpp/util/string_ref.cc @@ -80,7 +80,7 @@ size_t string_ref::find(string_ref s) const { } size_t string_ref::find(char c) const { - auto it = std::find_if(cbegin(), cend(), [c](char cc) { return cc == c; }); + auto it = std::find(cbegin(), cend(), c); return it == cend() ? npos : std::distance(cbegin(), it); } diff --git a/test/cpp/util/string_ref_test.cc b/test/cpp/util/string_ref_test.cc index c4ca4fce84..465072d43e 100644 --- a/test/cpp/util/string_ref_test.cc +++ b/test/cpp/util/string_ref_test.cc @@ -100,8 +100,8 @@ TEST_F(StringRefTest, Assignment) { TEST_F(StringRefTest, Iterator) { string_ref s(kTestString); size_t i = 0; - for (char c : s) { - EXPECT_EQ(kTestString[i++], c); + for (auto it = s.cbegin(); it != s.cend(); ++it) { + EXPECT_EQ(kTestString[i++], *it); } EXPECT_EQ(strlen(kTestString), i); } -- cgit v1.2.3 From 35b559f6f7e4e6410613632bbfe3f2ab84073feb Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Wed, 26 Aug 2015 23:17:35 -0700 Subject: Aligning C++ interface with C for the auth metadata processor. --- include/grpc++/auth_metadata_processor.h | 16 ++++++---- src/cpp/server/secure_server_credentials.cc | 46 ++++++++++++++++++----------- src/cpp/server/secure_server_credentials.h | 1 - 3 files changed, 39 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/include/grpc++/auth_metadata_processor.h b/include/grpc++/auth_metadata_processor.h index 3caf3e84fd..c0631bc11f 100644 --- a/include/grpc++/auth_metadata_processor.h +++ b/include/grpc++/auth_metadata_processor.h @@ -35,14 +35,18 @@ #define GRPCXX_AUTH_METADATA_PROCESSOR_H_ #include -#include #include +#include +#include namespace grpc { class AuthMetadataProcessor { public: + typedef std::multimap InputMetadata; + typedef std::multimap OutputMetadata; + virtual ~AuthMetadataProcessor() {} // If this method returns true, the Process function will be scheduled in @@ -54,11 +58,11 @@ class AuthMetadataProcessor { // from the passed-in auth_metadata. // consumed_auth_metadata needs to be filled with metadata that has been // consumed by the processor and will be removed from the call. - // Returns true if successful. - virtual bool Process( - const std::multimap& auth_metadata, - AuthContext* context, - std::multimap* consumed_auth_metadata) = 0; + // TODO(jboeuf). + virtual Status Process(const InputMetadata& auth_metadata, + AuthContext* context, + OutputMetadata* consumed_auth_metadata, + OutputMetadata* response_metadata) = 0; }; } // namespace grpc diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index a7d11856a0..86c180e7e2 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -66,28 +66,40 @@ 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) { - Metadata metadata; + AuthMetadataProcessor::InputMetadata metadata; for (size_t i = 0; i < num_md; i++) { metadata.insert(std::make_pair( - md[i].key, grpc::string(md[i].value, md[i].value_length))); + md[i].key, grpc::string_ref(md[i].value, md[i].value_length))); } SecureAuthContext context(ctx); - Metadata consumed_metadata; - bool ok = processor_->Process(metadata, &context, &consumed_metadata); - if (ok) { - std::vector consumed_md(consumed_metadata.size()); - for (const auto& entry : consumed_metadata) { - consumed_md.push_back({entry.first.c_str(), - entry.second.data(), - entry.second.size(), - 0, - {{nullptr, nullptr, nullptr, nullptr}}}); - } - cb(user_data, &consumed_md[0], consumed_md.size(), nullptr, 0, - GRPC_STATUS_OK, nullptr); - } else { - cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_UNAUTHENTICATED, nullptr); + AuthMetadataProcessor::OutputMetadata consumed_metadata; + AuthMetadataProcessor::OutputMetadata response_metadata; + + Status status = processor_->Process(metadata, &context, &consumed_metadata, + &response_metadata); + + std::vector consumed_md(consumed_metadata.size()); + 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 response_md(response_metadata.size()); + 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(status.error_code()), + status.error_message().c_str()); } int SecureServerCredentials::AddPortToServer(const grpc::string& addr, diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index e427280a37..d15b793b15 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -55,7 +55,6 @@ class AuthMetadataProcessorAyncWrapper GRPC_FINAL { : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {} private: - typedef std::multimap Metadata; void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data); -- cgit v1.2.3 From 99d7b661bede39143d1be6040fb67c81b8117ae3 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 27 Aug 2015 07:36:12 -0700 Subject: Revert "Refactor Endpoint API" --- include/grpc/support/slice_buffer.h | 2 - src/core/httpcli/httpcli.c | 95 +++--- src/core/iomgr/endpoint.c | 17 +- src/core/iomgr/endpoint.h | 63 ++-- src/core/iomgr/tcp_posix.c | 525 +++++++++++++++++++---------- src/core/iomgr/tcp_windows.c | 192 +++++------ src/core/security/secure_endpoint.c | 188 +++++------ src/core/security/secure_transport_setup.c | 119 +++---- src/core/support/slice_buffer.c | 22 -- src/core/transport/chttp2/internal.h | 12 +- src/core/transport/chttp2/writing.c | 21 +- src/core/transport/chttp2_transport.c | 140 ++++---- test/core/bad_client/bad_client.c | 17 +- test/core/iomgr/endpoint_tests.c | 204 +++++------ test/core/iomgr/tcp_posix_test.c | 148 ++++---- test/core/security/secure_endpoint_test.c | 55 ++- test/core/util/port_posix.c | 14 +- test/core/util/port_windows.c | 91 +---- 18 files changed, 978 insertions(+), 947 deletions(-) (limited to 'src') diff --git a/include/grpc/support/slice_buffer.h b/include/grpc/support/slice_buffer.h index 04db003ac5..ec048e8c91 100644 --- a/include/grpc/support/slice_buffer.h +++ b/include/grpc/support/slice_buffer.h @@ -86,8 +86,6 @@ void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb); void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b); /* move all of the elements of src into dst */ void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst); -/* remove n bytes from the end of a slice buffer */ -void gpr_slice_buffer_trim_end(gpr_slice_buffer *src, size_t n); #ifdef __cplusplus } diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c index 1e38479eb1..9012070e8e 100644 --- a/src/core/httpcli/httpcli.c +++ b/src/core/httpcli/httpcli.c @@ -61,10 +61,6 @@ typedef struct { grpc_httpcli_context *context; grpc_pollset *pollset; grpc_iomgr_object iomgr_obj; - gpr_slice_buffer incoming; - gpr_slice_buffer outgoing; - grpc_iomgr_closure on_read; - grpc_iomgr_closure done_write; } internal_request; static grpc_httpcli_get_override g_get_override = NULL; @@ -103,70 +99,73 @@ static void finish(internal_request *req, int success) { gpr_slice_unref(req->request_text); gpr_free(req->host); grpc_iomgr_unregister_object(&req->iomgr_obj); - gpr_slice_buffer_destroy(&req->incoming); - gpr_slice_buffer_destroy(&req->outgoing); gpr_free(req); } -static void on_read(void *user_data, int success); - -static void do_read(internal_request *req) { - switch (grpc_endpoint_read(req->ep, &req->incoming, &req->on_read)) { - case GRPC_ENDPOINT_DONE: - on_read(req, 1); - break; - case GRPC_ENDPOINT_PENDING: - break; - case GRPC_ENDPOINT_ERROR: - on_read(req, 0); - break; - } -} - -static void on_read(void *user_data, int success) { +static void on_read(void *user_data, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status status) { internal_request *req = user_data; size_t i; - for (i = 0; i < req->incoming.count; i++) { - if (GPR_SLICE_LENGTH(req->incoming.slices[i])) { + for (i = 0; i < nslices; i++) { + if (GPR_SLICE_LENGTH(slices[i])) { req->have_read_byte = 1; - if (!grpc_httpcli_parser_parse(&req->parser, req->incoming.slices[i])) { + if (!grpc_httpcli_parser_parse(&req->parser, slices[i])) { finish(req, 0); - return; + goto done; } } } - if (success) { - do_read(req); - } else if (!req->have_read_byte) { - next_address(req); - } else { - finish(req, grpc_httpcli_parser_eof(&req->parser)); + switch (status) { + case GRPC_ENDPOINT_CB_OK: + grpc_endpoint_notify_on_read(req->ep, on_read, req); + break; + case GRPC_ENDPOINT_CB_EOF: + case GRPC_ENDPOINT_CB_ERROR: + case GRPC_ENDPOINT_CB_SHUTDOWN: + if (!req->have_read_byte) { + next_address(req); + } else { + finish(req, grpc_httpcli_parser_eof(&req->parser)); + } + break; + } + +done: + for (i = 0; i < nslices; i++) { + gpr_slice_unref(slices[i]); } } -static void on_written(internal_request *req) { do_read(req); } +static void on_written(internal_request *req) { + grpc_endpoint_notify_on_read(req->ep, on_read, req); +} -static void done_write(void *arg, int success) { +static void done_write(void *arg, grpc_endpoint_cb_status status) { internal_request *req = arg; - if (success) { - on_written(req); - } else { - next_address(req); + switch (status) { + case GRPC_ENDPOINT_CB_OK: + on_written(req); + break; + case GRPC_ENDPOINT_CB_EOF: + case GRPC_ENDPOINT_CB_SHUTDOWN: + case GRPC_ENDPOINT_CB_ERROR: + next_address(req); + break; } } static void start_write(internal_request *req) { gpr_slice_ref(req->request_text); - gpr_slice_buffer_add(&req->outgoing, req->request_text); - switch (grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write)) { - case GRPC_ENDPOINT_DONE: + switch ( + grpc_endpoint_write(req->ep, &req->request_text, 1, done_write, req)) { + case GRPC_ENDPOINT_WRITE_DONE: on_written(req); break; - case GRPC_ENDPOINT_PENDING: + case GRPC_ENDPOINT_WRITE_PENDING: break; - case GRPC_ENDPOINT_ERROR: + case GRPC_ENDPOINT_WRITE_ERROR: finish(req, 0); break; } @@ -238,10 +237,6 @@ void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset, request->handshaker ? request->handshaker : &grpc_httpcli_plaintext; req->context = context; req->pollset = pollset; - grpc_iomgr_closure_init(&req->on_read, on_read, req); - grpc_iomgr_closure_init(&req->done_write, done_write, req); - gpr_slice_buffer_init(&req->incoming); - gpr_slice_buffer_init(&req->outgoing); gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path); grpc_iomgr_register_object(&req->iomgr_obj, name); gpr_free(name); @@ -275,11 +270,7 @@ void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset, request->handshaker ? request->handshaker : &grpc_httpcli_plaintext; req->context = context; req->pollset = pollset; - grpc_iomgr_closure_init(&req->on_read, on_read, req); - grpc_iomgr_closure_init(&req->done_write, done_write, req); - gpr_slice_buffer_init(&req->incoming); - gpr_slice_buffer_init(&req->outgoing); - gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->path); + gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path); grpc_iomgr_register_object(&req->iomgr_obj, name); gpr_free(name); req->host = gpr_strdup(request->host); diff --git a/src/core/iomgr/endpoint.c b/src/core/iomgr/endpoint.c index a7878e31dd..8ee14bce9b 100644 --- a/src/core/iomgr/endpoint.c +++ b/src/core/iomgr/endpoint.c @@ -33,16 +33,17 @@ #include "src/core/iomgr/endpoint.h" -grpc_endpoint_op_status grpc_endpoint_read(grpc_endpoint *ep, - gpr_slice_buffer *slices, - grpc_iomgr_closure *cb) { - return ep->vtable->read(ep, slices, cb); +void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, + void *user_data) { + ep->vtable->notify_on_read(ep, cb, user_data); } -grpc_endpoint_op_status grpc_endpoint_write(grpc_endpoint *ep, - gpr_slice_buffer *slices, - grpc_iomgr_closure *cb) { - return ep->vtable->write(ep, slices, cb); +grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, + gpr_slice *slices, + size_t nslices, + grpc_endpoint_write_cb cb, + void *user_data) { + return ep->vtable->write(ep, slices, nslices, cb, user_data); } void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { diff --git a/src/core/iomgr/endpoint.h b/src/core/iomgr/endpoint.h index d14d52d561..ea92a500e8 100644 --- a/src/core/iomgr/endpoint.h +++ b/src/core/iomgr/endpoint.h @@ -37,7 +37,6 @@ #include "src/core/iomgr/pollset.h" #include "src/core/iomgr/pollset_set.h" #include -#include #include /* An endpoint caps a streaming channel between two communicating processes. @@ -46,17 +45,31 @@ typedef struct grpc_endpoint grpc_endpoint; typedef struct grpc_endpoint_vtable grpc_endpoint_vtable; -typedef enum grpc_endpoint_op_status { - GRPC_ENDPOINT_DONE, /* completed immediately, cb won't be called */ - GRPC_ENDPOINT_PENDING, /* cb will be called when completed */ - GRPC_ENDPOINT_ERROR /* write errored out, cb won't be called */ -} grpc_endpoint_op_status; +typedef enum grpc_endpoint_cb_status { + GRPC_ENDPOINT_CB_OK = 0, /* Call completed successfully */ + GRPC_ENDPOINT_CB_EOF, /* Call completed successfully, end of file reached */ + GRPC_ENDPOINT_CB_SHUTDOWN, /* Call interrupted by shutdown */ + GRPC_ENDPOINT_CB_ERROR /* Call interrupted by socket error */ +} grpc_endpoint_cb_status; + +typedef enum grpc_endpoint_write_status { + GRPC_ENDPOINT_WRITE_DONE, /* completed immediately, cb won't be called */ + GRPC_ENDPOINT_WRITE_PENDING, /* cb will be called when completed */ + GRPC_ENDPOINT_WRITE_ERROR /* write errored out, cb won't be called */ +} grpc_endpoint_write_status; + +typedef void (*grpc_endpoint_read_cb)(void *user_data, gpr_slice *slices, + size_t nslices, + grpc_endpoint_cb_status error); +typedef void (*grpc_endpoint_write_cb)(void *user_data, + grpc_endpoint_cb_status error); struct grpc_endpoint_vtable { - grpc_endpoint_op_status (*read)(grpc_endpoint *ep, gpr_slice_buffer *slices, - grpc_iomgr_closure *cb); - grpc_endpoint_op_status (*write)(grpc_endpoint *ep, gpr_slice_buffer *slices, - grpc_iomgr_closure *cb); + void (*notify_on_read)(grpc_endpoint *ep, grpc_endpoint_read_cb cb, + void *user_data); + grpc_endpoint_write_status (*write)(grpc_endpoint *ep, gpr_slice *slices, + size_t nslices, grpc_endpoint_write_cb cb, + void *user_data); void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset); void (*add_to_pollset_set)(grpc_endpoint *ep, grpc_pollset_set *pollset); void (*shutdown)(grpc_endpoint *ep); @@ -64,32 +77,26 @@ struct grpc_endpoint_vtable { char *(*get_peer)(grpc_endpoint *ep); }; -/* When data is available on the connection, calls the callback with slices. - Callback success indicates that the endpoint can accept more reads, failure - indicates the endpoint is closed. - Valid slices may be placed into \a slices even on callback success == 0. */ -grpc_endpoint_op_status grpc_endpoint_read( - grpc_endpoint *ep, gpr_slice_buffer *slices, - grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT; +/* When data is available on the connection, calls the callback with slices. */ +void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, + void *user_data); char *grpc_endpoint_get_peer(grpc_endpoint *ep); /* Write slices out to the socket. If the connection is ready for more data after the end of the call, it - returns GRPC_ENDPOINT_DONE. - Otherwise it returns GRPC_ENDPOINT_PENDING and calls cb when the - connection is ready for more data. - \a slices may be mutated at will by the endpoint until cb is called. - No guarantee is made to the content of slices after a write EXCEPT that - it is a valid slice buffer. - */ -grpc_endpoint_op_status grpc_endpoint_write( - grpc_endpoint *ep, gpr_slice_buffer *slices, - grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT; + returns GRPC_ENDPOINT_WRITE_DONE. + Otherwise it returns GRPC_ENDPOINT_WRITE_PENDING and calls cb when the + connection is ready for more data. */ +grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, + gpr_slice *slices, + size_t nslices, + grpc_endpoint_write_cb cb, + void *user_data); /* Causes any pending read/write callbacks to run immediately with - success==0 */ + GRPC_ENDPOINT_CB_SHUTDOWN status */ void grpc_endpoint_shutdown(grpc_endpoint *ep); void grpc_endpoint_destroy(grpc_endpoint *ep); diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index 0db7cd9f0e..360e6ebd8c 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -61,8 +61,209 @@ #define SENDMSG_FLAGS 0 #endif +/* Holds a slice array and associated state. */ +typedef struct grpc_tcp_slice_state { + gpr_slice *slices; /* Array of slices */ + size_t nslices; /* Size of slices array. */ + ssize_t first_slice; /* First valid slice in array */ + ssize_t last_slice; /* Last valid slice in array */ + gpr_slice working_slice; /* pointer to original final slice */ + int working_slice_valid; /* True if there is a working slice */ + int memory_owned; /* True if slices array is owned */ +} grpc_tcp_slice_state; + int grpc_tcp_trace = 0; +static void slice_state_init(grpc_tcp_slice_state *state, gpr_slice *slices, + size_t nslices, size_t valid_slices) { + state->slices = slices; + state->nslices = nslices; + if (valid_slices == 0) { + state->first_slice = -1; + } else { + state->first_slice = 0; + } + state->last_slice = valid_slices - 1; + state->working_slice_valid = 0; + state->memory_owned = 0; +} + +/* Returns true if there is still available data */ +static int slice_state_has_available(grpc_tcp_slice_state *state) { + return state->first_slice != -1 && state->last_slice >= state->first_slice; +} + +static ssize_t slice_state_slices_allocated(grpc_tcp_slice_state *state) { + if (state->first_slice == -1) { + return 0; + } else { + return state->last_slice - state->first_slice + 1; + } +} + +static void slice_state_realloc(grpc_tcp_slice_state *state, size_t new_size) { + /* TODO(klempner): use realloc instead when first_slice is 0 */ + /* TODO(klempner): Avoid a realloc in cases where it is unnecessary */ + gpr_slice *slices = state->slices; + size_t original_size = slice_state_slices_allocated(state); + size_t i; + gpr_slice *new_slices = gpr_malloc(sizeof(gpr_slice) * new_size); + + for (i = 0; i < original_size; ++i) { + new_slices[i] = slices[i + state->first_slice]; + } + + state->slices = new_slices; + state->last_slice = original_size - 1; + if (original_size > 0) { + state->first_slice = 0; + } else { + state->first_slice = -1; + } + state->nslices = new_size; + + if (state->memory_owned) { + gpr_free(slices); + } + state->memory_owned = 1; +} + +static void slice_state_remove_prefix(grpc_tcp_slice_state *state, + size_t prefix_bytes) { + gpr_slice *current_slice = &state->slices[state->first_slice]; + size_t current_slice_size; + + while (slice_state_has_available(state)) { + current_slice_size = GPR_SLICE_LENGTH(*current_slice); + if (current_slice_size > prefix_bytes) { + /* TODO(klempner): Get rid of the extra refcount created here by adding a + native "trim the first N bytes" operation to splice */ + /* TODO(klempner): This really shouldn't be modifying the current slice + unless we own the slices array. */ + gpr_slice tail; + tail = gpr_slice_split_tail(current_slice, prefix_bytes); + gpr_slice_unref(*current_slice); + *current_slice = tail; + return; + } else { + gpr_slice_unref(*current_slice); + ++state->first_slice; + ++current_slice; + prefix_bytes -= current_slice_size; + } + } +} + +static void slice_state_destroy(grpc_tcp_slice_state *state) { + while (slice_state_has_available(state)) { + gpr_slice_unref(state->slices[state->first_slice]); + ++state->first_slice; + } + + if (state->memory_owned) { + gpr_free(state->slices); + state->memory_owned = 0; + } +} + +void slice_state_transfer_ownership(grpc_tcp_slice_state *state, + gpr_slice **slices, size_t *nslices) { + *slices = state->slices + state->first_slice; + *nslices = state->last_slice - state->first_slice + 1; + + state->first_slice = -1; + state->last_slice = -1; +} + +/* Fills iov with the first min(iov_size, available) slices, returns number + filled */ +static size_t slice_state_to_iovec(grpc_tcp_slice_state *state, + struct iovec *iov, size_t iov_size) { + size_t nslices = state->last_slice - state->first_slice + 1; + gpr_slice *slices = state->slices + state->first_slice; + size_t i; + if (nslices < iov_size) { + iov_size = nslices; + } + + for (i = 0; i < iov_size; ++i) { + iov[i].iov_base = GPR_SLICE_START_PTR(slices[i]); + iov[i].iov_len = GPR_SLICE_LENGTH(slices[i]); + } + return iov_size; +} + +/* Makes n blocks available at the end of state, writes them into iov, and + returns the number of bytes allocated */ +static size_t slice_state_append_blocks_into_iovec(grpc_tcp_slice_state *state, + struct iovec *iov, size_t n, + size_t slice_size) { + size_t target_size; + size_t i; + size_t allocated_bytes; + ssize_t allocated_slices = slice_state_slices_allocated(state); + + if (n - state->working_slice_valid >= state->nslices - state->last_slice) { + /* Need to grow the slice array */ + target_size = state->nslices; + do { + target_size = target_size * 2; + } while (target_size < allocated_slices + n - state->working_slice_valid); + /* TODO(klempner): If this ever needs to support both prefix removal and + append, we should be smarter about the growth logic here */ + slice_state_realloc(state, target_size); + } + + i = 0; + allocated_bytes = 0; + + if (state->working_slice_valid) { + iov[0].iov_base = GPR_SLICE_END_PTR(state->slices[state->last_slice]); + iov[0].iov_len = GPR_SLICE_LENGTH(state->working_slice) - + GPR_SLICE_LENGTH(state->slices[state->last_slice]); + allocated_bytes += iov[0].iov_len; + ++i; + state->slices[state->last_slice] = state->working_slice; + state->working_slice_valid = 0; + } + + for (; i < n; ++i) { + ++state->last_slice; + state->slices[state->last_slice] = gpr_slice_malloc(slice_size); + iov[i].iov_base = GPR_SLICE_START_PTR(state->slices[state->last_slice]); + iov[i].iov_len = slice_size; + allocated_bytes += slice_size; + } + if (state->first_slice == -1) { + state->first_slice = 0; + } + return allocated_bytes; +} + +/* Remove the last n bytes from state */ +/* TODO(klempner): Consider having this defer actual deletion until later */ +static void slice_state_remove_last(grpc_tcp_slice_state *state, size_t bytes) { + while (bytes > 0 && slice_state_has_available(state)) { + if (GPR_SLICE_LENGTH(state->slices[state->last_slice]) > bytes) { + state->working_slice = state->slices[state->last_slice]; + state->working_slice_valid = 1; + /* TODO(klempner): Combine these into a single operation that doesn't need + to refcount */ + gpr_slice_unref(gpr_slice_split_tail( + &state->slices[state->last_slice], + GPR_SLICE_LENGTH(state->slices[state->last_slice]) - bytes)); + bytes = 0; + } else { + bytes -= GPR_SLICE_LENGTH(state->slices[state->last_slice]); + gpr_slice_unref(state->slices[state->last_slice]); + --state->last_slice; + if (state->last_slice == -1) { + state->first_slice = -1; + } + } + } +} + typedef struct { grpc_endpoint base; grpc_fd *em_fd; @@ -72,111 +273,80 @@ typedef struct { size_t slice_size; gpr_refcount refcount; - gpr_slice_buffer *incoming_buffer; - gpr_slice_buffer *outgoing_buffer; - /** slice within outgoing_buffer to write next */ - size_t outgoing_slice_idx; - /** byte within outgoing_buffer->slices[outgoing_slice_idx] to write next */ - size_t outgoing_byte_idx; + grpc_endpoint_read_cb read_cb; + void *read_user_data; + grpc_endpoint_write_cb write_cb; + void *write_user_data; - grpc_iomgr_closure *read_cb; - grpc_iomgr_closure *write_cb; + grpc_tcp_slice_state write_state; grpc_iomgr_closure read_closure; grpc_iomgr_closure write_closure; + grpc_iomgr_closure handle_read_closure; + char *peer_string; } grpc_tcp; -static void tcp_handle_read(void *arg /* grpc_tcp */, int success); -static void tcp_handle_write(void *arg /* grpc_tcp */, int success); +static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); +static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success); -static void tcp_shutdown(grpc_endpoint *ep) { +static void grpc_tcp_shutdown(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_fd_shutdown(tcp->em_fd); } -static void tcp_free(grpc_tcp *tcp) { - grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan"); - gpr_free(tcp->peer_string); - gpr_free(tcp); -} - -/*#define GRPC_TCP_REFCOUNT_DEBUG*/ -#ifdef GRPC_TCP_REFCOUNT_DEBUG -#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) -#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) -static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, - int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, - reason, tcp->refcount.count, tcp->refcount.count - 1); - if (gpr_unref(&tcp->refcount)) { - tcp_free(tcp); +static void grpc_tcp_unref(grpc_tcp *tcp) { + int refcount_zero = gpr_unref(&tcp->refcount); + if (refcount_zero) { + grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan"); + gpr_free(tcp->peer_string); + gpr_free(tcp); } } -static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, - int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, - reason, tcp->refcount.count, tcp->refcount.count + 1); - gpr_ref(&tcp->refcount); -} -#else -#define TCP_UNREF(tcp, reason) tcp_unref((tcp)) -#define TCP_REF(tcp, reason) tcp_ref((tcp)) -static void tcp_unref(grpc_tcp *tcp) { - if (gpr_unref(&tcp->refcount)) { - tcp_free(tcp); - } -} - -static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } -#endif - -static void tcp_destroy(grpc_endpoint *ep) { +static void grpc_tcp_destroy(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; - TCP_UNREF(tcp, "destroy"); + grpc_tcp_unref(tcp); } -static void call_read_cb(grpc_tcp *tcp, int success) { - grpc_iomgr_closure *cb = tcp->read_cb; +static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status status) { + grpc_endpoint_read_cb cb = tcp->read_cb; if (grpc_tcp_trace) { size_t i; - gpr_log(GPR_DEBUG, "read: success=%d", success); - for (i = 0; i < tcp->incoming_buffer->count; i++) { - char *dump = gpr_dump_slice(tcp->incoming_buffer->slices[i], - GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "read: status=%d", status); + for (i = 0; i < nslices; i++) { + char *dump = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump); gpr_free(dump); } } tcp->read_cb = NULL; - tcp->incoming_buffer = NULL; - cb->cb(cb->cb_arg, success); + cb(tcp->read_user_data, slices, nslices, status); } +#define INLINE_SLICE_BUFFER_SIZE 8 #define MAX_READ_IOVEC 4 -static void tcp_continue_read(grpc_tcp *tcp) { +static void grpc_tcp_continue_read(grpc_tcp *tcp) { + gpr_slice static_read_slices[INLINE_SLICE_BUFFER_SIZE]; struct msghdr msg; struct iovec iov[MAX_READ_IOVEC]; ssize_t read_bytes; - size_t i; + ssize_t allocated_bytes; + struct grpc_tcp_slice_state read_state; + gpr_slice *final_slices; + size_t final_nslices; GPR_ASSERT(!tcp->finished_edge); - GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC); - GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC); GRPC_TIMER_BEGIN(GRPC_PTAG_HANDLE_READ, 0); + slice_state_init(&read_state, static_read_slices, INLINE_SLICE_BUFFER_SIZE, + 0); - while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) { - gpr_slice_buffer_add_indexed(tcp->incoming_buffer, - gpr_slice_malloc(tcp->slice_size)); - } - for (i = 0; i < tcp->incoming_buffer->count; i++) { - iov[i].iov_base = GPR_SLICE_START_PTR(tcp->incoming_buffer->slices[i]); - iov[i].iov_len = GPR_SLICE_LENGTH(tcp->incoming_buffer->slices[i]); - } + allocated_bytes = slice_state_append_blocks_into_iovec( + &read_state, iov, tcp->iov_size, tcp->slice_size); msg.msg_name = NULL; msg.msg_namelen = 0; @@ -192,105 +362,106 @@ static void tcp_continue_read(grpc_tcp *tcp) { } while (read_bytes < 0 && errno == EINTR); GRPC_TIMER_END(GRPC_PTAG_RECVMSG, 0); + if (read_bytes < allocated_bytes) { + /* TODO(klempner): Consider a second read first, in hopes of getting a + * quick EAGAIN and saving a bunch of allocations. */ + slice_state_remove_last(&read_state, read_bytes < 0 + ? allocated_bytes + : allocated_bytes - read_bytes); + } + if (read_bytes < 0) { - /* NB: After calling call_read_cb a parallel call of the read handler may + /* NB: After calling the user_cb a parallel call of the read handler may * be running. */ if (errno == EAGAIN) { if (tcp->iov_size > 1) { tcp->iov_size /= 2; } - /* We've consumed the edge, request a new one */ - grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); + if (slice_state_has_available(&read_state)) { + /* TODO(klempner): We should probably do the call into the application + without all this junk on the stack */ + /* FIXME(klempner): Refcount properly */ + slice_state_transfer_ownership(&read_state, &final_slices, + &final_nslices); + tcp->finished_edge = 1; + call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_OK); + slice_state_destroy(&read_state); + grpc_tcp_unref(tcp); + } else { + /* We've consumed the edge, request a new one */ + slice_state_destroy(&read_state); + grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); + } } else { /* TODO(klempner): Log interesting errors */ - gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); - call_read_cb(tcp, 0); - TCP_UNREF(tcp, "read"); + call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_ERROR); + slice_state_destroy(&read_state); + grpc_tcp_unref(tcp); } } else if (read_bytes == 0) { /* 0 read size ==> end of stream */ - gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); - call_read_cb(tcp, 0); - TCP_UNREF(tcp, "read"); + if (slice_state_has_available(&read_state)) { + /* there were bytes already read: pass them up to the application */ + slice_state_transfer_ownership(&read_state, &final_slices, + &final_nslices); + call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_EOF); + } else { + call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_EOF); + } + slice_state_destroy(&read_state); + grpc_tcp_unref(tcp); } else { - GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length); - if ((size_t)read_bytes < tcp->incoming_buffer->length) { - gpr_slice_buffer_trim_end(tcp->incoming_buffer, - tcp->incoming_buffer->length - read_bytes); - } else if (tcp->iov_size < MAX_READ_IOVEC) { + if (tcp->iov_size < MAX_READ_IOVEC) { ++tcp->iov_size; } - GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length); - call_read_cb(tcp, 1); - TCP_UNREF(tcp, "read"); + GPR_ASSERT(slice_state_has_available(&read_state)); + slice_state_transfer_ownership(&read_state, &final_slices, &final_nslices); + call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_OK); + slice_state_destroy(&read_state); + grpc_tcp_unref(tcp); } GRPC_TIMER_END(GRPC_PTAG_HANDLE_READ, 0); } -static void tcp_handle_read(void *arg /* grpc_tcp */, int success) { +static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { grpc_tcp *tcp = (grpc_tcp *)arg; GPR_ASSERT(!tcp->finished_edge); if (!success) { - gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); - call_read_cb(tcp, 0); - TCP_UNREF(tcp, "read"); + call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); + grpc_tcp_unref(tcp); } else { - tcp_continue_read(tcp); + grpc_tcp_continue_read(tcp); } } -static grpc_endpoint_op_status tcp_read(grpc_endpoint *ep, - gpr_slice_buffer *incoming_buffer, - grpc_iomgr_closure *cb) { +static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, + void *user_data) { grpc_tcp *tcp = (grpc_tcp *)ep; GPR_ASSERT(tcp->read_cb == NULL); tcp->read_cb = cb; - tcp->incoming_buffer = incoming_buffer; - gpr_slice_buffer_reset_and_unref(incoming_buffer); - TCP_REF(tcp, "read"); + tcp->read_user_data = user_data; + gpr_ref(&tcp->refcount); if (tcp->finished_edge) { tcp->finished_edge = 0; grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); } else { - grpc_iomgr_add_delayed_callback(&tcp->read_closure, 1); + tcp->handle_read_closure.cb_arg = tcp; + grpc_iomgr_add_delayed_callback(&tcp->handle_read_closure, 1); } - /* TODO(ctiller): immediate return */ - return GRPC_ENDPOINT_PENDING; } #define MAX_WRITE_IOVEC 16 -static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) { +static grpc_endpoint_write_status grpc_tcp_flush(grpc_tcp *tcp) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; int iov_size; ssize_t sent_length; - ssize_t sending_length; - ssize_t trailing; - ssize_t unwind_slice_idx; - ssize_t unwind_byte_idx; + grpc_tcp_slice_state *state = &tcp->write_state; for (;;) { - sending_length = 0; - unwind_slice_idx = tcp->outgoing_slice_idx; - unwind_byte_idx = tcp->outgoing_byte_idx; - for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count && - iov_size != MAX_WRITE_IOVEC; - iov_size++) { - iov[iov_size].iov_base = - GPR_SLICE_START_PTR( - tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) + - tcp->outgoing_byte_idx; - iov[iov_size].iov_len = - GPR_SLICE_LENGTH( - tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) - - tcp->outgoing_byte_idx; - sending_length += iov[iov_size].iov_len; - tcp->outgoing_slice_idx++; - tcp->outgoing_byte_idx = 0; - } - GPR_ASSERT(iov_size > 0); + iov_size = slice_state_to_iovec(state, iov, MAX_WRITE_IOVEC); msg.msg_name = NULL; msg.msg_namelen = 0; @@ -309,75 +480,70 @@ static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) { if (sent_length < 0) { if (errno == EAGAIN) { - tcp->outgoing_slice_idx = unwind_slice_idx; - tcp->outgoing_byte_idx = unwind_byte_idx; - return GRPC_ENDPOINT_PENDING; + return GRPC_ENDPOINT_WRITE_PENDING; } else { /* TODO(klempner): Log some of these */ - return GRPC_ENDPOINT_ERROR; + slice_state_destroy(state); + return GRPC_ENDPOINT_WRITE_ERROR; } } - GPR_ASSERT(tcp->outgoing_byte_idx == 0); - trailing = sending_length - sent_length; - while (trailing > 0) { - ssize_t slice_length; - - tcp->outgoing_slice_idx--; - slice_length = GPR_SLICE_LENGTH( - tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]); - if (slice_length > trailing) { - tcp->outgoing_byte_idx = slice_length - trailing; - break; - } else { - trailing -= slice_length; - } - } + /* TODO(klempner): Probably better to batch this after we finish flushing */ + slice_state_remove_prefix(state, sent_length); - if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) { - return GRPC_ENDPOINT_DONE; + if (!slice_state_has_available(state)) { + return GRPC_ENDPOINT_WRITE_DONE; } }; } -static void tcp_handle_write(void *arg /* grpc_tcp */, int success) { +static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) { grpc_tcp *tcp = (grpc_tcp *)arg; - grpc_endpoint_op_status status; - grpc_iomgr_closure *cb; + grpc_endpoint_write_status write_status; + grpc_endpoint_cb_status cb_status; + grpc_endpoint_write_cb cb; if (!success) { + slice_state_destroy(&tcp->write_state); cb = tcp->write_cb; tcp->write_cb = NULL; - cb->cb(cb->cb_arg, 0); - TCP_UNREF(tcp, "write"); + cb(tcp->write_user_data, GRPC_ENDPOINT_CB_SHUTDOWN); + grpc_tcp_unref(tcp); return; } GRPC_TIMER_BEGIN(GRPC_PTAG_TCP_CB_WRITE, 0); - status = tcp_flush(tcp); - if (status == GRPC_ENDPOINT_PENDING) { + write_status = grpc_tcp_flush(tcp); + if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure); } else { + slice_state_destroy(&tcp->write_state); + if (write_status == GRPC_ENDPOINT_WRITE_DONE) { + cb_status = GRPC_ENDPOINT_CB_OK; + } else { + cb_status = GRPC_ENDPOINT_CB_ERROR; + } cb = tcp->write_cb; tcp->write_cb = NULL; - cb->cb(cb->cb_arg, status == GRPC_ENDPOINT_DONE); - TCP_UNREF(tcp, "write"); + cb(tcp->write_user_data, cb_status); + grpc_tcp_unref(tcp); } GRPC_TIMER_END(GRPC_PTAG_TCP_CB_WRITE, 0); } -static grpc_endpoint_op_status tcp_write(grpc_endpoint *ep, - gpr_slice_buffer *buf, - grpc_iomgr_closure *cb) { +static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, + gpr_slice *slices, + size_t nslices, + grpc_endpoint_write_cb cb, + void *user_data) { grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_endpoint_op_status status; + grpc_endpoint_write_status status; if (grpc_tcp_trace) { size_t i; - for (i = 0; i < buf->count; i++) { - char *data = - gpr_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < nslices; i++) { + char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data); gpr_free(data); } @@ -385,19 +551,15 @@ static grpc_endpoint_op_status tcp_write(grpc_endpoint *ep, GRPC_TIMER_BEGIN(GRPC_PTAG_TCP_WRITE, 0); GPR_ASSERT(tcp->write_cb == NULL); + slice_state_init(&tcp->write_state, slices, nslices, nslices); - if (buf->length == 0) { - GRPC_TIMER_END(GRPC_PTAG_TCP_WRITE, 0); - return GRPC_ENDPOINT_DONE; - } - tcp->outgoing_buffer = buf; - tcp->outgoing_slice_idx = 0; - tcp->outgoing_byte_idx = 0; - - status = tcp_flush(tcp); - if (status == GRPC_ENDPOINT_PENDING) { - TCP_REF(tcp, "write"); + status = grpc_tcp_flush(tcp); + if (status == GRPC_ENDPOINT_WRITE_PENDING) { + /* TODO(klempner): Consider inlining rather than malloc for small nslices */ + slice_state_realloc(&tcp->write_state, nslices); + gpr_ref(&tcp->refcount); tcp->write_cb = cb; + tcp->write_user_data = user_data; grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure); } @@ -405,25 +567,27 @@ static grpc_endpoint_op_status tcp_write(grpc_endpoint *ep, return status; } -static void tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { +static void grpc_tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_pollset_add_fd(pollset, tcp->em_fd); } -static void tcp_add_to_pollset_set(grpc_endpoint *ep, - grpc_pollset_set *pollset_set) { +static void grpc_tcp_add_to_pollset_set(grpc_endpoint *ep, + grpc_pollset_set *pollset_set) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_pollset_set_add_fd(pollset_set, tcp->em_fd); } -static char *tcp_get_peer(grpc_endpoint *ep) { +static char *grpc_tcp_get_peer(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return gpr_strdup(tcp->peer_string); } static const grpc_endpoint_vtable vtable = { - tcp_read, tcp_write, tcp_add_to_pollset, tcp_add_to_pollset_set, - tcp_shutdown, tcp_destroy, tcp_get_peer}; + grpc_tcp_notify_on_read, grpc_tcp_write, + grpc_tcp_add_to_pollset, grpc_tcp_add_to_pollset_set, + grpc_tcp_shutdown, grpc_tcp_destroy, + grpc_tcp_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, const char *peer_string) { @@ -433,18 +597,21 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, tcp->fd = em_fd->fd; tcp->read_cb = NULL; tcp->write_cb = NULL; - tcp->incoming_buffer = NULL; + tcp->read_user_data = NULL; + tcp->write_user_data = NULL; tcp->slice_size = slice_size; tcp->iov_size = 1; tcp->finished_edge = 1; + slice_state_init(&tcp->write_state, NULL, 0, 0); /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); tcp->em_fd = em_fd; - tcp->read_closure.cb = tcp_handle_read; + tcp->read_closure.cb = grpc_tcp_handle_read; tcp->read_closure.cb_arg = tcp; - tcp->write_closure.cb = tcp_handle_write; + tcp->write_closure.cb = grpc_tcp_handle_write; tcp->write_closure.cb_arg = tcp; + tcp->handle_read_closure.cb = grpc_tcp_handle_read; return &tcp->base; } diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index 58f9160ef9..901793ec43 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -82,11 +82,13 @@ typedef struct grpc_tcp { /* Refcounting how many operations are in progress. */ gpr_refcount refcount; - grpc_iomgr_closure *read_cb; - grpc_iomgr_closure *write_cb; + grpc_endpoint_read_cb read_cb; + void *read_user_data; gpr_slice read_slice; - gpr_slice_buffer *write_slices; - gpr_slice_buffer *read_slices; + + grpc_endpoint_write_cb write_cb; + void *write_user_data; + gpr_slice_buffer write_slices; /* The IO Completion Port runs from another thread. We need some mechanism to protect ourselves when requesting a shutdown. */ @@ -96,55 +98,34 @@ typedef struct grpc_tcp { char *peer_string; } grpc_tcp; -static void tcp_free(grpc_tcp *tcp) { - grpc_winsocket_orphan(tcp->socket); - gpr_mu_destroy(&tcp->mu); - gpr_free(tcp->peer_string); - gpr_free(tcp); -} - -/*#define GRPC_TCP_REFCOUNT_DEBUG*/ -#ifdef GRPC_TCP_REFCOUNT_DEBUG -#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) -#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) -static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, - int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, - reason, tcp->refcount.count, tcp->refcount.count - 1); - if (gpr_unref(&tcp->refcount)) { - tcp_free(tcp); - } -} +static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } -static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, - int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, - reason, tcp->refcount.count, tcp->refcount.count + 1); - gpr_ref(&tcp->refcount); -} -#else -#define TCP_UNREF(tcp, reason) tcp_unref((tcp)) -#define TCP_REF(tcp, reason) tcp_ref((tcp)) static void tcp_unref(grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { - tcp_free(tcp); + gpr_slice_buffer_destroy(&tcp->write_slices); + grpc_winsocket_orphan(tcp->socket); + gpr_mu_destroy(&tcp->mu); + gpr_free(tcp->peer_string); + gpr_free(tcp); } } -static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } -#endif - /* Asynchronous callback from the IOCP, or the background thread. */ -static int on_read(grpc_tcp *tcp, int from_iocp) { +static void on_read(void *tcpp, int from_iocp) { + grpc_tcp *tcp = (grpc_tcp *)tcpp; grpc_winsocket *socket = tcp->socket; gpr_slice sub; gpr_slice *slice = NULL; size_t nslices = 0; - int success; + grpc_endpoint_cb_status status; + grpc_endpoint_read_cb cb; grpc_winsocket_callback_info *info = &socket->read_info; + void *opaque = tcp->read_user_data; int do_abort = 0; gpr_mu_lock(&tcp->mu); + cb = tcp->read_cb; + tcp->read_cb = NULL; if (!from_iocp || tcp->shutting_down) { /* If we are here with from_iocp set to true, it means we got raced to shutting down the endpoint. No actual abort callback will happen @@ -158,7 +139,9 @@ static int on_read(grpc_tcp *tcp, int from_iocp) { tcp->socket->read_info.outstanding = 0; gpr_slice_unref(tcp->read_slice); } - return 0; + tcp_unref(tcp); + if (cb) cb(opaque, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); + return; } GPR_ASSERT(tcp->socket->read_info.outstanding); @@ -169,38 +152,28 @@ static int on_read(grpc_tcp *tcp, int from_iocp) { gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); gpr_free(utf8_message); } - success = 0; gpr_slice_unref(tcp->read_slice); + status = GRPC_ENDPOINT_CB_ERROR; } else { if (info->bytes_transfered != 0) { sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); - gpr_slice_buffer_add(tcp->read_slices, sub); - success = 1; + status = GRPC_ENDPOINT_CB_OK; + slice = ⊂ + nslices = 1; } else { gpr_slice_unref(tcp->read_slice); - success = 0; + status = GRPC_ENDPOINT_CB_EOF; } } tcp->socket->read_info.outstanding = 0; - return success; -} - -static void on_read_cb(void *tcpp, int from_iocp) { - grpc_tcp *tcp = tcpp; - grpc_iomgr_closure *cb = tcp->read_cb; - int success = on_read(tcp, from_iocp); - tcp->read_cb = NULL; - TCP_UNREF(tcp, "read"); - if (cb) { - cb->cb(cb->cb_arg, success); - } + tcp_unref(tcp); + cb(opaque, slice, nslices, status); } -static grpc_endpoint_op_status win_read(grpc_endpoint *ep, - gpr_slice_buffer *read_slices, - grpc_iomgr_closure *cb) { +static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, + void *arg) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->read_info; @@ -211,15 +184,13 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, GPR_ASSERT(!tcp->socket->read_info.outstanding); if (tcp->shutting_down) { - return GRPC_ENDPOINT_ERROR; + cb(arg, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); + return; } - - TCP_REF(tcp, "read"); - + tcp_ref(tcp); tcp->socket->read_info.outstanding = 1; tcp->read_cb = cb; - tcp->read_slices = read_slices; - gpr_slice_buffer_reset_and_unref(read_slices); + tcp->read_user_data = arg; tcp->read_slice = gpr_slice_malloc(8192); @@ -233,11 +204,10 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, /* Did we get data immediately ? Yay. */ if (info->wsa_error != WSAEWOULDBLOCK) { - int ok; info->bytes_transfered = bytes_read; - ok = on_read(tcp, 1); - TCP_UNREF(tcp, "read"); - return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; + /* This might heavily recurse. */ + on_read(tcp, 1); + return; } /* Otherwise, let's retry, by queuing a read. */ @@ -248,15 +218,13 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { - int ok; info->wsa_error = wsa_error; - ok = on_read(tcp, 1); - return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; + on_read(tcp, 1); + return; } } - grpc_socket_notify_on_read(tcp->socket, on_read_cb, tcp); - return GRPC_ENDPOINT_PENDING; + grpc_socket_notify_on_read(tcp->socket, on_read, tcp); } /* Asynchronous callback from the IOCP, or the background thread. */ @@ -264,8 +232,9 @@ static void on_write(void *tcpp, int from_iocp) { grpc_tcp *tcp = (grpc_tcp *)tcpp; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->write_info; - grpc_iomgr_closure *cb; - int success; + grpc_endpoint_cb_status status = GRPC_ENDPOINT_CB_OK; + grpc_endpoint_write_cb cb; + void *opaque = tcp->write_user_data; int do_abort = 0; gpr_mu_lock(&tcp->mu); @@ -282,11 +251,10 @@ static void on_write(void *tcpp, int from_iocp) { if (do_abort) { if (from_iocp) { tcp->socket->write_info.outstanding = 0; + gpr_slice_buffer_reset_and_unref(&tcp->write_slices); } - TCP_UNREF(tcp, "write"); - if (cb) { - cb->cb(cb->cb_arg, 0); - } + tcp_unref(tcp); + if (cb) cb(opaque, GRPC_ENDPOINT_CB_SHUTDOWN); return; } @@ -298,22 +266,23 @@ static void on_write(void *tcpp, int from_iocp) { gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); gpr_free(utf8_message); } - success = 0; + status = GRPC_ENDPOINT_CB_ERROR; } else { - GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length); - success = 1; + GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length); } + gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; - TCP_UNREF(tcp, "write"); - cb->cb(cb->cb_arg, success); + tcp_unref(tcp); + cb(opaque, status); } /* Initiates a write. */ -static grpc_endpoint_op_status win_write(grpc_endpoint *ep, - gpr_slice_buffer *slices, - grpc_iomgr_closure *cb) { +static grpc_endpoint_write_status win_write(grpc_endpoint *ep, + gpr_slice *slices, size_t nslices, + grpc_endpoint_write_cb cb, + void *arg) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *socket = tcp->socket; grpc_winsocket_callback_info *info = &socket->write_info; @@ -326,26 +295,28 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, GPR_ASSERT(!tcp->socket->write_info.outstanding); if (tcp->shutting_down) { - return GRPC_ENDPOINT_ERROR; + return GRPC_ENDPOINT_WRITE_ERROR; } - TCP_REF(tcp, "write"); + tcp_ref(tcp); tcp->socket->write_info.outstanding = 1; tcp->write_cb = cb; - tcp->write_slices = slices; + tcp->write_user_data = arg; + + gpr_slice_buffer_addn(&tcp->write_slices, slices, nslices); - if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) { - buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count); + if (tcp->write_slices.count > GPR_ARRAY_SIZE(local_buffers)) { + buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices.count); allocated = buffers; } - for (i = 0; i < tcp->write_slices->count; i++) { - buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]); - buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]); + for (i = 0; i < tcp->write_slices.count; i++) { + buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices.slices[i]); + buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices.slices[i]); } /* First, let's try a synchronous, non-blocking write. */ - status = WSASend(socket->socket, buffers, tcp->write_slices->count, + status = WSASend(socket->socket, buffers, tcp->write_slices.count, &bytes_sent, 0, NULL, NULL); info->wsa_error = status == 0 ? 0 : WSAGetLastError(); @@ -353,10 +324,10 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, connection that has its send queue filled up. But if we don't, then we can avoid doing an async write operation at all. */ if (info->wsa_error != WSAEWOULDBLOCK) { - grpc_endpoint_op_status ret = GRPC_ENDPOINT_ERROR; + grpc_endpoint_write_status ret = GRPC_ENDPOINT_WRITE_ERROR; if (status == 0) { - ret = GRPC_ENDPOINT_DONE; - GPR_ASSERT(bytes_sent == tcp->write_slices->length); + ret = GRPC_ENDPOINT_WRITE_DONE; + GPR_ASSERT(bytes_sent == tcp->write_slices.length); } else { if (socket->read_info.wsa_error != WSAECONNRESET) { char *utf8_message = gpr_format_message(info->wsa_error); @@ -365,31 +336,33 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, } } if (allocated) gpr_free(allocated); + gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; - TCP_UNREF(tcp, "write"); + tcp_unref(tcp); return ret; } /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same operation, this time asynchronously. */ memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED)); - status = WSASend(socket->socket, buffers, tcp->write_slices->count, + status = WSASend(socket->socket, buffers, tcp->write_slices.count, &bytes_sent, 0, &socket->write_info.overlapped, NULL); if (allocated) gpr_free(allocated); if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { + gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; - TCP_UNREF(tcp, "write"); - return GRPC_ENDPOINT_ERROR; + tcp_unref(tcp); + return GRPC_ENDPOINT_WRITE_ERROR; } } /* As all is now setup, we can now ask for the IOCP notification. It may trigger the callback immediately however, but no matter. */ grpc_socket_notify_on_write(socket, on_write, tcp); - return GRPC_ENDPOINT_PENDING; + return GRPC_ENDPOINT_WRITE_PENDING; } static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *ps) { @@ -414,17 +387,19 @@ static void win_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pss) { concurrent access of the data structure in that regard. */ static void win_shutdown(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; + int extra_refs = 0; gpr_mu_lock(&tcp->mu); /* At that point, what may happen is that we're already inside the IOCP callback. See the comments in on_read and on_write. */ tcp->shutting_down = 1; - grpc_winsocket_shutdown(tcp->socket); + extra_refs = grpc_winsocket_shutdown(tcp->socket); + while (extra_refs--) tcp_ref(tcp); gpr_mu_unlock(&tcp->mu); } static void win_destroy(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; - TCP_UNREF(tcp, "destroy"); + tcp_unref(tcp); } static char *win_get_peer(grpc_endpoint *ep) { @@ -433,8 +408,8 @@ static char *win_get_peer(grpc_endpoint *ep) { } static grpc_endpoint_vtable vtable = { - win_read, win_write, win_add_to_pollset, win_add_to_pollset_set, - win_shutdown, win_destroy, win_get_peer}; + win_notify_on_read, win_write, win_add_to_pollset, win_add_to_pollset_set, + win_shutdown, win_destroy, win_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); @@ -442,6 +417,7 @@ grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { tcp->base.vtable = &vtable; tcp->socket = socket; gpr_mu_init(&tcp->mu); + gpr_slice_buffer_init(&tcp->write_slices); gpr_ref_init(&tcp->refcount, 1); tcp->peer_string = gpr_strdup(peer_string); return &tcp->base; diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c index b696e384fc..81b3e33cb2 100644 --- a/src/core/security/secure_endpoint.c +++ b/src/core/security/secure_endpoint.c @@ -49,15 +49,15 @@ typedef struct { struct tsi_frame_protector *protector; gpr_mu protector_mu; /* saved upper level callbacks and user_data. */ - grpc_iomgr_closure *read_cb; - grpc_iomgr_closure *write_cb; - grpc_iomgr_closure on_read; - gpr_slice_buffer *read_buffer; - gpr_slice_buffer source_buffer; + grpc_endpoint_read_cb read_cb; + void *read_user_data; + grpc_endpoint_write_cb write_cb; + void *write_user_data; /* saved handshaker leftover data to unprotect. */ gpr_slice_buffer leftover_bytes; /* buffers for read and write */ gpr_slice read_staging_buffer; + gpr_slice_buffer input_buffer; gpr_slice write_staging_buffer; gpr_slice_buffer output_buffer; @@ -67,91 +67,62 @@ typedef struct { int grpc_trace_secure_endpoint = 0; +static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } + static void destroy(secure_endpoint *secure_ep) { secure_endpoint *ep = secure_ep; grpc_endpoint_destroy(ep->wrapped_ep); tsi_frame_protector_destroy(ep->protector); gpr_slice_buffer_destroy(&ep->leftover_bytes); gpr_slice_unref(ep->read_staging_buffer); + gpr_slice_buffer_destroy(&ep->input_buffer); gpr_slice_unref(ep->write_staging_buffer); gpr_slice_buffer_destroy(&ep->output_buffer); - gpr_slice_buffer_destroy(&ep->source_buffer); gpr_mu_destroy(&ep->protector_mu); gpr_free(ep); } -/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/ -#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG -#define SECURE_ENDPOINT_UNREF(ep, reason) \ - secure_endpoint_unref((ep), (reason), __FILE__, __LINE__) -#define SECURE_ENDPOINT_REF(ep, reason) \ - secure_endpoint_ref((ep), (reason), __FILE__, __LINE__) -static void secure_endpoint_unref(secure_endpoint *ep, const char *reason, - const char *file, int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d", - ep, reason, ep->ref.count, ep->ref.count - 1); - if (gpr_unref(&ep->ref)) { - destroy(ep); - } -} - -static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, - const char *file, int line) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d", - ep, reason, ep->ref.count, ep->ref.count + 1); - gpr_ref(&ep->ref); -} -#else -#define SECURE_ENDPOINT_UNREF(ep, reason) secure_endpoint_unref((ep)) -#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep)) static void secure_endpoint_unref(secure_endpoint *ep) { if (gpr_unref(&ep->ref)) { destroy(ep); } } -static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } -#endif - static void flush_read_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, gpr_uint8 **end) { - gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer); + gpr_slice_buffer_add(&ep->input_buffer, ep->read_staging_buffer); ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); } -static void call_read_cb(secure_endpoint *ep, int success) { +static void call_read_cb(secure_endpoint *ep, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error) { if (grpc_trace_secure_endpoint) { size_t i; - for (i = 0; i < ep->read_buffer->count; i++) { - char *data = gpr_dump_slice(ep->read_buffer->slices[i], - GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < nslices; i++) { + char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p: %s", ep, data); gpr_free(data); } } - ep->read_buffer = NULL; - ep->read_cb->cb(ep->read_cb->cb_arg, success); - SECURE_ENDPOINT_UNREF(ep, "read"); + ep->read_cb(ep->read_user_data, slices, nslices, error); + secure_endpoint_unref(ep); } -static int on_read(void *user_data, int success) { +static void on_read(void *user_data, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error) { unsigned i; gpr_uint8 keep_looping = 0; + size_t input_buffer_count = 0; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)user_data; gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); gpr_uint8 *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); - if (!success) { - gpr_slice_buffer_reset_and_unref(ep->read_buffer); - return 0; - } - /* TODO(yangg) check error, maybe bail out early */ - for (i = 0; i < ep->source_buffer.count; i++) { - gpr_slice encrypted = ep->source_buffer.slices[i]; + for (i = 0; i < nslices; i++) { + gpr_slice encrypted = slices[i]; gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(encrypted); size_t message_size = GPR_SLICE_LENGTH(encrypted); @@ -190,7 +161,7 @@ static int on_read(void *user_data, int success) { if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) { gpr_slice_buffer_add( - ep->read_buffer, + &ep->input_buffer, gpr_slice_split_head( &ep->read_staging_buffer, (size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer)))); @@ -198,53 +169,38 @@ static int on_read(void *user_data, int success) { /* TODO(yangg) experiment with moving this block after read_cb to see if it helps latency */ - gpr_slice_buffer_reset_and_unref(&ep->source_buffer); + for (i = 0; i < nslices; i++) { + gpr_slice_unref(slices[i]); + } if (result != TSI_OK) { - gpr_slice_buffer_reset_and_unref(ep->read_buffer); - return 0; + gpr_slice_buffer_reset_and_unref(&ep->input_buffer); + call_read_cb(ep, NULL, 0, GRPC_ENDPOINT_CB_ERROR); + return; } - - return 1; -} - -static void on_read_cb(void *user_data, int success) { - call_read_cb(user_data, on_read(user_data, success)); + /* The upper level will unref the slices. */ + input_buffer_count = ep->input_buffer.count; + ep->input_buffer.count = 0; + call_read_cb(ep, ep->input_buffer.slices, input_buffer_count, error); } -static grpc_endpoint_op_status endpoint_read(grpc_endpoint *secure_ep, - gpr_slice_buffer *slices, - grpc_iomgr_closure *cb) { +static void endpoint_notify_on_read(grpc_endpoint *secure_ep, + grpc_endpoint_read_cb cb, void *user_data) { secure_endpoint *ep = (secure_endpoint *)secure_ep; - int immediate_read_success = -1; ep->read_cb = cb; - ep->read_buffer = slices; - gpr_slice_buffer_reset_and_unref(ep->read_buffer); + ep->read_user_data = user_data; - if (ep->leftover_bytes.count) { - gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer); - GPR_ASSERT(ep->leftover_bytes.count == 0); - return on_read(ep, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; - } + secure_endpoint_ref(ep); - SECURE_ENDPOINT_REF(ep, "read"); - - switch ( - grpc_endpoint_read(ep->wrapped_ep, &ep->source_buffer, &ep->on_read)) { - case GRPC_ENDPOINT_DONE: - immediate_read_success = on_read(ep, 1); - break; - case GRPC_ENDPOINT_PENDING: - return GRPC_ENDPOINT_PENDING; - case GRPC_ENDPOINT_ERROR: - immediate_read_success = on_read(ep, 0); - break; + if (ep->leftover_bytes.count) { + size_t leftover_nslices = ep->leftover_bytes.count; + ep->leftover_bytes.count = 0; + on_read(ep, ep->leftover_bytes.slices, leftover_nslices, + GRPC_ENDPOINT_CB_OK); + return; } - GPR_ASSERT(immediate_read_success != -1); - SECURE_ENDPOINT_UNREF(ep, "read"); - - return immediate_read_success ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; + grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep); } static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, @@ -255,28 +211,36 @@ static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); } -static grpc_endpoint_op_status endpoint_write(grpc_endpoint *secure_ep, - gpr_slice_buffer *slices, - grpc_iomgr_closure *cb) { +static void on_write(void *data, grpc_endpoint_cb_status error) { + secure_endpoint *ep = data; + ep->write_cb(ep->write_user_data, error); + secure_endpoint_unref(ep); +} + +static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, + gpr_slice *slices, + size_t nslices, + grpc_endpoint_write_cb cb, + void *user_data) { unsigned i; + size_t output_buffer_count = 0; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)secure_ep; gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer); gpr_uint8 *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); - - gpr_slice_buffer_reset_and_unref(&ep->output_buffer); + grpc_endpoint_write_status status; + GPR_ASSERT(ep->output_buffer.count == 0); if (grpc_trace_secure_endpoint) { - for (i = 0; i < slices->count; i++) { - char *data = - gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < nslices; i++) { + char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data); gpr_free(data); } } - for (i = 0; i < slices->count; i++) { - gpr_slice plain = slices->slices[i]; + for (i = 0; i < nslices; i++) { + gpr_slice plain = slices[i]; gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(plain); size_t message_size = GPR_SLICE_LENGTH(plain); while (message_size > 0) { @@ -326,13 +290,29 @@ static grpc_endpoint_op_status endpoint_write(grpc_endpoint *secure_ep, } } + for (i = 0; i < nslices; i++) { + gpr_slice_unref(slices[i]); + } + if (result != TSI_OK) { /* TODO(yangg) do different things according to the error type? */ gpr_slice_buffer_reset_and_unref(&ep->output_buffer); - return GRPC_ENDPOINT_ERROR; + return GRPC_ENDPOINT_WRITE_ERROR; } - return grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb); + /* clear output_buffer and let the lower level handle its slices. */ + output_buffer_count = ep->output_buffer.count; + ep->output_buffer.count = 0; + ep->write_cb = cb; + ep->write_user_data = user_data; + /* Need to keep the endpoint alive across a transport */ + secure_endpoint_ref(ep); + status = grpc_endpoint_write(ep->wrapped_ep, ep->output_buffer.slices, + output_buffer_count, on_write, ep); + if (status != GRPC_ENDPOINT_WRITE_PENDING) { + secure_endpoint_unref(ep); + } + return status; } static void endpoint_shutdown(grpc_endpoint *secure_ep) { @@ -340,9 +320,9 @@ static void endpoint_shutdown(grpc_endpoint *secure_ep) { grpc_endpoint_shutdown(ep->wrapped_ep); } -static void endpoint_destroy(grpc_endpoint *secure_ep) { +static void endpoint_unref(grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; - SECURE_ENDPOINT_UNREF(ep, "destroy"); + secure_endpoint_unref(ep); } static void endpoint_add_to_pollset(grpc_endpoint *secure_ep, @@ -363,9 +343,9 @@ static char *endpoint_get_peer(grpc_endpoint *secure_ep) { } static const grpc_endpoint_vtable vtable = { - endpoint_read, endpoint_write, + endpoint_notify_on_read, endpoint_write, endpoint_add_to_pollset, endpoint_add_to_pollset_set, - endpoint_shutdown, endpoint_destroy, + endpoint_shutdown, endpoint_unref, endpoint_get_peer}; grpc_endpoint *grpc_secure_endpoint_create( @@ -383,10 +363,8 @@ grpc_endpoint *grpc_secure_endpoint_create( } ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); + gpr_slice_buffer_init(&ep->input_buffer); gpr_slice_buffer_init(&ep->output_buffer); - gpr_slice_buffer_init(&ep->source_buffer); - ep->read_buffer = NULL; - grpc_iomgr_closure_init(&ep->on_read, on_read_cb, ep); gpr_mu_init(&ep->protector_mu); gpr_ref_init(&ep->ref, 1); return &ep->base; diff --git a/src/core/security/secure_transport_setup.c b/src/core/security/secure_transport_setup.c index bf0079577e..0c3572b53c 100644 --- a/src/core/security/secure_transport_setup.c +++ b/src/core/security/secure_transport_setup.c @@ -50,17 +50,16 @@ typedef struct { grpc_endpoint *wrapped_endpoint; grpc_endpoint *secure_endpoint; gpr_slice_buffer left_overs; - gpr_slice_buffer incoming; - gpr_slice_buffer outgoing; grpc_secure_transport_setup_done_cb cb; void *user_data; - grpc_iomgr_closure on_handshake_data_sent_to_peer; - grpc_iomgr_closure on_handshake_data_received_from_peer; } grpc_secure_transport_setup; -static void on_handshake_data_received_from_peer(void *setup, int success); +static void on_handshake_data_received_from_peer(void *setup, gpr_slice *slices, + size_t nslices, + grpc_endpoint_cb_status error); -static void on_handshake_data_sent_to_peer(void *setup, int success); +static void on_handshake_data_sent_to_peer(void *setup, + grpc_endpoint_cb_status error); static void secure_transport_setup_done(grpc_secure_transport_setup *s, int is_success) { @@ -79,8 +78,6 @@ static void secure_transport_setup_done(grpc_secure_transport_setup *s, if (s->handshaker != NULL) tsi_handshaker_destroy(s->handshaker); if (s->handshake_buffer != NULL) gpr_free(s->handshake_buffer); gpr_slice_buffer_destroy(&s->left_overs); - gpr_slice_buffer_destroy(&s->outgoing); - gpr_slice_buffer_destroy(&s->incoming); GRPC_SECURITY_CONNECTOR_UNREF(s->connector, "secure_transport_setup"); gpr_free(s); } @@ -105,8 +102,6 @@ static void on_peer_checked(void *user_data, grpc_security_status status) { s->secure_endpoint = grpc_secure_endpoint_create(protector, s->wrapped_endpoint, s->left_overs.slices, s->left_overs.count); - s->left_overs.count = 0; - s->left_overs.length = 0; secure_transport_setup_done(s, 1); return; } @@ -137,6 +132,7 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) { size_t offset = 0; tsi_result result = TSI_OK; gpr_slice to_send; + grpc_endpoint_write_status write_status; do { size_t to_send_size = s->handshake_buffer_size - offset; @@ -159,25 +155,28 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) { to_send = gpr_slice_from_copied_buffer((const char *)s->handshake_buffer, offset); - gpr_slice_buffer_reset_and_unref(&s->outgoing); - gpr_slice_buffer_add(&s->outgoing, to_send); /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ - switch (grpc_endpoint_write(s->wrapped_endpoint, &s->outgoing, - &s->on_handshake_data_sent_to_peer)) { - case GRPC_ENDPOINT_ERROR: - gpr_log(GPR_ERROR, "Could not send handshake data to peer."); - secure_transport_setup_done(s, 0); - break; - case GRPC_ENDPOINT_DONE: - on_handshake_data_sent_to_peer(s, 1); - break; - case GRPC_ENDPOINT_PENDING: - break; + write_status = grpc_endpoint_write(s->wrapped_endpoint, &to_send, 1, + on_handshake_data_sent_to_peer, s); + if (write_status == GRPC_ENDPOINT_WRITE_ERROR) { + gpr_log(GPR_ERROR, "Could not send handshake data to peer."); + secure_transport_setup_done(s, 0); + } else if (write_status == GRPC_ENDPOINT_WRITE_DONE) { + on_handshake_data_sent_to_peer(s, GRPC_ENDPOINT_CB_OK); + } +} + +static void cleanup_slices(gpr_slice *slices, size_t num_slices) { + size_t i; + for (i = 0; i < num_slices; i++) { + gpr_slice_unref(slices[i]); } } -static void on_handshake_data_received_from_peer(void *setup, int success) { +static void on_handshake_data_received_from_peer( + void *setup, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error) { grpc_secure_transport_setup *s = setup; size_t consumed_slice_size = 0; tsi_result result = TSI_OK; @@ -185,37 +184,32 @@ static void on_handshake_data_received_from_peer(void *setup, int success) { size_t num_left_overs; int has_left_overs_in_current_slice = 0; - if (!success) { + if (error != GRPC_ENDPOINT_CB_OK) { gpr_log(GPR_ERROR, "Read failed."); + cleanup_slices(slices, nslices); secure_transport_setup_done(s, 0); return; } - for (i = 0; i < s->incoming.count; i++) { - consumed_slice_size = GPR_SLICE_LENGTH(s->incoming.slices[i]); + for (i = 0; i < nslices; i++) { + consumed_slice_size = GPR_SLICE_LENGTH(slices[i]); result = tsi_handshaker_process_bytes_from_peer( - s->handshaker, GPR_SLICE_START_PTR(s->incoming.slices[i]), - &consumed_slice_size); + s->handshaker, GPR_SLICE_START_PTR(slices[i]), &consumed_slice_size); if (!tsi_handshaker_is_in_progress(s->handshaker)) break; } if (tsi_handshaker_is_in_progress(s->handshaker)) { /* We may need more data. */ if (result == TSI_INCOMPLETE_DATA) { - switch (grpc_endpoint_read(s->wrapped_endpoint, &s->incoming, - &s->on_handshake_data_received_from_peer)) { - case GRPC_ENDPOINT_DONE: - on_handshake_data_received_from_peer(s, 1); - break; - case GRPC_ENDPOINT_ERROR: - on_handshake_data_received_from_peer(s, 0); - break; - case GRPC_ENDPOINT_PENDING: - break; - } + /* TODO(klempner,jboeuf): This should probably use the client setup + deadline */ + grpc_endpoint_notify_on_read(s->wrapped_endpoint, + on_handshake_data_received_from_peer, setup); + cleanup_slices(slices, nslices); return; } else { send_handshake_bytes_to_peer(s); + cleanup_slices(slices, nslices); return; } } @@ -223,40 +217,42 @@ static void on_handshake_data_received_from_peer(void *setup, int success) { if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshake failed with error %s", tsi_result_to_string(result)); + cleanup_slices(slices, nslices); secure_transport_setup_done(s, 0); return; } /* Handshake is done and successful this point. */ has_left_overs_in_current_slice = - (consumed_slice_size < GPR_SLICE_LENGTH(s->incoming.slices[i])); - num_left_overs = - (has_left_overs_in_current_slice ? 1 : 0) + s->incoming.count - i - 1; + (consumed_slice_size < GPR_SLICE_LENGTH(slices[i])); + num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) + nslices - i - 1; if (num_left_overs == 0) { + cleanup_slices(slices, nslices); check_peer(s); return; } + cleanup_slices(slices, nslices - num_left_overs); + /* Put the leftovers in our buffer (ownership transfered). */ if (has_left_overs_in_current_slice) { - gpr_slice_buffer_add( - &s->left_overs, - gpr_slice_split_tail(&s->incoming.slices[i], consumed_slice_size)); - gpr_slice_unref( - s->incoming.slices[i]); /* split_tail above increments refcount. */ + gpr_slice_buffer_add(&s->left_overs, + gpr_slice_split_tail(&slices[i], consumed_slice_size)); + gpr_slice_unref(slices[i]); /* split_tail above increments refcount. */ } gpr_slice_buffer_addn( - &s->left_overs, &s->incoming.slices[i + 1], + &s->left_overs, &slices[i + 1], num_left_overs - (size_t)has_left_overs_in_current_slice); check_peer(s); } /* If setup is NULL, the setup is done. */ -static void on_handshake_data_sent_to_peer(void *setup, int success) { +static void on_handshake_data_sent_to_peer(void *setup, + grpc_endpoint_cb_status error) { grpc_secure_transport_setup *s = setup; /* Make sure that write is OK. */ - if (!success) { - gpr_log(GPR_ERROR, "Write failed."); + if (error != GRPC_ENDPOINT_CB_OK) { + gpr_log(GPR_ERROR, "Write failed with error %d.", error); if (setup != NULL) secure_transport_setup_done(s, 0); return; } @@ -265,17 +261,8 @@ static void on_handshake_data_sent_to_peer(void *setup, int success) { if (tsi_handshaker_is_in_progress(s->handshaker)) { /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ - switch (grpc_endpoint_read(s->wrapped_endpoint, &s->incoming, - &s->on_handshake_data_received_from_peer)) { - case GRPC_ENDPOINT_ERROR: - on_handshake_data_received_from_peer(s, 0); - break; - case GRPC_ENDPOINT_PENDING: - break; - case GRPC_ENDPOINT_DONE: - on_handshake_data_received_from_peer(s, 1); - break; - } + grpc_endpoint_notify_on_read(s->wrapped_endpoint, + on_handshake_data_received_from_peer, setup); } else { check_peer(s); } @@ -301,12 +288,6 @@ void grpc_setup_secure_transport(grpc_security_connector *connector, s->wrapped_endpoint = nonsecure_endpoint; s->user_data = user_data; s->cb = cb; - grpc_iomgr_closure_init(&s->on_handshake_data_sent_to_peer, - on_handshake_data_sent_to_peer, s); - grpc_iomgr_closure_init(&s->on_handshake_data_received_from_peer, - on_handshake_data_received_from_peer, s); gpr_slice_buffer_init(&s->left_overs); - gpr_slice_buffer_init(&s->outgoing); - gpr_slice_buffer_init(&s->incoming); send_handshake_bytes_to_peer(s); } diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c index 6482ef9c9f..987d5cb9b5 100644 --- a/src/core/support/slice_buffer.c +++ b/src/core/support/slice_buffer.c @@ -207,25 +207,3 @@ void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst) { src->count = 0; src->length = 0; } - -void gpr_slice_buffer_trim_end(gpr_slice_buffer *sb, size_t n) { - GPR_ASSERT(n <= sb->length); - sb->length -= n; - for (;;) { - size_t idx = sb->count - 1; - gpr_slice slice = sb->slices[idx]; - size_t slice_len = GPR_SLICE_LENGTH(slice); - if (slice_len > n) { - sb->slices[idx] = gpr_slice_sub_no_ref(slice, 0, slice_len - n); - return; - } else if (slice_len == n) { - gpr_slice_unref(slice); - sb->count = idx; - return; - } else { - gpr_slice_unref(slice); - n -= slice_len; - sb->count = idx; - } - } -} diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h index a1b773b1ca..42cf0ecd5b 100644 --- a/src/core/transport/chttp2/internal.h +++ b/src/core/transport/chttp2/internal.h @@ -214,8 +214,6 @@ typedef struct { grpc_chttp2_hpack_compressor hpack_compressor; /** is this a client? */ gpr_uint8 is_client; - /** callback for when writing is done */ - grpc_iomgr_closure done_cb; } grpc_chttp2_transport_writing; struct grpc_chttp2_transport_parsing { @@ -331,11 +329,8 @@ struct grpc_chttp2_transport { /** closure to execute writing */ grpc_iomgr_closure writing_action; - /** closure to finish reading from the endpoint */ - grpc_iomgr_closure recv_data; - - /** incoming read bytes */ - gpr_slice_buffer read_buffer; + /** closure to start reading from the endpoint */ + grpc_iomgr_closure reading_action; /** address to place a newly accepted stream - set and unset by grpc_chttp2_parsing_accept_stream; used by init_stream to @@ -468,7 +463,8 @@ int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global, grpc_chttp2_transport_writing *writing); void grpc_chttp2_perform_writes( grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint); -void grpc_chttp2_terminate_writing(void *transport_writing, int success); +void grpc_chttp2_terminate_writing( + grpc_chttp2_transport_writing *transport_writing, int success); void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global, grpc_chttp2_transport_writing *writing); diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c index 2c8c48f47b..123061b3fc 100644 --- a/src/core/transport/chttp2/writing.c +++ b/src/core/transport/chttp2/writing.c @@ -37,6 +37,7 @@ #include static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing); +static void finish_write_cb(void *tw, grpc_endpoint_cb_status write_status); int grpc_chttp2_unlocking_check_writes( grpc_chttp2_transport_global *transport_global, @@ -164,15 +165,16 @@ void grpc_chttp2_perform_writes( GPR_ASSERT(transport_writing->outbuf.count > 0); GPR_ASSERT(endpoint); - switch (grpc_endpoint_write(endpoint, &transport_writing->outbuf, - &transport_writing->done_cb)) { - case GRPC_ENDPOINT_DONE: + switch (grpc_endpoint_write(endpoint, transport_writing->outbuf.slices, + transport_writing->outbuf.count, finish_write_cb, + transport_writing)) { + case GRPC_ENDPOINT_WRITE_DONE: grpc_chttp2_terminate_writing(transport_writing, 1); break; - case GRPC_ENDPOINT_ERROR: + case GRPC_ENDPOINT_WRITE_ERROR: grpc_chttp2_terminate_writing(transport_writing, 0); break; - case GRPC_ENDPOINT_PENDING: + case GRPC_ENDPOINT_WRITE_PENDING: break; } } @@ -207,6 +209,12 @@ static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) { } } +static void finish_write_cb(void *tw, grpc_endpoint_cb_status write_status) { + grpc_chttp2_transport_writing *transport_writing = tw; + grpc_chttp2_terminate_writing(transport_writing, + write_status == GRPC_ENDPOINT_CB_OK); +} + void grpc_chttp2_cleanup_writing( grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_writing *transport_writing) { @@ -235,5 +243,6 @@ void grpc_chttp2_cleanup_writing( grpc_chttp2_list_add_read_write_state_changed(transport_global, stream_global); } - gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf); + transport_writing->outbuf.count = 0; + transport_writing->outbuf.length = 0; } diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 8caa10c938..1bbd210e46 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -84,13 +84,15 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t); /* forward declarations of various callbacks that we'll build closures around */ static void writing_action(void *t, int iomgr_success_ignored); +static void reading_action(void *t, int iomgr_success_ignored); /** Set a transport level setting, and push it to our peer */ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, gpr_uint32 value); /** Endpoint callback to process incoming data */ -static void recv_data(void *tp, int success); +static void recv_data(void *tp, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error); /** Start disconnection chain */ static void drop_connection(grpc_chttp2_transport *t); @@ -141,7 +143,6 @@ static void destruct_transport(grpc_chttp2_transport *t) { grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor); gpr_slice_buffer_destroy(&t->parsing.qbuf); - gpr_slice_buffer_destroy(&t->read_buffer); grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser); grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser); @@ -248,16 +249,12 @@ static void init_transport(grpc_chttp2_transport *t, gpr_slice_buffer_init(&t->writing.outbuf); grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor, mdctx); grpc_iomgr_closure_init(&t->writing_action, writing_action, t); + grpc_iomgr_closure_init(&t->reading_action, reading_action, t); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser, t->metadata_context); - grpc_iomgr_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, - &t->writing); - grpc_iomgr_closure_init(&t->recv_data, recv_data, t); - gpr_slice_buffer_init(&t->read_buffer); - if (is_client) { gpr_slice_buffer_add( &t->global.qbuf, @@ -505,8 +502,8 @@ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, } } -void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { - grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr; +void grpc_chttp2_terminate_writing( + grpc_chttp2_transport_writing *transport_writing, int success) { grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); lock(t); @@ -1063,76 +1060,74 @@ static void read_error_locked(grpc_chttp2_transport *t) { } /* tcp read callback */ -static int recv_data_loop(grpc_chttp2_transport *t, int *success) { +static void recv_data(void *tp, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error) { + grpc_chttp2_transport *t = tp; size_t i; - int keep_reading = 0; + int unref = 0; - lock(t); - i = 0; - GPR_ASSERT(!t->parsing_active); - if (!t->closed) { - t->parsing_active = 1; - /* merge stream lists */ - grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); - grpc_chttp2_prepare_to_read(&t->global, &t->parsing); - gpr_mu_unlock(&t->mu); - for (; i < t->read_buffer.count && - grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]); - i++) - ; - gpr_mu_lock(&t->mu); - if (i != t->read_buffer.count) { + switch (error) { + case GRPC_ENDPOINT_CB_SHUTDOWN: + case GRPC_ENDPOINT_CB_EOF: + case GRPC_ENDPOINT_CB_ERROR: + lock(t); drop_connection(t); - } - /* merge stream lists */ - grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); - t->global.concurrent_stream_count = - grpc_chttp2_stream_map_size(&t->parsing_stream_map); - if (t->parsing.initial_window_update != 0) { - grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, - update_global_window, t); - t->parsing.initial_window_update = 0; - } - /* handle higher level things */ - grpc_chttp2_publish_reads(&t->global, &t->parsing); - t->parsing_active = 0; - } - if (!*success || i != t->read_buffer.count) { - drop_connection(t); - read_error_locked(t); - } else { - keep_reading = 1; + read_error_locked(t); + unlock(t); + unref = 1; + for (i = 0; i < nslices; i++) gpr_slice_unref(slices[i]); + break; + case GRPC_ENDPOINT_CB_OK: + lock(t); + i = 0; + GPR_ASSERT(!t->parsing_active); + if (!t->closed) { + t->parsing_active = 1; + /* merge stream lists */ + grpc_chttp2_stream_map_move_into(&t->new_stream_map, + &t->parsing_stream_map); + grpc_chttp2_prepare_to_read(&t->global, &t->parsing); + gpr_mu_unlock(&t->mu); + for (; i < nslices && grpc_chttp2_perform_read(&t->parsing, slices[i]); + i++) { + gpr_slice_unref(slices[i]); + } + gpr_mu_lock(&t->mu); + if (i != nslices) { + drop_connection(t); + } + /* merge stream lists */ + grpc_chttp2_stream_map_move_into(&t->new_stream_map, + &t->parsing_stream_map); + t->global.concurrent_stream_count = + grpc_chttp2_stream_map_size(&t->parsing_stream_map); + if (t->parsing.initial_window_update != 0) { + grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, + update_global_window, t); + t->parsing.initial_window_update = 0; + } + /* handle higher level things */ + grpc_chttp2_publish_reads(&t->global, &t->parsing); + t->parsing_active = 0; + } + if (i == nslices) { + grpc_chttp2_schedule_closure(&t->global, &t->reading_action, 1); + } else { + read_error_locked(t); + unref = 1; + } + unlock(t); + for (; i < nslices; i++) gpr_slice_unref(slices[i]); + break; } - gpr_slice_buffer_reset_and_unref(&t->read_buffer); - unlock(t); - - if (keep_reading) { - switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { - case GRPC_ENDPOINT_DONE: - *success = 1; - return 1; - case GRPC_ENDPOINT_ERROR: - *success = 0; - return 1; - case GRPC_ENDPOINT_PENDING: - return 0; - } - } else { + if (unref) { UNREF_TRANSPORT(t, "recv_data"); - return 0; } - - gpr_log(GPR_ERROR, "should never reach here"); - abort(); } -static void recv_data(void *tp, int success) { - grpc_chttp2_transport *t = tp; - - while (recv_data_loop(t, &success)) - ; +static void reading_action(void *pt, int iomgr_success_ignored) { + grpc_chttp2_transport *t = pt; + grpc_endpoint_notify_on_read(t->ep, recv_data, t); } /* @@ -1245,6 +1240,5 @@ void grpc_chttp2_transport_start_reading(grpc_transport *transport, gpr_slice *slices, size_t nslices) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport; REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */ - gpr_slice_buffer_addn(&t->read_buffer, slices, nslices); - recv_data(t, 1); + recv_data(t, slices, nslices, GRPC_ENDPOINT_CB_OK); } diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index 1d98879662..24bf5d3625 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -59,7 +59,7 @@ static void thd_func(void *arg) { gpr_event_set(&a->done_thd, (void *)1); } -static void done_write(void *arg, int success) { +static void done_write(void *arg, grpc_endpoint_cb_status status) { thd_args *a = arg; gpr_event_set(&a->done_write, (void *)1); } @@ -85,8 +85,6 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, grpc_mdctx *mdctx = grpc_mdctx_create(); gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); - gpr_slice_buffer outgoing; - grpc_iomgr_closure done_write_closure; hex = gpr_dump(client_payload, client_payload_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); @@ -124,18 +122,14 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, /* Start validator */ gpr_thd_new(&id, thd_func, &a, NULL); - gpr_slice_buffer_init(&outgoing); - gpr_slice_buffer_add(&outgoing, slice); - grpc_iomgr_closure_init(&done_write_closure, done_write, &a); - /* Write data */ - switch (grpc_endpoint_write(sfd.client, &outgoing, &done_write_closure)) { - case GRPC_ENDPOINT_DONE: + switch (grpc_endpoint_write(sfd.client, &slice, 1, done_write, &a)) { + case GRPC_ENDPOINT_WRITE_DONE: done_write(&a, 1); break; - case GRPC_ENDPOINT_PENDING: + case GRPC_ENDPOINT_WRITE_PENDING: break; - case GRPC_ENDPOINT_ERROR: + case GRPC_ENDPOINT_WRITE_ERROR: done_write(&a, 0); break; } @@ -161,7 +155,6 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, .type == GRPC_OP_COMPLETE); grpc_server_destroy(a.server); grpc_completion_queue_destroy(a.cq); - gpr_slice_buffer_destroy(&outgoing); grpc_shutdown(); } diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c index ef673747a1..6ef8e9ca3b 100644 --- a/test/core/iomgr/endpoint_tests.c +++ b/test/core/iomgr/endpoint_tests.c @@ -59,7 +59,8 @@ static grpc_pollset *g_pollset; -size_t count_slices(gpr_slice *slices, size_t nslices, int *current_data) { +size_t count_and_unref_slices(gpr_slice *slices, size_t nslices, + int *current_data) { size_t num_bytes = 0; size_t i; size_t j; @@ -71,6 +72,7 @@ size_t count_slices(gpr_slice *slices, size_t nslices, int *current_data) { *current_data = (*current_data + 1) % 256; } num_bytes += GPR_SLICE_LENGTH(slices[i]); + gpr_slice_unref(slices[i]); } return num_bytes; } @@ -119,76 +121,86 @@ struct read_and_write_test_state { int current_write_data; int read_done; int write_done; - gpr_slice_buffer incoming; - gpr_slice_buffer outgoing; - grpc_iomgr_closure done_read; - grpc_iomgr_closure done_write; }; -static void read_and_write_test_read_handler(void *data, int success) { +static void read_and_write_test_read_handler(void *data, gpr_slice *slices, + size_t nslices, + grpc_endpoint_cb_status error) { struct read_and_write_test_state *state = data; + GPR_ASSERT(error != GRPC_ENDPOINT_CB_ERROR); + if (error == GRPC_ENDPOINT_CB_SHUTDOWN) { + gpr_log(GPR_INFO, "Read handler shutdown"); + gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); + state->read_done = 1; + grpc_pollset_kick(g_pollset, NULL); + gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); + return; + } - state->bytes_read += count_slices( - state->incoming.slices, state->incoming.count, &state->current_read_data); - if (state->bytes_read == state->target_bytes || !success) { + state->bytes_read += + count_and_unref_slices(slices, nslices, &state->current_read_data); + if (state->bytes_read == state->target_bytes) { gpr_log(GPR_INFO, "Read handler done"); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->read_done = 1 + success; + state->read_done = 1; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - } else if (success) { - switch (grpc_endpoint_read(state->read_ep, &state->incoming, - &state->done_read)) { - case GRPC_ENDPOINT_ERROR: - read_and_write_test_read_handler(data, 0); - break; - case GRPC_ENDPOINT_DONE: - read_and_write_test_read_handler(data, 1); - break; - case GRPC_ENDPOINT_PENDING: - break; - } + } else { + grpc_endpoint_notify_on_read(state->read_ep, + read_and_write_test_read_handler, data); } } -static void read_and_write_test_write_handler(void *data, int success) { +static void read_and_write_test_write_handler(void *data, + grpc_endpoint_cb_status error) { struct read_and_write_test_state *state = data; gpr_slice *slices = NULL; size_t nslices; - grpc_endpoint_op_status write_status; - - if (success) { - for (;;) { - /* Need to do inline writes until they don't succeed synchronously or we - finish writing */ - state->bytes_written += state->current_write_size; - if (state->target_bytes - state->bytes_written < - state->current_write_size) { - state->current_write_size = state->target_bytes - state->bytes_written; - } - if (state->current_write_size == 0) { - break; - } - - slices = allocate_blocks(state->current_write_size, 8192, &nslices, - &state->current_write_data); - gpr_slice_buffer_reset_and_unref(&state->outgoing); - gpr_slice_buffer_addn(&state->outgoing, slices, nslices); - write_status = grpc_endpoint_write(state->write_ep, &state->outgoing, - &state->done_write); - gpr_log(GPR_DEBUG, "write_status=%d", write_status); - GPR_ASSERT(write_status != GRPC_ENDPOINT_ERROR); - free(slices); - if (write_status == GRPC_ENDPOINT_PENDING) { - return; - } + grpc_endpoint_write_status write_status; + + GPR_ASSERT(error != GRPC_ENDPOINT_CB_ERROR); + + gpr_log(GPR_DEBUG, "%s: error=%d", "read_and_write_test_write_handler", + error); + + if (error == GRPC_ENDPOINT_CB_SHUTDOWN) { + gpr_log(GPR_INFO, "Write handler shutdown"); + gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); + state->write_done = 1; + grpc_pollset_kick(g_pollset, NULL); + gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); + return; + } + + for (;;) { + /* Need to do inline writes until they don't succeed synchronously or we + finish writing */ + state->bytes_written += state->current_write_size; + if (state->target_bytes - state->bytes_written < + state->current_write_size) { + state->current_write_size = state->target_bytes - state->bytes_written; + } + if (state->current_write_size == 0) { + break; + } + + slices = allocate_blocks(state->current_write_size, 8192, &nslices, + &state->current_write_data); + write_status = + grpc_endpoint_write(state->write_ep, slices, nslices, + read_and_write_test_write_handler, state); + gpr_log(GPR_DEBUG, "write_status=%d", write_status); + GPR_ASSERT(write_status != GRPC_ENDPOINT_WRITE_ERROR); + free(slices); + if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { + return; } - GPR_ASSERT(state->bytes_written == state->target_bytes); } + GPR_ASSERT(state->bytes_written == state->target_bytes); gpr_log(GPR_INFO, "Write handler done"); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->write_done = 1 + success; + state->write_done = 1; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); } @@ -222,31 +234,16 @@ static void read_and_write_test(grpc_endpoint_test_config config, state.write_done = 0; state.current_read_data = 0; state.current_write_data = 0; - grpc_iomgr_closure_init(&state.done_read, read_and_write_test_read_handler, - &state); - grpc_iomgr_closure_init(&state.done_write, read_and_write_test_write_handler, - &state); - gpr_slice_buffer_init(&state.outgoing); - gpr_slice_buffer_init(&state.incoming); /* Get started by pretending an initial write completed */ /* NOTE: Sets up initial conditions so we can have the same write handler for the first iteration as for later iterations. It does the right thing even when bytes_written is unsigned. */ state.bytes_written -= state.current_write_size; - read_and_write_test_write_handler(&state, 1); + read_and_write_test_write_handler(&state, GRPC_ENDPOINT_CB_OK); - switch ( - grpc_endpoint_read(state.read_ep, &state.incoming, &state.done_read)) { - case GRPC_ENDPOINT_PENDING: - break; - case GRPC_ENDPOINT_ERROR: - read_and_write_test_read_handler(&state, 0); - break; - case GRPC_ENDPOINT_DONE: - read_and_write_test_read_handler(&state, 1); - break; - } + grpc_endpoint_notify_on_read(state.read_ep, read_and_write_test_read_handler, + &state); if (shutdown) { gpr_log(GPR_DEBUG, "shutdown read"); @@ -266,8 +263,6 @@ static void read_and_write_test(grpc_endpoint_test_config config, grpc_endpoint_destroy(state.read_ep); grpc_endpoint_destroy(state.write_ep); - gpr_slice_buffer_destroy(&state.outgoing); - gpr_slice_buffer_destroy(&state.incoming); end_test(config); } @@ -278,40 +273,36 @@ struct timeout_test_state { typedef struct { int done; grpc_endpoint *ep; - gpr_slice_buffer incoming; - grpc_iomgr_closure done_read; } shutdown_during_write_test_state; -static void shutdown_during_write_test_read_handler(void *user_data, - int success) { +static void shutdown_during_write_test_read_handler( + void *user_data, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error) { + size_t i; shutdown_during_write_test_state *st = user_data; - if (!success) { + for (i = 0; i < nslices; i++) { + gpr_slice_unref(slices[i]); + } + + if (error != GRPC_ENDPOINT_CB_OK) { grpc_endpoint_destroy(st->ep); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - st->done = 1; + st->done = error; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); } else { - switch (grpc_endpoint_read(st->ep, &st->incoming, &st->done_read)) { - case GRPC_ENDPOINT_PENDING: - break; - case GRPC_ENDPOINT_ERROR: - shutdown_during_write_test_read_handler(user_data, 0); - break; - case GRPC_ENDPOINT_DONE: - shutdown_during_write_test_read_handler(user_data, 1); - break; - } + grpc_endpoint_notify_on_read( + st->ep, shutdown_during_write_test_read_handler, user_data); } } -static void shutdown_during_write_test_write_handler(void *user_data, - int success) { +static void shutdown_during_write_test_write_handler( + void *user_data, grpc_endpoint_cb_status error) { shutdown_during_write_test_state *st = user_data; - gpr_log(GPR_INFO, "shutdown_during_write_test_write_handler: success = %d", - success); - if (success) { + gpr_log(GPR_INFO, "shutdown_during_write_test_write_handler: error = %d", + error); + if (error == 0) { /* This happens about 0.5% of the time when run under TSAN, and is entirely legitimate, but means we aren't testing the path we think we are. */ /* TODO(klempner): Change this test to retry the write in that case */ @@ -334,8 +325,6 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, shutdown_during_write_test_state read_st; shutdown_during_write_test_state write_st; gpr_slice *slices; - gpr_slice_buffer outgoing; - grpc_iomgr_closure done_write; grpc_endpoint_test_fixture f = begin_test(config, "shutdown_during_write_test", slice_size); @@ -346,26 +335,19 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, read_st.done = 0; write_st.done = 0; - grpc_iomgr_closure_init(&done_write, shutdown_during_write_test_write_handler, - &write_st); - grpc_iomgr_closure_init(&read_st.done_read, - shutdown_during_write_test_read_handler, &read_st); - gpr_slice_buffer_init(&read_st.incoming); - gpr_slice_buffer_init(&outgoing); - - GPR_ASSERT(grpc_endpoint_read(read_st.ep, &read_st.incoming, - &read_st.done_read) == GRPC_ENDPOINT_PENDING); + grpc_endpoint_notify_on_read( + read_st.ep, shutdown_during_write_test_read_handler, &read_st); for (size = 1;; size *= 2) { slices = allocate_blocks(size, 1, &nblocks, ¤t_data); - gpr_slice_buffer_reset_and_unref(&outgoing); - gpr_slice_buffer_addn(&outgoing, slices, nblocks); - switch (grpc_endpoint_write(write_st.ep, &outgoing, &done_write)) { - case GRPC_ENDPOINT_DONE: + switch (grpc_endpoint_write(write_st.ep, slices, nblocks, + shutdown_during_write_test_write_handler, + &write_st)) { + case GRPC_ENDPOINT_WRITE_DONE: break; - case GRPC_ENDPOINT_ERROR: + case GRPC_ENDPOINT_WRITE_ERROR: gpr_log(GPR_ERROR, "error writing"); abort(); - case GRPC_ENDPOINT_PENDING: + case GRPC_ENDPOINT_WRITE_PENDING: grpc_endpoint_shutdown(write_st.ep); deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); @@ -386,8 +368,6 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, } gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); gpr_free(slices); - gpr_slice_buffer_destroy(&read_st.incoming); - gpr_slice_buffer_destroy(&outgoing); end_test(config); return; } diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 8acaa433bb..6ad832231f 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -118,12 +118,10 @@ struct read_socket_state { grpc_endpoint *ep; ssize_t read_bytes; ssize_t target_read_bytes; - gpr_slice_buffer incoming; - grpc_iomgr_closure read_cb; }; -static ssize_t count_slices(gpr_slice *slices, size_t nslices, - int *current_data) { +static ssize_t count_and_unref_slices(gpr_slice *slices, size_t nslices, + int *current_data) { ssize_t num_bytes = 0; unsigned i, j; unsigned char *buf; @@ -134,41 +132,31 @@ static ssize_t count_slices(gpr_slice *slices, size_t nslices, *current_data = (*current_data + 1) % 256; } num_bytes += GPR_SLICE_LENGTH(slices[i]); + gpr_slice_unref(slices[i]); } return num_bytes; } -static void read_cb(void *user_data, int success) { +static void read_cb(void *user_data, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error) { struct read_socket_state *state = (struct read_socket_state *)user_data; ssize_t read_bytes; int current_data; - GPR_ASSERT(success); + GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); current_data = state->read_bytes % 256; - read_bytes = count_slices(state->incoming.slices, state->incoming.count, - ¤t_data); + read_bytes = count_and_unref_slices(slices, nslices, ¤t_data); state->read_bytes += read_bytes; gpr_log(GPR_INFO, "Read %d bytes of %d", read_bytes, state->target_read_bytes); if (state->read_bytes >= state->target_read_bytes) { - gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + /* empty */ } else { - switch (grpc_endpoint_read(state->ep, &state->incoming, &state->read_cb)) { - case GRPC_ENDPOINT_DONE: - gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); - read_cb(user_data, 1); - break; - case GRPC_ENDPOINT_ERROR: - gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); - read_cb(user_data, 0); - break; - case GRPC_ENDPOINT_PENDING: - gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); - break; - } + grpc_endpoint_notify_on_read(state->ep, read_cb, state); } + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); } /* Write to a socket, then read from it using the grpc_tcp API. */ @@ -193,19 +181,8 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { state.ep = ep; state.read_bytes = 0; state.target_read_bytes = written_bytes; - gpr_slice_buffer_init(&state.incoming); - grpc_iomgr_closure_init(&state.read_cb, read_cb, &state); - switch (grpc_endpoint_read(ep, &state.incoming, &state.read_cb)) { - case GRPC_ENDPOINT_DONE: - read_cb(&state, 1); - break; - case GRPC_ENDPOINT_ERROR: - read_cb(&state, 0); - break; - case GRPC_ENDPOINT_PENDING: - break; - } + grpc_endpoint_notify_on_read(ep, read_cb, &state); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (state.read_bytes < state.target_read_bytes) { @@ -216,7 +193,6 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { GPR_ASSERT(state.read_bytes == state.target_read_bytes); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); - gpr_slice_buffer_destroy(&state.incoming); grpc_endpoint_destroy(ep); } @@ -243,19 +219,8 @@ static void large_read_test(ssize_t slice_size) { state.ep = ep; state.read_bytes = 0; state.target_read_bytes = written_bytes; - gpr_slice_buffer_init(&state.incoming); - grpc_iomgr_closure_init(&state.read_cb, read_cb, &state); - switch (grpc_endpoint_read(ep, &state.incoming, &state.read_cb)) { - case GRPC_ENDPOINT_DONE: - read_cb(&state, 1); - break; - case GRPC_ENDPOINT_ERROR: - read_cb(&state, 0); - break; - case GRPC_ENDPOINT_PENDING: - break; - } + grpc_endpoint_notify_on_read(ep, read_cb, &state); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (state.read_bytes < state.target_read_bytes) { @@ -266,7 +231,6 @@ static void large_read_test(ssize_t slice_size) { GPR_ASSERT(state.read_bytes == state.target_read_bytes); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); - gpr_slice_buffer_destroy(&state.incoming); grpc_endpoint_destroy(ep); } @@ -298,7 +262,8 @@ static gpr_slice *allocate_blocks(ssize_t num_bytes, ssize_t slice_size, return slices; } -static void write_done(void *user_data /* write_socket_state */, int success) { +static void write_done(void *user_data /* write_socket_state */, + grpc_endpoint_cb_status error) { struct write_socket_state *state = (struct write_socket_state *)user_data; gpr_log(GPR_INFO, "Write done callback called"); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); @@ -374,8 +339,6 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { size_t num_blocks; gpr_slice *slices; int current_data = 0; - gpr_slice_buffer outgoing; - grpc_iomgr_closure write_done_closure; gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20); gpr_log(GPR_INFO, "Start write test with %d bytes, slice size %d", num_bytes, @@ -392,21 +355,74 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - gpr_slice_buffer_init(&outgoing); - gpr_slice_buffer_addn(&outgoing, slices, num_blocks); - grpc_iomgr_closure_init(&write_done_closure, write_done, &state); + if (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state) == + GRPC_ENDPOINT_WRITE_DONE) { + /* Write completed immediately */ + read_bytes = drain_socket(sv[0]); + GPR_ASSERT(read_bytes == num_bytes); + } else { + drain_socket_blocking(sv[0], num_bytes, num_bytes); + gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); + for (;;) { + grpc_pollset_worker worker; + if (state.write_done) { + break; + } + grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), + deadline); + } + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + } + + grpc_endpoint_destroy(ep); + gpr_free(slices); +} + +static void read_done_for_write_error(void *ud, gpr_slice *slices, + size_t nslices, + grpc_endpoint_cb_status error) { + GPR_ASSERT(error != GRPC_ENDPOINT_CB_OK); + GPR_ASSERT(nslices == 0); +} + +/* Write to a socket using the grpc_tcp API, then drain it directly. + Note that if the write does not complete immediately we need to drain the + socket in parallel with the read. */ +static void write_error_test(ssize_t num_bytes, ssize_t slice_size) { + int sv[2]; + grpc_endpoint *ep; + struct write_socket_state state; + size_t num_blocks; + gpr_slice *slices; + int current_data = 0; + grpc_pollset_worker worker; + gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20); + + gpr_log(GPR_INFO, "Start write error test with %d bytes, slice size %d", + num_bytes, slice_size); + + create_sockets(sv); - switch (grpc_endpoint_write(ep, &outgoing, &write_done_closure)) { - case GRPC_ENDPOINT_DONE: + ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_error_test"), + GRPC_TCP_DEFAULT_READ_SLICE_SIZE, "test"); + grpc_endpoint_add_to_pollset(ep, &g_pollset); + + close(sv[0]); + + state.ep = ep; + state.write_done = 0; + + slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); + + switch (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state)) { + case GRPC_ENDPOINT_WRITE_DONE: + case GRPC_ENDPOINT_WRITE_ERROR: /* Write completed immediately */ - read_bytes = drain_socket(sv[0]); - GPR_ASSERT(read_bytes == num_bytes); break; - case GRPC_ENDPOINT_PENDING: - drain_socket_blocking(sv[0], num_bytes, num_bytes); + case GRPC_ENDPOINT_WRITE_PENDING: + grpc_endpoint_notify_on_read(ep, read_done_for_write_error, NULL); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); for (;;) { - grpc_pollset_worker worker; if (state.write_done) { break; } @@ -415,14 +431,10 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); break; - case GRPC_ENDPOINT_ERROR: - gpr_log(GPR_ERROR, "endpoint got error"); - abort(); } - gpr_slice_buffer_destroy(&outgoing); grpc_endpoint_destroy(ep); - gpr_free(slices); + free(slices); } void run_tests(void) { @@ -441,6 +453,10 @@ void run_tests(void) { write_test(100000, 1); write_test(100000, 137); + for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { + write_error_test(40320, i); + } + for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { write_test(40320, i); } diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index c76ddcd194..a8368fc842 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -135,26 +135,62 @@ static grpc_endpoint_test_config configs[] = { secure_endpoint_create_fixture_tcp_socketpair_leftover, clean_up}, }; -static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { - grpc_endpoint_test_fixture f = config.create_fixture(slice_size); - gpr_slice_buffer incoming; +static void verify_leftover(void *user_data, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error) { gpr_slice s = gpr_slice_from_copied_string("hello world 12345678900987654321"); + + GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); + GPR_ASSERT(nslices == 1); + + GPR_ASSERT(0 == gpr_slice_cmp(s, slices[0])); + gpr_slice_unref(slices[0]); + gpr_slice_unref(s); + *(int *)user_data = 1; +} + +static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { + grpc_endpoint_test_fixture f = config.create_fixture(slice_size); + int verified = 0; gpr_log(GPR_INFO, "Start test left over"); - gpr_slice_buffer_init(&incoming); - GPR_ASSERT(grpc_endpoint_read(f.client_ep, &incoming, NULL) == - GRPC_ENDPOINT_DONE); - GPR_ASSERT(incoming.count == 1); - GPR_ASSERT(0 == gpr_slice_cmp(s, incoming.slices[0])); + grpc_endpoint_notify_on_read(f.client_ep, verify_leftover, &verified); + GPR_ASSERT(verified == 1); grpc_endpoint_shutdown(f.client_ep); grpc_endpoint_shutdown(f.server_ep); grpc_endpoint_destroy(f.client_ep); grpc_endpoint_destroy(f.server_ep); + clean_up(); +} + +static void destroy_early(void *user_data, gpr_slice *slices, size_t nslices, + grpc_endpoint_cb_status error) { + grpc_endpoint_test_fixture *f = user_data; + gpr_slice s = + gpr_slice_from_copied_string("hello world 12345678900987654321"); + + GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); + GPR_ASSERT(nslices == 1); + + grpc_endpoint_shutdown(f->client_ep); + grpc_endpoint_destroy(f->client_ep); + + GPR_ASSERT(0 == gpr_slice_cmp(s, slices[0])); + gpr_slice_unref(slices[0]); gpr_slice_unref(s); - gpr_slice_buffer_destroy(&incoming); +} +/* test which destroys the ep before finishing reading */ +static void test_destroy_ep_early(grpc_endpoint_test_config config, + size_t slice_size) { + grpc_endpoint_test_fixture f = config.create_fixture(slice_size); + gpr_log(GPR_INFO, "Start test destroy early"); + + grpc_endpoint_notify_on_read(f.client_ep, destroy_early, &f); + + grpc_endpoint_shutdown(f.server_ep); + grpc_endpoint_destroy(f.server_ep); clean_up(); } @@ -167,6 +203,7 @@ int main(int argc, char **argv) { grpc_pollset_init(&g_pollset); grpc_endpoint_tests(configs[0], &g_pollset); test_leftover(configs[1], 1); + test_destroy_ep_early(configs[1], 1); grpc_pollset_shutdown(&g_pollset, destroy_pollset, &g_pollset); grpc_iomgr_shutdown(); diff --git a/test/core/util/port_posix.c b/test/core/util/port_posix.c index 4781d334e2..836e62a541 100644 --- a/test/core/util/port_posix.c +++ b/test/core/util/port_posix.c @@ -198,13 +198,14 @@ int grpc_pick_unused_port(void) { races with other processes on kernels that want to reuse the same port numbers over and over. */ - /* In alternating iterations we trial UDP ports before TCP ports UDP + /* In alternating iterations we try UDP ports before TCP ports UDP ports -- it could be the case that this machine has been using up UDP ports and they are scarcer. */ /* Type of port to first pick in next iteration */ int is_tcp = 1; - int trial = 0; + int try + = 0; char *env = gpr_getenv("GRPC_TEST_PORT_SERVER"); if (env) { @@ -217,10 +218,11 @@ int grpc_pick_unused_port(void) { for (;;) { int port; - trial++; - if (trial == 1) { + try + ++; + if (try == 1) { port = getpid() % (65536 - 30000) + 30000; - } else if (trial <= NUM_RANDOM_PORTS_TO_PICK) { + } else if (try <= NUM_RANDOM_PORTS_TO_PICK) { port = rand() % (65536 - 30000) + 30000; } else { port = 0; @@ -237,7 +239,7 @@ int grpc_pick_unused_port(void) { GPR_ASSERT(port > 0); /* Check that the port # is free for the other type of socket also */ if (!is_port_available(&port, !is_tcp)) { - /* In the next iteration trial to bind to the other type first + /* In the next iteration try to bind to the other type first because perhaps it is more rare. */ is_tcp = !is_tcp; continue; diff --git a/test/core/util/port_windows.c b/test/core/util/port_windows.c index 2f64626cf3..5b072f805a 100644 --- a/test/core/util/port_windows.c +++ b/test/core/util/port_windows.c @@ -35,6 +35,7 @@ #include "test/core/util/test_config.h" #if defined(GPR_WINSOCK_SOCKET) && defined(GRPC_TEST_PICK_PORT) +#include "src/core/iomgr/sockaddr_utils.h" #include "test/core/util/port.h" #include @@ -42,14 +43,8 @@ #include #include -#include -#include #include -#include "src/core/support/env.h" -#include "src/core/httpcli/httpcli.h" -#include "src/core/iomgr/sockaddr_utils.h" - #define NUM_RANDOM_PORTS_TO_PICK 100 static int is_port_available(int *port, int is_tcp) { @@ -104,67 +99,6 @@ static int is_port_available(int *port, int is_tcp) { return 1; } -typedef struct portreq { - grpc_pollset pollset; - int port; -} portreq; - -static void got_port_from_server(void *arg, - const grpc_httpcli_response *response) { - size_t i; - int port = 0; - portreq *pr = arg; - GPR_ASSERT(response); - GPR_ASSERT(response->status == 200); - for (i = 0; i < response->body_length; i++) { - GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9'); - port = port * 10 + response->body[i] - '0'; - } - GPR_ASSERT(port > 1024); - gpr_mu_lock(GRPC_POLLSET_MU(&pr->pollset)); - pr->port = port; - grpc_pollset_kick(&pr->pollset, NULL); - gpr_mu_unlock(GRPC_POLLSET_MU(&pr->pollset)); -} - -static void destroy_pollset_and_shutdown(void *p) { - grpc_pollset_destroy(p); - grpc_shutdown(); -} - -static int pick_port_using_server(char *server) { - grpc_httpcli_context context; - grpc_httpcli_request req; - portreq pr; - - grpc_init(); - - memset(&pr, 0, sizeof(pr)); - memset(&req, 0, sizeof(req)); - grpc_pollset_init(&pr.pollset); - pr.port = -1; - - req.host = server; - req.path = "/get"; - - grpc_httpcli_context_init(&context); - grpc_httpcli_get(&context, &pr.pollset, &req, - GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server, - &pr); - gpr_mu_lock(GRPC_POLLSET_MU(&pr.pollset)); - while (pr.port == -1) { - grpc_pollset_worker worker; - grpc_pollset_work(&pr.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), - GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)); - } - gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset)); - - grpc_httpcli_context_destroy(&context); - grpc_pollset_shutdown(&pr.pollset, destroy_pollset_and_shutdown, &pr.pollset); - - return pr.port; -} - int grpc_pick_unused_port(void) { /* We repeatedly pick a port and then see whether or not it is available for use both as a TCP socket and a UDP socket. First, we @@ -174,29 +108,22 @@ int grpc_pick_unused_port(void) { races with other processes on kernels that want to reuse the same port numbers over and over. */ - /* In alternating iterations we trial UDP ports before TCP ports UDP + /* In alternating iterations we try UDP ports before TCP ports UDP ports -- it could be the case that this machine has been using up UDP ports and they are scarcer. */ /* Type of port to first pick in next iteration */ int is_tcp = 1; - int trial = 0; - - char *env = gpr_getenv("GRPC_TEST_PORT_SERVER"); - if (env) { - int port = pick_port_using_server(env); - gpr_free(env); - if (port != 0) { - return port; - } - } + int try + = 0; for (;;) { int port; - trial++; - if (trial == 1) { + try + ++; + if (try == 1) { port = _getpid() % (65536 - 30000) + 30000; - } else if (trial <= NUM_RANDOM_PORTS_TO_PICK) { + } else if (try <= NUM_RANDOM_PORTS_TO_PICK) { port = rand() % (65536 - 30000) + 30000; } else { port = 0; @@ -209,7 +136,7 @@ int grpc_pick_unused_port(void) { GPR_ASSERT(port > 0); /* Check that the port # is free for the other type of socket also */ if (!is_port_available(&port, !is_tcp)) { - /* In the next iteration trial to bind to the other type first + /* In the next iteration try to bind to the other type first because perhaps it is more rare. */ is_tcp = !is_tcp; continue; -- cgit v1.2.3 From b029859e580bfb7281c623622cdc32daf9846769 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 27 Aug 2015 07:38:01 -0700 Subject: Revert "Revert "Refactor Endpoint API"" --- include/grpc/support/slice_buffer.h | 2 + src/core/httpcli/httpcli.c | 95 +++--- src/core/iomgr/endpoint.c | 17 +- src/core/iomgr/endpoint.h | 63 ++-- src/core/iomgr/tcp_posix.c | 525 ++++++++++------------------- src/core/iomgr/tcp_windows.c | 192 ++++++----- src/core/security/secure_endpoint.c | 188 ++++++----- src/core/security/secure_transport_setup.c | 119 ++++--- src/core/support/slice_buffer.c | 22 ++ src/core/transport/chttp2/internal.h | 12 +- src/core/transport/chttp2/writing.c | 21 +- src/core/transport/chttp2_transport.c | 140 ++++---- test/core/bad_client/bad_client.c | 17 +- test/core/iomgr/endpoint_tests.c | 204 ++++++----- test/core/iomgr/tcp_posix_test.c | 148 ++++---- test/core/security/secure_endpoint_test.c | 55 +-- test/core/util/port_posix.c | 14 +- test/core/util/port_windows.c | 91 ++++- 18 files changed, 947 insertions(+), 978 deletions(-) (limited to 'src') diff --git a/include/grpc/support/slice_buffer.h b/include/grpc/support/slice_buffer.h index ec048e8c91..04db003ac5 100644 --- a/include/grpc/support/slice_buffer.h +++ b/include/grpc/support/slice_buffer.h @@ -86,6 +86,8 @@ void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb); void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b); /* move all of the elements of src into dst */ void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst); +/* remove n bytes from the end of a slice buffer */ +void gpr_slice_buffer_trim_end(gpr_slice_buffer *src, size_t n); #ifdef __cplusplus } diff --git a/src/core/httpcli/httpcli.c b/src/core/httpcli/httpcli.c index 9012070e8e..1e38479eb1 100644 --- a/src/core/httpcli/httpcli.c +++ b/src/core/httpcli/httpcli.c @@ -61,6 +61,10 @@ typedef struct { grpc_httpcli_context *context; grpc_pollset *pollset; grpc_iomgr_object iomgr_obj; + gpr_slice_buffer incoming; + gpr_slice_buffer outgoing; + grpc_iomgr_closure on_read; + grpc_iomgr_closure done_write; } internal_request; static grpc_httpcli_get_override g_get_override = NULL; @@ -99,73 +103,70 @@ static void finish(internal_request *req, int success) { gpr_slice_unref(req->request_text); gpr_free(req->host); grpc_iomgr_unregister_object(&req->iomgr_obj); + gpr_slice_buffer_destroy(&req->incoming); + gpr_slice_buffer_destroy(&req->outgoing); gpr_free(req); } -static void on_read(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status status) { +static void on_read(void *user_data, int success); + +static void do_read(internal_request *req) { + switch (grpc_endpoint_read(req->ep, &req->incoming, &req->on_read)) { + case GRPC_ENDPOINT_DONE: + on_read(req, 1); + break; + case GRPC_ENDPOINT_PENDING: + break; + case GRPC_ENDPOINT_ERROR: + on_read(req, 0); + break; + } +} + +static void on_read(void *user_data, int success) { internal_request *req = user_data; size_t i; - for (i = 0; i < nslices; i++) { - if (GPR_SLICE_LENGTH(slices[i])) { + for (i = 0; i < req->incoming.count; i++) { + if (GPR_SLICE_LENGTH(req->incoming.slices[i])) { req->have_read_byte = 1; - if (!grpc_httpcli_parser_parse(&req->parser, slices[i])) { + if (!grpc_httpcli_parser_parse(&req->parser, req->incoming.slices[i])) { finish(req, 0); - goto done; + return; } } } - switch (status) { - case GRPC_ENDPOINT_CB_OK: - grpc_endpoint_notify_on_read(req->ep, on_read, req); - break; - case GRPC_ENDPOINT_CB_EOF: - case GRPC_ENDPOINT_CB_ERROR: - case GRPC_ENDPOINT_CB_SHUTDOWN: - if (!req->have_read_byte) { - next_address(req); - } else { - finish(req, grpc_httpcli_parser_eof(&req->parser)); - } - break; - } - -done: - for (i = 0; i < nslices; i++) { - gpr_slice_unref(slices[i]); + if (success) { + do_read(req); + } else if (!req->have_read_byte) { + next_address(req); + } else { + finish(req, grpc_httpcli_parser_eof(&req->parser)); } } -static void on_written(internal_request *req) { - grpc_endpoint_notify_on_read(req->ep, on_read, req); -} +static void on_written(internal_request *req) { do_read(req); } -static void done_write(void *arg, grpc_endpoint_cb_status status) { +static void done_write(void *arg, int success) { internal_request *req = arg; - switch (status) { - case GRPC_ENDPOINT_CB_OK: - on_written(req); - break; - case GRPC_ENDPOINT_CB_EOF: - case GRPC_ENDPOINT_CB_SHUTDOWN: - case GRPC_ENDPOINT_CB_ERROR: - next_address(req); - break; + if (success) { + on_written(req); + } else { + next_address(req); } } static void start_write(internal_request *req) { gpr_slice_ref(req->request_text); - switch ( - grpc_endpoint_write(req->ep, &req->request_text, 1, done_write, req)) { - case GRPC_ENDPOINT_WRITE_DONE: + gpr_slice_buffer_add(&req->outgoing, req->request_text); + switch (grpc_endpoint_write(req->ep, &req->outgoing, &req->done_write)) { + case GRPC_ENDPOINT_DONE: on_written(req); break; - case GRPC_ENDPOINT_WRITE_PENDING: + case GRPC_ENDPOINT_PENDING: break; - case GRPC_ENDPOINT_WRITE_ERROR: + case GRPC_ENDPOINT_ERROR: finish(req, 0); break; } @@ -237,6 +238,10 @@ void grpc_httpcli_get(grpc_httpcli_context *context, grpc_pollset *pollset, request->handshaker ? request->handshaker : &grpc_httpcli_plaintext; req->context = context; req->pollset = pollset; + grpc_iomgr_closure_init(&req->on_read, on_read, req); + grpc_iomgr_closure_init(&req->done_write, done_write, req); + gpr_slice_buffer_init(&req->incoming); + gpr_slice_buffer_init(&req->outgoing); gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path); grpc_iomgr_register_object(&req->iomgr_obj, name); gpr_free(name); @@ -270,7 +275,11 @@ void grpc_httpcli_post(grpc_httpcli_context *context, grpc_pollset *pollset, request->handshaker ? request->handshaker : &grpc_httpcli_plaintext; req->context = context; req->pollset = pollset; - gpr_asprintf(&name, "HTTP:GET:%s:%s", request->host, request->path); + grpc_iomgr_closure_init(&req->on_read, on_read, req); + grpc_iomgr_closure_init(&req->done_write, done_write, req); + gpr_slice_buffer_init(&req->incoming); + gpr_slice_buffer_init(&req->outgoing); + gpr_asprintf(&name, "HTTP:POST:%s:%s", request->host, request->path); grpc_iomgr_register_object(&req->iomgr_obj, name); gpr_free(name); req->host = gpr_strdup(request->host); diff --git a/src/core/iomgr/endpoint.c b/src/core/iomgr/endpoint.c index 8ee14bce9b..a7878e31dd 100644 --- a/src/core/iomgr/endpoint.c +++ b/src/core/iomgr/endpoint.c @@ -33,17 +33,16 @@ #include "src/core/iomgr/endpoint.h" -void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data) { - ep->vtable->notify_on_read(ep, cb, user_data); +grpc_endpoint_op_status grpc_endpoint_read(grpc_endpoint *ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { + return ep->vtable->read(ep, slices, cb); } -grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { - return ep->vtable->write(ep, slices, nslices, cb, user_data); +grpc_endpoint_op_status grpc_endpoint_write(grpc_endpoint *ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { + return ep->vtable->write(ep, slices, cb); } void grpc_endpoint_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { diff --git a/src/core/iomgr/endpoint.h b/src/core/iomgr/endpoint.h index ea92a500e8..d14d52d561 100644 --- a/src/core/iomgr/endpoint.h +++ b/src/core/iomgr/endpoint.h @@ -37,6 +37,7 @@ #include "src/core/iomgr/pollset.h" #include "src/core/iomgr/pollset_set.h" #include +#include #include /* An endpoint caps a streaming channel between two communicating processes. @@ -45,31 +46,17 @@ typedef struct grpc_endpoint grpc_endpoint; typedef struct grpc_endpoint_vtable grpc_endpoint_vtable; -typedef enum grpc_endpoint_cb_status { - GRPC_ENDPOINT_CB_OK = 0, /* Call completed successfully */ - GRPC_ENDPOINT_CB_EOF, /* Call completed successfully, end of file reached */ - GRPC_ENDPOINT_CB_SHUTDOWN, /* Call interrupted by shutdown */ - GRPC_ENDPOINT_CB_ERROR /* Call interrupted by socket error */ -} grpc_endpoint_cb_status; - -typedef enum grpc_endpoint_write_status { - GRPC_ENDPOINT_WRITE_DONE, /* completed immediately, cb won't be called */ - GRPC_ENDPOINT_WRITE_PENDING, /* cb will be called when completed */ - GRPC_ENDPOINT_WRITE_ERROR /* write errored out, cb won't be called */ -} grpc_endpoint_write_status; - -typedef void (*grpc_endpoint_read_cb)(void *user_data, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error); -typedef void (*grpc_endpoint_write_cb)(void *user_data, - grpc_endpoint_cb_status error); +typedef enum grpc_endpoint_op_status { + GRPC_ENDPOINT_DONE, /* completed immediately, cb won't be called */ + GRPC_ENDPOINT_PENDING, /* cb will be called when completed */ + GRPC_ENDPOINT_ERROR /* write errored out, cb won't be called */ +} grpc_endpoint_op_status; struct grpc_endpoint_vtable { - void (*notify_on_read)(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data); - grpc_endpoint_write_status (*write)(grpc_endpoint *ep, gpr_slice *slices, - size_t nslices, grpc_endpoint_write_cb cb, - void *user_data); + grpc_endpoint_op_status (*read)(grpc_endpoint *ep, gpr_slice_buffer *slices, + grpc_iomgr_closure *cb); + grpc_endpoint_op_status (*write)(grpc_endpoint *ep, gpr_slice_buffer *slices, + grpc_iomgr_closure *cb); void (*add_to_pollset)(grpc_endpoint *ep, grpc_pollset *pollset); void (*add_to_pollset_set)(grpc_endpoint *ep, grpc_pollset_set *pollset); void (*shutdown)(grpc_endpoint *ep); @@ -77,26 +64,32 @@ struct grpc_endpoint_vtable { char *(*get_peer)(grpc_endpoint *ep); }; -/* When data is available on the connection, calls the callback with slices. */ -void grpc_endpoint_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data); +/* When data is available on the connection, calls the callback with slices. + Callback success indicates that the endpoint can accept more reads, failure + indicates the endpoint is closed. + Valid slices may be placed into \a slices even on callback success == 0. */ +grpc_endpoint_op_status grpc_endpoint_read( + grpc_endpoint *ep, gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT; char *grpc_endpoint_get_peer(grpc_endpoint *ep); /* Write slices out to the socket. If the connection is ready for more data after the end of the call, it - returns GRPC_ENDPOINT_WRITE_DONE. - Otherwise it returns GRPC_ENDPOINT_WRITE_PENDING and calls cb when the - connection is ready for more data. */ -grpc_endpoint_write_status grpc_endpoint_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data); + returns GRPC_ENDPOINT_DONE. + Otherwise it returns GRPC_ENDPOINT_PENDING and calls cb when the + connection is ready for more data. + \a slices may be mutated at will by the endpoint until cb is called. + No guarantee is made to the content of slices after a write EXCEPT that + it is a valid slice buffer. + */ +grpc_endpoint_op_status grpc_endpoint_write( + grpc_endpoint *ep, gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) GRPC_MUST_USE_RESULT; /* Causes any pending read/write callbacks to run immediately with - GRPC_ENDPOINT_CB_SHUTDOWN status */ + success==0 */ void grpc_endpoint_shutdown(grpc_endpoint *ep); void grpc_endpoint_destroy(grpc_endpoint *ep); diff --git a/src/core/iomgr/tcp_posix.c b/src/core/iomgr/tcp_posix.c index 360e6ebd8c..0db7cd9f0e 100644 --- a/src/core/iomgr/tcp_posix.c +++ b/src/core/iomgr/tcp_posix.c @@ -61,209 +61,8 @@ #define SENDMSG_FLAGS 0 #endif -/* Holds a slice array and associated state. */ -typedef struct grpc_tcp_slice_state { - gpr_slice *slices; /* Array of slices */ - size_t nslices; /* Size of slices array. */ - ssize_t first_slice; /* First valid slice in array */ - ssize_t last_slice; /* Last valid slice in array */ - gpr_slice working_slice; /* pointer to original final slice */ - int working_slice_valid; /* True if there is a working slice */ - int memory_owned; /* True if slices array is owned */ -} grpc_tcp_slice_state; - int grpc_tcp_trace = 0; -static void slice_state_init(grpc_tcp_slice_state *state, gpr_slice *slices, - size_t nslices, size_t valid_slices) { - state->slices = slices; - state->nslices = nslices; - if (valid_slices == 0) { - state->first_slice = -1; - } else { - state->first_slice = 0; - } - state->last_slice = valid_slices - 1; - state->working_slice_valid = 0; - state->memory_owned = 0; -} - -/* Returns true if there is still available data */ -static int slice_state_has_available(grpc_tcp_slice_state *state) { - return state->first_slice != -1 && state->last_slice >= state->first_slice; -} - -static ssize_t slice_state_slices_allocated(grpc_tcp_slice_state *state) { - if (state->first_slice == -1) { - return 0; - } else { - return state->last_slice - state->first_slice + 1; - } -} - -static void slice_state_realloc(grpc_tcp_slice_state *state, size_t new_size) { - /* TODO(klempner): use realloc instead when first_slice is 0 */ - /* TODO(klempner): Avoid a realloc in cases where it is unnecessary */ - gpr_slice *slices = state->slices; - size_t original_size = slice_state_slices_allocated(state); - size_t i; - gpr_slice *new_slices = gpr_malloc(sizeof(gpr_slice) * new_size); - - for (i = 0; i < original_size; ++i) { - new_slices[i] = slices[i + state->first_slice]; - } - - state->slices = new_slices; - state->last_slice = original_size - 1; - if (original_size > 0) { - state->first_slice = 0; - } else { - state->first_slice = -1; - } - state->nslices = new_size; - - if (state->memory_owned) { - gpr_free(slices); - } - state->memory_owned = 1; -} - -static void slice_state_remove_prefix(grpc_tcp_slice_state *state, - size_t prefix_bytes) { - gpr_slice *current_slice = &state->slices[state->first_slice]; - size_t current_slice_size; - - while (slice_state_has_available(state)) { - current_slice_size = GPR_SLICE_LENGTH(*current_slice); - if (current_slice_size > prefix_bytes) { - /* TODO(klempner): Get rid of the extra refcount created here by adding a - native "trim the first N bytes" operation to splice */ - /* TODO(klempner): This really shouldn't be modifying the current slice - unless we own the slices array. */ - gpr_slice tail; - tail = gpr_slice_split_tail(current_slice, prefix_bytes); - gpr_slice_unref(*current_slice); - *current_slice = tail; - return; - } else { - gpr_slice_unref(*current_slice); - ++state->first_slice; - ++current_slice; - prefix_bytes -= current_slice_size; - } - } -} - -static void slice_state_destroy(grpc_tcp_slice_state *state) { - while (slice_state_has_available(state)) { - gpr_slice_unref(state->slices[state->first_slice]); - ++state->first_slice; - } - - if (state->memory_owned) { - gpr_free(state->slices); - state->memory_owned = 0; - } -} - -void slice_state_transfer_ownership(grpc_tcp_slice_state *state, - gpr_slice **slices, size_t *nslices) { - *slices = state->slices + state->first_slice; - *nslices = state->last_slice - state->first_slice + 1; - - state->first_slice = -1; - state->last_slice = -1; -} - -/* Fills iov with the first min(iov_size, available) slices, returns number - filled */ -static size_t slice_state_to_iovec(grpc_tcp_slice_state *state, - struct iovec *iov, size_t iov_size) { - size_t nslices = state->last_slice - state->first_slice + 1; - gpr_slice *slices = state->slices + state->first_slice; - size_t i; - if (nslices < iov_size) { - iov_size = nslices; - } - - for (i = 0; i < iov_size; ++i) { - iov[i].iov_base = GPR_SLICE_START_PTR(slices[i]); - iov[i].iov_len = GPR_SLICE_LENGTH(slices[i]); - } - return iov_size; -} - -/* Makes n blocks available at the end of state, writes them into iov, and - returns the number of bytes allocated */ -static size_t slice_state_append_blocks_into_iovec(grpc_tcp_slice_state *state, - struct iovec *iov, size_t n, - size_t slice_size) { - size_t target_size; - size_t i; - size_t allocated_bytes; - ssize_t allocated_slices = slice_state_slices_allocated(state); - - if (n - state->working_slice_valid >= state->nslices - state->last_slice) { - /* Need to grow the slice array */ - target_size = state->nslices; - do { - target_size = target_size * 2; - } while (target_size < allocated_slices + n - state->working_slice_valid); - /* TODO(klempner): If this ever needs to support both prefix removal and - append, we should be smarter about the growth logic here */ - slice_state_realloc(state, target_size); - } - - i = 0; - allocated_bytes = 0; - - if (state->working_slice_valid) { - iov[0].iov_base = GPR_SLICE_END_PTR(state->slices[state->last_slice]); - iov[0].iov_len = GPR_SLICE_LENGTH(state->working_slice) - - GPR_SLICE_LENGTH(state->slices[state->last_slice]); - allocated_bytes += iov[0].iov_len; - ++i; - state->slices[state->last_slice] = state->working_slice; - state->working_slice_valid = 0; - } - - for (; i < n; ++i) { - ++state->last_slice; - state->slices[state->last_slice] = gpr_slice_malloc(slice_size); - iov[i].iov_base = GPR_SLICE_START_PTR(state->slices[state->last_slice]); - iov[i].iov_len = slice_size; - allocated_bytes += slice_size; - } - if (state->first_slice == -1) { - state->first_slice = 0; - } - return allocated_bytes; -} - -/* Remove the last n bytes from state */ -/* TODO(klempner): Consider having this defer actual deletion until later */ -static void slice_state_remove_last(grpc_tcp_slice_state *state, size_t bytes) { - while (bytes > 0 && slice_state_has_available(state)) { - if (GPR_SLICE_LENGTH(state->slices[state->last_slice]) > bytes) { - state->working_slice = state->slices[state->last_slice]; - state->working_slice_valid = 1; - /* TODO(klempner): Combine these into a single operation that doesn't need - to refcount */ - gpr_slice_unref(gpr_slice_split_tail( - &state->slices[state->last_slice], - GPR_SLICE_LENGTH(state->slices[state->last_slice]) - bytes)); - bytes = 0; - } else { - bytes -= GPR_SLICE_LENGTH(state->slices[state->last_slice]); - gpr_slice_unref(state->slices[state->last_slice]); - --state->last_slice; - if (state->last_slice == -1) { - state->first_slice = -1; - } - } - } -} - typedef struct { grpc_endpoint base; grpc_fd *em_fd; @@ -273,80 +72,111 @@ typedef struct { size_t slice_size; gpr_refcount refcount; - grpc_endpoint_read_cb read_cb; - void *read_user_data; - grpc_endpoint_write_cb write_cb; - void *write_user_data; + gpr_slice_buffer *incoming_buffer; + gpr_slice_buffer *outgoing_buffer; + /** slice within outgoing_buffer to write next */ + size_t outgoing_slice_idx; + /** byte within outgoing_buffer->slices[outgoing_slice_idx] to write next */ + size_t outgoing_byte_idx; - grpc_tcp_slice_state write_state; + grpc_iomgr_closure *read_cb; + grpc_iomgr_closure *write_cb; grpc_iomgr_closure read_closure; grpc_iomgr_closure write_closure; - grpc_iomgr_closure handle_read_closure; - char *peer_string; } grpc_tcp; -static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success); -static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success); +static void tcp_handle_read(void *arg /* grpc_tcp */, int success); +static void tcp_handle_write(void *arg /* grpc_tcp */, int success); -static void grpc_tcp_shutdown(grpc_endpoint *ep) { +static void tcp_shutdown(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_fd_shutdown(tcp->em_fd); } -static void grpc_tcp_unref(grpc_tcp *tcp) { - int refcount_zero = gpr_unref(&tcp->refcount); - if (refcount_zero) { - grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan"); - gpr_free(tcp->peer_string); - gpr_free(tcp); +static void tcp_free(grpc_tcp *tcp) { + grpc_fd_orphan(tcp->em_fd, NULL, "tcp_unref_orphan"); + gpr_free(tcp->peer_string); + gpr_free(tcp); +} + +/*#define GRPC_TCP_REFCOUNT_DEBUG*/ +#ifdef GRPC_TCP_REFCOUNT_DEBUG +#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) +#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) +static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, + reason, tcp->refcount.count, tcp->refcount.count - 1); + if (gpr_unref(&tcp->refcount)) { + tcp_free(tcp); } } -static void grpc_tcp_destroy(grpc_endpoint *ep) { +static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, + reason, tcp->refcount.count, tcp->refcount.count + 1); + gpr_ref(&tcp->refcount); +} +#else +#define TCP_UNREF(tcp, reason) tcp_unref((tcp)) +#define TCP_REF(tcp, reason) tcp_ref((tcp)) +static void tcp_unref(grpc_tcp *tcp) { + if (gpr_unref(&tcp->refcount)) { + tcp_free(tcp); + } +} + +static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } +#endif + +static void tcp_destroy(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_tcp_unref(tcp); + TCP_UNREF(tcp, "destroy"); } -static void call_read_cb(grpc_tcp *tcp, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status status) { - grpc_endpoint_read_cb cb = tcp->read_cb; +static void call_read_cb(grpc_tcp *tcp, int success) { + grpc_iomgr_closure *cb = tcp->read_cb; if (grpc_tcp_trace) { size_t i; - gpr_log(GPR_DEBUG, "read: status=%d", status); - for (i = 0; i < nslices; i++) { - char *dump = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + gpr_log(GPR_DEBUG, "read: success=%d", success); + for (i = 0; i < tcp->incoming_buffer->count; i++) { + char *dump = gpr_dump_slice(tcp->incoming_buffer->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p: %s", tcp, dump); gpr_free(dump); } } tcp->read_cb = NULL; - cb(tcp->read_user_data, slices, nslices, status); + tcp->incoming_buffer = NULL; + cb->cb(cb->cb_arg, success); } -#define INLINE_SLICE_BUFFER_SIZE 8 #define MAX_READ_IOVEC 4 -static void grpc_tcp_continue_read(grpc_tcp *tcp) { - gpr_slice static_read_slices[INLINE_SLICE_BUFFER_SIZE]; +static void tcp_continue_read(grpc_tcp *tcp) { struct msghdr msg; struct iovec iov[MAX_READ_IOVEC]; ssize_t read_bytes; - ssize_t allocated_bytes; - struct grpc_tcp_slice_state read_state; - gpr_slice *final_slices; - size_t final_nslices; + size_t i; GPR_ASSERT(!tcp->finished_edge); + GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC); + GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC); GRPC_TIMER_BEGIN(GRPC_PTAG_HANDLE_READ, 0); - slice_state_init(&read_state, static_read_slices, INLINE_SLICE_BUFFER_SIZE, - 0); - allocated_bytes = slice_state_append_blocks_into_iovec( - &read_state, iov, tcp->iov_size, tcp->slice_size); + while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) { + gpr_slice_buffer_add_indexed(tcp->incoming_buffer, + gpr_slice_malloc(tcp->slice_size)); + } + for (i = 0; i < tcp->incoming_buffer->count; i++) { + iov[i].iov_base = GPR_SLICE_START_PTR(tcp->incoming_buffer->slices[i]); + iov[i].iov_len = GPR_SLICE_LENGTH(tcp->incoming_buffer->slices[i]); + } msg.msg_name = NULL; msg.msg_namelen = 0; @@ -362,106 +192,105 @@ static void grpc_tcp_continue_read(grpc_tcp *tcp) { } while (read_bytes < 0 && errno == EINTR); GRPC_TIMER_END(GRPC_PTAG_RECVMSG, 0); - if (read_bytes < allocated_bytes) { - /* TODO(klempner): Consider a second read first, in hopes of getting a - * quick EAGAIN and saving a bunch of allocations. */ - slice_state_remove_last(&read_state, read_bytes < 0 - ? allocated_bytes - : allocated_bytes - read_bytes); - } - if (read_bytes < 0) { - /* NB: After calling the user_cb a parallel call of the read handler may + /* NB: After calling call_read_cb a parallel call of the read handler may * be running. */ if (errno == EAGAIN) { if (tcp->iov_size > 1) { tcp->iov_size /= 2; } - if (slice_state_has_available(&read_state)) { - /* TODO(klempner): We should probably do the call into the application - without all this junk on the stack */ - /* FIXME(klempner): Refcount properly */ - slice_state_transfer_ownership(&read_state, &final_slices, - &final_nslices); - tcp->finished_edge = 1; - call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_OK); - slice_state_destroy(&read_state); - grpc_tcp_unref(tcp); - } else { - /* We've consumed the edge, request a new one */ - slice_state_destroy(&read_state); - grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); - } + /* We've consumed the edge, request a new one */ + grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); } else { /* TODO(klempner): Log interesting errors */ - call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_ERROR); - slice_state_destroy(&read_state); - grpc_tcp_unref(tcp); + gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); + call_read_cb(tcp, 0); + TCP_UNREF(tcp, "read"); } } else if (read_bytes == 0) { /* 0 read size ==> end of stream */ - if (slice_state_has_available(&read_state)) { - /* there were bytes already read: pass them up to the application */ - slice_state_transfer_ownership(&read_state, &final_slices, - &final_nslices); - call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_EOF); - } else { - call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_EOF); - } - slice_state_destroy(&read_state); - grpc_tcp_unref(tcp); + gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); + call_read_cb(tcp, 0); + TCP_UNREF(tcp, "read"); } else { - if (tcp->iov_size < MAX_READ_IOVEC) { + GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length); + if ((size_t)read_bytes < tcp->incoming_buffer->length) { + gpr_slice_buffer_trim_end(tcp->incoming_buffer, + tcp->incoming_buffer->length - read_bytes); + } else if (tcp->iov_size < MAX_READ_IOVEC) { ++tcp->iov_size; } - GPR_ASSERT(slice_state_has_available(&read_state)); - slice_state_transfer_ownership(&read_state, &final_slices, &final_nslices); - call_read_cb(tcp, final_slices, final_nslices, GRPC_ENDPOINT_CB_OK); - slice_state_destroy(&read_state); - grpc_tcp_unref(tcp); + GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length); + call_read_cb(tcp, 1); + TCP_UNREF(tcp, "read"); } GRPC_TIMER_END(GRPC_PTAG_HANDLE_READ, 0); } -static void grpc_tcp_handle_read(void *arg /* grpc_tcp */, int success) { +static void tcp_handle_read(void *arg /* grpc_tcp */, int success) { grpc_tcp *tcp = (grpc_tcp *)arg; GPR_ASSERT(!tcp->finished_edge); if (!success) { - call_read_cb(tcp, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); - grpc_tcp_unref(tcp); + gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); + call_read_cb(tcp, 0); + TCP_UNREF(tcp, "read"); } else { - grpc_tcp_continue_read(tcp); + tcp_continue_read(tcp); } } -static void grpc_tcp_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *user_data) { +static grpc_endpoint_op_status tcp_read(grpc_endpoint *ep, + gpr_slice_buffer *incoming_buffer, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; GPR_ASSERT(tcp->read_cb == NULL); tcp->read_cb = cb; - tcp->read_user_data = user_data; - gpr_ref(&tcp->refcount); + tcp->incoming_buffer = incoming_buffer; + gpr_slice_buffer_reset_and_unref(incoming_buffer); + TCP_REF(tcp, "read"); if (tcp->finished_edge) { tcp->finished_edge = 0; grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); } else { - tcp->handle_read_closure.cb_arg = tcp; - grpc_iomgr_add_delayed_callback(&tcp->handle_read_closure, 1); + grpc_iomgr_add_delayed_callback(&tcp->read_closure, 1); } + /* TODO(ctiller): immediate return */ + return GRPC_ENDPOINT_PENDING; } #define MAX_WRITE_IOVEC 16 -static grpc_endpoint_write_status grpc_tcp_flush(grpc_tcp *tcp) { +static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; int iov_size; ssize_t sent_length; - grpc_tcp_slice_state *state = &tcp->write_state; + ssize_t sending_length; + ssize_t trailing; + ssize_t unwind_slice_idx; + ssize_t unwind_byte_idx; for (;;) { - iov_size = slice_state_to_iovec(state, iov, MAX_WRITE_IOVEC); + sending_length = 0; + unwind_slice_idx = tcp->outgoing_slice_idx; + unwind_byte_idx = tcp->outgoing_byte_idx; + for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count && + iov_size != MAX_WRITE_IOVEC; + iov_size++) { + iov[iov_size].iov_base = + GPR_SLICE_START_PTR( + tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) + + tcp->outgoing_byte_idx; + iov[iov_size].iov_len = + GPR_SLICE_LENGTH( + tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) - + tcp->outgoing_byte_idx; + sending_length += iov[iov_size].iov_len; + tcp->outgoing_slice_idx++; + tcp->outgoing_byte_idx = 0; + } + GPR_ASSERT(iov_size > 0); msg.msg_name = NULL; msg.msg_namelen = 0; @@ -480,70 +309,75 @@ static grpc_endpoint_write_status grpc_tcp_flush(grpc_tcp *tcp) { if (sent_length < 0) { if (errno == EAGAIN) { - return GRPC_ENDPOINT_WRITE_PENDING; + tcp->outgoing_slice_idx = unwind_slice_idx; + tcp->outgoing_byte_idx = unwind_byte_idx; + return GRPC_ENDPOINT_PENDING; } else { /* TODO(klempner): Log some of these */ - slice_state_destroy(state); - return GRPC_ENDPOINT_WRITE_ERROR; + return GRPC_ENDPOINT_ERROR; } } - /* TODO(klempner): Probably better to batch this after we finish flushing */ - slice_state_remove_prefix(state, sent_length); + GPR_ASSERT(tcp->outgoing_byte_idx == 0); + trailing = sending_length - sent_length; + while (trailing > 0) { + ssize_t slice_length; + + tcp->outgoing_slice_idx--; + slice_length = GPR_SLICE_LENGTH( + tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]); + if (slice_length > trailing) { + tcp->outgoing_byte_idx = slice_length - trailing; + break; + } else { + trailing -= slice_length; + } + } - if (!slice_state_has_available(state)) { - return GRPC_ENDPOINT_WRITE_DONE; + if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) { + return GRPC_ENDPOINT_DONE; } }; } -static void grpc_tcp_handle_write(void *arg /* grpc_tcp */, int success) { +static void tcp_handle_write(void *arg /* grpc_tcp */, int success) { grpc_tcp *tcp = (grpc_tcp *)arg; - grpc_endpoint_write_status write_status; - grpc_endpoint_cb_status cb_status; - grpc_endpoint_write_cb cb; + grpc_endpoint_op_status status; + grpc_iomgr_closure *cb; if (!success) { - slice_state_destroy(&tcp->write_state); cb = tcp->write_cb; tcp->write_cb = NULL; - cb(tcp->write_user_data, GRPC_ENDPOINT_CB_SHUTDOWN); - grpc_tcp_unref(tcp); + cb->cb(cb->cb_arg, 0); + TCP_UNREF(tcp, "write"); return; } GRPC_TIMER_BEGIN(GRPC_PTAG_TCP_CB_WRITE, 0); - write_status = grpc_tcp_flush(tcp); - if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { + status = tcp_flush(tcp); + if (status == GRPC_ENDPOINT_PENDING) { grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure); } else { - slice_state_destroy(&tcp->write_state); - if (write_status == GRPC_ENDPOINT_WRITE_DONE) { - cb_status = GRPC_ENDPOINT_CB_OK; - } else { - cb_status = GRPC_ENDPOINT_CB_ERROR; - } cb = tcp->write_cb; tcp->write_cb = NULL; - cb(tcp->write_user_data, cb_status); - grpc_tcp_unref(tcp); + cb->cb(cb->cb_arg, status == GRPC_ENDPOINT_DONE); + TCP_UNREF(tcp, "write"); } GRPC_TIMER_END(GRPC_PTAG_TCP_CB_WRITE, 0); } -static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { +static grpc_endpoint_op_status tcp_write(grpc_endpoint *ep, + gpr_slice_buffer *buf, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; - grpc_endpoint_write_status status; + grpc_endpoint_op_status status; if (grpc_tcp_trace) { size_t i; - for (i = 0; i < nslices; i++) { - char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < buf->count; i++) { + char *data = + gpr_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p: %s", tcp, data); gpr_free(data); } @@ -551,15 +385,19 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, GRPC_TIMER_BEGIN(GRPC_PTAG_TCP_WRITE, 0); GPR_ASSERT(tcp->write_cb == NULL); - slice_state_init(&tcp->write_state, slices, nslices, nslices); - status = grpc_tcp_flush(tcp); - if (status == GRPC_ENDPOINT_WRITE_PENDING) { - /* TODO(klempner): Consider inlining rather than malloc for small nslices */ - slice_state_realloc(&tcp->write_state, nslices); - gpr_ref(&tcp->refcount); + if (buf->length == 0) { + GRPC_TIMER_END(GRPC_PTAG_TCP_WRITE, 0); + return GRPC_ENDPOINT_DONE; + } + tcp->outgoing_buffer = buf; + tcp->outgoing_slice_idx = 0; + tcp->outgoing_byte_idx = 0; + + status = tcp_flush(tcp); + if (status == GRPC_ENDPOINT_PENDING) { + TCP_REF(tcp, "write"); tcp->write_cb = cb; - tcp->write_user_data = user_data; grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_closure); } @@ -567,27 +405,25 @@ static grpc_endpoint_write_status grpc_tcp_write(grpc_endpoint *ep, return status; } -static void grpc_tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { +static void tcp_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_pollset_add_fd(pollset, tcp->em_fd); } -static void grpc_tcp_add_to_pollset_set(grpc_endpoint *ep, - grpc_pollset_set *pollset_set) { +static void tcp_add_to_pollset_set(grpc_endpoint *ep, + grpc_pollset_set *pollset_set) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_pollset_set_add_fd(pollset_set, tcp->em_fd); } -static char *grpc_tcp_get_peer(grpc_endpoint *ep) { +static char *tcp_get_peer(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; return gpr_strdup(tcp->peer_string); } static const grpc_endpoint_vtable vtable = { - grpc_tcp_notify_on_read, grpc_tcp_write, - grpc_tcp_add_to_pollset, grpc_tcp_add_to_pollset_set, - grpc_tcp_shutdown, grpc_tcp_destroy, - grpc_tcp_get_peer}; + tcp_read, tcp_write, tcp_add_to_pollset, tcp_add_to_pollset_set, + tcp_shutdown, tcp_destroy, tcp_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, const char *peer_string) { @@ -597,21 +433,18 @@ grpc_endpoint *grpc_tcp_create(grpc_fd *em_fd, size_t slice_size, tcp->fd = em_fd->fd; tcp->read_cb = NULL; tcp->write_cb = NULL; - tcp->read_user_data = NULL; - tcp->write_user_data = NULL; + tcp->incoming_buffer = NULL; tcp->slice_size = slice_size; tcp->iov_size = 1; tcp->finished_edge = 1; - slice_state_init(&tcp->write_state, NULL, 0, 0); /* paired with unref in grpc_tcp_destroy */ gpr_ref_init(&tcp->refcount, 1); tcp->em_fd = em_fd; - tcp->read_closure.cb = grpc_tcp_handle_read; + tcp->read_closure.cb = tcp_handle_read; tcp->read_closure.cb_arg = tcp; - tcp->write_closure.cb = grpc_tcp_handle_write; + tcp->write_closure.cb = tcp_handle_write; tcp->write_closure.cb_arg = tcp; - tcp->handle_read_closure.cb = grpc_tcp_handle_read; return &tcp->base; } diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index 901793ec43..58f9160ef9 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -82,13 +82,11 @@ typedef struct grpc_tcp { /* Refcounting how many operations are in progress. */ gpr_refcount refcount; - grpc_endpoint_read_cb read_cb; - void *read_user_data; + grpc_iomgr_closure *read_cb; + grpc_iomgr_closure *write_cb; gpr_slice read_slice; - - grpc_endpoint_write_cb write_cb; - void *write_user_data; - gpr_slice_buffer write_slices; + gpr_slice_buffer *write_slices; + gpr_slice_buffer *read_slices; /* The IO Completion Port runs from another thread. We need some mechanism to protect ourselves when requesting a shutdown. */ @@ -98,34 +96,55 @@ typedef struct grpc_tcp { char *peer_string; } grpc_tcp; -static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } +static void tcp_free(grpc_tcp *tcp) { + grpc_winsocket_orphan(tcp->socket); + gpr_mu_destroy(&tcp->mu); + gpr_free(tcp->peer_string); + gpr_free(tcp); +} + +/*#define GRPC_TCP_REFCOUNT_DEBUG*/ +#ifdef GRPC_TCP_REFCOUNT_DEBUG +#define TCP_UNREF(tcp, reason) tcp_unref((tcp), (reason), __FILE__, __LINE__) +#define TCP_REF(tcp, reason) tcp_ref((tcp), (reason), __FILE__, __LINE__) +static void tcp_unref(grpc_tcp *tcp, const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP unref %p : %s %d -> %d", tcp, + reason, tcp->refcount.count, tcp->refcount.count - 1); + if (gpr_unref(&tcp->refcount)) { + tcp_free(tcp); + } +} +static void tcp_ref(grpc_tcp *tcp, const char *reason, const char *file, + int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "TCP ref %p : %s %d -> %d", tcp, + reason, tcp->refcount.count, tcp->refcount.count + 1); + gpr_ref(&tcp->refcount); +} +#else +#define TCP_UNREF(tcp, reason) tcp_unref((tcp)) +#define TCP_REF(tcp, reason) tcp_ref((tcp)) static void tcp_unref(grpc_tcp *tcp) { if (gpr_unref(&tcp->refcount)) { - gpr_slice_buffer_destroy(&tcp->write_slices); - grpc_winsocket_orphan(tcp->socket); - gpr_mu_destroy(&tcp->mu); - gpr_free(tcp->peer_string); - gpr_free(tcp); + tcp_free(tcp); } } +static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } +#endif + /* Asynchronous callback from the IOCP, or the background thread. */ -static void on_read(void *tcpp, int from_iocp) { - grpc_tcp *tcp = (grpc_tcp *)tcpp; +static int on_read(grpc_tcp *tcp, int from_iocp) { grpc_winsocket *socket = tcp->socket; gpr_slice sub; gpr_slice *slice = NULL; size_t nslices = 0; - grpc_endpoint_cb_status status; - grpc_endpoint_read_cb cb; + int success; grpc_winsocket_callback_info *info = &socket->read_info; - void *opaque = tcp->read_user_data; int do_abort = 0; gpr_mu_lock(&tcp->mu); - cb = tcp->read_cb; - tcp->read_cb = NULL; if (!from_iocp || tcp->shutting_down) { /* If we are here with from_iocp set to true, it means we got raced to shutting down the endpoint. No actual abort callback will happen @@ -139,9 +158,7 @@ static void on_read(void *tcpp, int from_iocp) { tcp->socket->read_info.outstanding = 0; gpr_slice_unref(tcp->read_slice); } - tcp_unref(tcp); - if (cb) cb(opaque, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); - return; + return 0; } GPR_ASSERT(tcp->socket->read_info.outstanding); @@ -152,28 +169,38 @@ static void on_read(void *tcpp, int from_iocp) { gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); gpr_free(utf8_message); } + success = 0; gpr_slice_unref(tcp->read_slice); - status = GRPC_ENDPOINT_CB_ERROR; } else { if (info->bytes_transfered != 0) { sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); - status = GRPC_ENDPOINT_CB_OK; - slice = ⊂ - nslices = 1; + gpr_slice_buffer_add(tcp->read_slices, sub); + success = 1; } else { gpr_slice_unref(tcp->read_slice); - status = GRPC_ENDPOINT_CB_EOF; + success = 0; } } tcp->socket->read_info.outstanding = 0; - tcp_unref(tcp); - cb(opaque, slice, nslices, status); + return success; +} + +static void on_read_cb(void *tcpp, int from_iocp) { + grpc_tcp *tcp = tcpp; + grpc_iomgr_closure *cb = tcp->read_cb; + int success = on_read(tcp, from_iocp); + tcp->read_cb = NULL; + TCP_UNREF(tcp, "read"); + if (cb) { + cb->cb(cb->cb_arg, success); + } } -static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, - void *arg) { +static grpc_endpoint_op_status win_read(grpc_endpoint *ep, + gpr_slice_buffer *read_slices, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->read_info; @@ -184,13 +211,15 @@ static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, GPR_ASSERT(!tcp->socket->read_info.outstanding); if (tcp->shutting_down) { - cb(arg, NULL, 0, GRPC_ENDPOINT_CB_SHUTDOWN); - return; + return GRPC_ENDPOINT_ERROR; } - tcp_ref(tcp); + + TCP_REF(tcp, "read"); + tcp->socket->read_info.outstanding = 1; tcp->read_cb = cb; - tcp->read_user_data = arg; + tcp->read_slices = read_slices; + gpr_slice_buffer_reset_and_unref(read_slices); tcp->read_slice = gpr_slice_malloc(8192); @@ -204,10 +233,11 @@ static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, /* Did we get data immediately ? Yay. */ if (info->wsa_error != WSAEWOULDBLOCK) { + int ok; info->bytes_transfered = bytes_read; - /* This might heavily recurse. */ - on_read(tcp, 1); - return; + ok = on_read(tcp, 1); + TCP_UNREF(tcp, "read"); + return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } /* Otherwise, let's retry, by queuing a read. */ @@ -218,13 +248,15 @@ static void win_notify_on_read(grpc_endpoint *ep, grpc_endpoint_read_cb cb, if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { + int ok; info->wsa_error = wsa_error; - on_read(tcp, 1); - return; + ok = on_read(tcp, 1); + return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } } - grpc_socket_notify_on_read(tcp->socket, on_read, tcp); + grpc_socket_notify_on_read(tcp->socket, on_read_cb, tcp); + return GRPC_ENDPOINT_PENDING; } /* Asynchronous callback from the IOCP, or the background thread. */ @@ -232,9 +264,8 @@ static void on_write(void *tcpp, int from_iocp) { grpc_tcp *tcp = (grpc_tcp *)tcpp; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->write_info; - grpc_endpoint_cb_status status = GRPC_ENDPOINT_CB_OK; - grpc_endpoint_write_cb cb; - void *opaque = tcp->write_user_data; + grpc_iomgr_closure *cb; + int success; int do_abort = 0; gpr_mu_lock(&tcp->mu); @@ -251,10 +282,11 @@ static void on_write(void *tcpp, int from_iocp) { if (do_abort) { if (from_iocp) { tcp->socket->write_info.outstanding = 0; - gpr_slice_buffer_reset_and_unref(&tcp->write_slices); } - tcp_unref(tcp); - if (cb) cb(opaque, GRPC_ENDPOINT_CB_SHUTDOWN); + TCP_UNREF(tcp, "write"); + if (cb) { + cb->cb(cb->cb_arg, 0); + } return; } @@ -266,23 +298,22 @@ static void on_write(void *tcpp, int from_iocp) { gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); gpr_free(utf8_message); } - status = GRPC_ENDPOINT_CB_ERROR; + success = 0; } else { - GPR_ASSERT(info->bytes_transfered == tcp->write_slices.length); + GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length); + success = 1; } - gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; - tcp_unref(tcp); - cb(opaque, status); + TCP_UNREF(tcp, "write"); + cb->cb(cb->cb_arg, success); } /* Initiates a write. */ -static grpc_endpoint_write_status win_write(grpc_endpoint *ep, - gpr_slice *slices, size_t nslices, - grpc_endpoint_write_cb cb, - void *arg) { +static grpc_endpoint_op_status win_write(grpc_endpoint *ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *socket = tcp->socket; grpc_winsocket_callback_info *info = &socket->write_info; @@ -295,28 +326,26 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, GPR_ASSERT(!tcp->socket->write_info.outstanding); if (tcp->shutting_down) { - return GRPC_ENDPOINT_WRITE_ERROR; + return GRPC_ENDPOINT_ERROR; } - tcp_ref(tcp); + TCP_REF(tcp, "write"); tcp->socket->write_info.outstanding = 1; tcp->write_cb = cb; - tcp->write_user_data = arg; - - gpr_slice_buffer_addn(&tcp->write_slices, slices, nslices); + tcp->write_slices = slices; - if (tcp->write_slices.count > GPR_ARRAY_SIZE(local_buffers)) { - buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices.count); + if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) { + buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count); allocated = buffers; } - for (i = 0; i < tcp->write_slices.count; i++) { - buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices.slices[i]); - buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices.slices[i]); + for (i = 0; i < tcp->write_slices->count; i++) { + buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]); + buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]); } /* First, let's try a synchronous, non-blocking write. */ - status = WSASend(socket->socket, buffers, tcp->write_slices.count, + status = WSASend(socket->socket, buffers, tcp->write_slices->count, &bytes_sent, 0, NULL, NULL); info->wsa_error = status == 0 ? 0 : WSAGetLastError(); @@ -324,10 +353,10 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, connection that has its send queue filled up. But if we don't, then we can avoid doing an async write operation at all. */ if (info->wsa_error != WSAEWOULDBLOCK) { - grpc_endpoint_write_status ret = GRPC_ENDPOINT_WRITE_ERROR; + grpc_endpoint_op_status ret = GRPC_ENDPOINT_ERROR; if (status == 0) { - ret = GRPC_ENDPOINT_WRITE_DONE; - GPR_ASSERT(bytes_sent == tcp->write_slices.length); + ret = GRPC_ENDPOINT_DONE; + GPR_ASSERT(bytes_sent == tcp->write_slices->length); } else { if (socket->read_info.wsa_error != WSAECONNRESET) { char *utf8_message = gpr_format_message(info->wsa_error); @@ -336,33 +365,31 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, } } if (allocated) gpr_free(allocated); - gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; - tcp_unref(tcp); + TCP_UNREF(tcp, "write"); return ret; } /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same operation, this time asynchronously. */ memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED)); - status = WSASend(socket->socket, buffers, tcp->write_slices.count, + status = WSASend(socket->socket, buffers, tcp->write_slices->count, &bytes_sent, 0, &socket->write_info.overlapped, NULL); if (allocated) gpr_free(allocated); if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { - gpr_slice_buffer_reset_and_unref(&tcp->write_slices); tcp->socket->write_info.outstanding = 0; - tcp_unref(tcp); - return GRPC_ENDPOINT_WRITE_ERROR; + TCP_UNREF(tcp, "write"); + return GRPC_ENDPOINT_ERROR; } } /* As all is now setup, we can now ask for the IOCP notification. It may trigger the callback immediately however, but no matter. */ grpc_socket_notify_on_write(socket, on_write, tcp); - return GRPC_ENDPOINT_WRITE_PENDING; + return GRPC_ENDPOINT_PENDING; } static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *ps) { @@ -387,19 +414,17 @@ static void win_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pss) { concurrent access of the data structure in that regard. */ static void win_shutdown(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; - int extra_refs = 0; gpr_mu_lock(&tcp->mu); /* At that point, what may happen is that we're already inside the IOCP callback. See the comments in on_read and on_write. */ tcp->shutting_down = 1; - extra_refs = grpc_winsocket_shutdown(tcp->socket); - while (extra_refs--) tcp_ref(tcp); + grpc_winsocket_shutdown(tcp->socket); gpr_mu_unlock(&tcp->mu); } static void win_destroy(grpc_endpoint *ep) { grpc_tcp *tcp = (grpc_tcp *)ep; - tcp_unref(tcp); + TCP_UNREF(tcp, "destroy"); } static char *win_get_peer(grpc_endpoint *ep) { @@ -408,8 +433,8 @@ static char *win_get_peer(grpc_endpoint *ep) { } static grpc_endpoint_vtable vtable = { - win_notify_on_read, win_write, win_add_to_pollset, win_add_to_pollset_set, - win_shutdown, win_destroy, win_get_peer}; + win_read, win_write, win_add_to_pollset, win_add_to_pollset_set, + win_shutdown, win_destroy, win_get_peer}; grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { grpc_tcp *tcp = (grpc_tcp *)gpr_malloc(sizeof(grpc_tcp)); @@ -417,7 +442,6 @@ grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) { tcp->base.vtable = &vtable; tcp->socket = socket; gpr_mu_init(&tcp->mu); - gpr_slice_buffer_init(&tcp->write_slices); gpr_ref_init(&tcp->refcount, 1); tcp->peer_string = gpr_strdup(peer_string); return &tcp->base; diff --git a/src/core/security/secure_endpoint.c b/src/core/security/secure_endpoint.c index 81b3e33cb2..b696e384fc 100644 --- a/src/core/security/secure_endpoint.c +++ b/src/core/security/secure_endpoint.c @@ -49,15 +49,15 @@ typedef struct { struct tsi_frame_protector *protector; gpr_mu protector_mu; /* saved upper level callbacks and user_data. */ - grpc_endpoint_read_cb read_cb; - void *read_user_data; - grpc_endpoint_write_cb write_cb; - void *write_user_data; + grpc_iomgr_closure *read_cb; + grpc_iomgr_closure *write_cb; + grpc_iomgr_closure on_read; + gpr_slice_buffer *read_buffer; + gpr_slice_buffer source_buffer; /* saved handshaker leftover data to unprotect. */ gpr_slice_buffer leftover_bytes; /* buffers for read and write */ gpr_slice read_staging_buffer; - gpr_slice_buffer input_buffer; gpr_slice write_staging_buffer; gpr_slice_buffer output_buffer; @@ -67,62 +67,91 @@ typedef struct { int grpc_trace_secure_endpoint = 0; -static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } - static void destroy(secure_endpoint *secure_ep) { secure_endpoint *ep = secure_ep; grpc_endpoint_destroy(ep->wrapped_ep); tsi_frame_protector_destroy(ep->protector); gpr_slice_buffer_destroy(&ep->leftover_bytes); gpr_slice_unref(ep->read_staging_buffer); - gpr_slice_buffer_destroy(&ep->input_buffer); gpr_slice_unref(ep->write_staging_buffer); gpr_slice_buffer_destroy(&ep->output_buffer); + gpr_slice_buffer_destroy(&ep->source_buffer); gpr_mu_destroy(&ep->protector_mu); gpr_free(ep); } +/*#define GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG*/ +#ifdef GRPC_SECURE_ENDPOINT_REFCOUNT_DEBUG +#define SECURE_ENDPOINT_UNREF(ep, reason) \ + secure_endpoint_unref((ep), (reason), __FILE__, __LINE__) +#define SECURE_ENDPOINT_REF(ep, reason) \ + secure_endpoint_ref((ep), (reason), __FILE__, __LINE__) +static void secure_endpoint_unref(secure_endpoint *ep, const char *reason, + const char *file, int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP unref %p : %s %d -> %d", + ep, reason, ep->ref.count, ep->ref.count - 1); + if (gpr_unref(&ep->ref)) { + destroy(ep); + } +} + +static void secure_endpoint_ref(secure_endpoint *ep, const char *reason, + const char *file, int line) { + gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, "SECENDP ref %p : %s %d -> %d", + ep, reason, ep->ref.count, ep->ref.count + 1); + gpr_ref(&ep->ref); +} +#else +#define SECURE_ENDPOINT_UNREF(ep, reason) secure_endpoint_unref((ep)) +#define SECURE_ENDPOINT_REF(ep, reason) secure_endpoint_ref((ep)) static void secure_endpoint_unref(secure_endpoint *ep) { if (gpr_unref(&ep->ref)) { destroy(ep); } } +static void secure_endpoint_ref(secure_endpoint *ep) { gpr_ref(&ep->ref); } +#endif + static void flush_read_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, gpr_uint8 **end) { - gpr_slice_buffer_add(&ep->input_buffer, ep->read_staging_buffer); + gpr_slice_buffer_add(ep->read_buffer, ep->read_staging_buffer); ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); } -static void call_read_cb(secure_endpoint *ep, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static void call_read_cb(secure_endpoint *ep, int success) { if (grpc_trace_secure_endpoint) { size_t i; - for (i = 0; i < nslices; i++) { - char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < ep->read_buffer->count; i++) { + char *data = gpr_dump_slice(ep->read_buffer->slices[i], + GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "READ %p: %s", ep, data); gpr_free(data); } } - ep->read_cb(ep->read_user_data, slices, nslices, error); - secure_endpoint_unref(ep); + ep->read_buffer = NULL; + ep->read_cb->cb(ep->read_cb->cb_arg, success); + SECURE_ENDPOINT_UNREF(ep, "read"); } -static void on_read(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static int on_read(void *user_data, int success) { unsigned i; gpr_uint8 keep_looping = 0; - size_t input_buffer_count = 0; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)user_data; gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->read_staging_buffer); gpr_uint8 *end = GPR_SLICE_END_PTR(ep->read_staging_buffer); + if (!success) { + gpr_slice_buffer_reset_and_unref(ep->read_buffer); + return 0; + } + /* TODO(yangg) check error, maybe bail out early */ - for (i = 0; i < nslices; i++) { - gpr_slice encrypted = slices[i]; + for (i = 0; i < ep->source_buffer.count; i++) { + gpr_slice encrypted = ep->source_buffer.slices[i]; gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(encrypted); size_t message_size = GPR_SLICE_LENGTH(encrypted); @@ -161,7 +190,7 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices, if (cur != GPR_SLICE_START_PTR(ep->read_staging_buffer)) { gpr_slice_buffer_add( - &ep->input_buffer, + ep->read_buffer, gpr_slice_split_head( &ep->read_staging_buffer, (size_t)(cur - GPR_SLICE_START_PTR(ep->read_staging_buffer)))); @@ -169,38 +198,53 @@ static void on_read(void *user_data, gpr_slice *slices, size_t nslices, /* TODO(yangg) experiment with moving this block after read_cb to see if it helps latency */ - for (i = 0; i < nslices; i++) { - gpr_slice_unref(slices[i]); - } + gpr_slice_buffer_reset_and_unref(&ep->source_buffer); if (result != TSI_OK) { - gpr_slice_buffer_reset_and_unref(&ep->input_buffer); - call_read_cb(ep, NULL, 0, GRPC_ENDPOINT_CB_ERROR); - return; + gpr_slice_buffer_reset_and_unref(ep->read_buffer); + return 0; } - /* The upper level will unref the slices. */ - input_buffer_count = ep->input_buffer.count; - ep->input_buffer.count = 0; - call_read_cb(ep, ep->input_buffer.slices, input_buffer_count, error); + + return 1; +} + +static void on_read_cb(void *user_data, int success) { + call_read_cb(user_data, on_read(user_data, success)); } -static void endpoint_notify_on_read(grpc_endpoint *secure_ep, - grpc_endpoint_read_cb cb, void *user_data) { +static grpc_endpoint_op_status endpoint_read(grpc_endpoint *secure_ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { secure_endpoint *ep = (secure_endpoint *)secure_ep; + int immediate_read_success = -1; ep->read_cb = cb; - ep->read_user_data = user_data; - - secure_endpoint_ref(ep); + ep->read_buffer = slices; + gpr_slice_buffer_reset_and_unref(ep->read_buffer); if (ep->leftover_bytes.count) { - size_t leftover_nslices = ep->leftover_bytes.count; - ep->leftover_bytes.count = 0; - on_read(ep, ep->leftover_bytes.slices, leftover_nslices, - GRPC_ENDPOINT_CB_OK); - return; + gpr_slice_buffer_swap(&ep->leftover_bytes, &ep->source_buffer); + GPR_ASSERT(ep->leftover_bytes.count == 0); + return on_read(ep, 1) ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } - grpc_endpoint_notify_on_read(ep->wrapped_ep, on_read, ep); + SECURE_ENDPOINT_REF(ep, "read"); + + switch ( + grpc_endpoint_read(ep->wrapped_ep, &ep->source_buffer, &ep->on_read)) { + case GRPC_ENDPOINT_DONE: + immediate_read_success = on_read(ep, 1); + break; + case GRPC_ENDPOINT_PENDING: + return GRPC_ENDPOINT_PENDING; + case GRPC_ENDPOINT_ERROR: + immediate_read_success = on_read(ep, 0); + break; + } + + GPR_ASSERT(immediate_read_success != -1); + SECURE_ENDPOINT_UNREF(ep, "read"); + + return immediate_read_success ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, @@ -211,36 +255,28 @@ static void flush_write_staging_buffer(secure_endpoint *ep, gpr_uint8 **cur, *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); } -static void on_write(void *data, grpc_endpoint_cb_status error) { - secure_endpoint *ep = data; - ep->write_cb(ep->write_user_data, error); - secure_endpoint_unref(ep); -} - -static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, - gpr_slice *slices, - size_t nslices, - grpc_endpoint_write_cb cb, - void *user_data) { +static grpc_endpoint_op_status endpoint_write(grpc_endpoint *secure_ep, + gpr_slice_buffer *slices, + grpc_iomgr_closure *cb) { unsigned i; - size_t output_buffer_count = 0; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)secure_ep; gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer); gpr_uint8 *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); - grpc_endpoint_write_status status; - GPR_ASSERT(ep->output_buffer.count == 0); + + gpr_slice_buffer_reset_and_unref(&ep->output_buffer); if (grpc_trace_secure_endpoint) { - for (i = 0; i < nslices; i++) { - char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); + for (i = 0; i < slices->count; i++) { + char *data = + gpr_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data); gpr_free(data); } } - for (i = 0; i < nslices; i++) { - gpr_slice plain = slices[i]; + for (i = 0; i < slices->count; i++) { + gpr_slice plain = slices->slices[i]; gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(plain); size_t message_size = GPR_SLICE_LENGTH(plain); while (message_size > 0) { @@ -290,29 +326,13 @@ static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, } } - for (i = 0; i < nslices; i++) { - gpr_slice_unref(slices[i]); - } - if (result != TSI_OK) { /* TODO(yangg) do different things according to the error type? */ gpr_slice_buffer_reset_and_unref(&ep->output_buffer); - return GRPC_ENDPOINT_WRITE_ERROR; + return GRPC_ENDPOINT_ERROR; } - /* clear output_buffer and let the lower level handle its slices. */ - output_buffer_count = ep->output_buffer.count; - ep->output_buffer.count = 0; - ep->write_cb = cb; - ep->write_user_data = user_data; - /* Need to keep the endpoint alive across a transport */ - secure_endpoint_ref(ep); - status = grpc_endpoint_write(ep->wrapped_ep, ep->output_buffer.slices, - output_buffer_count, on_write, ep); - if (status != GRPC_ENDPOINT_WRITE_PENDING) { - secure_endpoint_unref(ep); - } - return status; + return grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb); } static void endpoint_shutdown(grpc_endpoint *secure_ep) { @@ -320,9 +340,9 @@ static void endpoint_shutdown(grpc_endpoint *secure_ep) { grpc_endpoint_shutdown(ep->wrapped_ep); } -static void endpoint_unref(grpc_endpoint *secure_ep) { +static void endpoint_destroy(grpc_endpoint *secure_ep) { secure_endpoint *ep = (secure_endpoint *)secure_ep; - secure_endpoint_unref(ep); + SECURE_ENDPOINT_UNREF(ep, "destroy"); } static void endpoint_add_to_pollset(grpc_endpoint *secure_ep, @@ -343,9 +363,9 @@ static char *endpoint_get_peer(grpc_endpoint *secure_ep) { } static const grpc_endpoint_vtable vtable = { - endpoint_notify_on_read, endpoint_write, + endpoint_read, endpoint_write, endpoint_add_to_pollset, endpoint_add_to_pollset_set, - endpoint_shutdown, endpoint_unref, + endpoint_shutdown, endpoint_destroy, endpoint_get_peer}; grpc_endpoint *grpc_secure_endpoint_create( @@ -363,8 +383,10 @@ grpc_endpoint *grpc_secure_endpoint_create( } ep->write_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); ep->read_staging_buffer = gpr_slice_malloc(STAGING_BUFFER_SIZE); - gpr_slice_buffer_init(&ep->input_buffer); gpr_slice_buffer_init(&ep->output_buffer); + gpr_slice_buffer_init(&ep->source_buffer); + ep->read_buffer = NULL; + grpc_iomgr_closure_init(&ep->on_read, on_read_cb, ep); gpr_mu_init(&ep->protector_mu); gpr_ref_init(&ep->ref, 1); return &ep->base; diff --git a/src/core/security/secure_transport_setup.c b/src/core/security/secure_transport_setup.c index 0c3572b53c..bf0079577e 100644 --- a/src/core/security/secure_transport_setup.c +++ b/src/core/security/secure_transport_setup.c @@ -50,16 +50,17 @@ typedef struct { grpc_endpoint *wrapped_endpoint; grpc_endpoint *secure_endpoint; gpr_slice_buffer left_overs; + gpr_slice_buffer incoming; + gpr_slice_buffer outgoing; grpc_secure_transport_setup_done_cb cb; void *user_data; + grpc_iomgr_closure on_handshake_data_sent_to_peer; + grpc_iomgr_closure on_handshake_data_received_from_peer; } grpc_secure_transport_setup; -static void on_handshake_data_received_from_peer(void *setup, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error); +static void on_handshake_data_received_from_peer(void *setup, int success); -static void on_handshake_data_sent_to_peer(void *setup, - grpc_endpoint_cb_status error); +static void on_handshake_data_sent_to_peer(void *setup, int success); static void secure_transport_setup_done(grpc_secure_transport_setup *s, int is_success) { @@ -78,6 +79,8 @@ static void secure_transport_setup_done(grpc_secure_transport_setup *s, if (s->handshaker != NULL) tsi_handshaker_destroy(s->handshaker); if (s->handshake_buffer != NULL) gpr_free(s->handshake_buffer); gpr_slice_buffer_destroy(&s->left_overs); + gpr_slice_buffer_destroy(&s->outgoing); + gpr_slice_buffer_destroy(&s->incoming); GRPC_SECURITY_CONNECTOR_UNREF(s->connector, "secure_transport_setup"); gpr_free(s); } @@ -102,6 +105,8 @@ static void on_peer_checked(void *user_data, grpc_security_status status) { s->secure_endpoint = grpc_secure_endpoint_create(protector, s->wrapped_endpoint, s->left_overs.slices, s->left_overs.count); + s->left_overs.count = 0; + s->left_overs.length = 0; secure_transport_setup_done(s, 1); return; } @@ -132,7 +137,6 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) { size_t offset = 0; tsi_result result = TSI_OK; gpr_slice to_send; - grpc_endpoint_write_status write_status; do { size_t to_send_size = s->handshake_buffer_size - offset; @@ -155,28 +159,25 @@ static void send_handshake_bytes_to_peer(grpc_secure_transport_setup *s) { to_send = gpr_slice_from_copied_buffer((const char *)s->handshake_buffer, offset); + gpr_slice_buffer_reset_and_unref(&s->outgoing); + gpr_slice_buffer_add(&s->outgoing, to_send); /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ - write_status = grpc_endpoint_write(s->wrapped_endpoint, &to_send, 1, - on_handshake_data_sent_to_peer, s); - if (write_status == GRPC_ENDPOINT_WRITE_ERROR) { - gpr_log(GPR_ERROR, "Could not send handshake data to peer."); - secure_transport_setup_done(s, 0); - } else if (write_status == GRPC_ENDPOINT_WRITE_DONE) { - on_handshake_data_sent_to_peer(s, GRPC_ENDPOINT_CB_OK); - } -} - -static void cleanup_slices(gpr_slice *slices, size_t num_slices) { - size_t i; - for (i = 0; i < num_slices; i++) { - gpr_slice_unref(slices[i]); + switch (grpc_endpoint_write(s->wrapped_endpoint, &s->outgoing, + &s->on_handshake_data_sent_to_peer)) { + case GRPC_ENDPOINT_ERROR: + gpr_log(GPR_ERROR, "Could not send handshake data to peer."); + secure_transport_setup_done(s, 0); + break; + case GRPC_ENDPOINT_DONE: + on_handshake_data_sent_to_peer(s, 1); + break; + case GRPC_ENDPOINT_PENDING: + break; } } -static void on_handshake_data_received_from_peer( - void *setup, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static void on_handshake_data_received_from_peer(void *setup, int success) { grpc_secure_transport_setup *s = setup; size_t consumed_slice_size = 0; tsi_result result = TSI_OK; @@ -184,32 +185,37 @@ static void on_handshake_data_received_from_peer( size_t num_left_overs; int has_left_overs_in_current_slice = 0; - if (error != GRPC_ENDPOINT_CB_OK) { + if (!success) { gpr_log(GPR_ERROR, "Read failed."); - cleanup_slices(slices, nslices); secure_transport_setup_done(s, 0); return; } - for (i = 0; i < nslices; i++) { - consumed_slice_size = GPR_SLICE_LENGTH(slices[i]); + for (i = 0; i < s->incoming.count; i++) { + consumed_slice_size = GPR_SLICE_LENGTH(s->incoming.slices[i]); result = tsi_handshaker_process_bytes_from_peer( - s->handshaker, GPR_SLICE_START_PTR(slices[i]), &consumed_slice_size); + s->handshaker, GPR_SLICE_START_PTR(s->incoming.slices[i]), + &consumed_slice_size); if (!tsi_handshaker_is_in_progress(s->handshaker)) break; } if (tsi_handshaker_is_in_progress(s->handshaker)) { /* We may need more data. */ if (result == TSI_INCOMPLETE_DATA) { - /* TODO(klempner,jboeuf): This should probably use the client setup - deadline */ - grpc_endpoint_notify_on_read(s->wrapped_endpoint, - on_handshake_data_received_from_peer, setup); - cleanup_slices(slices, nslices); + switch (grpc_endpoint_read(s->wrapped_endpoint, &s->incoming, + &s->on_handshake_data_received_from_peer)) { + case GRPC_ENDPOINT_DONE: + on_handshake_data_received_from_peer(s, 1); + break; + case GRPC_ENDPOINT_ERROR: + on_handshake_data_received_from_peer(s, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + } return; } else { send_handshake_bytes_to_peer(s); - cleanup_slices(slices, nslices); return; } } @@ -217,42 +223,40 @@ static void on_handshake_data_received_from_peer( if (result != TSI_OK) { gpr_log(GPR_ERROR, "Handshake failed with error %s", tsi_result_to_string(result)); - cleanup_slices(slices, nslices); secure_transport_setup_done(s, 0); return; } /* Handshake is done and successful this point. */ has_left_overs_in_current_slice = - (consumed_slice_size < GPR_SLICE_LENGTH(slices[i])); - num_left_overs = (has_left_overs_in_current_slice ? 1 : 0) + nslices - i - 1; + (consumed_slice_size < GPR_SLICE_LENGTH(s->incoming.slices[i])); + num_left_overs = + (has_left_overs_in_current_slice ? 1 : 0) + s->incoming.count - i - 1; if (num_left_overs == 0) { - cleanup_slices(slices, nslices); check_peer(s); return; } - cleanup_slices(slices, nslices - num_left_overs); - /* Put the leftovers in our buffer (ownership transfered). */ if (has_left_overs_in_current_slice) { - gpr_slice_buffer_add(&s->left_overs, - gpr_slice_split_tail(&slices[i], consumed_slice_size)); - gpr_slice_unref(slices[i]); /* split_tail above increments refcount. */ + gpr_slice_buffer_add( + &s->left_overs, + gpr_slice_split_tail(&s->incoming.slices[i], consumed_slice_size)); + gpr_slice_unref( + s->incoming.slices[i]); /* split_tail above increments refcount. */ } gpr_slice_buffer_addn( - &s->left_overs, &slices[i + 1], + &s->left_overs, &s->incoming.slices[i + 1], num_left_overs - (size_t)has_left_overs_in_current_slice); check_peer(s); } /* If setup is NULL, the setup is done. */ -static void on_handshake_data_sent_to_peer(void *setup, - grpc_endpoint_cb_status error) { +static void on_handshake_data_sent_to_peer(void *setup, int success) { grpc_secure_transport_setup *s = setup; /* Make sure that write is OK. */ - if (error != GRPC_ENDPOINT_CB_OK) { - gpr_log(GPR_ERROR, "Write failed with error %d.", error); + if (!success) { + gpr_log(GPR_ERROR, "Write failed."); if (setup != NULL) secure_transport_setup_done(s, 0); return; } @@ -261,8 +265,17 @@ static void on_handshake_data_sent_to_peer(void *setup, if (tsi_handshaker_is_in_progress(s->handshaker)) { /* TODO(klempner,jboeuf): This should probably use the client setup deadline */ - grpc_endpoint_notify_on_read(s->wrapped_endpoint, - on_handshake_data_received_from_peer, setup); + switch (grpc_endpoint_read(s->wrapped_endpoint, &s->incoming, + &s->on_handshake_data_received_from_peer)) { + case GRPC_ENDPOINT_ERROR: + on_handshake_data_received_from_peer(s, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + case GRPC_ENDPOINT_DONE: + on_handshake_data_received_from_peer(s, 1); + break; + } } else { check_peer(s); } @@ -288,6 +301,12 @@ void grpc_setup_secure_transport(grpc_security_connector *connector, s->wrapped_endpoint = nonsecure_endpoint; s->user_data = user_data; s->cb = cb; + grpc_iomgr_closure_init(&s->on_handshake_data_sent_to_peer, + on_handshake_data_sent_to_peer, s); + grpc_iomgr_closure_init(&s->on_handshake_data_received_from_peer, + on_handshake_data_received_from_peer, s); gpr_slice_buffer_init(&s->left_overs); + gpr_slice_buffer_init(&s->outgoing); + gpr_slice_buffer_init(&s->incoming); send_handshake_bytes_to_peer(s); } diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c index 987d5cb9b5..6482ef9c9f 100644 --- a/src/core/support/slice_buffer.c +++ b/src/core/support/slice_buffer.c @@ -207,3 +207,25 @@ void gpr_slice_buffer_move_into(gpr_slice_buffer *src, gpr_slice_buffer *dst) { src->count = 0; src->length = 0; } + +void gpr_slice_buffer_trim_end(gpr_slice_buffer *sb, size_t n) { + GPR_ASSERT(n <= sb->length); + sb->length -= n; + for (;;) { + size_t idx = sb->count - 1; + gpr_slice slice = sb->slices[idx]; + size_t slice_len = GPR_SLICE_LENGTH(slice); + if (slice_len > n) { + sb->slices[idx] = gpr_slice_sub_no_ref(slice, 0, slice_len - n); + return; + } else if (slice_len == n) { + gpr_slice_unref(slice); + sb->count = idx; + return; + } else { + gpr_slice_unref(slice); + n -= slice_len; + sb->count = idx; + } + } +} diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h index 42cf0ecd5b..a1b773b1ca 100644 --- a/src/core/transport/chttp2/internal.h +++ b/src/core/transport/chttp2/internal.h @@ -214,6 +214,8 @@ typedef struct { grpc_chttp2_hpack_compressor hpack_compressor; /** is this a client? */ gpr_uint8 is_client; + /** callback for when writing is done */ + grpc_iomgr_closure done_cb; } grpc_chttp2_transport_writing; struct grpc_chttp2_transport_parsing { @@ -329,8 +331,11 @@ struct grpc_chttp2_transport { /** closure to execute writing */ grpc_iomgr_closure writing_action; - /** closure to start reading from the endpoint */ - grpc_iomgr_closure reading_action; + /** closure to finish reading from the endpoint */ + grpc_iomgr_closure recv_data; + + /** incoming read bytes */ + gpr_slice_buffer read_buffer; /** address to place a newly accepted stream - set and unset by grpc_chttp2_parsing_accept_stream; used by init_stream to @@ -463,8 +468,7 @@ int grpc_chttp2_unlocking_check_writes(grpc_chttp2_transport_global *global, grpc_chttp2_transport_writing *writing); void grpc_chttp2_perform_writes( grpc_chttp2_transport_writing *transport_writing, grpc_endpoint *endpoint); -void grpc_chttp2_terminate_writing( - grpc_chttp2_transport_writing *transport_writing, int success); +void grpc_chttp2_terminate_writing(void *transport_writing, int success); void grpc_chttp2_cleanup_writing(grpc_chttp2_transport_global *global, grpc_chttp2_transport_writing *writing); diff --git a/src/core/transport/chttp2/writing.c b/src/core/transport/chttp2/writing.c index 123061b3fc..2c8c48f47b 100644 --- a/src/core/transport/chttp2/writing.c +++ b/src/core/transport/chttp2/writing.c @@ -37,7 +37,6 @@ #include static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing); -static void finish_write_cb(void *tw, grpc_endpoint_cb_status write_status); int grpc_chttp2_unlocking_check_writes( grpc_chttp2_transport_global *transport_global, @@ -165,16 +164,15 @@ void grpc_chttp2_perform_writes( GPR_ASSERT(transport_writing->outbuf.count > 0); GPR_ASSERT(endpoint); - switch (grpc_endpoint_write(endpoint, transport_writing->outbuf.slices, - transport_writing->outbuf.count, finish_write_cb, - transport_writing)) { - case GRPC_ENDPOINT_WRITE_DONE: + switch (grpc_endpoint_write(endpoint, &transport_writing->outbuf, + &transport_writing->done_cb)) { + case GRPC_ENDPOINT_DONE: grpc_chttp2_terminate_writing(transport_writing, 1); break; - case GRPC_ENDPOINT_WRITE_ERROR: + case GRPC_ENDPOINT_ERROR: grpc_chttp2_terminate_writing(transport_writing, 0); break; - case GRPC_ENDPOINT_WRITE_PENDING: + case GRPC_ENDPOINT_PENDING: break; } } @@ -209,12 +207,6 @@ static void finalize_outbuf(grpc_chttp2_transport_writing *transport_writing) { } } -static void finish_write_cb(void *tw, grpc_endpoint_cb_status write_status) { - grpc_chttp2_transport_writing *transport_writing = tw; - grpc_chttp2_terminate_writing(transport_writing, - write_status == GRPC_ENDPOINT_CB_OK); -} - void grpc_chttp2_cleanup_writing( grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_writing *transport_writing) { @@ -243,6 +235,5 @@ void grpc_chttp2_cleanup_writing( grpc_chttp2_list_add_read_write_state_changed(transport_global, stream_global); } - transport_writing->outbuf.count = 0; - transport_writing->outbuf.length = 0; + gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf); } diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 1bbd210e46..8caa10c938 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -84,15 +84,13 @@ static void unlock_check_read_write_state(grpc_chttp2_transport *t); /* forward declarations of various callbacks that we'll build closures around */ static void writing_action(void *t, int iomgr_success_ignored); -static void reading_action(void *t, int iomgr_success_ignored); /** Set a transport level setting, and push it to our peer */ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, gpr_uint32 value); /** Endpoint callback to process incoming data */ -static void recv_data(void *tp, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error); +static void recv_data(void *tp, int success); /** Start disconnection chain */ static void drop_connection(grpc_chttp2_transport *t); @@ -143,6 +141,7 @@ static void destruct_transport(grpc_chttp2_transport *t) { grpc_chttp2_hpack_compressor_destroy(&t->writing.hpack_compressor); gpr_slice_buffer_destroy(&t->parsing.qbuf); + gpr_slice_buffer_destroy(&t->read_buffer); grpc_chttp2_hpack_parser_destroy(&t->parsing.hpack_parser); grpc_chttp2_goaway_parser_destroy(&t->parsing.goaway_parser); @@ -249,12 +248,16 @@ static void init_transport(grpc_chttp2_transport *t, gpr_slice_buffer_init(&t->writing.outbuf); grpc_chttp2_hpack_compressor_init(&t->writing.hpack_compressor, mdctx); grpc_iomgr_closure_init(&t->writing_action, writing_action, t); - grpc_iomgr_closure_init(&t->reading_action, reading_action, t); gpr_slice_buffer_init(&t->parsing.qbuf); grpc_chttp2_goaway_parser_init(&t->parsing.goaway_parser); grpc_chttp2_hpack_parser_init(&t->parsing.hpack_parser, t->metadata_context); + grpc_iomgr_closure_init(&t->writing.done_cb, grpc_chttp2_terminate_writing, + &t->writing); + grpc_iomgr_closure_init(&t->recv_data, recv_data, t); + gpr_slice_buffer_init(&t->read_buffer); + if (is_client) { gpr_slice_buffer_add( &t->global.qbuf, @@ -502,8 +505,8 @@ static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id, } } -void grpc_chttp2_terminate_writing( - grpc_chttp2_transport_writing *transport_writing, int success) { +void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { + grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr; grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); lock(t); @@ -1060,74 +1063,76 @@ static void read_error_locked(grpc_chttp2_transport *t) { } /* tcp read callback */ -static void recv_data(void *tp, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { - grpc_chttp2_transport *t = tp; +static int recv_data_loop(grpc_chttp2_transport *t, int *success) { size_t i; - int unref = 0; + int keep_reading = 0; - switch (error) { - case GRPC_ENDPOINT_CB_SHUTDOWN: - case GRPC_ENDPOINT_CB_EOF: - case GRPC_ENDPOINT_CB_ERROR: - lock(t); + lock(t); + i = 0; + GPR_ASSERT(!t->parsing_active); + if (!t->closed) { + t->parsing_active = 1; + /* merge stream lists */ + grpc_chttp2_stream_map_move_into(&t->new_stream_map, + &t->parsing_stream_map); + grpc_chttp2_prepare_to_read(&t->global, &t->parsing); + gpr_mu_unlock(&t->mu); + for (; i < t->read_buffer.count && + grpc_chttp2_perform_read(&t->parsing, t->read_buffer.slices[i]); + i++) + ; + gpr_mu_lock(&t->mu); + if (i != t->read_buffer.count) { drop_connection(t); - read_error_locked(t); - unlock(t); - unref = 1; - for (i = 0; i < nslices; i++) gpr_slice_unref(slices[i]); - break; - case GRPC_ENDPOINT_CB_OK: - lock(t); - i = 0; - GPR_ASSERT(!t->parsing_active); - if (!t->closed) { - t->parsing_active = 1; - /* merge stream lists */ - grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); - grpc_chttp2_prepare_to_read(&t->global, &t->parsing); - gpr_mu_unlock(&t->mu); - for (; i < nslices && grpc_chttp2_perform_read(&t->parsing, slices[i]); - i++) { - gpr_slice_unref(slices[i]); - } - gpr_mu_lock(&t->mu); - if (i != nslices) { - drop_connection(t); - } - /* merge stream lists */ - grpc_chttp2_stream_map_move_into(&t->new_stream_map, - &t->parsing_stream_map); - t->global.concurrent_stream_count = - grpc_chttp2_stream_map_size(&t->parsing_stream_map); - if (t->parsing.initial_window_update != 0) { - grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, - update_global_window, t); - t->parsing.initial_window_update = 0; - } - /* handle higher level things */ - grpc_chttp2_publish_reads(&t->global, &t->parsing); - t->parsing_active = 0; - } - if (i == nslices) { - grpc_chttp2_schedule_closure(&t->global, &t->reading_action, 1); - } else { - read_error_locked(t); - unref = 1; - } - unlock(t); - for (; i < nslices; i++) gpr_slice_unref(slices[i]); - break; + } + /* merge stream lists */ + grpc_chttp2_stream_map_move_into(&t->new_stream_map, + &t->parsing_stream_map); + t->global.concurrent_stream_count = + grpc_chttp2_stream_map_size(&t->parsing_stream_map); + if (t->parsing.initial_window_update != 0) { + grpc_chttp2_stream_map_for_each(&t->parsing_stream_map, + update_global_window, t); + t->parsing.initial_window_update = 0; + } + /* handle higher level things */ + grpc_chttp2_publish_reads(&t->global, &t->parsing); + t->parsing_active = 0; + } + if (!*success || i != t->read_buffer.count) { + drop_connection(t); + read_error_locked(t); + } else { + keep_reading = 1; } - if (unref) { + gpr_slice_buffer_reset_and_unref(&t->read_buffer); + unlock(t); + + if (keep_reading) { + switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { + case GRPC_ENDPOINT_DONE: + *success = 1; + return 1; + case GRPC_ENDPOINT_ERROR: + *success = 0; + return 1; + case GRPC_ENDPOINT_PENDING: + return 0; + } + } else { UNREF_TRANSPORT(t, "recv_data"); + return 0; } + + gpr_log(GPR_ERROR, "should never reach here"); + abort(); } -static void reading_action(void *pt, int iomgr_success_ignored) { - grpc_chttp2_transport *t = pt; - grpc_endpoint_notify_on_read(t->ep, recv_data, t); +static void recv_data(void *tp, int success) { + grpc_chttp2_transport *t = tp; + + while (recv_data_loop(t, &success)) + ; } /* @@ -1240,5 +1245,6 @@ void grpc_chttp2_transport_start_reading(grpc_transport *transport, gpr_slice *slices, size_t nslices) { grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport; REF_TRANSPORT(t, "recv_data"); /* matches unref inside recv_data */ - recv_data(t, slices, nslices, GRPC_ENDPOINT_CB_OK); + gpr_slice_buffer_addn(&t->read_buffer, slices, nslices); + recv_data(t, 1); } diff --git a/test/core/bad_client/bad_client.c b/test/core/bad_client/bad_client.c index 24bf5d3625..1d98879662 100644 --- a/test/core/bad_client/bad_client.c +++ b/test/core/bad_client/bad_client.c @@ -59,7 +59,7 @@ static void thd_func(void *arg) { gpr_event_set(&a->done_thd, (void *)1); } -static void done_write(void *arg, grpc_endpoint_cb_status status) { +static void done_write(void *arg, int success) { thd_args *a = arg; gpr_event_set(&a->done_write, (void *)1); } @@ -85,6 +85,8 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, grpc_mdctx *mdctx = grpc_mdctx_create(); gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); + gpr_slice_buffer outgoing; + grpc_iomgr_closure done_write_closure; hex = gpr_dump(client_payload, client_payload_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); @@ -122,14 +124,18 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, /* Start validator */ gpr_thd_new(&id, thd_func, &a, NULL); + gpr_slice_buffer_init(&outgoing); + gpr_slice_buffer_add(&outgoing, slice); + grpc_iomgr_closure_init(&done_write_closure, done_write, &a); + /* Write data */ - switch (grpc_endpoint_write(sfd.client, &slice, 1, done_write, &a)) { - case GRPC_ENDPOINT_WRITE_DONE: + switch (grpc_endpoint_write(sfd.client, &outgoing, &done_write_closure)) { + case GRPC_ENDPOINT_DONE: done_write(&a, 1); break; - case GRPC_ENDPOINT_WRITE_PENDING: + case GRPC_ENDPOINT_PENDING: break; - case GRPC_ENDPOINT_WRITE_ERROR: + case GRPC_ENDPOINT_ERROR: done_write(&a, 0); break; } @@ -155,6 +161,7 @@ void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, .type == GRPC_OP_COMPLETE); grpc_server_destroy(a.server); grpc_completion_queue_destroy(a.cq); + gpr_slice_buffer_destroy(&outgoing); grpc_shutdown(); } diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c index 6ef8e9ca3b..ef673747a1 100644 --- a/test/core/iomgr/endpoint_tests.c +++ b/test/core/iomgr/endpoint_tests.c @@ -59,8 +59,7 @@ static grpc_pollset *g_pollset; -size_t count_and_unref_slices(gpr_slice *slices, size_t nslices, - int *current_data) { +size_t count_slices(gpr_slice *slices, size_t nslices, int *current_data) { size_t num_bytes = 0; size_t i; size_t j; @@ -72,7 +71,6 @@ size_t count_and_unref_slices(gpr_slice *slices, size_t nslices, *current_data = (*current_data + 1) % 256; } num_bytes += GPR_SLICE_LENGTH(slices[i]); - gpr_slice_unref(slices[i]); } return num_bytes; } @@ -121,86 +119,76 @@ struct read_and_write_test_state { int current_write_data; int read_done; int write_done; + gpr_slice_buffer incoming; + gpr_slice_buffer outgoing; + grpc_iomgr_closure done_read; + grpc_iomgr_closure done_write; }; -static void read_and_write_test_read_handler(void *data, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error) { +static void read_and_write_test_read_handler(void *data, int success) { struct read_and_write_test_state *state = data; - GPR_ASSERT(error != GRPC_ENDPOINT_CB_ERROR); - if (error == GRPC_ENDPOINT_CB_SHUTDOWN) { - gpr_log(GPR_INFO, "Read handler shutdown"); - gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->read_done = 1; - grpc_pollset_kick(g_pollset, NULL); - gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - return; - } - state->bytes_read += - count_and_unref_slices(slices, nslices, &state->current_read_data); - if (state->bytes_read == state->target_bytes) { + state->bytes_read += count_slices( + state->incoming.slices, state->incoming.count, &state->current_read_data); + if (state->bytes_read == state->target_bytes || !success) { gpr_log(GPR_INFO, "Read handler done"); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->read_done = 1; + state->read_done = 1 + success; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - } else { - grpc_endpoint_notify_on_read(state->read_ep, - read_and_write_test_read_handler, data); + } else if (success) { + switch (grpc_endpoint_read(state->read_ep, &state->incoming, + &state->done_read)) { + case GRPC_ENDPOINT_ERROR: + read_and_write_test_read_handler(data, 0); + break; + case GRPC_ENDPOINT_DONE: + read_and_write_test_read_handler(data, 1); + break; + case GRPC_ENDPOINT_PENDING: + break; + } } } -static void read_and_write_test_write_handler(void *data, - grpc_endpoint_cb_status error) { +static void read_and_write_test_write_handler(void *data, int success) { struct read_and_write_test_state *state = data; gpr_slice *slices = NULL; size_t nslices; - grpc_endpoint_write_status write_status; - - GPR_ASSERT(error != GRPC_ENDPOINT_CB_ERROR); - - gpr_log(GPR_DEBUG, "%s: error=%d", "read_and_write_test_write_handler", - error); - - if (error == GRPC_ENDPOINT_CB_SHUTDOWN) { - gpr_log(GPR_INFO, "Write handler shutdown"); - gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->write_done = 1; - grpc_pollset_kick(g_pollset, NULL); - gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - return; - } - - for (;;) { - /* Need to do inline writes until they don't succeed synchronously or we - finish writing */ - state->bytes_written += state->current_write_size; - if (state->target_bytes - state->bytes_written < - state->current_write_size) { - state->current_write_size = state->target_bytes - state->bytes_written; - } - if (state->current_write_size == 0) { - break; - } - - slices = allocate_blocks(state->current_write_size, 8192, &nslices, - &state->current_write_data); - write_status = - grpc_endpoint_write(state->write_ep, slices, nslices, - read_and_write_test_write_handler, state); - gpr_log(GPR_DEBUG, "write_status=%d", write_status); - GPR_ASSERT(write_status != GRPC_ENDPOINT_WRITE_ERROR); - free(slices); - if (write_status == GRPC_ENDPOINT_WRITE_PENDING) { - return; + grpc_endpoint_op_status write_status; + + if (success) { + for (;;) { + /* Need to do inline writes until they don't succeed synchronously or we + finish writing */ + state->bytes_written += state->current_write_size; + if (state->target_bytes - state->bytes_written < + state->current_write_size) { + state->current_write_size = state->target_bytes - state->bytes_written; + } + if (state->current_write_size == 0) { + break; + } + + slices = allocate_blocks(state->current_write_size, 8192, &nslices, + &state->current_write_data); + gpr_slice_buffer_reset_and_unref(&state->outgoing); + gpr_slice_buffer_addn(&state->outgoing, slices, nslices); + write_status = grpc_endpoint_write(state->write_ep, &state->outgoing, + &state->done_write); + gpr_log(GPR_DEBUG, "write_status=%d", write_status); + GPR_ASSERT(write_status != GRPC_ENDPOINT_ERROR); + free(slices); + if (write_status == GRPC_ENDPOINT_PENDING) { + return; + } } + GPR_ASSERT(state->bytes_written == state->target_bytes); } - GPR_ASSERT(state->bytes_written == state->target_bytes); gpr_log(GPR_INFO, "Write handler done"); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - state->write_done = 1; + state->write_done = 1 + success; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); } @@ -234,16 +222,31 @@ static void read_and_write_test(grpc_endpoint_test_config config, state.write_done = 0; state.current_read_data = 0; state.current_write_data = 0; + grpc_iomgr_closure_init(&state.done_read, read_and_write_test_read_handler, + &state); + grpc_iomgr_closure_init(&state.done_write, read_and_write_test_write_handler, + &state); + gpr_slice_buffer_init(&state.outgoing); + gpr_slice_buffer_init(&state.incoming); /* Get started by pretending an initial write completed */ /* NOTE: Sets up initial conditions so we can have the same write handler for the first iteration as for later iterations. It does the right thing even when bytes_written is unsigned. */ state.bytes_written -= state.current_write_size; - read_and_write_test_write_handler(&state, GRPC_ENDPOINT_CB_OK); + read_and_write_test_write_handler(&state, 1); - grpc_endpoint_notify_on_read(state.read_ep, read_and_write_test_read_handler, - &state); + switch ( + grpc_endpoint_read(state.read_ep, &state.incoming, &state.done_read)) { + case GRPC_ENDPOINT_PENDING: + break; + case GRPC_ENDPOINT_ERROR: + read_and_write_test_read_handler(&state, 0); + break; + case GRPC_ENDPOINT_DONE: + read_and_write_test_read_handler(&state, 1); + break; + } if (shutdown) { gpr_log(GPR_DEBUG, "shutdown read"); @@ -263,6 +266,8 @@ static void read_and_write_test(grpc_endpoint_test_config config, grpc_endpoint_destroy(state.read_ep); grpc_endpoint_destroy(state.write_ep); + gpr_slice_buffer_destroy(&state.outgoing); + gpr_slice_buffer_destroy(&state.incoming); end_test(config); } @@ -273,36 +278,40 @@ struct timeout_test_state { typedef struct { int done; grpc_endpoint *ep; + gpr_slice_buffer incoming; + grpc_iomgr_closure done_read; } shutdown_during_write_test_state; -static void shutdown_during_write_test_read_handler( - void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { - size_t i; +static void shutdown_during_write_test_read_handler(void *user_data, + int success) { shutdown_during_write_test_state *st = user_data; - for (i = 0; i < nslices; i++) { - gpr_slice_unref(slices[i]); - } - - if (error != GRPC_ENDPOINT_CB_OK) { + if (!success) { grpc_endpoint_destroy(st->ep); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - st->done = error; + st->done = 1; grpc_pollset_kick(g_pollset, NULL); gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); } else { - grpc_endpoint_notify_on_read( - st->ep, shutdown_during_write_test_read_handler, user_data); + switch (grpc_endpoint_read(st->ep, &st->incoming, &st->done_read)) { + case GRPC_ENDPOINT_PENDING: + break; + case GRPC_ENDPOINT_ERROR: + shutdown_during_write_test_read_handler(user_data, 0); + break; + case GRPC_ENDPOINT_DONE: + shutdown_during_write_test_read_handler(user_data, 1); + break; + } } } -static void shutdown_during_write_test_write_handler( - void *user_data, grpc_endpoint_cb_status error) { +static void shutdown_during_write_test_write_handler(void *user_data, + int success) { shutdown_during_write_test_state *st = user_data; - gpr_log(GPR_INFO, "shutdown_during_write_test_write_handler: error = %d", - error); - if (error == 0) { + gpr_log(GPR_INFO, "shutdown_during_write_test_write_handler: success = %d", + success); + if (success) { /* This happens about 0.5% of the time when run under TSAN, and is entirely legitimate, but means we aren't testing the path we think we are. */ /* TODO(klempner): Change this test to retry the write in that case */ @@ -325,6 +334,8 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, shutdown_during_write_test_state read_st; shutdown_during_write_test_state write_st; gpr_slice *slices; + gpr_slice_buffer outgoing; + grpc_iomgr_closure done_write; grpc_endpoint_test_fixture f = begin_test(config, "shutdown_during_write_test", slice_size); @@ -335,19 +346,26 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, read_st.done = 0; write_st.done = 0; - grpc_endpoint_notify_on_read( - read_st.ep, shutdown_during_write_test_read_handler, &read_st); + grpc_iomgr_closure_init(&done_write, shutdown_during_write_test_write_handler, + &write_st); + grpc_iomgr_closure_init(&read_st.done_read, + shutdown_during_write_test_read_handler, &read_st); + gpr_slice_buffer_init(&read_st.incoming); + gpr_slice_buffer_init(&outgoing); + + GPR_ASSERT(grpc_endpoint_read(read_st.ep, &read_st.incoming, + &read_st.done_read) == GRPC_ENDPOINT_PENDING); for (size = 1;; size *= 2) { slices = allocate_blocks(size, 1, &nblocks, ¤t_data); - switch (grpc_endpoint_write(write_st.ep, slices, nblocks, - shutdown_during_write_test_write_handler, - &write_st)) { - case GRPC_ENDPOINT_WRITE_DONE: + gpr_slice_buffer_reset_and_unref(&outgoing); + gpr_slice_buffer_addn(&outgoing, slices, nblocks); + switch (grpc_endpoint_write(write_st.ep, &outgoing, &done_write)) { + case GRPC_ENDPOINT_DONE: break; - case GRPC_ENDPOINT_WRITE_ERROR: + case GRPC_ENDPOINT_ERROR: gpr_log(GPR_ERROR, "error writing"); abort(); - case GRPC_ENDPOINT_WRITE_PENDING: + case GRPC_ENDPOINT_PENDING: grpc_endpoint_shutdown(write_st.ep); deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); @@ -368,6 +386,8 @@ static void shutdown_during_write_test(grpc_endpoint_test_config config, } gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); gpr_free(slices); + gpr_slice_buffer_destroy(&read_st.incoming); + gpr_slice_buffer_destroy(&outgoing); end_test(config); return; } diff --git a/test/core/iomgr/tcp_posix_test.c b/test/core/iomgr/tcp_posix_test.c index 6ad832231f..8acaa433bb 100644 --- a/test/core/iomgr/tcp_posix_test.c +++ b/test/core/iomgr/tcp_posix_test.c @@ -118,10 +118,12 @@ struct read_socket_state { grpc_endpoint *ep; ssize_t read_bytes; ssize_t target_read_bytes; + gpr_slice_buffer incoming; + grpc_iomgr_closure read_cb; }; -static ssize_t count_and_unref_slices(gpr_slice *slices, size_t nslices, - int *current_data) { +static ssize_t count_slices(gpr_slice *slices, size_t nslices, + int *current_data) { ssize_t num_bytes = 0; unsigned i, j; unsigned char *buf; @@ -132,31 +134,41 @@ static ssize_t count_and_unref_slices(gpr_slice *slices, size_t nslices, *current_data = (*current_data + 1) % 256; } num_bytes += GPR_SLICE_LENGTH(slices[i]); - gpr_slice_unref(slices[i]); } return num_bytes; } -static void read_cb(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { +static void read_cb(void *user_data, int success) { struct read_socket_state *state = (struct read_socket_state *)user_data; ssize_t read_bytes; int current_data; - GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); + GPR_ASSERT(success); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); current_data = state->read_bytes % 256; - read_bytes = count_and_unref_slices(slices, nslices, ¤t_data); + read_bytes = count_slices(state->incoming.slices, state->incoming.count, + ¤t_data); state->read_bytes += read_bytes; gpr_log(GPR_INFO, "Read %d bytes of %d", read_bytes, state->target_read_bytes); if (state->read_bytes >= state->target_read_bytes) { - /* empty */ + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); } else { - grpc_endpoint_notify_on_read(state->ep, read_cb, state); + switch (grpc_endpoint_read(state->ep, &state->incoming, &state->read_cb)) { + case GRPC_ENDPOINT_DONE: + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + read_cb(user_data, 1); + break; + case GRPC_ENDPOINT_ERROR: + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + read_cb(user_data, 0); + break; + case GRPC_ENDPOINT_PENDING: + gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + break; + } } - gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); } /* Write to a socket, then read from it using the grpc_tcp API. */ @@ -181,8 +193,19 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { state.ep = ep; state.read_bytes = 0; state.target_read_bytes = written_bytes; + gpr_slice_buffer_init(&state.incoming); + grpc_iomgr_closure_init(&state.read_cb, read_cb, &state); - grpc_endpoint_notify_on_read(ep, read_cb, &state); + switch (grpc_endpoint_read(ep, &state.incoming, &state.read_cb)) { + case GRPC_ENDPOINT_DONE: + read_cb(&state, 1); + break; + case GRPC_ENDPOINT_ERROR: + read_cb(&state, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + } gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (state.read_bytes < state.target_read_bytes) { @@ -193,6 +216,7 @@ static void read_test(ssize_t num_bytes, ssize_t slice_size) { GPR_ASSERT(state.read_bytes == state.target_read_bytes); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + gpr_slice_buffer_destroy(&state.incoming); grpc_endpoint_destroy(ep); } @@ -219,8 +243,19 @@ static void large_read_test(ssize_t slice_size) { state.ep = ep; state.read_bytes = 0; state.target_read_bytes = written_bytes; + gpr_slice_buffer_init(&state.incoming); + grpc_iomgr_closure_init(&state.read_cb, read_cb, &state); - grpc_endpoint_notify_on_read(ep, read_cb, &state); + switch (grpc_endpoint_read(ep, &state.incoming, &state.read_cb)) { + case GRPC_ENDPOINT_DONE: + read_cb(&state, 1); + break; + case GRPC_ENDPOINT_ERROR: + read_cb(&state, 0); + break; + case GRPC_ENDPOINT_PENDING: + break; + } gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); while (state.read_bytes < state.target_read_bytes) { @@ -231,6 +266,7 @@ static void large_read_test(ssize_t slice_size) { GPR_ASSERT(state.read_bytes == state.target_read_bytes); gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); + gpr_slice_buffer_destroy(&state.incoming); grpc_endpoint_destroy(ep); } @@ -262,8 +298,7 @@ static gpr_slice *allocate_blocks(ssize_t num_bytes, ssize_t slice_size, return slices; } -static void write_done(void *user_data /* write_socket_state */, - grpc_endpoint_cb_status error) { +static void write_done(void *user_data /* write_socket_state */, int success) { struct write_socket_state *state = (struct write_socket_state *)user_data; gpr_log(GPR_INFO, "Write done callback called"); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); @@ -339,6 +374,8 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { size_t num_blocks; gpr_slice *slices; int current_data = 0; + gpr_slice_buffer outgoing; + grpc_iomgr_closure write_done_closure; gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20); gpr_log(GPR_INFO, "Start write test with %d bytes, slice size %d", num_bytes, @@ -355,74 +392,21 @@ static void write_test(ssize_t num_bytes, ssize_t slice_size) { slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - if (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state) == - GRPC_ENDPOINT_WRITE_DONE) { - /* Write completed immediately */ - read_bytes = drain_socket(sv[0]); - GPR_ASSERT(read_bytes == num_bytes); - } else { - drain_socket_blocking(sv[0], num_bytes, num_bytes); - gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); - for (;;) { - grpc_pollset_worker worker; - if (state.write_done) { - break; - } - grpc_pollset_work(&g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), - deadline); - } - gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); - } - - grpc_endpoint_destroy(ep); - gpr_free(slices); -} - -static void read_done_for_write_error(void *ud, gpr_slice *slices, - size_t nslices, - grpc_endpoint_cb_status error) { - GPR_ASSERT(error != GRPC_ENDPOINT_CB_OK); - GPR_ASSERT(nslices == 0); -} - -/* Write to a socket using the grpc_tcp API, then drain it directly. - Note that if the write does not complete immediately we need to drain the - socket in parallel with the read. */ -static void write_error_test(ssize_t num_bytes, ssize_t slice_size) { - int sv[2]; - grpc_endpoint *ep; - struct write_socket_state state; - size_t num_blocks; - gpr_slice *slices; - int current_data = 0; - grpc_pollset_worker worker; - gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20); - - gpr_log(GPR_INFO, "Start write error test with %d bytes, slice size %d", - num_bytes, slice_size); - - create_sockets(sv); + gpr_slice_buffer_init(&outgoing); + gpr_slice_buffer_addn(&outgoing, slices, num_blocks); + grpc_iomgr_closure_init(&write_done_closure, write_done, &state); - ep = grpc_tcp_create(grpc_fd_create(sv[1], "write_error_test"), - GRPC_TCP_DEFAULT_READ_SLICE_SIZE, "test"); - grpc_endpoint_add_to_pollset(ep, &g_pollset); - - close(sv[0]); - - state.ep = ep; - state.write_done = 0; - - slices = allocate_blocks(num_bytes, slice_size, &num_blocks, ¤t_data); - - switch (grpc_endpoint_write(ep, slices, num_blocks, write_done, &state)) { - case GRPC_ENDPOINT_WRITE_DONE: - case GRPC_ENDPOINT_WRITE_ERROR: + switch (grpc_endpoint_write(ep, &outgoing, &write_done_closure)) { + case GRPC_ENDPOINT_DONE: /* Write completed immediately */ + read_bytes = drain_socket(sv[0]); + GPR_ASSERT(read_bytes == num_bytes); break; - case GRPC_ENDPOINT_WRITE_PENDING: - grpc_endpoint_notify_on_read(ep, read_done_for_write_error, NULL); + case GRPC_ENDPOINT_PENDING: + drain_socket_blocking(sv[0], num_bytes, num_bytes); gpr_mu_lock(GRPC_POLLSET_MU(&g_pollset)); for (;;) { + grpc_pollset_worker worker; if (state.write_done) { break; } @@ -431,10 +415,14 @@ static void write_error_test(ssize_t num_bytes, ssize_t slice_size) { } gpr_mu_unlock(GRPC_POLLSET_MU(&g_pollset)); break; + case GRPC_ENDPOINT_ERROR: + gpr_log(GPR_ERROR, "endpoint got error"); + abort(); } + gpr_slice_buffer_destroy(&outgoing); grpc_endpoint_destroy(ep); - free(slices); + gpr_free(slices); } void run_tests(void) { @@ -453,10 +441,6 @@ void run_tests(void) { write_test(100000, 1); write_test(100000, 137); - for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { - write_error_test(40320, i); - } - for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { write_test(40320, i); } diff --git a/test/core/security/secure_endpoint_test.c b/test/core/security/secure_endpoint_test.c index a8368fc842..c76ddcd194 100644 --- a/test/core/security/secure_endpoint_test.c +++ b/test/core/security/secure_endpoint_test.c @@ -135,62 +135,26 @@ static grpc_endpoint_test_config configs[] = { secure_endpoint_create_fixture_tcp_socketpair_leftover, clean_up}, }; -static void verify_leftover(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { - gpr_slice s = - gpr_slice_from_copied_string("hello world 12345678900987654321"); - - GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); - GPR_ASSERT(nslices == 1); - - GPR_ASSERT(0 == gpr_slice_cmp(s, slices[0])); - gpr_slice_unref(slices[0]); - gpr_slice_unref(s); - *(int *)user_data = 1; -} - static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { grpc_endpoint_test_fixture f = config.create_fixture(slice_size); - int verified = 0; + gpr_slice_buffer incoming; + gpr_slice s = + gpr_slice_from_copied_string("hello world 12345678900987654321"); gpr_log(GPR_INFO, "Start test left over"); - grpc_endpoint_notify_on_read(f.client_ep, verify_leftover, &verified); - GPR_ASSERT(verified == 1); + gpr_slice_buffer_init(&incoming); + GPR_ASSERT(grpc_endpoint_read(f.client_ep, &incoming, NULL) == + GRPC_ENDPOINT_DONE); + GPR_ASSERT(incoming.count == 1); + GPR_ASSERT(0 == gpr_slice_cmp(s, incoming.slices[0])); grpc_endpoint_shutdown(f.client_ep); grpc_endpoint_shutdown(f.server_ep); grpc_endpoint_destroy(f.client_ep); grpc_endpoint_destroy(f.server_ep); - clean_up(); -} - -static void destroy_early(void *user_data, gpr_slice *slices, size_t nslices, - grpc_endpoint_cb_status error) { - grpc_endpoint_test_fixture *f = user_data; - gpr_slice s = - gpr_slice_from_copied_string("hello world 12345678900987654321"); - - GPR_ASSERT(error == GRPC_ENDPOINT_CB_OK); - GPR_ASSERT(nslices == 1); - - grpc_endpoint_shutdown(f->client_ep); - grpc_endpoint_destroy(f->client_ep); - - GPR_ASSERT(0 == gpr_slice_cmp(s, slices[0])); - gpr_slice_unref(slices[0]); gpr_slice_unref(s); -} + gpr_slice_buffer_destroy(&incoming); -/* test which destroys the ep before finishing reading */ -static void test_destroy_ep_early(grpc_endpoint_test_config config, - size_t slice_size) { - grpc_endpoint_test_fixture f = config.create_fixture(slice_size); - gpr_log(GPR_INFO, "Start test destroy early"); - - grpc_endpoint_notify_on_read(f.client_ep, destroy_early, &f); - - grpc_endpoint_shutdown(f.server_ep); - grpc_endpoint_destroy(f.server_ep); clean_up(); } @@ -203,7 +167,6 @@ int main(int argc, char **argv) { grpc_pollset_init(&g_pollset); grpc_endpoint_tests(configs[0], &g_pollset); test_leftover(configs[1], 1); - test_destroy_ep_early(configs[1], 1); grpc_pollset_shutdown(&g_pollset, destroy_pollset, &g_pollset); grpc_iomgr_shutdown(); diff --git a/test/core/util/port_posix.c b/test/core/util/port_posix.c index 836e62a541..4781d334e2 100644 --- a/test/core/util/port_posix.c +++ b/test/core/util/port_posix.c @@ -198,14 +198,13 @@ int grpc_pick_unused_port(void) { races with other processes on kernels that want to reuse the same port numbers over and over. */ - /* In alternating iterations we try UDP ports before TCP ports UDP + /* In alternating iterations we trial UDP ports before TCP ports UDP ports -- it could be the case that this machine has been using up UDP ports and they are scarcer. */ /* Type of port to first pick in next iteration */ int is_tcp = 1; - int try - = 0; + int trial = 0; char *env = gpr_getenv("GRPC_TEST_PORT_SERVER"); if (env) { @@ -218,11 +217,10 @@ int grpc_pick_unused_port(void) { for (;;) { int port; - try - ++; - if (try == 1) { + trial++; + if (trial == 1) { port = getpid() % (65536 - 30000) + 30000; - } else if (try <= NUM_RANDOM_PORTS_TO_PICK) { + } else if (trial <= NUM_RANDOM_PORTS_TO_PICK) { port = rand() % (65536 - 30000) + 30000; } else { port = 0; @@ -239,7 +237,7 @@ int grpc_pick_unused_port(void) { GPR_ASSERT(port > 0); /* Check that the port # is free for the other type of socket also */ if (!is_port_available(&port, !is_tcp)) { - /* In the next iteration try to bind to the other type first + /* In the next iteration trial to bind to the other type first because perhaps it is more rare. */ is_tcp = !is_tcp; continue; diff --git a/test/core/util/port_windows.c b/test/core/util/port_windows.c index 5b072f805a..2f64626cf3 100644 --- a/test/core/util/port_windows.c +++ b/test/core/util/port_windows.c @@ -35,7 +35,6 @@ #include "test/core/util/test_config.h" #if defined(GPR_WINSOCK_SOCKET) && defined(GRPC_TEST_PICK_PORT) -#include "src/core/iomgr/sockaddr_utils.h" #include "test/core/util/port.h" #include @@ -43,8 +42,14 @@ #include #include +#include +#include #include +#include "src/core/support/env.h" +#include "src/core/httpcli/httpcli.h" +#include "src/core/iomgr/sockaddr_utils.h" + #define NUM_RANDOM_PORTS_TO_PICK 100 static int is_port_available(int *port, int is_tcp) { @@ -99,6 +104,67 @@ static int is_port_available(int *port, int is_tcp) { return 1; } +typedef struct portreq { + grpc_pollset pollset; + int port; +} portreq; + +static void got_port_from_server(void *arg, + const grpc_httpcli_response *response) { + size_t i; + int port = 0; + portreq *pr = arg; + GPR_ASSERT(response); + GPR_ASSERT(response->status == 200); + for (i = 0; i < response->body_length; i++) { + GPR_ASSERT(response->body[i] >= '0' && response->body[i] <= '9'); + port = port * 10 + response->body[i] - '0'; + } + GPR_ASSERT(port > 1024); + gpr_mu_lock(GRPC_POLLSET_MU(&pr->pollset)); + pr->port = port; + grpc_pollset_kick(&pr->pollset, NULL); + gpr_mu_unlock(GRPC_POLLSET_MU(&pr->pollset)); +} + +static void destroy_pollset_and_shutdown(void *p) { + grpc_pollset_destroy(p); + grpc_shutdown(); +} + +static int pick_port_using_server(char *server) { + grpc_httpcli_context context; + grpc_httpcli_request req; + portreq pr; + + grpc_init(); + + memset(&pr, 0, sizeof(pr)); + memset(&req, 0, sizeof(req)); + grpc_pollset_init(&pr.pollset); + pr.port = -1; + + req.host = server; + req.path = "/get"; + + grpc_httpcli_context_init(&context); + grpc_httpcli_get(&context, &pr.pollset, &req, + GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), got_port_from_server, + &pr); + gpr_mu_lock(GRPC_POLLSET_MU(&pr.pollset)); + while (pr.port == -1) { + grpc_pollset_worker worker; + grpc_pollset_work(&pr.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), + GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)); + } + gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset)); + + grpc_httpcli_context_destroy(&context); + grpc_pollset_shutdown(&pr.pollset, destroy_pollset_and_shutdown, &pr.pollset); + + return pr.port; +} + int grpc_pick_unused_port(void) { /* We repeatedly pick a port and then see whether or not it is available for use both as a TCP socket and a UDP socket. First, we @@ -108,22 +174,29 @@ int grpc_pick_unused_port(void) { races with other processes on kernels that want to reuse the same port numbers over and over. */ - /* In alternating iterations we try UDP ports before TCP ports UDP + /* In alternating iterations we trial UDP ports before TCP ports UDP ports -- it could be the case that this machine has been using up UDP ports and they are scarcer. */ /* Type of port to first pick in next iteration */ int is_tcp = 1; - int try - = 0; + int trial = 0; + + char *env = gpr_getenv("GRPC_TEST_PORT_SERVER"); + if (env) { + int port = pick_port_using_server(env); + gpr_free(env); + if (port != 0) { + return port; + } + } for (;;) { int port; - try - ++; - if (try == 1) { + trial++; + if (trial == 1) { port = _getpid() % (65536 - 30000) + 30000; - } else if (try <= NUM_RANDOM_PORTS_TO_PICK) { + } else if (trial <= NUM_RANDOM_PORTS_TO_PICK) { port = rand() % (65536 - 30000) + 30000; } else { port = 0; @@ -136,7 +209,7 @@ int grpc_pick_unused_port(void) { GPR_ASSERT(port > 0); /* Check that the port # is free for the other type of socket also */ if (!is_port_available(&port, !is_tcp)) { - /* In the next iteration try to bind to the other type first + /* In the next iteration trial to bind to the other type first because perhaps it is more rare. */ is_tcp = !is_tcp; continue; -- cgit v1.2.3 From d68ef4f9ae4ed077d576d6870d8f79514e9b9a94 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 26 Aug 2015 11:43:45 -0700 Subject: upgrade third_party/protobufs to 3.0.0-beta-1 --- src/csharp/.gitignore | 3 +++ .../Grpc.Examples.Tests/Grpc.Examples.Tests.csproj | 5 +++-- src/csharp/Grpc.Examples.Tests/packages.config | 2 +- src/csharp/Grpc.Examples/Grpc.Examples.csproj | 5 +++-- src/csharp/Grpc.Examples/packages.config | 2 +- .../Grpc.HealthCheck.Tests.csproj | 5 +++-- src/csharp/Grpc.HealthCheck.Tests/packages.config | 2 +- .../Grpc.HealthCheck/Grpc.HealthCheck.csproj | 5 +++-- src/csharp/Grpc.HealthCheck/packages.config | 2 +- .../Grpc.IntegrationTesting.csproj | 7 ++++--- src/csharp/Grpc.IntegrationTesting/packages.config | 2 +- src/csharp/Grpc.Tools.nuspec | 2 +- src/csharp/build_packages.bat | 8 +++++--- third_party/protobuf | 2 +- tools/run_tests/run_sanity.sh | 2 +- vsprojects/build_plugins.bat | 23 ++++++++++++++++++++++ 16 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 vsprojects/build_plugins.bat (limited to 'src') 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.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj index 8b05c9cad8..ba7fad8633 100644 --- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj +++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj @@ -37,8 +37,9 @@ C:\keys\Grpc.snk - - ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config index d84b85822f..7c8fd1ebe5 100644 --- a/src/csharp/Grpc.Examples.Tests/packages.config +++ b/src/csharp/Grpc.Examples.Tests/packages.config @@ -1,6 +1,6 @@  - + \ 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 cb99c20079..e97474b8ae 100644 --- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj +++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj @@ -37,8 +37,9 @@ C:\keys\Grpc.snk - - ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config index 27e9d2ce15..126b775ac5 100644 --- a/src/csharp/Grpc.Examples/packages.config +++ b/src/csharp/Grpc.Examples/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj index 7f0ff66fa1..89935e22c0 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj +++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj @@ -37,8 +37,9 @@ C:\keys\Grpc.snk - - ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config index 228e0725c8..7c85c0eee0 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/packages.config +++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config @@ -1,5 +1,5 @@  - + \ 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 dac8c21d70..feaf47b531 100644 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -38,8 +38,9 @@ C:\keys\Grpc.snk - - ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config index 7f9cb2dd48..e1de987afb 100644 --- a/src/csharp/Grpc.HealthCheck/packages.config +++ b/src/csharp/Grpc.HealthCheck/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index b115eac909..1dbd0a4c56 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -42,9 +42,6 @@ False ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll - - ..\packages\Google.Protobuf.3.0.0-a20150813-2093749ca\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll - False ..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll @@ -57,6 +54,10 @@ False ..\packages\Google.Apis.Core.1.9.3\lib\portable-net40+sl50+win+wpa81+wp80\Google.Apis.Core.dll + + False + ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + False ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config index 54b594bb63..3891f7b475 100644 --- a/src/csharp/Grpc.IntegrationTesting/packages.config +++ b/src/csharp/Grpc.IntegrationTesting/packages.config @@ -1,9 +1,9 @@  - + diff --git a/src/csharp/Grpc.Tools.nuspec b/src/csharp/Grpc.Tools.nuspec index b6e116f537..48a7b1f3af 100644 --- a/src/csharp/Grpc.Tools.nuspec +++ b/src/csharp/Grpc.Tools.nuspec @@ -16,6 +16,6 @@ gRPC RPC Protocol HTTP/2 - + diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 6aa5e4b0b7..540b617875 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -1,9 +1,9 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.7.0-preview20150813 -set CORE_VERSION=0.11.0-preview20150813 -set PROTOBUF_VERSION=3.0.0-a20150813-2093749ca +set VERSION=0.7.0-preview20150826 +set CORE_VERSION=0.11.0-preview20150826 +set PROTOBUF_VERSION=3.0.0-a20150826-7e05a2d @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe @@ -15,6 +15,8 @@ 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 diff --git a/third_party/protobuf b/third_party/protobuf index 2093749caf..23408684b4 160000 --- a/third_party/protobuf +++ b/third_party/protobuf @@ -1 +1 @@ -Subproject commit 2093749caf6add1f1be63194e585fffd5ef98ecb +Subproject commit 23408684b4d2bf1b25e14314413a14d542c18bc4 diff --git a/tools/run_tests/run_sanity.sh b/tools/run_tests/run_sanity.sh index ac331b54d3..2737e564c6 100755 --- a/tools/run_tests/run_sanity.sh +++ b/tools/run_tests/run_sanity.sh @@ -46,7 +46,7 @@ diff -u $submodules - << EOF 05b155ff59114735ec8cd089f669c4c3d8f59029 third_party/gflags (v2.1.0-45-g05b155f) c99458533a9b4c743ed51537e25989ea55944908 third_party/googletest (release-1.7.0) 33dd08320648ac71d7d9d732be774ed3818dccc5 third_party/openssl (OpenSSL_1_0_2d) - 3e2c8a5dd79481e1d36572cdf65be93514ba6581 third_party/protobuf (v3.0.0-alpha-1-1048-g3e2c8a5) + 23408684b4d2bf1b25e14314413a14d542c18bc4 third_party/protobuf (v3.0.0-alpha-1-1592-g2340868) 50893291621658f355bc5b4d450a8d06a563053d third_party/zlib (v1.2.8) EOF diff --git a/vsprojects/build_plugins.bat b/vsprojects/build_plugins.bat new file mode 100644 index 0000000000..4c33a584ad --- /dev/null +++ b/vsprojects/build_plugins.bat @@ -0,0 +1,23 @@ +@rem Convenience script to build gRPC protoc plugins from command line. protoc plugins are used to generate service stub code from .proto service defintions. + +setlocal + +@rem enter this directory +cd /d %~dp0 + +@rem Set VS variables (uses Visual Studio 2013) +@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86 + +@rem Build third_party/protobuf +msbuild ..\third_party\protobuf\cmake\protobuf.sln /p:Configuration=Release || goto :error + +@rem Build the C# protoc plugins +msbuild grpc_protoc_plugins.sln /p:Configuration=Release || goto :error + +endlocal + +goto :EOF + +:error +echo Failed! +exit /b %errorlevel% -- cgit v1.2.3 From 939ccbe0ffb1ece37eca300fe218830000b847b5 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 27 Aug 2015 08:51:36 -0700 Subject: switch C# projects to Google.Protobuf 3.0.0-alpha4 package --- src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj | 2 +- src/csharp/Grpc.Examples.Tests/packages.config | 2 +- src/csharp/Grpc.Examples/Grpc.Examples.csproj | 2 +- src/csharp/Grpc.Examples/packages.config | 2 +- src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj | 2 +- src/csharp/Grpc.HealthCheck.Tests/packages.config | 2 +- src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj | 2 +- src/csharp/Grpc.HealthCheck/packages.config | 2 +- src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj | 2 +- src/csharp/Grpc.IntegrationTesting/packages.config | 2 +- src/csharp/build_packages.bat | 6 +++--- 11 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj index ba7fad8633..c4c1ee6d00 100644 --- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj +++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj @@ -39,7 +39,7 @@ False - ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.Examples.Tests/packages.config b/src/csharp/Grpc.Examples.Tests/packages.config index 7c8fd1ebe5..7266fa1763 100644 --- a/src/csharp/Grpc.Examples.Tests/packages.config +++ b/src/csharp/Grpc.Examples.Tests/packages.config @@ -1,6 +1,6 @@  - + \ 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 e97474b8ae..55462e02fd 100644 --- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj +++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj @@ -39,7 +39,7 @@ False - ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll diff --git a/src/csharp/Grpc.Examples/packages.config b/src/csharp/Grpc.Examples/packages.config index 126b775ac5..adf8da2363 100644 --- a/src/csharp/Grpc.Examples/packages.config +++ b/src/csharp/Grpc.Examples/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj index 89935e22c0..396dc43a02 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj +++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj @@ -39,7 +39,7 @@ False - ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll ..\packages\NUnit.2.6.4\lib\nunit.framework.dll diff --git a/src/csharp/Grpc.HealthCheck.Tests/packages.config b/src/csharp/Grpc.HealthCheck.Tests/packages.config index 7c85c0eee0..40ffb85203 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/packages.config +++ b/src/csharp/Grpc.HealthCheck.Tests/packages.config @@ -1,5 +1,5 @@  - + \ 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 feaf47b531..8fce5d39aa 100644 --- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj +++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj @@ -40,7 +40,7 @@ False - ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll diff --git a/src/csharp/Grpc.HealthCheck/packages.config b/src/csharp/Grpc.HealthCheck/packages.config index e1de987afb..cafff6123a 100644 --- a/src/csharp/Grpc.HealthCheck/packages.config +++ b/src/csharp/Grpc.HealthCheck/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index 1dbd0a4c56..a5945be922 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -56,7 +56,7 @@ False - ..\packages\Google.Protobuf.3.0.0-a20150826-7e05a2d\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll + ..\packages\Google.Protobuf.3.0.0-alpha4\lib\portable-net45+netcore45+wpa81+wp8\Google.Protobuf.dll False diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config index 3891f7b475..8dfded1964 100644 --- a/src/csharp/Grpc.IntegrationTesting/packages.config +++ b/src/csharp/Grpc.IntegrationTesting/packages.config @@ -3,7 +3,7 @@ - + diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 540b617875..255b7469ab 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -1,9 +1,9 @@ @rem Builds gRPC NuGet packages @rem Current package versions -set VERSION=0.7.0-preview20150826 -set CORE_VERSION=0.11.0-preview20150826 -set PROTOBUF_VERSION=3.0.0-a20150826-7e05a2d +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 -- cgit v1.2.3 From 69e9747eb9ada375c8a3c685682f73af8487ca2c Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 21 Aug 2015 13:46:31 -0700 Subject: php: fix interop stub construction after codegen fix --- src/php/tests/generated_code/AbstractGeneratedCodeTest.php | 4 ++++ src/php/tests/interop/interop_client.php | 6 +----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') 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..ed7b073f8f 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"; -- cgit v1.2.3 From 4135a219c59271fb00327b9a4095937549eb394c Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 21 Aug 2015 14:36:22 -0700 Subject: php: add comment for why cancel_after_begin cannot be done --- src/php/tests/interop/interop_client.php | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index ed7b073f8f..bd15ee4303 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -368,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); } -- cgit v1.2.3 From 4ad400341e624947abbd08dd8ab8f06a6610b7e5 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 27 Aug 2015 10:02:24 -0700 Subject: Fixed handling of binary metadata values --- src/node/ext/call.cc | 23 ++++++++++++----------- src/node/src/metadata.js | 4 +++- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 18858fa334..fddc1e214f 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -111,17 +111,19 @@ bool CreateMetadataArray(Handle metadata, grpc_metadata_array *array, NanAssignPersistent(*handle, value); resources->handles.push_back(unique_ptr( new PersistentHolder(handle))); - continue; + } else { + return false; } - } - if (value->IsString()) { - Handle string_value = value->ToString(); - NanUtf8String *utf8_value = new NanUtf8String(string_value); - resources->strings.push_back(unique_ptr(utf8_value)); - current->value = **utf8_value; - current->value_length = string_value->Length(); } else { - return false; + if (value->IsString()) { + Handle string_value = value->ToString(); + NanUtf8String *utf8_value = new NanUtf8String(string_value); + resources->strings.push_back(unique_ptr(utf8_value)); + current->value = **utf8_value; + current->value_length = string_value->Length(); + } else { + return false; + } } array->count += 1; } @@ -156,8 +158,7 @@ Handle 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)); } diff --git a/src/node/src/metadata.js b/src/node/src/metadata.js index 65fd91f367..c1da70b197 100644 --- a/src/node/src/metadata.js +++ b/src/node/src/metadata.js @@ -147,7 +147,9 @@ Metadata.prototype.getMap = function() { */ Metadata.prototype.clone = function() { var copy = new Metadata(); - copy._internal_repr = _.cloneDeep(this._internal_repr); + _.forOwn(this._internal_repr, function(value, key) { + copy._internal_repr[key] = _.clone(value); + }); return copy; }; -- cgit v1.2.3 From 868545987b2ae926e349b4f45404be6e654f3efd Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 27 Aug 2015 10:27:19 -0700 Subject: Fixed incorrect include line in core/census/grpc_filter.c --- src/core/census/grpc_filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/census/grpc_filter.c b/src/core/census/grpc_filter.c index fbedb35661..b78445595c 100644 --- a/src/core/census/grpc_filter.c +++ b/src/core/census/grpc_filter.c @@ -36,12 +36,12 @@ #include #include -#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 #include #include #include -- cgit v1.2.3 From b59f1348a2acb0711827aecdce23ee716070d13c Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Thu, 27 Aug 2015 11:09:20 -0700 Subject: Python OAuth2 auth-token interop test --- src/python/grpcio_test/grpc_interop/client.py | 8 +++++++- src/python/grpcio_test/grpc_interop/methods.py | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'src') 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..642458e892 100644 --- a/src/python/grpcio_test/grpc_interop/methods.py +++ b/src/python/grpcio_test/grpc_interop/methods.py @@ -360,6 +360,19 @@ def _service_account_creds(stub, args): (response.oauth_scope, args.oauth_scope)) +def _oauth2_auth_token(stub, args): + json_key_filename = os.environ[ + oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] + wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] + response = _large_unary_common_behavior(stub, True, True) + if wanted_email != response.username: + raise ValueError( + 'expected username %s, got %s' % (wanted_email, response.username)) + if args.oauth_scope.find(response.oauth_scope) == -1: + raise ValueError( + 'expected to find oauth scope "%s" in received "%s"' % + (response.oauth_scope, args.oauth_scope)) + @enum.unique class TestCase(enum.Enum): EMPTY_UNARY = 'empty_unary' @@ -371,6 +384,7 @@ class TestCase(enum.Enum): 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): @@ -394,5 +408,7 @@ class TestCase(enum.Enum): _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) -- cgit v1.2.3 From dafcce980d847e3a90cb7aa31641c464bbc5809a Mon Sep 17 00:00:00 2001 From: yang-g Date: Thu, 27 Aug 2015 11:34:05 -0700 Subject: channel creation API change --- include/grpc++/create_channel.h | 6 ++++++ src/cpp/client/create_channel.cc | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h index 0e559ac53e..916f3b0b97 100644 --- a/include/grpc++/create_channel.h +++ b/include/grpc++/create_channel.h @@ -44,6 +44,12 @@ namespace grpc { // If creds does not hold an object or is invalid, a lame channel is returned. std::shared_ptr CreateChannel( + const grpc::string& target, const std::shared_ptr& creds); + +// For advanced use and testing ONLY. Override default channel arguments only +// if necessary. +// If creds does not hold an object or is invalid, a lame channel is returned. +std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args); diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 8c571cbbaa..8d2f1bf37a 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -43,7 +43,12 @@ namespace grpc { class ChannelArguments; -std::shared_ptr CreateChannel( +std::shared_ptr CreateCustomChannel( + const grpc::string& target, const std::shared_ptr& creds) { + return CreateCustomChannel(target, creds, ChannelArguments()); +} + +std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args) { ChannelArguments cp_args = args; @@ -57,4 +62,5 @@ std::shared_ptr CreateChannel( NULL, GRPC_STATUS_INVALID_ARGUMENT, "Invalid credentials.")); } + } // namespace grpc -- cgit v1.2.3 From 730055d9628ca6d27e46d7c6716148a8d93bf95d Mon Sep 17 00:00:00 2001 From: yang-g Date: Thu, 27 Aug 2015 12:29:45 -0700 Subject: implementation fix --- include/grpc++/credentials.h | 2 +- src/cpp/client/create_channel.cc | 2 +- test/cpp/end2end/async_end2end_test.cc | 8 ++++---- test/cpp/end2end/client_crash_test.cc | 2 +- test/cpp/end2end/end2end_test.cc | 9 ++++----- test/cpp/end2end/generic_end2end_test.cc | 4 ++-- test/cpp/end2end/mock_test.cc | 4 ++-- test/cpp/end2end/server_crash_test_client.cc | 4 ++-- test/cpp/end2end/shutdown_test.cc | 2 +- test/cpp/end2end/thread_stress_test.cc | 4 ++-- test/cpp/end2end/zookeeper_test.cc | 2 +- test/cpp/qps/driver.cc | 8 ++++---- test/cpp/qps/report.h | 4 ++-- test/cpp/util/cli_call_test.cc | 3 +-- test/cpp/util/create_test_channel.cc | 4 ++-- test/cpp/util/grpc_cli.cc | 2 +- 16 files changed, 31 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h index 71e1f00f15..d623bcef60 100644 --- a/include/grpc++/credentials.h +++ b/include/grpc++/credentials.h @@ -57,7 +57,7 @@ class Credentials : public GrpcLibrary { virtual SecureCredentials* AsSecureCredentials() = 0; private: - friend std::shared_ptr CreateChannel( + friend std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args); diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 8d2f1bf37a..1dac960017 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -43,7 +43,7 @@ namespace grpc { class ChannelArguments; -std::shared_ptr CreateCustomChannel( +std::shared_ptr CreateChannel( const grpc::string& target, const std::shared_ptr& creds) { return CreateCustomChannel(target, creds, ChannelArguments()); } diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index 41b91e459b..bbcac9ba34 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -200,8 +200,8 @@ class AsyncEnd2endTest : public ::testing::TestWithParam { } void ResetStub() { - std::shared_ptr channel = CreateChannel( - server_address_.str(), InsecureCredentials(), ChannelArguments()); + std::shared_ptr channel = + CreateChannel(server_address_.str(), InsecureCredentials()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); } @@ -750,8 +750,8 @@ TEST_P(AsyncEnd2endTest, ServerCheckDone) { } TEST_P(AsyncEnd2endTest, UnimplementedRpc) { - std::shared_ptr channel = CreateChannel( - server_address_.str(), InsecureCredentials(), ChannelArguments()); + std::shared_ptr channel = + CreateChannel(server_address_.str(), InsecureCredentials()); std::unique_ptr stub; stub = std::move(grpc::cpp::test::util::UnimplementedService::NewStub(channel)); diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc index 3359080cec..3a6e55216a 100644 --- a/test/cpp/end2end/client_crash_test.cc +++ b/test/cpp/end2end/client_crash_test.cc @@ -76,7 +76,7 @@ class CrashTest : public ::testing::Test { })); GPR_ASSERT(server_); return grpc::cpp::test::util::TestService::NewStub( - CreateChannel(addr, InsecureCredentials(), ChannelArguments())); + CreateChannel(addr, InsecureCredentials())); } void KillServer() { server_.reset(); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 9826837c60..37a6e693e6 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -291,8 +291,8 @@ class End2endTest : public ::testing::TestWithParam { ChannelArguments args; args.SetSslTargetNameOverride("foo.test.google.fr"); args.SetString(GRPC_ARG_SECONDARY_USER_AGENT_STRING, "end2end_test"); - channel_ = - CreateChannel(server_address_.str(), SslCredentials(ssl_opts), args); + channel_ = CreateCustomChannel(server_address_.str(), + SslCredentials(ssl_opts), args); } void ResetStub(bool use_proxy) { @@ -307,8 +307,7 @@ class End2endTest : public ::testing::TestWithParam { builder.RegisterService(proxy_service_.get()); proxy_server_ = builder.BuildAndStart(); - channel_ = CreateChannel(proxyaddr.str(), InsecureCredentials(), - ChannelArguments()); + channel_ = CreateChannel(proxyaddr.str(), InsecureCredentials()); } stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_)); @@ -566,7 +565,7 @@ TEST_F(End2endTest, BadCredentials) { std::shared_ptr bad_creds = ServiceAccountCredentials("", "", 1); EXPECT_EQ(static_cast(nullptr), bad_creds.get()); std::shared_ptr channel = - CreateChannel(server_address_.str(), bad_creds, ChannelArguments()); + CreateChannel(server_address_.str(), bad_creds); std::unique_ptr stub( grpc::cpp::test::util::TestService::NewStub(channel)); EchoRequest request; diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc index 809eef058c..7acbc711fb 100644 --- a/test/cpp/end2end/generic_end2end_test.cc +++ b/test/cpp/end2end/generic_end2end_test.cc @@ -121,8 +121,8 @@ class GenericEnd2endTest : public ::testing::Test { } void ResetStub() { - std::shared_ptr channel = CreateChannel( - server_address_.str(), InsecureCredentials(), ChannelArguments()); + std::shared_ptr channel = + CreateChannel(server_address_.str(), InsecureCredentials()); generic_stub_.reset(new GenericStub(channel)); } diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc index b2c6dc39a8..077d21aa72 100644 --- a/test/cpp/end2end/mock_test.cc +++ b/test/cpp/end2end/mock_test.cc @@ -245,8 +245,8 @@ class MockTest : public ::testing::Test { void TearDown() GRPC_OVERRIDE { server_->Shutdown(); } void ResetStub() { - std::shared_ptr channel = CreateChannel( - server_address_.str(), InsecureCredentials(), ChannelArguments()); + std::shared_ptr channel = + CreateChannel(server_address_.str(), InsecureCredentials()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); } diff --git a/test/cpp/end2end/server_crash_test_client.cc b/test/cpp/end2end/server_crash_test_client.cc index 7ca43a0c5b..6ff42fcb30 100644 --- a/test/cpp/end2end/server_crash_test_client.cc +++ b/test/cpp/end2end/server_crash_test_client.cc @@ -58,8 +58,8 @@ using namespace gflags; int main(int argc, char** argv) { ParseCommandLineFlags(&argc, &argv, true); - auto stub = grpc::cpp::test::util::TestService::NewStub(grpc::CreateChannel( - FLAGS_address, grpc::InsecureCredentials(), grpc::ChannelArguments())); + auto stub = grpc::cpp::test::util::TestService::NewStub( + grpc::CreateChannel(FLAGS_address, grpc::InsecureCredentials())); EchoRequest request; EchoResponse response; diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc index e83f86f7ec..59fec6ad40 100644 --- a/test/cpp/end2end/shutdown_test.cc +++ b/test/cpp/end2end/shutdown_test.cc @@ -95,7 +95,7 @@ class ShutdownTest : public ::testing::Test { void ResetStub() { string target = "dns:localhost:" + to_string(port_); - channel_ = CreateChannel(target, InsecureCredentials(), ChannelArguments()); + channel_ = CreateChannel(target, InsecureCredentials()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_)); } diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index 8304f04d56..2a16481972 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -191,8 +191,8 @@ class End2endTest : public ::testing::Test { void TearDown() GRPC_OVERRIDE { server_->Shutdown(); } void ResetStub() { - std::shared_ptr channel = CreateChannel( - server_address_.str(), InsecureCredentials(), ChannelArguments()); + std::shared_ptr channel = + CreateChannel(server_address_.str(), InsecureCredentials()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel)); } diff --git a/test/cpp/end2end/zookeeper_test.cc b/test/cpp/end2end/zookeeper_test.cc index e7d95b1c46..931541ca34 100644 --- a/test/cpp/end2end/zookeeper_test.cc +++ b/test/cpp/end2end/zookeeper_test.cc @@ -159,7 +159,7 @@ class ZookeeperTest : public ::testing::Test { void ResetStub() { string target = "zookeeper://" + zookeeper_address_ + "/test"; - channel_ = CreateChannel(target, InsecureCredentials(), ChannelArguments()); + channel_ = CreateChannel(target, InsecureCredentials()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_)); } diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index 3bd61ea4e8..0e771d6b81 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -154,8 +154,8 @@ std::unique_ptr RunScenario( // where class contained in std::vector must have a copy constructor auto* servers = new ServerData[num_servers]; for (size_t i = 0; i < num_servers; i++) { - servers[i].stub = std::move(Worker::NewStub( - CreateChannel(workers[i], InsecureCredentials(), ChannelArguments()))); + servers[i].stub = std::move( + Worker::NewStub(CreateChannel(workers[i], InsecureCredentials()))); ServerArgs args; result_server_config = server_config; result_server_config.set_host(workers[i]); @@ -182,8 +182,8 @@ std::unique_ptr RunScenario( // where class contained in std::vector must have a copy constructor auto* clients = new ClientData[num_clients]; for (size_t i = 0; i < num_clients; i++) { - clients[i].stub = std::move(Worker::NewStub(CreateChannel( - workers[i + num_servers], InsecureCredentials(), ChannelArguments()))); + clients[i].stub = std::move(Worker::NewStub( + CreateChannel(workers[i + num_servers], InsecureCredentials()))); ClientArgs args; result_client_config = client_config; result_client_config.set_host(workers[i + num_servers]); diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h index 620abade39..5914fc4e30 100644 --- a/test/cpp/qps/report.h +++ b/test/cpp/qps/report.h @@ -116,8 +116,8 @@ class PerfDbReporter : public Reporter { test_name_(test_name), sys_info_(sys_info), tag_(tag) { - perf_db_client_.init(grpc::CreateChannel( - server_address, grpc::InsecureCredentials(), ChannelArguments())); + perf_db_client_.init( + grpc::CreateChannel(server_address, grpc::InsecureCredentials())); } ~PerfDbReporter() GRPC_OVERRIDE { SendData(); }; diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc index 111a0e9f76..0efa201622 100644 --- a/test/cpp/util/cli_call_test.cc +++ b/test/cpp/util/cli_call_test.cc @@ -91,8 +91,7 @@ class CliCallTest : public ::testing::Test { void TearDown() GRPC_OVERRIDE { server_->Shutdown(); } void ResetStub() { - channel_ = CreateChannel(server_address_.str(), InsecureCredentials(), - ChannelArguments()); + channel_ = CreateChannel(server_address_.str(), InsecureCredentials()); stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_)); } diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index 161b4bdc1d..e993d14e71 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -74,9 +74,9 @@ std::shared_ptr CreateTestChannel( if (creds.get()) { channel_creds = CompositeCredentials(creds, channel_creds); } - return CreateChannel(connect_to, channel_creds, channel_args); + return CreateCustomChannel(connect_to, channel_creds, channel_args); } else { - return CreateChannel(server, InsecureCredentials(), channel_args); + return CreateChannel(server, InsecureCredentials()); } } diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc index a4888efebe..22cac21f77 100644 --- a/test/cpp/util/grpc_cli.cc +++ b/test/cpp/util/grpc_cli.cc @@ -159,7 +159,7 @@ int main(int argc, char** argv) { } } std::shared_ptr channel = - grpc::CreateChannel(server_address, creds, grpc::ChannelArguments()); + grpc::CreateChannel(server_address, creds); grpc::string response; std::multimap client_metadata; -- cgit v1.2.3 From 7dc25d3ca6fd5233906567d7b0592894c762d44e Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Thu, 27 Aug 2015 19:25:41 +0000 Subject: Add force_client_auth to _low.ServerCredentials --- .../grpcio/grpc/_adapter/_c/types/server_credentials.c | 13 ++++++------- src/python/grpcio/grpc/_adapter/_intermediary_low.py | 3 ++- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') 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 2ba855e76c..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, NULL); + 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..1fb6a2b27d 100644 --- a/src/python/grpcio/grpc/_adapter/_intermediary_low.py +++ b/src/python/grpcio/grpc/_adapter/_intermediary_low.py @@ -256,4 +256,5 @@ 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)) + self._internal = _low.ServerCredentials.ssl( + root_credentials, list(pair_sequence), False) -- cgit v1.2.3 From 5414df3011238c6443e0ca38c308aa96c115622c Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 27 Aug 2015 13:15:24 -0700 Subject: make ToLower culture invariant --- src/csharp/Grpc.Core/Metadata.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs index 99fe0b5478..2b08e0de51 100644 --- a/src/csharp/Grpc.Core/Metadata.cs +++ b/src/csharp/Grpc.Core/Metadata.cs @@ -33,6 +33,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; +using System.Globalization; using System.Runtime.InteropServices; using System.Text; @@ -320,7 +321,7 @@ namespace Grpc.Core private static string NormalizeKey(string key) { - return Preconditions.CheckNotNull(key, "key").ToLower(); + return Preconditions.CheckNotNull(key, "key").ToLower(CultureInfo.InvariantCulture); } } } -- cgit v1.2.3 From 9a09982e2dd193a91430ba70ed4e446d8d96e363 Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Thu, 27 Aug 2015 13:16:00 -0700 Subject: view and aggregation API --- BUILD | 9 +- Makefile | 2 - build.json | 5 +- gRPC.podspec | 7 +- include/grpc/census.h | 236 ++++++++++++--------- src/core/census/grpc_filter.c | 31 +-- src/core/census/record_stat.c | 38 ---- src/core/census/rpc_metric_id.h | 51 +++++ src/core/census/rpc_stat_id.h | 46 ---- third_party/openssl | 2 +- tools/doxygen/Doxyfile.core.internal | 3 +- tools/run_tests/sources_and_headers.json | 10 +- vsprojects/grpc/grpc.vcxproj | 4 +- vsprojects/grpc/grpc.vcxproj.filters | 5 +- vsprojects/grpc_unsecure/grpc_unsecure.vcxproj | 4 +- .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 5 +- 16 files changed, 217 insertions(+), 241 deletions(-) delete mode 100644 src/core/census/record_stat.c create mode 100644 src/core/census/rpc_metric_id.h delete mode 100644 src/core/census/rpc_stat_id.h (limited to 'src') diff --git a/BUILD b/BUILD index 25b26b7b24..3072195251 100644 --- a/BUILD +++ b/BUILD @@ -246,7 +246,7 @@ cc_library( "src/core/transport/transport.h", "src/core/transport/transport_impl.h", "src/core/census/context.h", - "src/core/census/rpc_stat_id.h", + "src/core/census/rpc_metric_id.h", "src/core/httpcli/httpcli_security_connector.c", "src/core/security/base64.c", "src/core/security/client_auth_filter.c", @@ -386,7 +386,6 @@ cc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", - "src/core/census/record_stat.c", ], hdrs = [ "include/grpc/grpc_security.h", @@ -515,7 +514,7 @@ cc_library( "src/core/transport/transport.h", "src/core/transport/transport_impl.h", "src/core/census/context.h", - "src/core/census/rpc_stat_id.h", + "src/core/census/rpc_metric_id.h", "src/core/surface/init_unsecure.c", "src/core/census/grpc_context.c", "src/core/census/grpc_filter.c", @@ -635,7 +634,6 @@ cc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", - "src/core/census/record_stat.c", ], hdrs = [ "include/grpc/byte_buffer.h", @@ -1144,7 +1142,6 @@ objc_library( "src/core/transport/transport_op_string.c", "src/core/census/context.c", "src/core/census/initialize.c", - "src/core/census/record_stat.c", ], hdrs = [ "include/grpc/grpc_security.h", @@ -1270,7 +1267,7 @@ objc_library( "src/core/transport/transport.h", "src/core/transport/transport_impl.h", "src/core/census/context.h", - "src/core/census/rpc_stat_id.h", + "src/core/census/rpc_metric_id.h", ], includes = [ "include", diff --git a/Makefile b/Makefile index 48ecea9831..620508c19a 100644 --- a/Makefile +++ b/Makefile @@ -4196,7 +4196,6 @@ LIBGRPC_SRC = \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ - src/core/census/record_stat.c \ PUBLIC_HEADERS_C += \ include/grpc/grpc_security.h \ @@ -4470,7 +4469,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ - src/core/census/record_stat.c \ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer.h \ diff --git a/build.json b/build.json index 54cae41546..02cee31d08 100644 --- a/build.json +++ b/build.json @@ -19,12 +19,11 @@ ], "headers": [ "src/core/census/context.h", - "src/core/census/rpc_stat_id.h" + "src/core/census/rpc_metric_id.h" ], "src": [ "src/core/census/context.c", - "src/core/census/initialize.c", - "src/core/census/record_stat.c" + "src/core/census/initialize.c" ] }, { diff --git a/gRPC.podspec b/gRPC.podspec index f6d09dbaa6..28a4ad45e0 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -248,7 +248,7 @@ Pod::Spec.new do |s| 'src/core/transport/transport.h', 'src/core/transport/transport_impl.h', 'src/core/census/context.h', - 'src/core/census/rpc_stat_id.h', + 'src/core/census/rpc_metric_id.h', 'grpc/grpc_security.h', 'grpc/byte_buffer.h', 'grpc/byte_buffer_reader.h', @@ -394,8 +394,7 @@ Pod::Spec.new do |s| 'src/core/transport/transport.c', 'src/core/transport/transport_op_string.c', 'src/core/census/context.c', - 'src/core/census/initialize.c', - 'src/core/census/record_stat.c' + 'src/core/census/initialize.c' ss.private_header_files = 'src/core/support/env.h', 'src/core/support/file.h', @@ -520,7 +519,7 @@ Pod::Spec.new do |s| 'src/core/transport/transport.h', 'src/core/transport/transport_impl.h', 'src/core/census/context.h', - 'src/core/census/rpc_stat_id.h' + 'src/core/census/rpc_metric_id.h' ss.header_mappings_dir = '.' diff --git a/include/grpc/census.h b/include/grpc/census.h index db3e89685a..968f5825a5 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -159,114 +159,154 @@ int census_tag_set_next(census_tag_set_iterator *it, census_tag_const *tag); invalidated, and should not be used once close is called. */ void census_tag_set_close(census_tag_set_iterator *it); -/* A census statistic to be recorded comprises two parts: an ID for the - * particular statistic and the value to be recorded against it. */ +/* Core stats collection API's. There following concepts are used: + * Aggregation: A collection of values. Census supports the following + aggregation types: + Scalar - a single scalar value. Typically used for keeping (e.g.) + counts of events. + Distribution - statistical distribution information, used for + recording average, standard deviation etc. + Histogram - a histogram of measurements falling in defined bucket + boundaries. + Window - a count of events that happen in reolling time window. + New aggregation types can be added by the user, if desired (see + census_register_aggregation()). + * Metric: Each measurement is for a single metric. Examples include RPC + latency, CPU seconds consumed, and bytes transmitted. + * View: A view is a tag set, in which the tag values are regular expressions, + combined with an arbitrary number of aggregations and their initialization + parameters. + + Each metric can have an arbitrary number of views by which it will be + broken down. For every measurement recorded, they are broken down by + unique tag combinations, and recorded in each matvhing view/aggregation. +*/ + +/* A single value to be recorded comprises two parts: an ID for the particular + * metric and the value to be recorded against it. */ typedef struct { - int id; + gpr_int32 metric_id; double value; -} census_stat; +} census_value; + +/* Record new usage values against the given context. */ +void census_record_usage(census_context *context, census_value *values, + size_t nvalues); + +/** Structure used to describe an aggregation type. */ +typedef struct { + /* Create a new aggregation. The pointer returned can be used in future calls + to free(), record(), data() and reset(). */ + void *(*create)(const void *create_arg); + /* 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(). */ + const void *(*data)(const void *aggregation); + /* destroy an aggregation result eturned from get_aggregation(). */ + void (*free_data)(const void *data); + /* Reset an aggregation to default (zero) values. */ + void (*reset)(void *aggregation); +} census_aggregation_descriptor; + +/** Register a new aggregation type. + @param descriptor Describes aggregation + @return An identifier that can be used to identify the aggregation in other + census functions. */ +gpr_int32 census_register_aggregation( + const census_aggregation_descriptor *descriptor); + +/* Aggregation Identifiers for built-in census aggregations. */ +#define CENSUS_AGGREGATION_ID_SCALAR ((gpr_int32)0) +#define CENSUS_AGGREGATION_ID_DISTRIBUTION ((gpr_int32)1) +#define CENSUS_AGGREGATION_ID_HISTOGRAM ((gpr_int32)2) +#define CENSUS_AGGREGATION_ID_WINDOW ((gpr_int32)3) + +/** Information needed to instantiate a new aggregation. Used in view + construction via census_define_view(). */ +typedef struct { + gpr_int32 id; /* aggregation ID */ + const void + *create_arg; /* Argument to be used for aggregation initialization. */ +} census_aggregation; -/* Record new stats against the given context. */ -void census_record_stat(census_context *context, census_stat *stats, - size_t nstats); +/** Type representing a single view. */ +typedef struct census_view census_view; -/* Stats Configuration - Census clients can use these functions and structures - to extend and define what stats get recorded for what measurements. */ +/** Create a new view. + @param tags tags that define the view + @param aggregations aggregations to associate with the view + @param naggregations number of aggregations -/** Stats types supported by census. */ -typedef enum { - CENSUS_STAT_SCALAR = 0, /* Simple scalar */ - CENSUS_STAT_DISTRIBUTION = 1, /* count, average, variance */ - CENSUS_STAT_HISTOGRAM = 2, /* Histogram. */ - CENSUS_STAT_WINDOW = 3, /* Count over a time window. */ - CENSUS_STAT_NSTATS = 4 /* Total number of stats types. */ -} census_stat_type; + @return A new census view +*/ +const census_view *census_define_view(const census_tag_set *tags, + const census_aggregation *aggregations, + size_t naggregations); -/* - Each stats type differs in how it is initialized, how it is represented, and - the results it provides. The following structures allow us to use a generic - type for each of those. - - Types referenced (one for each stat type in census_stat_type, by creation - arguments, output blob, and object representation. */ - -typedef struct census_stat_scalar_create_arg census_stat_scalar_create_arg; -typedef struct census_stat_distribution_create_arg - census_stat_distribution_create_arg; -typedef struct census_stat_histogram_create_arg - census_stat_histogram_create_arg; -typedef struct census_stat_window_create_arg census_stat_window_create_arg; - -/** - Type for representing information to construct a new instance of a given - stats type (e.g. histogram bucket boundaries). +/** Number of aggregations associated with view. */ +size_t census_view_naggregations(const census_view *view); + +/** Get tags associated with view. */ +const census_tag_set *census_view_tags(const census_view *view); + +/** Get aggregations associated with a view. */ +const census_aggregation *census_view_aggregrations(const census_view *view); + +/** Associate a given view with a metric. Every metric can have many different + views. + @param metric_id Identifier of metric with which to attah the view + @param view View to attach to the metric + @return A view identifier: can be used to retrieve aggregation data from + the view using census_view_data(). */ +gpr_int64 census_attach_view(gpr_int32 metric_id, const census_view *view); + +/** Holds aggregation data, as it applies to a particular view. This structure + is used as one component of the data returned from census_get_view_data(). */ typedef struct { - census_stat_type stat_type; /* The "real" type of the stat. */ - union { - const census_stat_scalar_create_arg *scalar_arg; - const census_stat_distribution_create_arg *distribution_arg; - const census_stat_histogram_create_arg *histogram_arg; - const census_stat_window_create_arg *window_arg; - } -} census_stat_create_arg; - -/** - Type for representing a single stats result. */ + /** Aggregation index in original view. Use as (e.g.) + census_view_aggregations(view)[index] to get the original + census_aggregation structure. */ + size_t index; + /** Data as returned from the data() function for the relevant + aggregation descriptor. It is the user responsibility to cast this to the + correct type for the aggregation. */ + void *data; +} census_aggregation_data; + +/** Holds all the aggregation data for a particular view instantiation. Forms + part of the data returned by census_get_view_data(). */ typedef struct { - const census_tag_set *view; /* Unique tags associated with this result. */ - census_stat_type stat_type; - union { - const census_stat_scalar_result *scalar_result; - const census_stat_distribution_result *distribution_result; - const census_stat_histogram_result *histogram_result; - const census_stat_window_result *window_result; - } -} census_stat_result; - -/** - Generic type for representing a stat "object". -*/ -typdef struct { - census_stat_type stat_type; - union { - census_stat_scalar *scalar; - census_stat_distribution *distribution; - census_stat_histogram *histogram; - census_stat_window *window; - } -} census_stat; - -/** - Structure holding function pointers and associated information needed to - manipulate a statstics "object". Every stats type must provide an instance - of this structure. */ + const census_tag_set *tags; /* Tags for this set of aggregations */ + size_t naggregations; /* Number of aggregations in data. */ + const census_aggregation_data *data; /* Aggregation data */ +} census_view_aggregation_data; + +/** Census view data as returned by census_get_view_data(). */ typedef struct { - /* Create a new statistic. The pointer returned can be used in future calls - to clone_stat(), destroy_stat(), record_stat() and get_stats(). */ - (census_stat *) (*create_stat)(const census_stat_create_arg *create_arg); - /* Create a new statistic, using an existing one as base. */ - (census_stat *) (*clone_stat)(const census_stat *stat); - /* destroy a stats object created by {create,clone}_stat(). */ - (void) (*destroy_stat)(census_stat *stat); - /* Record a new value against a given statistics object instance. */ - (void) (*record_stat)(census_stat *stat, double value); - /* Return current state of a stat. The object returned can be freed by - using destroy_stats_result(). */ - (const census_stat_result *) (*get_stat)(const census_stat *stat); - /* destroy a stats result object, as returned from get_stat(). */ - (void) (*destroy_stats_result)(census_stat_result *result); - /* Reset a stats values. */ - (void) (*reset_stat)(census_stat *stat); -} census_stat; - -gpr_int32 census_define_view(const census_tag_set *view); - -gpr_int32 census_define_stat(gpr_int32 metric_id, gpr_int32 view_id, - const census_stat *stat, - const census_stat_create_arg *create_arg); - -census_stat_result *census_get_stat(gpr_int32 stat_id, gpr_int32 *nstats); + const census_view *view; /* Original view */ + size_t n_tag_sets; /* Number of unique tag sets that matched view. */ + const census_view_aggregation_data *data; /* n_tag_sets entries */ +} census_view_data; + +/** Get data from aggregations associated with a view. + @param view_id View identifier returned from census_attach_view + @param aggregation_indices Indexes of aggregations (relative to original view) + for which to return current data. This parameter is ignored if + nindices == 0. + @param nindices. Number of entries in aggregation_indices. If this is set to + 0, then all aggregations for the current view are returned. +*/ +const census_view_data *census_get_view_data(gpr_int64 view_id, + size_t *aggregation_indices, + size_t nindices); + +/** Reset all view data to zero for the specified view id. */ +void census_reset_view_data(gpr_int64 view_id); #ifdef __cplusplus } diff --git a/src/core/census/grpc_filter.c b/src/core/census/grpc_filter.c index fbedb35661..45b5656e3c 100644 --- a/src/core/census/grpc_filter.c +++ b/src/core/census/grpc_filter.c @@ -37,7 +37,6 @@ #include #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" @@ -173,25 +172,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/record_stat.c b/src/core/census/record_stat.c deleted file mode 100644 index 3dd918618b..0000000000 --- a/src/core/census/record_stat.c +++ /dev/null @@ -1,38 +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. - * - */ - -#include -#include "src/core/census/rpc_stat_id.h" - -void census_record_stat(census_context *context, census_stat *stats, - size_t nstats) {} diff --git a/src/core/census/rpc_metric_id.h b/src/core/census/rpc_metric_id.h new file mode 100644 index 0000000000..2cd30c2fc0 --- /dev/null +++ b/src/core/census/rpc_metric_id.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef CENSUS_RPC_METRIC_ID_H +#define CENSUS_RPC_METRIC_ID_H + +/* Metric ID's used for RPC measurements. */ +/* Count of client requests sent. */ +#define CENSUS_METRIC_RPC_CLIENT_REQUESTS ((gpr_int32)0) +/* Count of server requests sent. */ +#define CENSUS_METRIC_RPC_SERVER_REQUESTS ((gpr_int32)1) +/* Client error counts. */ +#define CENSUS_METRIC_RPC_CLIENT_ERRORS ((gpr_int32)2) +/* Server error counts. */ +#define CENSUS_METRIC_RPC_SERVER_ERRORS ((gpr_int32)3) +/* Client side request latency. */ +#define CENSUS_METRIC_RPC_CLIENT_LATENCY ((gpr_int32)4) +/* Server side request latency. */ +#define CENSUS_METRIC_RPC_SERVER_LATENCY ((gpr_int32)5) + +#endif /* CENSUS_RPC_METRIC_ID_H */ diff --git a/src/core/census/rpc_stat_id.h b/src/core/census/rpc_stat_id.h deleted file mode 100644 index fc0aa6f43f..0000000000 --- a/src/core/census/rpc_stat_id.h +++ /dev/null @@ -1,46 +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. - * - */ - -#ifndef CENSUS_RPC_STAT_ID_H -#define CENSUS_RPC_STAT_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. */ - -#endif /* CENSUS_RPC_STAT_ID_H */ diff --git a/third_party/openssl b/third_party/openssl index 33dd083206..3df69d3aef 160000 --- a/third_party/openssl +++ b/third_party/openssl @@ -1 +1 @@ -Subproject commit 33dd08320648ac71d7d9d732be774ed3818dccc5 +Subproject commit 3df69d3aefde7671053d4e3c242b228e5d79c83f diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 06f0f4ee83..1fe43efe46 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -883,7 +883,7 @@ src/core/transport/stream_op.h \ src/core/transport/transport.h \ src/core/transport/transport_impl.h \ src/core/census/context.h \ -src/core/census/rpc_stat_id.h \ +src/core/census/rpc_metric_id.h \ src/core/httpcli/httpcli_security_connector.c \ src/core/security/base64.c \ src/core/security/client_auth_filter.c \ @@ -1023,7 +1023,6 @@ src/core/transport/transport.c \ src/core/transport/transport_op_string.c \ src/core/census/context.c \ src/core/census/initialize.c \ -src/core/census/record_stat.c \ include/grpc/support/alloc.h \ include/grpc/support/atm.h \ include/grpc/support/atm_gcc_atomic.h \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index c7df23a7c4..e8cd3ef1bf 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -12265,7 +12265,7 @@ "include/grpc/status.h", "src/core/census/context.h", "src/core/census/grpc_filter.h", - "src/core/census/rpc_stat_id.h", + "src/core/census/rpc_metric_id.h", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.h", "src/core/channel/client_channel.h", @@ -12397,8 +12397,7 @@ "src/core/census/grpc_filter.c", "src/core/census/grpc_filter.h", "src/core/census/initialize.c", - "src/core/census/record_stat.c", - "src/core/census/rpc_stat_id.h", + "src/core/census/rpc_metric_id.h", "src/core/channel/channel_args.c", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.c", @@ -12744,7 +12743,7 @@ "include/grpc/status.h", "src/core/census/context.h", "src/core/census/grpc_filter.h", - "src/core/census/rpc_stat_id.h", + "src/core/census/rpc_metric_id.h", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.h", "src/core/channel/client_channel.h", @@ -12862,8 +12861,7 @@ "src/core/census/grpc_filter.c", "src/core/census/grpc_filter.h", "src/core/census/initialize.c", - "src/core/census/record_stat.c", - "src/core/census/rpc_stat_id.h", + "src/core/census/rpc_metric_id.h", "src/core/channel/channel_args.c", "src/core/channel/channel_args.h", "src/core/channel/channel_stack.c", diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj index b17eea9235..fdb637b590 100644 --- a/vsprojects/grpc/grpc.vcxproj +++ b/vsprojects/grpc/grpc.vcxproj @@ -345,7 +345,7 @@ - + @@ -626,8 +626,6 @@ - - diff --git a/vsprojects/grpc/grpc.vcxproj.filters b/vsprojects/grpc/grpc.vcxproj.filters index a955e9e993..10ec6e6203 100644 --- a/vsprojects/grpc/grpc.vcxproj.filters +++ b/vsprojects/grpc/grpc.vcxproj.filters @@ -418,9 +418,6 @@ src\core\census - - src\core\census - @@ -794,7 +791,7 @@ src\core\census - + src\core\census diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj index a692c48f81..93e1e0fc29 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj @@ -328,7 +328,7 @@ - + @@ -569,8 +569,6 @@ - - diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters index 1c4036d464..ed0896c81a 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -358,9 +358,6 @@ src\core\census - - src\core\census - @@ -692,7 +689,7 @@ src\core\census - + src\core\census -- cgit v1.2.3 From 047f20d302f48c5ffafc58a5278e27d7edfba80f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 27 Aug 2015 13:48:25 -0700 Subject: Make single-response calls emit INTERNAL status for unparseable responses --- src/node/src/client.js | 74 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/node/src/client.js b/src/node/src/client.js index e1bed3512e..2323caecc0 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -142,7 +142,13 @@ 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.cancel(); + } + if (self.push(deserialized) && data !== null) { var read_batch = {}; read_batch[grpc.opType.RECV_MESSAGE] = true; self.call.startBatch(read_batch, readCallback); @@ -296,23 +302,38 @@ function makeUnaryRequestFunction(method, serialize, deserialize) { call.startBatch(client_batch, function(err, response) { response.status.metadata = Metadata._fromCoreRepresentation( response.status.metadata); - 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 { + 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' + }; + } } } + 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)); - callback(null, deserialize(response.read)); }); }); return emitter; @@ -374,21 +395,36 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { call.startBatch(client_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); - error.code = response.status.code; - error.metadata = response.status.metadata; - callback(error); - return; - } else { + 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; -- cgit v1.2.3 From 0a268216c2c8e112351b7ed038da04bf50b9eb5a Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Thu, 27 Aug 2015 14:38:38 -0700 Subject: replace all grpc-common occurances with examples --- README.md | 4 ++-- doc/grpc-auth-support.md | 2 +- doc/interop-test-descriptions.md | 2 +- examples/README.md | 31 +++++++++++++++-------------- examples/cpp/README.md | 18 ++++++++--------- examples/cpp/cpptutorial.md | 20 +++++++++---------- examples/cpp/helloworld/README.md | 20 +++++++++---------- examples/csharp/README.md | 2 +- examples/csharp/route_guide/README.md | 18 ++++++++--------- examples/node/README.md | 6 +++--- examples/node/route_guide/README.md | 18 ++++++++--------- examples/objective-c/auth_sample/README.md | 14 ++++++------- examples/objective-c/helloworld/README.md | 14 ++++++------- examples/objective-c/route_guide/README.md | 18 ++++++++--------- examples/php/README.md | 10 +++++----- examples/php/route_guide/README.md | 16 +++++++-------- examples/python/helloworld/README.md | 16 +++++++-------- examples/python/route_guide/README.md | 18 ++++++++--------- examples/ruby/README.md | 4 ++-- examples/ruby/grpc-demo.gemspec | 2 +- examples/ruby/route_guide/README.md | 24 +++++++++++----------- src/csharp/README.md | 6 +++--- src/objective-c/README.md | 2 +- src/objective-c/tests/LocalClearTextTests.m | 2 +- 24 files changed, 144 insertions(+), 143 deletions(-) (limited to 'src') diff --git a/README.md b/README.md index f830629816..599e6bcee0 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Copyright 2015 Google Inc. #Documentation -You can find more detailed documentation and examples in the [grpc-common repository](http://github.com/grpc/grpc-common). +You can find more detailed documentation and examples in the [doc](doc) and [examples](examples) directories respectively. #Installation @@ -95,7 +95,7 @@ messages are delivered in the order they were sent. #Protocol -The [gRPC protocol](https://github.com/grpc/grpc-common/blob/master/PROTOCOL-HTTP2.md) specifies the abstract requirements for communication between +The [gRPC protocol](examples/PROTOCOL-HTTP2.md) specifies the abstract requirements for communication between clients and servers. A concrete embedding over HTTP/2 completes the picture by fleshing out the details of each of the required operations. diff --git a/doc/grpc-auth-support.md b/doc/grpc-auth-support.md index b9ef299332..800fbedd80 100644 --- a/doc/grpc-auth-support.md +++ b/doc/grpc-auth-support.md @@ -264,7 +264,7 @@ call.requestMetadata[@"Authorization"] = [@"Bearer " stringByAppendingString:acc [call start]; ``` -You can see a working example app, with a more detailed explanation, [here](https://github.com/grpc/grpc-common/tree/master/objective-c/auth_sample). +You can see a working example app, with a more detailed explanation, [here](examples/objective-c/auth_sample). ### Authenticating with Google (Python) ```python diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md index 75110e8977..aa14a7cfdf 100644 --- a/doc/interop-test-descriptions.md +++ b/doc/interop-test-descriptions.md @@ -4,7 +4,7 @@ Interoperability Test Case Descriptions Client and server use [test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto) and the [gRPC over HTTP/2 v2 -protocol](https://github.com/grpc/grpc-common/blob/master/PROTOCOL-HTTP2.md). +protocol](examples/doc/PROTOCOL-HTTP2.md). Client ------ diff --git a/examples/README.md b/examples/README.md index 5939db3ab5..6465115e18 100644 --- a/examples/README.md +++ b/examples/README.md @@ -10,19 +10,20 @@ Hello World example. You'll find more tutorials and reference docs in this repos ## Quick start You can find quick start guides for each language, including installation instructions, examples, and tutorials here: -* [C++](https://github.com/grpc/grpc-common/tree/master/cpp) -* [Java](https://github.com/grpc/grpc-common/tree/master/java) -* [Go](https://github.com/grpc/grpc-common/tree/master/go) -* [Ruby](https://github.com/grpc/grpc-common/tree/master/ruby) -* [Node.js](https://github.com/grpc/grpc-common/tree/master/node) -* [Android Java](https://github.com/grpc/grpc-common/tree/master/java/android) -* [Python](https://github.com/grpc/grpc-common/tree/master/python/helloworld) -* [C#](https://github.com/grpc/grpc-common/tree/master/csharp) -* [Objective-C](https://github.com/grpc/grpc-common/tree/master/objective-c/route_guide) +* [C++](examples/cpp) +* [Java](https://github.com/grpc/grpc-java/tree/master/examples) +* [Go](https://github.com/grpc/grpc-go/tree/master/examples) +* [Ruby](examples/ruby) +* [Node.js](examples/node) +* [Android Java](examples/java/android) +* [Python](examples/python/helloworld) +* [C#](examples/csharp) +* [Objective-C](examples/objective-c/route_guide) +* [PHP](examples/php) ## What's in this repository? -The `grpc-common` repository contains documentation, resources, and examples +The `examples` directory contains documentation, resources, and examples for all gRPC users. You can find examples and instructions specific to your favourite language in the relevant subdirectory. @@ -93,8 +94,8 @@ Hello World method. - Create a Go client that accesses the same Java server. -The complete code for the example is available in the `grpc-common` GitHub -repository. We use the Git versioning system for source code management: +The complete code for the example is available in the `examples` +directory. We use the Git versioning system for source code management: however, you don't need to know anything about Git to follow along other than how to install and run a few git commands. @@ -400,8 +401,8 @@ and client uses interface code generated from the same proto that we used for the Java example. So, for example, if we visit the [`go` example -directory](https://github.com/grpc/grpc-common/tree/master/go) and look at the -[`greeter_client`](https://github.com/grpc/grpc-common/blob/master/go/greeter_client/main.go), +directory](https://github.com/grpc/grpc-go/tree/master/examples) and look at the +[`greeter_client`](https://github.com/grpc/grpc-go/blob/master/examples/greeter_client/main.go), we can see that like the Java client, it connects to a `Greeter` service at `localhost:50051` and uses a stub to call the `SayHello` method with a `HelloRequest`: @@ -446,4 +447,4 @@ $ greeter_client ## Read more! - You can find links to language-specific tutorials, examples, and other docs in each language's [quick start](#quickstart). -- [gRPC Authentication Support](https://github.com/grpc/grpc-common/blob/master/grpc-auth-support.md) introduces authentication support in gRPC with supported mechanisms and examples. +- [gRPC Authentication Support](doc/grpc-auth-support.md) introduces authentication support in gRPC with supported mechanisms and examples. diff --git a/examples/cpp/README.md b/examples/cpp/README.md index e0a09ff8b8..70418b4425 100644 --- a/examples/cpp/README.md +++ b/examples/cpp/README.md @@ -7,21 +7,21 @@ To install gRPC on your system, follow the instructions here: ## Hello C++ gRPC! -Here's how to build and run the C++ implementation of the [Hello World](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto) example used in [Getting started](https://github.com/grpc/grpc-common). +Here's how to build and run the C++ implementation of the [Hello World](examples/protos/helloworld.proto) example used in [Getting started](https://github.com/grpc/grpc/tree/master/examples). -The example code for this and our other examples lives in the `grpc-common` -GitHub repository. Clone this repository to your local machine by running the +The example code for this and our other examples lives in the `examples` +directory. Clone this repository to your local machine by running the following command: ```sh -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Change your current directory to grpc-common/cpp/helloworld +Change your current directory to examples/cpp/helloworld ```sh -$ cd grpc-common/cpp/helloworld/ +$ cd examples/cpp/helloworld/ ``` @@ -41,9 +41,9 @@ $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto ### Client and server implementations -The client implementation is at [greeter_client.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_client.cc). +The client implementation is at [greeter_client.cc](examples/cpp/helloworld/greeter_client.cc). -The server implementation is at [greeter_server.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_server.cc). +The server implementation is at [greeter_server.cc](examples/cpp/helloworld/greeter_server.cc). ### Try it! Build client and server: @@ -62,4 +62,4 @@ If things go smoothly, you will see the "Greeter received: Hello world" in the c ## Tutorial -You can find a more detailed tutorial in [gRPC Basics: C++](https://github.com/grpc/grpc-common/blob/master/cpp/cpptutorial.md) +You can find a more detailed tutorial in [gRPC Basics: C++](examples/cpp/cpptutorial.md) diff --git a/examples/cpp/cpptutorial.md b/examples/cpp/cpptutorial.md index c19b472744..22be42d500 100644 --- a/examples/cpp/cpptutorial.md +++ b/examples/cpp/cpptutorial.md @@ -6,7 +6,7 @@ This tutorial provides a basic C++ programmer's introduction to working with gRP - Generate server and client code using the protocol buffer compiler. - Use the C++ gRPC API to write a simple client and server for your service. -It assumes that you have read the [Getting started](https://github.com/grpc/grpc-common) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release: you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. +It assumes that you have read the [Getting started](https://github.com/grpc/grpc/tree/master/examples) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release: you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. This isn't a comprehensive guide to using gRPC in C++: more reference documentation is coming soon. @@ -18,22 +18,22 @@ With gRPC we can define our service once in a .proto file and implement clients ## Example code and setup -The example code for our tutorial is in [grpc/grpc-common/cpp/route_guide](https://github.com/grpc/grpc-common/tree/master/cpp/route_guide). To download the example, clone the `grpc-common` repository by running the following command: +The example code for our tutorial is in [examples/cpp/route_guide](examples/cpp/route_guide). To download the example, clone this repository by running the following command: ```shell -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Then change your current directory to `grpc-common/cpp/route_guide`: +Then change your current directory to `examples/cpp/route_guide`: ```shell -$ cd grpc-common/cpp/route_guide +$ cd examples/cpp/route_guide ``` -You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the C++ quick start guide](https://github.com/grpc/grpc-common/tree/master/cpp). +You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the C++ quick start guide](examples/cpp). ## Defining the service -Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc-common)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`grpc-common/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/protos/route_guide.proto). +Our first step (as you'll know from [Getting started](examples/) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto). To define a service, you specify a named `service` in your .proto file: @@ -91,7 +91,7 @@ message Point { Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C++ plugin. -For simplicity, we've provided a [makefile](https://github.com/grpc/grpc-common/blob/master/cpp/route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL) first): +For simplicity, we've provided a [makefile](examples/cpp/route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL) first): ```shell $ make route_guide.grpc.pb.cc route_guide.pb.cc @@ -126,7 +126,7 @@ There are two parts to making our `RouteGuide` service do its job: - Implementing the service interface generated from our service definition: doing the actual "work" of our service. - Running a gRPC server to listen for requests from clients and return the service responses. -You can find our example `RouteGuide` server in [grpc-common/cpp/route_guide/route_guide_server.cc](https://github.com/grpc/grpc-common/blob/master/cpp/route_guide/route_guide_server.cc). Let's take a closer look at how it works. +You can find our example `RouteGuide` server in [examples/cpp/route_guide/route_guide_server.cc](examples/cpp/route_guide/route_guide_server.cc). Let's take a closer look at how it works. ### Implementing RouteGuide @@ -236,7 +236,7 @@ As you can see, we build and start our server using a `ServerBuilder`. To do thi ## Creating the client -In this section, we'll look at creating a C++ client for our `RouteGuide` service. You can see our complete example client code in [grpc-common/cpp/route_guide/route_guide_client.cc](https://github.com/grpc/grpc-common/blob/master/cpp/route_guide/route_guide_client.cc). +In this section, we'll look at creating a C++ client for our `RouteGuide` service. You can see our complete example client code in [examples/cpp/route_guide/route_guide_client.cc](examples/cpp/route_guide/route_guide_client.cc). ### Creating a stub diff --git a/examples/cpp/helloworld/README.md b/examples/cpp/helloworld/README.md index c406051e80..641aadd52d 100644 --- a/examples/cpp/helloworld/README.md +++ b/examples/cpp/helloworld/README.md @@ -6,19 +6,19 @@ Make sure you have installed gRPC on your system. Follow the instructions here: ### Get the tutorial source code -The example code for this and our other examples lives in the `grpc-common` -GitHub repository. Clone this repository to your local machine by running the +The example code for this and our other examples lives in the `examples` +directory. Clone this repository to your local machine by running the following command: ```sh -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Change your current directory to grpc-common/cpp/helloworld +Change your current directory to examples/cpp/helloworld ```sh -$ cd grpc-common/cpp/helloworld/ +$ cd examples/cpp/helloworld/ ``` ### Defining a service @@ -34,7 +34,7 @@ types as protocol buffer message types. Both the client and the server use interface code generated from the service definition. Here's our example service definition, defined using protocol buffers IDL in -[helloworld.proto](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto). The `Greeting` +[helloworld.proto](examples/protos/helloworld.proto). The `Greeting` service has one method, `hello`, that lets the server receive a single `HelloRequest` message from the remote client containing the user's name, then send back @@ -124,7 +124,7 @@ $ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto } ``` -For a working example, refer to [greeter_client.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_client.cc). +For a working example, refer to [greeter_client.cc](examples/cpp/helloworld/greeter_client.cc). ### Writing a server @@ -152,7 +152,7 @@ For a working example, refer to [greeter_client.cc](https://github.com/grpc/grpc std::unique_ptr server(builder.BuildAndStart()); ``` -For a working example, refer to [greeter_server.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_server.cc). +For a working example, refer to [greeter_server.cc](examples/cpp/helloworld/greeter_server.cc). ### Writing asynchronous client and server @@ -194,7 +194,7 @@ The channel and stub creation code is the same as the sync client. } ``` -For a working example, refer to [greeter_async_client.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_async_client.cc). +For a working example, refer to [greeter_async_client.cc](examples/cpp/helloworld/greeter_async_client.cc). #### Async server @@ -253,7 +253,7 @@ maintain the state of each rpc and use the address of it as the unique tag. For simplicity the server only uses one completion queue for all events, and runs a main loop in `HandleRpcs` to query the queue. -For a working example, refer to [greeter_async_server.cc](https://github.com/grpc/grpc-common/blob/master/cpp/helloworld/greeter_async_server.cc). +For a working example, refer to [greeter_async_server.cc](examples/cpp/helloworld/greeter_async_server.cc). diff --git a/examples/csharp/README.md b/examples/csharp/README.md index 77d1aaf2e6..fcdcc735f9 100644 --- a/examples/csharp/README.md +++ b/examples/csharp/README.md @@ -69,4 +69,4 @@ On Linux or Mac, use `mono GreeterServer.exe` and `mono GreeterClient.exe` to ru Tutorial -------- -You can find a more detailed tutorial in [gRPC Basics: C#](https://github.com/grpc/grpc-common/blob/master/csharp/route_guide/README.md) +You can find a more detailed tutorial in [gRPC Basics: C#](examples/csharp/route_guide/README.md) diff --git a/examples/csharp/route_guide/README.md b/examples/csharp/route_guide/README.md index 35c6024bcf..c3262c9b8a 100644 --- a/examples/csharp/route_guide/README.md +++ b/examples/csharp/route_guide/README.md @@ -6,7 +6,7 @@ This tutorial provides a basic C# programmer's introduction to working with gRPC - Generate server and client code using the protocol buffer compiler. - Use the C# gRPC API to write a simple client and server for your service. -It assumes that you have read the [Getting started](https://github.com/grpc/grpc-common) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial only uses the proto2 version of the protocol buffers language, as proto3 support for C# is not ready yet (see [protobuf C# README](https://github.com/google/protobuf/tree/master/csharp#proto2--proto3)). +It assumes that you have read the [Getting started](https://github.com/grpc/grpc/tree/master/examples) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial only uses the proto2 version of the protocol buffers language, as proto3 support for C# is not ready yet (see [protobuf C# README](https://github.com/google/protobuf/tree/master/csharp#proto2--proto3)). This isn't a comprehensive guide to using gRPC in C#: more reference documentation is coming soon. @@ -18,13 +18,13 @@ With gRPC we can define our service once in a .proto file and implement clients ## Example code and setup -The example code for our tutorial is in [grpc/grpc-common/csharp/route_guide](https://github.com/grpc/grpc-common/tree/master/csharp/route_guide). To download the example, clone the `grpc-common` repository by running the following command: +The example code for our tutorial is in [examples/csharp/route_guide](examples/csharp/route_guide). To download the example, clone this repository by running the following command: ```shell -$ git clone https://github.com/google/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -All the files for this tutorial are in the directory `grpc-common/csharp/route_guide`. -Open the solution `grpc-common/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux). +All the files for this tutorial are in the directory `examples/csharp/route_guide`. +Open the solution `examples/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux). On Windows, you should not need to do anything besides opening the solution. All the needed dependencies will be restored for you automatically by the `Grpc` NuGet package upon building the solution. @@ -34,7 +34,7 @@ able to generate the server and client interface code and run the examples. Foll ## Defining the service -Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc-common)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`grpc-common/csharp/route_guide/RouteGuide/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/sharp/route_guide/RouteGuide/protos/route_guide.proto). +Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/csharp/route_guide/RouteGuide/protos/route_guide.proto`](examples/csharp/route_guide/RouteGuide/protos/route_guide.proto). To define a service, you specify a named `service` in your .proto file: @@ -127,7 +127,7 @@ There are two parts to making our `RouteGuide` service do its job: - Implementing the service interface generated from our service definition: doing the actual "work" of our service. - Running a gRPC server to listen for requests from clients and return the service responses. -You can find our example `RouteGuide` server in [grpc-common/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs](https://github.com/grpc/grpc-common/blob/master/csharp/route_guide/RouteGuideServer/RouteGuideServerImpl.cs). Let's take a closer look at how it works. +You can find our example `RouteGuide` server in [examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs](examples/csharp/route_guide/RouteGuideServer/RouteGuideServerImpl.cs). Let's take a closer look at how it works. ### Implementing RouteGuide @@ -288,7 +288,7 @@ As you can see, we build and start our server using `Grpc.Core.Server` class. To ## Creating the client -In this section, we'll look at creating a C# client for our `RouteGuide` service. You can see our complete example client code in [grpc-common/csharp/route_guide/RouteGuideClient/Program.cs](https://github.com/grpc/grpc-common/blob/master/csharp/route_guide/RouteGuideClient/Program.cs). +In this section, we'll look at creating a C# client for our `RouteGuide` service. You can see our complete example client code in [examples/csharp/route_guide/RouteGuideClient/Program.cs](examples/csharp/route_guide/RouteGuideClient/Program.cs). ### Creating a stub @@ -390,7 +390,7 @@ Finally, let's look at our bidirectional streaming RPC `RouteChat`. In this case Build client and server: -Open the solution `grpc-common/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux) and hit "Build". +Open the solution `examples/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux) and hit "Build". Run the server, which will listen on port 50052: ``` diff --git a/examples/node/README.md b/examples/node/README.md index 8c24a960a3..045fe51ede 100644 --- a/examples/node/README.md +++ b/examples/node/README.md @@ -18,13 +18,13 @@ INSTALL - Clone this repository ```sh - $ git clone https://github.com/grpc/grpc-common.git + $ git clone https://github.com/grpc/grpc.git ``` - Install this package's dependencies ```sh - $ cd grpc-common/node + $ cd examples/node $ npm install ``` @@ -57,4 +57,4 @@ You can find a more detailed tutorial in [gRPC Basics: Node.js][] [homebrew]:http://brew.sh [linuxbrew]:https://github.com/Homebrew/linuxbrew#installation [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install -[gRPC Basics: Node.js]:https://github.com/grpc/grpc-common/blob/master/node/route_guide/README.md +[gRPC Basics: Node.js]:https://github.com/grpc/grpc/blob/master/examples/node/route_guide/README.md diff --git a/examples/node/route_guide/README.md b/examples/node/route_guide/README.md index 5460c9905d..2efc5a5da5 100644 --- a/examples/node/route_guide/README.md +++ b/examples/node/route_guide/README.md @@ -5,7 +5,7 @@ This tutorial provides a basic Node.js programmer's introduction to working with - Define a service in a .proto file. - Use the Node.js gRPC API to write a simple client and server for your service. -It assumes that you have read the [Getting started](https://github.com/grpc/grpc-common) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release:you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. +It assumes that you have read the [Getting started](https://github.com/grpc/grpc/tree/master/examples) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release:you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. This isn't a comprehensive guide to using gRPC in Node.js: more reference documentation is coming soon. @@ -17,22 +17,22 @@ With gRPC we can define our service once in a .proto file and implement clients ## Example code and setup -The example code for our tutorial is in [grpc/grpc-common/node/route_guide](https://github.com/grpc/grpc-common/tree/master/node/route_guide). To download the example, clone the `grpc-common` repository by running the following command: +The example code for our tutorial is in [examples/node/route_guide](examples/node/route_guide). To download the example, clone this repository by running the following command: ```shell -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Then change your current directory to `grpc-common/node/route_guide`: +Then change your current directory to `examples/node/route_guide`: ```shell -$ cd grpc-common/node/route_guide +$ cd examples/node/route_guide ``` -You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Node.js quick start guide](https://github.com/grpc/grpc-common/tree/master/node). +You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Node.js quick start guide](examples/node). ## Defining the service -Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc-common)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`grpc-common/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/protos/route_guide.proto). +Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto). To define a service, you specify a named `service` in your .proto file: @@ -110,7 +110,7 @@ There are two parts to making our `RouteGuide` service do its job: - Implementing the service interface generated from our service definition: doing the actual "work" of our service. - Running a gRPC server to listen for requests from clients and return the service responses. -You can find our example `RouteGuide` server in [grpc-common/node/route_guide/route_guide_server.js](https://github.com/grpc/grpc-common/blob/master/node/route_guide/route_guide_server.js). Let's take a closer look at how it works. +You can find our example `RouteGuide` server in [examples/node/route_guide/route_guide_server.js](examples/node/route_guide/route_guide_server.js). Let's take a closer look at how it works. ### Implementing RouteGuide @@ -244,7 +244,7 @@ As you can see, we build and start our server with the following steps: ## Creating the client -In this section, we'll look at creating a Node.js client for our `RouteGuide` service. You can see our complete example client code in [grpc-common/node/route_guide/route_guide_client.js](https://github.com/grpc/grpc-common/blob/master/node/route_guide/route_guide_client.js). +In this section, we'll look at creating a Node.js client for our `RouteGuide` service. You can see our complete example client code in [examples/node/route_guide/route_guide_client.js](examples/node/route_guide/route_guide_client.js). ### Creating a stub diff --git a/examples/objective-c/auth_sample/README.md b/examples/objective-c/auth_sample/README.md index 4ca4982f53..3dbe7e334c 100644 --- a/examples/objective-c/auth_sample/README.md +++ b/examples/objective-c/auth_sample/README.md @@ -9,8 +9,8 @@ headers. - Read response metadata from a call, which is equivalent to HTTP response headers and trailers. It assumes you know the basics on how to make gRPC API calls using the Objective-C client library, -as shown in the [Hello World](https://github.com/grpc/grpc-common/tree/master/objective-c/helloworld) -or [Route Guide](https://github.com/grpc/grpc-common/tree/master/objective-c/route_guide) tutorials, +as shown in the [Hello World](examples/objective-c/helloworld) +or [Route Guide](examples/objective-c/route_guide) tutorials, and are familiar with OAuth2 concepts like _access token_. - [Example code and setup](#setup) @@ -22,15 +22,15 @@ and are familiar with OAuth2 concepts like _access token_. ## Example code and setup -The example code for our tutorial is in [grpc/grpc-common/objective-c/auth_sample](https://github.com/grpc/grpc-common/tree/master/objective-c/auth_sample). -To download the example, clone the `grpc-common` repository by running the following command: +The example code for our tutorial is in [examples/objective-c/auth_sample](examples/objective-c/auth_sample). +To download the example, clone this repository by running the following command: ```shell -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Then change your current directory to `grpc-common/objective-c/auth_sample`: +Then change your current directory to `examples/objective-c/auth_sample`: ```shell -$ cd grpc-common/objective-c/auth_sample +$ cd examples/objective-c/auth_sample ``` Our example is a simple application with two views. The first one lets a user sign in and out using diff --git a/examples/objective-c/helloworld/README.md b/examples/objective-c/helloworld/README.md index 685339e84a..3b852f857f 100644 --- a/examples/objective-c/helloworld/README.md +++ b/examples/objective-c/helloworld/README.md @@ -8,21 +8,21 @@ testing). You can obtain the latter by following [these setup instructions](http ## Hello Objective-C gRPC! -Here's how to build and run the Objective-C implementation of the [Hello World](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto) -example used in [Getting started](https://github.com/grpc/grpc-common). +Here's how to build and run the Objective-C implementation of the [Hello World](examples/protos/helloworld.proto) +example used in [Getting started](https://github.com/grpc/grpc/tree/master/examples). -The example code for this and our other examples lives in the `grpc-common` GitHub repository. Clone +The example code for this and our other examples lives in the `examples` directory. Clone this repository to your local machine by running the following command: ```sh -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Change your current directory to `grpc-common/objective-c/helloworld` +Change your current directory to `examples/objective-c/helloworld` ```sh -$ cd grpc-common/objective-c/helloworld +$ cd examples/objective-c/helloworld ``` ### Try it! @@ -53,4 +53,4 @@ responds with a `HLWHelloResponse`, which contains a string that is then output ## Tutorial -You can find a more detailed tutorial in [gRPC Basics: Objective-C](https://github.com/grpc/grpc-common/blob/master/objective-c/route_guide/README.md). +You can find a more detailed tutorial in [gRPC Basics: Objective-C](examples/objective-c/route_guide/README.md). diff --git a/examples/objective-c/route_guide/README.md b/examples/objective-c/route_guide/README.md index bbbd9e020d..dd20a07995 100644 --- a/examples/objective-c/route_guide/README.md +++ b/examples/objective-c/route_guide/README.md @@ -43,15 +43,15 @@ code is limited by the dynamic nature of the language. ## Example code and setup -The example code for our tutorial is in [grpc/grpc-common/objective-c/route_guide](https://github.com/grpc/grpc-common/tree/master/objective-c/route_guide). -To download the example, clone the `grpc-common` repository by running the following command: +The example code for our tutorial is in [examples/objective-c/route_guide](examples/objective-c/route_guide). +To download the example, clone this repository by running the following command: ```shell -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Then change your current directory to `grpc-common/objective-c/route_guide`: +Then change your current directory to `examples/objective-c/route_guide`: ```shell -$ cd grpc-common/objective-c/route_guide +$ cd examples/objective-c/route_guide ``` Our example is a simple route mapping application that lets clients get information about features @@ -97,7 +97,7 @@ a client library from it, and how to create an app that uses that library. First let's look at how the service we're using is defined. A gRPC *service* and its method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). -You can see the complete .proto file for our example in [`grpc-common/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/protos/route_guide.proto). +You can see the complete .proto file for our example in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto). To define a service, you specify a named `service` in your .proto file: @@ -177,9 +177,9 @@ option objc_class_prefix = "RTG"; Next we need to generate the gRPC client interfaces from our .proto service definition. We do this using the protocol buffer compiler (`protoc`) with a special gRPC Objective-C plugin. -For simplicity, we've provided a [Podspec file](https://github.com/grpc/grpc-common/blob/master/objective-c/route_guide/RouteGuide.podspec) +For simplicity, we've provided a [Podspec file](examples/objective-c/route_guide/RouteGuide.podspec) that runs `protoc` for you with the appropriate plugin, input, and output, and describes how to -compile the generated files. You just need to run in this directory (`grpc-common/objective-c/route_guide`): +compile the generated files. You just need to run in this directory (`examples/objective-c/route_guide`): ```shell $ pod install @@ -211,7 +211,7 @@ definition; just replace the name (matching the file name), version, and other m ## Creating the client In this section, we'll look at creating an Objective-C client for our `RouteGuide` service. You can -see our complete example client code in [grpc-common/objective-c/route_guide/ViewControllers.m](https://github.com/grpc/grpc-common/blob/master/objective-c/route_guide/ViewControllers.m). +see our complete example client code in [examples/objective-c/route_guide/ViewControllers.m](examples/objective-c/route_guide/ViewControllers.m). (Note: In your apps, for maintainability and readability reasons, you shouldn't put all of your view controllers in a single file; it's done here only to simplify the learning process). diff --git a/examples/php/README.md b/examples/php/README.md index 247235adfd..5c327f10fa 100644 --- a/examples/php/README.md +++ b/examples/php/README.md @@ -18,13 +18,13 @@ INSTALL - Clone this repository ```sh - $ git clone https://github.com/grpc/grpc-common.git + $ git clone https://github.com/grpc/grpc.git ``` - Install composer ``` - $ cd grpc-common/php + $ cd examples/php $ curl -sS https://getcomposer.org/installer | php $ php composer.phar install ``` @@ -36,14 +36,14 @@ TRY IT! Please follow the instruction in [Node][] to run the server ``` - $ cd grpc-common/node + $ cd examples/node $ nodejs greeter_server.js ``` - Run the client ``` - $ cd grpc-common/php + $ cd examples/php $ ./run_greeter_client.sh ``` @@ -61,4 +61,4 @@ Coming soon [homebrew]:http://brew.sh [linuxbrew]:https://github.com/Homebrew/linuxbrew#installation [gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install -[Node]:https://github.com/grpc/grpc-common/tree/master/node +[Node]:https://github.com/grpc/grpc/tree/master/examples/node diff --git a/examples/php/route_guide/README.md b/examples/php/route_guide/README.md index 084661a5eb..e5230ae4e4 100644 --- a/examples/php/route_guide/README.md +++ b/examples/php/route_guide/README.md @@ -8,7 +8,7 @@ This tutorial provides a basic PHP programmer's introduction to working with gRP It assumes a passing familiarity with [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto2 version of the protocol buffers language. -Also note that currently you can only create clients in PHP for gRPC services - you can find out how to create gRPC servers in our other tutorials, e.g. [Node.js](https://github.com/grpc/grpc-common/tree/master/node/route_guide). +Also note that currently you can only create clients in PHP for gRPC services - you can find out how to create gRPC servers in our other tutorials, e.g. [Node.js](examples/node/route_guide). This isn't a comprehensive guide to using gRPC in PHP: more reference documentation is coming soon. @@ -29,14 +29,14 @@ With gRPC you can define your service once in a .proto file and implement client ## Example code and setup -The example code for our tutorial is in [grpc/grpc-common/php/route_guide](https://github.com/grpc/grpc-common/tree/master/php/route_guide). To download the example, clone the `grpc-common` repository by running the following command: +The example code for our tutorial is in [examples/php/route_guide](examples/php/route_guide). To download the example, clone this repository by running the following command: ```shell -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Then change your current directory to `grpc-common/php/route_guide`: +Then change your current directory to `examples/php/route_guide`: ```shell -$ cd grpc-common/php/route_guide +$ cd examples/php/route_guide ``` Our example is a simple route mapping application that lets clients get information about features on their route, create a summary of their route, and exchange route information such as traffic updates with the server and other clients. @@ -68,7 +68,7 @@ The next sections guide you step-by-step through how this proto service is defin ## Defining the service -First let's look at how the service we're using is defined. A gRPC *service* and its method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file for our example in [`grpc-common/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/protos/route_guide.proto). +First let's look at how the service we're using is defined. A gRPC *service* and its method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file for our example in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto). To define a service, you specify a named `service` in your .proto file: @@ -128,7 +128,7 @@ message Point { The PHP client stub implementation of the proto files can be generated by the [`protoc-gen-php`](https://github.com/datto/protobuf-php) tool. To install the tool: ```sh -$ cd grpc-common/php +$ cd examples/php $ php composer.phar install $ cd vendor/datto/protobuf-php $ gem install rake ronn @@ -159,7 +159,7 @@ The file contains: ## Creating the client -In this section, we'll look at creating a PHP client for our `RouteGuide` service. You can see our complete example client code in [grpc-common/php/route_guide/route_guide_client.php](https://github.com/grpc/grpc-common/blob/master/php/route_guide/route_guide_client.php). +In this section, we'll look at creating a PHP client for our `RouteGuide` service. You can see our complete example client code in [examples/php/route_guide/route_guide_client.php](examples/php/route_guide/route_guide_client.php). ### Constructing a client object diff --git a/examples/python/helloworld/README.md b/examples/python/helloworld/README.md index 0a6a718bae..d199c401ec 100644 --- a/examples/python/helloworld/README.md +++ b/examples/python/helloworld/README.md @@ -1,6 +1,6 @@ # gRPC Python Hello World -This is a quick introduction with a simple example and installation instructions: for a more complete tutorial see [gRPC Basics: Python](https://github.com/grpc/grpc-common/tree/master/python/route_guide). +This is a quick introduction with a simple example and installation instructions: for a more complete tutorial see [gRPC Basics: Python](examples/python/route_guide). ### Install gRPC Make sure you have built gRPC Python from source on your system. Follow the instructions here: @@ -12,19 +12,19 @@ have cloned the [gRPC git repo](https://github.com/grpc/grpc). ### Get the source code -The example code for our Hello World and our other examples live in the `grpc-common` -GitHub repository. Clone this repository to your local machine by running the +The example code for our Hello World and our other examples live in the `examples` +directory. Clone this repository to your local machine by running the following command: ```sh -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Change your current directory to grpc-common/python/helloworld +Change your current directory to examples/python/helloworld ```sh -$ cd grpc-common/python/helloworld/ +$ cd examples/python/helloworld/ ``` ### Defining a service @@ -96,7 +96,7 @@ been generated for you (helloworld_pb2.py). ### The client -Client-side code can be found in [greeter_client.py](https://github.com/grpc/grpc-common/blob/master/python/helloworld/greeter_client.py). +Client-side code can be found in [greeter_client.py](examples/python/helloworld/greeter_client.py). You can run the client using: @@ -107,7 +107,7 @@ $ ./run_client.sh ### The server -Server side code can be found in [greeter_server.py](https://github.com/grpc/grpc-common/blob/master/python/helloworld/greeter_server.py). +Server side code can be found in [greeter_server.py](examples/python/helloworld/greeter_server.py). You can run the server using: diff --git a/examples/python/route_guide/README.md b/examples/python/route_guide/README.md index 91bef0ac00..dc97892ea5 100644 --- a/examples/python/route_guide/README.md +++ b/examples/python/route_guide/README.md @@ -6,7 +6,7 @@ This tutorial provides a basic Python programmer's introduction to working with - Generate server and client code using the protocol buffer compiler. - Use the Python gRPC API to write a simple client and server for your service. -It assumes that you have read the [Getting started](https://github.com/grpc/grpc-common) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release:you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. +It assumes that you have read the [Getting started](https://github.com/grpc/grpc/tree/master/examples) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release:you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. This isn't a comprehensive guide to using gRPC in Python: more reference documentation is coming soon. @@ -19,21 +19,21 @@ With gRPC you can define your service once in a .proto file and implement client ## Example code and setup -The example code for this tutorial is in [grpc/grpc-common/python/route_guide](https://github.com/grpc/grpc-common/tree/master/python/route_guide). To download the example, clone the `grpc-common` repository by running the following command: +The example code for this tutorial is in [examples/python/route_guide](examples/python/route_guide). To download the example, clone this repository by running the following command: ```shell -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Then change your current directory to `grpc-common/python/route_guide`: +Then change your current directory to `examples/python/route_guide`: ```shell -$ cd grpc-common/python/route_guide +$ cd examples/python/route_guide ``` -You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Python quick start guide](https://github.com/grpc/grpc-common/tree/master/python). +You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Python quick start guide](examples/python). ## Defining the service -Your first step (as you'll know from [Getting started](https://github.com/grpc/grpc-common)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`grpc-common/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/protos/route_guide.proto). +Your first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto). To define a service, you specify a named `service` in your .proto file: @@ -115,7 +115,7 @@ Creating and running a `RouteGuide` server breaks down into two work items: - Implementing the servicer interface generated from our service definition with functions that perform the actual "work" of the service. - Running a gRPC server to listen for requests from clients and transmit responses. -You can find the example `RouteGuide` server in [grpc-common/python/route_guide/route_guide_server.py](https://github.com/grpc/grpc-common/blob/master/python/route_guide/route_guide_server.py). +You can find the example `RouteGuide` server in [examples/python/route_guide/route_guide_server.py](examples/python/route_guide/route_guide_server.py). ### Implementing RouteGuide @@ -222,7 +222,7 @@ Because `start()` does not block you may need to sleep-loop if there is nothing ## Creating the client -You can see the complete example client code in [grpc-common/python/route_guide/route_guide_client.py](https://github.com/grpc/grpc-common/blob/master/python/route_guide/route_guide_client.py). +You can see the complete example client code in [examples/python/route_guide/route_guide_client.py](examples/python/route_guide/route_guide_client.py). ### Creating a stub diff --git a/examples/ruby/README.md b/examples/ruby/README.md index fecd8041e0..dc21f5dd49 100644 --- a/examples/ruby/README.md +++ b/examples/ruby/README.md @@ -55,7 +55,7 @@ Try it! Tutorial -------- -You can find a more detailed tutorial in [gRPC Basics: Ruby](https://github.com/grpc/grpc-common/blob/master/ruby/route_guide/README.md) +You can find a more detailed tutorial in [gRPC Basics: Ruby](examples/ruby/route_guide/README.md) -[helloworld.proto]:https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto +[helloworld.proto]:examples/protos/helloworld.proto [RVM]:https://www.rvm.io/ diff --git a/examples/ruby/grpc-demo.gemspec b/examples/ruby/grpc-demo.gemspec index fa69eb20c1..2cc1eb8f41 100644 --- a/examples/ruby/grpc-demo.gemspec +++ b/examples/ruby/grpc-demo.gemspec @@ -6,7 +6,7 @@ Gem::Specification.new do |s| s.version = '0.5.0' s.authors = ['gRPC Authors'] s.email = 'temiola@google.com' - s.homepage = 'https://github.com/grpc/grpc-common' + s.homepage = 'https://github.com/grpc/grpc' s.summary = 'gRPC Ruby overview sample' s.description = 'Simple demo of using gRPC from Ruby' diff --git a/examples/ruby/route_guide/README.md b/examples/ruby/route_guide/README.md index d22874799f..c7231fb43f 100644 --- a/examples/ruby/route_guide/README.md +++ b/examples/ruby/route_guide/README.md @@ -6,7 +6,7 @@ This tutorial provides a basic Ruby programmer's introduction to working with gR - Generate server and client code using the protocol buffer compiler. - Use the Ruby gRPC API to write a simple client and server for your service. -It assumes that you have read the [Getting started](https://github.com/grpc/grpc-common) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release:you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. +It assumes that you have read the [Getting started](https://github.com/grpc/grpc/tree/master/examples) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release:you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository. This isn't a comprehensive guide to using gRPC in Ruby: more reference documentation is coming soon. @@ -18,22 +18,22 @@ With gRPC we can define our service once in a .proto file and implement clients ## Example code and setup -The example code for our tutorial is in [grpc/grpc-common/ruby/route_guide](https://github.com/grpc/grpc-common/tree/master/ruby/route_guide). To download the example, clone the `grpc-common` repository by running the following command: +The example code for our tutorial is in [examples/ruby/route_guide](examples/ruby/route_guide). To download the example, clone this repository by running the following command: ```shell -$ git clone https://github.com/grpc/grpc-common.git +$ git clone https://github.com/grpc/grpc.git ``` -Then change your current directory to `grpc-common/ruby/route_guide`: +Then change your current directory to `examples/ruby/route_guide`: ```shell -$ cd grpc-common/ruby/route_guide +$ cd examples/ruby/route_guide ``` -You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Ruby quick start guide](https://github.com/grpc/grpc-common/tree/master/ruby). +You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Ruby quick start guide](examples/ruby). ## Defining the service -Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc-common)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`grpc-common/protos/route_guide.proto`](https://github.com/grpc/grpc-common/blob/master/protos/route_guide.proto). +Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto). To define a service, you specify a named `service` in your .proto file: @@ -116,7 +116,7 @@ There are two parts to making our `RouteGuide` service do its job: - Implementing the service interface generated from our service definition: doing the actual "work" of our service. - Running a gRPC server to listen for requests from clients and return the service responses. -You can find our example `RouteGuide` server in [grpc-common/ruby/route_guide/route_guide_server.rb](https://github.com/grpc/grpc-common/blob/master/ruby/route_guide/route_guide_server.rb). Let's take a closer look at how it works. +You can find our example `RouteGuide` server in [examples/ruby/route_guide/route_guide_server.rb](examples/ruby/route_guide/route_guide_server.rb). Let's take a closer look at how it works. ### Implementing RouteGuide @@ -199,7 +199,7 @@ As you can see, we build and start our server using a `GRPC::RpcServer`. To do t ## Creating the client -In this section, we'll look at creating a Ruby client for our `RouteGuide` service. You can see our complete example client code in [grpc-common/ruby/route_guide/route_guide_client.rb](https://github.com/grpc/grpc-common/blob/master/ruby/route_guide/route_guide_client.rb). +In this section, we'll look at creating a Ruby client for our `RouteGuide` service. You can see our complete example client code in [examples/ruby/route_guide/route_guide_client.rb](examples/ruby/route_guide/route_guide_client.rb). ### Creating a stub @@ -269,17 +269,17 @@ Although it's not shown well by this example, each enumerable is independent of Build client and server: ```shell -$ # from grpc-common/ruby +$ # from examples/ruby $ gem install bundler && bundle install ``` Run the server, which will listen on port 50051: ```shell -$ # from grpc-common/ruby +$ # from examples/ruby $ bundle exec route_guide/route_guide_server.rb ../node/route_guide/route_guide_db.json & ``` Run the client (in a different terminal): ```shell -$ # from grpc-common/ruby +$ # from examples/ruby $ bundle exec route_guide/route_guide_client.rb ../node/route_guide/route_guide_db.json & ``` diff --git a/src/csharp/README.md b/src/csharp/README.md index bb5e165986..30523b3bd2 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 ----------------- 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). ## Integrate a proto library in your project diff --git a/src/objective-c/tests/LocalClearTextTests.m b/src/objective-c/tests/LocalClearTextTests.m index 4317614dd9..d01fe91afa 100644 --- a/src/objective-c/tests/LocalClearTextTests.m +++ b/src/objective-c/tests/LocalClearTextTests.m @@ -42,7 +42,7 @@ #import // 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 -- cgit v1.2.3 From 240b7db1ca666a01f359fa1509be9c495b728827 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 27 Aug 2015 15:35:32 -0700 Subject: Outlaw comma in non-binary metadata values --- src/core/transport/metadata.c | 2 +- tools/codegen/core/gen_legal_metadata_characters.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') 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/tools/codegen/core/gen_legal_metadata_characters.c b/tools/codegen/core/gen_legal_metadata_characters.c index 5c290f2923..0fbc545d8d 100644 --- a/tools/codegen/core/gen_legal_metadata_characters.c +++ b/tools/codegen/core/gen_legal_metadata_characters.c @@ -66,7 +66,10 @@ int main(void) { dump(); clear(); - for (i = 32; i <= 126; i++) legal(i); + for (i = 32; i <= 126; i++) { + if (i == ',') continue; + legal(i); + } dump(); return 0; -- cgit v1.2.3 From 7d58abae60a829c5c763fbd5bf8aca85287f9d05 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Thu, 27 Aug 2015 16:11:08 -0700 Subject: Emit proper status when failing to parse server stream --- src/node/ext/call.cc | 23 +++++++++++++++++++++++ src/node/ext/call.h | 1 + src/node/src/client.js | 3 ++- 3 files changed, 26 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index fddc1e214f..560869e6fa 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -461,6 +461,9 @@ void Call::Init(Handle exports) { NanNew(StartBatch)->GetFunction()); NanSetPrototypeTemplate(tpl, "cancel", NanNew(Cancel)->GetFunction()); + NanSetPrototypeTemplate( + tpl, "cancelWithStatus", + NanNew(CancelWithStatus)->GetFunction()); NanSetPrototypeTemplate(tpl, "getPeer", NanNew(GetPeer)->GetFunction()); NanAssignPersistent(fun_tpl, tpl); @@ -643,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(args.This()); + grpc_status_code code = static_cast(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/src/client.js b/src/node/src/client.js index 2323caecc0..6a49490910 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -146,7 +146,8 @@ function _read(size) { try { deserialized = self.deserialize(data); } catch (e) { - self.cancel(); + self.call.cancelWithStatus(grpc.status.INTERNAL, + 'Failed to parse server response'); } if (self.push(deserialized) && data !== null) { var read_batch = {}; -- cgit v1.2.3 From e62f68cebb8a43f880542035ef8b3369ebb46f6b Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Thu, 27 Aug 2015 16:24:27 -0700 Subject: make metric part of view --- include/grpc/census.h | 59 ++++++++++++++++++++--------------------- src/core/census/rpc_metric_id.h | 12 ++++----- 2 files changed, 35 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/include/grpc/census.h b/include/grpc/census.h index 968f5825a5..77b93c1cb8 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -159,7 +159,7 @@ int census_tag_set_next(census_tag_set_iterator *it, census_tag_const *tag); invalidated, and should not be used once close is called. */ void census_tag_set_close(census_tag_set_iterator *it); -/* Core stats collection API's. There following concepts are used: +/* Core stats collection API's. The following concepts are used: * Aggregation: A collection of values. Census supports the following aggregation types: Scalar - a single scalar value. Typically used for keeping (e.g.) @@ -174,18 +174,18 @@ void census_tag_set_close(census_tag_set_iterator *it); * Metric: Each measurement is for a single metric. Examples include RPC latency, CPU seconds consumed, and bytes transmitted. * View: A view is a tag set, in which the tag values are regular expressions, - combined with an arbitrary number of aggregations and their initialization - parameters. + combined with a metric and an arbitrary number of aggregations and their + initialization parameters. Each metric can have an arbitrary number of views by which it will be broken down. For every measurement recorded, they are broken down by - unique tag combinations, and recorded in each matvhing view/aggregation. + unique tag combinations, and recorded in each matching view/aggregation. */ /* A single value to be recorded comprises two parts: an ID for the particular * metric and the value to be recorded against it. */ typedef struct { - gpr_int32 metric_id; + gpr_uint32 metric_id; double value; } census_value; @@ -210,25 +210,30 @@ typedef struct { void (*free_data)(const 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. */ + void (*print)(const void *aggregation, char *buffer, size_t n); } census_aggregation_descriptor; /** Register a new aggregation type. @param descriptor Describes aggregation @return An identifier that can be used to identify the aggregation in other census functions. */ -gpr_int32 census_register_aggregation( +gpr_uint32 census_register_aggregation( const census_aggregation_descriptor *descriptor); /* Aggregation Identifiers for built-in census aggregations. */ -#define CENSUS_AGGREGATION_ID_SCALAR ((gpr_int32)0) -#define CENSUS_AGGREGATION_ID_DISTRIBUTION ((gpr_int32)1) -#define CENSUS_AGGREGATION_ID_HISTOGRAM ((gpr_int32)2) -#define CENSUS_AGGREGATION_ID_WINDOW ((gpr_int32)3) +#define CENSUS_AGGREGATION_ID_SCALAR ((gpr_uint32)0) +#define CENSUS_AGGREGATION_ID_DISTRIBUTION ((gpr_uint32)1) +#define CENSUS_AGGREGATION_ID_HISTOGRAM ((gpr_uint32)2) +#define CENSUS_AGGREGATION_ID_WINDOW ((gpr_uint32)3) /** Information needed to instantiate a new aggregation. Used in view construction via census_define_view(). */ typedef struct { - gpr_int32 id; /* aggregation ID */ + gpr_uint32 id; /* aggregation ID */ const void *create_arg; /* Argument to be used for aggregation initialization. */ } census_aggregation; @@ -237,16 +242,21 @@ typedef struct { typedef struct census_view census_view; /** Create a new view. + @param metric_id Metric with which this view is associated. @param tags tags that define the view @param aggregations aggregations to associate with the view @param naggregations number of aggregations @return A new census view */ -const census_view *census_define_view(const census_tag_set *tags, +const census_view *census_define_view(gpr_uint32 metric_id, + const census_tag_set *tags, const census_aggregation *aggregations, size_t naggregations); +/** Metric ID associated with a view */ +size_t census_view_metric(const census_view *view); + /** Number of aggregations associated with view. */ size_t census_view_naggregations(const census_view *view); @@ -256,15 +266,6 @@ const census_tag_set *census_view_tags(const census_view *view); /** Get aggregations associated with a view. */ const census_aggregation *census_view_aggregrations(const census_view *view); -/** Associate a given view with a metric. Every metric can have many different - views. - @param metric_id Identifier of metric with which to attah the view - @param view View to attach to the metric - @return A view identifier: can be used to retrieve aggregation data from - the view using census_view_data(). -*/ -gpr_int64 census_attach_view(gpr_int32 metric_id, const census_view *view); - /** Holds aggregation data, as it applies to a particular view. This structure is used as one component of the data returned from census_get_view_data(). */ typedef struct { @@ -288,25 +289,23 @@ typedef struct { /** Census view data as returned by census_get_view_data(). */ typedef struct { - const census_view *view; /* Original view */ - size_t n_tag_sets; /* Number of unique tag sets that matched view. */ + size_t n_tag_sets; /* Number of unique tag sets that matched view. */ const census_view_aggregation_data *data; /* n_tag_sets entries */ } census_view_data; /** Get data from aggregations associated with a view. - @param view_id View identifier returned from census_attach_view - @param aggregation_indices Indexes of aggregations (relative to original view) - for which to return current data. This parameter is ignored if - nindices == 0. + @param view View from which to get data. + @param aggregation_indices Indexes of view aggregations for which to return + current data. This parameter is ignored if nindices == 0. @param nindices. Number of entries in aggregation_indices. If this is set to - 0, then all aggregations for the current view are returned. + 0, then all aggregations are returned. */ -const census_view_data *census_get_view_data(gpr_int64 view_id, +const census_view_data *census_get_view_data(census_view *view, size_t *aggregation_indices, size_t nindices); /** Reset all view data to zero for the specified view id. */ -void census_reset_view_data(gpr_int64 view_id); +void census_reset_view_data(gpr_uint64 view_id); #ifdef __cplusplus } diff --git a/src/core/census/rpc_metric_id.h b/src/core/census/rpc_metric_id.h index 2cd30c2fc0..1d8e8806f5 100644 --- a/src/core/census/rpc_metric_id.h +++ b/src/core/census/rpc_metric_id.h @@ -36,16 +36,16 @@ /* Metric ID's used for RPC measurements. */ /* Count of client requests sent. */ -#define CENSUS_METRIC_RPC_CLIENT_REQUESTS ((gpr_int32)0) +#define CENSUS_METRIC_RPC_CLIENT_REQUESTS ((gpr_uint32)0) /* Count of server requests sent. */ -#define CENSUS_METRIC_RPC_SERVER_REQUESTS ((gpr_int32)1) +#define CENSUS_METRIC_RPC_SERVER_REQUESTS ((gpr_uint32)1) /* Client error counts. */ -#define CENSUS_METRIC_RPC_CLIENT_ERRORS ((gpr_int32)2) +#define CENSUS_METRIC_RPC_CLIENT_ERRORS ((gpr_uint32)2) /* Server error counts. */ -#define CENSUS_METRIC_RPC_SERVER_ERRORS ((gpr_int32)3) +#define CENSUS_METRIC_RPC_SERVER_ERRORS ((gpr_uint32)3) /* Client side request latency. */ -#define CENSUS_METRIC_RPC_CLIENT_LATENCY ((gpr_int32)4) +#define CENSUS_METRIC_RPC_CLIENT_LATENCY ((gpr_uint32)4) /* Server side request latency. */ -#define CENSUS_METRIC_RPC_SERVER_LATENCY ((gpr_int32)5) +#define CENSUS_METRIC_RPC_SERVER_LATENCY ((gpr_uint32)5) #endif /* CENSUS_RPC_METRIC_ID_H */ -- cgit v1.2.3 From 63720d4ecf690051744e331e2afb6e0a5a9d45cc Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Thu, 27 Aug 2015 17:22:16 -0700 Subject: Python service account cleanup. --- src/python/grpcio/grpc/_adapter/_c/types.h | 2 -- .../grpc/_adapter/_c/types/client_credentials.c | 2 -- .../grpcio/grpc/_cython/_cygrpc/credentials.pyx | 20 -------------------- src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd | 2 -- src/python/grpcio/grpc/_cython/adapter_low.py | 4 ---- src/python/grpcio_test/grpc_interop/methods.py | 17 ----------------- 6 files changed, 47 deletions(-) (limited to 'src') 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/client_credentials.c b/src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c index 9554796631..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, 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 c793774c8d..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( 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 @@ -59,10 +59,6 @@ class ClientCredentials(object): def compute_engine(): raise NotImplementedError() - @staticmethod - def service_account(): - raise NotImplementedError() - @staticmethod def jwt(): raise NotImplementedError() diff --git a/src/python/grpcio_test/grpc_interop/methods.py b/src/python/grpcio_test/grpc_interop/methods.py index 7a831f3cbd..19a1e17c3e 100644 --- a/src/python/grpcio_test/grpc_interop/methods.py +++ b/src/python/grpcio_test/grpc_interop/methods.py @@ -346,20 +346,6 @@ def _compute_engine_creds(stub, args): response.username)) -def _service_account_creds(stub, args): - json_key_filename = os.environ[ - oauth2client_client.GOOGLE_APPLICATION_CREDENTIALS] - wanted_email = json.load(open(json_key_filename, 'rb'))['client_email'] - response = _large_unary_common_behavior(stub, True, True) - if wanted_email != response.username: - raise ValueError( - 'expected username %s, got %s' % (wanted_email, response.username)) - if args.oauth_scope.find(response.oauth_scope) == -1: - raise ValueError( - 'expected to find oauth scope "%s" in received "%s"' % - (response.oauth_scope, args.oauth_scope)) - - @enum.unique class TestCase(enum.Enum): EMPTY_UNARY = 'empty_unary' @@ -370,7 +356,6 @@ 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' TIMEOUT_ON_SLEEPING_SERVER = 'timeout_on_sleeping_server' def test_interoperability(self, stub, args): @@ -392,7 +377,5 @@ 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) else: raise NotImplementedError('Test case "%s" not implemented!' % self.name) -- cgit v1.2.3 From 0908c23c442f0fdf586dae064ad9adf551e4f028 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Fri, 28 Aug 2015 03:04:04 +0000 Subject: Expand force_client_auth to old ServerCredentials --- src/python/grpcio/grpc/_adapter/_intermediary_low.py | 4 ++-- src/python/grpcio/grpc/_adapter/fore.py | 2 +- src/python/grpcio/grpc/_links/service.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/_adapter/_intermediary_low.py b/src/python/grpcio/grpc/_adapter/_intermediary_low.py index 1fb6a2b27d..06358e72bc 100644 --- a/src/python/grpcio/grpc/_adapter/_intermediary_low.py +++ b/src/python/grpcio/grpc/_adapter/_intermediary_low.py @@ -255,6 +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): + def __init__(self, root_credentials, pair_sequence, force_client_auth): self._internal = _low.ServerCredentials.ssl( - root_credentials, list(pair_sequence), False) + 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/_links/service.py b/src/python/grpcio/grpc/_links/service.py index 43c4c0e80c..10634e43b5 100644 --- a/src/python/grpcio/grpc/_links/service.py +++ b/src/python/grpcio/grpc/_links/service.py @@ -366,10 +366,10 @@ class ServiceLink(links.Link): """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. + port: The port on which to service RPCs, or zero to request that a port + 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. -- cgit v1.2.3 From 67c4587c88018ab5dc8919d9e5a7416cc88bd69a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 27 Aug 2015 18:12:39 -0700 Subject: error spec compliance and marshalling tests --- src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj | 1 + .../Grpc.Core.Tests/MarshallingErrorsTest.cs | 176 +++++++++++++++++++++ src/csharp/Grpc.Core.Tests/MockServiceHelper.cs | 80 +++++----- src/csharp/Grpc.Core/Internal/AsyncCall.cs | 17 +- src/csharp/Grpc.Core/Internal/AsyncCallBase.cs | 50 +++--- src/csharp/Grpc.Core/Internal/AsyncCallServer.cs | 5 + src/csharp/Grpc.Core/Marshaller.cs | 2 +- .../Grpc.Examples.Tests/MathClientServerTests.cs | 2 +- .../HealthClientServerTest.cs | 2 +- .../HealthServiceImplTest.cs | 2 +- .../Grpc.IntegrationTesting/InteropClient.cs | 5 +- 11 files changed, 273 insertions(+), 69 deletions(-) create mode 100644 src/csharp/Grpc.Core.Tests/MarshallingErrorsTest.cs (limited to 'src') 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 @@ Version.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( + (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((request, context) => + { + return Task.FromResult("UNPARSEABLE_VALUE"); + }); + + var ex = Assert.Throws(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "REQUEST")); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + [Test] + public void ResponseParsingError_StreamingResponse() + { + helper.ServerStreamingHandler = new ServerStreamingServerMethod(async (request, responseStream, context) => + { + await responseStream.WriteAsync("UNPARSEABLE_VALUE"); + await Task.Delay(10000); + }); + + var call = Calls.AsyncServerStreamingCall(helper.CreateServerStreamingCall(), "REQUEST"); + var ex = Assert.Throws(async () => await call.ResponseStream.MoveNext()); + Assert.AreEqual(StatusCode.Internal, ex.Status.StatusCode); + } + + [Test] + public void RequestParsingError_UnaryRequest() + { + helper.UnaryHandler = new UnaryServerMethod((request, context) => + { + return Task.FromResult("RESPONSE"); + }); + + var ex = Assert.Throws(() => 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(async (requestStream, context) => + { + Assert.Throws(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(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); + } + + [Test] + public void RequestSerializationError_AsyncUnary() + { + Assert.Throws(async () => await Calls.AsyncUnaryCall(helper.CreateUnaryCall(), "UNSERIALIZABLE_VALUE")); + } + + [Test] + public async Task RequestSerializationError_ClientStreaming() + { + helper.ClientStreamingHandler = new ClientStreamingServerMethod(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(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/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 UnaryMethod = new Method( - MethodType.Unary, - ServiceName, - "Unary", - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - - public static readonly Method ClientStreamingMethod = new Method( - MethodType.ClientStreaming, - ServiceName, - "ClientStreaming", - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - - public static readonly Method ServerStreamingMethod = new Method( - MethodType.ServerStreaming, - ServiceName, - "ServerStreaming", - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - - public static readonly Method DuplexStreamingMethod = new Method( - MethodType.DuplexStreaming, - ServiceName, - "DuplexStreaming", - Marshallers.StringMarshaller, - Marshallers.StringMarshaller); - readonly string host; readonly ServerServiceDefinition serviceDefinition; + readonly Method unaryMethod; + readonly Method clientStreamingMethod; + readonly Method serverStreamingMethod; + readonly Method duplexStreamingMethod; + UnaryServerMethod unaryHandler; ClientStreamingServerMethod clientStreamingHandler; ServerStreamingServerMethod serverStreamingHandler; @@ -89,15 +66,44 @@ namespace Grpc.Core.Tests Server server; Channel channel; - public MockServiceHelper(string host = null) + public MockServiceHelper(string host = null, Marshaller marshaller = null) { this.host = host ?? "localhost"; + marshaller = marshaller ?? Marshallers.StringMarshaller; + + unaryMethod = new Method( + MethodType.Unary, + ServiceName, + "Unary", + marshaller, + marshaller); + + clientStreamingMethod = new Method( + MethodType.ClientStreaming, + ServiceName, + "ClientStreaming", + marshaller, + marshaller); + + serverStreamingMethod = new Method( + MethodType.ServerStreaming, + ServiceName, + "ServerStreaming", + marshaller, + marshaller); + + duplexStreamingMethod = new Method( + 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 CreateUnaryCall(CallOptions options = default(CallOptions)) { - return new CallInvocationDetails(channel, UnaryMethod, options); + return new CallInvocationDetails(channel, unaryMethod, options); } public CallInvocationDetails CreateClientStreamingCall(CallOptions options = default(CallOptions)) { - return new CallInvocationDetails(channel, ClientStreamingMethod, options); + return new CallInvocationDetails(channel, clientStreamingMethod, options); } public CallInvocationDetails CreateServerStreamingCall(CallOptions options = default(CallOptions)) { - return new CallInvocationDetails(channel, ServerStreamingMethod, options); + return new CallInvocationDetails(channel, serverStreamingMethod, options); } public CallInvocationDetails CreateDuplexStreamingCall(CallOptions options = default(CallOptions)) { - return new CallInvocationDetails(channel, DuplexStreamingMethod, options); + return new CallInvocationDetails(channel, duplexStreamingMethod, options); } public string Host 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 /// 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 { static readonly ILogger Logger = GrpcEnvironment.Logger.ForType>(); + protected static readonly Status DeserializeResponseFailureStatus = new Status(StatusCode.Internal, "Failed to deserialize response message."); readonly Func serializer; readonly Func deserializer; @@ -100,11 +103,10 @@ namespace Grpc.Core.Internal /// /// Requests cancelling the call with given status. /// - 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 /// protected void HandleReadFinished(bool success, byte[] receivedMessage) { + TRead msg = default(TRead); + var deserializeException = (success && receivedMessage != null) ? TryDeserialize(receivedMessage, out msg) : null; + AsyncCompletionDelegate 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 /// /// Encapsulates the logic for serializing and deserializing messages. /// - public struct Marshaller + public class Marshaller { readonly Func serializer; readonly Func deserializer; diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs index d8547758d2..e2975b5da9 100644 --- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs +++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs @@ -162,7 +162,7 @@ namespace Math.Tests { using (var call = client.Sum()) { - var numbers = new List { 10, 20, 30 }.ConvertAll(n => new Num{ Num_ = n }); + var numbers = new List { 10, 20, 30 }.ConvertAll(n => new Num { Num_ = n }); await call.RequestStream.WriteAllAsync(numbers); var result = await call.ResponseAsync; diff --git a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs index 95f742cc99..6c3a53bec0 100644 --- a/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs +++ b/src/csharp/Grpc.HealthCheck.Tests/HealthClientServerTest.cs @@ -88,7 +88,7 @@ namespace Grpc.HealthCheck.Tests [Test] public void ServiceDoesntExist() { - Assert.Throws(Is.TypeOf(typeof(RpcException)).And.Property("Status").Property("StatusCode").EqualTo(StatusCode.NotFound), () => client.Check(new HealthCheckRequest{ Host = "", Service = "nonexistent.service" })); + 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 8de8645cd1..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(new HealthCheckRequest{ Host = host, Service = service}, null).Result.Status; + return impl.Check(new HealthCheckRequest { Host = host, Service = service }, null).Result.Status; } } } diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index ed51af1942..8343e54122 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -37,13 +37,12 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Google.Apis.Auth.OAuth2; +using Google.Protobuf; using Grpc.Auth; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; -using Google.Protobuf; -using Google.Apis.Auth.OAuth2; - using NUnit.Framework; namespace Grpc.IntegrationTesting -- cgit v1.2.3 From 9f80fcf8e79d71e99b28f152a7b8662d815a6ee2 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 28 Aug 2015 08:22:48 -0700 Subject: Cleaning up Windows endpoint code - removed the need to track some state - fixed chttp2 transport endpoint shutdown management - made a bunch of tests pass --- src/core/iomgr/iocp_windows.c | 20 +----- src/core/iomgr/iocp_windows.h | 1 - src/core/iomgr/socket_windows.c | 41 ++---------- src/core/iomgr/socket_windows.h | 16 +---- src/core/iomgr/tcp_client_windows.c | 9 +-- src/core/iomgr/tcp_server_windows.c | 6 +- src/core/iomgr/tcp_windows.c | 114 ++++++++++------------------------ src/core/transport/chttp2/internal.h | 3 + src/core/transport/chttp2_transport.c | 32 ++++++++-- test/core/iomgr/endpoint_pair_test.c | 7 --- test/core/iomgr/endpoint_tests.c | 111 +++++++-------------------------- 11 files changed, 100 insertions(+), 260 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c index 09a457dd9a..0799622497 100644 --- a/src/core/iomgr/iocp_windows.c +++ b/src/core/iomgr/iocp_windows.c @@ -52,7 +52,6 @@ static OVERLAPPED g_iocp_custom_overlap; static gpr_event g_shutdown_iocp; static gpr_event g_iocp_done; -static gpr_atm g_orphans = 0; static gpr_atm g_custom_events = 0; static HANDLE g_iocp; @@ -92,22 +91,13 @@ static void do_iocp_work() { gpr_log(GPR_ERROR, "Unknown IOCP operation"); abort(); } - GPR_ASSERT(info->outstanding); - if (socket->orphan) { - info->outstanding = 0; - if (!socket->read_info.outstanding && !socket->write_info.outstanding) { - grpc_winsocket_destroy(socket); - gpr_atm_full_fetch_add(&g_orphans, -1); - } - return; - } success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, FALSE, &flags); info->bytes_transfered = bytes; info->wsa_error = success ? 0 : WSAGetLastError(); GPR_ASSERT(overlapped == &info->overlapped); - gpr_mu_lock(&socket->state_mu); GPR_ASSERT(!info->has_pending_iocp); + gpr_mu_lock(&socket->state_mu); if (info->cb) { f = info->cb; opaque = info->opaque; @@ -120,7 +110,7 @@ static void do_iocp_work() { } static void iocp_loop(void *p) { - while (gpr_atm_acq_load(&g_orphans) || gpr_atm_acq_load(&g_custom_events) || + while (gpr_atm_acq_load(&g_custom_events) || !gpr_event_get(&g_shutdown_iocp)) { grpc_maybe_call_delayed_callbacks(NULL, 1); do_iocp_work(); @@ -175,12 +165,6 @@ void grpc_iocp_add_socket(grpc_winsocket *socket) { GPR_ASSERT(ret == g_iocp); } -void grpc_iocp_socket_orphan(grpc_winsocket *socket) { - GPR_ASSERT(!socket->orphan); - gpr_atm_full_fetch_add(&g_orphans, 1); - socket->orphan = 1; -} - /* Calling notify_on_read or write means either of two things: -) The IOCP already completed in the background, and we need to call the callback now. diff --git a/src/core/iomgr/iocp_windows.h b/src/core/iomgr/iocp_windows.h index ee3847a229..7d2dc45176 100644 --- a/src/core/iomgr/iocp_windows.h +++ b/src/core/iomgr/iocp_windows.h @@ -42,7 +42,6 @@ void grpc_iocp_init(void); void grpc_iocp_kick(void); void grpc_iocp_shutdown(void); void grpc_iocp_add_socket(grpc_winsocket *); -void grpc_iocp_socket_orphan(grpc_winsocket *); void grpc_socket_notify_on_write(grpc_winsocket *, void (*cb)(void *, int success), void *opaque); diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c index 7d8421376b..dbc64637b5 100644 --- a/src/core/iomgr/socket_windows.c +++ b/src/core/iomgr/socket_windows.c @@ -62,46 +62,13 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) { operations to abort them. We need to do that this way because of the various callsites of that function, which happens to be in various mutex hold states, and that'd be unsafe to call them directly. */ -int grpc_winsocket_shutdown(grpc_winsocket *winsocket) { - int callbacks_set = 0; - SOCKET socket; - gpr_mu_lock(&winsocket->state_mu); - socket = winsocket->socket; - if (winsocket->read_info.cb) { - callbacks_set++; - grpc_iomgr_closure_init(&winsocket->shutdown_closure, - winsocket->read_info.cb, - winsocket->read_info.opaque); - grpc_iomgr_add_delayed_callback(&winsocket->shutdown_closure, 0); - } - if (winsocket->write_info.cb) { - callbacks_set++; - grpc_iomgr_closure_init(&winsocket->shutdown_closure, - winsocket->write_info.cb, - winsocket->write_info.opaque); - grpc_iomgr_add_delayed_callback(&winsocket->shutdown_closure, 0); - } - gpr_mu_unlock(&winsocket->state_mu); - closesocket(socket); - return callbacks_set; -} - -/* Abandons a socket. Either we're going to queue it up for garbage collecting - from the IO Completion Port thread, or destroy it immediately. Note that this - mechanisms assumes that we're either always waiting for an operation, or we - explicitly know that we don't. If there is a future case where we can have - an "idle" socket which is neither trying to read or write, we'd start leaking - both memory and sockets. */ -void grpc_winsocket_orphan(grpc_winsocket *winsocket) { - grpc_iomgr_unregister_object(&winsocket->iomgr_object); - if (winsocket->read_info.outstanding || winsocket->write_info.outstanding) { - grpc_iocp_socket_orphan(winsocket); - } else { - grpc_winsocket_destroy(winsocket); - } +void grpc_winsocket_shutdown(grpc_winsocket *winsocket) { + shutdown(winsocket->socket, SD_BOTH); } void grpc_winsocket_destroy(grpc_winsocket *winsocket) { + closesocket(winsocket->socket); + grpc_iomgr_unregister_object(&winsocket->iomgr_object); gpr_mu_destroy(&winsocket->state_mu); gpr_free(winsocket); } diff --git a/src/core/iomgr/socket_windows.h b/src/core/iomgr/socket_windows.h index ecf2530173..498921e0fd 100644 --- a/src/core/iomgr/socket_windows.h +++ b/src/core/iomgr/socket_windows.h @@ -68,8 +68,6 @@ typedef struct grpc_winsocket_callback_info { /* The results of the overlapped operation. */ DWORD bytes_transfered; int wsa_error; - /* A boolean indicating that we started an operation. */ - int outstanding; } grpc_winsocket_callback_info; /* This is a wrapper to a Windows socket. A socket can have one outstanding @@ -92,10 +90,6 @@ typedef struct grpc_winsocket { /* You can't add the same socket twice to the same IO Completion Port. This prevents that. */ int added_to_iocp; - /* A boolean to indicate that the caller has abandoned that socket, but - there is a pending operation that the IO Completion Port will have to - wait for. The socket will be collected at that time. */ - int orphan; grpc_iomgr_closure shutdown_closure; @@ -108,14 +102,10 @@ typedef struct grpc_winsocket { grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name); /* Initiate an asynchronous shutdown of the socket. Will call off any pending - operation to cancel them. Returns the number of callbacks that got setup. */ -int grpc_winsocket_shutdown(grpc_winsocket *socket); + operation to cancel them. */ +void grpc_winsocket_shutdown(grpc_winsocket *socket); -/* Abandon a socket. */ -void grpc_winsocket_orphan(grpc_winsocket *socket); - -/* Destroy a socket. Should only be called by the IO Completion Port thread, - or by grpc_winsocket_orphan if there's no pending operation. */ +/* Destroy a socket. Should only be called if there's no pending operation. */ void grpc_winsocket_destroy(grpc_winsocket *socket); #endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKET_WINDOWS_H */ diff --git a/src/core/iomgr/tcp_client_windows.c b/src/core/iomgr/tcp_client_windows.c index 79a58fe2af..665ef2885f 100644 --- a/src/core/iomgr/tcp_client_windows.c +++ b/src/core/iomgr/tcp_client_windows.c @@ -102,7 +102,6 @@ static void on_connect(void *acp, int from_iocp) { DWORD flags; BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, &transfered_bytes, FALSE, &flags); - info->outstanding = 0; GPR_ASSERT(transfered_bytes == 0); if (!wsa_success) { char *utf8_message = gpr_format_message(WSAGetLastError()); @@ -125,12 +124,10 @@ static void on_connect(void *acp, int from_iocp) { return; } - ac->socket->write_info.outstanding = 0; - /* If we don't have an endpoint, it means the connection failed, so it doesn't matter if it aborted or failed. We need to orphan that socket. */ - if (!ep || aborted) grpc_winsocket_orphan(ac->socket); + if (!ep || aborted) grpc_winsocket_destroy(ac->socket); async_connect_cleanup(ac); /* If the connection was aborted, the callback was already called when the deadline was met. */ @@ -196,7 +193,6 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp), socket = grpc_winsocket_create(sock, "client"); info = &socket->write_info; - info->outstanding = 1; success = ConnectEx(sock, addr, addr_len, NULL, 0, NULL, &info->overlapped); /* It wouldn't be unusual to get a success immediately. But we'll still get @@ -220,7 +216,6 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp), grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC)); - socket->write_info.outstanding = 1; grpc_socket_notify_on_write(socket, on_connect, ac); return; @@ -229,7 +224,7 @@ failure: gpr_log(GPR_ERROR, message, utf8_message); gpr_free(utf8_message); if (socket) { - grpc_winsocket_orphan(socket); + grpc_winsocket_destroy(socket); } else if (sock != INVALID_SOCKET) { closesocket(sock); } diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c index d0478d3604..79ea223d54 100644 --- a/src/core/iomgr/tcp_server_windows.c +++ b/src/core/iomgr/tcp_server_windows.c @@ -116,7 +116,7 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s, for (i = 0; i < s->nports; i++) { server_port *sp = &s->ports[i]; sp->shutting_down = 1; - s->iomgr_callbacks_pending += grpc_winsocket_shutdown(sp->socket); + grpc_winsocket_shutdown(sp->socket); } /* This happens asynchronously. Wait while that happens. */ while (s->active_ports || s->iomgr_callbacks_pending) { @@ -129,7 +129,7 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s, closed by the system. */ for (i = 0; i < s->nports; i++) { server_port *sp = &s->ports[i]; - grpc_winsocket_orphan(sp->socket); + grpc_winsocket_destroy(sp->socket); } gpr_free(s->ports); gpr_free(s); @@ -189,7 +189,6 @@ error: static void decrement_active_ports_and_notify(server_port *sp) { sp->shutting_down = 0; - sp->socket->read_info.outstanding = 0; gpr_mu_lock(&sp->server->mu); GPR_ASSERT(sp->server->active_ports > 0); if (0 == --sp->server->active_ports) { @@ -462,7 +461,6 @@ void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset **pollset, s->cb = cb; s->cb_arg = cb_arg; for (i = 0; i < s->nports; i++) { - s->ports[i].socket->read_info.outstanding = 1; start_accept(s->ports + i); s->active_ports++; } diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index 58f9160ef9..fe3673c607 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -97,7 +97,7 @@ typedef struct grpc_tcp { } grpc_tcp; static void tcp_free(grpc_tcp *tcp) { - grpc_winsocket_orphan(tcp->socket); + grpc_winsocket_destroy(tcp->socket); gpr_mu_destroy(&tcp->mu); gpr_free(tcp->peer_string); gpr_free(tcp); @@ -135,55 +135,35 @@ static void tcp_ref(grpc_tcp *tcp) { gpr_ref(&tcp->refcount); } #endif /* Asynchronous callback from the IOCP, or the background thread. */ -static int on_read(grpc_tcp *tcp, int from_iocp) { +static int on_read(grpc_tcp *tcp, int success) { grpc_winsocket *socket = tcp->socket; gpr_slice sub; gpr_slice *slice = NULL; size_t nslices = 0; - int success; grpc_winsocket_callback_info *info = &socket->read_info; int do_abort = 0; - gpr_mu_lock(&tcp->mu); - if (!from_iocp || tcp->shutting_down) { - /* If we are here with from_iocp set to true, it means we got raced to - shutting down the endpoint. No actual abort callback will happen - though, so we're going to do it from here. */ - do_abort = 1; - } - gpr_mu_unlock(&tcp->mu); - - if (do_abort) { - if (from_iocp) { - tcp->socket->read_info.outstanding = 0; + if (success) { + if (socket->read_info.wsa_error != 0) { + if (socket->read_info.wsa_error != WSAECONNRESET) { + char *utf8_message = gpr_format_message(info->wsa_error); + gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); + gpr_free(utf8_message); + } + success = 0; gpr_slice_unref(tcp->read_slice); - } - return 0; - } - - GPR_ASSERT(tcp->socket->read_info.outstanding); - - if (socket->read_info.wsa_error != 0) { - if (socket->read_info.wsa_error != WSAECONNRESET) { - char *utf8_message = gpr_format_message(info->wsa_error); - gpr_log(GPR_ERROR, "ReadFile overlapped error: %s", utf8_message); - gpr_free(utf8_message); - } - success = 0; - gpr_slice_unref(tcp->read_slice); - } else { - if (info->bytes_transfered != 0) { - sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); - gpr_slice_buffer_add(tcp->read_slices, sub); - success = 1; } else { - gpr_slice_unref(tcp->read_slice); - success = 0; + if (info->bytes_transfered != 0) { + sub = gpr_slice_sub_no_ref(tcp->read_slice, 0, info->bytes_transfered); + gpr_slice_buffer_add(tcp->read_slices, sub); + success = 1; + } else { + gpr_slice_unref(tcp->read_slice); + success = 0; + } } } - tcp->socket->read_info.outstanding = 0; - return success; } @@ -209,14 +189,10 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, DWORD flags = 0; WSABUF buffer; - GPR_ASSERT(!tcp->socket->read_info.outstanding); if (tcp->shutting_down) { return GRPC_ENDPOINT_ERROR; } - TCP_REF(tcp, "read"); - - tcp->socket->read_info.outstanding = 1; tcp->read_cb = cb; tcp->read_slices = read_slices; gpr_slice_buffer_reset_and_unref(read_slices); @@ -236,10 +212,11 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, int ok; info->bytes_transfered = bytes_read; ok = on_read(tcp, 1); - TCP_UNREF(tcp, "read"); return ok ? GRPC_ENDPOINT_DONE : GRPC_ENDPOINT_ERROR; } + TCP_REF(tcp, "read"); + /* Otherwise, let's retry, by queuing a read. */ memset(&tcp->socket->read_info.overlapped, 0, sizeof(OVERLAPPED)); status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, @@ -260,52 +237,31 @@ static grpc_endpoint_op_status win_read(grpc_endpoint *ep, } /* Asynchronous callback from the IOCP, or the background thread. */ -static void on_write(void *tcpp, int from_iocp) { +static void on_write(void *tcpp, int success) { grpc_tcp *tcp = (grpc_tcp *)tcpp; grpc_winsocket *handle = tcp->socket; grpc_winsocket_callback_info *info = &handle->write_info; grpc_iomgr_closure *cb; - int success; int do_abort = 0; gpr_mu_lock(&tcp->mu); cb = tcp->write_cb; tcp->write_cb = NULL; - if (!from_iocp || tcp->shutting_down) { - /* If we are here with from_iocp set to true, it means we got raced to - shutting down the endpoint. No actual abort callback will happen - though, so we're going to do it from here. */ - do_abort = 1; - } gpr_mu_unlock(&tcp->mu); - if (do_abort) { - if (from_iocp) { - tcp->socket->write_info.outstanding = 0; - } - TCP_UNREF(tcp, "write"); - if (cb) { - cb->cb(cb->cb_arg, 0); - } - return; - } - - GPR_ASSERT(tcp->socket->write_info.outstanding); - - if (info->wsa_error != 0) { - if (info->wsa_error != WSAECONNRESET) { - char *utf8_message = gpr_format_message(info->wsa_error); - gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); - gpr_free(utf8_message); + if (success) { + if (info->wsa_error != 0) { + if (info->wsa_error != WSAECONNRESET) { + char *utf8_message = gpr_format_message(info->wsa_error); + gpr_log(GPR_ERROR, "WSASend overlapped error: %s", utf8_message); + gpr_free(utf8_message); + } + success = 0; + } else { + GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length); } - success = 0; - } else { - GPR_ASSERT(info->bytes_transfered == tcp->write_slices->length); - success = 1; } - tcp->socket->write_info.outstanding = 0; - TCP_UNREF(tcp, "write"); cb->cb(cb->cb_arg, success); } @@ -324,13 +280,10 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, WSABUF *allocated = NULL; WSABUF *buffers = local_buffers; - GPR_ASSERT(!tcp->socket->write_info.outstanding); if (tcp->shutting_down) { return GRPC_ENDPOINT_ERROR; } - TCP_REF(tcp, "write"); - tcp->socket->write_info.outstanding = 1; tcp->write_cb = cb; tcp->write_slices = slices; @@ -365,11 +318,11 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, } } if (allocated) gpr_free(allocated); - tcp->socket->write_info.outstanding = 0; - TCP_UNREF(tcp, "write"); return ret; } + TCP_REF(tcp, "write"); + /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same operation, this time asynchronously. */ memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED)); @@ -380,7 +333,6 @@ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { - tcp->socket->write_info.outstanding = 0; TCP_UNREF(tcp, "write"); return GRPC_ENDPOINT_ERROR; } diff --git a/src/core/transport/chttp2/internal.h b/src/core/transport/chttp2/internal.h index a1b773b1ca..7a42de9245 100644 --- a/src/core/transport/chttp2/internal.h +++ b/src/core/transport/chttp2/internal.h @@ -293,6 +293,9 @@ struct grpc_chttp2_transport { gpr_refcount refs; char *peer_string; + /** when this drops to zero it's safe to shutdown the endpoint */ + gpr_refcount shutdown_ep_refs; + gpr_mu mu; /** is the transport destroying itself? */ diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 8caa10c938..aa7a7c9471 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -222,6 +222,8 @@ static void init_transport(grpc_chttp2_transport *t, t->ep = ep; /* one ref is for destroy, the other for when ep becomes NULL */ gpr_ref_init(&t->refs, 2); + /* ref is dropped at transport close() */ + gpr_ref_init(&t->shutdown_ep_refs, 1); gpr_mu_init(&t->mu); grpc_mdctx_ref(mdctx); t->peer_string = grpc_endpoint_get_peer(ep); @@ -336,13 +338,26 @@ static void destroy_transport(grpc_transport *gt) { UNREF_TRANSPORT(t, "destroy"); } +/** block grpc_endpoint_shutdown being called until a paired + allow_endpoint_shutdown is made */ +static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) { + GPR_ASSERT(t->shutdown_ep_refs.count); + gpr_ref(&t->shutdown_ep_refs); +} + +static void allow_endpoint_shutdown(grpc_chttp2_transport *t) { + if (gpr_unref(&t->shutdown_ep_refs)) { + grpc_endpoint_shutdown(t->ep); + } +} + static void close_transport_locked(grpc_chttp2_transport *t) { if (!t->closed) { t->closed = 1; connectivity_state_set(&t->global, GRPC_CHANNEL_FATAL_FAILURE, "close_transport"); if (t->ep) { - grpc_endpoint_shutdown(t->ep); + allow_endpoint_shutdown(t); } } } @@ -471,6 +486,7 @@ static void unlock(grpc_chttp2_transport *t) { t->writing_active = 1; REF_TRANSPORT(t, "writing"); grpc_chttp2_schedule_closure(&t->global, &t->writing_action, 1); + prevent_endpoint_shutdown(t); } run_closures = t->global.pending_closures_head; @@ -536,6 +552,7 @@ void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { static void writing_action(void *gt, int iomgr_success_ignored) { grpc_chttp2_transport *t = gt; grpc_chttp2_perform_writes(&t->writing, t->ep); + allow_endpoint_shutdown(t); } void grpc_chttp2_add_incoming_goaway( @@ -1104,21 +1121,28 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { read_error_locked(t); } else { keep_reading = 1; + prevent_endpoint_shutdown(t); } gpr_slice_buffer_reset_and_unref(&t->read_buffer); unlock(t); if (keep_reading) { + int ret = -1; switch (grpc_endpoint_read(t->ep, &t->read_buffer, &t->recv_data)) { case GRPC_ENDPOINT_DONE: *success = 1; - return 1; + ret = 1; + break; case GRPC_ENDPOINT_ERROR: *success = 0; - return 1; + ret = 1; + break; case GRPC_ENDPOINT_PENDING: - return 0; + ret = 0; + break; } + allow_endpoint_shutdown(t); + return ret; } else { UNREF_TRANSPORT(t, "recv_data"); return 0; diff --git a/test/core/iomgr/endpoint_pair_test.c b/test/core/iomgr/endpoint_pair_test.c index 276fe758d9..3abde5ac35 100644 --- a/test/core/iomgr/endpoint_pair_test.c +++ b/test/core/iomgr/endpoint_pair_test.c @@ -33,13 +33,6 @@ #include "src/core/iomgr/tcp_posix.h" -#include -#include -#include -#include -#include -#include - #include #include #include diff --git a/test/core/iomgr/endpoint_tests.c b/test/core/iomgr/endpoint_tests.c index ef673747a1..148aa9e4ca 100644 --- a/test/core/iomgr/endpoint_tests.c +++ b/test/core/iomgr/endpoint_tests.c @@ -39,6 +39,7 @@ #include #include #include +#include #include "test/core/util/test_config.h" /* @@ -128,6 +129,7 @@ struct read_and_write_test_state { static void read_and_write_test_read_handler(void *data, int success) { struct read_and_write_test_state *state = data; +loop: state->bytes_read += count_slices( state->incoming.slices, state->incoming.count, &state->current_read_data); if (state->bytes_read == state->target_bytes || !success) { @@ -140,11 +142,11 @@ static void read_and_write_test_read_handler(void *data, int success) { switch (grpc_endpoint_read(state->read_ep, &state->incoming, &state->done_read)) { case GRPC_ENDPOINT_ERROR: - read_and_write_test_read_handler(data, 0); - break; + success = 0; + goto loop; case GRPC_ENDPOINT_DONE: - read_and_write_test_read_handler(data, 1); - break; + success = 1; + goto loop; case GRPC_ENDPOINT_PENDING: break; } @@ -176,16 +178,17 @@ static void read_and_write_test_write_handler(void *data, int success) { gpr_slice_buffer_addn(&state->outgoing, slices, nslices); write_status = grpc_endpoint_write(state->write_ep, &state->outgoing, &state->done_write); - gpr_log(GPR_DEBUG, "write_status=%d", write_status); - GPR_ASSERT(write_status != GRPC_ENDPOINT_ERROR); free(slices); if (write_status == GRPC_ENDPOINT_PENDING) { return; + } else if (write_status == GRPC_ENDPOINT_ERROR) { + goto cleanup; } } GPR_ASSERT(state->bytes_written == state->target_bytes); } +cleanup: gpr_log(GPR_INFO, "Write handler done"); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); state->write_done = 1 + success; @@ -204,6 +207,8 @@ static void read_and_write_test(grpc_endpoint_test_config config, gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(20); grpc_endpoint_test_fixture f = begin_test(config, "read_and_write_test", slice_size); + gpr_log(GPR_DEBUG, "num_bytes=%d write_size=%d slice_size=%d shutdown=%d", + num_bytes, write_size, slice_size, shutdown); if (shutdown) { gpr_log(GPR_INFO, "Start read and write shutdown test"); @@ -264,11 +269,11 @@ static void read_and_write_test(grpc_endpoint_test_config config, } gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - grpc_endpoint_destroy(state.read_ep); - grpc_endpoint_destroy(state.write_ep); + end_test(config); gpr_slice_buffer_destroy(&state.outgoing); gpr_slice_buffer_destroy(&state.incoming); - end_test(config); + grpc_endpoint_destroy(state.read_ep); + grpc_endpoint_destroy(state.write_ep); } struct timeout_test_state { @@ -286,6 +291,7 @@ static void shutdown_during_write_test_read_handler(void *user_data, int success) { shutdown_during_write_test_state *st = user_data; +loop: if (!success) { grpc_endpoint_destroy(st->ep); gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); @@ -297,11 +303,11 @@ static void shutdown_during_write_test_read_handler(void *user_data, case GRPC_ENDPOINT_PENDING: break; case GRPC_ENDPOINT_ERROR: - shutdown_during_write_test_read_handler(user_data, 0); - break; + success = 0; + goto loop; case GRPC_ENDPOINT_DONE: - shutdown_during_write_test_read_handler(user_data, 1); - break; + success = 1; + goto loop; } } } @@ -324,86 +330,15 @@ static void shutdown_during_write_test_write_handler(void *user_data, gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); } -static void shutdown_during_write_test(grpc_endpoint_test_config config, - size_t slice_size) { - /* test that shutdown with a pending write creates no leaks */ - gpr_timespec deadline; - size_t size; - size_t nblocks; - int current_data = 1; - shutdown_during_write_test_state read_st; - shutdown_during_write_test_state write_st; - gpr_slice *slices; - gpr_slice_buffer outgoing; - grpc_iomgr_closure done_write; - grpc_endpoint_test_fixture f = - begin_test(config, "shutdown_during_write_test", slice_size); - - gpr_log(GPR_INFO, "testing shutdown during a write"); - - read_st.ep = f.client_ep; - write_st.ep = f.server_ep; - read_st.done = 0; - write_st.done = 0; - - grpc_iomgr_closure_init(&done_write, shutdown_during_write_test_write_handler, - &write_st); - grpc_iomgr_closure_init(&read_st.done_read, - shutdown_during_write_test_read_handler, &read_st); - gpr_slice_buffer_init(&read_st.incoming); - gpr_slice_buffer_init(&outgoing); - - GPR_ASSERT(grpc_endpoint_read(read_st.ep, &read_st.incoming, - &read_st.done_read) == GRPC_ENDPOINT_PENDING); - for (size = 1;; size *= 2) { - slices = allocate_blocks(size, 1, &nblocks, ¤t_data); - gpr_slice_buffer_reset_and_unref(&outgoing); - gpr_slice_buffer_addn(&outgoing, slices, nblocks); - switch (grpc_endpoint_write(write_st.ep, &outgoing, &done_write)) { - case GRPC_ENDPOINT_DONE: - break; - case GRPC_ENDPOINT_ERROR: - gpr_log(GPR_ERROR, "error writing"); - abort(); - case GRPC_ENDPOINT_PENDING: - grpc_endpoint_shutdown(write_st.ep); - deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10); - gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - while (!write_st.done) { - grpc_pollset_worker worker; - GPR_ASSERT(gpr_time_cmp(gpr_now(deadline.clock_type), deadline) < 0); - grpc_pollset_work(g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), - deadline); - } - gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - grpc_endpoint_destroy(write_st.ep); - gpr_mu_lock(GRPC_POLLSET_MU(g_pollset)); - while (!read_st.done) { - grpc_pollset_worker worker; - GPR_ASSERT(gpr_time_cmp(gpr_now(deadline.clock_type), deadline) < 0); - grpc_pollset_work(g_pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), - deadline); - } - gpr_mu_unlock(GRPC_POLLSET_MU(g_pollset)); - gpr_free(slices); - gpr_slice_buffer_destroy(&read_st.incoming); - gpr_slice_buffer_destroy(&outgoing); - end_test(config); - return; - } - gpr_free(slices); - } - - gpr_log(GPR_ERROR, "should never reach here"); - abort(); -} - void grpc_endpoint_tests(grpc_endpoint_test_config config, grpc_pollset *pollset) { + size_t i; g_pollset = pollset; read_and_write_test(config, 10000000, 100000, 8192, 0); read_and_write_test(config, 1000000, 100000, 1, 0); read_and_write_test(config, 100000000, 100000, 1, 1); - shutdown_during_write_test(config, 1000); + for (i = 1; i < 1000; i = GPR_MAX(i + 1, i * 5 / 4)) { + read_and_write_test(config, 40320, i, i, 0); + } g_pollset = NULL; } -- cgit v1.2.3 From 4b41ba249df4f290b3551b82b6004a0ce77bf2cf Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Fri, 28 Aug 2015 15:48:23 +0000 Subject: Two fixes in grpc.framework.core._end (1) Call "cancel" on each future, not on the list of futures. (2) If and when futures mature their actions should simply abort all outstanding operations and cancel any other futures. They should not shut down the _End's internal thread pool; only the termination action of the last operation to terminate should shut down the pool (in the case of their having been active operations at the time at which the _End's stop(grace) method was called). --- src/python/grpcio/grpc/framework/core/_end.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/framework/core/_end.py b/src/python/grpcio/grpc/framework/core/_end.py index fb2c532df6..5ef2f6d3a3 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 -- cgit v1.2.3 From 727956741da9e79b1f8c725ee61bc184e72e701e Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 28 Aug 2015 08:54:26 -0700 Subject: check for allowed characters in metadata key --- src/csharp/Grpc.Core.Tests/MetadataTest.cs | 11 +++++++++++ src/csharp/Grpc.Core/Metadata.cs | 7 ++++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src') 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 @@ -74,6 +74,17 @@ namespace Grpc.Core.Tests Assert.AreEqual("[Entry: key=abc-bin, valueBytes=System.Byte[]]", entry.ToString()); } + [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() { diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs index 2b08e0de51..21bdf4f114 100644 --- a/src/csharp/Grpc.Core/Metadata.cs +++ b/src/csharp/Grpc.Core/Metadata.cs @@ -36,6 +36,7 @@ using System.Collections.Specialized; using System.Globalization; using System.Runtime.InteropServices; using System.Text; +using System.Text.RegularExpressions; using Grpc.Core.Utils; @@ -189,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; @@ -321,7 +323,10 @@ namespace Grpc.Core private static string NormalizeKey(string key) { - return Preconditions.CheckNotNull(key, "key").ToLower(CultureInfo.InvariantCulture); + 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; } } } -- cgit v1.2.3 From 6e6ddbec9183b0081c199908b2ef36d6d954de87 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Fri, 28 Aug 2015 16:37:38 +0000 Subject: Accept addresses rather than ports in add_port --- src/python/grpcio/grpc/_links/service.py | 18 ++++++++++-------- .../grpc_test/_core_over_links_base_interface_test.py | 2 +- .../_crust_over_core_over_links_face_interface_test.py | 2 +- .../grpcio_test/grpc_test/_links/_transmission_test.py | 6 +++--- 4 files changed, 15 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py index 10634e43b5..393f80c1cc 100644 --- a/src/python/grpcio/grpc/_links/service.py +++ b/src/python/grpcio/grpc/_links/service.py @@ -316,9 +316,8 @@ class _Kernel(object): call.status(status, call) self._rpc_states.pop(call, None) - 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) @@ -362,17 +361,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. + 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. + A 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() @@ -417,8 +419,8 @@ 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() 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..9c095d670c 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 @@ -95,7 +95,7 @@ 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', 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..1659a58325 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 @@ -85,7 +85,7 @@ 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', 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..0fef9b0c5a 100644 --- a/src/python/grpcio_test/grpc_test/_links/_transmission_test.py +++ b/src/python/grpcio_test/grpc_test/_links/_transmission_test.py @@ -50,7 +50,7 @@ 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( @@ -116,7 +116,7 @@ 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( @@ -160,7 +160,7 @@ 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( -- cgit v1.2.3 From 4a6bbdddd392b06370c0fc56868855d05c0c66ec Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Fri, 28 Aug 2015 17:38:05 +0000 Subject: Python test clean-up (1) Move metadata and details constants for gRPC-on-the-wire tests into grpc.test_common. (2) Drop definitions of setUpModule and tearDownModule from a unit test module that, because it uses the load_tests protocol, never had those methods called anyway. :-( --- .../_core_over_links_base_interface_test.py | 20 +++++--------------- ...crust_over_core_over_links_face_interface_test.py | 11 +++++------ src/python/grpcio_test/grpc_test/test_common.py | 5 +++++ 3 files changed, 15 insertions(+), 21 deletions(-) (limited to 'src') 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..c8e325aea0 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( @@ -117,16 +113,18 @@ class _Implementation(test_interfaces.Implementation): service_grpc_link.stop_gracefully() 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 +144,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..5ba6d4afe6 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( @@ -130,19 +129,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/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. -- cgit v1.2.3 From c3ee1d5eb4aa790db7c309627286be5d60ff60ec Mon Sep 17 00:00:00 2001 From: yang-g Date: Fri, 28 Aug 2015 11:33:52 -0700 Subject: Do not include internal proto header --- src/compiler/csharp_generator.cc | 7 +++++-- src/compiler/csharp_generator.h | 3 --- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc index 51d8d982e2..7b497df7f4 100644 --- a/src/compiler/csharp_generator.cc +++ b/src/compiler/csharp_generator.cc @@ -33,6 +33,7 @@ #include #include +#include #include #include "src/compiler/csharp_generator.h" @@ -44,7 +45,6 @@ using google::protobuf::compiler::csharp::GetFileNamespace; using google::protobuf::compiler::csharp::GetClassName; using google::protobuf::compiler::csharp::GetUmbrellaClassName; -using google::protobuf::SimpleItoa; using grpc::protobuf::FileDescriptor; using grpc::protobuf::Descriptor; using grpc::protobuf::ServiceDescriptor; @@ -228,11 +228,14 @@ void GenerateStaticMethodField(Printer* out, const MethodDescriptor *method) { } 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", SimpleItoa(service->index())); + "umbrella", GetUmbrellaClassName(service->file()), "index", + index.str()); out->Print("}\n"); out->Print("\n"); } diff --git a/src/compiler/csharp_generator.h b/src/compiler/csharp_generator.h index 67e3ee30b5..90eb7e2984 100644 --- a/src/compiler/csharp_generator.h +++ b/src/compiler/csharp_generator.h @@ -36,10 +36,7 @@ #include "src/compiler/config.h" -using namespace std; - #include -#include namespace grpc_csharp_generator { -- cgit v1.2.3 From 487a72b7262f0184c517093c2a8a6a7ef5fba046 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 28 Aug 2015 13:33:38 -0700 Subject: Provide troubleshooting instructions for 'cannot load grpc_csharp_ext.dll' problem. --- src/csharp/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/csharp/README.md b/src/csharp/README.md index 30523b3bd2..3fbc1c5f05 100644 --- a/src/csharp/README.md +++ b/src/csharp/README.md @@ -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. -- cgit v1.2.3 From 6afe53f2360a20a4d3abda60cfdde576c29b9857 Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Fri, 28 Aug 2015 14:05:15 -0700 Subject: add functions for getting trace records --- include/grpc/census.h | 48 +++++++++++++++++++++++++++++++++++++++++++++-- src/core/census/tracing.c | 4 ++-- 2 files changed, 48 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/include/grpc/census.h b/include/grpc/census.h index ef6275fe58..d1a2978bd2 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -276,9 +276,53 @@ census_context *census_start_op(census_context *context, const char *family, */ void census_end_op(census_context *context, int status); +#define CENSUS_TRACE_RECORD_START_OP ((gpr_uint32)0) +#define CENSUS_TRACE_RECORD_END_OP ((gpr_uint32)1) + /** Insert a trace record into the trace stream. The record consists of an - * arbitrary size buffer, the size of which is provided in 'n'. */ -void census_trace_print(census_context *context, const char *buffer, size_t n); + arbitrary size buffer, the size of which is provided in 'n'. + @param context Trace context + @param type User-defined type to associate with trace entry. + @param buffer Pointer to buffer to use + @param n Number of bytes in buffer +*/ +void census_trace_print(census_context *context, gpr_uint32 type, + const char *buffer, size_t n); + +/** Trace record. */ +typedef struct { + census_timestamp timestamp; /* Time of record creation */ + gpr_uint64 trace_id; /* Trace ID associated with record */ + gpr_uint64 op_id; /* Operation ID associated with record */ + gpr_uint32 type; /* Type (as used in census_trace_print() */ + const char *buffer; /* Buffer (from census_trace_print() */ + size_t buf_size; /* Number of bytes inside buffer */ +} census_trace_record; + +/** Start a scan of existing trace records. While a scan is ongoing, addition + of new trace records will be blocked if the underlying trace buffers + fill up, so trace processing systems should endeavor to complete + reading as soon as possible. + @param consume if non-zero, indicates that reading records also "consumes" + the previously read record - i.e. releases space in the trace log + while scanning is ongoing. + @returns 0 on success, non-zero on failure (e.g. if a scan is already ongoing) +*/ +int census_trace_scan_start(int consume); + +/** Get a trace record. The data pointed to by the trace buffer is guaranteed + stable until the next census_get_trace_record() call (if the consume + argument to census_trace_scan_start was non-zero) or census_trace_scan_end() + is called (otherwise). + @param trace_record structure that will be filled in with oldest trace record. + @returns -1 if an error occurred (e.g. no previous call to + census_trace_scan_start()), 0 if there is no more trace data (and + trace_record will not be modified) or 1 otherwise. +*/ +int census_get_trace_record(census_trace_record *trace_record); + +/** End a scan previously started by census_trace_scan_start() */ +void census_trace_scan_end(); /* Max number of characters in tag key */ #define CENSUS_MAX_TAG_KEY_LENGTH 20 diff --git a/src/core/census/tracing.c b/src/core/census/tracing.c index 44db95653c..ae38773c0a 100644 --- a/src/core/census/tracing.c +++ b/src/core/census/tracing.c @@ -41,5 +41,5 @@ int census_trace_mask(const census_context *context) { void census_set_trace_mask(int trace_mask) {} -void census_trace_print(census_context *context, const char *buffer, size_t n) { -} +void census_trace_print(census_context *context, gpr_uint32 type, + const char *buffer, size_t n) {} -- cgit v1.2.3 From 4354f3e6809f12512d93b33e667133bc15f44029 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Fri, 28 Aug 2015 16:07:23 +0000 Subject: Make ServiceLink shut-down a two step process --- src/python/grpcio/grpc/_links/service.py | 33 +++++++++++----------- .../_core_over_links_base_interface_test.py | 3 +- ...ust_over_core_over_links_face_interface_test.py | 3 +- .../grpc_test/_links/_transmission_test.py | 9 ++++-- 4 files changed, 26 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py index 10634e43b5..5ab8efb4c4 100644 --- a/src/python/grpcio/grpc/_links/service.py +++ b/src/python/grpcio/grpc/_links/service.py @@ -337,10 +337,13 @@ class _Kernel(object): self._server.start() self._server.service(None) - def graceful_stop(self): + def begin_stop(self): with self._lock: self._server.stop() self._server = None + + def end_stop(self): + with self._lock: self._completion_queue.stop() self._completion_queue = None pool = self._pool @@ -348,11 +351,6 @@ class _Kernel(object): 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. @@ -386,18 +384,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. """ @@ -424,12 +424,11 @@ class _ServiceLink(ServiceLink): 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_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..91386f2697 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 @@ -114,7 +114,8 @@ 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 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..c619056170 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 @@ -121,8 +121,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) 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..616d8a670d 100644 --- a/src/python/grpcio_test/grpc_test/_links/_transmission_test.py +++ b/src/python/grpcio_test/grpc_test/_links/_transmission_test.py @@ -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 ( @@ -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, @@ -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() -- cgit v1.2.3 From 0c711ad88b632bea173bdea9ea24372052aa231d Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Fri, 28 Aug 2015 14:10:58 -0700 Subject: Adding C++ metadata processor. - Had to chnage the core API to add a destroy function pointer in grpc_auth_metadata_processor. - Tested end to end. - Fixed some issues in the server_auth_filter (we were not checking the length which put us at risk of an overflow). --- include/grpc++/auth_metadata_processor.h | 5 +- include/grpc++/server_credentials.h | 10 +- include/grpc++/support/auth_context.h | 5 +- include/grpc/grpc_security.h | 1 + src/core/security/credentials.c | 15 +- src/core/security/security_context.c | 13 -- src/core/security/server_auth_filter.c | 10 +- src/core/security/server_secure_chttp2.c | 9 ++ src/cpp/client/create_channel.cc | 1 + src/cpp/common/secure_auth_context.cc | 15 +- src/cpp/common/secure_auth_context.h | 7 +- src/cpp/common/secure_create_auth_context.cc | 2 +- src/cpp/server/secure_server_credentials.cc | 17 +- src/cpp/server/secure_server_credentials.h | 2 + test/core/end2end/fixtures/chttp2_fake_security.c | 2 +- .../end2end/fixtures/chttp2_simple_ssl_fullstack.c | 2 +- .../chttp2_simple_ssl_fullstack_with_poll.c | 2 +- .../chttp2_simple_ssl_fullstack_with_proxy.c | 2 +- .../chttp2_simple_ssl_with_oauth2_fullstack.c | 45 ++++-- test/cpp/end2end/end2end_test.cc | 175 +++++++++++++++++++-- test/cpp/util/messages.proto | 1 + 21 files changed, 276 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/include/grpc++/auth_metadata_processor.h b/include/grpc++/auth_metadata_processor.h index c0631bc11f..a42abef416 100644 --- a/include/grpc++/auth_metadata_processor.h +++ b/include/grpc++/auth_metadata_processor.h @@ -58,7 +58,10 @@ class AuthMetadataProcessor { // from the passed-in auth_metadata. // consumed_auth_metadata needs to be filled with metadata that has been // consumed by the processor and will be removed from the call. - // TODO(jboeuf). + // response_metadata is the metadata that will be sent as part of the + // response. + // If the return value is not Status::OK, the rpc call will be aborted with + // the error code and error message sent back to the client. virtual Status Process(const InputMetadata& auth_metadata, AuthContext* context, OutputMetadata* consumed_auth_metadata, diff --git a/include/grpc++/server_credentials.h b/include/grpc++/server_credentials.h index 486c35c56b..e006f3a180 100644 --- a/include/grpc++/server_credentials.h +++ b/include/grpc++/server_credentials.h @@ -50,16 +50,16 @@ class ServerCredentials { public: virtual ~ServerCredentials(); + // This method is not thread-safe and has to be called before the server is + // started. The last call to this function wins. + virtual void SetAuthMetadataProcessor( + const std::shared_ptr& processor) = 0; + private: friend class ::grpc::Server; virtual int AddPortToServer(const grpc::string& addr, grpc_server* server) = 0; - - // This method is not thread-safe and has to be called before the server is - // started. The last call to this function wins. - virtual void SetAuthMetadataProcessor( - const std::shared_ptr& processor) = 0; }; // Options to create ServerCredentials with SSL diff --git a/include/grpc++/support/auth_context.h b/include/grpc++/support/auth_context.h index 5d5f8e837d..fc2701e806 100644 --- a/include/grpc++/support/auth_context.h +++ b/include/grpc++/support/auth_context.h @@ -77,6 +77,9 @@ class AuthContext { public: virtual ~AuthContext() {} + // Returns true if the peer is authenticated. + virtual bool IsPeerAuthenticated() const = 0; + // A peer identity, in general is one or more properties (in which case they // have the same name). virtual std::vector GetPeerIdentity() const = 0; @@ -92,7 +95,7 @@ class AuthContext { // Mutation functions: should only be used by an AuthMetadataProcessor. virtual void AddProperty(const grpc::string& key, - const grpc::string& value) = 0; + const grpc::string_ref& value) = 0; virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0; }; diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h index e2205eea30..0b540c0e66 100644 --- a/include/grpc/grpc_security.h +++ b/include/grpc/grpc_security.h @@ -293,6 +293,7 @@ typedef struct { void (*process)(void *state, grpc_auth_context *context, const grpc_metadata *md, size_t num_md, grpc_process_auth_metadata_done_cb cb, void *user_data); + void (*destroy)(void *state); void *state; } grpc_auth_metadata_processor; diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 362d5f4b6f..cae80f0216 100644 --- a/src/core/security/credentials.c +++ b/src/core/security/credentials.c @@ -152,9 +152,20 @@ 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; } +void grpc_server_credentials_destroy(grpc_server_credentials *creds) { + if (creds == NULL) return; + if (creds->processor.destroy != NULL && creds->processor.state != NULL) { + creds->processor.destroy(creds->processor.state); + } + gpr_free(creds); +} + /* -- Ssl credentials. -- */ static void ssl_destroy(grpc_credentials *creds) { @@ -185,7 +196,7 @@ 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); + grpc_server_credentials_destroy(creds); } static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; } @@ -902,7 +913,7 @@ static void fake_transport_security_credentials_destroy( static void fake_transport_security_server_credentials_destroy( grpc_server_credentials *creds) { - gpr_free(creds); + grpc_server_credentials_destroy(creds); } static int fake_transport_security_has_request_metadata( 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 #include -/* --- 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 57729be32c..b767f85498 100644 --- a/src/core/security/server_auth_filter.c +++ b/src/core/security/server_auth_filter.c @@ -91,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. */ } diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c index 8d9d036d80..96ca4cbd76 100644 --- a/src/core/security/server_secure_chttp2.c +++ b/src/core/security/server_secure_chttp2.c @@ -79,6 +79,9 @@ static void state_unref(grpc_server_secure_state *state) { gpr_mu_unlock(&state->mu); /* clean up */ GRPC_SECURITY_CONNECTOR_UNREF(state->sc, "server"); + if (state->processor.state != NULL && state->processor.destroy != NULL) { + state->processor.destroy(state->processor.state); + } gpr_free(state); } } @@ -262,7 +265,13 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, state->server = server; state->tcp = tcp; state->sc = sc; + + /* Transfer ownership of the processor. */ state->processor = creds->processor; + creds->processor.state = NULL; + creds->processor.destroy = NULL; + creds->processor.process = NULL; + state->handshaking_tcp_endpoints = NULL; state->is_shutdown = 0; gpr_mu_init(&state->mu); diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc index 8c571cbbaa..4f6f2dd068 100644 --- a/src/cpp/client/create_channel.cc +++ b/src/cpp/client/create_channel.cc @@ -46,6 +46,7 @@ class ChannelArguments; std::shared_ptr CreateChannel( const grpc::string& target, const std::shared_ptr& 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(); diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc index 823ad8b0e2..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 SecureAuthContext::GetPeerIdentity() const { if (!ctx_) { @@ -95,7 +99,7 @@ AuthPropertyIterator SecureAuthContext::end() const { } void SecureAuthContext::AddProperty(const grpc::string& key, - const grpc::string& value) { + const grpc::string_ref& value) { if (!ctx_) return; grpc_auth_context_add_property(ctx_, key.c_str(), value.data(), value.size()); } @@ -106,4 +110,9 @@ bool SecureAuthContext::SetPeerIdentityPropertyName(const grpc::string& name) { 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 cc09a29ecb..6edab0cee1 100644 --- a/src/cpp/common/secure_auth_context.h +++ b/src/cpp/common/secure_auth_context.h @@ -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 GetPeerIdentity() const GRPC_OVERRIDE; grpc::string GetPeerIdentityPropertyName() const GRPC_OVERRIDE; @@ -58,13 +60,14 @@ class SecureAuthContext GRPC_FINAL : public AuthContext { AuthPropertyIterator end() const GRPC_OVERRIDE; void AddProperty(const grpc::string& key, - const grpc::string& value) GRPC_OVERRIDE; + 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..5a907d0c0b 100644 --- a/src/cpp/common/secure_create_auth_context.cc +++ b/src/cpp/common/secure_create_auth_context.cc @@ -44,7 +44,7 @@ std::shared_ptr CreateAuthContext(grpc_call* call) { return std::shared_ptr(); } return std::shared_ptr( - new SecureAuthContext(grpc_call_auth_context(call))); + new SecureAuthContext(grpc_call_auth_context(call), true)); } } // namespace grpc diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index f8847b80f7..0e2927bafe 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -43,6 +43,11 @@ namespace grpc { +void AuthMetadataProcessorAyncWrapper::Destroy(void *wrapper) { + auto* w = reinterpret_cast(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) { @@ -71,14 +76,14 @@ void AuthMetadataProcessorAyncWrapper::InvokeProcessor( metadata.insert(std::make_pair( md[i].key, grpc::string_ref(md[i].value, md[i].value_length))); } - SecureAuthContext context(ctx); + SecureAuthContext context(ctx, false); AuthMetadataProcessor::OutputMetadata consumed_metadata; AuthMetadataProcessor::OutputMetadata response_metadata; Status status = processor_->Process(metadata, &context, &consumed_metadata, &response_metadata); - std::vector consumed_md(consumed_metadata.size()); + std::vector consumed_md; for (auto it = consumed_metadata.begin(); it != consumed_metadata.end(); ++it) { consumed_md.push_back({it->first.c_str(), @@ -87,8 +92,7 @@ void AuthMetadataProcessorAyncWrapper::InvokeProcessor( 0, {{nullptr, nullptr, nullptr, nullptr}}}); } - - std::vector response_md(response_metadata.size()); + std::vector response_md; for (auto it = response_metadata.begin(); it != response_metadata.end(); ++it) { response_md.push_back({it->first.c_str(), @@ -109,9 +113,10 @@ int SecureServerCredentials::AddPortToServer(const grpc::string& addr, void SecureServerCredentials::SetAuthMetadataProcessor( const std::shared_ptr& processor) { - processor_.reset(new AuthMetadataProcessorAyncWrapper(processor)); + auto *wrapper = new AuthMetadataProcessorAyncWrapper(processor); grpc_server_credentials_set_auth_metadata_processor( - creds_, {AuthMetadataProcessorAyncWrapper::Process, processor_.get()}); + creds_, {AuthMetadataProcessorAyncWrapper::Process, + AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); } std::shared_ptr SslServerCredentials( diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index d15b793b15..17be9e310d 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -46,6 +46,8 @@ 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); diff --git a/test/core/end2end/fixtures/chttp2_fake_security.c b/test/core/end2end/fixtures/chttp2_fake_security.c index b4a248fb52..3e64cc08e8 100644 --- a/test/core/end2end/fixtures/chttp2_fake_security.c +++ b/test/core/end2end/fixtures/chttp2_fake_security.c @@ -128,7 +128,7 @@ static void chttp2_init_server_fake_secure_fullstack( grpc_server_credentials *fake_ts_creds = grpc_fake_transport_security_server_credentials_create(); if (fail_server_auth_check(server_args)) { - grpc_auth_metadata_processor processor = {process_auth_failure, NULL}; + grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; grpc_server_credentials_set_auth_metadata_processor(fake_ts_creds, processor); } diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c index 201d202dff..9193a09b17 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c @@ -138,7 +138,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); if (fail_server_auth_check(server_args)) { - grpc_auth_metadata_processor processor = {process_auth_failure, NULL}; + grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); } chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c index e7375f15e6..2c605d1471 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c @@ -138,7 +138,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); if (fail_server_auth_check(server_args)) { - grpc_auth_metadata_processor processor = {process_auth_failure, NULL}; + grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); } chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c index be0dda25a6..8133a69a0c 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c @@ -167,7 +167,7 @@ static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); if (fail_server_auth_check(server_args)) { - grpc_auth_metadata_processor processor = {process_auth_failure, NULL}; + grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); } chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c index 9a545b1e3d..e61e276fff 100644 --- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c +++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c @@ -67,13 +67,21 @@ static const grpc_metadata *find_metadata(const grpc_metadata *md, return NULL; } +typedef struct { + size_t pseudo_refcount; +} test_processor_state; + static void process_oauth2_success(void *state, grpc_auth_context *ctx, const grpc_metadata *md, size_t md_count, grpc_process_auth_metadata_done_cb cb, void *user_data) { const grpc_metadata *oauth2 = find_metadata(md, md_count, "Authorization", oauth2_md); - GPR_ASSERT(state == NULL); + test_processor_state *s; + + GPR_ASSERT(state != NULL); + s = (test_processor_state *)state; + GPR_ASSERT(s->pseudo_refcount == 1); GPR_ASSERT(oauth2 != NULL); grpc_auth_context_add_cstring_property(ctx, client_identity_property_name, client_identity); @@ -88,7 +96,10 @@ static void process_oauth2_failure(void *state, grpc_auth_context *ctx, void *user_data) { const grpc_metadata *oauth2 = find_metadata(md, md_count, "Authorization", oauth2_md); - GPR_ASSERT(state == NULL); + test_processor_state *s; + GPR_ASSERT(state != NULL); + s = (test_processor_state *)state; + GPR_ASSERT(s->pseudo_refcount == 1); GPR_ASSERT(oauth2 != NULL); cb(user_data, oauth2, 1, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); } @@ -171,20 +182,34 @@ static int fail_server_auth_check(grpc_channel_args *server_args) { return 0; } +static void processor_destroy(void *state) { + test_processor_state *s = (test_processor_state *)state; + GPR_ASSERT((s->pseudo_refcount--) == 1); + gpr_free(s); +} + +static grpc_auth_metadata_processor test_processor_create(int failing) { + test_processor_state *s = gpr_malloc(sizeof(*s)); + grpc_auth_metadata_processor result; + s->pseudo_refcount = 1; + result.state = s; + result.destroy = processor_destroy; + if (failing) { + result.process = process_oauth2_failure; + } else { + result.process = process_oauth2_success; + } + return result; +} + static void chttp2_init_server_simple_ssl_secure_fullstack( grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0, NULL); - grpc_auth_metadata_processor processor; - processor.state = NULL; - if (fail_server_auth_check(server_args)) { - processor.process = process_oauth2_failure; - } else { - processor.process = process_oauth2_success; - } - grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); + grpc_server_credentials_set_auth_metadata_processor( + ssl_creds, test_processor_create(fail_server_auth_check(server_args))); chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 9826837c60..72188e4da5 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -79,14 +80,23 @@ void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request, } } -void CheckServerAuthContext(const ServerContext* context) { +void CheckServerAuthContext(const ServerContext* context, + const grpc::string& expected_client_identity) { std::shared_ptr auth_ctx = context->auth_context(); std::vector ssl = auth_ctx->FindPropertyValues("transport_security_type"); EXPECT_EQ(1u, ssl.size()); EXPECT_EQ("ssl", ToString(ssl[0])); - EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty()); - EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty()); + if (expected_client_identity.length() == 0) { + EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty()); + EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty()); + EXPECT_FALSE(auth_ctx->IsPeerAuthenticated()); + } else { + auto identity = auth_ctx->GetPeerIdentity(); + EXPECT_TRUE(auth_ctx->IsPeerAuthenticated()); + EXPECT_EQ(1u, identity.size()); + EXPECT_EQ(expected_client_identity, identity[0]); + } } bool CheckIsLocalhost(const grpc::string& addr) { @@ -98,6 +108,54 @@ bool CheckIsLocalhost(const grpc::string& addr) { addr.substr(0, kIpv6.size()) == kIpv6; } +class TestAuthMetadataProcessor : public AuthMetadataProcessor { + public: + static const char kGoodGuy[]; + + TestAuthMetadataProcessor(bool is_blocking) : is_blocking_(is_blocking) {} + + std::shared_ptr GetCompatibleClientCreds() { + return AccessTokenCredentials(kGoodGuy); + } + std::shared_ptr GetIncompatibleClientCreds() { + return AccessTokenCredentials("Mr Hyde"); + } + + // Interface implementation + bool IsBlocking() const GRPC_OVERRIDE { return is_blocking_; } + + Status Process(const InputMetadata& auth_metadata, AuthContext* context, + OutputMetadata* consumed_auth_metadata, + OutputMetadata* response_metadata) GRPC_OVERRIDE { + EXPECT_TRUE(consumed_auth_metadata != nullptr); + EXPECT_TRUE(context != nullptr); + EXPECT_TRUE(response_metadata != nullptr); + auto auth_md = auth_metadata.find(GRPC_AUTHORIZATION_METADATA_KEY); + EXPECT_NE(auth_md, auth_metadata.end()); + string_ref auth_md_value = auth_md->second; + if (auth_md_value.ends_with("Dr Jekyll")) { + context->AddProperty(kIdentityPropName, kGoodGuy); + context->SetPeerIdentityPropertyName(kIdentityPropName); + consumed_auth_metadata->insert( + std::make_pair(string(auth_md->first.data(), auth_md->first.length()), + auth_md->second)); + return Status::OK; + } else { + return Status(StatusCode::UNAUTHENTICATED, + string("Invalid principal: ") + + string(auth_md_value.data(), auth_md_value.length())); + } + } + + protected: + static const char kIdentityPropName[]; + bool is_blocking_; +}; + +const char TestAuthMetadataProcessor::kGoodGuy[] = "Dr Jekyll"; +const char TestAuthMetadataProcessor::kIdentityPropName[] = "novel identity"; + + } // namespace class Proxy : public ::grpc::cpp::test::util::TestService::Service { @@ -162,8 +220,10 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service { ToString(iter->second)); } } - if (request->has_param() && request->param().check_auth_context()) { - CheckServerAuthContext(context); + if (request->has_param() && + (request->param().expected_client_identity().length() > 0 || + request->param().check_auth_context())) { + CheckServerAuthContext(context, request->param().expected_client_identity()); } if (request->has_param() && request->param().response_message_length() > 0) { @@ -259,9 +319,18 @@ class TestServiceImplDupPkg class End2endTest : public ::testing::TestWithParam { protected: End2endTest() - : kMaxMessageSize_(8192), special_service_("special") {} + : is_server_started_(false), + kMaxMessageSize_(8192), + special_service_("special") {} + + void TearDown() GRPC_OVERRIDE { + if (is_server_started_) { + server_->Shutdown(); + if (proxy_server_) proxy_server_->Shutdown(); + } + } - void SetUp() GRPC_OVERRIDE { + void StartServer(const std::shared_ptr& processor) { int port = grpc_pick_unused_port_or_die(); server_address_ << "127.0.0.1:" << port; // Setup server @@ -271,22 +340,23 @@ class End2endTest : public ::testing::TestWithParam { SslServerCredentialsOptions ssl_opts; ssl_opts.pem_root_certs = ""; ssl_opts.pem_key_cert_pairs.push_back(pkcp); - builder.AddListeningPort(server_address_.str(), - SslServerCredentials(ssl_opts)); + auto server_creds = SslServerCredentials(ssl_opts); + server_creds->SetAuthMetadataProcessor(processor); + builder.AddListeningPort(server_address_.str(), server_creds); builder.RegisterService(&service_); builder.RegisterService("foo.test.youtube.com", &special_service_); builder.SetMaxMessageSize( kMaxMessageSize_); // For testing max message size. builder.RegisterService(&dup_pkg_service_); server_ = builder.BuildAndStart(); - } - - void TearDown() GRPC_OVERRIDE { - server_->Shutdown(); - if (proxy_server_) proxy_server_->Shutdown(); + is_server_started_ = true; } void ResetChannel() { + if (!is_server_started_) { + StartServer(std::shared_ptr()); + } + EXPECT_TRUE(is_server_started_); SslCredentialsOptions ssl_opts = {test_root_cert, "", ""}; ChannelArguments args; args.SetSslTargetNameOverride("foo.test.google.fr"); @@ -314,6 +384,7 @@ class End2endTest : public ::testing::TestWithParam { stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_)); } + bool is_server_started_; std::shared_ptr channel_; std::unique_ptr stub_; std::unique_ptr server_; @@ -806,6 +877,82 @@ TEST_F(End2endTest, OverridePerCallCredentials) { EXPECT_TRUE(s.ok()); } +TEST_F(End2endTest, NonBlockingAuthMetadataProcessorSuccess) { + auto* processor = new TestAuthMetadataProcessor(false); + StartServer(std::shared_ptr(processor)); + ResetStub(false); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(processor->GetCompatibleClientCreds()); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + request.mutable_param()->set_expected_client_identity( + TestAuthMetadataProcessor::kGoodGuy); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); + + // Metadata should have been consumed by the processor. + EXPECT_FALSE(MetadataContains( + context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY, + grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy)); +} + +TEST_F(End2endTest, NonBlockingAuthMetadataProcessorFailure) { + auto* processor = new TestAuthMetadataProcessor(false); + StartServer(std::shared_ptr(processor)); + ResetStub(false); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(processor->GetIncompatibleClientCreds()); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); +} + +TEST_F(End2endTest, BlockingAuthMetadataProcessorSuccess) { + auto* processor = new TestAuthMetadataProcessor(true); + StartServer(std::shared_ptr(processor)); + ResetStub(false); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(processor->GetCompatibleClientCreds()); + request.set_message("Hello"); + request.mutable_param()->set_echo_metadata(true); + request.mutable_param()->set_expected_client_identity( + TestAuthMetadataProcessor::kGoodGuy); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_EQ(request.message(), response.message()); + EXPECT_TRUE(s.ok()); + + // Metadata should have been consumed by the processor. + EXPECT_FALSE(MetadataContains( + context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY, + grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy)); +} + +TEST_F(End2endTest, BlockingAuthMetadataProcessorFailure) { + auto* processor = new TestAuthMetadataProcessor(true); + StartServer(std::shared_ptr(processor)); + ResetStub(false); + EchoRequest request; + EchoResponse response; + ClientContext context; + context.set_credentials(processor->GetIncompatibleClientCreds()); + request.set_message("Hello"); + + Status s = stub_->Echo(&context, request, &response); + EXPECT_FALSE(s.ok()); + EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED); +} + // Client sends 20 requests and the server returns CANCELLED status after // reading 10 requests. TEST_F(End2endTest, RequestStreamServerEarlyCancelTest) { diff --git a/test/cpp/util/messages.proto b/test/cpp/util/messages.proto index 359d1db74f..a022707be9 100644 --- a/test/cpp/util/messages.proto +++ b/test/cpp/util/messages.proto @@ -40,6 +40,7 @@ message RequestParams { bool check_auth_context = 5; int32 response_message_length = 6; bool echo_peer = 7; + string expected_client_identity = 8; // will force check_auth_context. } message EchoRequest { -- cgit v1.2.3 From 76ba1ff65af66550f71ee2fcac1e715535c98b94 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 28 Aug 2015 14:57:04 -0700 Subject: Switched to using static functions for accessing Client properties --- src/node/index.js | 10 +++++ src/node/interop/interop_client.js | 4 +- src/node/src/client.js | 83 +++++++++++++++++++++----------------- src/node/test/surface_test.js | 17 ++++---- 4 files changed, 68 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/node/index.js b/src/node/index.js index 51d3fa590c..02b73f66ee 100644 --- a/src/node/index.js +++ b/src/node/index.js @@ -164,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 da5e0f4afb..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, @@ -338,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/src/client.js b/src/node/src/client.js index 53b7cc3e8d..d6b7f59d7e 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -275,7 +275,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); @@ -349,7 +349,7 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) { 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); @@ -425,7 +425,7 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) { 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); @@ -503,7 +503,7 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) { 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); @@ -594,43 +594,16 @@ exports.makeClientConstructor = function(methods, serviceName) { options = {}; } options['grpc.primary_user_agent'] = 'grpc-node/' + version; + /* 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, '$')) { @@ -660,6 +633,44 @@ exports.makeClientConstructor = function(methods, serviceName) { return Client; }; +/** + * 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 diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js index 6bb90a2303..d917c7a171 100644 --- a/src/node/test/surface_test.js +++ b/src/node/test/surface_test.js @@ -151,7 +151,7 @@ describe('Client constructor building', function() { }, /\$/); }); }); -describe('Client#$waitForReady', function() { +describe('waitForClientReady', function() { var server; var port; var Client; @@ -169,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(); }); @@ -184,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(); }); @@ -444,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; -- cgit v1.2.3 From 7b773e94819d73433a7d2e4b961fade4e37c6814 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 28 Aug 2015 09:53:16 -0700 Subject: php: update readme; --- src/php/README.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/php/README.md b/src/php/README.md index f432935fde..0892816137 100644 --- a/src/php/README.md +++ b/src/php/README.md @@ -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 -- cgit v1.2.3 From aec4ac8221696447ddca43e223d29a1f2590922e Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 28 Aug 2015 14:48:14 -0700 Subject: update debian unstable to testing --- INSTALL | 4 ++-- src/node/README.md | 6 +++--- src/php/README.md | 6 +++--- src/python/README.md | 6 +++--- src/ruby/README.md | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/INSTALL b/INSTALL index d183fceb9a..de13d65d41 100644 --- a/INSTALL +++ b/INSTALL @@ -11,12 +11,12 @@ wiki pages: On Linux (Debian): - Note: you will need to add the Debian 'unstable' distribution to your sources + Note: you will need to add the Debian 'testing' distribution to your sources file first. Add the following line to your `/etc/apt/sources.list` file: - deb http://ftp.us.debian.org/debian unstable main contrib non-free + deb http://ftp.us.debian.org/debian testing main contrib non-free Install the gRPC library: diff --git a/src/node/README.md b/src/node/README.md index b6411537c7..c96bc96642 100644 --- a/src/node/README.md +++ b/src/node/README.md @@ -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/php/README.md b/src/php/README.md index 0892816137..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 ``` @@ -167,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/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/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/ -- cgit v1.2.3 From 5be92a316de32fd7552d64bcf70703f1ea9e41d8 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Fri, 28 Aug 2015 16:28:18 -0700 Subject: Shuffling headers around. --- include/grpc++/auth_metadata_processor.h | 74 ------------ include/grpc++/client_context.h | 2 +- include/grpc++/create_channel.h | 2 +- include/grpc++/credentials.h | 134 ---------------------- include/grpc++/security/auth_context.h | 104 +++++++++++++++++ include/grpc++/security/auth_metadata_processor.h | 74 ++++++++++++ include/grpc++/security/credentials.h | 134 ++++++++++++++++++++++ include/grpc++/security/server_credentials.h | 86 ++++++++++++++ include/grpc++/server_context.h | 2 +- include/grpc++/server_credentials.h | 86 -------------- include/grpc++/support/auth_context.h | 104 ----------------- src/cpp/client/channel.cc | 2 +- src/cpp/client/client_context.cc | 2 +- src/cpp/client/credentials.cc | 2 +- src/cpp/client/insecure_credentials.cc | 2 +- src/cpp/client/secure_credentials.h | 2 +- src/cpp/common/auth_property_iterator.cc | 2 +- src/cpp/common/create_auth_context.h | 2 +- src/cpp/common/insecure_create_auth_context.cc | 2 +- src/cpp/common/secure_auth_context.h | 2 +- src/cpp/common/secure_create_auth_context.cc | 2 +- src/cpp/server/insecure_server_credentials.cc | 2 +- src/cpp/server/secure_server_credentials.cc | 2 +- src/cpp/server/secure_server_credentials.h | 2 +- src/cpp/server/server.cc | 6 +- src/cpp/server/server_credentials.cc | 2 +- test/cpp/client/credentials_test.cc | 2 +- test/cpp/common/auth_property_iterator_test.cc | 2 +- test/cpp/common/secure_auth_context_test.cc | 2 +- test/cpp/end2end/async_end2end_test.cc | 4 +- test/cpp/end2end/client_crash_test.cc | 4 +- test/cpp/end2end/client_crash_test_server.cc | 2 +- test/cpp/end2end/end2end_test.cc | 6 +- test/cpp/end2end/generic_end2end_test.cc | 4 +- test/cpp/end2end/mock_test.cc | 4 +- test/cpp/end2end/server_crash_test.cc | 4 +- test/cpp/end2end/server_crash_test_client.cc | 2 +- test/cpp/end2end/shutdown_test.cc | 4 +- test/cpp/end2end/thread_stress_test.cc | 4 +- test/cpp/interop/client_helper.cc | 2 +- test/cpp/interop/interop_client.cc | 2 +- test/cpp/interop/reconnect_interop_server.cc | 2 +- test/cpp/interop/server.cc | 2 +- test/cpp/interop/server_helper.cc | 2 +- test/cpp/interop/server_helper.h | 2 +- test/cpp/qps/perf_db_client.h | 2 +- test/cpp/qps/qps_worker.cc | 2 +- test/cpp/qps/server_async.cc | 2 +- test/cpp/qps/server_sync.cc | 2 +- test/cpp/util/cli_call_test.cc | 4 +- test/cpp/util/create_test_channel.cc | 2 +- test/cpp/util/create_test_channel.h | 2 +- test/cpp/util/grpc_cli.cc | 4 +- 53 files changed, 456 insertions(+), 456 deletions(-) delete mode 100644 include/grpc++/auth_metadata_processor.h delete mode 100644 include/grpc++/credentials.h create mode 100644 include/grpc++/security/auth_context.h create mode 100644 include/grpc++/security/auth_metadata_processor.h create mode 100644 include/grpc++/security/credentials.h create mode 100644 include/grpc++/security/server_credentials.h delete mode 100644 include/grpc++/server_credentials.h delete mode 100644 include/grpc++/support/auth_context.h (limited to 'src') diff --git a/include/grpc++/auth_metadata_processor.h b/include/grpc++/auth_metadata_processor.h deleted file mode 100644 index a42abef416..0000000000 --- a/include/grpc++/auth_metadata_processor.h +++ /dev/null @@ -1,74 +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. - * - */ - -#ifndef GRPCXX_AUTH_METADATA_PROCESSOR_H_ -#define GRPCXX_AUTH_METADATA_PROCESSOR_H_ - -#include - -#include -#include -#include - -namespace grpc { - -class AuthMetadataProcessor { - public: - typedef std::multimap InputMetadata; - typedef std::multimap OutputMetadata; - - virtual ~AuthMetadataProcessor() {} - - // If this method returns true, the Process function will be scheduled in - // a different thread from the one processing the call. - virtual bool IsBlocking() const { return true; } - - // context is read/write: it contains the properties of the channel peer and - // it is the job of the Process method to augment it with properties derived - // from the passed-in auth_metadata. - // consumed_auth_metadata needs to be filled with metadata that has been - // consumed by the processor and will be removed from the call. - // response_metadata is the metadata that will be sent as part of the - // response. - // If the return value is not Status::OK, the rpc call will be aborted with - // the error code and error message sent back to the client. - virtual Status Process(const InputMetadata& auth_metadata, - AuthContext* context, - OutputMetadata* consumed_auth_metadata, - OutputMetadata* response_metadata) = 0; -}; - -} // namespace grpc - -#endif // GRPCXX_AUTH_METADATA_PROCESSOR_H_ - diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h index 62e5260a18..917a1222a8 100644 --- a/include/grpc++/client_context.h +++ b/include/grpc++/client_context.h @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h index 916f3b0b97..72f05174e1 100644 --- a/include/grpc++/create_channel.h +++ b/include/grpc++/create_channel.h @@ -36,7 +36,7 @@ #include -#include +#include #include #include diff --git a/include/grpc++/credentials.h b/include/grpc++/credentials.h deleted file mode 100644 index ce5a9e0606..0000000000 --- a/include/grpc++/credentials.h +++ /dev/null @@ -1,134 +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. - * - */ - -#ifndef GRPCXX_CREDENTIALS_H -#define GRPCXX_CREDENTIALS_H - -#include - -#include -#include - -namespace grpc { -class ChannelArguments; -class Channel; -class SecureCredentials; - -class Credentials : public GrpcLibrary { - public: - ~Credentials() GRPC_OVERRIDE; - virtual bool ApplyToCall(grpc_call* call) = 0; - - protected: - friend std::shared_ptr CompositeCredentials( - const std::shared_ptr& creds1, - const std::shared_ptr& creds2); - - virtual SecureCredentials* AsSecureCredentials() = 0; - - private: - friend std::shared_ptr CreateCustomChannel( - const grpc::string& target, const std::shared_ptr& creds, - const ChannelArguments& args); - - virtual std::shared_ptr CreateChannel( - const grpc::string& target, const ChannelArguments& args) = 0; -}; - -// Options used to build SslCredentials -// pem_roots_cert is the buffer containing the PEM encoding of the server root -// certificates. If this parameter is empty, the default roots will be used. -// pem_private_key is the buffer containing the PEM encoding of the client's -// private key. This parameter can be empty if the client does not have a -// private key. -// pem_cert_chain is the buffer containing the PEM encoding of the client's -// certificate chain. This parameter can be empty if the client does not have -// a certificate chain. -struct SslCredentialsOptions { - grpc::string pem_root_certs; - grpc::string pem_private_key; - grpc::string pem_cert_chain; -}; - -// Factories for building different types of Credentials -// The functions may return empty shared_ptr when credentials cannot be created. -// If a Credentials pointer is returned, it can still be invalid when used to -// create a channel. A lame channel will be created then and all rpcs will -// fail on it. - -// Builds credentials with reasonable defaults. -std::shared_ptr GoogleDefaultCredentials(); - -// Builds SSL Credentials given SSL specific options -std::shared_ptr SslCredentials( - const SslCredentialsOptions& options); - -// Builds credentials for use when running in GCE -std::shared_ptr GoogleComputeEngineCredentials(); - -// Builds Service Account JWT Access credentials. -// json_key is the JSON key string containing the client's private key. -// token_lifetime_seconds is the lifetime in seconds of each Json Web Token -// (JWT) created with this credentials. It should not exceed -// grpc_max_auth_token_lifetime or will be cropped to this value. -std::shared_ptr ServiceAccountJWTAccessCredentials( - const grpc::string& json_key, long token_lifetime_seconds); - -// Builds refresh token credentials. -// json_refresh_token is the JSON string containing the refresh token along -// with a client_id and client_secret. -std::shared_ptr GoogleRefreshTokenCredentials( - const grpc::string& json_refresh_token); - -// Builds access token credentials. -// access_token is an oauth2 access token that was fetched using an out of band -// mechanism. -std::shared_ptr AccessTokenCredentials( - const grpc::string& access_token); - -// Builds IAM credentials. -std::shared_ptr GoogleIAMCredentials( - const grpc::string& authorization_token, - const grpc::string& authority_selector); - -// Combines two credentials objects into a composite credentials -std::shared_ptr CompositeCredentials( - const std::shared_ptr& creds1, - const std::shared_ptr& creds2); - -// Credentials for an unencrypted, unauthenticated channel -std::shared_ptr InsecureCredentials(); - -} // namespace grpc - -#endif // GRPCXX_CREDENTIALS_H diff --git a/include/grpc++/security/auth_context.h b/include/grpc++/security/auth_context.h new file mode 100644 index 0000000000..fc2701e806 --- /dev/null +++ b/include/grpc++/security/auth_context.h @@ -0,0 +1,104 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPCXX_SUPPORT_AUTH_CONTEXT_H +#define GRPCXX_SUPPORT_AUTH_CONTEXT_H + +#include +#include + +#include +#include + +struct grpc_auth_context; +struct grpc_auth_property; +struct grpc_auth_property_iterator; + +namespace grpc { +class SecureAuthContext; + +typedef std::pair AuthProperty; + +class AuthPropertyIterator + : public std::iterator { + public: + ~AuthPropertyIterator(); + AuthPropertyIterator& operator++(); + AuthPropertyIterator operator++(int); + bool operator==(const AuthPropertyIterator& rhs) const; + bool operator!=(const AuthPropertyIterator& rhs) const; + const AuthProperty operator*(); + + protected: + AuthPropertyIterator(); + AuthPropertyIterator(const grpc_auth_property* property, + const grpc_auth_property_iterator* iter); + + private: + friend class SecureAuthContext; + const grpc_auth_property* property_; + // The following items form a grpc_auth_property_iterator. + const grpc_auth_context* ctx_; + size_t index_; + const char* name_; +}; + +class AuthContext { + public: + virtual ~AuthContext() {} + + // Returns true if the peer is authenticated. + virtual bool IsPeerAuthenticated() const = 0; + + // A peer identity, in general is one or more properties (in which case they + // have the same name). + virtual std::vector GetPeerIdentity() const = 0; + virtual grpc::string GetPeerIdentityPropertyName() const = 0; + + // Returns all the property values with the given name. + virtual std::vector FindPropertyValues( + const grpc::string& name) const = 0; + + // Iteration over all the properties. + virtual AuthPropertyIterator begin() const = 0; + virtual AuthPropertyIterator end() const = 0; + + // Mutation functions: should only be used by an AuthMetadataProcessor. + virtual void AddProperty(const grpc::string& key, + const grpc::string_ref& value) = 0; + virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0; +}; + +} // namespace grpc + +#endif // GRPCXX_SUPPORT_AUTH_CONTEXT_H diff --git a/include/grpc++/security/auth_metadata_processor.h b/include/grpc++/security/auth_metadata_processor.h new file mode 100644 index 0000000000..18ad922321 --- /dev/null +++ b/include/grpc++/security/auth_metadata_processor.h @@ -0,0 +1,74 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPCXX_AUTH_METADATA_PROCESSOR_H_ +#define GRPCXX_AUTH_METADATA_PROCESSOR_H_ + +#include + +#include +#include +#include + +namespace grpc { + +class AuthMetadataProcessor { + public: + typedef std::multimap InputMetadata; + typedef std::multimap OutputMetadata; + + virtual ~AuthMetadataProcessor() {} + + // If this method returns true, the Process function will be scheduled in + // a different thread from the one processing the call. + virtual bool IsBlocking() const { return true; } + + // context is read/write: it contains the properties of the channel peer and + // it is the job of the Process method to augment it with properties derived + // from the passed-in auth_metadata. + // consumed_auth_metadata needs to be filled with metadata that has been + // consumed by the processor and will be removed from the call. + // response_metadata is the metadata that will be sent as part of the + // response. + // If the return value is not Status::OK, the rpc call will be aborted with + // the error code and error message sent back to the client. + virtual Status Process(const InputMetadata& auth_metadata, + AuthContext* context, + OutputMetadata* consumed_auth_metadata, + OutputMetadata* response_metadata) = 0; +}; + +} // namespace grpc + +#endif // GRPCXX_AUTH_METADATA_PROCESSOR_H_ + diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h new file mode 100644 index 0000000000..ce5a9e0606 --- /dev/null +++ b/include/grpc++/security/credentials.h @@ -0,0 +1,134 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPCXX_CREDENTIALS_H +#define GRPCXX_CREDENTIALS_H + +#include + +#include +#include + +namespace grpc { +class ChannelArguments; +class Channel; +class SecureCredentials; + +class Credentials : public GrpcLibrary { + public: + ~Credentials() GRPC_OVERRIDE; + virtual bool ApplyToCall(grpc_call* call) = 0; + + protected: + friend std::shared_ptr CompositeCredentials( + const std::shared_ptr& creds1, + const std::shared_ptr& creds2); + + virtual SecureCredentials* AsSecureCredentials() = 0; + + private: + friend std::shared_ptr CreateCustomChannel( + const grpc::string& target, const std::shared_ptr& creds, + const ChannelArguments& args); + + virtual std::shared_ptr CreateChannel( + const grpc::string& target, const ChannelArguments& args) = 0; +}; + +// Options used to build SslCredentials +// pem_roots_cert is the buffer containing the PEM encoding of the server root +// certificates. If this parameter is empty, the default roots will be used. +// pem_private_key is the buffer containing the PEM encoding of the client's +// private key. This parameter can be empty if the client does not have a +// private key. +// pem_cert_chain is the buffer containing the PEM encoding of the client's +// certificate chain. This parameter can be empty if the client does not have +// a certificate chain. +struct SslCredentialsOptions { + grpc::string pem_root_certs; + grpc::string pem_private_key; + grpc::string pem_cert_chain; +}; + +// Factories for building different types of Credentials +// The functions may return empty shared_ptr when credentials cannot be created. +// If a Credentials pointer is returned, it can still be invalid when used to +// create a channel. A lame channel will be created then and all rpcs will +// fail on it. + +// Builds credentials with reasonable defaults. +std::shared_ptr GoogleDefaultCredentials(); + +// Builds SSL Credentials given SSL specific options +std::shared_ptr SslCredentials( + const SslCredentialsOptions& options); + +// Builds credentials for use when running in GCE +std::shared_ptr GoogleComputeEngineCredentials(); + +// Builds Service Account JWT Access credentials. +// json_key is the JSON key string containing the client's private key. +// token_lifetime_seconds is the lifetime in seconds of each Json Web Token +// (JWT) created with this credentials. It should not exceed +// grpc_max_auth_token_lifetime or will be cropped to this value. +std::shared_ptr ServiceAccountJWTAccessCredentials( + const grpc::string& json_key, long token_lifetime_seconds); + +// Builds refresh token credentials. +// json_refresh_token is the JSON string containing the refresh token along +// with a client_id and client_secret. +std::shared_ptr GoogleRefreshTokenCredentials( + const grpc::string& json_refresh_token); + +// Builds access token credentials. +// access_token is an oauth2 access token that was fetched using an out of band +// mechanism. +std::shared_ptr AccessTokenCredentials( + const grpc::string& access_token); + +// Builds IAM credentials. +std::shared_ptr GoogleIAMCredentials( + const grpc::string& authorization_token, + const grpc::string& authority_selector); + +// Combines two credentials objects into a composite credentials +std::shared_ptr CompositeCredentials( + const std::shared_ptr& creds1, + const std::shared_ptr& creds2); + +// Credentials for an unencrypted, unauthenticated channel +std::shared_ptr InsecureCredentials(); + +} // namespace grpc + +#endif // GRPCXX_CREDENTIALS_H diff --git a/include/grpc++/security/server_credentials.h b/include/grpc++/security/server_credentials.h new file mode 100644 index 0000000000..2094c7403c --- /dev/null +++ b/include/grpc++/security/server_credentials.h @@ -0,0 +1,86 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPCXX_SERVER_CREDENTIALS_H +#define GRPCXX_SERVER_CREDENTIALS_H + +#include +#include + +#include +#include + +struct grpc_server; + +namespace grpc { +class Server; + +// grpc_server_credentials wrapper class. +class ServerCredentials { + public: + virtual ~ServerCredentials(); + + // This method is not thread-safe and has to be called before the server is + // started. The last call to this function wins. + virtual void SetAuthMetadataProcessor( + const std::shared_ptr& processor) = 0; + + private: + friend class ::grpc::Server; + + virtual int AddPortToServer(const grpc::string& addr, + grpc_server* server) = 0; +}; + +// Options to create ServerCredentials with SSL +struct SslServerCredentialsOptions { + SslServerCredentialsOptions() : force_client_auth(false) {} + + struct PemKeyCertPair { + grpc::string private_key; + grpc::string cert_chain; + }; + grpc::string pem_root_certs; + std::vector pem_key_cert_pairs; + bool force_client_auth; +}; + +// Builds SSL ServerCredentials given SSL specific options +std::shared_ptr SslServerCredentials( + const SslServerCredentialsOptions& options); + +std::shared_ptr InsecureServerCredentials(); + +} // namespace grpc + +#endif // GRPCXX_SERVER_CREDENTIALS_H diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h index 4b17a28047..85f384d477 100644 --- a/include/grpc++/server_context.h +++ b/include/grpc++/server_context.h @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/grpc++/server_credentials.h b/include/grpc++/server_credentials.h deleted file mode 100644 index e006f3a180..0000000000 --- a/include/grpc++/server_credentials.h +++ /dev/null @@ -1,86 +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. - * - */ - -#ifndef GRPCXX_SERVER_CREDENTIALS_H -#define GRPCXX_SERVER_CREDENTIALS_H - -#include -#include - -#include -#include - -struct grpc_server; - -namespace grpc { -class Server; - -// grpc_server_credentials wrapper class. -class ServerCredentials { - public: - virtual ~ServerCredentials(); - - // This method is not thread-safe and has to be called before the server is - // started. The last call to this function wins. - virtual void SetAuthMetadataProcessor( - const std::shared_ptr& processor) = 0; - - private: - friend class ::grpc::Server; - - virtual int AddPortToServer(const grpc::string& addr, - grpc_server* server) = 0; -}; - -// Options to create ServerCredentials with SSL -struct SslServerCredentialsOptions { - SslServerCredentialsOptions() : force_client_auth(false) {} - - struct PemKeyCertPair { - grpc::string private_key; - grpc::string cert_chain; - }; - grpc::string pem_root_certs; - std::vector pem_key_cert_pairs; - bool force_client_auth; -}; - -// Builds SSL ServerCredentials given SSL specific options -std::shared_ptr SslServerCredentials( - const SslServerCredentialsOptions& options); - -std::shared_ptr InsecureServerCredentials(); - -} // namespace grpc - -#endif // GRPCXX_SERVER_CREDENTIALS_H diff --git a/include/grpc++/support/auth_context.h b/include/grpc++/support/auth_context.h deleted file mode 100644 index fc2701e806..0000000000 --- a/include/grpc++/support/auth_context.h +++ /dev/null @@ -1,104 +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. - * - */ - -#ifndef GRPCXX_SUPPORT_AUTH_CONTEXT_H -#define GRPCXX_SUPPORT_AUTH_CONTEXT_H - -#include -#include - -#include -#include - -struct grpc_auth_context; -struct grpc_auth_property; -struct grpc_auth_property_iterator; - -namespace grpc { -class SecureAuthContext; - -typedef std::pair AuthProperty; - -class AuthPropertyIterator - : public std::iterator { - public: - ~AuthPropertyIterator(); - AuthPropertyIterator& operator++(); - AuthPropertyIterator operator++(int); - bool operator==(const AuthPropertyIterator& rhs) const; - bool operator!=(const AuthPropertyIterator& rhs) const; - const AuthProperty operator*(); - - protected: - AuthPropertyIterator(); - AuthPropertyIterator(const grpc_auth_property* property, - const grpc_auth_property_iterator* iter); - - private: - friend class SecureAuthContext; - const grpc_auth_property* property_; - // The following items form a grpc_auth_property_iterator. - const grpc_auth_context* ctx_; - size_t index_; - const char* name_; -}; - -class AuthContext { - public: - virtual ~AuthContext() {} - - // Returns true if the peer is authenticated. - virtual bool IsPeerAuthenticated() const = 0; - - // A peer identity, in general is one or more properties (in which case they - // have the same name). - virtual std::vector GetPeerIdentity() const = 0; - virtual grpc::string GetPeerIdentityPropertyName() const = 0; - - // Returns all the property values with the given name. - virtual std::vector FindPropertyValues( - const grpc::string& name) const = 0; - - // Iteration over all the properties. - virtual AuthPropertyIterator begin() const = 0; - virtual AuthPropertyIterator end() const = 0; - - // Mutation functions: should only be used by an AuthMetadataProcessor. - virtual void AddProperty(const grpc::string& key, - const grpc::string_ref& value) = 0; - virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0; -}; - -} // namespace grpc - -#endif // GRPCXX_SUPPORT_AUTH_CONTEXT_H 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 #include #include -#include +#include #include #include #include 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 #include #include -#include +#include #include #include 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 +#include 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 +#include #include #include 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 #include -#include +#include 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 +#include #include 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 #include -#include +#include 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 #include -#include +#include namespace grpc { diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h index 6edab0cee1..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 +#include struct grpc_auth_context; diff --git a/src/cpp/common/secure_create_auth_context.cc b/src/cpp/common/secure_create_auth_context.cc index 5a907d0c0b..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 #include -#include +#include #include "src/cpp/common/secure_auth_context.h" namespace grpc { diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc index 12807e70e7..ef3cae5fd7 100644 --- a/src/cpp/server/insecure_server_credentials.cc +++ b/src/cpp/server/insecure_server_credentials.cc @@ -31,7 +31,7 @@ * */ -#include +#include #include #include diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index 0e2927bafe..dfa9229c98 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -39,7 +39,7 @@ #include "src/cpp/common/secure_auth_context.h" #include "src/cpp/server/secure_server_credentials.h" -#include +#include namespace grpc { diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index 17be9e310d..4f003c6b7e 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -36,7 +36,7 @@ #include -#include +#include #include 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 #include #include -#include +#include #include #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 +#include namespace grpc { diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc index 18fcffe7cd..743ad065d1 100644 --- a/test/cpp/client/credentials_test.cc +++ b/test/cpp/client/credentials_test.cc @@ -31,7 +31,7 @@ * */ -#include +#include #include diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc index e6226d6a09..a629ff5a90 100644 --- a/test/cpp/common/auth_property_iterator_test.cc +++ b/test/cpp/common/auth_property_iterator_test.cc @@ -32,7 +32,7 @@ */ #include -#include +#include #include #include "src/cpp/common/secure_auth_context.h" #include "test/cpp/util/string_ref_helper.h" diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc index e1f2c5e968..11de646999 100644 --- a/test/cpp/common/secure_auth_context_test.cc +++ b/test/cpp/common/secure_auth_context_test.cc @@ -32,7 +32,7 @@ */ #include -#include +#include #include #include "src/cpp/common/secure_auth_context.h" #include "test/cpp/util/string_ref_helper.h" diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index bbcac9ba34..46886a2f15 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -39,11 +39,11 @@ #include #include #include -#include +#include +#include #include #include #include -#include #include #include "test/core/util/port.h" diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc index 3a6e55216a..4123fd5f13 100644 --- a/test/cpp/end2end/client_crash_test.cc +++ b/test/cpp/end2end/client_crash_test.cc @@ -37,11 +37,11 @@ #include #include #include -#include +#include #include #include #include -#include +#include #include #include "test/core/util/port.h" diff --git a/test/cpp/end2end/client_crash_test_server.cc b/test/cpp/end2end/client_crash_test_server.cc index 79a7832874..6e1d84c3a5 100644 --- a/test/cpp/end2end/client_crash_test_server.cc +++ b/test/cpp/end2end/client_crash_test_server.cc @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "test/cpp/util/echo.grpc.pb.h" DEFINE_string(address, "", "Address to bind to"); diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 3fc73ab9e5..e339549880 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -37,15 +37,15 @@ #include #include #include -#include #include #include #include -#include +#include +#include +#include #include #include #include -#include #include #include "src/core/security/credentials.h" diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc index 7acbc711fb..166e576826 100644 --- a/test/cpp/end2end/generic_end2end_test.cc +++ b/test/cpp/end2end/generic_end2end_test.cc @@ -40,13 +40,13 @@ #include #include #include -#include #include #include +#include +#include #include #include #include -#include #include #include diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc index 077d21aa72..b7bec02458 100644 --- a/test/cpp/end2end/mock_test.cc +++ b/test/cpp/end2end/mock_test.cc @@ -39,11 +39,11 @@ #include #include #include -#include +#include +#include #include #include #include -#include #include #include "test/core/util/port.h" diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc index 1a0f04e22b..23e9af312c 100644 --- a/test/cpp/end2end/server_crash_test.cc +++ b/test/cpp/end2end/server_crash_test.cc @@ -37,11 +37,11 @@ #include #include #include -#include +#include +#include #include #include #include -#include #include #include "test/core/util/port.h" diff --git a/test/cpp/end2end/server_crash_test_client.cc b/test/cpp/end2end/server_crash_test_client.cc index 6ff42fcb30..4cfb131ab2 100644 --- a/test/cpp/end2end/server_crash_test_client.cc +++ b/test/cpp/end2end/server_crash_test_client.cc @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include "test/cpp/util/echo.grpc.pb.h" DEFINE_string(address, "", "Address to connect to"); diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc index 59fec6ad40..e351b43260 100644 --- a/test/cpp/end2end/shutdown_test.cc +++ b/test/cpp/end2end/shutdown_test.cc @@ -38,11 +38,11 @@ #include #include #include -#include +#include +#include #include #include #include -#include #include #include "src/core/support/env.h" diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc index 2a16481972..85042e0055 100644 --- a/test/cpp/end2end/thread_stress_test.cc +++ b/test/cpp/end2end/thread_stress_test.cc @@ -40,11 +40,11 @@ #include #include #include -#include +#include +#include #include #include #include -#include #include #include "test/core/util/port.h" diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc index 7093463fa8..f85aa6ad8e 100644 --- a/test/cpp/interop/client_helper.cc +++ b/test/cpp/interop/client_helper.cc @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include "src/cpp/client/secure_credentials.h" #include "test/core/security/oauth2_utils.h" diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc index 73d1a143c4..48ccf06da9 100644 --- a/test/cpp/interop/interop_client.cc +++ b/test/cpp/interop/interop_client.cc @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include "src/core/transport/stream_op.h" #include "test/cpp/interop/client_helper.h" diff --git a/test/cpp/interop/reconnect_interop_server.cc b/test/cpp/interop/reconnect_interop_server.cc index d4f171b1d0..be1d840bdf 100644 --- a/test/cpp/interop/reconnect_interop_server.cc +++ b/test/cpp/interop/reconnect_interop_server.cc @@ -42,10 +42,10 @@ #include #include #include +#include #include #include #include -#include #include "test/core/util/reconnect_server.h" #include "test/cpp/util/test_config.h" diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc index 4921fde9fa..03b6532447 100644 --- a/test/cpp/interop/server.cc +++ b/test/cpp/interop/server.cc @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include "test/cpp/interop/server_helper.h" #include "test/cpp/util/test_config.h" diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc index e897f4ebf0..015198354e 100644 --- a/test/cpp/interop/server_helper.cc +++ b/test/cpp/interop/server_helper.cc @@ -36,7 +36,7 @@ #include #include -#include +#include #include "src/core/surface/call.h" #include "test/core/end2end/data/ssl_test_data.h" diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h index 7b6b12cd4d..dc0ae1dccd 100644 --- a/test/cpp/interop/server_helper.h +++ b/test/cpp/interop/server_helper.h @@ -38,7 +38,7 @@ #include #include -#include +#include namespace grpc { namespace testing { diff --git a/test/cpp/qps/perf_db_client.h b/test/cpp/qps/perf_db_client.h index ae5d17074b..72ebe79c3c 100644 --- a/test/cpp/qps/perf_db_client.h +++ b/test/cpp/qps/perf_db_client.h @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include "test/cpp/qps/perf_db.grpc.pb.h" namespace grpc { diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc index 51e955a80a..4b4ca1a0ce 100644 --- a/test/cpp/qps/qps_worker.cc +++ b/test/cpp/qps/qps_worker.cc @@ -49,7 +49,7 @@ #include #include #include -#include +#include #include "test/core/util/grpc_profiler.h" #include "test/cpp/qps/qpstest.pb.h" diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index 77415f42ce..4160392cbe 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -49,7 +49,7 @@ #include #include #include -#include +#include #include #include "test/cpp/qps/qpstest.grpc.pb.h" diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc index 29ec19cd4b..01ae3480f9 100644 --- a/test/cpp/qps/server_sync.cc +++ b/test/cpp/qps/server_sync.cc @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include "test/cpp/qps/qpstest.grpc.pb.h" #include "test/cpp/qps/server.h" diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc index 0efa201622..1c3f0d3f73 100644 --- a/test/cpp/util/cli_call_test.cc +++ b/test/cpp/util/cli_call_test.cc @@ -37,11 +37,11 @@ #include #include #include -#include +#include +#include #include #include #include -#include #include #include "test/core/util/port.h" diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc index e993d14e71..f0d5bfc7eb 100644 --- a/test/cpp/util/create_test_channel.cc +++ b/test/cpp/util/create_test_channel.cc @@ -34,7 +34,7 @@ #include "test/cpp/util/create_test_channel.h" #include -#include +#include #include "test/core/end2end/data/ssl_test_data.h" diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h index 1263d4ed68..a4750689a0 100644 --- a/test/cpp/util/create_test_channel.h +++ b/test/cpp/util/create_test_channel.h @@ -36,7 +36,7 @@ #include -#include +#include namespace grpc { class Channel; diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc index 22cac21f77..334b6efb6a 100644 --- a/test/cpp/util/grpc_cli.cc +++ b/test/cpp/util/grpc_cli.cc @@ -1,5 +1,5 @@ /* - * + * Copyright 2015, Google Inc. * All rights reserved. * @@ -67,7 +67,7 @@ #include #include #include -#include +#include #include #include "test/cpp/util/cli_call.h" -- cgit v1.2.3 From 81d950a5a91d863547761bcf5647ae8ebfc72722 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Fri, 28 Aug 2015 16:57:28 -0700 Subject: Updates server shutdown handling - ensures that servers cancels calls after the shutdown timeout - uses an infinite timeout when request server calls This two changes fix the issue where the server segfaults on shutdown. --- src/ruby/bin/math_client.rb | 6 +++--- src/ruby/bin/math_server.rb | 16 ++++++++++++++++ src/ruby/ext/grpc/rb_server.c | 30 +++++------------------------- src/ruby/lib/grpc/generic/rpc_server.rb | 15 ++++++++------- 4 files changed, 32 insertions(+), 35 deletions(-) (limited to 'src') 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..9a921b13d6 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) diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 7e76349d2e..bd19b2fe4e 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -234,6 +234,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,36 +299,15 @@ 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; } /* diff --git a/src/ruby/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 67bf35ce02..38ea333413 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,14 +414,13 @@ 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) 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? @@ -431,6 +430,8 @@ module GRPC end end end + @running = false + GRPC.logger.info("stopped: #{self}") end def new_active_server_call(an_rpc) -- cgit v1.2.3 From 1d14618a0e3a86a705d543a8c761aa60bd1a59c0 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Sat, 29 Aug 2015 19:18:22 +0000 Subject: Fix grace period bug in _end.accept_ticket Tickets should not be ignored if the end is in a grace period; rather they should be ignored if they are for an unrecognized (likely new) operation and the end is in a grace period. --- src/python/grpcio/grpc/framework/core/_end.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/framework/core/_end.py b/src/python/grpcio/grpc/framework/core/_end.py index 5ef2f6d3a3..f57cde4e58 100644 --- a/src/python/grpcio/grpc/framework/core/_end.py +++ b/src/python/grpcio/grpc/framework/core/_end.py @@ -203,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( -- cgit v1.2.3 From 154e762ae8f2711cbb7097616859f5ff9c677ecf Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Sun, 30 Aug 2015 18:44:56 +0000 Subject: Fix gRPC links lifecycle tracking --- src/python/grpcio/grpc/_links/invocation.py | 115 +++++++++++++++++----------- src/python/grpcio/grpc/_links/service.py | 80 ++++++++++++------- 2 files changed, 123 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/_links/invocation.py b/src/python/grpcio/grpc/_links/invocation.py index ee3d72fdbc..729b987dd1 100644 --- a/src/python/grpcio/grpc/_links/invocation.py +++ b/src/python/grpcio/grpc/_links/invocation.py @@ -41,6 +41,13 @@ from grpc.framework.foundation import logging_pool from grpc.framework.foundation import relay from grpc.framework.interfaces.links import links +_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 +74,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,6 +83,13 @@ 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): @@ -91,12 +105,14 @@ class _Kernel(object): 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 +121,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 +142,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 +179,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, @@ -221,26 +245,31 @@ class _Kernel(object): 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) diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py index c5ecc47cd9..bbfe9bcd55 100644 --- a/src/python/grpcio/grpc/_links/service.py +++ b/src/python/grpcio/grpc/_links/service.py @@ -53,6 +53,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 +91,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 +106,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 +138,7 @@ class _Kernel(object): self._relay = ticket_relay self._completion_queue = None + self._due = set() self._server = None self._rpc_states = {} self._pool = None @@ -149,7 +164,8 @@ class _Kernel(object): 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,7 +338,7 @@ 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, address, server_credentials): with self._lock: @@ -335,19 +359,17 @@ 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 begin_stop(self): with self._lock: self._server.stop() + self._due.add(_STOP) self._server = None def end_stop(self): with self._lock: - self._completion_queue.stop() - self._completion_queue = None pool = self._pool - self._pool = None - self._rpc_states = None pool.shutdown(wait=True) @@ -369,7 +391,7 @@ class ServiceLink(links.Link): None for insecure service. Returns: - A integer port on which RPCs will be serviced after this link has been + 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. -- cgit v1.2.3 From dff73c7d23fe6fa405b7311696e8f3c4b8484e8e Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Sun, 30 Aug 2015 20:09:33 +0000 Subject: Drop invoker during test tear-down The invoker is an object derived from, and referring to, objects of the Face implementation under test. If those objects are to be garbage collected at the appropriate time the invoker that references them must be made eligible for garbage collection in the test's tearDown method. --- .../framework/interfaces/face/_blocking_invocation_inline_service.py | 1 + .../interfaces/face/_event_invocation_synchronous_event_service.py | 1 + .../interfaces/face/_future_invocation_asynchronous_event_service.py | 1 + 3 files changed, 3 insertions(+) (limited to 'src') 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) -- cgit v1.2.3 From fe1478f19e0bf8d7f26ecd3f3b02b25b2fbd86d0 Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Sun, 30 Aug 2015 21:57:38 -0700 Subject: Change the ownership model of the auth processor. - The processor now belongs to the server credentials in core. - The server credentials now needs to be refcounted. - Changed slighly the vtable of credentials to make it easier to avoid memory leaks (free'ing the pointer is now done at the common layer, the implementations of the creds are now only reponsible for destructing the implementations' specific members. --- src/core/security/credentials.c | 95 +++++++++++++++++--------------- src/core/security/credentials.h | 12 +++- src/core/security/server_secure_chttp2.c | 16 ++---- 3 files changed, 65 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c index 721e871ade..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( @@ -158,25 +178,16 @@ void grpc_server_credentials_set_auth_metadata_processor( creds->processor = processor; } -void grpc_server_credentials_destroy(grpc_server_credentials *creds) { - if (creds == NULL) return; - if (creds->processor.destroy != NULL && creds->processor.state != NULL) { - creds->processor.destroy(creds->processor.state); - } - gpr_free(creds); -} - /* -- 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++) { @@ -196,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); - grpc_server_credentials_destroy(creds); } static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; } @@ -242,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) { @@ -327,9 +337,9 @@ grpc_server_credentials *grpc_ssl_server_credentials_create( grpc_ssl_server_credentials *c = gpr_malloc(sizeof(grpc_ssl_server_credentials)); GPR_ASSERT(reserved == NULL); - memset(c, 0, sizeof(grpc_ssl_credentials)); 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); @@ -350,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; } @@ -421,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 * @@ -453,13 +462,12 @@ grpc_credentials *grpc_service_account_jwt_access_credentials_create( /* -- 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( @@ -632,7 +640,7 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c, /* -- 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}; @@ -663,15 +671,15 @@ grpc_credentials *grpc_google_compute_engine_credentials_create( /* -- GoogleRefreshToken credentials. -- */ -static void refresh_token_destroy(grpc_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}; @@ -724,10 +732,9 @@ grpc_credentials *grpc_google_refresh_token_credentials_create( /* -- 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) { @@ -768,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}; @@ -789,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) { @@ -814,7 +820,7 @@ 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}; @@ -838,14 +844,14 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token, /* -- 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) { - grpc_server_credentials_destroy(creds); + /* Nothing to do here. */ } static int fake_transport_security_has_request_metadata( @@ -874,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) { @@ -898,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; } @@ -914,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) { @@ -1037,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}; @@ -1136,10 +1142,9 @@ grpc_credentials *grpc_credentials_contains_type( /* -- IAM credentials. -- */ -static void iam_destroy(grpc_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; } @@ -1159,7 +1164,7 @@ static void iam_get_request_metadata(grpc_credentials *creds, } 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_google_iam_credentials_create( diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h index d9bd53adc2..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 { diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c index 96ca4cbd76..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,9 +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"); - if (state->processor.state != NULL && state->processor.destroy != NULL) { - state->processor.destroy(state->processor.state); - } + grpc_server_credentials_unref(state->creds); gpr_free(state); } } @@ -94,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)); @@ -265,12 +264,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr, state->server = server; state->tcp = tcp; state->sc = sc; - - /* Transfer ownership of the processor. */ - state->processor = creds->processor; - creds->processor.state = NULL; - creds->processor.destroy = NULL; - creds->processor.process = NULL; + state->creds = grpc_server_credentials_ref(creds); state->handshaking_tcp_endpoints = NULL; state->is_shutdown = 0; -- cgit v1.2.3 From 99355ce1cc6926d6a39b6660e8c60ad49e53d510 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Mon, 31 Aug 2015 05:11:52 +0000 Subject: Metadata plumbing and serialization tweaks (1) Plumb the metadata transformer given at the Beta API through to the InvocationLink where it will be used. (2) In both InvocationLink and ServiceLink, if there isn't a registered serializer or deserializer, just pass the payload through rather than ignoring the entire RPC. --- src/python/grpcio/grpc/_links/invocation.py | 43 ++++++++++++++-------- src/python/grpcio/grpc/_links/service.py | 16 ++++---- src/python/grpcio/grpc/beta/_stub.py | 24 ++++++------ src/python/grpcio/grpc/beta/beta.py | 4 +- .../_core_over_links_base_interface_test.py | 2 +- ...ust_over_core_over_links_face_interface_test.py | 2 +- .../_links/_lonely_invocation_link_test.py | 6 +-- .../grpc_test/_links/_transmission_test.py | 6 +-- 8 files changed, 60 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/_links/invocation.py b/src/python/grpcio/grpc/_links/invocation.py index 729b987dd1..1676fe7941 100644 --- a/src/python/grpcio/grpc/_links/invocation.py +++ b/src/python/grpcio/grpc/_links/invocation.py @@ -41,6 +41,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 + _STOP = _intermediary_low.Event.Kind.STOP _WRITE = _intermediary_low.Event.Kind.WRITE_ACCEPTED _COMPLETE = _intermediary_low.Event.Kind.COMPLETE_ACCEPTED @@ -95,11 +97,12 @@ def _no_longer_due(kind, rpc_state, key, rpc_states): 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 @@ -225,20 +228,17 @@ 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: @@ -336,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() @@ -376,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 @@ -391,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 bbfe9bcd55..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, @@ -154,12 +156,10 @@ 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( @@ -433,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) diff --git a/src/python/grpcio/grpc/beta/_stub.py b/src/python/grpcio/grpc/beta/_stub.py index 178f06d21e..cfbecb852b 100644 --- a/src/python/grpcio/grpc/beta/_stub.py +++ b/src/python/grpcio/grpc/beta/_stub.py @@ -54,11 +54,12 @@ class _AutoIntermediary(object): def _assemble( - channel, host, request_serializers, response_deserializers, thread_pool, - thread_pool_size): + 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, request_serializers, response_deserializers) + 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) @@ -89,21 +90,22 @@ def _wrap_assembly(stub, end_link, grpc_link, assembly_pool): def generic_stub( - channel, host, request_serializers, response_deserializers, thread_pool, - thread_pool_size): + channel, host, metadata_transformer, request_serializers, + response_deserializers, thread_pool, thread_pool_size): end_link, grpc_link, invocation_pool, assembly_pool = _assemble( - channel, host, request_serializers, response_deserializers, thread_pool, - thread_pool_size) + 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, request_serializers, - response_deserializers, thread_pool, thread_pool_size): + 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, request_serializers, response_deserializers, thread_pool, - thread_pool_size) + 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 index 640e4eb86b..b3a161087f 100644 --- a/src/python/grpcio/grpc/beta/beta.py +++ b/src/python/grpcio/grpc/beta/beta.py @@ -238,6 +238,7 @@ def generic_stub(channel, options=None): 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) @@ -260,7 +261,8 @@ def dynamic_stub(channel, service, cardinalities, options=None): 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.request_serializers, + cardinalities, effective_options.metadata_transformer, + effective_options.request_serializers, effective_options.response_deserializers, effective_options.thread_pool, effective_options.thread_pool_size) 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 9112c34190..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 @@ -94,7 +94,7 @@ class _Implementation(test_interfaces.Implementation): 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) 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 1401536503..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 @@ -87,7 +87,7 @@ class _Implementation(test_interfaces.Implementation): 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) 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 c114cef6a6..716323cc20 100644 --- a/src/python/grpcio_test/grpc_test/_links/_transmission_test.py +++ b/src/python/grpcio_test/grpc_test/_links/_transmission_test.py @@ -54,7 +54,7 @@ class TransmissionTest(test_cases.TransmissionTest, unittest.TestCase): 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() @@ -121,7 +121,7 @@ class RoundTripTest(unittest.TestCase): 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() @@ -166,7 +166,7 @@ class RoundTripTest(unittest.TestCase): 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() -- cgit v1.2.3 From 14d0a3c7968fb14a94fcaa1fe182e853ad361576 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Fri, 28 Aug 2015 18:41:10 -0700 Subject: Updates implementation of rb_server_credentials - allows use of multiple credentials, e.g, per servername --- src/ruby/ext/grpc/rb_server_credentials.c | 125 +++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c index 6af4c86c45..ea4d0d864e 100644 --- a/src/ruby/ext/grpc/rb_server_credentials.c +++ b/src/ruby/ext/grpc/rb_server_credentials.c @@ -135,63 +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: , + {cert_chain: }], + force_client_auth) + creds = ServerCredentials.new(pem_root_certs, + [{private_key: , + {cert_chain: }], + 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: ", + 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: ", + 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 , 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, NULL); + 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, NULL); + 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; @@ -211,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 */ -- cgit v1.2.3 From 73a540ae577b10e83b81d0cb60da816294a3a5bb Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Fri, 28 Aug 2015 18:56:17 -0700 Subject: Update sites using ServerCredentials.new --- src/ruby/bin/math_server.rb | 3 ++- src/ruby/bin/noproto_server.rb | 3 ++- src/ruby/pb/test/server.rb | 3 ++- src/ruby/spec/client_server_spec.rb | 15 ++++++------ src/ruby/spec/credentials_spec.rb | 14 ++++++------ src/ruby/spec/server_credentials_spec.rb | 39 ++++++++++++++++++++++++++------ src/ruby/spec/server_spec.rb | 3 ++- 7 files changed, 55 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb index b41ccf6ce1..5e2b7e701d 100755 --- a/src/ruby/bin/math_server.rb +++ b/src/ruby/bin/math_server.rb @@ -155,7 +155,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/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..9aacea906f 100644 --- a/src/ruby/spec/client_server_spec.rb +++ b/src/ruby/spec/client_server_spec.rb @@ -32,12 +32,6 @@ 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' } @@ -420,12 +414,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/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..c52fe0d9b6 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 -- cgit v1.2.3 From 934ae9ac0c1e9506e2a514dc0950a5a351d08ef9 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Mon, 31 Aug 2015 09:42:59 -0700 Subject: Make insecure construction explicit, to address #2614 --- src/ruby/ext/grpc/rb_server.c | 23 ++++++++++++++--------- src/ruby/spec/client_server_spec.rb | 2 +- src/ruby/spec/generic/active_call_spec.rb | 2 +- src/ruby/spec/generic/client_stub_spec.rb | 2 +- src/ruby/spec/generic/rpc_server_spec.rb | 2 +- src/ruby/spec/pb/health/checker_spec.rb | 2 +- src/ruby/spec/server_spec.rb | 9 ++++++--- 7 files changed, 25 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 7e76349d2e..8958237510 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 { @@ -334,7 +337,7 @@ static VALUE grpc_rb_server_destroy(int argc, VALUE *argv, VALUE self) { 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_not_secure) // secure port server_creds = ... @@ -342,21 +345,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 +402,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/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb index 9aacea906f..387f2baec2 100644 --- a/src/ruby/spec/client_server_spec.rb +++ b/src/ruby/spec/client_server_spec.rb @@ -396,7 +396,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 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..d7b7535cbe 100644 --- a/src/ruby/spec/pb/health/checker_spec.rb +++ b/src/ruby/spec/pb/health/checker_spec.rb @@ -186,7 +186,7 @@ describe Grpc::Health::Checker 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_spec.rb b/src/ruby/spec/server_spec.rb index c52fe0d9b6..439b19fb8d 100644 --- a/src/ruby/spec/server_spec.rb +++ b/src/ruby/spec/server_spec.rb @@ -105,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 @@ -114,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 @@ -199,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 -- cgit v1.2.3 From 643ebb6fb83f9734032e7d0291ad7df69be5ace1 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Mon, 31 Aug 2015 09:50:48 -0700 Subject: Fixes a comment --- src/ruby/ext/grpc/rb_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 8958237510..c43eed224b 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -337,7 +337,7 @@ static VALUE grpc_rb_server_destroy(int argc, VALUE *argv, VALUE self) { call-seq: // insecure port insecure_server = Server.new(cq, {'arg1': 'value1'}) - insecure_server.add_http2_port('mydomain:50051', :this_port_is_not_secure) + insecure_server.add_http2_port('mydomain:50051', :this_port_is_insecure) // secure port server_creds = ... -- cgit v1.2.3 From cd9ec0e96553f50af495d022f4db931e9318ec6c Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Mon, 31 Aug 2015 07:49:45 +0000 Subject: Code generation for Python Beta API --- src/compiler/python_generator.cc | 308 +++++++++++- src/compiler/python_generator.h | 3 +- src/compiler/python_plugin.cc | 3 +- .../grpc_protoc_plugin/alpha_python_plugin_test.py | 541 +++++++++++++++++++++ .../grpc_protoc_plugin/beta_python_plugin_test.py | 501 +++++++++++++++++++ 5 files changed, 1336 insertions(+), 20 deletions(-) create mode 100644 src/python/grpcio_test/grpc_protoc_plugin/alpha_python_plugin_test.py create mode 100644 src/python/grpcio_test/grpc_protoc_plugin/beta_python_plugin_test.py (limited to 'src') 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 = ""; map 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 = ""; map 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 = ""; map 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 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 = ""; + map 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 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 method_implementation_constructors; + map> + input_message_modules_and_classes; + map> + 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 input_message_module_and_class; + if (!GetModuleAndMessagePath(method->input_type(), + &input_message_module_and_class)) { + return false; + } + pair 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 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 method_cardinalities; + map> + input_message_modules_and_classes; + map> + 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 input_message_module_and_class; + if (!GetModuleAndMessagePath(method->input_type(), + &input_message_module_and_class)) { + return false; + } + pair 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 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/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) -- cgit v1.2.3 From c7b488d0d248abef8591853b1ae97b2329344597 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 31 Aug 2015 11:48:34 -0700 Subject: Remove redundant Node route guide examples --- src/node/examples/route_guide.proto | 120 ------- src/node/examples/route_guide_client.js | 240 ------------- src/node/examples/route_guide_db.json | 601 -------------------------------- src/node/examples/route_guide_server.js | 255 -------------- 4 files changed, 1216 deletions(-) delete mode 100644 src/node/examples/route_guide.proto delete mode 100644 src/node/examples/route_guide_client.js delete mode 100644 src/node/examples/route_guide_db.json delete mode 100644 src/node/examples/route_guide_server.js (limited to 'src') 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; -- cgit v1.2.3 From 7d3d485aa7dc5ed98f2152aceeb79674286aed15 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 31 Aug 2015 13:36:48 -0700 Subject: add roots.pem to Grpc C# nuget package --- src/csharp/Grpc.Core/Grpc.Core.nuspec | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') 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 @@ Release $version$ of gRPC C# Copyright 2015, Google Inc. gRPC RPC Protocol HTTP/2 - - - + + + + - - - + + + -- cgit v1.2.3 From e7fb1899f80eb6eb257f6dc8ddd27aa3398614f0 Mon Sep 17 00:00:00 2001 From: yang-g Date: Mon, 31 Aug 2015 14:13:25 -0700 Subject: fix internal objc test proto --- src/objective-c/generated_libraries/RouteGuideClient/route_guide.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') 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"; -- cgit v1.2.3 From 65ad41f53b1d230cfdcb33f9e111b9a1358a1bbb Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Mon, 31 Aug 2015 21:29:12 +0000 Subject: Fixes for bugs found during manual use (1) In _ingestion, it's the "details" attribute of a NoSuchMethodException that we want. The "message" is inherited from the base Exception class. (2) In _transmission, use a proper sum type for representing operation abortion. Trying to overload the existing _completion value for status-and-details-when-aborting was trying to be too clever. (3) In _calls... oof. Just look. Oof. Test coverage for this code path is added. (4) In _service, the application-provided face.MultiMethodImplementation isn't directly callable, but rather exposes a method named "service". (5) In crust.implementations, the wrapping that we've put around the application-provided face.MultiMethodImplementation *is* directly callable, and *does not* expose a method named "service". (6) Also in crust.implementations, base.NoSuchMethodError's constructor takes a code value and a details value. (7) Again in crust.implementations, the application-provided face.MultiMethodImplementation may be None, and if it is None, we shouldn't wrap it with an adaptation function that would only raise a TypeError at a later time. --- .../grpcio/grpc/framework/core/_ingestion.py | 2 +- .../grpcio/grpc/framework/core/_transmission.py | 101 +++++++++++++-------- src/python/grpcio/grpc/framework/crust/_calls.py | 2 +- src/python/grpcio/grpc/framework/crust/_service.py | 2 +- .../grpcio/grpc/framework/crust/implementations.py | 13 ++- .../face/_blocking_invocation_inline_service.py | 8 +- 6 files changed, 77 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/framework/core/_ingestion.py b/src/python/grpcio/grpc/framework/core/_ingestion.py index 7b8127f3fc..766d57f931 100644 --- a/src/python/grpcio/grpc/framework/core/_ingestion.py +++ b/src/python/grpcio/grpc/framework/core/_ingestion.py @@ -114,7 +114,7 @@ class _ServiceSubscriptionCreator(_SubscriptionCreator): group, method, self._operation_context, self._output_operator) except base.NoSuchMethodError as e: return _SubscriptionCreation( - _SubscriptionCreation.Kind.REMOTE_ERROR, None, e.code, e.message) + _SubscriptionCreation.Kind.REMOTE_ERROR, None, e.code, e.details) except abandonment.Abandoned: return _SubscriptionCreation( _SubscriptionCreation.Kind.ABANDONED, None, None, None) diff --git a/src/python/grpcio/grpc/framework/core/_transmission.py b/src/python/grpcio/grpc/framework/core/_transmission.py index efef87dd4c..202a71dd71 100644 --- a/src/python/grpcio/grpc/framework/core/_transmission.py +++ b/src/python/grpcio/grpc/framework/core/_transmission.py @@ -29,6 +29,9 @@ """State and behavior for ticket transmission during an operation.""" +import collections +import enum + from grpc.framework.core import _constants from grpc.framework.core import _interfaces from grpc.framework.foundation import callable_util @@ -47,6 +50,31 @@ def _explode_completion(completion): links.Ticket.Termination.COMPLETION) +class _Abort( + collections.namedtuple( + '_Abort', ('kind', 'termination', 'code', 'details',))): + """Tracks whether the operation aborted and what is to be done about it. + + Attributes: + kind: A Kind value describing the overall kind of the _Abort. + termination: A links.Ticket.Termination value to be sent to the other side + of the operation. Only valid if kind is Kind.ABORTED_NOTIFY_NEEDED. + code: A code value to be sent to the other side of the operation. Only + valid if kind is Kind.ABORTED_NOTIFY_NEEDED. + details: A details value to be sent to the other side of the operation. + Only valid if kind is Kind.ABORTED_NOTIFY_NEEDED. + """ + + @enum.unique + class Kind(enum.Enum): + NOT_ABORTED = 'not aborted' + ABORTED_NOTIFY_NEEDED = 'aborted notify needed' + ABORTED_NO_NOTIFY = 'aborted no notify' + +_NOT_ABORTED = _Abort(_Abort.Kind.NOT_ABORTED, None, None, None) +_ABORTED_NO_NOTIFY = _Abort(_Abort.Kind.ABORTED_NO_NOTIFY, None, None, None) + + class TransmissionManager(_interfaces.TransmissionManager): """An _interfaces.TransmissionManager that sends links.Tickets.""" @@ -79,8 +107,7 @@ class TransmissionManager(_interfaces.TransmissionManager): self._initial_metadata = None self._payloads = [] self._completion = None - self._aborted = False - self._abortion_outcome = None + self._abort = _NOT_ABORTED self._transmitting = False def set_expiration_manager(self, expiration_manager): @@ -94,24 +121,15 @@ class TransmissionManager(_interfaces.TransmissionManager): A links.Ticket to be sent to the other side of the operation or None if there is nothing to be sent at this time. """ - if self._aborted: - if self._abortion_outcome is None: - return None - else: - termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION[ - self._abortion_outcome] - if termination is None: - return None - else: - self._abortion_outcome = None - if self._completion is None: - code, message = None, None - else: - code, message = self._completion.code, self._completion.message - return links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, - None, None, None, None, None, None, None, code, message, - termination, None) + if self._abort.kind is _Abort.Kind.ABORTED_NO_NOTIFY: + return None + elif self._abort.kind is _Abort.Kind.ABORTED_NOTIFY_NEEDED: + termination = self._abort.termination + code, details = self._abort.code, self._abort.details + self._abort = _ABORTED_NO_NOTIFY + return links.Ticket( + self._operation_id, self._lowest_unused_sequence_number, None, None, + None, None, None, None, None, None, code, details, termination, None) action = False # TODO(nathaniel): Support other subscriptions. @@ -174,6 +192,7 @@ class TransmissionManager(_interfaces.TransmissionManager): return else: with self._lock: + self._abort = _ABORTED_NO_NOTIFY if self._termination_manager.outcome is None: self._termination_manager.abort(base.Outcome.TRANSMISSION_FAILURE) self._expiration_manager.terminate() @@ -201,6 +220,9 @@ class TransmissionManager(_interfaces.TransmissionManager): def advance(self, initial_metadata, payload, completion, allowance): """See _interfaces.TransmissionManager.advance for specification.""" + if self._abort.kind is not _Abort.Kind.NOT_ABORTED: + return + effective_initial_metadata = initial_metadata effective_payload = payload effective_completion = completion @@ -246,7 +268,9 @@ class TransmissionManager(_interfaces.TransmissionManager): def timeout(self, timeout): """See _interfaces.TransmissionManager.timeout for specification.""" - if self._transmitting: + if self._abort.kind is not _Abort.Kind.NOT_ABORTED: + return + elif self._transmitting: self._timeout = timeout else: ticket = links.Ticket( @@ -257,7 +281,9 @@ class TransmissionManager(_interfaces.TransmissionManager): def allowance(self, allowance): """See _interfaces.TransmissionManager.allowance for specification.""" - if self._transmitting or not self._payloads: + if self._abort.kind is not _Abort.Kind.NOT_ABORTED: + return + elif self._transmitting or not self._payloads: self._remote_allowance += allowance else: self._remote_allowance += allowance - 1 @@ -283,20 +309,17 @@ class TransmissionManager(_interfaces.TransmissionManager): def abort(self, outcome, code, message): """See _interfaces.TransmissionManager.abort for specification.""" - if self._transmitting: - self._aborted, self._abortion_outcome = True, outcome - else: - self._aborted = True - if outcome is not None: - termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION[ - outcome] - if termination is not None: - if self._completion is None: - code, message = None, None - else: - code, message = self._completion.code, self._completion.message - ticket = links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, - None, None, None, None, None, None, None, code, message, - termination, None) - self._transmit(ticket) + if self._abort.kind is _Abort.Kind.NOT_ABORTED: + termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION.get( + outcome) + if termination is None: + self._abort = _ABORTED_NO_NOTIFY + elif self._transmitting: + self._abort = _Abort( + _Abort.Kind.ABORTED_NOTIFY_NEEDED, termination, code, message) + else: + ticket = links.Ticket( + self._operation_id, self._lowest_unused_sequence_number, None, + None, None, None, None, None, None, None, code, message, + termination, None) + self._transmit(ticket) diff --git a/src/python/grpcio/grpc/framework/crust/_calls.py b/src/python/grpcio/grpc/framework/crust/_calls.py index f9077bedfe..4c6bf16f43 100644 --- a/src/python/grpcio/grpc/framework/crust/_calls.py +++ b/src/python/grpcio/grpc/framework/crust/_calls.py @@ -98,7 +98,7 @@ def blocking_unary_unary( rendezvous, unused_operation_context, unused_outcome = _invoke( end, group, method, timeout, initial_metadata, payload, True) if with_call: - return next(rendezvous, rendezvous) + return next(rendezvous), rendezvous else: return next(rendezvous) diff --git a/src/python/grpcio/grpc/framework/crust/_service.py b/src/python/grpcio/grpc/framework/crust/_service.py index 2455a58f59..6ff7249e75 100644 --- a/src/python/grpcio/grpc/framework/crust/_service.py +++ b/src/python/grpcio/grpc/framework/crust/_service.py @@ -154,7 +154,7 @@ def adapt_multi_method(multi_method, pool): outcome = operation_context.add_termination_callback(rendezvous.set_outcome) if outcome is None: def in_pool(): - request_consumer = multi_method( + request_consumer = multi_method.service( group, method, rendezvous, _ServicerContext(rendezvous)) for request in rendezvous: request_consumer.consume(request) diff --git a/src/python/grpcio/grpc/framework/crust/implementations.py b/src/python/grpcio/grpc/framework/crust/implementations.py index 12f7e79641..d38fab8ba0 100644 --- a/src/python/grpcio/grpc/framework/crust/implementations.py +++ b/src/python/grpcio/grpc/framework/crust/implementations.py @@ -49,12 +49,12 @@ class _BaseServicer(base.Servicer): return adapted_method(output_operator, context) elif self._adapted_multi_method is not None: try: - return self._adapted_multi_method.service( + return self._adapted_multi_method( group, method, output_operator, context) except face.NoSuchMethodError: - raise base.NoSuchMethodError() + raise base.NoSuchMethodError(None, None) else: - raise base.NoSuchMethodError() + raise base.NoSuchMethodError(None, None) class _UnaryUnaryMultiCallable(face.UnaryUnaryMultiCallable): @@ -315,8 +315,11 @@ def servicer(method_implementations, multi_method_implementation, pool): """ adapted_implementations = _adapt_method_implementations( method_implementations, pool) - adapted_multi_method_implementation = _service.adapt_multi_method( - multi_method_implementation, pool) + if multi_method_implementation is None: + adapted_multi_method_implementation = None + else: + adapted_multi_method_implementation = _service.adapt_multi_method( + multi_method_implementation, pool) return _BaseServicer( adapted_implementations, adapted_multi_method_implementation) 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 b7dd5d4d17..2d2a081955 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 @@ -82,8 +82,8 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): for test_messages in test_messages_sequence: request = test_messages.request() - response = self._invoker.blocking(group, method)( - request, test_constants.LONG_TIMEOUT) + response, call = self._invoker.blocking(group, method)( + request, test_constants.LONG_TIMEOUT, with_call=True) test_messages.verify(request, response, self) @@ -105,8 +105,8 @@ class TestCase(test_coverage.Coverage, unittest.TestCase): for test_messages in test_messages_sequence: requests = test_messages.requests() - response = self._invoker.blocking(group, method)( - iter(requests), test_constants.LONG_TIMEOUT) + response, call = self._invoker.blocking(group, method)( + iter(requests), test_constants.LONG_TIMEOUT, with_call=True) test_messages.verify(requests, response, self) -- cgit v1.2.3 From 391664afa1e7fc79b7817658699fc7886f70adbb Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Mon, 31 Aug 2015 15:38:43 -0700 Subject: Improves test stability --- src/ruby/.rspec | 1 + src/ruby/lib/grpc/generic/rpc_server.rb | 12 ++++++------ src/ruby/spec/client_server_spec.rb | 3 +-- src/ruby/spec/pb/health/checker_spec.rb | 1 - 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') 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/lib/grpc/generic/rpc_server.rb b/src/ruby/lib/grpc/generic/rpc_server.rb index 38ea333413..3740ac52da 100644 --- a/src/ruby/lib/grpc/generic/rpc_server.rb +++ b/src/ruby/lib/grpc/generic/rpc_server.rb @@ -417,18 +417,18 @@ module GRPC begin 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, 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}") diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb index 2e673ff413..bfd3d4188b 100644 --- a/src/ruby/spec/client_server_spec.rb +++ b/src/ruby/spec/client_server_spec.rb @@ -28,7 +28,6 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. require 'grpc' -require 'spec_helper' include GRPC::Core @@ -47,7 +46,7 @@ shared_context 'setup: tags' do end def deadline - Time.now + 2 + Time.now + 5 end def server_allows_client_to_proceed diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb index 6999a69105..e743ff496d 100644 --- a/src/ruby/spec/pb/health/checker_spec.rb +++ b/src/ruby/spec/pb/health/checker_spec.rb @@ -179,7 +179,6 @@ 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 -- cgit v1.2.3 From bab6706f4118dbff14c55f08fd0b5c59759cc8b8 Mon Sep 17 00:00:00 2001 From: Tim Emiola Date: Mon, 31 Aug 2015 15:51:53 -0700 Subject: Bumps the ruby version to beta --- src/ruby/grpc.gemspec | 2 +- src/ruby/lib/grpc/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') 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/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 -- cgit v1.2.3 From b6c6efdd005c231af0cb31a8db38877e6f494d2b Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Mon, 31 Aug 2015 15:56:15 -0700 Subject: Update Node verison to 0.11 and status to 'Beta' --- src/node/README.md | 2 +- src/node/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/node/README.md b/src/node/README.md index c96bc96642..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. 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/", -- cgit v1.2.3 From 3fecb24c555f45bac9110cd4a5947de91f11a78b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 31 Aug 2015 16:38:58 -0700 Subject: Add a little experiment --- src/core/surface/call.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/surface/call.c b/src/core/surface/call.c index f25ef74a92..a8b4d65fbc 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -641,7 +641,9 @@ static void unlock(grpc_call *call) { op.max_recv_bytes = MAX_RECV_PEEK_AHEAD - buffered_bytes; } } - if (op.max_recv_bytes != 0) { + /* TODO(ctiller): 1024 is basically to cover a bug + I don't understand yet */ + if (op.max_recv_bytes > 1024) { op.recv_ops = &call->recv_ops; op.recv_state = &call->recv_state; op.on_done_recv = &call->on_done_recv; -- cgit v1.2.3 From 61cfa57f5a1737ec7966733ec6932e1b29c33c42 Mon Sep 17 00:00:00 2001 From: yang-g Date: Mon, 31 Aug 2015 16:41:29 -0700 Subject: change test too --- src/objective-c/tests/LocalClearTextTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/objective-c/tests/LocalClearTextTests.m b/src/objective-c/tests/LocalClearTextTests.m index d01fe91afa..976fff55bc 100644 --- a/src/objective-c/tests/LocalClearTextTests.m +++ b/src/objective-c/tests/LocalClearTextTests.m @@ -47,7 +47,7 @@ // 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 -- cgit v1.2.3 From 1c09accaad6668b68ae47a7f9638bc4b79429caa Mon Sep 17 00:00:00 2001 From: Alistair Veitch Date: Mon, 31 Aug 2015 16:57:32 -0700 Subject: change aggregation_ops to internal type --- BUILD | 3 + build.json | 1 + gRPC.podspec | 2 + include/grpc/census.h | 32 ++--------- src/core/census/aggregation.h | 66 ++++++++++++++++++++++ tools/doxygen/Doxyfile.core.internal | 1 + tools/run_tests/sources_and_headers.json | 4 ++ vsprojects/grpc/grpc.vcxproj | 1 + vsprojects/grpc/grpc.vcxproj.filters | 3 + vsprojects/grpc_unsecure/grpc_unsecure.vcxproj | 1 + .../grpc_unsecure/grpc_unsecure.vcxproj.filters | 3 + 11 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 src/core/census/aggregation.h (limited to 'src') diff --git a/BUILD b/BUILD index d09a56f4ef..864d735e91 100644 --- a/BUILD +++ b/BUILD @@ -245,6 +245,7 @@ cc_library( "src/core/transport/stream_op.h", "src/core/transport/transport.h", "src/core/transport/transport_impl.h", + "src/core/census/aggregation.h", "src/core/census/context.h", "src/core/census/rpc_metric_id.h", "src/core/httpcli/httpcli_security_connector.c", @@ -514,6 +515,7 @@ cc_library( "src/core/transport/stream_op.h", "src/core/transport/transport.h", "src/core/transport/transport_impl.h", + "src/core/census/aggregation.h", "src/core/census/context.h", "src/core/census/rpc_metric_id.h", "src/core/surface/init_unsecure.c", @@ -1271,6 +1273,7 @@ objc_library( "src/core/transport/stream_op.h", "src/core/transport/transport.h", "src/core/transport/transport_impl.h", + "src/core/census/aggregation.h", "src/core/census/context.h", "src/core/census/rpc_metric_id.h", ], diff --git a/build.json b/build.json index d62a7f34b8..644253afc8 100644 --- a/build.json +++ b/build.json @@ -18,6 +18,7 @@ "include/grpc/census.h" ], "headers": [ + "src/core/census/aggregation.h", "src/core/census/context.h", "src/core/census/rpc_metric_id.h" ], diff --git a/gRPC.podspec b/gRPC.podspec index ff191c5073..d0e1e2d848 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -247,6 +247,7 @@ Pod::Spec.new do |s| 'src/core/transport/stream_op.h', 'src/core/transport/transport.h', 'src/core/transport/transport_impl.h', + 'src/core/census/aggregation.h', 'src/core/census/context.h', 'src/core/census/rpc_metric_id.h', 'grpc/grpc_security.h', @@ -520,6 +521,7 @@ Pod::Spec.new do |s| 'src/core/transport/stream_op.h', 'src/core/transport/transport.h', 'src/core/transport/transport_impl.h', + 'src/core/census/aggregation.h', 'src/core/census/context.h', 'src/core/census/rpc_metric_id.h' diff --git a/include/grpc/census.h b/include/grpc/census.h index 9c0291bf96..2f36665d46 100644 --- a/include/grpc/census.h +++ b/include/grpc/census.h @@ -411,34 +411,10 @@ typedef struct { void census_record_values(census_context *context, census_value *values, size_t nvalues); -/** Structure used to describe an aggregation type. */ -typedef struct { - /* 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); -} census_aggregation_ops; - -/* Predefined aggregation types. */ +/** Type representing a particular aggregation */ +typedef struct census_aggregation_ops census_aggregation_ops; + +/* Predefined aggregation types, for use with census_view_create(). */ extern census_aggregation_ops census_agg_sum; extern census_aggregation_ops census_agg_distribution; extern census_aggregation_ops census_agg_histogram; 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 + +#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/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 26846011ae..729f8bf2ff 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -881,6 +881,7 @@ src/core/transport/metadata.h \ src/core/transport/stream_op.h \ src/core/transport/transport.h \ src/core/transport/transport_impl.h \ +src/core/census/aggregation.h \ src/core/census/context.h \ src/core/census/rpc_metric_id.h \ src/core/httpcli/httpcli_security_connector.c \ diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json index 40a9fa4075..36f8dc6f27 100644 --- a/tools/run_tests/sources_and_headers.json +++ b/tools/run_tests/sources_and_headers.json @@ -12229,6 +12229,7 @@ "include/grpc/grpc.h", "include/grpc/grpc_security.h", "include/grpc/status.h", + "src/core/census/aggregation.h", "src/core/census/context.h", "src/core/census/grpc_filter.h", "src/core/census/rpc_metric_id.h", @@ -12356,6 +12357,7 @@ "include/grpc/grpc.h", "include/grpc/grpc_security.h", "include/grpc/status.h", + "src/core/census/aggregation.h", "src/core/census/context.c", "src/core/census/context.h", "src/core/census/grpc_context.c", @@ -12707,6 +12709,7 @@ "include/grpc/compression.h", "include/grpc/grpc.h", "include/grpc/status.h", + "src/core/census/aggregation.h", "src/core/census/context.h", "src/core/census/grpc_filter.h", "src/core/census/rpc_metric_id.h", @@ -12820,6 +12823,7 @@ "include/grpc/compression.h", "include/grpc/grpc.h", "include/grpc/status.h", + "src/core/census/aggregation.h", "src/core/census/context.c", "src/core/census/context.h", "src/core/census/grpc_context.c", diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj index 68be5277f0..6857f7c9a2 100644 --- a/vsprojects/grpc/grpc.vcxproj +++ b/vsprojects/grpc/grpc.vcxproj @@ -343,6 +343,7 @@ + diff --git a/vsprojects/grpc/grpc.vcxproj.filters b/vsprojects/grpc/grpc.vcxproj.filters index c6d88b827a..dc35c0535f 100644 --- a/vsprojects/grpc/grpc.vcxproj.filters +++ b/vsprojects/grpc/grpc.vcxproj.filters @@ -791,6 +791,9 @@ src\core\transport + + src\core\census + src\core\census diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj index 5aeaf89ac5..bec4ebf692 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj @@ -326,6 +326,7 @@ + diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters index ff8f3e18fa..63d69222e8 100644 --- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters +++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters @@ -689,6 +689,9 @@ src\core\transport + + src\core\census + src\core\census -- cgit v1.2.3 From 40205944f7a36cdcc3d48a9e3bf4ddcccd3f0b8f Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Mon, 31 Aug 2015 15:54:59 -0700 Subject: Minimal Swift sample app template --- .../examples/SwiftSample/AppDelegate.swift | 39 +++ .../SwiftSample/Base.lproj/Main.storyboard | 25 ++ .../AppIcon.appiconset/Contents.json | 68 +++++ src/objective-c/examples/SwiftSample/Info.plist | 47 ++++ .../SwiftSample.xcodeproj/project.pbxproj | 286 +++++++++++++++++++++ .../project.xcworkspace/contents.xcworkspacedata | 7 + .../examples/SwiftSample/ViewController.swift | 43 ++++ 7 files changed, 515 insertions(+) create mode 100644 src/objective-c/examples/SwiftSample/AppDelegate.swift create mode 100644 src/objective-c/examples/SwiftSample/Base.lproj/Main.storyboard create mode 100644 src/objective-c/examples/SwiftSample/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 src/objective-c/examples/SwiftSample/Info.plist create mode 100644 src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj create mode 100644 src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 src/objective-c/examples/SwiftSample/ViewController.swift (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/AppDelegate.swift b/src/objective-c/examples/SwiftSample/AppDelegate.swift new file mode 100644 index 0000000000..88027d997b --- /dev/null +++ b/src/objective-c/examples/SwiftSample/AppDelegate.swift @@ -0,0 +1,39 @@ +/* + * + * 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 UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? +} diff --git a/src/objective-c/examples/SwiftSample/Base.lproj/Main.storyboard b/src/objective-c/examples/SwiftSample/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..3a2a49bad8 --- /dev/null +++ b/src/objective-c/examples/SwiftSample/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/objective-c/examples/SwiftSample/Images.xcassets/AppIcon.appiconset/Contents.json b/src/objective-c/examples/SwiftSample/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..36d2c80d88 --- /dev/null +++ b/src/objective-c/examples/SwiftSample/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/src/objective-c/examples/SwiftSample/Info.plist b/src/objective-c/examples/SwiftSample/Info.plist new file mode 100644 index 0000000000..10f0450b34 --- /dev/null +++ b/src/objective-c/examples/SwiftSample/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + io.grpc.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + Main + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..fcfa890241 --- /dev/null +++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj @@ -0,0 +1,286 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC71B950B210007E424 /* AppDelegate.swift */; }; + 633BFFCA1B950B210007E424 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC91B950B210007E424 /* ViewController.swift */; }; + 633BFFCD1B950B210007E424 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCB1B950B210007E424 /* Main.storyboard */; }; + 633BFFCF1B950B210007E424 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCE1B950B210007E424 /* Images.xcassets */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 633BFFC21B950B210007E424 /* SwiftSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 633BFFC61B950B210007E424 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 633BFFC71B950B210007E424 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 633BFFC91B950B210007E424 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 633BFFCC1B950B210007E424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 633BFFCE1B950B210007E424 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 633BFFBF1B950B210007E424 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 633BFFB91B950B210007E424 = { + isa = PBXGroup; + children = ( + 633BFFC41B950B210007E424 /* SwiftSample */, + 633BFFC31B950B210007E424 /* Products */, + ); + sourceTree = ""; + }; + 633BFFC31B950B210007E424 /* Products */ = { + isa = PBXGroup; + children = ( + 633BFFC21B950B210007E424 /* SwiftSample.app */, + ); + name = Products; + sourceTree = ""; + }; + 633BFFC41B950B210007E424 /* SwiftSample */ = { + isa = PBXGroup; + children = ( + 633BFFC71B950B210007E424 /* AppDelegate.swift */, + 633BFFC91B950B210007E424 /* ViewController.swift */, + 633BFFCB1B950B210007E424 /* Main.storyboard */, + 633BFFCE1B950B210007E424 /* Images.xcassets */, + 633BFFC51B950B210007E424 /* Supporting Files */, + ); + name = SwiftSample; + sourceTree = SOURCE_ROOT; + }; + 633BFFC51B950B210007E424 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 633BFFC61B950B210007E424 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 633BFFC11B950B210007E424 /* SwiftSample */ = { + isa = PBXNativeTarget; + buildConfigurationList = 633BFFE11B950B210007E424 /* Build configuration list for PBXNativeTarget "SwiftSample" */; + buildPhases = ( + 633BFFBE1B950B210007E424 /* Sources */, + 633BFFBF1B950B210007E424 /* Frameworks */, + 633BFFC01B950B210007E424 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SwiftSample; + productName = SwiftSample; + productReference = 633BFFC21B950B210007E424 /* SwiftSample.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 633BFFBA1B950B210007E424 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0640; + ORGANIZATIONNAME = gRPC; + TargetAttributes = { + 633BFFC11B950B210007E424 = { + CreatedOnToolsVersion = 6.4; + }; + }; + }; + buildConfigurationList = 633BFFBD1B950B210007E424 /* Build configuration list for PBXProject "SwiftSample" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 633BFFB91B950B210007E424; + productRefGroup = 633BFFC31B950B210007E424 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 633BFFC11B950B210007E424 /* SwiftSample */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 633BFFC01B950B210007E424 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 633BFFCD1B950B210007E424 /* Main.storyboard in Resources */, + 633BFFCF1B950B210007E424 /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 633BFFBE1B950B210007E424 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 633BFFCA1B950B210007E424 /* ViewController.swift in Sources */, + 633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 633BFFCB1B950B210007E424 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 633BFFCC1B950B210007E424 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 633BFFDF1B950B210007E424 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.4; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 633BFFE01B950B210007E424 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.4; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 633BFFE21B950B210007E424 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 633BFFE31B950B210007E424 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 633BFFBD1B950B210007E424 /* Build configuration list for PBXProject "SwiftSample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 633BFFDF1B950B210007E424 /* Debug */, + 633BFFE01B950B210007E424 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 633BFFE11B950B210007E424 /* Build configuration list for PBXNativeTarget "SwiftSample" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 633BFFE21B950B210007E424 /* Debug */, + 633BFFE31B950B210007E424 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 633BFFBA1B950B210007E424 /* Project object */; +} diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..3b0f1c15b2 --- /dev/null +++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift new file mode 100644 index 0000000000..73dd953167 --- /dev/null +++ b/src/objective-c/examples/SwiftSample/ViewController.swift @@ -0,0 +1,43 @@ +/* + * + * 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 UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + } +} + -- cgit v1.2.3 From 5e5733b36c89ec0e90c0f672c4be2cfce4b7019e Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Mon, 31 Aug 2015 15:58:16 -0700 Subject: Test Podfile --- src/objective-c/examples/SwiftSample/Podfile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/objective-c/examples/SwiftSample/Podfile (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/Podfile b/src/objective-c/examples/SwiftSample/Podfile new file mode 100644 index 0000000000..0caa8cae8b --- /dev/null +++ b/src/objective-c/examples/SwiftSample/Podfile @@ -0,0 +1,8 @@ +source 'https://github.com/CocoaPods/Specs.git' +platform :ios, '8.0' + +pod 'gRPC', :path => "../../../.." +# pod 'RemoteTest', :path => "../../generated_libraries/RemoteTestClient" + +target 'SwiftSample' do +end -- cgit v1.2.3 From fd09d84f66f2f2bc4a377a0e51285fdf42e55d5b Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Mon, 31 Aug 2015 15:58:48 -0700 Subject: Install pods in project --- .../SwiftSample.xcodeproj/project.pbxproj | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj index fcfa890241..4f176b2923 100644 --- a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 253D3A297105CA46DA960A11 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DC58ACA18DCCB1553531B885 /* libPods.a */; }; 633BFFC81B950B210007E424 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC71B950B210007E424 /* AppDelegate.swift */; }; 633BFFCA1B950B210007E424 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 633BFFC91B950B210007E424 /* ViewController.swift */; }; 633BFFCD1B950B210007E424 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 633BFFCB1B950B210007E424 /* Main.storyboard */; }; @@ -14,12 +15,15 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 12C7B447AA80E624D93B5C54 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 633BFFC21B950B210007E424 /* SwiftSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 633BFFC61B950B210007E424 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 633BFFC71B950B210007E424 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 633BFFC91B950B210007E424 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 633BFFCC1B950B210007E424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 633BFFCE1B950B210007E424 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + C335CBC4C160E0D9EDEE646B /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; + DC58ACA18DCCB1553531B885 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -27,17 +31,29 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 253D3A297105CA46DA960A11 /* libPods.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 31F283C976AE97586C17CCD9 /* Pods */ = { + isa = PBXGroup; + children = ( + 12C7B447AA80E624D93B5C54 /* Pods.debug.xcconfig */, + C335CBC4C160E0D9EDEE646B /* Pods.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; 633BFFB91B950B210007E424 = { isa = PBXGroup; children = ( 633BFFC41B950B210007E424 /* SwiftSample */, 633BFFC31B950B210007E424 /* Products */, + 31F283C976AE97586C17CCD9 /* Pods */, + 9D63A7F6423989BA306810CA /* Frameworks */, ); sourceTree = ""; }; @@ -69,6 +85,14 @@ name = "Supporting Files"; sourceTree = ""; }; + 9D63A7F6423989BA306810CA /* Frameworks */ = { + isa = PBXGroup; + children = ( + DC58ACA18DCCB1553531B885 /* libPods.a */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -76,9 +100,11 @@ isa = PBXNativeTarget; buildConfigurationList = 633BFFE11B950B210007E424 /* Build configuration list for PBXNativeTarget "SwiftSample" */; buildPhases = ( + 6BEEB33CA2705D7D2F2210E6 /* Check Pods Manifest.lock */, 633BFFBE1B950B210007E424 /* Sources */, 633BFFBF1B950B210007E424 /* Frameworks */, 633BFFC01B950B210007E424 /* Resources */, + AC2F6F9AB1C090BB0BEE6E4D /* Copy Pods Resources */, ); buildRules = ( ); @@ -133,6 +159,39 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 6BEEB33CA2705D7D2F2210E6 /* Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Check Pods Manifest.lock"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + showEnvVarsInLog = 0; + }; + AC2F6F9AB1C090BB0BEE6E4D /* Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Pods Resources"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 633BFFBE1B950B210007E424 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -242,6 +301,7 @@ }; 633BFFE21B950B210007E424 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 12C7B447AA80E624D93B5C54 /* Pods.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; @@ -252,6 +312,7 @@ }; 633BFFE31B950B210007E424 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = C335CBC4C160E0D9EDEE646B /* Pods.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Info.plist; @@ -279,6 +340,7 @@ 633BFFE31B950B210007E424 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; -- cgit v1.2.3 From 587c2550dd83b92ef454f4f7f5f3ad44f9934e7d Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Mon, 31 Aug 2015 16:17:15 -0700 Subject: Add empty bridging header --- .../examples/SwiftSample/Bridging-Header.h | 38 ++++++++++++++++++++++ .../SwiftSample.xcodeproj/project.pbxproj | 6 ++++ 2 files changed, 44 insertions(+) create mode 100644 src/objective-c/examples/SwiftSample/Bridging-Header.h (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/Bridging-Header.h b/src/objective-c/examples/SwiftSample/Bridging-Header.h new file mode 100644 index 0000000000..a85f7f7a5a --- /dev/null +++ b/src/objective-c/examples/SwiftSample/Bridging-Header.h @@ -0,0 +1,38 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef SwiftSample_Bridging_Header_h +#define SwiftSample_Bridging_Header_h + + +#endif diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj index 4f176b2923..cfccdd453f 100644 --- a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj +++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 633BFFC91B950B210007E424 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 633BFFCC1B950B210007E424 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 633BFFCE1B950B210007E424 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 6367AD231B951655007FD3A4 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; C335CBC4C160E0D9EDEE646B /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; DC58ACA18DCCB1553531B885 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -73,6 +74,7 @@ 633BFFCB1B950B210007E424 /* Main.storyboard */, 633BFFCE1B950B210007E424 /* Images.xcassets */, 633BFFC51B950B210007E424 /* Supporting Files */, + 6367AD231B951655007FD3A4 /* Bridging-Header.h */, ); name = SwiftSample; sourceTree = SOURCE_ROOT; @@ -307,6 +309,8 @@ INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h"; + USER_HEADER_SEARCH_PATHS = "Pods/**"; }; name = Debug; }; @@ -318,6 +322,8 @@ INFOPLIST_FILE = Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h"; + USER_HEADER_SEARCH_PATHS = "Pods/**"; }; name = Release; }; -- cgit v1.2.3 From 875d1d15c85358c735d449c347d1e6b3c015e594 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Mon, 31 Aug 2015 18:05:56 -0700 Subject: Add Swift example with non-generated code :D --- .../examples/SwiftSample/Bridging-Header.h | 5 +++++ .../examples/SwiftSample/ViewController.swift | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/Bridging-Header.h b/src/objective-c/examples/SwiftSample/Bridging-Header.h index a85f7f7a5a..3b2ae74d8b 100644 --- a/src/objective-c/examples/SwiftSample/Bridging-Header.h +++ b/src/objective-c/examples/SwiftSample/Bridging-Header.h @@ -34,5 +34,10 @@ #ifndef SwiftSample_Bridging_Header_h #define SwiftSample_Bridging_Header_h +#import +#import +#import +#import +#import #endif diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift index 73dd953167..dedcce20e7 100644 --- a/src/objective-c/examples/SwiftSample/ViewController.swift +++ b/src/objective-c/examples/SwiftSample/ViewController.swift @@ -37,7 +37,25 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. + + let RemoteHost = "grpc-test.sandbox.google.com" + + // Same example call using the generic gRPC client library: + + let method = ProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall") + + let requestsWriter = GRXWriter(value: NSData()) + + let call = GRPCCall(host: RemoteHost, path: method.HTTPPath, requestsWriter: requestsWriter) + + let responsesWriteable = GRXWriteable { (value: AnyObject?, error: NSError?) in + if let value = value as? NSData { + NSLog("Received response:\n\(value)") + } else { + NSLog("Finished with error: \(error!)") + } + } + + call.startWithWriteable(responsesWriteable) } } - -- cgit v1.2.3 From 0bf6b20876e14769abf4f2c871abe25d3fa8b3f7 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Mon, 31 Aug 2015 18:17:46 -0700 Subject: Create RemoteTest proto client that doesn’t depend on the tests framework MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../examples/RemoteTestClient/RemoteTest.podspec | 28 +++++ .../examples/RemoteTestClient/empty.proto | 44 +++++++ .../examples/RemoteTestClient/messages.proto | 133 +++++++++++++++++++++ .../examples/RemoteTestClient/test.proto | 73 +++++++++++ 4 files changed, 278 insertions(+) create mode 100644 src/objective-c/examples/RemoteTestClient/RemoteTest.podspec create mode 100644 src/objective-c/examples/RemoteTestClient/empty.proto create mode 100644 src/objective-c/examples/RemoteTestClient/messages.proto create mode 100644 src/objective-c/examples/RemoteTestClient/test.proto (limited to 'src') diff --git a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec new file mode 100644 index 0000000000..dcb0c4e500 --- /dev/null +++ b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec @@ -0,0 +1,28 @@ +Pod::Spec.new do |s| + s.name = "RemoteTest" + s.version = "0.0.1" + s.license = "New BSD" + + s.ios.deployment_target = "6.0" + s.osx.deployment_target = "10.8" + + # Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients. + s.prepare_command = <<-CMD + protoc --objc_out=. --objcgrpc_out=. *.proto + CMD + + s.subspec "Messages" do |ms| + ms.source_files = "*.pbobjc.{h,m}" + ms.header_mappings_dir = "." + ms.requires_arc = false + ms.dependency "Protobuf", "~> 3.0.0-alpha-3" + end + + s.subspec "Services" do |ss| + ss.source_files = "*.pbrpc.{h,m}" + ss.header_mappings_dir = "." + ss.requires_arc = true + ss.dependency "gRPC", "~> 0.5" + ss.dependency "#{s.name}/Messages" + end +end diff --git a/src/objective-c/examples/RemoteTestClient/empty.proto b/src/objective-c/examples/RemoteTestClient/empty.proto new file mode 100644 index 0000000000..a678048289 --- /dev/null +++ b/src/objective-c/examples/RemoteTestClient/empty.proto @@ -0,0 +1,44 @@ +// 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"; + +package grpc.testing; + +option objc_class_prefix = "RMT"; + +// An empty message that you can re-use to avoid defining duplicated empty +// messages in your project. A typical example is to use it as argument or the +// return value of a service API. For instance: +// +// service Foo { +// rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { }; +// }; +// +message Empty {} diff --git a/src/objective-c/examples/RemoteTestClient/messages.proto b/src/objective-c/examples/RemoteTestClient/messages.proto new file mode 100644 index 0000000000..85d93c2ff9 --- /dev/null +++ b/src/objective-c/examples/RemoteTestClient/messages.proto @@ -0,0 +1,133 @@ +// 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. + +// Message definitions to be used by integration test service definitions. + +syntax = "proto3"; + +package grpc.testing; + +option objc_class_prefix = "RMT"; + +// The type of payload that should be returned. +enum PayloadType { + // Compressable text format. + COMPRESSABLE = 0; + + // Uncompressable binary format. + UNCOMPRESSABLE = 1; + + // Randomly chosen from all other formats defined in this enum. + RANDOM = 2; +} + +// A block of data, to simply increase gRPC message size. +message Payload { + // The type of data in body. + PayloadType type = 1; + // Primary contents of payload. + 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. + PayloadType response_type = 1; + + // Desired payload size in the response from the server. + // If response_type is COMPRESSABLE, this denotes the size before compression. + int32 response_size = 2; + + // Optional input payload sent along with the request. + Payload payload = 3; + + // Whether SimpleResponse should include username. + bool fill_username = 4; + + // Whether SimpleResponse should include OAuth scope. + bool fill_oauth_scope = 5; +} + +// Unary response, as configured by the request. +message SimpleResponse { + // Payload to increase message size. + Payload payload = 1; + // The user the request came from, for verifying authentication was + // successful when the client expected it. + string username = 2; + // OAuth scope. + string oauth_scope = 3; +} + +// Client-streaming request. +message StreamingInputCallRequest { + // Optional input payload sent along with the request. + Payload payload = 1; + + // Not expecting any payload from the response. +} + +// Client-streaming response. +message StreamingInputCallResponse { + // Aggregated size of payloads received from the client. + 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. + int32 size = 1; + + // Desired interval between consecutive responses in the response stream in + // microseconds. + int32 interval_us = 2; +} + +// Server-streaming request. +message StreamingOutputCallRequest { + // Desired payload type in the response from the server. + // 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. + PayloadType response_type = 1; + + // Configuration for each expected response message. + repeated ResponseParameters response_parameters = 2; + + // Optional input payload sent along with the request. + Payload payload = 3; +} + +// Server-streaming response, as configured by the request and parameters. +message StreamingOutputCallResponse { + // Payload to increase response size. + Payload payload = 1; +} diff --git a/src/objective-c/examples/RemoteTestClient/test.proto b/src/objective-c/examples/RemoteTestClient/test.proto new file mode 100644 index 0000000000..2f5a5489b3 --- /dev/null +++ b/src/objective-c/examples/RemoteTestClient/test.proto @@ -0,0 +1,73 @@ +// 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. + +// An integration test service that covers all the method signature permutations +// of unary/streaming requests/responses. +syntax = "proto3"; + +import "empty.proto"; +import "messages.proto"; + +package grpc.testing; + +option objc_class_prefix = "RMT"; + +// A simple service to test the various types of RPCs and experiment with +// performance with various types of payload. +service TestService { + // One empty request followed by one empty response. + rpc EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty); + + // One request followed by one response. + // TODO(Issue 527): Describe required server behavior. + rpc UnaryCall(SimpleRequest) returns (SimpleResponse); + + // One request followed by a sequence of responses (streamed download). + // The server returns the payload with client desired type and sizes. + rpc StreamingOutputCall(StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by one response (streamed upload). + // The server returns the aggregated size of client payload as the result. + rpc StreamingInputCall(stream StreamingInputCallRequest) + returns (StreamingInputCallResponse); + + // A sequence of requests with each request served by the server immediately. + // As one request could lead to multiple responses, this interface + // demonstrates the idea of full duplexing. + rpc FullDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); + + // A sequence of requests followed by a sequence of responses. + // The server buffers all the client requests and then serves them in order. A + // stream of responses are returned to the client when the server starts with + // first request. + rpc HalfDuplexCall(stream StreamingOutputCallRequest) + returns (stream StreamingOutputCallResponse); +} -- cgit v1.2.3 From d4a0785569c78486b0917a5fc949034fbb53dd01 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Mon, 31 Aug 2015 18:18:07 -0700 Subject: Point to the new RemoteTest pod --- src/objective-c/examples/SwiftSample/Podfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/Podfile b/src/objective-c/examples/SwiftSample/Podfile index 0caa8cae8b..7b5941eef7 100644 --- a/src/objective-c/examples/SwiftSample/Podfile +++ b/src/objective-c/examples/SwiftSample/Podfile @@ -2,7 +2,7 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' pod 'gRPC', :path => "../../../.." -# pod 'RemoteTest', :path => "../../generated_libraries/RemoteTestClient" +pod 'RemoteTest', :path => "../RemoteTestClient" target 'SwiftSample' do end -- cgit v1.2.3 From 9fffc2618740111691454acaec65854c99027f53 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Mon, 31 Aug 2015 19:15:21 -0700 Subject: Example with generated code :) --- .../examples/SwiftSample/Bridging-Header.h | 1 + .../examples/SwiftSample/ViewController.swift | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/Bridging-Header.h b/src/objective-c/examples/SwiftSample/Bridging-Header.h index 3b2ae74d8b..33db2dd1cb 100644 --- a/src/objective-c/examples/SwiftSample/Bridging-Header.h +++ b/src/objective-c/examples/SwiftSample/Bridging-Header.h @@ -39,5 +39,6 @@ #import #import #import +#import #endif diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift index dedcce20e7..e4e7aeae49 100644 --- a/src/objective-c/examples/SwiftSample/ViewController.swift +++ b/src/objective-c/examples/SwiftSample/ViewController.swift @@ -40,17 +40,33 @@ class ViewController: UIViewController { let RemoteHost = "grpc-test.sandbox.google.com" + let request = RMTSimpleRequest() + request.responseSize = 10 + request.fillUsername = true + request.fillOauthScope = true + + // Example gRPC call using a generated proto client library: + + let service = RMTTestService(host: RemoteHost) + service.unaryCallWithRequest(request) { (response: RMTSimpleResponse?, error: NSError?) in + if let response = response { + NSLog("Finished successfully with response:\n\(response)") + } else { + NSLog("Finished with error: \(error!)") + } + } + // Same example call using the generic gRPC client library: let method = ProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall") - let requestsWriter = GRXWriter(value: NSData()) + let requestsWriter = GRXWriter(value: request.data()) let call = GRPCCall(host: RemoteHost, path: method.HTTPPath, requestsWriter: requestsWriter) let responsesWriteable = GRXWriteable { (value: AnyObject?, error: NSError?) in if let value = value as? NSData { - NSLog("Received response:\n\(value)") + NSLog("Received response:\n\(RMTSimpleResponse(data: value, error: nil))") } else { NSLog("Finished with error: \(error!)") } -- cgit v1.2.3 From 2402078be383845a45b314d0385543d8cd5347c0 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Tue, 1 Sep 2015 15:13:59 +0000 Subject: Bump Python version to 0.11 and status to Beta --- src/python/README.md | 2 +- src/python/grpcio/setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/python/README.md b/src/python/README.md index a21deb33ef..67d1a173a2 100644 --- a/src/python/README.md +++ b/src/python/README.md @@ -4,7 +4,7 @@ The Python facility of gRPC. Status ------- -Alpha : Ready for early adopters +Beta : Core behavior well-used and proven; bugs lurk off the beaten path. PREREQUISITES ------------- diff --git a/src/python/grpcio/setup.py b/src/python/grpcio/setup.py index caa71a4f7c..4735ce080b 100644 --- a/src/python/grpcio/setup.py +++ b/src/python/grpcio/setup.py @@ -104,7 +104,7 @@ _COMMAND_CLASS = { setuptools.setup( name='grpcio', - version='0.10.0a0', + version='0.11.0', ext_modules=_EXTENSION_MODULES, packages=list(_PACKAGES), package_dir=_PACKAGE_DIRECTORIES, -- cgit v1.2.3 From 063560e3fb28c7b42d36ef5c7b799828994ee57d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 1 Sep 2015 08:44:42 -0700 Subject: Fixup windows server --- src/core/iomgr/tcp_server_windows.c | 49 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c index 79ea223d54..21f19f0ba2 100644 --- a/src/core/iomgr/tcp_server_windows.c +++ b/src/core/iomgr/tcp_server_windows.c @@ -75,18 +75,18 @@ struct grpc_tcp_server { void *cb_arg; gpr_mu mu; - gpr_cv cv; /* active port count: how many ports are actually still listening */ int active_ports; - /* number of iomgr callbacks that have been explicitly scheduled during - * shutdown */ - int iomgr_callbacks_pending; /* all listening ports */ server_port *ports; size_t nports; size_t port_capacity; + + /* shutdown callback */ + void(*shutdown_complete)(void *); + void *shutdown_complete_arg; }; /* Public function. Allocates the proper data structures to hold a @@ -94,34 +94,41 @@ struct grpc_tcp_server { grpc_tcp_server *grpc_tcp_server_create(void) { grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server)); gpr_mu_init(&s->mu); - gpr_cv_init(&s->cv); s->active_ports = 0; - s->iomgr_callbacks_pending = 0; s->cb = NULL; s->cb_arg = NULL; s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP); s->nports = 0; s->port_capacity = INIT_PORT_CAP; + s->shutdown_complete = NULL; return s; } +static void dont_care_about_shutdown_completion(void *arg) {} + /* Public function. Stops and destroys a grpc_tcp_server. */ void grpc_tcp_server_destroy(grpc_tcp_server *s, - void (*shutdown_done)(void *shutdown_done_arg), - void *shutdown_done_arg) { + void (*shutdown_complete)(void *shutdown_done_arg), + void *shutdown_complete_arg) { size_t i; + int immediately_done = 0; gpr_mu_lock(&s->mu); + + s->shutdown_complete = shutdown_complete + ? shutdown_complete + : dont_care_about_shutdown_completion; + s->shutdown_complete_arg = shutdown_complete_arg; + /* First, shutdown all fd's. This will queue abortion calls for all of the pending accepts due to the normal operation mechanism. */ + if (s->active_ports == 0) { + immediately_done = 1; + } for (i = 0; i < s->nports; i++) { server_port *sp = &s->ports[i]; sp->shutting_down = 1; grpc_winsocket_shutdown(sp->socket); } - /* This happens asynchronously. Wait while that happens. */ - while (s->active_ports || s->iomgr_callbacks_pending) { - gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future(GPR_CLOCK_REALTIME)); - } gpr_mu_unlock(&s->mu); /* Now that the accepts have been aborted, we can destroy the sockets. @@ -134,8 +141,8 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s, gpr_free(s->ports); gpr_free(s); - if (shutdown_done) { - shutdown_done(shutdown_done_arg); + if (immediately_done) { + s->shutdown_complete(s->shutdown_complete_arg); } } @@ -188,13 +195,19 @@ error: } static void decrement_active_ports_and_notify(server_port *sp) { + void(*notify)(void *) = NULL; + void *notify_arg = NULL; sp->shutting_down = 0; gpr_mu_lock(&sp->server->mu); GPR_ASSERT(sp->server->active_ports > 0); if (0 == --sp->server->active_ports) { - gpr_cv_broadcast(&sp->server->cv); + notify = sp->server->shutdown_complete; + notify_arg = sp->server->shutdown_complete_arg; } gpr_mu_unlock(&sp->server->mu); + if (notify != NULL) { + notify(notify_arg); + } } /* start_accept will reference that for the IOCP notification request. */ @@ -279,12 +292,6 @@ static void on_accept(void *arg, int from_iocp) { this is necessary in the read/write case, it's useless for the accept case. We only need to adjust the pending callback count */ if (!from_iocp) { - gpr_mu_lock(&sp->server->mu); - GPR_ASSERT(sp->server->iomgr_callbacks_pending > 0); - if (0 == --sp->server->iomgr_callbacks_pending) { - gpr_cv_broadcast(&sp->server->cv); - } - gpr_mu_unlock(&sp->server->mu); return; } -- cgit v1.2.3 From 0d728c1e9eb9f685eedc27788e6923378d115459 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Tue, 1 Sep 2015 20:23:09 +0200 Subject: Bumping revision to 0.11 for beta. --- Makefile | 2 +- build.yaml | 2 +- src/core/surface/version.c | 2 +- tools/doxygen/Doxyfile.c++ | 2 +- tools/doxygen/Doxyfile.c++.internal | 2 +- tools/doxygen/Doxyfile.core | 2 +- tools/doxygen/Doxyfile.core.internal | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index b724ee2a7c..00875cd8e7 100644 --- a/Makefile +++ b/Makefile @@ -309,7 +309,7 @@ E = @echo Q = @ endif -VERSION = 0.10.1.0 +VERSION = 0.11.0.0 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) diff --git a/build.yaml b/build.yaml index 183c0ae78f..31a1e328a8 100644 --- a/build.yaml +++ b/build.yaml @@ -3,7 +3,7 @@ '#3': Please refer to the templates directory for more information. settings: '#': The public version number of the library. - version: {major: 0, minor: 10, micro: 1, build: 0} + version: {major: 0, minor: 11, micro: 0, build: 0} filegroups: - name: census public_headers: [include/grpc/census.h] diff --git a/src/core/surface/version.c b/src/core/surface/version.c index d7aaba3868..4b90e06a04 100644 --- a/src/core/surface/version.c +++ b/src/core/surface/version.c @@ -37,5 +37,5 @@ #include const char *grpc_version_string(void) { - return "0.10.1.0"; + return "0.11.0.0"; } diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 96708c0622..a352341774 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.10.1.0 +PROJECT_NUMBER = 0.11.0.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 185d24720c..dfaeb43ca7 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.10.1.0 +PROJECT_NUMBER = 0.11.0.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core index 4c83e22b7f..beb0128e41 100644 --- a/tools/doxygen/Doxyfile.core +++ b/tools/doxygen/Doxyfile.core @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.10.1.0 +PROJECT_NUMBER = 0.11.0.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal index 729f8bf2ff..fdc32c7776 100644 --- a/tools/doxygen/Doxyfile.core.internal +++ b/tools/doxygen/Doxyfile.core.internal @@ -40,7 +40,7 @@ PROJECT_NAME = "GRPC Core" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.10.1.0 +PROJECT_NUMBER = 0.11.0.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a -- cgit v1.2.3 From 5100ea0043be791587b7d21b4cb32dac3648f17c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 1 Sep 2015 12:23:28 -0700 Subject: fixes for windows --- src/core/iomgr/iocp_windows.c | 1 - src/core/iomgr/socket_windows.c | 3 +-- src/core/iomgr/tcp_server_windows.c | 40 +++++++++++++++++++---------------- src/core/transport/chttp2_transport.c | 2 +- 4 files changed, 24 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c index 0799622497..006f8b2abf 100644 --- a/src/core/iomgr/iocp_windows.c +++ b/src/core/iomgr/iocp_windows.c @@ -112,7 +112,6 @@ static void do_iocp_work() { static void iocp_loop(void *p) { while (gpr_atm_acq_load(&g_custom_events) || !gpr_event_get(&g_shutdown_iocp)) { - grpc_maybe_call_delayed_callbacks(NULL, 1); do_iocp_work(); } diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c index dbc64637b5..2cbe945ca3 100644 --- a/src/core/iomgr/socket_windows.c +++ b/src/core/iomgr/socket_windows.c @@ -63,11 +63,10 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) { various callsites of that function, which happens to be in various mutex hold states, and that'd be unsafe to call them directly. */ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) { - shutdown(winsocket->socket, SD_BOTH); + closesocket(winsocket->socket); } void grpc_winsocket_destroy(grpc_winsocket *winsocket) { - closesocket(winsocket->socket); grpc_iomgr_unregister_object(&winsocket->iomgr_object); gpr_mu_destroy(&winsocket->state_mu); gpr_free(winsocket); diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c index 21f19f0ba2..b513d854aa 100644 --- a/src/core/iomgr/tcp_server_windows.c +++ b/src/core/iomgr/tcp_server_windows.c @@ -106,6 +106,22 @@ grpc_tcp_server *grpc_tcp_server_create(void) { static void dont_care_about_shutdown_completion(void *arg) {} +static void finish_shutdown(grpc_tcp_server *s) { + size_t i; + + s->shutdown_complete(s->shutdown_complete_arg); + + /* Now that the accepts have been aborted, we can destroy the sockets. + The IOCP won't get notified on these, so we can flag them as already + closed by the system. */ + for (i = 0; i < s->nports; i++) { + server_port *sp = &s->ports[i]; + grpc_winsocket_destroy(sp->socket); + } + gpr_free(s->ports); + gpr_free(s); +} + /* Public function. Stops and destroys a grpc_tcp_server. */ void grpc_tcp_server_destroy(grpc_tcp_server *s, void (*shutdown_complete)(void *shutdown_done_arg), @@ -131,18 +147,8 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s, } gpr_mu_unlock(&s->mu); - /* Now that the accepts have been aborted, we can destroy the sockets. - The IOCP won't get notified on these, so we can flag them as already - closed by the system. */ - for (i = 0; i < s->nports; i++) { - server_port *sp = &s->ports[i]; - grpc_winsocket_destroy(sp->socket); - } - gpr_free(s->ports); - gpr_free(s); - if (immediately_done) { - s->shutdown_complete(s->shutdown_complete_arg); + finish_shutdown(s); } } @@ -195,18 +201,16 @@ error: } static void decrement_active_ports_and_notify(server_port *sp) { - void(*notify)(void *) = NULL; - void *notify_arg = NULL; + int notify = 0; sp->shutting_down = 0; gpr_mu_lock(&sp->server->mu); GPR_ASSERT(sp->server->active_ports > 0); - if (0 == --sp->server->active_ports) { - notify = sp->server->shutdown_complete; - notify_arg = sp->server->shutdown_complete_arg; + if (0 == --sp->server->active_ports && sp->server->shutdown_complete != NULL) { + notify = 1; } gpr_mu_unlock(&sp->server->mu); - if (notify != NULL) { - notify(notify_arg); + if (notify) { + finish_shutdown(sp->server); } } diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index aa7a7c9471..b8705cc49b 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -1119,7 +1119,7 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { if (!*success || i != t->read_buffer.count) { drop_connection(t); read_error_locked(t); - } else { + } else if (!t->closed) { keep_reading = 1; prevent_endpoint_shutdown(t); } -- cgit v1.2.3 From deb3d2255dac7da1131a40bc028fbdc977a43e44 Mon Sep 17 00:00:00 2001 From: yang-g Date: Tue, 1 Sep 2015 12:51:28 -0700 Subject: Add missed header --- src/cpp/util/string_ref.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cpp/util/string_ref.cc b/src/cpp/util/string_ref.cc index 9adc092013..c42033f61f 100644 --- a/src/cpp/util/string_ref.cc +++ b/src/cpp/util/string_ref.cc @@ -36,6 +36,7 @@ #include #include +#include namespace grpc { -- cgit v1.2.3 From ae96a504dfac822bb14a2968448d62abdbb03cae Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 1 Sep 2015 15:15:42 -0700 Subject: Fix asan bug --- src/core/transport/chttp2_transport.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index b8705cc49b..386ba04b9c 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -338,10 +338,10 @@ static void destroy_transport(grpc_transport *gt) { UNREF_TRANSPORT(t, "destroy"); } -/** block grpc_endpoint_shutdown being called until a paired +/** block grpc_endpoint_shutdown being called until a paired allow_endpoint_shutdown is made */ static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) { - GPR_ASSERT(t->shutdown_ep_refs.count); + GPR_ASSERT(t->ep); gpr_ref(&t->shutdown_ep_refs); } @@ -525,6 +525,8 @@ void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr; grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); + allow_endpoint_shutdown(t); + lock(t); if (!success) { @@ -552,7 +554,6 @@ void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { static void writing_action(void *gt, int iomgr_success_ignored) { grpc_chttp2_transport *t = gt; grpc_chttp2_perform_writes(&t->writing, t->ep); - allow_endpoint_shutdown(t); } void grpc_chttp2_add_incoming_goaway( -- cgit v1.2.3 From c9f43e5cc3820353fc9055ce6a30f6e36ca79b27 Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Tue, 1 Sep 2015 18:24:27 -0700 Subject: Fix bugs that were causing auth interop tests to fail --- src/node/interop/interop_client.js | 8 ++++---- src/node/src/client.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js index 6a8d2633ca..215d42121c 100644 --- a/src/node/interop/interop_client.js +++ b/src/node/interop/interop_client.js @@ -44,7 +44,7 @@ var assert = require('assert'); var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo'; var AUTH_SCOPE_RESPONSE = 'xapi.zoo'; -var AUTH_USER = ('155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk' + +var AUTH_USER = ('155450119199-vefjjaekcc6cmsd5914v6lqufunmh9ue' + '@developer.gserviceaccount.com'); var COMPUTE_ENGINE_USER = ('155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel' + '@developer.gserviceaccount.com'); @@ -321,7 +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.Add('authorization', 'Bearer ' + token); + metadata.add('authorization', 'Bearer ' + token); callback(null, metadata); }; var makeTestCall = function(error, client_metadata) { @@ -336,10 +336,10 @@ function oauth2Test(expected_user, scope, per_rpc, client, done) { }, client_metadata); }; if (per_rpc) { - updateMetadata('', {}, makeTestCall); + updateMetadata('', new grpc.Metadata(), makeTestCall); } else { client.$updateMetadata = updateMetadata; - makeTestCall(null, {}); + makeTestCall(null, new grpc.Metadata()); } }); }); diff --git a/src/node/src/client.js b/src/node/src/client.js index b427297a8a..7f510231b3 100644 --- a/src/node/src/client.js +++ b/src/node/src/client.js @@ -637,7 +637,7 @@ exports.makeClientConstructor = function(methods, serviceName) { // 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.$auth_uri = 'https://' + this.$server_address + '/' + serviceName; this.$updateMetadata = updateMetadata; } -- cgit v1.2.3 From 18c975f9d391b4d4068200a94e4b1dcacca3e45b Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Tue, 1 Sep 2015 18:18:47 -0700 Subject: Fix C core build breakage. --- src/core/census/grpc_filter.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/core/census/grpc_filter.c b/src/core/census/grpc_filter.c index e01c9a2ad4..8b6ba1d472 100644 --- a/src/core/census/grpc_filter.c +++ b/src/core/census/grpc_filter.c @@ -36,7 +36,6 @@ #include #include -#include "include/grpc/census.h" #include "src/core/channel/channel_stack.h" #include "src/core/channel/noop_filter.h" #include "src/core/statistics/census_interface.h" -- cgit v1.2.3 From 84fa531e4d5a3ca295ffdf93b3b1d676b3dec26f Mon Sep 17 00:00:00 2001 From: murgatroid99 Date: Fri, 28 Aug 2015 10:55:55 -0700 Subject: Added class for setting request headers on a call --- src/objective-c/GRPCClient/GRPCCall+OAuth2.m | 1 + src/objective-c/GRPCClient/GRPCCall.h | 4 +- src/objective-c/GRPCClient/GRPCCall.m | 18 ++- .../GRPCClient/private/GRPCRequestHeaders.h | 51 ++++++++ .../GRPCClient/private/GRPCRequestHeaders.m | 128 +++++++++++++++++++++ 5 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 src/objective-c/GRPCClient/private/GRPCRequestHeaders.h create mode 100644 src/objective-c/GRPCClient/private/GRPCRequestHeaders.m (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall+OAuth2.m b/src/objective-c/GRPCClient/GRPCCall+OAuth2.m index 83b0de18e3..cb2cee17d7 100644 --- a/src/objective-c/GRPCClient/GRPCCall+OAuth2.m +++ b/src/objective-c/GRPCClient/GRPCCall+OAuth2.m @@ -32,6 +32,7 @@ */ #import "GRPCCall+OAuth2.h" +#import "private/GRPCRequestHeaders.h" static NSString * const kAuthorizationHeader = @"authorization"; static NSString * const kBearerPrefix = @"Bearer "; diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 4eda499b1a..975ff8feff 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -48,6 +48,8 @@ #import #import +@class GRPCRequestHeaders; + // Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by // the server. extern id const kGRPCHeadersKey; @@ -70,7 +72,7 @@ extern id const kGRPCTrailersKey; // // For convenience, the property is initialized to an empty NSMutableDictionary, and the setter // accepts (and copies) both mutable and immutable dictionaries. -- (NSMutableDictionary *)requestHeaders; // nonatomic +- (GRPCRequestHeaders *)requestHeaders; // nonatomic - (void)setRequestHeaders:(NSDictionary *)requestHeaders; // nonatomic, copy // This dictionary is populated with the HTTP headers received from the server. This happens before diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index ff5d1c5aaf..afa01e2f0f 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -41,6 +41,7 @@ #import "private/NSData+GRPC.h" #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" +#import "private/GRPCRequestHeaders.h" NSString * const kGRPCHeadersKey = @"io.grpc.HeadersKey"; NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; @@ -93,7 +94,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; // the response arrives. GRPCCall *_retainSelf; - NSMutableDictionary *_requestHeaders; + GRPCRequestHeaders *_requestHeaders; } @synthesize state = _state; @@ -124,19 +125,23 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; _requestWriter = requestWriter; - _requestHeaders = [NSMutableDictionary dictionary]; + _requestHeaders = [[GRPCRequestHeaders alloc] initWithCall:self]; } return self; } #pragma mark Metadata -- (NSMutableDictionary *)requestHeaders { +- (GRPCRequestHeaders *)requestHeaders { return _requestHeaders; } - (void)setRequestHeaders:(NSDictionary *)requestHeaders { - _requestHeaders = [NSMutableDictionary dictionaryWithDictionary:requestHeaders]; + GRPCRequestHeaders *newHeaders = [[GRPCRequestHeaders alloc] initWithCall:self]; + for (id key in requestHeaders) { + newHeaders[key] = requestHeaders[key]; + } + _requestHeaders = newHeaders; } #pragma mark Finish @@ -230,10 +235,11 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; #pragma mark Send headers -- (void)sendHeaders:(NSDictionary *)headers { +- (void)sendHeaders:(GRPCRequestHeaders *)headers { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] - initWithMetadata:headers ?: @{} handler:nil]]]; + initWithMetadata:[headers asDictionary] ?: @{} + handler:nil]]]; } #pragma mark GRXWriteable implementation diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h new file mode 100644 index 0000000000..320545190f --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h @@ -0,0 +1,51 @@ +/* + * + * 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 +#include + +@class GRPCCall; + +@interface GRPCRequestHeaders : NSObject + +- (instancetype)initWithCall:(GRPCCall *)call; + +- (id)objectForKeyedSubscript:(NSString *)key; +- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; + +- (void)removeAllObjects; +- (void)removeObjectForKey:(NSString *)aKey; + +- (NSDictionary *)asDictionary; + +@end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m new file mode 100644 index 0000000000..f479ed7501 --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -0,0 +1,128 @@ +/* + * + * 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 +#import "GRPCRequestHeaders.h" +#import "GRPCCall.h" + +static NSString* normalizeKey(NSString* key) { + if ([key canBeConvertedToEncoding:NSASCIIStringEncoding]) { + return [key lowercaseString]; + } else { + return nil; + } +} + +static bool isKeyValuePairValid(NSString *key, id value) { + if ([key hasSuffix:@"-bin"]) { + if (![value isKindOfClass:[NSData class]]) { + return false; + } + } else { + if (![value isKindOfClass:[NSString class]]) { + return false; + } + } + return true; +} + +@implementation GRPCRequestHeaders { + __weak GRPCCall *_call; + NSMutableDictionary *_proxy; +} + +- (instancetype) initWithCall:(GRPCCall *)call { + self = [super init]; + if (self) { + _call = call; + _proxy = [NSMutableDictionary dictionary]; + } + return self; +} + +- (id) objectForKeyedSubscript:(NSString *)key { + NSString *normalizedKey = normalizeKey(key); + if (normalizedKey) { + return _proxy[normalizedKey]; + } else { + return [NSNull null]; + } +} + +- (void) setObject:(id)obj forKeyedSubscript:(NSString *)key { + if (_call.state == GRXWriterStateNotStarted) { + NSString *normalizedKey = normalizeKey(key); + if (normalizedKey) { + if (isKeyValuePairValid(key, obj)) { + _proxy[normalizedKey] = obj; + } else { + [NSException raise:@"Invalid key/value pair" + format:@"Key %@ could not be added with value %@", key, obj]; + } + } else { + [NSException raise:@"Invalid key" format:@"Key %@ contains illegal characters", key]; + } + } else { + [NSException raise:@"Invalid modification" + format:@"Cannot modify request metadata after call is started"]; + } +} + +- (void) removeObjectForKey:(NSString *)aKey { + if (_call.state == GRXWriterStateNotStarted) { + NSString *normalizedKey = normalizeKey(aKey); + if (normalizedKey) { + [_proxy removeObjectForKey:normalizedKey]; + } else { + [NSException raise:@"Invalid key" format:@"Key %@ contains illegal characters", aKey]; + } + } else { + [NSException raise:@"Invalid modification" + format:@"Cannot modify request metadata after call is started"]; + } +} + +- (void) removeAllObjects { + if (_call.state == GRXWriterStateNotStarted) { + [_proxy removeAllObjects]; + } else { + [NSException raise:@"Invalid modification" + format:@"Cannot modify request metadata after call is started"]; + } +} + +- (NSDictionary *)asDictionary { + return [NSDictionary dictionaryWithDictionary:_proxy]; +} + +@end \ No newline at end of file -- cgit v1.2.3 From d45d55c39bcb5fef539720f1dcc7f91227af5b9b Mon Sep 17 00:00:00 2001 From: Masood Malekghassemi Date: Wed, 2 Sep 2015 09:40:15 -0700 Subject: Expose per-call credentials to Python --- src/python/grpcio/grpc/_adapter/_c/types.h | 2 ++ src/python/grpcio/grpc/_adapter/_c/types/call.c | 15 +++++++++++++++ src/python/grpcio/grpc/_adapter/_intermediary_low.py | 3 +++ src/python/grpcio/grpc/_adapter/_low.py | 3 +++ 4 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/python/grpcio/grpc/_adapter/_c/types.h b/src/python/grpcio/grpc/_adapter/_c/types.h index ec0687a9fd..31fd470d36 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types.h +++ b/src/python/grpcio/grpc/_adapter/_c/types.h @@ -112,6 +112,8 @@ void pygrpc_Call_dealloc(Call *self); PyObject *pygrpc_Call_start_batch(Call *self, PyObject *args, PyObject *kwargs); PyObject *pygrpc_Call_cancel(Call *self, PyObject *args, PyObject *kwargs); PyObject *pygrpc_Call_peer(Call *self); +PyObject *pygrpc_Call_set_credentials(Call *self, PyObject *args, + PyObject *kwargs); extern PyTypeObject pygrpc_Call_type; diff --git a/src/python/grpcio/grpc/_adapter/_c/types/call.c b/src/python/grpcio/grpc/_adapter/_c/types/call.c index 42a50151f6..5604aba39d 100644 --- a/src/python/grpcio/grpc/_adapter/_c/types/call.c +++ b/src/python/grpcio/grpc/_adapter/_c/types/call.c @@ -43,6 +43,8 @@ PyMethodDef pygrpc_Call_methods[] = { {"start_batch", (PyCFunction)pygrpc_Call_start_batch, METH_KEYWORDS, ""}, {"cancel", (PyCFunction)pygrpc_Call_cancel, METH_KEYWORDS, ""}, {"peer", (PyCFunction)pygrpc_Call_peer, METH_NOARGS, ""}, + {"set_credentials", (PyCFunction)pygrpc_Call_set_credentials, METH_KEYWORDS, + ""}, {NULL} }; const char pygrpc_Call_doc[] = "See grpc._adapter._types.Call."; @@ -169,3 +171,16 @@ PyObject *pygrpc_Call_peer(Call *self) { gpr_free(peer); return py_peer; } +PyObject *pygrpc_Call_set_credentials(Call *self, PyObject *args, + PyObject *kwargs) { + ClientCredentials *creds; + grpc_call_error errcode; + static char *keywords[] = {"creds", NULL}; + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, "O!:set_credentials", keywords, + &pygrpc_ClientCredentials_type, &creds)) { + return NULL; + } + errcode = grpc_call_set_credentials(self->c_call, creds->c_creds); + return PyInt_FromLong(errcode); +} diff --git a/src/python/grpcio/grpc/_adapter/_intermediary_low.py b/src/python/grpcio/grpc/_adapter/_intermediary_low.py index 06358e72bc..735ad205a4 100644 --- a/src/python/grpcio/grpc/_adapter/_intermediary_low.py +++ b/src/python/grpcio/grpc/_adapter/_intermediary_low.py @@ -163,6 +163,9 @@ class Call(object): def cancel(self): return self._internal.cancel() + def set_credentials(self, creds): + return self._internal.set_credentials(creds) + class Channel(object): """Adapter from old _low.Channel interface to new _low.Channel.""" diff --git a/src/python/grpcio/grpc/_adapter/_low.py b/src/python/grpcio/grpc/_adapter/_low.py index 3859ebb0e2..70ceb2a911 100644 --- a/src/python/grpcio/grpc/_adapter/_low.py +++ b/src/python/grpcio/grpc/_adapter/_low.py @@ -78,6 +78,9 @@ class Call(_types.Call): def peer(self): return self.call.peer() + def set_credentials(self, creds): + return self.call.set_credentials(creds) + class Channel(_types.Channel): -- cgit v1.2.3 From b059ae54c362833b287d4342cb96aae69792279f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 2 Sep 2015 11:11:57 -0700 Subject: Fix ASAN issues --- src/core/transport/chttp2_transport.c | 43 +++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 386ba04b9c..aa6a860c67 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -345,19 +345,38 @@ static void prevent_endpoint_shutdown(grpc_chttp2_transport *t) { gpr_ref(&t->shutdown_ep_refs); } -static void allow_endpoint_shutdown(grpc_chttp2_transport *t) { +static void allow_endpoint_shutdown_locked(grpc_chttp2_transport *t) { if (gpr_unref(&t->shutdown_ep_refs)) { - grpc_endpoint_shutdown(t->ep); + if (t->ep) { + grpc_endpoint_shutdown(t->ep); + } + } +} + +static void allow_endpoint_shutdown_unlocked(grpc_chttp2_transport *t) { + if (gpr_unref(&t->shutdown_ep_refs)) { + gpr_mu_lock(&t->mu); + if (t->ep) { + grpc_endpoint_shutdown(t->ep); + } + gpr_mu_unlock(&t->mu); } } +static void destroy_endpoint(grpc_chttp2_transport *t) { + grpc_endpoint_destroy(t->ep); + t->ep = NULL; + UNREF_TRANSPORT( + t, "disconnect"); /* safe because we'll still have the ref for write */ +} + static void close_transport_locked(grpc_chttp2_transport *t) { if (!t->closed) { t->closed = 1; connectivity_state_set(&t->global, GRPC_CHANNEL_FATAL_FAILURE, "close_transport"); if (t->ep) { - allow_endpoint_shutdown(t); + allow_endpoint_shutdown_locked(t); } } } @@ -525,10 +544,10 @@ void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { grpc_chttp2_transport_writing *transport_writing = transport_writing_ptr; grpc_chttp2_transport *t = TRANSPORT_FROM_WRITING(transport_writing); - allow_endpoint_shutdown(t); - lock(t); + allow_endpoint_shutdown_locked(t); + if (!success) { drop_connection(t); } @@ -540,10 +559,7 @@ void grpc_chttp2_terminate_writing(void *transport_writing_ptr, int success) { from starting */ t->writing_active = 0; if (t->ep && !t->endpoint_reading) { - grpc_endpoint_destroy(t->ep); - t->ep = NULL; - UNREF_TRANSPORT( - t, "disconnect"); /* safe because we'll still have the ref for write */ + destroy_endpoint(t); } unlock(t); @@ -1073,10 +1089,7 @@ static void update_global_window(void *args, gpr_uint32 id, void *stream) { static void read_error_locked(grpc_chttp2_transport *t) { t->endpoint_reading = 0; if (!t->writing_active && t->ep) { - grpc_endpoint_destroy(t->ep); - t->ep = NULL; - /* safe as we still have a ref for read */ - UNREF_TRANSPORT(t, "disconnect"); + destroy_endpoint(t); } } @@ -1122,6 +1135,7 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { read_error_locked(t); } else if (!t->closed) { keep_reading = 1; + REF_TRANSPORT(t, "keep_reading"); prevent_endpoint_shutdown(t); } gpr_slice_buffer_reset_and_unref(&t->read_buffer); @@ -1142,7 +1156,8 @@ static int recv_data_loop(grpc_chttp2_transport *t, int *success) { ret = 0; break; } - allow_endpoint_shutdown(t); + allow_endpoint_shutdown_unlocked(t); + UNREF_TRANSPORT(t, "keep_reading"); return ret; } else { UNREF_TRANSPORT(t, "recv_data"); -- cgit v1.2.3 From 3ab8e79b0111dc93696d72e815531b5ee3124230 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Mon, 24 Aug 2015 16:58:42 -0700 Subject: php: support per message compression disable --- src/php/ext/grpc/call.c | 27 +++++++++++- src/php/lib/Grpc/AbstractCall.php | 18 +++++++- src/php/lib/Grpc/BaseStub.php | 13 +++--- src/php/lib/Grpc/BidiStreamingCall.php | 11 +++-- src/php/lib/Grpc/ClientStreamingCall.php | 22 +++++++--- src/php/lib/Grpc/ServerStreamingCall.php | 15 ++++--- src/php/lib/Grpc/UnaryCall.php | 13 ++++-- .../generated_code/AbstractGeneratedCodeTest.php | 14 +++--- src/php/tests/interop/interop_client.php | 7 ++- src/php/tests/unit_tests/EndToEndTest.php | 49 ++++++++++++++++++++- src/php/tests/unit_tests/SecureEndToEndTest.php | 51 +++++++++++++++++++++- 11 files changed, 200 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index 252623d0c3..3b99de7538 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -265,6 +265,9 @@ PHP_METHOD(Call, startBatch) { HashTable *array_hash; HashPosition array_pointer; HashTable *status_hash; + HashTable *message_hash; + zval **message_value; + zval **message_flags; char *key; uint key_len; ulong index; @@ -319,13 +322,33 @@ PHP_METHOD(Call, startBatch) { metadata.metadata; break; case GRPC_OP_SEND_MESSAGE: - if (Z_TYPE_PP(value) != IS_STRING) { + if (Z_TYPE_PP(value) != IS_ARRAY) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected an array for send message", + 1 TSRMLS_CC); + goto cleanup; + } + message_hash = Z_ARRVAL_PP(value); + if (zend_hash_find(message_hash, "flags", sizeof("flags"), + (void **)&message_flags) == SUCCESS) { + if (Z_TYPE_PP(message_flags) != IS_LONG) { + zend_throw_exception(spl_ce_InvalidArgumentException, + "Expected an int for message flags", + 1 TSRMLS_CC); + } + ops[op_num].flags = Z_LVAL_PP(message_flags) & GRPC_WRITE_USED_MASK; + } + if (zend_hash_find(message_hash, "message", sizeof("message"), + (void **)&message_value) != SUCCESS || + Z_TYPE_PP(message_value) != IS_STRING) { zend_throw_exception(spl_ce_InvalidArgumentException, "Expected a string for send message", 1 TSRMLS_CC); + goto cleanup; } ops[op_num].data.send_message = - string_to_byte_buffer(Z_STRVAL_PP(value), Z_STRLEN_PP(value)); + string_to_byte_buffer(Z_STRVAL_PP(message_value), + Z_STRLEN_PP(message_value)); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: break; diff --git a/src/php/lib/Grpc/AbstractCall.php b/src/php/lib/Grpc/AbstractCall.php index 35057224f8..3fdaf2e487 100644 --- a/src/php/lib/Grpc/AbstractCall.php +++ b/src/php/lib/Grpc/AbstractCall.php @@ -92,4 +92,20 @@ abstract class AbstractCall { } return call_user_func($this->deserialize, $value); } -} \ No newline at end of file + + /** + * Get the list of Grpc Write Flags + * @param array $options an array of options + * @return The list of Grpc Write Flags contained in the input + */ + protected static function getGrpcWriteFlags($options) { + $grpc_write_flags = []; + foreach ([WRITE_BUFFER_HINT, + WRITE_NO_COMPRESS] as $flag) { + if (in_array($flag, $options)) { + $grpc_write_flags[] = $flag; + } + } + return $grpc_write_flags; + } +} diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php index 2e980c5eed..381b114399 100755 --- a/src/php/lib/Grpc/BaseStub.php +++ b/src/php/lib/Grpc/BaseStub.php @@ -168,7 +168,8 @@ class BaseStub { public function _simpleRequest($method, $argument, callable $deserialize, - $metadata = array()) { + $metadata = array(), + $options = array()) { list($actual_metadata, $timeout) = $this->_extract_timeout_from_metadata($metadata); $call = new UnaryCall($this->channel, $method, $deserialize, $timeout); $jwt_aud_uri = $this->_get_jwt_aud_uri($method); @@ -177,7 +178,7 @@ class BaseStub { $actual_metadata, $jwt_aud_uri); } - $call->start($argument, $actual_metadata); + $call->start($argument, $actual_metadata, $options); return $call; } @@ -193,7 +194,6 @@ class BaseStub { * @return ClientStreamingSurfaceActiveCall The active call object */ public function _clientStreamRequest($method, - $arguments, callable $deserialize, $metadata = array()) { list($actual_metadata, $timeout) = $this->_extract_timeout_from_metadata($metadata); @@ -204,7 +204,7 @@ class BaseStub { $actual_metadata, $jwt_aud_uri); } - $call->start($arguments, $actual_metadata); + $call->start($actual_metadata); return $call; } @@ -221,7 +221,8 @@ class BaseStub { public function _serverStreamRequest($method, $argument, callable $deserialize, - $metadata = array()) { + $metadata = array(), + $options = array()) { list($actual_metadata, $timeout) = $this->_extract_timeout_from_metadata($metadata); $call = new ServerStreamingCall($this->channel, $method, $deserialize, $timeout); $jwt_aud_uri = $this->_get_jwt_aud_uri($method); @@ -230,7 +231,7 @@ class BaseStub { $actual_metadata, $jwt_aud_uri); } - $call->start($argument, $actual_metadata); + $call->start($argument, $actual_metadata, $options); return $call; } diff --git a/src/php/lib/Grpc/BidiStreamingCall.php b/src/php/lib/Grpc/BidiStreamingCall.php index 76c642bef4..80b7a66a76 100644 --- a/src/php/lib/Grpc/BidiStreamingCall.php +++ b/src/php/lib/Grpc/BidiStreamingCall.php @@ -66,9 +66,14 @@ class BidiStreamingCall extends AbstractCall { * Write a single message to the server. This cannot be called after * writesDone is called. * @param ByteBuffer $data The data to write + * @param array $options an array of options */ - public function write($data) { - $this->call->startBatch([OP_SEND_MESSAGE => $data->serialize()]); + public function write($data, $options = array()) { + $message_array = ['message' => $data->serialize()]; + if ($grpc_write_flags = self::getGrpcWriteFlags($options)) { + $message_array['flags'] = $grpc_write_flags; + } + $this->call->startBatch([OP_SEND_MESSAGE => $message_array]); } /** @@ -86,7 +91,7 @@ class BidiStreamingCall extends AbstractCall { public function getStatus() { $status_event = $this->call->startBatch([ OP_RECV_STATUS_ON_CLIENT => true - ]); + ]); return $status_event->status; } } \ No newline at end of file diff --git a/src/php/lib/Grpc/ClientStreamingCall.php b/src/php/lib/Grpc/ClientStreamingCall.php index 61439d3f47..97c241a087 100644 --- a/src/php/lib/Grpc/ClientStreamingCall.php +++ b/src/php/lib/Grpc/ClientStreamingCall.php @@ -40,15 +40,24 @@ namespace Grpc; class ClientStreamingCall extends AbstractCall { /** * Start the call. - * @param Traversable $arg_iter The iterator of arguments to send * @param array $metadata Metadata to send with the call, if applicable */ - public function start($arg_iter, $metadata = array()) { - $event = $this->call->startBatch([OP_SEND_INITIAL_METADATA => $metadata]); - foreach($arg_iter as $arg) { - $this->call->startBatch([OP_SEND_MESSAGE => $arg->serialize()]); + public function start($metadata) { + $this->call->startBatch([OP_SEND_INITIAL_METADATA => $metadata]); + } + + /** + * Write a single message to the server. This cannot be called after + * wait is called. + * @param ByteBuffer $data The data to write + * @param array $options an array of options + */ + public function write($data, $options = array()) { + $message_array = ['message' => $data->serialize()]; + if ($grpc_write_flags = self::getGrpcWriteFlags($options)) { + $message_array['flags'] = $grpc_write_flags; } - $this->call->startBatch([OP_SEND_CLOSE_FROM_CLIENT => true]); + $this->call->startBatch([OP_SEND_MESSAGE => $message_array]); } /** @@ -57,6 +66,7 @@ class ClientStreamingCall extends AbstractCall { */ public function wait() { $event = $this->call->startBatch([ + OP_SEND_CLOSE_FROM_CLIENT => true, OP_RECV_INITIAL_METADATA => true, OP_RECV_MESSAGE => true, OP_RECV_STATUS_ON_CLIENT => true]); diff --git a/src/php/lib/Grpc/ServerStreamingCall.php b/src/php/lib/Grpc/ServerStreamingCall.php index 631c863345..159561b43a 100644 --- a/src/php/lib/Grpc/ServerStreamingCall.php +++ b/src/php/lib/Grpc/ServerStreamingCall.php @@ -40,14 +40,19 @@ namespace Grpc; class ServerStreamingCall extends AbstractCall { /** * Start the call - * @param $arg The argument to send + * @param $data The data to send * @param array $metadata Metadata to send with the call, if applicable + * @param array $options an array of options */ - public function start($arg, $metadata = array()) { + public function start($data, $metadata = array(), $options = array()) { + $message_array = ['message' => $data->serialize()]; + if ($grpc_write_flags = self::getGrpcWriteFlags($options)) { + $message_array['flags'] = $grpc_write_flags; + } $event = $this->call->startBatch([ OP_SEND_INITIAL_METADATA => $metadata, OP_RECV_INITIAL_METADATA => true, - OP_SEND_MESSAGE => $arg->serialize(), + OP_SEND_MESSAGE => $message_array, OP_SEND_CLOSE_FROM_CLIENT => true]); $this->metadata = $event->metadata; } @@ -71,7 +76,7 @@ class ServerStreamingCall extends AbstractCall { public function getStatus() { $status_event = $this->call->startBatch([ OP_RECV_STATUS_ON_CLIENT => true - ]); + ]); return $status_event->status; } -} \ No newline at end of file +} diff --git a/src/php/lib/Grpc/UnaryCall.php b/src/php/lib/Grpc/UnaryCall.php index 97a10a40f4..5ca7d9ed65 100644 --- a/src/php/lib/Grpc/UnaryCall.php +++ b/src/php/lib/Grpc/UnaryCall.php @@ -40,14 +40,19 @@ namespace Grpc; class UnaryCall extends AbstractCall { /** * Start the call - * @param $arg The argument to send + * @param $data The data to send * @param array $metadata Metadata to send with the call, if applicable + * @param array $options an array of options */ - public function start($arg, $metadata = array()) { + public function start($data, $metadata = array(), $options = array()) { + $message_array = ['message' => $data->serialize()]; + if ($grpc_write_flags = self::getGrpcWriteFlags($options)) { + $message_array['flags'] = $grpc_write_flags; + } $event = $this->call->startBatch([ OP_SEND_INITIAL_METADATA => $metadata, OP_RECV_INITIAL_METADATA => true, - OP_SEND_MESSAGE => $arg->serialize(), + OP_SEND_MESSAGE => $message_array, OP_SEND_CLOSE_FROM_CLIENT => true]); $this->metadata = $event->metadata; } @@ -62,4 +67,4 @@ class UnaryCall extends AbstractCall { OP_RECV_STATUS_ON_CLIENT => true]); return array($this->deserializeResponse($event->message), $event->status); } -} \ No newline at end of file +} diff --git a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php index a368dd4ee0..531e80aa61 100644 --- a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php +++ b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php @@ -79,15 +79,13 @@ abstract class AbstractGeneratedCodeTest extends PHPUnit_Framework_TestCase { } public function testClientStreaming() { - $num_iter = function() { - for ($i = 0; $i < 7; $i++) { - $num = new math\Num(); - $num->setNum($i); - yield $num; - } - }; - $call = self::$client->Sum($num_iter()); + $call = self::$client->Sum(); $this->assertTrue(is_string($call->getPeer())); + for ($i = 0; $i < 7; $i++) { + $num = new math\Num(); + $num->setNum($i); + $call->write($num); + } list($response, $status) = $call->wait(); $this->assertSame(21, $response->getNum()); $this->assertSame(\Grpc\STATUS_OK, $status->code); diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index bd15ee4303..28782735c0 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -173,7 +173,11 @@ function clientStreaming($stub) { return $request; }, $request_lengths); - list($result, $status) = $stub->StreamingInputCall($requests)->wait(); + $call = $stub->StreamingInputCall(); + foreach ($requests as $request) { + $call->write($request); + } + list($result, $status) = $call->wait(); hardAssert($status->code === Grpc\STATUS_OK, 'Call did not complete successfully'); hardAssert($result->getAggregatedPayloadSize() === 74922, 'aggregated_payload_size was incorrect'); @@ -374,5 +378,6 @@ switch ($args['test_case']) { // messages are sent immediately after metadata is sent. There is // currently no way to cancel before messages are sent. default: + echo "Unsupported test case $args[test_case]\n"; exit(1); } diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php index 4c0cf91d51..bd464f939f 100755 --- a/src/php/tests/unit_tests/EndToEndTest.php +++ b/src/php/tests/unit_tests/EndToEndTest.php @@ -91,6 +91,51 @@ class EndToEndTest extends PHPUnit_Framework_TestCase{ unset($server_call); } + public function testMessageWriteFlags() { + $deadline = Grpc\Timeval::infFuture(); + $req_text = 'message_write_flags_test'; + $status_text = 'xyz'; + $call = new Grpc\Call($this->channel, + 'dummy_method', + $deadline); + + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $req_text, + 'flags' => Grpc\WRITE_NO_COMPRESS], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true + ]); + + $this->assertTrue($event->send_metadata); + $this->assertTrue($event->send_close); + + $event = $this->server->requestCall(); + $this->assertSame('dummy_method', $event->method); + $server_call = $event->call; + + $event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text + ], + ]); + + $event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true + ]); + + $status = $event->status; + $this->assertSame([], $status->metadata); + $this->assertSame(Grpc\STATUS_OK, $status->code); + $this->assertSame($status_text, $status->details); + + unset($call); + unset($server_call); + } + public function testClientServerFullRequestResponse() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; @@ -104,7 +149,7 @@ class EndToEndTest extends PHPUnit_Framework_TestCase{ $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => $req_text + Grpc\OP_SEND_MESSAGE => ['message' => $req_text], ]); $this->assertTrue($event->send_metadata); @@ -117,7 +162,7 @@ class EndToEndTest extends PHPUnit_Framework_TestCase{ $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => $reply_text, + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, diff --git a/src/php/tests/unit_tests/SecureEndToEndTest.php b/src/php/tests/unit_tests/SecureEndToEndTest.php index 60341b983d..d7fca14a0d 100755 --- a/src/php/tests/unit_tests/SecureEndToEndTest.php +++ b/src/php/tests/unit_tests/SecureEndToEndTest.php @@ -107,6 +107,53 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase{ unset($server_call); } + public function testMessageWriteFlags() { + $deadline = Grpc\Timeval::infFuture(); + $req_text = 'message_write_flags_test'; + $status_text = 'xyz'; + $call = new Grpc\Call($this->channel, + 'dummy_method', + $deadline, + $this->host_override); + + $event = $call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_MESSAGE => ['message' => $req_text, + 'flags' => Grpc\WRITE_NO_COMPRESS], + Grpc\OP_SEND_CLOSE_FROM_CLIENT => true + ]); + + $this->assertTrue($event->send_metadata); + $this->assertTrue($event->send_close); + + $event = $this->server->requestCall(); + $this->assertSame('dummy_method', $event->method); + $server_call = $event->call; + + $event = $server_call->startBatch([ + Grpc\OP_SEND_INITIAL_METADATA => [], + Grpc\OP_SEND_STATUS_FROM_SERVER => [ + 'metadata' => [], + 'code' => Grpc\STATUS_OK, + 'details' => $status_text + ], + ]); + + $event = $call->startBatch([ + Grpc\OP_RECV_INITIAL_METADATA => true, + Grpc\OP_RECV_STATUS_ON_CLIENT => true + ]); + + $this->assertSame([], $event->metadata); + $status = $event->status; + $this->assertSame([], $status->metadata); + $this->assertSame(Grpc\STATUS_OK, $status->code); + $this->assertSame($status_text, $status->details); + + unset($call); + unset($server_call); + } + public function testClientServerFullRequestResponse() { $deadline = Grpc\Timeval::infFuture(); $req_text = 'client_server_full_request_response'; @@ -121,7 +168,7 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase{ $event = $call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], Grpc\OP_SEND_CLOSE_FROM_CLIENT => true, - Grpc\OP_SEND_MESSAGE => $req_text + Grpc\OP_SEND_MESSAGE => ['message' => $req_text] ]); $this->assertTrue($event->send_metadata); @@ -134,7 +181,7 @@ class SecureEndToEndTest extends PHPUnit_Framework_TestCase{ $event = $server_call->startBatch([ Grpc\OP_SEND_INITIAL_METADATA => [], - Grpc\OP_SEND_MESSAGE => $reply_text, + Grpc\OP_SEND_MESSAGE => ['message' => $reply_text], Grpc\OP_SEND_STATUS_FROM_SERVER => [ 'metadata' => [], 'code' => Grpc\STATUS_OK, -- cgit v1.2.3 From 5331776c17f775911fedcadfcb530bd46af024ea Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Thu, 27 Aug 2015 09:41:59 -0700 Subject: php: clean up api around flags --- src/php/lib/Grpc/AbstractCall.php | 16 ---------------- src/php/lib/Grpc/BidiStreamingCall.php | 7 ++++--- src/php/lib/Grpc/ClientStreamingCall.php | 7 ++++--- src/php/lib/Grpc/ServerStreamingCall.php | 7 ++++--- src/php/lib/Grpc/UnaryCall.php | 7 ++++--- .../tests/generated_code/AbstractGeneratedCodeTest.php | 12 ++++++++++++ 6 files changed, 28 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/php/lib/Grpc/AbstractCall.php b/src/php/lib/Grpc/AbstractCall.php index 3fdaf2e487..a3c7a9e017 100644 --- a/src/php/lib/Grpc/AbstractCall.php +++ b/src/php/lib/Grpc/AbstractCall.php @@ -92,20 +92,4 @@ abstract class AbstractCall { } return call_user_func($this->deserialize, $value); } - - /** - * Get the list of Grpc Write Flags - * @param array $options an array of options - * @return The list of Grpc Write Flags contained in the input - */ - protected static function getGrpcWriteFlags($options) { - $grpc_write_flags = []; - foreach ([WRITE_BUFFER_HINT, - WRITE_NO_COMPRESS] as $flag) { - if (in_array($flag, $options)) { - $grpc_write_flags[] = $flag; - } - } - return $grpc_write_flags; - } } diff --git a/src/php/lib/Grpc/BidiStreamingCall.php b/src/php/lib/Grpc/BidiStreamingCall.php index 80b7a66a76..2b19f031ec 100644 --- a/src/php/lib/Grpc/BidiStreamingCall.php +++ b/src/php/lib/Grpc/BidiStreamingCall.php @@ -66,12 +66,13 @@ class BidiStreamingCall extends AbstractCall { * Write a single message to the server. This cannot be called after * writesDone is called. * @param ByteBuffer $data The data to write - * @param array $options an array of options + * @param array $options an array of options, possible keys: + * 'flags' => a number */ public function write($data, $options = array()) { $message_array = ['message' => $data->serialize()]; - if ($grpc_write_flags = self::getGrpcWriteFlags($options)) { - $message_array['flags'] = $grpc_write_flags; + if (isset($options['flags'])) { + $message_array['flags'] = $options['flags']; } $this->call->startBatch([OP_SEND_MESSAGE => $message_array]); } diff --git a/src/php/lib/Grpc/ClientStreamingCall.php b/src/php/lib/Grpc/ClientStreamingCall.php index 97c241a087..29b9185411 100644 --- a/src/php/lib/Grpc/ClientStreamingCall.php +++ b/src/php/lib/Grpc/ClientStreamingCall.php @@ -50,12 +50,13 @@ class ClientStreamingCall extends AbstractCall { * Write a single message to the server. This cannot be called after * wait is called. * @param ByteBuffer $data The data to write - * @param array $options an array of options + * @param array $options an array of options, possible keys: + * 'flags' => a number */ public function write($data, $options = array()) { $message_array = ['message' => $data->serialize()]; - if ($grpc_write_flags = self::getGrpcWriteFlags($options)) { - $message_array['flags'] = $grpc_write_flags; + if (isset($options['flags'])) { + $message_array['flags'] = $options['flags']; } $this->call->startBatch([OP_SEND_MESSAGE => $message_array]); } diff --git a/src/php/lib/Grpc/ServerStreamingCall.php b/src/php/lib/Grpc/ServerStreamingCall.php index 159561b43a..a93c1a5d5e 100644 --- a/src/php/lib/Grpc/ServerStreamingCall.php +++ b/src/php/lib/Grpc/ServerStreamingCall.php @@ -42,12 +42,13 @@ class ServerStreamingCall extends AbstractCall { * Start the call * @param $data The data to send * @param array $metadata Metadata to send with the call, if applicable - * @param array $options an array of options + * @param array $options an array of options, possible keys: + * 'flags' => a number */ public function start($data, $metadata = array(), $options = array()) { $message_array = ['message' => $data->serialize()]; - if ($grpc_write_flags = self::getGrpcWriteFlags($options)) { - $message_array['flags'] = $grpc_write_flags; + if (isset($options['flags'])) { + $message_array['flags'] = $options['flags']; } $event = $this->call->startBatch([ OP_SEND_INITIAL_METADATA => $metadata, diff --git a/src/php/lib/Grpc/UnaryCall.php b/src/php/lib/Grpc/UnaryCall.php index 5ca7d9ed65..38af6b1d74 100644 --- a/src/php/lib/Grpc/UnaryCall.php +++ b/src/php/lib/Grpc/UnaryCall.php @@ -42,12 +42,13 @@ class UnaryCall extends AbstractCall { * Start the call * @param $data The data to send * @param array $metadata Metadata to send with the call, if applicable - * @param array $options an array of options + * @param array $options an array of options, possible keys: + * 'flags' => a number */ public function start($data, $metadata = array(), $options = array()) { $message_array = ['message' => $data->serialize()]; - if ($grpc_write_flags = self::getGrpcWriteFlags($options)) { - $message_array['flags'] = $grpc_write_flags; + if (isset($options['flags'])) { + $message_array['flags'] = $options['flags']; } $event = $this->call->startBatch([ OP_SEND_INITIAL_METADATA => $metadata, diff --git a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php index 531e80aa61..9cee188666 100644 --- a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php +++ b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php @@ -51,6 +51,18 @@ abstract class AbstractGeneratedCodeTest extends PHPUnit_Framework_TestCase { $this->assertTrue(is_string(self::$client->getTarget())); } + public function testWriteFlags() { + $div_arg = new math\DivArgs(); + $div_arg->setDividend(7); + $div_arg->setDivisor(4); + $call = self::$client->Div($div_arg, array(), array('flags' => Grpc\WRITE_NO_COMPRESS)); + $this->assertTrue(is_string($call->getPeer())); + list($response, $status) = $call->wait(); + $this->assertSame(1, $response->getQuotient()); + $this->assertSame(3, $response->getRemainder()); + $this->assertSame(\Grpc\STATUS_OK, $status->code); + } + public function testSimpleRequest() { $div_arg = new math\DivArgs(); $div_arg->setDividend(7); -- cgit v1.2.3 From 03e170eaf01b0790feffc582dd1e3d1c451715e4 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 28 Aug 2015 16:11:00 -0700 Subject: php: add cancel_after_begin interop test --- src/php/tests/interop/interop_client.php | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php index 28782735c0..d55d5629b7 100755 --- a/src/php/tests/interop/interop_client.php +++ b/src/php/tests/interop/interop_client.php @@ -250,6 +250,19 @@ function pingPong($stub) { 'Call did not complete successfully'); } +/** + * Run the cancel_after_begin test. + * Passes when run against the Node server as of 2015-08-28 + * @param $stub Stub object that has service methods. + */ +function cancelAfterBegin($stub) { + $call = $stub->StreamingInputCall(); + $call->cancel(); + list($result, $status) = $call->wait(); + hardAssert($status->code === Grpc\STATUS_CANCELLED, + 'Call status was not CANCELLED'); +} + /** * Run the cancel_after_first_response test. * Passes when run against the Node server as of 2015-04-30 @@ -357,6 +370,9 @@ switch ($args['test_case']) { case 'ping_pong': pingPong($stub); break; + case 'cancel_after_begin': + cancelAfterBegin($stub); + break; case 'cancel_after_first_response': cancelAfterFirstResponse($stub); break; @@ -372,11 +388,6 @@ 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: echo "Unsupported test case $args[test_case]\n"; exit(1); -- cgit v1.2.3 From 3ff5ceaae2dd349403738f08d3e5a3fe4c74f1c2 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Tue, 1 Sep 2015 13:22:25 -0700 Subject: php: $metadata at API should be optional --- src/php/lib/Grpc/BidiStreamingCall.php | 2 +- src/php/lib/Grpc/ClientStreamingCall.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/php/lib/Grpc/BidiStreamingCall.php b/src/php/lib/Grpc/BidiStreamingCall.php index 2b19f031ec..c432fd52d8 100644 --- a/src/php/lib/Grpc/BidiStreamingCall.php +++ b/src/php/lib/Grpc/BidiStreamingCall.php @@ -42,7 +42,7 @@ class BidiStreamingCall extends AbstractCall { * Start the call * @param array $metadata Metadata to send with the call, if applicable */ - public function start($metadata) { + public function start($metadata = array()) { $this->call->startBatch([OP_SEND_INITIAL_METADATA => $metadata]); } diff --git a/src/php/lib/Grpc/ClientStreamingCall.php b/src/php/lib/Grpc/ClientStreamingCall.php index 29b9185411..b96c17e751 100644 --- a/src/php/lib/Grpc/ClientStreamingCall.php +++ b/src/php/lib/Grpc/ClientStreamingCall.php @@ -42,7 +42,7 @@ class ClientStreamingCall extends AbstractCall { * Start the call. * @param array $metadata Metadata to send with the call, if applicable */ - public function start($metadata) { + public function start($metadata = array()) { $this->call->startBatch([OP_SEND_INITIAL_METADATA => $metadata]); } -- cgit v1.2.3 From 26883d8dbfb00709d50a41809e4f82f235d8d9b3 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Tue, 1 Sep 2015 13:45:28 -0700 Subject: php: update pecl package.xml --- src/php/ext/grpc/README.md | 22 +++++++---------- src/php/ext/grpc/package.xml | 57 +++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/php/ext/grpc/README.md b/src/php/ext/grpc/README.md index 88d2c481ec..cf38253397 100644 --- a/src/php/ext/grpc/README.md +++ b/src/php/ext/grpc/README.md @@ -4,7 +4,7 @@ gRPC PHP Extension # Requirements * PHP 5.5+ - * [gRPC core library](https://github.com/grpc/grpc) 0.10.0 + * [gRPC core library](https://github.com/grpc/grpc) 0.11.0 # Installation @@ -22,26 +22,20 @@ Clone the gRPC source code repository $ git clone https://github.com/grpc/grpc.git ``` -Build and install the Protocol Buffers compiler (protoc) +Build and install the gRPC C core libraries -``` -$ # from grpc -$ git checkout --track origin/release-0_9 +```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 library +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 -$ # from 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 @@ -55,7 +49,7 @@ $ sudo pecl install grpc Note: before a stable release, you may need to do ```sh -$ sudo pecl install grpc-0.5.1 +$ sudo pecl install grpc-beta ``` OR diff --git a/src/php/ext/grpc/package.xml b/src/php/ext/grpc/package.xml index bc2a05923b..381ae23b45 100644 --- a/src/php/ext/grpc/package.xml +++ b/src/php/ext/grpc/package.xml @@ -10,43 +10,48 @@ grpc-packages@google.com yes - 2015-07-09 - + 2015-09-01 + - 0.5.1 - 0.5.1 + 0.6.0 + 0.6.0 - alpha - alpha + beta + beta BSD -Update to wrap gRPC C Core version 0.10.0 + - support per message compression disable + - expose per-call host override option + - expose connectivity API + - expose channel target and call peer + - add user-agent + - update to wrap gRPC C core library beta version 0.11.0 - + - - - + + + - + - + - + - + - + @@ -93,5 +98,25 @@ First alpha release Update to wrap gRPC C Core version 0.10.0 + + + 0.6.0 + 0.6.0 + + + beta + beta + + 2015-09-01 + BSD + + - support per message compression disable + - expose per-call host override option + - expose connectivity API + - expose channel target and call peer + - add user-agent + - update to wrap gRPC C core library beta version 0.11.0 + + -- cgit v1.2.3 From 29d7be3ce1686621a56f06fb0b77b7e33c4a4cac Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Tue, 1 Sep 2015 13:46:51 -0700 Subject: php: missed a line in doc --- src/php/ext/grpc/README.md | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/php/ext/grpc/README.md b/src/php/ext/grpc/README.md index cf38253397..6e1cb2002f 100644 --- a/src/php/ext/grpc/README.md +++ b/src/php/ext/grpc/README.md @@ -26,6 +26,7 @@ Build and install the gRPC C core libraries ```sh $ cd grpc +$ git checkout --track origin/release-0_11 $ git pull --recurse-submodules && git submodule update --init --recursive $ make $ sudo make install -- cgit v1.2.3 From c84c2e3ab77ca1bf76bfd4e7fb754fc9b6986904 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Wed, 2 Sep 2015 13:58:25 -0700 Subject: fix C# nuget package building --- src/csharp/build_packages.bat | 5 ++++- vsprojects/nuget_package/buildall.bat | 2 +- vsprojects/nuget_package/grpc.native.csharp_ext.nuspec | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat index 255b7469ab..ea2206e760 100644 --- a/src/csharp/build_packages.bat +++ b/src/csharp/build_packages.bat @@ -5,6 +5,9 @@ set VERSION=0.7.0 set CORE_VERSION=0.11.0 set PROTOBUF_VERSION=3.0.0-alpha4 +@rem Packages that depend on prerelease packages (like Google.Protobuf) need to have prerelease suffix as well. +set VERSION_WITH_BETA=0.7.0-beta + @rem Adjust the location of nuget.exe set NUGET=C:\nuget\nuget.exe @@ -20,7 +23,7 @@ endlocal %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% -Properties ProtobufVersion=%PROTOBUF_VERSION% || goto :error +%NUGET% pack Grpc.HealthCheck\Grpc.HealthCheck.nuspec -Symbols -Version %VERSION_WITH_BETA% -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/vsprojects/nuget_package/buildall.bat b/vsprojects/nuget_package/buildall.bat index 80f5235fd9..71befb6920 100644 --- a/vsprojects/nuget_package/buildall.bat +++ b/vsprojects/nuget_package/buildall.bat @@ -39,7 +39,7 @@ endlocal goto :eof :build -msbuild /P:Platform=%1 /P:Configuration=%2 /P:PlatformToolset=%3 /P:OutDir=..\nuget_package\output\%3\%1\%2\ /P:IntDir=..\nuget_package\tmp\%3\%1\%2\ ..\grpc_csharp_ext.sln || goto :eof +msbuild /P:Platform=%1 /P:Configuration=%2 /P:PlatformToolset=%3 /P:OutDir=..\..\nuget_package\output\%3\%1\%2\ /P:IntDir=..\..\nuget_package\tmp\%3\%1\%2\ ..\grpc_csharp_ext.sln || goto :eof goto :eof diff --git a/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec b/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec index d2ac440dab..39791a5d8e 100644 --- a/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec +++ b/vsprojects/nuget_package/grpc.native.csharp_ext.nuspec @@ -2,21 +2,21 @@ grpc.native.csharp_ext - 0.10.0 + $version$ Google Inc. grpc-packages https://github.com/grpc/grpc/blob/master/LICENSE http://github.com/grpc/grpc false Native extension needed by gRPC C# library. This is not the package you are looking for, it is only meant to be used as a dependency. - Release of gRPC C core 0.10.0 libraries. + Release of gRPC C core $version$ libraries. Copyright 2015 gRPC C# Native Extension Native library required by gRPC C# gRPC native - + -- cgit v1.2.3 From 69210e598be64274def39c7da70129cffffe8c2a Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 2 Sep 2015 19:24:41 +0000 Subject: Add code and details to base.Outcome It may seem weird that code and details would travel along two paths now instead of one but it makes sense after considering that sometimes the code and details are application data from the remote application and sometimes they are transport data from the transport between the local and remote applications. --- .../grpcio/grpc/framework/core/_constants.py | 17 ++++----- src/python/grpcio/grpc/framework/core/_context.py | 10 +++--- src/python/grpcio/grpc/framework/core/_emission.py | 8 +++-- src/python/grpcio/grpc/framework/core/_end.py | 18 +++++----- .../grpcio/grpc/framework/core/_expiration.py | 4 ++- .../grpcio/grpc/framework/core/_ingestion.py | 29 ++++++++------- .../grpcio/grpc/framework/core/_interfaces.py | 40 ++++++++++----------- .../grpcio/grpc/framework/core/_operation.py | 8 ++--- .../grpcio/grpc/framework/core/_reception.py | 32 ++++++++++------- .../grpcio/grpc/framework/core/_termination.py | 32 ++++++++++++----- .../grpcio/grpc/framework/core/_transmission.py | 35 +++++++++++------- .../grpcio/grpc/framework/core/_utilities.py | 8 +++++ src/python/grpcio/grpc/framework/crust/_control.py | 31 +++++++++------- .../grpcio/grpc/framework/interfaces/base/base.py | 41 ++++++++++++++-------- .../framework/interfaces/base/_control.py | 20 +++++------ .../framework/interfaces/base/_sequence.py | 19 +++++----- .../framework/interfaces/base/test_cases.py | 14 ++++---- 17 files changed, 218 insertions(+), 148 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/framework/core/_constants.py b/src/python/grpcio/grpc/framework/core/_constants.py index d3be3a4c4a..0f47cb48e0 100644 --- a/src/python/grpcio/grpc/framework/core/_constants.py +++ b/src/python/grpcio/grpc/framework/core/_constants.py @@ -44,14 +44,15 @@ TICKET_SUBSCRIPTION_FOR_BASE_SUBSCRIPTION_KIND = { # ticket should be sent to the other side in the event of such an # outcome. ABORTION_OUTCOME_TO_TICKET_TERMINATION = { - base.Outcome.CANCELLED: links.Ticket.Termination.CANCELLATION, - base.Outcome.EXPIRED: links.Ticket.Termination.EXPIRATION, - base.Outcome.LOCAL_SHUTDOWN: links.Ticket.Termination.SHUTDOWN, - base.Outcome.REMOTE_SHUTDOWN: None, - base.Outcome.RECEPTION_FAILURE: links.Ticket.Termination.RECEPTION_FAILURE, - base.Outcome.TRANSMISSION_FAILURE: None, - base.Outcome.LOCAL_FAILURE: links.Ticket.Termination.LOCAL_FAILURE, - base.Outcome.REMOTE_FAILURE: links.Ticket.Termination.REMOTE_FAILURE, + base.Outcome.Kind.CANCELLED: links.Ticket.Termination.CANCELLATION, + base.Outcome.Kind.EXPIRED: links.Ticket.Termination.EXPIRATION, + base.Outcome.Kind.LOCAL_SHUTDOWN: links.Ticket.Termination.SHUTDOWN, + base.Outcome.Kind.REMOTE_SHUTDOWN: None, + base.Outcome.Kind.RECEPTION_FAILURE: + links.Ticket.Termination.RECEPTION_FAILURE, + base.Outcome.Kind.TRANSMISSION_FAILURE: None, + base.Outcome.Kind.LOCAL_FAILURE: links.Ticket.Termination.LOCAL_FAILURE, + base.Outcome.Kind.REMOTE_FAILURE: links.Ticket.Termination.REMOTE_FAILURE, } INTERNAL_ERROR_LOG_MESSAGE = ':-( RPC Framework (Core) internal error! )-:' diff --git a/src/python/grpcio/grpc/framework/core/_context.py b/src/python/grpcio/grpc/framework/core/_context.py index 76b3534530..a346e9d478 100644 --- a/src/python/grpcio/grpc/framework/core/_context.py +++ b/src/python/grpcio/grpc/framework/core/_context.py @@ -33,6 +33,7 @@ import time # _interfaces is referenced from specification in this module. from grpc.framework.core import _interfaces # pylint: disable=unused-import +from grpc.framework.core import _utilities from grpc.framework.interfaces.base import base @@ -56,11 +57,12 @@ class OperationContext(base.OperationContext): self._transmission_manager = transmission_manager self._expiration_manager = expiration_manager - def _abort(self, outcome): + def _abort(self, outcome_kind): with self._lock: if self._termination_manager.outcome is None: + outcome = _utilities.Outcome(outcome_kind, None, None) self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome, None, None) + self._transmission_manager.abort(outcome) self._expiration_manager.terminate() def outcome(self): @@ -85,8 +87,8 @@ class OperationContext(base.OperationContext): def cancel(self): """See base.OperationContext.cancel for specification.""" - self._abort(base.Outcome.CANCELLED) + self._abort(base.Outcome.Kind.CANCELLED) def fail(self, exception): """See base.OperationContext.fail for specification.""" - self._abort(base.Outcome.LOCAL_FAILURE) + self._abort(base.Outcome.Kind.LOCAL_FAILURE) diff --git a/src/python/grpcio/grpc/framework/core/_emission.py b/src/python/grpcio/grpc/framework/core/_emission.py index 2d7b2e2f10..8ab59dc3e5 100644 --- a/src/python/grpcio/grpc/framework/core/_emission.py +++ b/src/python/grpcio/grpc/framework/core/_emission.py @@ -30,6 +30,7 @@ """State and behavior for handling emitted values.""" from grpc.framework.core import _interfaces +from grpc.framework.core import _utilities from grpc.framework.interfaces.base import base @@ -81,9 +82,10 @@ class EmissionManager(_interfaces.EmissionManager): payload_present and self._completion_seen or completion_present and self._completion_seen or allowance_present and allowance <= 0): - self._termination_manager.abort(base.Outcome.LOCAL_FAILURE) - self._transmission_manager.abort( - base.Outcome.LOCAL_FAILURE, None, None) + outcome = _utilities.Outcome( + base.Outcome.Kind.LOCAL_FAILURE, None, None) + self._termination_manager.abort(outcome) + self._transmission_manager.abort(outcome) self._expiration_manager.terminate() else: self._initial_metadata_seen |= initial_metadata_present diff --git a/src/python/grpcio/grpc/framework/core/_end.py b/src/python/grpcio/grpc/framework/core/_end.py index f57cde4e58..336e9c21fd 100644 --- a/src/python/grpcio/grpc/framework/core/_end.py +++ b/src/python/grpcio/grpc/framework/core/_end.py @@ -69,7 +69,7 @@ class _Cycle(object): def _abort(operations): for operation in operations: - operation.abort(base.Outcome.LOCAL_SHUTDOWN) + operation.abort(base.Outcome.Kind.LOCAL_SHUTDOWN) def _cancel_futures(futures): @@ -90,19 +90,19 @@ def _termination_action(lock, stats, operation_id, cycle): Args: lock: A lock to hold during the termination action. - states: A mapping from base.Outcome values to integers to increment with - the outcome given to the termination action. + stats: A mapping from base.Outcome.Kind values to integers to increment + with the outcome kind given to the termination action. operation_id: The operation ID for the termination action. cycle: A _Cycle value to be updated during the termination action. Returns: - A callable that takes an operation outcome as its sole parameter and that - should be used as the termination action for the operation associated - with the given operation ID. + A callable that takes an operation outcome kind as its sole parameter and + that should be used as the termination action for the operation + associated with the given operation ID. """ - def termination_action(outcome): + def termination_action(outcome_kind): with lock: - stats[outcome] += 1 + stats[outcome_kind] += 1 cycle.operations.pop(operation_id, None) if not cycle.operations: for action in cycle.idle_actions: @@ -127,7 +127,7 @@ class _End(End): self._lock = threading.Condition() self._servicer_package = servicer_package - self._stats = {outcome: 0 for outcome in base.Outcome} + self._stats = {outcome_kind: 0 for outcome_kind in base.Outcome.Kind} self._mate = None diff --git a/src/python/grpcio/grpc/framework/core/_expiration.py b/src/python/grpcio/grpc/framework/core/_expiration.py index d8690b3a02..ded0ab6bce 100644 --- a/src/python/grpcio/grpc/framework/core/_expiration.py +++ b/src/python/grpcio/grpc/framework/core/_expiration.py @@ -32,6 +32,7 @@ import time from grpc.framework.core import _interfaces +from grpc.framework.core import _utilities from grpc.framework.foundation import later from grpc.framework.interfaces.base import base @@ -73,7 +74,8 @@ class _ExpirationManager(_interfaces.ExpirationManager): if self._future is not None and index == self._index: self._future = None self._termination_manager.expire() - self._transmission_manager.abort(base.Outcome.EXPIRED, None, None) + self._transmission_manager.abort( + _utilities.Outcome(base.Outcome.Kind.EXPIRED, None, None)) return expire def start(self): diff --git a/src/python/grpcio/grpc/framework/core/_ingestion.py b/src/python/grpcio/grpc/framework/core/_ingestion.py index 766d57f931..9a7959a2dd 100644 --- a/src/python/grpcio/grpc/framework/core/_ingestion.py +++ b/src/python/grpcio/grpc/framework/core/_ingestion.py @@ -35,6 +35,7 @@ import enum from grpc.framework.core import _constants from grpc.framework.core import _interfaces +from grpc.framework.core import _utilities from grpc.framework.foundation import abandonment from grpc.framework.foundation import callable_util from grpc.framework.interfaces.base import base @@ -46,7 +47,7 @@ _INGESTION_EXCEPTION_LOG_MESSAGE = 'Exception during ingestion!' class _SubscriptionCreation( collections.namedtuple( '_SubscriptionCreation', - ('kind', 'subscription', 'code', 'message',))): + ('kind', 'subscription', 'code', 'details',))): """A sum type for the outcome of ingestion initialization. Attributes: @@ -56,7 +57,7 @@ class _SubscriptionCreation( code: A code value to be sent to the other side of the operation along with an indication that the operation is being aborted due to an error on the remote side of the operation. Only present if kind is Kind.REMOTE_ERROR. - message: A message value to be sent to the other side of the operation + details: A details value to be sent to the other side of the operation along with an indication that the operation is being aborted due to an error on the remote side of the operation. Only present if kind is Kind.REMOTE_ERROR. @@ -190,11 +191,13 @@ class _IngestionManager(_interfaces.IngestionManager): self._pending_payloads = None self._pending_completion = None - def _abort_and_notify(self, outcome, code, message): + def _abort_and_notify(self, outcome_kind, code, details): self._abort_internal_only() - self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome, code, message) - self._expiration_manager.terminate() + if self._termination_manager.outcome is None: + outcome = _utilities.Outcome(outcome_kind, code, details) + self._termination_manager.abort(outcome) + self._transmission_manager.abort(outcome) + self._expiration_manager.terminate() def _operator_next(self): """Computes the next step for full-subscription ingestion. @@ -250,12 +253,13 @@ class _IngestionManager(_interfaces.IngestionManager): else: with self._lock: if self._termination_manager.outcome is None: - self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) + self._abort_and_notify( + base.Outcome.Kind.LOCAL_FAILURE, None, None) return else: with self._lock: if self._termination_manager.outcome is None: - self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) + self._abort_and_notify(base.Outcome.Kind.LOCAL_FAILURE, None, None) return def _operator_post_create(self, subscription): @@ -279,17 +283,18 @@ class _IngestionManager(_interfaces.IngestionManager): if outcome.return_value is None: with self._lock: if self._termination_manager.outcome is None: - self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) + self._abort_and_notify(base.Outcome.Kind.LOCAL_FAILURE, None, None) elif outcome.return_value.kind is _SubscriptionCreation.Kind.ABANDONED: with self._lock: if self._termination_manager.outcome is None: - self._abort_and_notify(base.Outcome.LOCAL_FAILURE, None, None) + self._abort_and_notify(base.Outcome.Kind.LOCAL_FAILURE, None, None) elif outcome.return_value.kind is _SubscriptionCreation.Kind.REMOTE_ERROR: code = outcome.return_value.code - message = outcome.return_value.message + details = outcome.return_value.details with self._lock: if self._termination_manager.outcome is None: - self._abort_and_notify(base.Outcome.REMOTE_FAILURE, code, message) + self._abort_and_notify( + base.Outcome.Kind.REMOTE_FAILURE, code, details) elif outcome.return_value.subscription.kind is base.Subscription.Kind.FULL: self._operator_post_create(outcome.return_value.subscription) else: diff --git a/src/python/grpcio/grpc/framework/core/_interfaces.py b/src/python/grpcio/grpc/framework/core/_interfaces.py index deb5f34f9b..2a534cb7e7 100644 --- a/src/python/grpcio/grpc/framework/core/_interfaces.py +++ b/src/python/grpcio/grpc/framework/core/_interfaces.py @@ -50,13 +50,13 @@ class TerminationManager(object): If the operation has already terminated the callback will not be called. Args: - callback: A callable that will be passed an interfaces.Outcome value. + callback: A callable that will be passed a base.Outcome value. Returns: None if the operation has not yet terminated and the passed callback will - be called when it does, or a base.Outcome value describing the operation - termination if the operation has terminated and the callback will not be - called as a result of this method call. + be called when it does, or a base.Outcome value describing the + operation termination if the operation has terminated and the callback + will not be called as a result of this method call. """ raise NotImplementedError() @@ -76,8 +76,13 @@ class TerminationManager(object): raise NotImplementedError() @abc.abstractmethod - def reception_complete(self): - """Indicates that reception from the other side is complete.""" + def reception_complete(self, code, details): + """Indicates that reception from the other side is complete. + + Args: + code: An application-specific code value. + details: An application-specific details value. + """ raise NotImplementedError() @abc.abstractmethod @@ -95,7 +100,7 @@ class TerminationManager(object): """Indicates that the operation must abort for the indicated reason. Args: - outcome: An interfaces.Outcome indicating operation abortion. + outcome: A base.Outcome indicating operation abortion. """ raise NotImplementedError() @@ -155,19 +160,13 @@ class TransmissionManager(object): raise NotImplementedError() @abc.abstractmethod - def abort(self, outcome, code, message): + def abort(self, outcome): """Indicates that the operation has aborted. Args: - outcome: An interfaces.Outcome for the operation. If None, indicates that - the operation abortion should not be communicated to the other side of - the operation. - code: A code value to communicate to the other side of the operation - along with indication of operation abortion. May be None, and has no - effect if outcome is None. - message: A message value to communicate to the other side of the - operation along with indication of operation abortion. May be None, and - has no effect if outcome is None. + outcome: A base.Outcome for the operation. If None, indicates that the + operation abortion should not be communicated to the other side of the + operation. """ raise NotImplementedError() @@ -279,8 +278,7 @@ class ReceptionManager(object): """Handle a ticket from the other side of the operation. Args: - ticket: An interfaces.BackToFrontTicket or interfaces.FrontToBackTicket - appropriate to this end of the operation and this object. + ticket: A links.Ticket for the operation. """ raise NotImplementedError() @@ -305,10 +303,10 @@ class Operation(object): raise NotImplementedError() @abc.abstractmethod - def abort(self, outcome): + def abort(self, outcome_kind): """Aborts the operation. Args: - outcome: A base.Outcome value indicating operation abortion. + outcome_kind: A base.Outcome.Kind value indicating operation abortion. """ raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/core/_operation.py b/src/python/grpcio/grpc/framework/core/_operation.py index cc873c03f9..f5679d0356 100644 --- a/src/python/grpcio/grpc/framework/core/_operation.py +++ b/src/python/grpcio/grpc/framework/core/_operation.py @@ -31,7 +31,6 @@ import threading -# _utilities is referenced from specification in this module. from grpc.framework.core import _context from grpc.framework.core import _emission from grpc.framework.core import _expiration @@ -40,7 +39,7 @@ from grpc.framework.core import _interfaces from grpc.framework.core import _reception from grpc.framework.core import _termination from grpc.framework.core import _transmission -from grpc.framework.core import _utilities # pylint: disable=unused-import +from grpc.framework.core import _utilities class _EasyOperation(_interfaces.Operation): @@ -75,11 +74,12 @@ class _EasyOperation(_interfaces.Operation): with self._lock: self._reception_manager.receive_ticket(ticket) - def abort(self, outcome): + def abort(self, outcome_kind): with self._lock: if self._termination_manager.outcome is None: + outcome = _utilities.Outcome(outcome_kind, None, None) self._termination_manager.abort(outcome) - self._transmission_manager.abort(outcome, None, None) + self._transmission_manager.abort(outcome) self._expiration_manager.terminate() diff --git a/src/python/grpcio/grpc/framework/core/_reception.py b/src/python/grpcio/grpc/framework/core/_reception.py index 1cebe3874b..d374cf0c8c 100644 --- a/src/python/grpcio/grpc/framework/core/_reception.py +++ b/src/python/grpcio/grpc/framework/core/_reception.py @@ -30,21 +30,26 @@ """State and behavior for ticket reception.""" from grpc.framework.core import _interfaces +from grpc.framework.core import _utilities from grpc.framework.interfaces.base import base from grpc.framework.interfaces.base import utilities from grpc.framework.interfaces.links import links -_REMOTE_TICKET_TERMINATION_TO_LOCAL_OUTCOME = { - links.Ticket.Termination.CANCELLATION: base.Outcome.CANCELLED, - links.Ticket.Termination.EXPIRATION: base.Outcome.EXPIRED, - links.Ticket.Termination.SHUTDOWN: base.Outcome.REMOTE_SHUTDOWN, - links.Ticket.Termination.RECEPTION_FAILURE: base.Outcome.RECEPTION_FAILURE, +_REMOTE_TICKET_TERMINATION_TO_LOCAL_OUTCOME_KIND = { + links.Ticket.Termination.CANCELLATION: base.Outcome.Kind.CANCELLED, + links.Ticket.Termination.EXPIRATION: base.Outcome.Kind.EXPIRED, + links.Ticket.Termination.SHUTDOWN: base.Outcome.Kind.REMOTE_SHUTDOWN, + links.Ticket.Termination.RECEPTION_FAILURE: + base.Outcome.Kind.RECEPTION_FAILURE, links.Ticket.Termination.TRANSMISSION_FAILURE: - base.Outcome.TRANSMISSION_FAILURE, - links.Ticket.Termination.LOCAL_FAILURE: base.Outcome.REMOTE_FAILURE, - links.Ticket.Termination.REMOTE_FAILURE: base.Outcome.LOCAL_FAILURE, + base.Outcome.Kind.TRANSMISSION_FAILURE, + links.Ticket.Termination.LOCAL_FAILURE: base.Outcome.Kind.REMOTE_FAILURE, + links.Ticket.Termination.REMOTE_FAILURE: base.Outcome.Kind.LOCAL_FAILURE, } +_RECEPTION_FAILURE_OUTCOME = _utilities.Outcome( + base.Outcome.Kind.RECEPTION_FAILURE, None, None) + class ReceptionManager(_interfaces.ReceptionManager): """A ReceptionManager based around a _Receiver passed to it.""" @@ -73,7 +78,7 @@ class ReceptionManager(_interfaces.ReceptionManager): self._aborted = True if self._termination_manager.outcome is None: self._termination_manager.abort(outcome) - self._transmission_manager.abort(None, None, None) + self._transmission_manager.abort(None) self._expiration_manager.terminate() def _sequence_failure(self, ticket): @@ -102,6 +107,7 @@ class ReceptionManager(_interfaces.ReceptionManager): else: completion = utilities.completion( ticket.terminal_metadata, ticket.code, ticket.message) + self._termination_manager.reception_complete(ticket.code, ticket.message) self._ingestion_manager.advance( ticket.initial_metadata, ticket.payload, completion, ticket.allowance) if ticket.allowance is not None: @@ -129,10 +135,12 @@ class ReceptionManager(_interfaces.ReceptionManager): if self._aborted: return elif self._sequence_failure(ticket): - self._abort(base.Outcome.RECEPTION_FAILURE) + self._abort(_RECEPTION_FAILURE_OUTCOME) elif ticket.termination not in (None, links.Ticket.Termination.COMPLETION): - outcome = _REMOTE_TICKET_TERMINATION_TO_LOCAL_OUTCOME[ticket.termination] - self._abort(outcome) + outcome_kind = _REMOTE_TICKET_TERMINATION_TO_LOCAL_OUTCOME_KIND[ + ticket.termination] + self._abort( + _utilities.Outcome(outcome_kind, ticket.code, ticket.message)) elif ticket.sequence_number == self._lowest_unseen_sequence_number: self._process(ticket) else: diff --git a/src/python/grpcio/grpc/framework/core/_termination.py b/src/python/grpcio/grpc/framework/core/_termination.py index ad9f6123d8..3bf7ade30f 100644 --- a/src/python/grpcio/grpc/framework/core/_termination.py +++ b/src/python/grpcio/grpc/framework/core/_termination.py @@ -33,6 +33,7 @@ import abc from grpc.framework.core import _constants from grpc.framework.core import _interfaces +from grpc.framework.core import _utilities from grpc.framework.foundation import callable_util from grpc.framework.interfaces.base import base @@ -74,7 +75,8 @@ class _TerminationManager(TerminationManager): predicate: One of _invocation_completion_predicate or _service_completion_predicate to be used to determine when the operation has completed. - action: A behavior to pass the operation outcome on operation termination. + action: A behavior to pass the operation outcome's kind on operation + termination. pool: A thread pool. """ self._predicate = predicate @@ -82,14 +84,19 @@ class _TerminationManager(TerminationManager): self._pool = pool self._expiration_manager = None - self.outcome = None self._callbacks = [] + self._code = None + self._details = None self._emission_complete = False self._transmission_complete = False self._reception_complete = False self._ingestion_complete = False + # The None-ness of outcome is the operation-wide record of whether and how + # the operation has terminated. + self.outcome = None + def set_expiration_manager(self, expiration_manager): self._expiration_manager = expiration_manager @@ -106,8 +113,8 @@ class _TerminationManager(TerminationManager): act = callable_util.with_exceptions_logged( self._action, _constants.INTERNAL_ERROR_LOG_MESSAGE) - if outcome is base.Outcome.LOCAL_FAILURE: - self._pool.submit(act, outcome) + if outcome.kind is base.Outcome.Kind.LOCAL_FAILURE: + self._pool.submit(act, base.Outcome.Kind.LOCAL_FAILURE) else: def call_callbacks_and_act(callbacks, outcome): for callback in callbacks: @@ -115,9 +122,11 @@ class _TerminationManager(TerminationManager): callback, _constants.TERMINATION_CALLBACK_EXCEPTION_LOG_MESSAGE, outcome) if callback_outcome.exception is not None: - outcome = base.Outcome.LOCAL_FAILURE + act_outcome_kind = base.Outcome.Kind.LOCAL_FAILURE break - act(outcome) + else: + act_outcome_kind = outcome.kind + act(act_outcome_kind) self._pool.submit( callable_util.with_exceptions_logged( @@ -132,7 +141,9 @@ class _TerminationManager(TerminationManager): if self._predicate( self._emission_complete, self._transmission_complete, self._reception_complete, self._ingestion_complete): - self._terminate_and_notify(base.Outcome.COMPLETED) + self._terminate_and_notify( + _utilities.Outcome( + base.Outcome.Kind.COMPLETED, self._code, self._details)) return True else: return False @@ -163,10 +174,12 @@ class _TerminationManager(TerminationManager): else: return False - def reception_complete(self): + def reception_complete(self, code, details): """See superclass method for specification.""" if self.outcome is None: self._reception_complete = True + self._code = code + self._details = details self._perhaps_complete() def ingestion_complete(self): @@ -177,7 +190,8 @@ class _TerminationManager(TerminationManager): def expire(self): """See _interfaces.TerminationManager.expire for specification.""" - self._terminate_internal_only(base.Outcome.EXPIRED) + self._terminate_internal_only( + _utilities.Outcome(base.Outcome.Kind.EXPIRED, None, None)) def abort(self, outcome): """See _interfaces.TerminationManager.abort for specification.""" diff --git a/src/python/grpcio/grpc/framework/core/_transmission.py b/src/python/grpcio/grpc/framework/core/_transmission.py index 202a71dd71..8f852cfe9f 100644 --- a/src/python/grpcio/grpc/framework/core/_transmission.py +++ b/src/python/grpcio/grpc/framework/core/_transmission.py @@ -34,12 +34,16 @@ import enum from grpc.framework.core import _constants from grpc.framework.core import _interfaces +from grpc.framework.core import _utilities from grpc.framework.foundation import callable_util from grpc.framework.interfaces.base import base from grpc.framework.interfaces.links import links _TRANSMISSION_EXCEPTION_LOG_MESSAGE = 'Exception during transmission!' +_TRANSMISSION_FAILURE_OUTCOME = _utilities.Outcome( + base.Outcome.Kind.TRANSMISSION_FAILURE, None, None) + def _explode_completion(completion): if completion is None: @@ -194,7 +198,7 @@ class TransmissionManager(_interfaces.TransmissionManager): with self._lock: self._abort = _ABORTED_NO_NOTIFY if self._termination_manager.outcome is None: - self._termination_manager.abort(base.Outcome.TRANSMISSION_FAILURE) + self._termination_manager.abort(_TRANSMISSION_FAILURE_OUTCOME) self._expiration_manager.terminate() return @@ -307,19 +311,24 @@ class TransmissionManager(_interfaces.TransmissionManager): self._remote_complete = True self._local_allowance = 0 - def abort(self, outcome, code, message): + def abort(self, outcome): """See _interfaces.TransmissionManager.abort for specification.""" if self._abort.kind is _Abort.Kind.NOT_ABORTED: - termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION.get( - outcome) - if termination is None: + if outcome is None: self._abort = _ABORTED_NO_NOTIFY - elif self._transmitting: - self._abort = _Abort( - _Abort.Kind.ABORTED_NOTIFY_NEEDED, termination, code, message) else: - ticket = links.Ticket( - self._operation_id, self._lowest_unused_sequence_number, None, - None, None, None, None, None, None, None, code, message, - termination, None) - self._transmit(ticket) + termination = _constants.ABORTION_OUTCOME_TO_TICKET_TERMINATION.get( + outcome.kind) + if termination is None: + self._abort = _ABORTED_NO_NOTIFY + elif self._transmitting: + self._abort = _Abort( + _Abort.Kind.ABORTED_NOTIFY_NEEDED, termination, outcome.code, + outcome.details) + else: + ticket = links.Ticket( + self._operation_id, self._lowest_unused_sequence_number, None, + None, None, None, None, None, None, None, outcome.code, + outcome.details, termination, None) + self._transmit(ticket) + self._abort = _ABORTED_NO_NOTIFY diff --git a/src/python/grpcio/grpc/framework/core/_utilities.py b/src/python/grpcio/grpc/framework/core/_utilities.py index 5b0d798751..abedc727e4 100644 --- a/src/python/grpcio/grpc/framework/core/_utilities.py +++ b/src/python/grpcio/grpc/framework/core/_utilities.py @@ -31,6 +31,8 @@ import collections +from grpc.framework.interfaces.base import base + class ServicerPackage( collections.namedtuple( @@ -44,3 +46,9 @@ class ServicerPackage( maximum_timeout: A float indicating the maximum length of time in seconds to allow for an operation. """ + + +class Outcome( + base.Outcome, + collections.namedtuple('Outcome', ('kind', 'code', 'details',))): + """A trivial implementation of base.Outcome.""" diff --git a/src/python/grpcio/grpc/framework/crust/_control.py b/src/python/grpcio/grpc/framework/crust/_control.py index 01de3c15bd..7bddf46a57 100644 --- a/src/python/grpcio/grpc/framework/crust/_control.py +++ b/src/python/grpcio/grpc/framework/crust/_control.py @@ -110,30 +110,31 @@ class _Termination( _NOT_TERMINATED = _Termination(False, None, None) -_OPERATION_OUTCOME_TO_TERMINATION_CONSTRUCTOR = { - base.Outcome.COMPLETED: lambda *unused_args: _Termination(True, None, None), - base.Outcome.CANCELLED: lambda *args: _Termination( +_OPERATION_OUTCOME_KIND_TO_TERMINATION_CONSTRUCTOR = { + base.Outcome.Kind.COMPLETED: lambda *unused_args: _Termination( + True, None, None), + base.Outcome.Kind.CANCELLED: lambda *args: _Termination( True, face.Abortion(face.Abortion.Kind.CANCELLED, *args), face.CancellationError(*args)), - base.Outcome.EXPIRED: lambda *args: _Termination( + base.Outcome.Kind.EXPIRED: lambda *args: _Termination( True, face.Abortion(face.Abortion.Kind.EXPIRED, *args), face.ExpirationError(*args)), - base.Outcome.LOCAL_SHUTDOWN: lambda *args: _Termination( + base.Outcome.Kind.LOCAL_SHUTDOWN: lambda *args: _Termination( True, face.Abortion(face.Abortion.Kind.LOCAL_SHUTDOWN, *args), face.LocalShutdownError(*args)), - base.Outcome.REMOTE_SHUTDOWN: lambda *args: _Termination( + base.Outcome.Kind.REMOTE_SHUTDOWN: lambda *args: _Termination( True, face.Abortion(face.Abortion.Kind.REMOTE_SHUTDOWN, *args), face.RemoteShutdownError(*args)), - base.Outcome.RECEPTION_FAILURE: lambda *args: _Termination( + base.Outcome.Kind.RECEPTION_FAILURE: lambda *args: _Termination( True, face.Abortion(face.Abortion.Kind.NETWORK_FAILURE, *args), face.NetworkError(*args)), - base.Outcome.TRANSMISSION_FAILURE: lambda *args: _Termination( + base.Outcome.Kind.TRANSMISSION_FAILURE: lambda *args: _Termination( True, face.Abortion(face.Abortion.Kind.NETWORK_FAILURE, *args), face.NetworkError(*args)), - base.Outcome.LOCAL_FAILURE: lambda *args: _Termination( + base.Outcome.Kind.LOCAL_FAILURE: lambda *args: _Termination( True, face.Abortion(face.Abortion.Kind.LOCAL_FAILURE, *args), face.LocalError(*args)), - base.Outcome.REMOTE_FAILURE: lambda *args: _Termination( + base.Outcome.Kind.REMOTE_FAILURE: lambda *args: _Termination( True, face.Abortion(face.Abortion.Kind.REMOTE_FAILURE, *args), face.RemoteError(*args)), } @@ -247,13 +248,17 @@ class Rendezvous(base.Operator, future.Future, stream.Consumer, face.Call): else: initial_metadata = self._up_initial_metadata.value if self._up_completion.kind is _Awaited.Kind.NOT_YET_ARRIVED: - terminal_metadata, code, details = None, None, None + terminal_metadata = None else: terminal_metadata = self._up_completion.value.terminal_metadata + if outcome.kind is base.Outcome.Kind.COMPLETED: code = self._up_completion.value.code details = self._up_completion.value.message - self._termination = _OPERATION_OUTCOME_TO_TERMINATION_CONSTRUCTOR[ - outcome](initial_metadata, terminal_metadata, code, details) + else: + code = outcome.code + details = outcome.details + self._termination = _OPERATION_OUTCOME_KIND_TO_TERMINATION_CONSTRUCTOR[ + outcome.kind](initial_metadata, terminal_metadata, code, details) self._condition.notify_all() diff --git a/src/python/grpcio/grpc/framework/interfaces/base/base.py b/src/python/grpcio/grpc/framework/interfaces/base/base.py index bc52efb4c5..0d9d6b464e 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/base.py +++ b/src/python/grpcio/grpc/framework/interfaces/base/base.py @@ -40,7 +40,7 @@ applications choose. # threading is referenced from specification in this module. import abc import enum -import threading +import threading # pylint: disable=unused-import # abandonment is referenced from specification in this module. from grpc.framework.foundation import abandonment # pylint: disable=unused-import @@ -69,19 +69,30 @@ class NoSuchMethodError(Exception): self.details = details -@enum.unique -class Outcome(enum.Enum): - """Operation outcomes.""" +class Outcome(object): + """The outcome of an operation. - COMPLETED = 'completed' - CANCELLED = 'cancelled' - EXPIRED = 'expired' - LOCAL_SHUTDOWN = 'local shutdown' - REMOTE_SHUTDOWN = 'remote shutdown' - RECEPTION_FAILURE = 'reception failure' - TRANSMISSION_FAILURE = 'transmission failure' - LOCAL_FAILURE = 'local failure' - REMOTE_FAILURE = 'remote failure' + Attributes: + kind: A Kind value coarsely identifying how the operation terminated. + code: An application-specific code value or None if no such value was + provided. + details: An application-specific details value or None if no such value was + provided. + """ + + @enum.unique + class Kind(enum.Enum): + """Ways in which an operation can terminate.""" + + COMPLETED = 'completed' + CANCELLED = 'cancelled' + EXPIRED = 'expired' + LOCAL_SHUTDOWN = 'local shutdown' + REMOTE_SHUTDOWN = 'remote shutdown' + RECEPTION_FAILURE = 'reception failure' + TRANSMISSION_FAILURE = 'transmission failure' + LOCAL_FAILURE = 'local failure' + REMOTE_FAILURE = 'remote failure' class Completion(object): @@ -294,8 +305,8 @@ class End(object): """Reports the number of terminated operations broken down by outcome. Returns: - A dictionary from Outcome value to an integer identifying the number - of operations that terminated with that outcome. + A dictionary from Outcome.Kind value to an integer identifying the number + of operations that terminated with that outcome kind. """ raise NotImplementedError() diff --git a/src/python/grpcio_test/grpc_test/framework/interfaces/base/_control.py b/src/python/grpcio_test/grpc_test/framework/interfaces/base/_control.py index e4d2a7a0d7..46a01876d8 100644 --- a/src/python/grpcio_test/grpc_test/framework/interfaces/base/_control.py +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/base/_control.py @@ -236,8 +236,8 @@ class Instruction( collections.namedtuple( 'Instruction', ('kind', 'advance_args', 'advance_kwargs', 'conclude_success', - 'conclude_message', 'conclude_invocation_outcome', - 'conclude_service_outcome',))): + 'conclude_message', 'conclude_invocation_outcome_kind', + 'conclude_service_outcome_kind',))): """""" @enum.unique @@ -532,24 +532,24 @@ class _SequenceController(Controller): self._state.service_side_outcome = outcome if self._todo is not None or self._remaining_elements: self._failed('Premature service-side outcome %s!' % (outcome,)) - elif outcome is not self._sequence.outcome.service: + elif outcome.kind is not self._sequence.outcome_kinds.service: self._failed( - 'Incorrect service-side outcome: %s should have been %s' % ( - outcome, self._sequence.outcome.service)) + 'Incorrect service-side outcome kind: %s should have been %s' % ( + outcome.kind, self._sequence.outcome_kinds.service)) elif self._state.invocation_side_outcome is not None: - self._passed(self._state.invocation_side_outcome, outcome) + self._passed(self._state.invocation_side_outcome.kind, outcome.kind) def invocation_on_termination(self, outcome): with self._condition: self._state.invocation_side_outcome = outcome if self._todo is not None or self._remaining_elements: self._failed('Premature invocation-side outcome %s!' % (outcome,)) - elif outcome is not self._sequence.outcome.invocation: + elif outcome.kind is not self._sequence.outcome_kinds.invocation: self._failed( - 'Incorrect invocation-side outcome: %s should have been %s' % ( - outcome, self._sequence.outcome.invocation)) + 'Incorrect invocation-side outcome kind: %s should have been %s' % ( + outcome.kind, self._sequence.outcome_kinds.invocation)) elif self._state.service_side_outcome is not None: - self._passed(outcome, self._state.service_side_outcome) + self._passed(outcome.kind, self._state.service_side_outcome.kind) class _SequenceControllerCreator(ControllerCreator): diff --git a/src/python/grpcio_test/grpc_test/framework/interfaces/base/_sequence.py b/src/python/grpcio_test/grpc_test/framework/interfaces/base/_sequence.py index 1d77aaebe6..f547d91681 100644 --- a/src/python/grpcio_test/grpc_test/framework/interfaces/base/_sequence.py +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/base/_sequence.py @@ -103,13 +103,14 @@ class Element(collections.namedtuple('Element', ('kind', 'transmission',))): SERVICE_FAILURE = 'service failure' -class Outcome(collections.namedtuple('Outcome', ('invocation', 'service',))): +class OutcomeKinds( + collections.namedtuple('Outcome', ('invocation', 'service',))): """A description of the expected outcome of an operation test. Attributes: - invocation: The base.Outcome value expected on the invocation side of the - operation. - service: The base.Outcome value expected on the service side of the + invocation: The base.Outcome.Kind value expected on the invocation side of + the operation. + service: The base.Outcome.Kind value expected on the service side of the operation. """ @@ -117,7 +118,8 @@ class Outcome(collections.namedtuple('Outcome', ('invocation', 'service',))): class Sequence( collections.namedtuple( 'Sequence', - ('name', 'maximum_duration', 'invocation', 'elements', 'outcome',))): + ('name', 'maximum_duration', 'invocation', 'elements', + 'outcome_kinds',))): """Describes at a high level steps to perform in a test. Attributes: @@ -128,7 +130,8 @@ class Sequence( under test. elements: A sequence of Element values describing at coarse granularity actions to take during the operation under test. - outcome: An Outcome value describing the expected outcome of the test. + outcome_kinds: An OutcomeKinds value describing the expected outcome kinds + of the test. """ _EASY = Sequence( @@ -139,7 +142,7 @@ _EASY = Sequence( Element( Element.Kind.SERVICE_TRANSMISSION, Transmission(True, True, True)), ), - Outcome(base.Outcome.COMPLETED, base.Outcome.COMPLETED)) + OutcomeKinds(base.Outcome.Kind.COMPLETED, base.Outcome.Kind.COMPLETED)) _PEASY = Sequence( 'Peasy', @@ -154,7 +157,7 @@ _PEASY = Sequence( Element( Element.Kind.SERVICE_TRANSMISSION, Transmission(False, True, True)), ), - Outcome(base.Outcome.COMPLETED, base.Outcome.COMPLETED)) + OutcomeKinds(base.Outcome.Kind.COMPLETED, base.Outcome.Kind.COMPLETED)) # TODO(issue 2959): Finish this test suite. This tuple of sequences should diff --git a/src/python/grpcio_test/grpc_test/framework/interfaces/base/test_cases.py b/src/python/grpcio_test/grpc_test/framework/interfaces/base/test_cases.py index 87332cf612..5065a3f38a 100644 --- a/src/python/grpcio_test/grpc_test/framework/interfaces/base/test_cases.py +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/base/test_cases.py @@ -44,7 +44,8 @@ from grpc_test.framework.interfaces.base import test_interfaces _SYNCHRONICITY_VARIATION = (('Sync', False), ('Async', True)) -_EMPTY_OUTCOME_DICT = {outcome: 0 for outcome in base.Outcome} +_EMPTY_OUTCOME_KIND_DICT = { + outcome_kind: 0 for outcome_kind in base.Outcome.Kind} class _Serialization(test_interfaces.Serialization): @@ -119,7 +120,7 @@ class _Operator(base.Operator): class _Servicer(base.Servicer): - """An base.Servicer with instrumented for testing.""" + """A base.Servicer with instrumented for testing.""" def __init__(self, group, method, controllers, pool): self._condition = threading.Condition() @@ -223,11 +224,12 @@ class _OperationTest(unittest.TestCase): self.assertTrue( instruction.conclude_success, msg=instruction.conclude_message) - expected_invocation_stats = dict(_EMPTY_OUTCOME_DICT) - expected_invocation_stats[instruction.conclude_invocation_outcome] += 1 + expected_invocation_stats = dict(_EMPTY_OUTCOME_KIND_DICT) + expected_invocation_stats[ + instruction.conclude_invocation_outcome_kind] += 1 self.assertDictEqual(expected_invocation_stats, invocation_stats) - expected_service_stats = dict(_EMPTY_OUTCOME_DICT) - expected_service_stats[instruction.conclude_service_outcome] += 1 + expected_service_stats = dict(_EMPTY_OUTCOME_KIND_DICT) + expected_service_stats[instruction.conclude_service_outcome_kind] += 1 self.assertDictEqual(expected_service_stats, service_stats) -- cgit v1.2.3 From 1d750d6ca2d878385e4a13a933663bbfe87e5358 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 2 Sep 2015 20:04:23 +0000 Subject: UNIMPLEMENTED status for methods not found --- src/python/grpcio/grpc/_links/_constants.py | 42 ++++++++++++ src/python/grpcio/grpc/_links/invocation.py | 8 ++- src/python/grpcio/grpc/_links/service.py | 13 ++-- src/python/grpcio/grpc/beta/_server.py | 24 ++++++- src/python/grpcio/grpc/beta/interfaces.py | 54 ++++++++++++++++ .../grpcio/grpc/framework/core/_termination.py | 4 +- .../_core_over_links_base_interface_test.py | 7 +- ...ust_over_core_over_links_face_interface_test.py | 3 +- .../grpc_test/_links/_transmission_test.py | 10 ++- .../grpc_test/beta/_face_interface_test.py | 4 +- .../grpcio_test/grpc_test/beta/_not_found_test.py | 75 ++++++++++++++++++++++ 11 files changed, 223 insertions(+), 21 deletions(-) create mode 100644 src/python/grpcio/grpc/_links/_constants.py create mode 100644 src/python/grpcio/grpc/beta/interfaces.py create mode 100644 src/python/grpcio_test/grpc_test/beta/_not_found_test.py (limited to 'src') diff --git a/src/python/grpcio/grpc/_links/_constants.py b/src/python/grpcio/grpc/_links/_constants.py new file mode 100644 index 0000000000..117fc5a639 --- /dev/null +++ b/src/python/grpcio/grpc/_links/_constants.py @@ -0,0 +1,42 @@ +# 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 for use within this package.""" + +from grpc._adapter import _intermediary_low +from grpc.beta import interfaces as beta_interfaces + +LOW_STATUS_CODE_TO_HIGH_STATUS_CODE = { + low: high for low, high in zip( + _intermediary_low.Code, beta_interfaces.StatusCode) +} + +HIGH_STATUS_CODE_TO_LOW_STATUS_CODE = { + high: low for low, high in LOW_STATUS_CODE_TO_HIGH_STATUS_CODE.items() +} diff --git a/src/python/grpcio/grpc/_links/invocation.py b/src/python/grpcio/grpc/_links/invocation.py index 1676fe7941..fecb550ae0 100644 --- a/src/python/grpcio/grpc/_links/invocation.py +++ b/src/python/grpcio/grpc/_links/invocation.py @@ -36,6 +36,7 @@ import threading import time from grpc._adapter import _intermediary_low +from grpc._links import _constants from grpc.framework.foundation import activated from grpc.framework.foundation import logging_pool from grpc.framework.foundation import relay @@ -168,14 +169,17 @@ class _Kernel(object): termination = links.Ticket.Termination.CANCELLATION elif event.status.code is _intermediary_low.Code.DEADLINE_EXCEEDED: termination = links.Ticket.Termination.EXPIRATION + elif event.status.code is _intermediary_low.Code.UNIMPLEMENTED: + termination = links.Ticket.Termination.REMOTE_FAILURE elif event.status.code is _intermediary_low.Code.UNKNOWN: termination = links.Ticket.Termination.LOCAL_FAILURE else: termination = links.Ticket.Termination.TRANSMISSION_FAILURE + code = _constants.LOW_STATUS_CODE_TO_HIGH_STATUS_CODE[event.status.code] ticket = links.Ticket( operation_id, rpc_state.sequence_number, None, None, None, None, None, - None, None, event.metadata, event.status.code, event.status.details, - termination, None) + None, None, event.metadata, code, event.status.details, termination, + None) rpc_state.sequence_number += 1 self._relay.add_value(ticket) diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py index 94e7cfc716..34d3b262c9 100644 --- a/src/python/grpcio/grpc/_links/service.py +++ b/src/python/grpcio/grpc/_links/service.py @@ -36,6 +36,7 @@ import threading import time from grpc._adapter import _intermediary_low +from grpc._links import _constants from grpc.framework.foundation import logging_pool from grpc.framework.foundation import relay from grpc.framework.interfaces.links import links @@ -122,13 +123,13 @@ def _metadatafy(call, metadata): call.add_metadata(metadata_key, metadata_value) -def _status(termination_kind, code, details): - effective_details = b'' if details is None else details - if code is None: - effective_code = _TERMINATION_KIND_TO_CODE[termination_kind] +def _status(termination_kind, high_code, details): + low_details = b'' if details is None else details + if high_code is None: + low_code = _TERMINATION_KIND_TO_CODE[termination_kind] else: - effective_code = code - return _intermediary_low.Status(effective_code, effective_details) + low_code = _constants.HIGH_STATUS_CODE_TO_LOW_STATUS_CODE[high_code] + return _intermediary_low.Status(low_code, low_details) class _Kernel(object): diff --git a/src/python/grpcio/grpc/beta/_server.py b/src/python/grpcio/grpc/beta/_server.py index 4e46ffd17f..ebf91d80ab 100644 --- a/src/python/grpcio/grpc/beta/_server.py +++ b/src/python/grpcio/grpc/beta/_server.py @@ -32,9 +32,11 @@ import threading from grpc._links import service +from grpc.beta import interfaces 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.base import base from grpc.framework.interfaces.links import utilities _DEFAULT_POOL_SIZE = 8 @@ -42,6 +44,23 @@ _DEFAULT_TIMEOUT = 300 _MAXIMUM_TIMEOUT = 24 * 60 * 60 +class _GRPCServicer(base.Servicer): + + def __init__(self, delegate): + self._delegate = delegate + + def service(self, group, method, context, output_operator): + try: + return self._delegate.service(group, method, context, output_operator) + except base.NoSuchMethodError as e: + if e.code is None and e.details is None: + raise base.NoSuchMethodError( + interfaces.StatusCode.UNIMPLEMENTED, + b'Method "%s" of service "%s" not implemented!' % (method, group)) + else: + raise + + def _disassemble(grpc_link, end_link, pool, event, grace): grpc_link.begin_stop() end_link.stop(grace).wait() @@ -99,8 +118,9 @@ def server( service_thread_pool = thread_pool assembly_thread_pool = None - servicer = _crust_implementations.servicer( - implementations, multi_implementation, service_thread_pool) + servicer = _GRPCServicer( + _crust_implementations.servicer( + implementations, multi_implementation, service_thread_pool)) grpc_link = service.service_link(request_deserializers, response_serializers) diff --git a/src/python/grpcio/grpc/beta/interfaces.py b/src/python/grpcio/grpc/beta/interfaces.py new file mode 100644 index 0000000000..25e6a9c66b --- /dev/null +++ b/src/python/grpcio/grpc/beta/interfaces.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. + +"""Constants and interfaces of the Beta API of gRPC Python.""" + +import enum + + +@enum.unique +class StatusCode(enum.Enum): + """Mirrors grpc_status_code in the C core.""" + OK = 0 + CANCELLED = 1 + UNKNOWN = 2 + INVALID_ARGUMENT = 3 + DEADLINE_EXCEEDED = 4 + NOT_FOUND = 5 + ALREADY_EXISTS = 6 + PERMISSION_DENIED = 7 + RESOURCE_EXHAUSTED = 8 + FAILED_PRECONDITION = 9 + ABORTED = 10 + OUT_OF_RANGE = 11 + UNIMPLEMENTED = 12 + INTERNAL = 13 + UNAVAILABLE = 14 + DATA_LOSS = 15 + UNAUTHENTICATED = 16 diff --git a/src/python/grpcio/grpc/framework/core/_termination.py b/src/python/grpcio/grpc/framework/core/_termination.py index 3bf7ade30f..bdb9147e5b 100644 --- a/src/python/grpcio/grpc/framework/core/_termination.py +++ b/src/python/grpcio/grpc/framework/core/_termination.py @@ -113,7 +113,9 @@ class _TerminationManager(TerminationManager): act = callable_util.with_exceptions_logged( self._action, _constants.INTERNAL_ERROR_LOG_MESSAGE) - if outcome.kind is base.Outcome.Kind.LOCAL_FAILURE: + # TODO(issue 3202): Don't call the local application's callbacks if it has + # previously shown a programming defect. + if False and outcome.kind is base.Outcome.Kind.LOCAL_FAILURE: self._pool.submit(act, base.Outcome.Kind.LOCAL_FAILURE) else: def call_callbacks_and_act(callbacks, outcome): 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 f0bd989ea6..cafb6b6eae 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 @@ -38,6 +38,7 @@ import unittest from grpc._adapter import _intermediary_low from grpc._links import invocation from grpc._links import service +from grpc.beta import interfaces as beta_interfaces from grpc.framework.core import implementations from grpc.framework.interfaces.base import utilities from grpc_test import test_common as grpc_test_common @@ -45,8 +46,6 @@ 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 -_CODE = _intermediary_low.Code.OK - class _SerializationBehaviors( collections.namedtuple( @@ -124,8 +123,8 @@ class _Implementation(test_interfaces.Implementation): def service_completion(self): return utilities.completion( - grpc_test_common.SERVICE_TERMINAL_METADATA, _CODE, - grpc_test_common.DETAILS) + grpc_test_common.SERVICE_TERMINAL_METADATA, + beta_interfaces.StatusCode.OK, 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/_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 28c0619f7c..a4d4dee38c 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 @@ -35,6 +35,7 @@ import unittest from grpc._adapter import _intermediary_low from grpc._links import invocation from grpc._links import service +from grpc.beta import interfaces as beta_interfaces 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 @@ -139,7 +140,7 @@ class _Implementation(test_interfaces.Implementation): return grpc_test_common.SERVICE_TERMINAL_METADATA def code(self): - return _intermediary_low.Code.OK + return beta_interfaces.StatusCode.OK def details(self): return grpc_test_common.DETAILS 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 716323cc20..77e83d5561 100644 --- a/src/python/grpcio_test/grpc_test/_links/_transmission_test.py +++ b/src/python/grpcio_test/grpc_test/_links/_transmission_test.py @@ -34,6 +34,7 @@ import unittest from grpc._adapter import _intermediary_low from grpc._links import invocation from grpc._links import service +from grpc.beta import interfaces as beta_interfaces from grpc.framework.interfaces.links import links from grpc_test import test_common from grpc_test._links import _proto_scenarios @@ -93,7 +94,8 @@ class TransmissionTest(test_cases.TransmissionTest, unittest.TestCase): return None, None def create_service_completion(self): - return _intermediary_low.Code.OK, 'An exuberant test "details" message!' + return ( + beta_interfaces.StatusCode.OK, b'An exuberant test "details" message!') def assertMetadataTransmitted(self, original_metadata, transmitted_metadata): self.assertTrue( @@ -110,7 +112,7 @@ class RoundTripTest(unittest.TestCase): test_group = 'test package.Test Group' test_method = 'test method' identity_transformation = {(test_group, test_method): _IDENTITY} - test_code = _intermediary_low.Code.OK + test_code = beta_interfaces.StatusCode.OK test_message = 'a test message' service_link = service.service_link( @@ -150,11 +152,13 @@ class RoundTripTest(unittest.TestCase): self.assertIs( invocation_mate.tickets()[-1].termination, links.Ticket.Termination.COMPLETION) + self.assertIs(invocation_mate.tickets()[-1].code, test_code) + self.assertEqual(invocation_mate.tickets()[-1].message, test_message) def _perform_scenario_test(self, scenario): test_operation_id = object() test_group, test_method = scenario.group_and_method() - test_code = _intermediary_low.Code.OK + test_code = beta_interfaces.StatusCode.OK test_message = 'a scenario test message' service_link = service.service_link( 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 index ce4c59c0ee..e9087a7949 100644 --- a/src/python/grpcio_test/grpc_test/beta/_face_interface_test.py +++ b/src/python/grpcio_test/grpc_test/beta/_face_interface_test.py @@ -32,8 +32,8 @@ import collections import unittest -from grpc._adapter import _intermediary_low from grpc.beta import beta +from grpc.beta import interfaces from grpc_test import resources from grpc_test import test_common as grpc_test_common from grpc_test.beta import test_utilities @@ -116,7 +116,7 @@ class _Implementation(test_interfaces.Implementation): return grpc_test_common.SERVICE_TERMINAL_METADATA def code(self): - return _intermediary_low.Code.OK + return interfaces.StatusCode.OK def details(self): return grpc_test_common.DETAILS diff --git a/src/python/grpcio_test/grpc_test/beta/_not_found_test.py b/src/python/grpcio_test/grpc_test/beta/_not_found_test.py new file mode 100644 index 0000000000..ecd10f2175 --- /dev/null +++ b/src/python/grpcio_test/grpc_test/beta/_not_found_test.py @@ -0,0 +1,75 @@ +# 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 RPC-method-not-found behavior.""" + +import unittest + +from grpc.beta import beta +from grpc.beta import interfaces +from grpc.framework.interfaces.face import face +from grpc_test.framework.common import test_constants + + +class NotFoundTest(unittest.TestCase): + + def setUp(self): + self._server = beta.server({}) + port = self._server.add_insecure_port('[::]:0') + channel = beta.create_insecure_channel('localhost', port) + self._generic_stub = beta.generic_stub(channel) + self._server.start() + + def tearDown(self): + self._server.stop(0).wait() + self._generic_stub = None + + def test_blocking_unary_unary_not_found(self): + with self.assertRaises(face.LocalError) as exception_assertion_context: + self._generic_stub.blocking_unary_unary( + 'groop', 'meffod', b'abc', test_constants.LONG_TIMEOUT, + with_call=True) + self.assertIs( + exception_assertion_context.exception.code, + interfaces.StatusCode.UNIMPLEMENTED) + + def test_future_stream_unary_not_found(self): + rpc_future = self._generic_stub.future_stream_unary( + 'grupe', 'mevvod', b'def', test_constants.LONG_TIMEOUT) + with self.assertRaises(face.LocalError) as exception_assertion_context: + rpc_future.result() + self.assertIs( + exception_assertion_context.exception.code, + interfaces.StatusCode.UNIMPLEMENTED) + self.assertIs( + rpc_future.exception().code, interfaces.StatusCode.UNIMPLEMENTED) + + +if __name__ == '__main__': + unittest.main(verbosity=2) -- cgit v1.2.3 From 1ea97363d62d918dc3f2fdd5db1965e01e5432bb Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Wed, 2 Sep 2015 15:30:48 -0700 Subject: php: bump version --- composer.json | 2 +- src/php/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/composer.json b/composer.json index 1d78a2ce21..61f81e02bf 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc", "type": "library", "description": "gRPC library for PHP", - "version": "0.5.1", + "version": "0.6.0", "keywords": ["rpc"], "homepage": "http://grpc.io", "license": "BSD-3-Clause", diff --git a/src/php/composer.json b/src/php/composer.json index 2d0fe0c87a..1d41f847ac 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -1,7 +1,7 @@ { "name": "grpc/grpc", "description": "gRPC library for PHP", - "version": "0.5.1", + "version": "0.6.0", "homepage": "http://grpc.io", "license": "BSD-3-Clause", "repositories": [ -- cgit v1.2.3 From 86e5a050f7db82f49e92bc79be3a0f8623353be3 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Tue, 1 Sep 2015 10:52:23 -0700 Subject: Make GRPCRequestHeaders public and import from GRPCCall --- src/objective-c/GRPCClient/GRPCCall+OAuth2.m | 1 - src/objective-c/GRPCClient/GRPCCall.h | 2 +- src/objective-c/GRPCClient/GRPCCall.m | 1 - src/objective-c/GRPCClient/GRPCRequestHeaders.h | 51 ++++++++ src/objective-c/GRPCClient/GRPCRequestHeaders.m | 128 +++++++++++++++++++++ .../GRPCClient/private/GRPCRequestHeaders.h | 51 -------- .../GRPCClient/private/GRPCRequestHeaders.m | 128 --------------------- 7 files changed, 180 insertions(+), 182 deletions(-) create mode 100644 src/objective-c/GRPCClient/GRPCRequestHeaders.h create mode 100644 src/objective-c/GRPCClient/GRPCRequestHeaders.m delete mode 100644 src/objective-c/GRPCClient/private/GRPCRequestHeaders.h delete mode 100644 src/objective-c/GRPCClient/private/GRPCRequestHeaders.m (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall+OAuth2.m b/src/objective-c/GRPCClient/GRPCCall+OAuth2.m index cb2cee17d7..83b0de18e3 100644 --- a/src/objective-c/GRPCClient/GRPCCall+OAuth2.m +++ b/src/objective-c/GRPCClient/GRPCCall+OAuth2.m @@ -32,7 +32,6 @@ */ #import "GRPCCall+OAuth2.h" -#import "private/GRPCRequestHeaders.h" static NSString * const kAuthorizationHeader = @"authorization"; static NSString * const kBearerPrefix = @"Bearer "; diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 975ff8feff..1487001da5 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -48,7 +48,7 @@ #import #import -@class GRPCRequestHeaders; +#import "GRPCRequestHeaders.h" // Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by // the server. diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index afa01e2f0f..e6d845c9c2 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -41,7 +41,6 @@ #import "private/NSData+GRPC.h" #import "private/NSDictionary+GRPC.h" #import "private/NSError+GRPC.h" -#import "private/GRPCRequestHeaders.h" NSString * const kGRPCHeadersKey = @"io.grpc.HeadersKey"; NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; diff --git a/src/objective-c/GRPCClient/GRPCRequestHeaders.h b/src/objective-c/GRPCClient/GRPCRequestHeaders.h new file mode 100644 index 0000000000..320545190f --- /dev/null +++ b/src/objective-c/GRPCClient/GRPCRequestHeaders.h @@ -0,0 +1,51 @@ +/* + * + * 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 +#include + +@class GRPCCall; + +@interface GRPCRequestHeaders : NSObject + +- (instancetype)initWithCall:(GRPCCall *)call; + +- (id)objectForKeyedSubscript:(NSString *)key; +- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; + +- (void)removeAllObjects; +- (void)removeObjectForKey:(NSString *)aKey; + +- (NSDictionary *)asDictionary; + +@end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/GRPCRequestHeaders.m new file mode 100644 index 0000000000..f479ed7501 --- /dev/null +++ b/src/objective-c/GRPCClient/GRPCRequestHeaders.m @@ -0,0 +1,128 @@ +/* + * + * 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 +#import "GRPCRequestHeaders.h" +#import "GRPCCall.h" + +static NSString* normalizeKey(NSString* key) { + if ([key canBeConvertedToEncoding:NSASCIIStringEncoding]) { + return [key lowercaseString]; + } else { + return nil; + } +} + +static bool isKeyValuePairValid(NSString *key, id value) { + if ([key hasSuffix:@"-bin"]) { + if (![value isKindOfClass:[NSData class]]) { + return false; + } + } else { + if (![value isKindOfClass:[NSString class]]) { + return false; + } + } + return true; +} + +@implementation GRPCRequestHeaders { + __weak GRPCCall *_call; + NSMutableDictionary *_proxy; +} + +- (instancetype) initWithCall:(GRPCCall *)call { + self = [super init]; + if (self) { + _call = call; + _proxy = [NSMutableDictionary dictionary]; + } + return self; +} + +- (id) objectForKeyedSubscript:(NSString *)key { + NSString *normalizedKey = normalizeKey(key); + if (normalizedKey) { + return _proxy[normalizedKey]; + } else { + return [NSNull null]; + } +} + +- (void) setObject:(id)obj forKeyedSubscript:(NSString *)key { + if (_call.state == GRXWriterStateNotStarted) { + NSString *normalizedKey = normalizeKey(key); + if (normalizedKey) { + if (isKeyValuePairValid(key, obj)) { + _proxy[normalizedKey] = obj; + } else { + [NSException raise:@"Invalid key/value pair" + format:@"Key %@ could not be added with value %@", key, obj]; + } + } else { + [NSException raise:@"Invalid key" format:@"Key %@ contains illegal characters", key]; + } + } else { + [NSException raise:@"Invalid modification" + format:@"Cannot modify request metadata after call is started"]; + } +} + +- (void) removeObjectForKey:(NSString *)aKey { + if (_call.state == GRXWriterStateNotStarted) { + NSString *normalizedKey = normalizeKey(aKey); + if (normalizedKey) { + [_proxy removeObjectForKey:normalizedKey]; + } else { + [NSException raise:@"Invalid key" format:@"Key %@ contains illegal characters", aKey]; + } + } else { + [NSException raise:@"Invalid modification" + format:@"Cannot modify request metadata after call is started"]; + } +} + +- (void) removeAllObjects { + if (_call.state == GRXWriterStateNotStarted) { + [_proxy removeAllObjects]; + } else { + [NSException raise:@"Invalid modification" + format:@"Cannot modify request metadata after call is started"]; + } +} + +- (NSDictionary *)asDictionary { + return [NSDictionary dictionaryWithDictionary:_proxy]; +} + +@end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h deleted file mode 100644 index 320545190f..0000000000 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h +++ /dev/null @@ -1,51 +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. - * - */ - -#import -#include - -@class GRPCCall; - -@interface GRPCRequestHeaders : NSObject - -- (instancetype)initWithCall:(GRPCCall *)call; - -- (id)objectForKeyedSubscript:(NSString *)key; -- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; - -- (void)removeAllObjects; -- (void)removeObjectForKey:(NSString *)aKey; - -- (NSDictionary *)asDictionary; - -@end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m deleted file mode 100644 index f479ed7501..0000000000 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ /dev/null @@ -1,128 +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. - * - */ - -#import -#import "GRPCRequestHeaders.h" -#import "GRPCCall.h" - -static NSString* normalizeKey(NSString* key) { - if ([key canBeConvertedToEncoding:NSASCIIStringEncoding]) { - return [key lowercaseString]; - } else { - return nil; - } -} - -static bool isKeyValuePairValid(NSString *key, id value) { - if ([key hasSuffix:@"-bin"]) { - if (![value isKindOfClass:[NSData class]]) { - return false; - } - } else { - if (![value isKindOfClass:[NSString class]]) { - return false; - } - } - return true; -} - -@implementation GRPCRequestHeaders { - __weak GRPCCall *_call; - NSMutableDictionary *_proxy; -} - -- (instancetype) initWithCall:(GRPCCall *)call { - self = [super init]; - if (self) { - _call = call; - _proxy = [NSMutableDictionary dictionary]; - } - return self; -} - -- (id) objectForKeyedSubscript:(NSString *)key { - NSString *normalizedKey = normalizeKey(key); - if (normalizedKey) { - return _proxy[normalizedKey]; - } else { - return [NSNull null]; - } -} - -- (void) setObject:(id)obj forKeyedSubscript:(NSString *)key { - if (_call.state == GRXWriterStateNotStarted) { - NSString *normalizedKey = normalizeKey(key); - if (normalizedKey) { - if (isKeyValuePairValid(key, obj)) { - _proxy[normalizedKey] = obj; - } else { - [NSException raise:@"Invalid key/value pair" - format:@"Key %@ could not be added with value %@", key, obj]; - } - } else { - [NSException raise:@"Invalid key" format:@"Key %@ contains illegal characters", key]; - } - } else { - [NSException raise:@"Invalid modification" - format:@"Cannot modify request metadata after call is started"]; - } -} - -- (void) removeObjectForKey:(NSString *)aKey { - if (_call.state == GRXWriterStateNotStarted) { - NSString *normalizedKey = normalizeKey(aKey); - if (normalizedKey) { - [_proxy removeObjectForKey:normalizedKey]; - } else { - [NSException raise:@"Invalid key" format:@"Key %@ contains illegal characters", aKey]; - } - } else { - [NSException raise:@"Invalid modification" - format:@"Cannot modify request metadata after call is started"]; - } -} - -- (void) removeAllObjects { - if (_call.state == GRXWriterStateNotStarted) { - [_proxy removeAllObjects]; - } else { - [NSException raise:@"Invalid modification" - format:@"Cannot modify request metadata after call is started"]; - } -} - -- (NSDictionary *)asDictionary { - return [NSDictionary dictionaryWithDictionary:_proxy]; -} - -@end \ No newline at end of file -- cgit v1.2.3 From 5c339d15b322952c71b7f3ecef94f6d2eb7dd2b4 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 17:41:43 -0700 Subject: Remove -[asDictionary] --- src/objective-c/GRPCClient/GRPCCall.m | 5 ++--- src/objective-c/GRPCClient/GRPCRequestHeaders.h | 5 +++-- src/objective-c/GRPCClient/GRPCRequestHeaders.m | 10 ++++++++-- src/objective-c/GRPCClient/private/GRPCWrappedCall.h | 4 +++- src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 4 +++- 5 files changed, 19 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index e6d845c9c2..d5f775c6e6 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -236,9 +236,8 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; - (void)sendHeaders:(GRPCRequestHeaders *)headers { // TODO(jcanizales): Add error handlers for async failures - [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] - initWithMetadata:[headers asDictionary] ?: @{} - handler:nil]]]; + [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers + handler:nil]]]; } #pragma mark GRXWriteable implementation diff --git a/src/objective-c/GRPCClient/GRPCRequestHeaders.h b/src/objective-c/GRPCClient/GRPCRequestHeaders.h index 320545190f..5a93f82cd8 100644 --- a/src/objective-c/GRPCClient/GRPCRequestHeaders.h +++ b/src/objective-c/GRPCClient/GRPCRequestHeaders.h @@ -38,6 +38,9 @@ @interface GRPCRequestHeaders : NSObject +@property(nonatomic, readonly) NSUInteger count; +@property(nonatomic, readonly) grpc_metadata *grpc_metadataArray; + - (instancetype)initWithCall:(GRPCCall *)call; - (id)objectForKeyedSubscript:(NSString *)key; @@ -46,6 +49,4 @@ - (void)removeAllObjects; - (void)removeObjectForKey:(NSString *)aKey; -- (NSDictionary *)asDictionary; - @end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/GRPCRequestHeaders.m index f479ed7501..041bc4e7a8 100644 --- a/src/objective-c/GRPCClient/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/GRPCRequestHeaders.m @@ -34,6 +34,7 @@ #import #import "GRPCRequestHeaders.h" #import "GRPCCall.h" +#import "NSDictionary+GRPC.h" static NSString* normalizeKey(NSString* key) { if ([key canBeConvertedToEncoding:NSASCIIStringEncoding]) { @@ -121,8 +122,13 @@ static bool isKeyValuePairValid(NSString *key, id value) { } } -- (NSDictionary *)asDictionary { - return [NSDictionary dictionaryWithDictionary:_proxy]; +// TODO(jcanizales): Just forward all invocations? + +- (NSUInteger)count { + return _proxy.count; } +- (grpc_metadata *)grpc_metadataArray { + return _proxy.grpc_metadataArray; +} @end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index da11cbb761..ba34c0a6e7 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -36,6 +36,8 @@ #import "GRPCChannel.h" +@class GRPCRequestHeaders; + @interface GRPCOperation : NSObject @property(nonatomic, readonly) grpc_op op; // Guaranteed to be called when the operation has finished. @@ -44,7 +46,7 @@ @interface GRPCOpSendMetadata : GRPCOperation -- (instancetype)initWithMetadata:(NSDictionary *)metadata +- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index fe3d51da53..3cb5613bd0 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -38,6 +38,8 @@ #include #include +#import "GRPCRequestHeaders.h" + #import "GRPCCompletionQueue.h" #import "GRPCHost.h" #import "NSDictionary+GRPC.h" @@ -65,7 +67,7 @@ return [self initWithMetadata:nil handler:nil]; } -- (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)())handler { +- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata handler:(void (^)())handler { if (self = [super init]) { _op.op = GRPC_OP_SEND_INITIAL_METADATA; _op.data.send_initial_metadata.count = metadata.count; -- cgit v1.2.3 From 030e5d0c9c2b9abd17dc061a3a682114a4d2cc38 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 17:52:30 -0700 Subject: nit: Style guide --- src/objective-c/GRPCClient/GRPCRequestHeaders.m | 29 +++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/GRPCRequestHeaders.m index 041bc4e7a8..23140cb78a 100644 --- a/src/objective-c/GRPCClient/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/GRPCRequestHeaders.m @@ -31,12 +31,14 @@ * */ -#import #import "GRPCRequestHeaders.h" + +#import + #import "GRPCCall.h" #import "NSDictionary+GRPC.h" -static NSString* normalizeKey(NSString* key) { +static NSString* NormalizeKey(NSString* key) { if ([key canBeConvertedToEncoding:NSASCIIStringEncoding]) { return [key lowercaseString]; } else { @@ -44,7 +46,7 @@ static NSString* normalizeKey(NSString* key) { } } -static bool isKeyValuePairValid(NSString *key, id value) { +static bool IsKeyValuePairValid(NSString *key, id value) { if ([key hasSuffix:@"-bin"]) { if (![value isKindOfClass:[NSData class]]) { return false; @@ -62,17 +64,16 @@ static bool isKeyValuePairValid(NSString *key, id value) { NSMutableDictionary *_proxy; } -- (instancetype) initWithCall:(GRPCCall *)call { - self = [super init]; - if (self) { +- (instancetype)initWithCall:(GRPCCall *)call { + if ((self = [super init])) { _call = call; _proxy = [NSMutableDictionary dictionary]; } return self; } -- (id) objectForKeyedSubscript:(NSString *)key { - NSString *normalizedKey = normalizeKey(key); +- (id)objectForKeyedSubscript:(NSString *)key { + NSString *normalizedKey = NormalizeKey(key); if (normalizedKey) { return _proxy[normalizedKey]; } else { @@ -80,11 +81,11 @@ static bool isKeyValuePairValid(NSString *key, id value) { } } -- (void) setObject:(id)obj forKeyedSubscript:(NSString *)key { +- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key { if (_call.state == GRXWriterStateNotStarted) { - NSString *normalizedKey = normalizeKey(key); + NSString *normalizedKey = NormalizeKey(key); if (normalizedKey) { - if (isKeyValuePairValid(key, obj)) { + if (IsKeyValuePairValid(key, obj)) { _proxy[normalizedKey] = obj; } else { [NSException raise:@"Invalid key/value pair" @@ -99,9 +100,9 @@ static bool isKeyValuePairValid(NSString *key, id value) { } } -- (void) removeObjectForKey:(NSString *)aKey { +- (void)removeObjectForKey:(NSString *)aKey { if (_call.state == GRXWriterStateNotStarted) { - NSString *normalizedKey = normalizeKey(aKey); + NSString *normalizedKey = NormalizeKey(aKey); if (normalizedKey) { [_proxy removeObjectForKey:normalizedKey]; } else { @@ -113,7 +114,7 @@ static bool isKeyValuePairValid(NSString *key, id value) { } } -- (void) removeAllObjects { +- (void)removeAllObjects { if (_call.state == GRXWriterStateNotStarted) { [_proxy removeAllObjects]; } else { -- cgit v1.2.3 From 05640a58dfef890165b49045cd158cc4defe7a86 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 19:35:13 -0700 Subject: Simpler code, better exceptions. --- src/objective-c/GRPCClient/GRPCRequestHeaders.m | 85 ++++++++++--------------- 1 file changed, 35 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/GRPCRequestHeaders.m index 23140cb78a..d4bbbdf84a 100644 --- a/src/objective-c/GRPCClient/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/GRPCRequestHeaders.m @@ -38,25 +38,33 @@ #import "GRPCCall.h" #import "NSDictionary+GRPC.h" +// Used by the setters. static NSString* NormalizeKey(NSString* key) { - if ([key canBeConvertedToEncoding:NSASCIIStringEncoding]) { - return [key lowercaseString]; - } else { - return nil; + if (!key) { + [NSException raise:NSInvalidArgumentException format:@"Key cannot be nil"]; + } + if (![key canBeConvertedToEncoding:NSASCIIStringEncoding]) { + [NSException raise:NSInvalidArgumentException + format:@"Key %@ contains non-ASCII characters", key]; } + return key.lowercaseString; } -static bool IsKeyValuePairValid(NSString *key, id value) { +// Precondition: key isn't nil. +static void CheckKeyValuePairIsValid(NSString *key, id value) { if ([key hasSuffix:@"-bin"]) { - if (![value isKindOfClass:[NSData class]]) { - return false; + if (![value isKindOfClass:NSData.class]) { + [NSException raise:NSInvalidArgumentException + format:@"Expected NSData value for header %@ ending in \"-bin\", " + @"instead got %@", key, value]; } } else { - if (![value isKindOfClass:[NSString class]]) { - return false; + if (![value isKindOfClass:NSString.class]) { + [NSException raise:NSInvalidArgumentException + format:@"Expected NSString value for header %@ not ending in \"-bin\", " + @"instead got %@", key, value]; } } - return true; } @implementation GRPCRequestHeaders { @@ -72,55 +80,32 @@ static bool IsKeyValuePairValid(NSString *key, id value) { return self; } -- (id)objectForKeyedSubscript:(NSString *)key { - NSString *normalizedKey = NormalizeKey(key); - if (normalizedKey) { - return _proxy[normalizedKey]; - } else { - return [NSNull null]; +- (void)checkCallIsNotStarted { + if (_call.state != GRXWriterStateNotStarted) { + [NSException raise:@"Invalid modification" + format:@"Cannot modify request headers after call is started"]; } } +- (id)objectForKeyedSubscript:(NSString *)key { + return _proxy[key.lowercaseString]; +} + - (void)setObject:(id)obj forKeyedSubscript:(NSString *)key { - if (_call.state == GRXWriterStateNotStarted) { - NSString *normalizedKey = NormalizeKey(key); - if (normalizedKey) { - if (IsKeyValuePairValid(key, obj)) { - _proxy[normalizedKey] = obj; - } else { - [NSException raise:@"Invalid key/value pair" - format:@"Key %@ could not be added with value %@", key, obj]; - } - } else { - [NSException raise:@"Invalid key" format:@"Key %@ contains illegal characters", key]; - } - } else { - [NSException raise:@"Invalid modification" - format:@"Cannot modify request metadata after call is started"]; - } + [self checkCallIsNotStarted]; + key = NormalizeKey(key); + CheckKeyValuePairIsValid(key, obj); + _proxy[key] = obj; } -- (void)removeObjectForKey:(NSString *)aKey { - if (_call.state == GRXWriterStateNotStarted) { - NSString *normalizedKey = NormalizeKey(aKey); - if (normalizedKey) { - [_proxy removeObjectForKey:normalizedKey]; - } else { - [NSException raise:@"Invalid key" format:@"Key %@ contains illegal characters", aKey]; - } - } else { - [NSException raise:@"Invalid modification" - format:@"Cannot modify request metadata after call is started"]; - } +- (void)removeObjectForKey:(NSString *)key { + [self checkCallIsNotStarted]; + [_proxy removeObjectForKey:NormalizeKey(key)]; } - (void)removeAllObjects { - if (_call.state == GRXWriterStateNotStarted) { - [_proxy removeAllObjects]; - } else { - [NSException raise:@"Invalid modification" - format:@"Cannot modify request metadata after call is started"]; - } + [self checkCallIsNotStarted]; + [_proxy removeAllObjects]; } // TODO(jcanizales): Just forward all invocations? -- cgit v1.2.3 From 2f10127f85ebb4f81d64e195bee7731a40d00fa2 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 21:55:37 -0700 Subject: Publish GRPCRequestHeaders as a protocol So we can make the property a dictionary later, by just extending NSMutableDictionary to conform to the protocol. --- src/objective-c/GRPCClient/GRPCCall.h | 17 ++- src/objective-c/GRPCClient/GRPCCall.m | 5 +- src/objective-c/GRPCClient/GRPCRequestHeaders.h | 52 --------- src/objective-c/GRPCClient/GRPCRequestHeaders.m | 120 --------------------- .../GRPCClient/private/GRPCRequestHeaders.h | 52 +++++++++ .../GRPCClient/private/GRPCRequestHeaders.m | 120 +++++++++++++++++++++ .../GRPCClient/private/GRPCWrappedCall.h | 5 +- .../GRPCClient/private/GRPCWrappedCall.m | 4 +- 8 files changed, 193 insertions(+), 182 deletions(-) delete mode 100644 src/objective-c/GRPCClient/GRPCRequestHeaders.h delete mode 100644 src/objective-c/GRPCClient/GRPCRequestHeaders.m create mode 100644 src/objective-c/GRPCClient/private/GRPCRequestHeaders.h create mode 100644 src/objective-c/GRPCClient/private/GRPCRequestHeaders.m (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 1487001da5..fc274a095f 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -48,13 +48,26 @@ #import #import -#import "GRPCRequestHeaders.h" +#include // Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by // the server. extern id const kGRPCHeadersKey; extern id const kGRPCTrailersKey; +@protocol GRPCRequestHeaders + +@property(nonatomic, readonly) NSUInteger count; +@property(nonatomic, readonly) grpc_metadata *grpc_metadataArray; + +- (id)objectForKeyedSubscript:(NSString *)key; +- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; + +- (void)removeAllObjects; +- (void)removeObjectForKey:(NSString *)key; + +@end + // Represents a single gRPC remote call. @interface GRPCCall : GRXWriter @@ -72,7 +85,7 @@ extern id const kGRPCTrailersKey; // // For convenience, the property is initialized to an empty NSMutableDictionary, and the setter // accepts (and copies) both mutable and immutable dictionaries. -- (GRPCRequestHeaders *)requestHeaders; // nonatomic +- (id)requestHeaders; // nonatomic - (void)setRequestHeaders:(NSDictionary *)requestHeaders; // nonatomic, copy // This dictionary is populated with the HTTP headers received from the server. This happens before diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index d5f775c6e6..1be753e688 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -37,6 +37,7 @@ #include #import +#import "private/GRPCRequestHeaders.h" #import "private/GRPCWrappedCall.h" #import "private/NSData+GRPC.h" #import "private/NSDictionary+GRPC.h" @@ -131,7 +132,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; #pragma mark Metadata -- (GRPCRequestHeaders *)requestHeaders { +- (id)requestHeaders { return _requestHeaders; } @@ -234,7 +235,7 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; #pragma mark Send headers -- (void)sendHeaders:(GRPCRequestHeaders *)headers { +- (void)sendHeaders:(id)headers { // TODO(jcanizales): Add error handlers for async failures [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendMetadata alloc] initWithMetadata:headers handler:nil]]]; diff --git a/src/objective-c/GRPCClient/GRPCRequestHeaders.h b/src/objective-c/GRPCClient/GRPCRequestHeaders.h deleted file mode 100644 index 5a93f82cd8..0000000000 --- a/src/objective-c/GRPCClient/GRPCRequestHeaders.h +++ /dev/null @@ -1,52 +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. - * - */ - -#import -#include - -@class GRPCCall; - -@interface GRPCRequestHeaders : NSObject - -@property(nonatomic, readonly) NSUInteger count; -@property(nonatomic, readonly) grpc_metadata *grpc_metadataArray; - -- (instancetype)initWithCall:(GRPCCall *)call; - -- (id)objectForKeyedSubscript:(NSString *)key; -- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; - -- (void)removeAllObjects; -- (void)removeObjectForKey:(NSString *)aKey; - -@end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/GRPCRequestHeaders.m deleted file mode 100644 index d4bbbdf84a..0000000000 --- a/src/objective-c/GRPCClient/GRPCRequestHeaders.m +++ /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. - * - */ - -#import "GRPCRequestHeaders.h" - -#import - -#import "GRPCCall.h" -#import "NSDictionary+GRPC.h" - -// Used by the setters. -static NSString* NormalizeKey(NSString* key) { - if (!key) { - [NSException raise:NSInvalidArgumentException format:@"Key cannot be nil"]; - } - if (![key canBeConvertedToEncoding:NSASCIIStringEncoding]) { - [NSException raise:NSInvalidArgumentException - format:@"Key %@ contains non-ASCII characters", key]; - } - return key.lowercaseString; -} - -// Precondition: key isn't nil. -static void CheckKeyValuePairIsValid(NSString *key, id value) { - if ([key hasSuffix:@"-bin"]) { - if (![value isKindOfClass:NSData.class]) { - [NSException raise:NSInvalidArgumentException - format:@"Expected NSData value for header %@ ending in \"-bin\", " - @"instead got %@", key, value]; - } - } else { - if (![value isKindOfClass:NSString.class]) { - [NSException raise:NSInvalidArgumentException - format:@"Expected NSString value for header %@ not ending in \"-bin\", " - @"instead got %@", key, value]; - } - } -} - -@implementation GRPCRequestHeaders { - __weak GRPCCall *_call; - NSMutableDictionary *_proxy; -} - -- (instancetype)initWithCall:(GRPCCall *)call { - if ((self = [super init])) { - _call = call; - _proxy = [NSMutableDictionary dictionary]; - } - return self; -} - -- (void)checkCallIsNotStarted { - if (_call.state != GRXWriterStateNotStarted) { - [NSException raise:@"Invalid modification" - format:@"Cannot modify request headers after call is started"]; - } -} - -- (id)objectForKeyedSubscript:(NSString *)key { - return _proxy[key.lowercaseString]; -} - -- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key { - [self checkCallIsNotStarted]; - key = NormalizeKey(key); - CheckKeyValuePairIsValid(key, obj); - _proxy[key] = obj; -} - -- (void)removeObjectForKey:(NSString *)key { - [self checkCallIsNotStarted]; - [_proxy removeObjectForKey:NormalizeKey(key)]; -} - -- (void)removeAllObjects { - [self checkCallIsNotStarted]; - [_proxy removeAllObjects]; -} - -// TODO(jcanizales): Just forward all invocations? - -- (NSUInteger)count { - return _proxy.count; -} - -- (grpc_metadata *)grpc_metadataArray { - return _proxy.grpc_metadataArray; -} -@end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h new file mode 100644 index 0000000000..066f71a8f6 --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h @@ -0,0 +1,52 @@ +/* + * + * 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 +#include + +#import "GRPCCall.h" + +@interface GRPCRequestHeaders : NSObject + +@property(nonatomic, readonly) NSUInteger count; +@property(nonatomic, readonly) grpc_metadata *grpc_metadataArray; + +- (instancetype)initWithCall:(GRPCCall *)call; + +- (id)objectForKeyedSubscript:(NSString *)key; +- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; + +- (void)removeAllObjects; +- (void)removeObjectForKey:(NSString *)aKey; + +@end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m new file mode 100644 index 0000000000..d4bbbdf84a --- /dev/null +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -0,0 +1,120 @@ +/* + * + * 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 "GRPCRequestHeaders.h" + +#import + +#import "GRPCCall.h" +#import "NSDictionary+GRPC.h" + +// Used by the setters. +static NSString* NormalizeKey(NSString* key) { + if (!key) { + [NSException raise:NSInvalidArgumentException format:@"Key cannot be nil"]; + } + if (![key canBeConvertedToEncoding:NSASCIIStringEncoding]) { + [NSException raise:NSInvalidArgumentException + format:@"Key %@ contains non-ASCII characters", key]; + } + return key.lowercaseString; +} + +// Precondition: key isn't nil. +static void CheckKeyValuePairIsValid(NSString *key, id value) { + if ([key hasSuffix:@"-bin"]) { + if (![value isKindOfClass:NSData.class]) { + [NSException raise:NSInvalidArgumentException + format:@"Expected NSData value for header %@ ending in \"-bin\", " + @"instead got %@", key, value]; + } + } else { + if (![value isKindOfClass:NSString.class]) { + [NSException raise:NSInvalidArgumentException + format:@"Expected NSString value for header %@ not ending in \"-bin\", " + @"instead got %@", key, value]; + } + } +} + +@implementation GRPCRequestHeaders { + __weak GRPCCall *_call; + NSMutableDictionary *_proxy; +} + +- (instancetype)initWithCall:(GRPCCall *)call { + if ((self = [super init])) { + _call = call; + _proxy = [NSMutableDictionary dictionary]; + } + return self; +} + +- (void)checkCallIsNotStarted { + if (_call.state != GRXWriterStateNotStarted) { + [NSException raise:@"Invalid modification" + format:@"Cannot modify request headers after call is started"]; + } +} + +- (id)objectForKeyedSubscript:(NSString *)key { + return _proxy[key.lowercaseString]; +} + +- (void)setObject:(id)obj forKeyedSubscript:(NSString *)key { + [self checkCallIsNotStarted]; + key = NormalizeKey(key); + CheckKeyValuePairIsValid(key, obj); + _proxy[key] = obj; +} + +- (void)removeObjectForKey:(NSString *)key { + [self checkCallIsNotStarted]; + [_proxy removeObjectForKey:NormalizeKey(key)]; +} + +- (void)removeAllObjects { + [self checkCallIsNotStarted]; + [_proxy removeAllObjects]; +} + +// TODO(jcanizales): Just forward all invocations? + +- (NSUInteger)count { + return _proxy.count; +} + +- (grpc_metadata *)grpc_metadataArray { + return _proxy.grpc_metadataArray; +} +@end \ No newline at end of file diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index ba34c0a6e7..9147ba0816 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -35,8 +35,7 @@ #include #import "GRPCChannel.h" - -@class GRPCRequestHeaders; +#import "GRPCCall.h" @interface GRPCOperation : NSObject @property(nonatomic, readonly) grpc_op op; @@ -46,7 +45,7 @@ @interface GRPCOpSendMetadata : GRPCOperation -- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata +- (instancetype)initWithMetadata:(id)metadata handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 3cb5613bd0..1f8c647fa6 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -38,8 +38,6 @@ #include #include -#import "GRPCRequestHeaders.h" - #import "GRPCCompletionQueue.h" #import "GRPCHost.h" #import "NSDictionary+GRPC.h" @@ -67,7 +65,7 @@ return [self initWithMetadata:nil handler:nil]; } -- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata handler:(void (^)())handler { +- (instancetype)initWithMetadata:(id)metadata handler:(void (^)())handler { if (self = [super init]) { _op.op = GRPC_OP_SEND_INITIAL_METADATA; _op.data.send_initial_metadata.count = metadata.count; -- cgit v1.2.3 From 5af286884e793c72a6842de5b2a79ac5e0eaa500 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 22:22:18 -0700 Subject: Make the grpc_metadataArray property private. --- src/objective-c/GRPCClient/GRPCCall.h | 1 - src/objective-c/GRPCClient/private/GRPCWrappedCall.h | 4 ++-- src/objective-c/GRPCClient/private/GRPCWrappedCall.m | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index fc274a095f..f4d1838da7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -58,7 +58,6 @@ extern id const kGRPCTrailersKey; @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; -@property(nonatomic, readonly) grpc_metadata *grpc_metadataArray; - (id)objectForKeyedSubscript:(NSString *)key; - (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h index 9147ba0816..4ca2766147 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h @@ -35,7 +35,7 @@ #include #import "GRPCChannel.h" -#import "GRPCCall.h" +#import "GRPCRequestHeaders.h" @interface GRPCOperation : NSObject @property(nonatomic, readonly) grpc_op op; @@ -45,7 +45,7 @@ @interface GRPCOpSendMetadata : GRPCOperation -- (instancetype)initWithMetadata:(id)metadata +- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata handler:(void(^)())handler NS_DESIGNATED_INITIALIZER; @end diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m index 1f8c647fa6..cea7c479e0 100644 --- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m +++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m @@ -65,7 +65,7 @@ return [self initWithMetadata:nil handler:nil]; } -- (instancetype)initWithMetadata:(id)metadata handler:(void (^)())handler { +- (instancetype)initWithMetadata:(GRPCRequestHeaders *)metadata handler:(void (^)())handler { if (self = [super init]) { _op.op = GRPC_OP_SEND_INITIAL_METADATA; _op.data.send_initial_metadata.count = metadata.count; -- cgit v1.2.3 From 12da424c9ae7fe35b926bfb5761ec1a300ccbf0f Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 22:22:34 -0700 Subject: nit: Documentation and formatting. --- src/objective-c/GRPCClient/GRPCCall.h | 7 +++++++ src/objective-c/GRPCClient/private/GRPCRequestHeaders.h | 4 ++-- src/objective-c/GRPCClient/private/GRPCRequestHeaders.m | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index f4d1838da7..c9b6e6d6e2 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -55,6 +55,13 @@ extern id const kGRPCHeadersKey; extern id const kGRPCTrailersKey; +// The container of the request headers of an RPC conforms to this protocol, which is a subset of +// NSMutableDictionary's interface. It will become a NSMutableDictionary later on. +// The keys of this container are the header names, which per the HTTP standard are case- +// insensitive. They are stored in lowercase (which is how HTTP/2 mandates them on the wire), and +// can only consist of ASCII characters. +// A header value is a NSString object (with only ASCII characters), unless the header name has the +// suffix "-bin", in which case the value has to be a NSData object. @protocol GRPCRequestHeaders @property(nonatomic, readonly) NSUInteger count; diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h index 066f71a8f6..1391b5725f 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.h @@ -47,6 +47,6 @@ - (void)setObject:(id)obj forKeyedSubscript:(NSString *)key; - (void)removeAllObjects; -- (void)removeObjectForKey:(NSString *)aKey; +- (void)removeObjectForKey:(NSString *)key; -@end \ No newline at end of file +@end diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m index d4bbbdf84a..d0d8de89a1 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -117,4 +117,4 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { - (grpc_metadata *)grpc_metadataArray { return _proxy.grpc_metadataArray; } -@end \ No newline at end of file +@end -- cgit v1.2.3 From acf5e107f3678334c08cc5effdbc73c3ae3f9042 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 22:56:01 -0700 Subject: Let remove nil or non-ASCII keys (noop instead of throw). --- src/objective-c/GRPCClient/private/GRPCRequestHeaders.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m index d0d8de89a1..50b04a6a87 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -38,8 +38,8 @@ #import "GRPCCall.h" #import "NSDictionary+GRPC.h" -// Used by the setters. -static NSString* NormalizeKey(NSString* key) { +// Used by the setter. +static void CheckKeyIsValid(NSString* key) { if (!key) { [NSException raise:NSInvalidArgumentException format:@"Key cannot be nil"]; } @@ -47,7 +47,6 @@ static NSString* NormalizeKey(NSString* key) { [NSException raise:NSInvalidArgumentException format:@"Key %@ contains non-ASCII characters", key]; } - return key.lowercaseString; } // Precondition: key isn't nil. @@ -93,14 +92,15 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { - (void)setObject:(id)obj forKeyedSubscript:(NSString *)key { [self checkCallIsNotStarted]; - key = NormalizeKey(key); + CheckKeyIsValid(key); + key = key.lowercaseString; CheckKeyValuePairIsValid(key, obj); _proxy[key] = obj; } - (void)removeObjectForKey:(NSString *)key { [self checkCallIsNotStarted]; - [_proxy removeObjectForKey:NormalizeKey(key)]; + [_proxy removeObjectForKey:key.lowercaseString]; } - (void)removeAllObjects { -- cgit v1.2.3 From 5f6001eb2330d8f1ba35674ffd6dfa0f7f0ecbe3 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 22:56:43 -0700 Subject: nit: _proxy -> _delegate --- src/objective-c/GRPCClient/private/GRPCRequestHeaders.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m index 50b04a6a87..7633107f55 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -68,13 +68,13 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { @implementation GRPCRequestHeaders { __weak GRPCCall *_call; - NSMutableDictionary *_proxy; + NSMutableDictionary *_delegate; } - (instancetype)initWithCall:(GRPCCall *)call { if ((self = [super init])) { _call = call; - _proxy = [NSMutableDictionary dictionary]; + _delegate = [NSMutableDictionary dictionary]; } return self; } @@ -87,7 +87,7 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { } - (id)objectForKeyedSubscript:(NSString *)key { - return _proxy[key.lowercaseString]; + return _delegate[key.lowercaseString]; } - (void)setObject:(id)obj forKeyedSubscript:(NSString *)key { @@ -95,26 +95,26 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { CheckKeyIsValid(key); key = key.lowercaseString; CheckKeyValuePairIsValid(key, obj); - _proxy[key] = obj; + _delegate[key] = obj; } - (void)removeObjectForKey:(NSString *)key { [self checkCallIsNotStarted]; - [_proxy removeObjectForKey:key.lowercaseString]; + [_delegate removeObjectForKey:key.lowercaseString]; } - (void)removeAllObjects { [self checkCallIsNotStarted]; - [_proxy removeAllObjects]; + [_delegate removeAllObjects]; } // TODO(jcanizales): Just forward all invocations? - (NSUInteger)count { - return _proxy.count; + return _delegate.count; } - (grpc_metadata *)grpc_metadataArray { - return _proxy.grpc_metadataArray; + return _delegate.grpc_metadataArray; } @end -- cgit v1.2.3 From 2529735d3d2c9124484b4c242e29e2fe8e0f938c Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 23:00:23 -0700 Subject: nit: remove obsolete comment --- src/objective-c/GRPCClient/private/GRPCRequestHeaders.m | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m index 7633107f55..310f1655e4 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -108,8 +108,6 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { [_delegate removeAllObjects]; } -// TODO(jcanizales): Just forward all invocations? - - (NSUInteger)count { return _delegate.count; } -- cgit v1.2.3 From bbba491b7cbf75104d1efcc72653a8498a935f17 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 23:05:53 -0700 Subject: Reject non-ASCII text header values too. --- src/objective-c/GRPCClient/private/GRPCRequestHeaders.m | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m index 310f1655e4..dfec2a7e7e 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -39,13 +39,13 @@ #import "NSDictionary+GRPC.h" // Used by the setter. -static void CheckKeyIsValid(NSString* key) { - if (!key) { - [NSException raise:NSInvalidArgumentException format:@"Key cannot be nil"]; +static void CheckIsNonNilASCII(NSString *name, NSString* value) { + if (!value) { + [NSException raise:NSInvalidArgumentException format:@"%@ cannot be nil", name]; } - if (![key canBeConvertedToEncoding:NSASCIIStringEncoding]) { + if (![value canBeConvertedToEncoding:NSASCIIStringEncoding]) { [NSException raise:NSInvalidArgumentException - format:@"Key %@ contains non-ASCII characters", key]; + format:@"%@ %@ contains non-ASCII characters", name, value]; } } @@ -63,6 +63,7 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { format:@"Expected NSString value for header %@ not ending in \"-bin\", " @"instead got %@", key, value]; } + CheckIsNonNilASCII(@"Text header value", (NSString *)value); } } @@ -92,7 +93,7 @@ static void CheckKeyValuePairIsValid(NSString *key, id value) { - (void)setObject:(id)obj forKeyedSubscript:(NSString *)key { [self checkCallIsNotStarted]; - CheckKeyIsValid(key); + CheckIsNonNilASCII(@"Header name", key); key = key.lowercaseString; CheckKeyValuePairIsValid(key, obj); _delegate[key] = obj; -- cgit v1.2.3 From 6697e7f9eaffd0d5882632d235f5a7203fa20cf1 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 23:47:56 -0700 Subject: Don’t append -bin automatically to binary request headers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GRPCClient/private/NSDictionary+GRPC.m | 44 ++++++++-------------- 1 file changed, 15 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m index 99c890e4ee..a7f6d34ed5 100644 --- a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m @@ -40,8 +40,8 @@ @interface NSData (GRPCMetadata) + (instancetype)grpc_dataFromMetadataValue:(grpc_metadata *)metadata; -// Fill a metadata object with the binary value in this NSData and the given key. -- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key; +// Fill a metadata object with the binary value in this NSData. +- (void)grpc_initMetadata:(grpc_metadata *)metadata; @end @implementation NSData (GRPCMetadata) @@ -50,9 +50,7 @@ return [self dataWithBytes:metadata->value length:metadata->value_length]; } -- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key { - // TODO(jcanizales): Encode Unicode chars as ASCII. - metadata->key = [key stringByAppendingString:@"-bin"].UTF8String; +- (void)grpc_initMetadata:(grpc_metadata *)metadata { metadata->value = self.bytes; metadata->value_length = self.length; } @@ -63,8 +61,8 @@ @interface NSString (GRPCMetadata) + (instancetype)grpc_stringFromMetadataValue:(grpc_metadata *)metadata; -// Fill a metadata object with the textual value in this NSString and the given key. -- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key; +// Fill a metadata object with the textual value in this NSString. +- (void)grpc_initMetadata:(grpc_metadata *)metadata; @end @implementation NSString (GRPCMetadata) @@ -74,22 +72,8 @@ encoding:NSASCIIStringEncoding]; } -- (void)grpc_initMetadata:(grpc_metadata *)metadata withKey:(NSString *)key { - if ([key hasSuffix:@"-bin"]) { - // Disallow this, as at best it will confuse the server. If the app really needs to send a - // textual header with a name ending in "-bin", it can be done by removing the suffix and - // encoding the NSString as a NSData object. - // - // Why raise an exception: In the most common case, the developer knows this won't happen in - // their code, so the exception isn't triggered. In the rare cases when the developer can't - // tell, it's easy enough to add a sanitizing filter before the header is set. There, the - // developer can choose whether to drop such a header, or trim its name. Doing either ourselves, - // silently, would be very unintuitive for the user. - [NSException raise:NSInvalidArgumentException - format:@"Metadata keys ending in '-bin' are reserved for NSData values."]; - } - // TODO(jcanizales): Encode Unicode chars as ASCII. - metadata->key = key.UTF8String; +// Precondition: This object contains only ASCII characters. +- (void)grpc_initMetadata:(grpc_metadata *)metadata { metadata->value = self.UTF8String; metadata->value_length = self.length; } @@ -124,19 +108,21 @@ return metadata; } +// Preconditions: All keys are ASCII strings. Keys ending in -bin have NSData values; the others +// have NSString values. - (grpc_metadata *)grpc_metadataArray { grpc_metadata *metadata = gpr_malloc([self count] * sizeof(grpc_metadata)); - int i = 0; - for (id key in self) { + grpc_metadata *current = metadata; + for (NSString* key in self) { id value = self[key]; - grpc_metadata *current = &metadata[i]; - if ([value respondsToSelector:@selector(grpc_initMetadata:withKey:)]) { - [value grpc_initMetadata:current withKey:key]; + current->key = key.UTF8String; + if ([value respondsToSelector:@selector(grpc_initMetadata:)]) { + [value grpc_initMetadata:current]; } else { [NSException raise:NSInvalidArgumentException format:@"Metadata values must be NSString or NSData."]; } - i += 1; + ++current; } return metadata; } -- cgit v1.2.3 From d6599a39e48b152eeb1b55d427fbe5f22817b663 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 3 Sep 2015 09:37:02 -0700 Subject: Replicate C++ docs from master to beta branch Original PR #3074 by @dgquintas --- examples/cpp/helloworld/greeter_async_client.cc | 52 ++++++-- examples/cpp/helloworld/greeter_async_server.cc | 60 ++++++++-- examples/cpp/helloworld/greeter_client.cc | 24 +++- examples/cpp/helloworld/greeter_server.cc | 15 ++- include/grpc++/channel.h | 13 +- include/grpc++/client_context.h | 103 ++++++++++++++-- include/grpc++/completion_queue.h | 91 ++++++++++---- include/grpc++/create_channel.h | 19 ++- include/grpc++/grpc++.h | 64 ++++++++++ include/grpc++/security/auth_context.h | 26 +++- include/grpc++/security/credentials.h | 100 +++++++++++----- include/grpc++/security/server_credentials.h | 12 +- include/grpc++/server.h | 65 ++++++++-- include/grpc++/server_builder.h | 63 ++++++---- include/grpc++/support/async_stream.h | 37 ++++-- include/grpc++/support/byte_buffer.h | 14 ++- include/grpc++/support/channel_arguments.h | 25 ++-- include/grpc++/support/slice.h | 26 +++- include/grpc++/support/status.h | 12 ++ include/grpc++/support/status_code_enum.h | 153 +++++++++++------------- include/grpc++/support/string_ref.h | 13 +- include/grpc++/support/sync_stream.h | 89 +++++++++----- include/grpc/grpc.h | 8 +- src/core/surface/completion_queue.h | 2 +- src/cpp/util/byte_buffer.cc | 6 + 25 files changed, 786 insertions(+), 306 deletions(-) create mode 100644 include/grpc++/grpc++.h (limited to 'src') diff --git a/examples/cpp/helloworld/greeter_async_client.cc b/examples/cpp/helloworld/greeter_async_client.cc index 605fb7fb3a..923c8ffa74 100644 --- a/examples/cpp/helloworld/greeter_async_client.cc +++ b/examples/cpp/helloworld/greeter_async_client.cc @@ -35,13 +35,8 @@ #include #include -#include -#include -#include -#include -#include -#include -#include +#include + #include "helloworld.grpc.pb.h" using grpc::Channel; @@ -58,39 +53,72 @@ class GreeterClient { explicit GreeterClient(std::shared_ptr channel) : stub_(Greeter::NewStub(channel)) {} + // Assambles the client's payload, sends it and presents the response back + // from the server. std::string SayHello(const std::string& user) { + // Data we are sending to the server. HelloRequest request; request.set_name(user); + + // Container for the data we expect from the server. HelloReply reply; + + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. ClientContext context; + + // The producer-consumer queue we use to communicate asynchronously with the + // gRPC runtime. CompletionQueue cq; + + // Storage for the status of the RPC upon completion. Status status; + // stub_->AsyncSayHello() perform the RPC call, returning an instance we + // store in "rpc". Because we are using the asynchronous API, we need the + // hold on to the "rpc" instance in order to get updates on the ongoig RPC. std::unique_ptr > rpc( stub_->AsyncSayHello(&context, request, &cq)); + + // Request that, upon completion of the RPC, "reply" be updated with the + // server's response; "status" with the indication of whether the operation + // was successful. Tag the request with the integer 1. rpc->Finish(&reply, &status, (void*)1); void* got_tag; bool ok = false; + // Block until the next result is available in the completion queue "cq". cq.Next(&got_tag, &ok); - GPR_ASSERT(ok); + + // Verify that the result from "cq" corresponds, by its tag, our previous + // request. GPR_ASSERT(got_tag == (void*)1); + // ... and that the request was completed successfully. Note that "ok" + // corresponds solely to the request for updates introduced by Finish(). + GPR_ASSERT(ok); + // Act upon the status of the actual RPC. if (status.ok()) { return reply.message(); } else { - return "Rpc failed"; + return "RPC failed"; } } private: + // Out of the passed in Channel comes the stub, stored here, our view of the + // server's exposed services. std::unique_ptr stub_; }; int main(int argc, char** argv) { - GreeterClient greeter(grpc::CreateChannel( - "localhost:50051", grpc::InsecureCredentials())); + // Instantiate the client. It requires a channel, out of which the actual RPCs + // are created. This channel models a connection to an endpoint (in this case, + // localhost at port 50051). We indicate that the channel isn't authenticated + // (use of InsecureCredentials()). + GreeterClient greeter( + grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials())); std::string user("world"); - std::string reply = greeter.SayHello(user); + std::string reply = greeter.SayHello(user); // The actual RPC call! std::cout << "Greeter received: " << reply << std::endl; return 0; diff --git a/examples/cpp/helloworld/greeter_async_server.cc b/examples/cpp/helloworld/greeter_async_server.cc index 189c3afe6d..b2047a8ce5 100644 --- a/examples/cpp/helloworld/greeter_async_server.cc +++ b/examples/cpp/helloworld/greeter_async_server.cc @@ -36,13 +36,8 @@ #include #include -#include -#include -#include -#include -#include -#include -#include +#include + #include "helloworld.grpc.pb.h" using grpc::Server; @@ -59,6 +54,7 @@ class ServerImpl final { public: ~ServerImpl() { server_->Shutdown(); + // Always shutdown the completion queue after the server. cq_->Shutdown(); } @@ -67,56 +63,102 @@ class ServerImpl final { std::string server_address("0.0.0.0:50051"); ServerBuilder builder; + // Listen on the given address without any authentication mechanism. builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + // Register "service_" as the instance through which we'll communicate with + // clients. In this case it corresponds to an *asynchronous* service. builder.RegisterAsyncService(&service_); + // Get hold of the completion queue used for the asynchronous communication + // with the gRPC runtime. cq_ = builder.AddCompletionQueue(); + // Finally assemble the server. server_ = builder.BuildAndStart(); std::cout << "Server listening on " << server_address << std::endl; + // Proceed to the server's main loop. HandleRpcs(); } private: + // Class encompasing the state and logic needed to serve a request. class CallData { public: + // Take in the "service" instance (in this case representing an asynchronous + // server) and the completion queue "cq" used for asynchronous communication + // with the gRPC runtime. CallData(Greeter::AsyncService* service, ServerCompletionQueue* cq) : service_(service), cq_(cq), responder_(&ctx_), status_(CREATE) { + // Invoke the serving logic right away. Proceed(); } void Proceed() { if (status_ == CREATE) { + // As part of the initial CREATE state, we *request* that the system + // start processing SayHello requests. In this request, "this" acts are + // the tag uniquely identifying the request (so that different CallData + // instances can serve different requests concurrently), in this case + // the memory address of this CallData instance. service_->RequestSayHello(&ctx_, &request_, &responder_, cq_, cq_, this); + // Make this instance progress to the PROCESS state. status_ = PROCESS; } else if (status_ == PROCESS) { + // Spawn a new CallData instance to serve new clients while we process + // the one for this CallData. The instance will deallocate itself as + // part of its FINISH state. new CallData(service_, cq_); + + // The actual processing. std::string prefix("Hello "); reply_.set_message(prefix + request_.name()); + + // And we are done! Let the gRPC runtime know we've finished, using the + // memory address of this instance as the uniquely identifying tag for + // the event. responder_.Finish(reply_, Status::OK, this); status_ = FINISH; } else { + GPR_ASSERT(status_ == FINISH); + // Once in the FINISH state, deallocate ourselves (CallData). delete this; } } private: + // The means of communication with the gRPC runtime for an asynchronous + // server. Greeter::AsyncService* service_; + // The producer-consumer queue where for asynchronous server notifications. ServerCompletionQueue* cq_; + // Context for the rpc, allowing to tweak aspects of it such as the use + // of compression, authentication, as well as to send metadata back to the + // client. ServerContext ctx_; + + // What we get from the client. HelloRequest request_; + // What we send back to the client. HelloReply reply_; + + // The means to get back to the client. ServerAsyncResponseWriter responder_; + + // Let's implement a tiny state machine with the following states. enum CallStatus { CREATE, PROCESS, FINISH }; - CallStatus status_; + CallStatus status_; // The current serving state. }; // This can be run in multiple threads if needed. void HandleRpcs() { + // Spawn a new CallData instance to serve new clients. new CallData(&service_, cq_.get()); - void* tag; + void* tag; // uniquely identifies a request. bool ok; while (true) { + // Block waiting to read the next event from the completion queue. The + // event is uniquely identified by its tag, which in this case is the + // memory address of a CallData instance. cq_->Next(&tag, &ok); GPR_ASSERT(ok); static_cast(tag)->Proceed(); diff --git a/examples/cpp/helloworld/greeter_client.cc b/examples/cpp/helloworld/greeter_client.cc index bfb7c12724..6cd8353a9f 100644 --- a/examples/cpp/helloworld/greeter_client.cc +++ b/examples/cpp/helloworld/greeter_client.cc @@ -35,11 +35,8 @@ #include #include -#include -#include -#include -#include -#include +#include + #include "helloworld.grpc.pb.h" using grpc::Channel; @@ -54,17 +51,28 @@ class GreeterClient { GreeterClient(std::shared_ptr channel) : stub_(Greeter::NewStub(channel)) {} + // Assambles the client's payload, sends it and presents the response back + // from the server. std::string SayHello(const std::string& user) { + // Data we are sending to the server. HelloRequest request; request.set_name(user); + + // Container for the data we expect from the server. HelloReply reply; + + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. ClientContext context; + // The actual RPC. Status status = stub_->SayHello(&context, request, &reply); + + // Act upon its status. if (status.ok()) { return reply.message(); } else { - return "Rpc failed"; + return "RPC failed"; } } @@ -73,6 +81,10 @@ class GreeterClient { }; int main(int argc, char** argv) { + // Instantiate the client. It requires a channel, out of which the actual RPCs + // are created. This channel models a connection to an endpoint (in this case, + // localhost at port 50051). We indicate that the channel isn't authenticated + // (use of InsecureCredentials()). GreeterClient greeter( grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials())); std::string user("world"); diff --git a/examples/cpp/helloworld/greeter_server.cc b/examples/cpp/helloworld/greeter_server.cc index b434752d87..9eab32c62b 100644 --- a/examples/cpp/helloworld/greeter_server.cc +++ b/examples/cpp/helloworld/greeter_server.cc @@ -35,11 +35,8 @@ #include #include -#include -#include -#include -#include -#include +#include + #include "helloworld.grpc.pb.h" using grpc::Server; @@ -50,6 +47,7 @@ using helloworld::HelloRequest; using helloworld::HelloReply; using helloworld::Greeter; +// Logic and data behind the server's behavior. class GreeterServiceImpl final : public Greeter::Service { Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* reply) override { @@ -64,10 +62,17 @@ void RunServer() { GreeterServiceImpl service; ServerBuilder builder; + // Listen on the given address without any authentication mechanism. builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + // Register "service" as the instance through which we'll communicate with + // clients. In this case it corresponds to an *synchronous* service. builder.RegisterService(&service); + // Finally assemble the server. std::unique_ptr server(builder.BuildAndStart()); std::cout << "Server listening on " << server_address << std::endl; + + // Wait for the server to shutdown. Note that some other thread must be + // responsible for shutting down the server for this call to ever return. server->Wait(); } diff --git a/include/grpc++/channel.h b/include/grpc++/channel.h index a8af74175b..60c816d58a 100644 --- a/include/grpc++/channel.h +++ b/include/grpc++/channel.h @@ -65,18 +65,19 @@ class ClientAsyncReaderWriter; template class ClientAsyncResponseReader; +/// Channels represent a connection to an endpoint. Created by \a CreateChannel. class Channel GRPC_FINAL : public GrpcLibrary, public CallHook, public std::enable_shared_from_this { public: ~Channel(); - // Get the current channel state. If the channel is in IDLE and try_to_connect - // is set to true, try to connect. + /// Get the current channel state. If the channel is in IDLE and + /// \a try_to_connect is set to true, try to connect. grpc_connectivity_state GetState(bool try_to_connect); - // Return the tag on cq when the channel state is changed or deadline expires. - // GetState needs to called to get the current state. + /// Return the \a tag on \a cq when the channel state is changed or \a + /// deadline expires. \a GetState needs to called to get the current state. template void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline, CompletionQueue* cq, void* tag) { @@ -84,8 +85,8 @@ class Channel GRPC_FINAL : public GrpcLibrary, NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag); } - // Blocking wait for channel state change or deadline expiration. - // GetState needs to called to get the current state. + /// Blocking wait for channel state change or \a deadline expiration. + /// \a GetState needs to called to get the current state. template bool WaitForStateChange(grpc_connectivity_state last_observed, T deadline) { TimePoint deadline_tp(deadline); diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h index 917a1222a8..7046f939e5 100644 --- a/include/grpc++/client_context.h +++ b/include/grpc++/client_context.h @@ -31,6 +31,21 @@ * */ +/// A ClientContext allows the person implementing a service client to: +/// +/// - Add custom metadata key-value pairs that will propagated to the server +/// side. +/// - Control call settings such as compression and authentication. +/// - Initial and trailing metadata coming from the server. +/// - Get performance metrics (ie, census). +/// +/// Context settings are only relevant to the call they are invoked with, that +/// is to say, they aren't sticky. Some of these settings, such as the +/// compression options, can be made persistant at channel construction time +/// (see \a grpc::CreateCustomChannel). +/// +/// \warning ClientContext instances should \em not be reused across rpcs. + #ifndef GRPCXX_CLIENT_CONTEXT_H #define GRPCXX_CLIENT_CONTEXT_H @@ -72,6 +87,11 @@ template class ClientAsyncResponseReader; class ServerContext; +/// Options for \a ClientContext::FromServerContext specifying which traits from +/// the \a ServerContext to propagate (copy) from it into a new \a +/// ClientContext. +/// +/// \see ClientContext::FromServerContext class PropagationOptions { public: PropagationOptions() : propagate_(GRPC_PROPAGATE_DEFAULTS) {} @@ -131,26 +151,66 @@ class ClientContext { ClientContext(); ~ClientContext(); - /// Create a new ClientContext that propagates some or all of its attributes + /// Create a new \a ClientContext as a child of an incoming server call, + /// according to \a options (\see PropagationOptions). + /// + /// \param server_context The source server context to use as the basis for + /// constructing the client context. + /// \param options The options controlling what to copy from the \a + /// server_context. + /// + /// \return A newly constructed \a ClientContext instance based on \a + /// server_context, with traits propagated (copied) according to \a options. static std::unique_ptr FromServerContext( const ServerContext& server_context, PropagationOptions options = PropagationOptions()); + /// Add the (\a meta_key, \a meta_value) pair to the metadata associated with + /// a client call. These are made available at the server side by the \a + /// grpc::ServerContext::client_metadata() method. + /// + /// \warning This method should only be called before invoking the rpc. + /// + /// \param meta_key The metadata key. If \a meta_value is binary data, it must + /// end in "-bin". + /// \param meta_value The metadata value. If its value is binary, it must be + /// base64-encoding (see https://tools.ietf.org/html/rfc4648#section-4) and \a + /// meta_key must end in "-bin". void AddMetadata(const grpc::string& meta_key, const grpc::string& meta_value); + /// Return a collection of initial metadata key-value pairs. Note that keys + /// may happen more than once (ie, a \a std::multimap is returned). + /// + /// \warning This method should only be called after initial metadata has been + /// received. For streaming calls, see \a + /// ClientReaderInterface::WaitForInitialMetadata(). + /// + /// \return A multimap of initial metadata key-value pairs from the server. const std::multimap& GetServerInitialMetadata() { GPR_ASSERT(initial_metadata_received_); return recv_initial_metadata_; } + /// Return a collection of trailing metadata key-value pairs. Note that keys + /// may happen more than once (ie, a \a std::multimap is returned). + /// + /// \warning This method is only callable once the stream has finished. + /// + /// \return A multimap of metadata trailing key-value pairs from the server. const std::multimap& GetServerTrailingMetadata() { // TODO(yangg) check finished return trailing_metadata_; } + /// Set the deadline for the client call. + /// + /// \warning This method should only be called before invoking the rpc. + /// + /// \param deadline the deadline for the client call. Units are determined by + /// the type used. template void set_deadline(const T& deadline) { TimePoint deadline_tp(deadline); @@ -158,40 +218,65 @@ class ClientContext { } #ifndef GRPC_CXX0X_NO_CHRONO + /// Return the deadline for the client call. std::chrono::system_clock::time_point deadline() { return Timespec2Timepoint(deadline_); } #endif // !GRPC_CXX0X_NO_CHRONO + /// Return a \a gpr_timespec representation of the client call's deadline. gpr_timespec raw_deadline() { return deadline_; } + /// Set the per call authority header (see + /// https://tools.ietf.org/html/rfc7540#section-8.1.2.3). void set_authority(const grpc::string& authority) { authority_ = authority; } - // Set credentials for the rpc. + /// Return the authentication context for this client call. + /// + /// \see grpc::AuthContext. + std::shared_ptr auth_context() const; + + /// Set credentials for the client call. + /// + /// A credentials object encapsulates all the state needed by a client to + /// authenticate with a server and make various assertions, e.g., about the + /// client’s identity, role, or whether it is authorized to make a particular + /// call. + /// + /// \see https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md void set_credentials(const std::shared_ptr& creds) { creds_ = creds; } + /// Return the compression algorithm to be used by the client call. grpc_compression_algorithm compression_algorithm() const { return compression_algorithm_; } + /// Set \a algorithm to be the compression algorithm used for the client call. + /// + /// \param algorith The compression algorithm used for the client call. void set_compression_algorithm(grpc_compression_algorithm algorithm); - std::shared_ptr auth_context() const; - - // Return the peer uri in a string. - // WARNING: this value is never authenticated or subject to any security - // related code. It must not be used for any authentication related - // functionality. Instead, use auth_context. + /// Return the peer uri in a string. + /// + /// \warning This value is never authenticated or subject to any security + /// related code. It must not be used for any authentication related + /// functionality. Instead, use auth_context. + /// + /// \return The call's peer URI. grpc::string peer() const; - // Get and set census context + /// Get and set census context void set_census_context(struct census_context* ccp) { census_context_ = ccp; } struct census_context* census_context() const { return census_context_; } + /// Send a best-effort out-of-band cancel. The call could be in any stage. + /// e.g. if it is already finished, it may still return success. + /// + /// There is no guarantee the call will be cancelled. void TryCancel(); private: diff --git a/include/grpc++/completion_queue.h b/include/grpc++/completion_queue.h index d81d2e735d..0ea970417e 100644 --- a/include/grpc++/completion_queue.h +++ b/include/grpc++/completion_queue.h @@ -31,6 +31,8 @@ * */ +/// A completion queue implements a concurrent producer-consumer queue, with two +/// main methods, \a Next and \a AsyncNext. #ifndef GRPCXX_COMPLETION_QUEUE_H #define GRPCXX_COMPLETION_QUEUE_H @@ -67,53 +69,79 @@ class UnknownMethodHandler; class Channel; class ClientContext; +class CompletionQueueTag; class CompletionQueue; class RpcMethod; class Server; class ServerBuilder; class ServerContext; -class CompletionQueueTag { - public: - virtual ~CompletionQueueTag() {} - // Called prior to returning from Next(), return value - // is the status of the operation (return status is the default thing - // to do) - // If this function returns false, the tag is dropped and not returned - // from the completion queue - virtual bool FinalizeResult(void** tag, bool* status) = 0; -}; - -// grpc_completion_queue wrapper class +/// A thin wrapper around \a grpc_completion_queue (see / \a +/// src/core/surface/completion_queue.h). class CompletionQueue : public GrpcLibrary { public: + /// Default constructor. Implicitly creates a \a grpc_completion_queue + /// instance. CompletionQueue(); + + /// Wrap \a take, taking ownership of the instance. + /// + /// \param take The completion queue instance to wrap. Ownership is taken. explicit CompletionQueue(grpc_completion_queue* take); - ~CompletionQueue() GRPC_OVERRIDE; - // Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT - enum NextStatus { SHUTDOWN, GOT_EVENT, TIMEOUT }; + /// Destructor. Destroys the owned wrapped completion queue / instance. + ~CompletionQueue() GRPC_OVERRIDE; - // Nonblocking (until deadline) read from queue. - // Cannot rely on result of tag or ok if return is TIMEOUT + /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT. + enum NextStatus { + SHUTDOWN, ///< The completion queue has been shutdown. + GOT_EVENT, ///< Got a new event; \a tag will be filled in with its + ///< associated value; \a ok indicating its success. + TIMEOUT ///< deadline was reached. + }; + + /// Read from the queue, blocking up to \a deadline (or the queue's shutdown). + /// Both \a tag and \a ok are updated upon success (if an event is available + /// within the \a deadline). A \a tag points to an arbitrary location usually + /// employed to uniquely identify an event. + /// + /// \param tag[out] Upon sucess, updated to point to the event's tag. + /// \param ok[out] Upon sucess, true if read a regular event, false otherwise. + /// \param deadline[in] How long to block in wait for an event. + /// + /// \return The type of event read. template NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) { TimePoint deadline_tp(deadline); return AsyncNextInternal(tag, ok, deadline_tp.raw_time()); } - // Blocking read from queue. - // Returns false if the queue is ready for destruction, true if event - + /// Read from the queue, blocking until an event is available or the queue is + /// shutting down. + /// + /// \param tag[out] Updated to point to the read event's tag. + /// \param ok[out] true if read a regular event, false otherwise. + /// + /// \return true if read a regular event, false if the queue is shutting down. bool Next(void** tag, bool* ok) { return (AsyncNextInternal(tag, ok, gpr_inf_future(GPR_CLOCK_REALTIME)) != SHUTDOWN); } - // Shutdown has to be called, and the CompletionQueue can only be - // destructed when false is returned from Next(). + /// Request the shutdown of the queue. + /// + /// \warning This method must be called at some point. Once invoked, \a Next + /// will start to return false and \a AsyncNext will return \a + /// NextStatus::SHUTDOWN. Only once either one of these methods does that + /// (that is, once the queue has been \em drained) can an instance of this + /// class be destroyed. void Shutdown(); + /// Returns a \em raw pointer to the underlying \a grpc_completion_queue + /// instance. + /// + /// \warning Remember that the returned instance is owned. No transfer of + /// owership is performed. grpc_completion_queue* cq() { return cq_; } private: @@ -150,16 +178,29 @@ class CompletionQueue : public GrpcLibrary { NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline); - // Wraps grpc_completion_queue_pluck. - // Cannot be mixed with calls to Next(). + /// Wraps \a grpc_completion_queue_pluck. + /// \warning Must not be mixed with calls to \a Next. bool Pluck(CompletionQueueTag* tag); - // Does a single polling pluck on tag + /// Performs a single polling pluck on \a tag. void TryPluck(CompletionQueueTag* tag); grpc_completion_queue* cq_; // owned }; +/// An interface allowing implementors to process and filter event tags. +class CompletionQueueTag { + public: + virtual ~CompletionQueueTag() {} + // Called prior to returning from Next(), return value is the status of the + // operation (return status is the default thing to do). If this function + // returns false, the tag is dropped and not returned from the completion + // queue + virtual bool FinalizeResult(void** tag, bool* status) = 0; +}; + +/// A specific type of completion queue used by the processing of notifications +/// by servers. Instantiated by \a ServerBuilder. class ServerCompletionQueue : public CompletionQueue { private: friend class ServerBuilder; diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h index 72f05174e1..196d2927a9 100644 --- a/include/grpc++/create_channel.h +++ b/include/grpc++/create_channel.h @@ -42,13 +42,24 @@ namespace grpc { -// If creds does not hold an object or is invalid, a lame channel is returned. +/// Create a new \a Channel pointing to \a target +/// +/// \param target The URI of the endpoint to connect to. +/// \param creds Credentials to use for the created channel. If it does not hold +/// an object or is invalid, a lame channel is returned. +/// \param args Options for channel creation. std::shared_ptr CreateChannel( const grpc::string& target, const std::shared_ptr& creds); -// For advanced use and testing ONLY. Override default channel arguments only -// if necessary. -// If creds does not hold an object or is invalid, a lame channel is returned. +/// Create a new \em custom \a Channel pointing to \a target +/// +/// \warning For advanced use and testing ONLY. Override default channel +/// arguments only if necessary. +/// +/// \param target The URI of the endpoint to connect to. +/// \param creds Credentials to use for the created channel. If it does not hold +/// an object or is invalid, a lame channel is returned. +/// \param args Options for channel creation. std::shared_ptr CreateCustomChannel( const grpc::string& target, const std::shared_ptr& creds, const ChannelArguments& args); diff --git a/include/grpc++/grpc++.h b/include/grpc++/grpc++.h new file mode 100644 index 0000000000..b7d5fb0bbc --- /dev/null +++ b/include/grpc++/grpc++.h @@ -0,0 +1,64 @@ +/* + * + * 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. + * + */ + +/// \mainpage gRPC C++ API +/// +/// The gRPC C++ API mainly consists of the following classes: +/// - grpc::Channel, which represents the connection to an endpoint. See [the +/// gRPC Concepts page](http://www.grpc.io/docs/guides/concepts.html) for more +/// details. Channels are created by the factory function grpc::CreateChannel. +/// - grpc::CompletionQueue, the producer-consumer queue used for all +/// asynchronous communication with the gRPC runtime. +/// - grpc::ClientContext and grpc::ServerContext, where optional configuration +/// for an RPC can be set, such as setting custom metadata to be conveyed to the +/// peer, compression settings, authentication, etc. +/// - grpc::Server, representing a gRPC server, created by grpc::ServerBuilder. +/// +/// Refer to the +/// [examples](https://github.com/grpc/grpc/blob/master/examples/cpp) +/// for code putting these pieces into play. + +#ifndef GRPCXX_GRPCXX_H +#define GRPCXX_GRPCXX_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +#endif // GRPCXX_GRPCXX_H diff --git a/include/grpc++/security/auth_context.h b/include/grpc++/security/auth_context.h index fc2701e806..4b1bbd85bc 100644 --- a/include/grpc++/security/auth_context.h +++ b/include/grpc++/security/auth_context.h @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -73,26 +74,41 @@ class AuthPropertyIterator const char* name_; }; +/// Class encapsulating the Authentication Information. +/// +/// It includes the secure identity of the peer, the type of secure transport +/// used as well as any other properties required by the authorization layer. class AuthContext { public: virtual ~AuthContext() {} - // Returns true if the peer is authenticated. + /// Returns true if the peer is authenticated. virtual bool IsPeerAuthenticated() const = 0; - // A peer identity, in general is one or more properties (in which case they - // have the same name). + /// A peer identity. + /// + /// It is, in general, comprised of one or more properties (in which case they + /// have the same name). virtual std::vector GetPeerIdentity() const = 0; virtual grpc::string GetPeerIdentityPropertyName() const = 0; - // Returns all the property values with the given name. + /// Returns all the property values with the given name. virtual std::vector FindPropertyValues( const grpc::string& name) const = 0; - // Iteration over all the properties. + /// Iteration over all the properties. virtual AuthPropertyIterator begin() const = 0; virtual AuthPropertyIterator end() const = 0; + static string transport_security_type_property_name() { + return GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME; + } + static string ssl_transport_security_type() { + return GRPC_SSL_TRANSPORT_SECURITY_TYPE; + } + static string x509_cn_property_name() { return GRPC_X509_CN_PROPERTY_NAME; } + static string x509_san_property_name() { return GRPC_X509_SAN_PROPERTY_NAME; } + // Mutation functions: should only be used by an AuthMetadataProcessor. virtual void AddProperty(const grpc::string& key, const grpc::string_ref& value) = 0; diff --git a/include/grpc++/security/credentials.h b/include/grpc++/security/credentials.h index ce5a9e0606..e423849714 100644 --- a/include/grpc++/security/credentials.h +++ b/include/grpc++/security/credentials.h @@ -44,9 +44,17 @@ class ChannelArguments; class Channel; class SecureCredentials; +/// A credentials object encapsulates all the state needed by a client to +/// authenticate with a server and make various assertions, e.g., about the +/// client’s identity, role, or whether it is authorized to make a particular +/// call. +/// +/// \see https://github.com/grpc/grpc/blob/master/doc/grpc-auth-support.md class Credentials : public GrpcLibrary { public: ~Credentials() GRPC_OVERRIDE; + + /// Apply this instance's credentials to \a call. virtual bool ApplyToCall(grpc_call* call) = 0; protected: @@ -65,68 +73,96 @@ class Credentials : public GrpcLibrary { const grpc::string& target, const ChannelArguments& args) = 0; }; -// Options used to build SslCredentials -// pem_roots_cert is the buffer containing the PEM encoding of the server root -// certificates. If this parameter is empty, the default roots will be used. -// pem_private_key is the buffer containing the PEM encoding of the client's -// private key. This parameter can be empty if the client does not have a -// private key. -// pem_cert_chain is the buffer containing the PEM encoding of the client's -// certificate chain. This parameter can be empty if the client does not have -// a certificate chain. +/// Options used to build SslCredentials. struct SslCredentialsOptions { + /// The buffer containing the PEM encoding of the server root certificates. If + /// this parameter is empty, the default roots will be used. The default + /// roots can be overridden using the \a GRPC_DEFAULT_SSL_ROOTS_FILE_PATH + /// environment variable pointing to a file on the file system containing the + /// roots. grpc::string pem_root_certs; + + /// The buffer containing the PEM encoding of the client's private key. This + /// parameter can be empty if the client does not have a private key. grpc::string pem_private_key; + + /// The buffer containing the PEM encoding of the client's certificate chain. + /// This parameter can be empty if the client does not have a certificate + /// chain. grpc::string pem_cert_chain; }; -// Factories for building different types of Credentials -// The functions may return empty shared_ptr when credentials cannot be created. -// If a Credentials pointer is returned, it can still be invalid when used to -// create a channel. A lame channel will be created then and all rpcs will -// fail on it. - -// Builds credentials with reasonable defaults. +// Factories for building different types of Credentials The functions may +// return empty shared_ptr when credentials cannot be created. If a +// Credentials pointer is returned, it can still be invalid when used to create +// a channel. A lame channel will be created then and all rpcs will fail on it. + +/// Builds credentials with reasonable defaults. +/// +/// \warning Only use these credentials when connecting to a Google endpoint. +/// Using these credentials to connect to any other service may result in this +/// service being able to impersonate your client for requests to Google +/// services. std::shared_ptr GoogleDefaultCredentials(); -// Builds SSL Credentials given SSL specific options +/// Builds SSL Credentials given SSL specific options std::shared_ptr SslCredentials( const SslCredentialsOptions& options); -// Builds credentials for use when running in GCE +/// Builds credentials for use when running in GCE +/// +/// \warning Only use these credentials when connecting to a Google endpoint. +/// Using these credentials to connect to any other service may result in this +/// service being able to impersonate your client for requests to Google +/// services. std::shared_ptr GoogleComputeEngineCredentials(); -// Builds Service Account JWT Access credentials. -// json_key is the JSON key string containing the client's private key. -// token_lifetime_seconds is the lifetime in seconds of each Json Web Token -// (JWT) created with this credentials. It should not exceed -// grpc_max_auth_token_lifetime or will be cropped to this value. +/// Builds Service Account JWT Access credentials. +/// json_key is the JSON key string containing the client's private key. +/// token_lifetime_seconds is the lifetime in seconds of each Json Web Token +/// (JWT) created with this credentials. It should not exceed +/// grpc_max_auth_token_lifetime or will be cropped to this value. std::shared_ptr ServiceAccountJWTAccessCredentials( const grpc::string& json_key, long token_lifetime_seconds); -// Builds refresh token credentials. -// json_refresh_token is the JSON string containing the refresh token along -// with a client_id and client_secret. +/// Builds refresh token credentials. +/// json_refresh_token is the JSON string containing the refresh token along +/// with a client_id and client_secret. +/// +/// \warning Only use these credentials when connecting to a Google endpoint. +/// Using these credentials to connect to any other service may result in this +/// service being able to impersonate your client for requests to Google +/// services. std::shared_ptr GoogleRefreshTokenCredentials( const grpc::string& json_refresh_token); -// Builds access token credentials. -// access_token is an oauth2 access token that was fetched using an out of band -// mechanism. +/// Builds access token credentials. +/// access_token is an oauth2 access token that was fetched using an out of band +/// mechanism. +/// +/// \warning Only use these credentials when connecting to a Google endpoint. +/// Using these credentials to connect to any other service may result in this +/// service being able to impersonate your client for requests to Google +/// services. std::shared_ptr AccessTokenCredentials( const grpc::string& access_token); -// Builds IAM credentials. +/// Builds IAM credentials. +/// +/// \warning Only use these credentials when connecting to a Google endpoint. +/// Using these credentials to connect to any other service may result in this +/// service being able to impersonate your client for requests to Google +/// services. std::shared_ptr GoogleIAMCredentials( const grpc::string& authorization_token, const grpc::string& authority_selector); -// Combines two credentials objects into a composite credentials +/// Combines two credentials objects into a composite credentials std::shared_ptr CompositeCredentials( const std::shared_ptr& creds1, const std::shared_ptr& creds2); -// Credentials for an unencrypted, unauthenticated channel +/// Credentials for an unencrypted, unauthenticated channel std::shared_ptr InsecureCredentials(); } // namespace grpc diff --git a/include/grpc++/security/server_credentials.h b/include/grpc++/security/server_credentials.h index 2094c7403c..e933825ec3 100644 --- a/include/grpc++/security/server_credentials.h +++ b/include/grpc++/security/server_credentials.h @@ -45,7 +45,7 @@ struct grpc_server; namespace grpc { class Server; -// grpc_server_credentials wrapper class. +// Wrapper around \a grpc_server_credentials, a way to authenticate a server. class ServerCredentials { public: virtual ~ServerCredentials(); @@ -58,11 +58,16 @@ class ServerCredentials { private: friend class ::grpc::Server; + /// Tries to bind \a server to the given \a addr (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.) + /// + /// \return bound port number on sucess, 0 on failure. + // TODO(dgq): the "port" part seems to be a misnomer. virtual int AddPortToServer(const grpc::string& addr, grpc_server* server) = 0; }; -// Options to create ServerCredentials with SSL +/// Options to create ServerCredentials with SSL struct SslServerCredentialsOptions { SslServerCredentialsOptions() : force_client_auth(false) {} @@ -75,10 +80,11 @@ struct SslServerCredentialsOptions { bool force_client_auth; }; -// Builds SSL ServerCredentials given SSL specific options +/// Builds SSL ServerCredentials given SSL specific options std::shared_ptr SslServerCredentials( const SslServerCredentialsOptions& options); +/// Builds insecure server credentials. std::shared_ptr InsecureServerCredentials(); } // namespace grpc diff --git a/include/grpc++/server.h b/include/grpc++/server.h index 22d14ee652..18a8017880 100644 --- a/include/grpc++/server.h +++ b/include/grpc++/server.h @@ -57,24 +57,30 @@ class RpcServiceMethod; class ServerAsyncStreamingInterface; class ThreadPoolInterface; -// Currently it only supports handling rpcs in a single thread. +/// Models a gRPC server. +/// +/// Servers are configured and started via \a grpc::ServerBuilder. class Server GRPC_FINAL : public GrpcLibrary, private CallHook { public: ~Server(); - // Shutdown the server, block until all rpc processing finishes. - // Forcefully terminate pending calls after deadline expires. + /// Shutdown the server, blocking until all rpc processing finishes. + /// Forcefully terminate pending calls after \a deadline expires. + /// + /// \param deadline How long to wait until pending rpcs are forcefully + /// terminated. template void Shutdown(const T& deadline) { ShutdownInternal(TimePoint(deadline).raw_time()); } - // Shutdown the server, waiting for all rpc processing to finish. + /// Shutdown the server, waiting for all rpc processing to finish. void Shutdown() { ShutdownInternal(gpr_inf_future(GPR_CLOCK_MONOTONIC)); } - // Block waiting for all work to complete (the server must either - // be shutting down or some other thread must call Shutdown for this - // function to ever return) + /// Block waiting for all work to complete. + /// + /// \warning The server must be either shutting down or some other thread must + /// call \a Shutdown for this function to ever return. void Wait(); private: @@ -86,22 +92,57 @@ class Server GRPC_FINAL : public GrpcLibrary, private CallHook { class AsyncRequest; class ShutdownRequest; - // ServerBuilder use only + /// Server constructors. To be used by \a ServerBuilder only. + /// + /// \param thread_pool The threadpool instance to use for call processing. + /// \param thread_pool_owned Does the server own the \a thread_pool instance? + /// \param max_message_size Maximum message length that the channel can + /// receive. Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned, int max_message_size); - // Register a service. This call does not take ownership of the service. - // The service must exist for the lifetime of the Server instance. + + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the Server instance. bool RegisterService(const grpc::string* host, RpcService* service); + + /// Register an asynchronous service. This call does not take ownership of the + /// service. The service must exist for the lifetime of the Server instance. bool RegisterAsyncService(const grpc::string* host, AsynchronousService* service); + + /// Register a generic service. This call does not take ownership of the + /// service. The service must exist for the lifetime of the Server instance. void RegisterAsyncGenericService(AsyncGenericService* service); - // Add a listening port. Can be called multiple times. + + /// Tries to bind \a server to the given \a addr. + /// + /// It can be invoked multiple times. + /// + /// \param addr The address to try to bind to the server (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.). + /// \params creds The credentials associated with the server. + /// + /// \return bound port number on sucess, 0 on failure. + /// + /// \warning It's an error to call this method on an already started server. int AddListeningPort(const grpc::string& addr, ServerCredentials* creds); - // Start the server. + + /// Start the server. + /// + /// \param cqs Completion queues for handling asynchronous services. The + /// caller is required to keep all completion queues live until the server is + /// destroyed. + /// \param num_cqs How many completion queues does \a cqs hold. + /// + /// \return true on a successful shutdown. bool Start(ServerCompletionQueue** cqs, size_t num_cqs); void HandleQueueClosed(); + + /// Process one or more incoming calls. void RunRpc(); + + /// Schedule \a RunRpc to run in the threadpool. void ScheduleCallback(); void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) GRPC_OVERRIDE; diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index 8cd2048592..496e7862c5 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -51,57 +51,68 @@ class ServerCredentials; class SynchronousService; class ThreadPoolInterface; +/// A builder class for the creation and startup of \a grpc::Server instances. class ServerBuilder { public: ServerBuilder(); - // Register a service. This call does not take ownership of the service. - // The service must exist for the lifetime of the Server instance returned by - // BuildAndStart(). - // Matches requests with any :authority + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the \a Server instance returned + /// by \a BuildAndStart(). + /// Matches requests with any :authority void RegisterService(SynchronousService* service); - // Register an asynchronous service. - // This call does not take ownership of the service or completion queue. - // The service and completion queuemust exist for the lifetime of the Server - // instance returned by BuildAndStart(). - // Matches requests with any :authority + /// Register an asynchronous service. + /// This call does not take ownership of the service or completion queue. + /// The service and completion queuemust exist for the lifetime of the \a + /// Server instance returned by \a BuildAndStart(). + /// Matches requests with any :authority void RegisterAsyncService(AsynchronousService* service); - // Register a generic service. - // Matches requests with any :authority + /// Register a generic service. + /// Matches requests with any :authority void RegisterAsyncGenericService(AsyncGenericService* service); - // Register a service. This call does not take ownership of the service. - // The service must exist for the lifetime of the Server instance returned by - // BuildAndStart(). - // Only matches requests with :authority \a host + /// Register a service. This call does not take ownership of the service. + /// The service must exist for the lifetime of the \a Server instance returned + /// by BuildAndStart(). + /// Only matches requests with :authority \a host void RegisterService(const grpc::string& host, SynchronousService* service); - // Register an asynchronous service. - // This call does not take ownership of the service or completion queue. - // The service and completion queuemust exist for the lifetime of the Server - // instance returned by BuildAndStart(). - // Only matches requests with :authority \a host + /// Register an asynchronous service. + /// This call does not take ownership of the service or completion queue. + /// The service and completion queuemust exist for the lifetime of the \a + /// Server instance returned by \a BuildAndStart(). + /// Only matches requests with :authority equal to \a host void RegisterAsyncService(const grpc::string& host, AsynchronousService* service); - // Set max message size in bytes. + /// Set max message size in bytes. void SetMaxMessageSize(int max_message_size) { max_message_size_ = max_message_size; } - // Add a listening port. Can be called multiple times. + /// Tries to bind \a server to the given \a addr. + /// + /// It can be invoked multiple times. + /// + /// \param addr The address to try to bind to the server (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.). + /// \params creds The credentials associated with the server. + /// \param selected_port[out] Upon success, updated to contain the port + /// number. \a nullptr otherwise. + /// + // TODO(dgq): the "port" part seems to be a misnomer. void AddListeningPort(const grpc::string& addr, std::shared_ptr creds, int* selected_port = nullptr); - // Add a completion queue for handling asynchronous services - // Caller is required to keep this completion queue live until - // the server is destroyed. + /// Add a completion queue for handling asynchronous services + /// Caller is required to keep this completion queue live until + /// the server is destroyed. std::unique_ptr AddCompletionQueue(); - // Return a running server which is ready for processing rpcs. + /// Return a running server which is ready for processing calls. std::unique_ptr BuildAndStart(); private: diff --git a/include/grpc++/support/async_stream.h b/include/grpc++/support/async_stream.h index 4c12fda12f..b4dae30cd5 100644 --- a/include/grpc++/support/async_stream.h +++ b/include/grpc++/support/async_stream.h @@ -45,32 +45,48 @@ namespace grpc { -// Async interfaces -// Common interface for all client side streaming. +/// Common interface for all client side asynchronous streaming. class ClientAsyncStreamingInterface { public: virtual ~ClientAsyncStreamingInterface() {} + /// Request notification of the reading of the initial metadata. Completion + /// will be notified by \a tag on the associated completion queue. + /// + /// \param[in] tag Tag identifying this request. virtual void ReadInitialMetadata(void* tag) = 0; + /// Request notification completion. + /// + /// \param[out] status To be updated with the operation status. + /// \param[in] tag Tag identifying this request. virtual void Finish(Status* status, void* tag) = 0; }; -// An interface that yields a sequence of R messages. +/// An interface that yields a sequence of messages of type \a R. template class AsyncReaderInterface { public: virtual ~AsyncReaderInterface() {} + /// Read a message of type \a R into \a msg. Completion will be notified by \a + /// tag on the associated completion queue. + /// + /// \param[out] msg Where to eventually store the read message. + /// \param[in] tag The tag identifying the operation. virtual void Read(R* msg, void* tag) = 0; }; -// An interface that can be fed a sequence of W messages. +/// An interface that can be fed a sequence of messages of type \a W. template class AsyncWriterInterface { public: virtual ~AsyncWriterInterface() {} + /// Request the writing of \a msg with identifying tag \a tag. + /// + /// \param[in] msg The message to be written. + /// \param[in] tag The tag identifying the operation. virtual void Write(const W& msg, void* tag) = 0; }; @@ -81,7 +97,7 @@ class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface, template class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface { public: - // Create a stream and write the first request out. + /// Create a stream and write the first request out. template ClientAsyncReader(Channel* channel, CompletionQueue* cq, const RpcMethod& method, ClientContext* context, @@ -131,10 +147,14 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface { CallOpSet finish_ops_; }; +/// Common interface for client side asynchronous writing. template class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface, public AsyncWriterInterface { public: + /// Signal the client is done with the writes. + /// + /// \param[in] tag The tag identifying the operation. virtual void WritesDone(void* tag) = 0; }; @@ -194,12 +214,15 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface { CallOpClientRecvStatus> finish_ops_; }; -// Client-side interface for bi-directional streaming. +/// Client-side interface for asynchronous bi-directional streaming. template class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface, public AsyncWriterInterface, public AsyncReaderInterface { public: + /// Signal the client is done with the writes. + /// + /// \param[in] tag The tag identifying the operation. virtual void WritesDone(void* tag) = 0; }; @@ -373,7 +396,7 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface, CallOpSet finish_ops_; }; -// Server-side interface for bi-directional streaming. +/// Server-side interface for asynchronous bi-directional streaming. template class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface, public AsyncWriterInterface, diff --git a/include/grpc++/support/byte_buffer.h b/include/grpc++/support/byte_buffer.h index 3f8cc25f47..c413703970 100644 --- a/include/grpc++/support/byte_buffer.h +++ b/include/grpc++/support/byte_buffer.h @@ -46,21 +46,24 @@ namespace grpc { +/// A sequence of bytes. class ByteBuffer GRPC_FINAL { public: + /// Constuct an empty buffer. ByteBuffer() : buffer_(nullptr) {} + /// Construct buffer from \a slices, of which there are \a nslices. ByteBuffer(const Slice* slices, size_t nslices); - ~ByteBuffer() { - if (buffer_) { - grpc_byte_buffer_destroy(buffer_); - } - } + ~ByteBuffer(); + /// Dump (read) the buffer contents into \a slices. void Dump(std::vector* slices) const; + /// Remove all data. void Clear(); + + /// Buffer size in bytes. size_t Length() const; private: @@ -78,6 +81,7 @@ class ByteBuffer GRPC_FINAL { buffer_ = buf; } + // For \a SerializationTraits's usage. grpc_byte_buffer* buffer() const { return buffer_; } grpc_byte_buffer* buffer_; diff --git a/include/grpc++/support/channel_arguments.h b/include/grpc++/support/channel_arguments.h index cee68467c7..9957712a96 100644 --- a/include/grpc++/support/channel_arguments.h +++ b/include/grpc++/support/channel_arguments.h @@ -46,9 +46,9 @@ namespace testing { class ChannelArgumentsTest; } // namespace testing -// Options for channel creation. The user can use generic setters to pass -// key value pairs down to c channel creation code. For grpc related options, -// concrete setters are provided. +/// Options for channel creation. The user can use generic setters to pass +/// key value pairs down to c channel creation code. For grpc related options, +/// concrete setters are provided. class ChannelArguments { public: ChannelArguments() {} @@ -62,21 +62,26 @@ class ChannelArguments { void Swap(ChannelArguments& other); - // grpc specific channel argument setters - // Set target name override for SSL host name checking. + /// Populates this instance with the arguments from \a channel_args. Does not + /// take ownership of \a channel_args. + /// + /// Note that the underlying arguments are shared. Changes made to either \a + /// channel_args or this instance would be reflected on both. + void SetChannelArgs(grpc_channel_args* channel_args) const; + + // gRPC specific channel argument setters + /// Set target name override for SSL host name checking. void SetSslTargetNameOverride(const grpc::string& name); // TODO(yangg) add flow control options - - // Set the compression algorithm for the channel. + /// Set the compression algorithm for the channel. void SetCompressionAlgorithm(grpc_compression_algorithm algorithm); // Generic channel argument setters. Only for advanced use cases. + /// Set an integer argument \a value under \a key. void SetInt(const grpc::string& key, int value); + /// Set a textual argument \a value under \a key. void SetString(const grpc::string& key, const grpc::string& value); - // Populates given channel_args with args_, does not take ownership. - void SetChannelArgs(grpc_channel_args* channel_args) const; - private: friend class SecureCredentials; friend class testing::ChannelArgumentsTest; diff --git a/include/grpc++/support/slice.h b/include/grpc++/support/slice.h index b2343a7f3d..456379cc5b 100644 --- a/include/grpc++/support/slice.h +++ b/include/grpc++/support/slice.h @@ -39,28 +39,42 @@ namespace grpc { +/// A wrapper around \a grpc_slice. +/// +/// A slice represents a contiguous reference counted array of bytes. +/// It is cheap to take references to a slice, and it is cheap to create a +/// slice pointing to a subset of another slice. class Slice GRPC_FINAL { public: - // construct empty slice + /// Construct an empty slice. Slice(); - // destructor - drops one ref + // Destructor - drops one reference. ~Slice(); - // construct slice from grpc slice, adding a ref + enum AddRef { ADD_REF }; + /// Construct a slice from \a slice, adding a reference. Slice(gpr_slice slice, AddRef); - // construct slice from grpc slice, stealing a ref + enum StealRef { STEAL_REF }; + /// Construct a slice from \a slice, stealing a reference. Slice(gpr_slice slice, StealRef); - // copy constructor - adds a ref + + /// Copy constructor, adds a reference. Slice(const Slice& other); - // assignment - ref count is unchanged + + /// Assignment, reference count is unchanged. Slice& operator=(Slice other) { std::swap(slice_, other.slice_); return *this; } + /// Byte size. size_t size() const { return GPR_SLICE_LENGTH(slice_); } + + /// Raw pointer to the beginning (first element) of the slice. const gpr_uint8* begin() const { return GPR_SLICE_START_PTR(slice_); } + + /// Raw pointer to the end (one byte \em past the last element) of the slice. const gpr_uint8* end() const { return GPR_SLICE_END_PTR(slice_); } private: diff --git a/include/grpc++/support/status.h b/include/grpc++/support/status.h index 05750ff600..e59bac92d1 100644 --- a/include/grpc++/support/status.h +++ b/include/grpc++/support/status.h @@ -39,19 +39,31 @@ namespace grpc { +/// Did it work? If it didn't, why? +/// +/// See \a grpc::StatusCode for details on the available code and their meaning. class Status { public: + /// Construct an OK instance. Status() : code_(StatusCode::OK) {} + + /// Construct an instance with associated \a code and \a details (also + // referred to as "error_message"). Status(StatusCode code, const grpc::string& details) : code_(code), details_(details) {} // Pre-defined special status objects. + /// An OK pre-defined instance. static const Status& OK; + /// A CANCELLED pre-defined instance. static const Status& CANCELLED; + /// Return the instance's error code. StatusCode error_code() const { return code_; } + /// Return the instance's error message. grpc::string error_message() const { return details_; } + /// Is the status OK? bool ok() const { return code_ == StatusCode::OK; } private: diff --git a/include/grpc++/support/status_code_enum.h b/include/grpc++/support/status_code_enum.h index 7cb40452c8..ee05b40b51 100644 --- a/include/grpc++/support/status_code_enum.h +++ b/include/grpc++/support/status_code_enum.h @@ -37,120 +37,113 @@ namespace grpc { enum StatusCode { - /* Not an error; returned on success */ + /// Not an error; returned on success. OK = 0, - /* The operation was cancelled (typically by the caller). */ + /// The operation was cancelled (typically by the caller). CANCELLED = 1, - /* Unknown error. An example of where this error may be returned is - if a Status value received from another address space belongs to - an error-space that is not known in this address space. Also - errors raised by APIs that do not return enough error information - may be converted to this error. */ + /// Unknown error. An example of where this error may be returned is if a + /// Status value received from another address space belongs to an error-space + /// that is not known in this address space. Also errors raised by APIs that + /// do not return enough error information may be converted to this error. UNKNOWN = 2, - /* Client specified an invalid argument. Note that this differs - from FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments - that are problematic regardless of the state of the system - (e.g., a malformed file name). */ + /// Client specified an invalid argument. Note that this differs from + /// FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are + /// problematic regardless of the state of the system (e.g., a malformed file + /// name). INVALID_ARGUMENT = 3, - /* Deadline expired before operation could complete. For operations - that change the state of the system, this error may be returned - even if the operation has completed successfully. For example, a - successful response from a server could have been delayed long - enough for the deadline to expire. */ + /// Deadline expired before operation could complete. For operations that + /// change the state of the system, this error may be returned even if the + /// operation has completed successfully. For example, a successful response + /// from a server could have been delayed long enough for the deadline to + /// expire. DEADLINE_EXCEEDED = 4, - /* Some requested entity (e.g., file or directory) was not found. */ + /// Some requested entity (e.g., file or directory) was not found. NOT_FOUND = 5, - /* Some entity that we attempted to create (e.g., file or directory) - already exists. */ + /// Some entity that we attempted to create (e.g., file or directory) already + /// exists. ALREADY_EXISTS = 6, - /* The caller does not have permission to execute the specified - operation. PERMISSION_DENIED must not be used for rejections - caused by exhausting some resource (use RESOURCE_EXHAUSTED - instead for those errors). PERMISSION_DENIED must not be - used if the caller can not be identified (use UNAUTHENTICATED - instead for those errors). */ + /// The caller does not have permission to execute the specified operation. + /// PERMISSION_DENIED must not be used for rejections caused by exhausting + /// some resource (use RESOURCE_EXHAUSTED instead for those errors). + /// PERMISSION_DENIED must not be used if the caller can not be identified + /// (use UNAUTHENTICATED instead for those errors). PERMISSION_DENIED = 7, - /* The request does not have valid authentication credentials for the - operation. */ + /// The request does not have valid authentication credentials for the + /// operation. UNAUTHENTICATED = 16, - /* Some resource has been exhausted, perhaps a per-user quota, or - perhaps the entire file system is out of space. */ + /// Some resource has been exhausted, perhaps a per-user quota, or perhaps the + /// entire file system is out of space. RESOURCE_EXHAUSTED = 8, - /* Operation was rejected because the system is not in a state - required for the operation's execution. For example, directory - to be deleted may be non-empty, an rmdir operation is applied to - a non-directory, etc. - - A litmus test that may help a service implementor in deciding - between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: - (a) Use UNAVAILABLE if the client can retry just the failing call. - (b) Use ABORTED if the client should retry at a higher-level - (e.g., restarting a read-modify-write sequence). - (c) Use FAILED_PRECONDITION if the client should not retry until - the system state has been explicitly fixed. E.g., if an "rmdir" - fails because the directory is non-empty, FAILED_PRECONDITION - should be returned since the client should not retry unless - they have first fixed up the directory by deleting files from it. - (d) Use FAILED_PRECONDITION if the client performs conditional - REST Get/Update/Delete on a resource and the resource on the - server does not match the condition. E.g., conflicting - read-modify-write on the same resource. */ + /// Operation was rejected because the system is not in a state required for + /// the operation's execution. For example, directory to be deleted may be + /// non-empty, an rmdir operation is applied to a non-directory, etc. + /// + /// A litmus test that may help a service implementor in deciding + /// between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE: + /// (a) Use UNAVAILABLE if the client can retry just the failing call. + /// (b) Use ABORTED if the client should retry at a higher-level + /// (e.g., restarting a read-modify-write sequence). + /// (c) Use FAILED_PRECONDITION if the client should not retry until + /// the system state has been explicitly fixed. E.g., if an "rmdir" + /// fails because the directory is non-empty, FAILED_PRECONDITION + /// should be returned since the client should not retry unless + /// they have first fixed up the directory by deleting files from it. + /// (d) Use FAILED_PRECONDITION if the client performs conditional + /// REST Get/Update/Delete on a resource and the resource on the + /// server does not match the condition. E.g., conflicting + /// read-modify-write on the same resource. FAILED_PRECONDITION = 9, - /* The operation was aborted, typically due to a concurrency issue - like sequencer check failures, transaction aborts, etc. - - See litmus test above for deciding between FAILED_PRECONDITION, - ABORTED, and UNAVAILABLE. */ + /// The operation was aborted, typically due to a concurrency issue like + /// sequencer check failures, transaction aborts, etc. + /// + /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, + /// and UNAVAILABLE. ABORTED = 10, - /* Operation was attempted past the valid range. E.g., seeking or - reading past end of file. - - Unlike INVALID_ARGUMENT, this error indicates a problem that may - be fixed if the system state changes. For example, a 32-bit file - system will generate INVALID_ARGUMENT if asked to read at an - offset that is not in the range [0,2^32-1], but it will generate - OUT_OF_RANGE if asked to read from an offset past the current - file size. - - There is a fair bit of overlap between FAILED_PRECONDITION and - OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific - error) when it applies so that callers who are iterating through - a space can easily look for an OUT_OF_RANGE error to detect when - they are done. */ + /// Operation was attempted past the valid range. E.g., seeking or reading + /// past end of file. + /// + /// Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed + /// if the system state changes. For example, a 32-bit file system will + /// generate INVALID_ARGUMENT if asked to read at an offset that is not in the + /// range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from + /// an offset past the current file size. + /// + /// There is a fair bit of overlap between FAILED_PRECONDITION and + /// OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error) + /// when it applies so that callers who are iterating through a space can + /// easily look for an OUT_OF_RANGE error to detect when they are done. OUT_OF_RANGE = 11, - /* Operation is not implemented or not supported/enabled in this service. */ + /// Operation is not implemented or not supported/enabled in this service. UNIMPLEMENTED = 12, - /* Internal errors. Means some invariants expected by underlying - system has been broken. If you see one of these errors, - something is very broken. */ + /// Internal errors. Means some invariants expected by underlying System has + /// been broken. If you see one of these errors, Something is very broken. INTERNAL = 13, - /* The service is currently unavailable. This is a most likely a - transient condition and may be corrected by retrying with - a backoff. - - See litmus test above for deciding between FAILED_PRECONDITION, - ABORTED, and UNAVAILABLE. */ + /// The service is currently unavailable. This is a most likely a transient + /// condition and may be corrected by retrying with a backoff. + /// + /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED, + /// and UNAVAILABLE. UNAVAILABLE = 14, - /* Unrecoverable data loss or corruption. */ + /// Unrecoverable data loss or corruption. DATA_LOSS = 15, - /* Force users to include a default branch: */ + /// Force users to include a default branch: DO_NOT_USE = -1 }; diff --git a/include/grpc++/support/string_ref.h b/include/grpc++/support/string_ref.h index 2bc1fecefe..a17e167d2b 100644 --- a/include/grpc++/support/string_ref.h +++ b/include/grpc++/support/string_ref.h @@ -41,11 +41,14 @@ namespace grpc { -// This class is a non owning reference to a string. -// It should be a strict subset of the upcoming std::string_ref. See: -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html -// The constexpr is dropped or replaced with const for legacy compiler -// compatibility. +/// This class is a non owning reference to a string. +/// +/// It should be a strict subset of the upcoming std::string_ref. +/// +/// \see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html +/// +/// The constexpr is dropped or replaced with const for legacy compiler +/// compatibility. class string_ref { public: // types diff --git a/include/grpc++/support/sync_stream.h b/include/grpc++/support/sync_stream.h index b4bb637ff2..514363338d 100644 --- a/include/grpc++/support/sync_stream.h +++ b/include/grpc++/support/sync_stream.h @@ -45,60 +45,78 @@ namespace grpc { -// Common interface for all client side streaming. +/// Common interface for all synchronous client side streaming. class ClientStreamingInterface { public: virtual ~ClientStreamingInterface() {} - // Wait until the stream finishes, and return the final status. When the - // client side declares it has no more message to send, either implicitly or - // by calling WritesDone, it needs to make sure there is no more message to - // be received from the server, either implicitly or by getting a false from - // a Read(). - // This function will return either: - // - when all incoming messages have been read and the server has returned - // status - // - OR when the server has returned a non-OK status + /// Wait until the stream finishes, and return the final status. When the + /// client side declares it has no more message to send, either implicitly or + /// by calling \a WritesDone(), it needs to make sure there is no more message + /// to be received from the server, either implicitly or by getting a false + /// from a \a Read(). + /// + /// This function will return either: + /// - when all incoming messages have been read and the server has returned + /// status. + /// - OR when the server has returned a non-OK status. virtual Status Finish() = 0; }; -// An interface that yields a sequence of R messages. +/// An interface that yields a sequence of messages of type \a R. template class ReaderInterface { public: virtual ~ReaderInterface() {} - // Blocking read a message and parse to msg. Returns true on success. - // The method returns false when there will be no more incoming messages, - // either because the other side has called WritesDone or the stream has - // failed (or been cancelled). + /// Blocking read a message and parse to \a msg. Returns \a true on success. + /// + /// \param[out] msg The read message. + /// + /// \return \a false when there will be no more incoming messages, either + /// because the other side has called \a WritesDone() or the stream has failed + /// (or been cancelled). virtual bool Read(R* msg) = 0; }; -// An interface that can be fed a sequence of W messages. +/// An interface that can be fed a sequence of messages of type \a W. template class WriterInterface { public: virtual ~WriterInterface() {} - // Blocking write msg to the stream. Returns true on success. - // Returns false when the stream has been closed. + /// Blocking write \a msg to the stream with options. + /// + /// \param msg The message to be written to the stream. + /// \param options Options affecting the write operation. + /// + /// \return \a true on success, \a false when the stream has been closed. virtual bool Write(const W& msg, const WriteOptions& options) = 0; + /// Blocking write \a msg to the stream with default options. + /// + /// \param msg The message to be written to the stream. + /// + /// \return \a true on success, \a false when the stream has been closed. inline bool Write(const W& msg) { return Write(msg, WriteOptions()); } }; +/// Client-side interface for streaming reads of message of type \a R. template class ClientReaderInterface : public ClientStreamingInterface, public ReaderInterface { public: + /// Blocking wait for initial metadata from server. The received metadata + /// can only be accessed after this call returns. Should only be called before + /// the first read. Calling this method is optional, and if it is not called + /// the metadata will be available in ClientContext after the first read. virtual void WaitForInitialMetadata() = 0; }; template class ClientReader GRPC_FINAL : public ClientReaderInterface { public: - // Blocking create a stream and write the first request out. + /// Blocking create a stream and write the first request out. template ClientReader(Channel* channel, const RpcMethod& method, ClientContext* context, const W& request) @@ -113,17 +131,13 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface { cq_.Pluck(&ops); } - // Blocking wait for initial metadata from server. The received metadata - // can only be accessed after this call returns. Should only be called before - // the first read. Calling this method is optional, and if it is not called - // the metadata will be available in ClientContext after the first read. void WaitForInitialMetadata() { GPR_ASSERT(!context_->initial_metadata_received_); CallOpSet ops; ops.RecvInitialMetadata(context_); call_.PerformOps(&ops); - cq_.Pluck(&ops); // status ignored + cq_.Pluck(&ops); /// status ignored } bool Read(R* msg) GRPC_OVERRIDE { @@ -151,17 +165,22 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface { Call call_; }; +/// Client-side interface for streaming writes of message of type \a W. template class ClientWriterInterface : public ClientStreamingInterface, public WriterInterface { public: + /// Half close writing from the client. + /// Block until writes are completed. + /// + /// \return Whether the writes were successful. virtual bool WritesDone() = 0; }; template class ClientWriter : public ClientWriterInterface { public: - // Blocking create a stream. + /// Blocking create a stream. template ClientWriter(Channel* channel, const RpcMethod& method, ClientContext* context, R* response) @@ -191,7 +210,7 @@ class ClientWriter : public ClientWriterInterface { return cq_.Pluck(&ops); } - // Read the final response and wait for the final status. + /// Read the final response and wait for the final status. Status Finish() GRPC_OVERRIDE { Status status; finish_ops_.ClientRecvStatus(context_, &status); @@ -207,20 +226,28 @@ class ClientWriter : public ClientWriterInterface { Call call_; }; -// Client-side interface for bi-directional streaming. +/// Client-side interface for bi-directional streaming. template class ClientReaderWriterInterface : public ClientStreamingInterface, public WriterInterface, public ReaderInterface { public: + /// Blocking wait for initial metadata from server. The received metadata + /// can only be accessed after this call returns. Should only be called before + /// the first read. Calling this method is optional, and if it is not called + /// the metadata will be available in ClientContext after the first read. virtual void WaitForInitialMetadata() = 0; + + /// Block until writes are completed. + /// + /// \return Whether the writes were successful. virtual bool WritesDone() = 0; }; template class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface { public: - // Blocking create a stream. + /// Blocking create a stream. ClientReaderWriter(Channel* channel, const RpcMethod& method, ClientContext* context) : context_(context), call_(channel->CreateCall(method, context, &cq_)) { @@ -230,10 +257,6 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface { cq_.Pluck(&ops); } - // Blocking wait for initial metadata from server. The received metadata - // can only be accessed after this call returns. Should only be called before - // the first read. Calling this method is optional, and if it is not called - // the metadata will be available in ClientContext after the first read. void WaitForInitialMetadata() { GPR_ASSERT(!context_->initial_metadata_received_); @@ -344,7 +367,7 @@ class ServerWriter GRPC_FINAL : public WriterInterface { ServerContext* const ctx_; }; -// Server-side interface for bi-directional streaming. +/// Server-side interface for bi-directional streaming. template class ServerReaderWriter GRPC_FINAL : public WriterInterface, public ReaderInterface { diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index a75f356312..47f3df6605 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -47,11 +47,9 @@ extern "C" { /*! \mainpage GRPC Core * - * \section intro_sec The GRPC Core library is a low-level library designed - * to be wrapped by higher level libraries. - * - * The top-level API is provided in grpc.h. - * Security related functionality lives in grpc_security.h. + * The GRPC Core library is a low-level library designed to be wrapped by higher + * level libraries. The top-level API is provided in grpc.h. Security related + * functionality lives in grpc_security.h. */ /** Completion Queues enable notification of the completion of asynchronous diff --git a/src/core/surface/completion_queue.h b/src/core/surface/completion_queue.h index 8de024aaea..74dc09e36e 100644 --- a/src/core/surface/completion_queue.h +++ b/src/core/surface/completion_queue.h @@ -34,7 +34,7 @@ #ifndef GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H #define GRPC_INTERNAL_CORE_SURFACE_COMPLETION_QUEUE_H -/* Internal API for completion channels */ +/* Internal API for completion queues */ #include "src/core/iomgr/pollset.h" #include diff --git a/src/cpp/util/byte_buffer.cc b/src/cpp/util/byte_buffer.cc index e46e656beb..755234d7e8 100644 --- a/src/cpp/util/byte_buffer.cc +++ b/src/cpp/util/byte_buffer.cc @@ -45,6 +45,12 @@ ByteBuffer::ByteBuffer(const Slice* slices, size_t nslices) { buffer_ = grpc_raw_byte_buffer_create(c_slices.data(), nslices); } +ByteBuffer::~ByteBuffer() { + if (buffer_) { + grpc_byte_buffer_destroy(buffer_); + } +} + void ByteBuffer::Clear() { if (buffer_) { grpc_byte_buffer_destroy(buffer_); -- cgit v1.2.3 From d2aa1cf0baa27da6191307463daedd7f11d73294 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Thu, 3 Sep 2015 20:31:16 +0000 Subject: Initial work on protocol objects --- src/python/grpcio/grpc/framework/core/_end.py | 8 +- .../grpcio/grpc/framework/core/_interfaces.py | 4 +- .../grpcio/grpc/framework/core/_operation.py | 10 +- .../grpcio/grpc/framework/core/_transmission.py | 7 +- src/python/grpcio/grpc/framework/crust/_calls.py | 71 +++++++++----- src/python/grpcio/grpc/framework/crust/_control.py | 4 + src/python/grpcio/grpc/framework/crust/_service.py | 3 + .../grpcio/grpc/framework/crust/implementations.py | 109 +++++++++++---------- .../grpcio/grpc/framework/interfaces/base/base.py | 4 +- .../grpcio/grpc/framework/interfaces/face/face.py | 99 +++++++++++++++---- .../grpc/framework/interfaces/links/links.py | 18 ++-- 11 files changed, 217 insertions(+), 120 deletions(-) (limited to 'src') diff --git a/src/python/grpcio/grpc/framework/core/_end.py b/src/python/grpcio/grpc/framework/core/_end.py index 336e9c21fd..8e07d9061e 100644 --- a/src/python/grpcio/grpc/framework/core/_end.py +++ b/src/python/grpcio/grpc/framework/core/_end.py @@ -168,7 +168,7 @@ class _End(End): def operate( self, group, method, subscription, timeout, initial_metadata=None, - payload=None, completion=None): + payload=None, completion=None, protocol_options=None): """See base.End.operate for specification.""" operation_id = uuid.uuid4() with self._lock: @@ -177,9 +177,9 @@ class _End(End): termination_action = _termination_action( self._lock, self._stats, operation_id, self._cycle) operation = _operation.invocation_operate( - operation_id, group, method, subscription, timeout, initial_metadata, - payload, completion, self._mate.accept_ticket, termination_action, - self._cycle.pool) + operation_id, group, method, subscription, timeout, protocol_options, + initial_metadata, payload, completion, self._mate.accept_ticket, + termination_action, self._cycle.pool) self._cycle.operations[operation_id] = operation return operation.context, operation.operator diff --git a/src/python/grpcio/grpc/framework/core/_interfaces.py b/src/python/grpcio/grpc/framework/core/_interfaces.py index 2a534cb7e7..7ac440722c 100644 --- a/src/python/grpcio/grpc/framework/core/_interfaces.py +++ b/src/python/grpcio/grpc/framework/core/_interfaces.py @@ -111,8 +111,8 @@ class TransmissionManager(object): @abc.abstractmethod def kick_off( - self, group, method, timeout, initial_metadata, payload, completion, - allowance): + self, group, method, timeout, protocol_options, initial_metadata, + payload, completion, allowance): """Transmits the values associated with operation invocation.""" raise NotImplementedError() diff --git a/src/python/grpcio/grpc/framework/core/_operation.py b/src/python/grpcio/grpc/framework/core/_operation.py index f5679d0356..d4eacc5a3f 100644 --- a/src/python/grpcio/grpc/framework/core/_operation.py +++ b/src/python/grpcio/grpc/framework/core/_operation.py @@ -84,8 +84,9 @@ class _EasyOperation(_interfaces.Operation): def invocation_operate( - operation_id, group, method, subscription, timeout, initial_metadata, - payload, completion, ticket_sink, termination_action, pool): + operation_id, group, method, subscription, timeout, protocol_options, + initial_metadata, payload, completion, ticket_sink, termination_action, + pool): """Constructs objects necessary for front-side operation management. Args: @@ -95,6 +96,8 @@ def invocation_operate( subscription: A base.Subscription describing the customer's interest in the results of the operation. timeout: A length of time in seconds to allow for the operation. + protocol_options: A transport-specific, application-specific, and/or + protocol-specific value relating to the invocation. May be None. initial_metadata: An initial metadata value to be sent to the other side of the operation. May be None if the initial metadata will be passed later or if there will be no initial metadata passed at all. @@ -136,7 +139,8 @@ def invocation_operate( emission_manager.set_ingestion_manager(ingestion_manager) transmission_manager.kick_off( - group, method, timeout, initial_metadata, payload, completion, None) + group, method, timeout, protocol_options, initial_metadata, payload, + completion, None) return _EasyOperation( lock, termination_manager, transmission_manager, expiration_manager, diff --git a/src/python/grpcio/grpc/framework/core/_transmission.py b/src/python/grpcio/grpc/framework/core/_transmission.py index 8f852cfe9f..65b12c4160 100644 --- a/src/python/grpcio/grpc/framework/core/_transmission.py +++ b/src/python/grpcio/grpc/framework/core/_transmission.py @@ -207,18 +207,19 @@ class TransmissionManager(_interfaces.TransmissionManager): self._transmitting = True def kick_off( - self, group, method, timeout, initial_metadata, payload, completion, - allowance): + self, group, method, timeout, protocol_options, initial_metadata, + payload, completion, allowance): """See _interfaces.TransmissionManager.kickoff for specification.""" # TODO(nathaniel): Support other subscriptions. subscription = links.Ticket.Subscription.FULL terminal_metadata, code, message, termination = _explode_completion( completion) self._remote_allowance = 1 if payload is None else 0 + protocol = links.Protocol(links.Protocol.Kind.CALL_OPTION, protocol_options) ticket = links.Ticket( self._operation_id, 0, group, method, subscription, timeout, allowance, initial_metadata, payload, terminal_metadata, code, message, - termination, None) + termination, protocol) self._lowest_unused_sequence_number = 1 self._transmit(ticket) diff --git a/src/python/grpcio/grpc/framework/crust/_calls.py b/src/python/grpcio/grpc/framework/crust/_calls.py index 4c6bf16f43..68db9fab8e 100644 --- a/src/python/grpcio/grpc/framework/crust/_calls.py +++ b/src/python/grpcio/grpc/framework/crust/_calls.py @@ -38,12 +38,14 @@ _ITERATOR_EXCEPTION_LOG_MESSAGE = 'Exception iterating over requests!' _EMPTY_COMPLETION = utilities.completion(None, None, None) -def _invoke(end, group, method, timeout, initial_metadata, payload, complete): +def _invoke( + end, group, method, timeout, protocol_options, initial_metadata, payload, + complete): rendezvous = _control.Rendezvous(None, None) operation_context, operator = end.operate( group, method, utilities.full_subscription(rendezvous), timeout, - initial_metadata=initial_metadata, payload=payload, - completion=_EMPTY_COMPLETION if complete else None) + protocol_options=protocol_options, initial_metadata=initial_metadata, + payload=payload, completion=_EMPTY_COMPLETION if complete else None) rendezvous.set_operator_and_context(operator, operation_context) outcome = operation_context.add_termination_callback(rendezvous.set_outcome) if outcome is not None: @@ -93,36 +95,43 @@ def _event_return_stream( def blocking_unary_unary( - end, group, method, timeout, with_call, initial_metadata, payload): + end, group, method, timeout, with_call, protocol_options, initial_metadata, + payload): """Services in a blocking fashion a unary-unary servicer method.""" rendezvous, unused_operation_context, unused_outcome = _invoke( - end, group, method, timeout, initial_metadata, payload, True) + end, group, method, timeout, protocol_options, initial_metadata, payload, + True) if with_call: return next(rendezvous), rendezvous else: return next(rendezvous) -def future_unary_unary(end, group, method, timeout, initial_metadata, payload): +def future_unary_unary( + end, group, method, timeout, protocol_options, initial_metadata, payload): """Services a value-in value-out servicer method by returning a Future.""" rendezvous, unused_operation_context, unused_outcome = _invoke( - end, group, method, timeout, initial_metadata, payload, True) + end, group, method, timeout, protocol_options, initial_metadata, payload, + True) return rendezvous -def inline_unary_stream(end, group, method, timeout, initial_metadata, payload): +def inline_unary_stream( + end, group, method, timeout, protocol_options, initial_metadata, payload): """Services a value-in stream-out servicer method.""" rendezvous, unused_operation_context, unused_outcome = _invoke( - end, group, method, timeout, initial_metadata, payload, True) + end, group, method, timeout, protocol_options, initial_metadata, payload, + True) return rendezvous def blocking_stream_unary( - end, group, method, timeout, with_call, initial_metadata, payload_iterator, - pool): + end, group, method, timeout, with_call, protocol_options, initial_metadata, + payload_iterator, pool): """Services in a blocking fashion a stream-in value-out servicer method.""" rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, initial_metadata, None, False) + end, group, method, timeout, protocol_options, initial_metadata, None, + False) if outcome is None: def in_pool(): for payload in payload_iterator: @@ -141,10 +150,12 @@ def blocking_stream_unary( def future_stream_unary( - end, group, method, timeout, initial_metadata, payload_iterator, pool): + end, group, method, timeout, protocol_options, initial_metadata, + payload_iterator, pool): """Services a stream-in value-out servicer method by returning a Future.""" rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, initial_metadata, None, False) + end, group, method, timeout, protocol_options, initial_metadata, None, + False) if outcome is None: def in_pool(): for payload in payload_iterator: @@ -155,10 +166,12 @@ def future_stream_unary( def inline_stream_stream( - end, group, method, timeout, initial_metadata, payload_iterator, pool): + end, group, method, timeout, protocol_options, initial_metadata, + payload_iterator, pool): """Services a stream-in stream-out servicer method.""" rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, initial_metadata, None, False) + end, group, method, timeout, protocol_options, initial_metadata, None, + False) if outcome is None: def in_pool(): for payload in payload_iterator: @@ -169,36 +182,40 @@ def inline_stream_stream( def event_unary_unary( - end, group, method, timeout, initial_metadata, payload, receiver, - abortion_callback, pool): + end, group, method, timeout, protocol_options, initial_metadata, payload, + receiver, abortion_callback, pool): rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, initial_metadata, payload, True) + end, group, method, timeout, protocol_options, initial_metadata, payload, + True) return _event_return_unary( receiver, abortion_callback, rendezvous, operation_context, outcome, pool) def event_unary_stream( - end, group, method, timeout, initial_metadata, payload, + end, group, method, timeout, protocol_options, initial_metadata, payload, receiver, abortion_callback, pool): rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, initial_metadata, payload, True) + end, group, method, timeout, protocol_options, initial_metadata, payload, + True) return _event_return_stream( receiver, abortion_callback, rendezvous, operation_context, outcome, pool) def event_stream_unary( - end, group, method, timeout, initial_metadata, receiver, abortion_callback, - pool): + end, group, method, timeout, protocol_options, initial_metadata, receiver, + abortion_callback, pool): rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, initial_metadata, None, False) + end, group, method, timeout, protocol_options, initial_metadata, None, + False) return _event_return_unary( receiver, abortion_callback, rendezvous, operation_context, outcome, pool) def event_stream_stream( - end, group, method, timeout, initial_metadata, receiver, abortion_callback, - pool): + end, group, method, timeout, protocol_options, initial_metadata, receiver, + abortion_callback, pool): rendezvous, operation_context, outcome = _invoke( - end, group, method, timeout, initial_metadata, None, False) + end, group, method, timeout, protocol_options, initial_metadata, None, + False) return _event_return_stream( receiver, abortion_callback, rendezvous, operation_context, outcome, pool) diff --git a/src/python/grpcio/grpc/framework/crust/_control.py b/src/python/grpcio/grpc/framework/crust/_control.py index 7bddf46a57..e02a41d720 100644 --- a/src/python/grpcio/grpc/framework/crust/_control.py +++ b/src/python/grpcio/grpc/framework/crust/_control.py @@ -442,6 +442,10 @@ class Rendezvous(base.Operator, future.Future, stream.Consumer, face.Call): else: return self._termination.abortion + def protocol_context(self): + with self._condition: + raise NotImplementedError('TODO: protocol context implementation!') + def initial_metadata(self): with self._condition: while True: diff --git a/src/python/grpcio/grpc/framework/crust/_service.py b/src/python/grpcio/grpc/framework/crust/_service.py index 6ff7249e75..f1855c2f47 100644 --- a/src/python/grpcio/grpc/framework/crust/_service.py +++ b/src/python/grpcio/grpc/framework/crust/_service.py @@ -52,6 +52,9 @@ class _ServicerContext(face.ServicerContext): def cancel(self): self._rendezvous.cancel() + def protocol_context(self): + return self._rendezvous.protocol_context() + def invocation_metadata(self): return self._rendezvous.initial_metadata() diff --git a/src/python/grpcio/grpc/framework/crust/implementations.py b/src/python/grpcio/grpc/framework/crust/implementations.py index d38fab8ba0..4ebc4e9ae8 100644 --- a/src/python/grpcio/grpc/framework/crust/implementations.py +++ b/src/python/grpcio/grpc/framework/crust/implementations.py @@ -66,22 +66,23 @@ class _UnaryUnaryMultiCallable(face.UnaryUnaryMultiCallable): self._pool = pool def __call__( - self, request, timeout, metadata=None, with_call=False): + self, request, timeout, metadata=None, with_call=False, + protocol_options=None): return _calls.blocking_unary_unary( self._end, self._group, self._method, timeout, with_call, - metadata, request) + protocol_options, metadata, request) - def future(self, request, timeout, metadata=None): + def future(self, request, timeout, metadata=None, protocol_options=None): return _calls.future_unary_unary( - self._end, self._group, self._method, timeout, metadata, - request) + self._end, self._group, self._method, timeout, protocol_options, + metadata, request) def event( self, request, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): return _calls.event_unary_unary( - self._end, self._group, self._method, timeout, metadata, - request, receiver, abortion_callback, self._pool) + self._end, self._group, self._method, timeout, protocol_options, + metadata, request, receiver, abortion_callback, self._pool) class _UnaryStreamMultiCallable(face.UnaryStreamMultiCallable): @@ -92,17 +93,17 @@ class _UnaryStreamMultiCallable(face.UnaryStreamMultiCallable): self._method = method self._pool = pool - def __call__(self, request, timeout, metadata=None): + def __call__(self, request, timeout, metadata=None, protocol_options=None): return _calls.inline_unary_stream( - self._end, self._group, self._method, timeout, metadata, - request) + self._end, self._group, self._method, timeout, protocol_options, + metadata, request) def event( self, request, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): return _calls.event_unary_stream( - self._end, self._group, self._method, timeout, metadata, - request, receiver, abortion_callback, self._pool) + self._end, self._group, self._method, timeout, protocol_options, + metadata, request, receiver, abortion_callback, self._pool) class _StreamUnaryMultiCallable(face.StreamUnaryMultiCallable): @@ -115,21 +116,23 @@ class _StreamUnaryMultiCallable(face.StreamUnaryMultiCallable): def __call__( self, request_iterator, timeout, metadata=None, - with_call=False): + with_call=False, protocol_options=None): return _calls.blocking_stream_unary( self._end, self._group, self._method, timeout, with_call, - metadata, request_iterator, self._pool) + protocol_options, metadata, request_iterator, self._pool) - def future(self, request_iterator, timeout, metadata=None): + def future( + self, request_iterator, timeout, metadata=None, protocol_options=None): return _calls.future_stream_unary( - self._end, self._group, self._method, timeout, metadata, - request_iterator, self._pool) + self._end, self._group, self._method, timeout, protocol_options, + metadata, request_iterator, self._pool) def event( - self, receiver, abortion_callback, timeout, metadata=None): + self, receiver, abortion_callback, timeout, metadata=None, + protocol_options=None): return _calls.event_stream_unary( - self._end, self._group, self._method, timeout, metadata, - receiver, abortion_callback, self._pool) + self._end, self._group, self._method, timeout, protocol_options, + metadata, receiver, abortion_callback, self._pool) class _StreamStreamMultiCallable(face.StreamStreamMultiCallable): @@ -140,16 +143,18 @@ class _StreamStreamMultiCallable(face.StreamStreamMultiCallable): self._method = method self._pool = pool - def __call__(self, request_iterator, timeout, metadata=None): + def __call__( + self, request_iterator, timeout, metadata=None, protocol_options=None): return _calls.inline_stream_stream( - self._end, self._group, self._method, timeout, metadata, - request_iterator, self._pool) + self._end, self._group, self._method, timeout, protocol_options, + metadata, request_iterator, self._pool) def event( - self, receiver, abortion_callback, timeout, metadata=None): + self, receiver, abortion_callback, timeout, metadata=None, + protocol_options=None): return _calls.event_stream_stream( - self._end, self._group, self._method, timeout, metadata, - receiver, abortion_callback, self._pool) + self._end, self._group, self._method, timeout, protocol_options, + metadata, receiver, abortion_callback, self._pool) class _GenericStub(face.GenericStub): @@ -161,66 +166,70 @@ class _GenericStub(face.GenericStub): def blocking_unary_unary( self, group, method, request, timeout, metadata=None, - with_call=None): + with_call=None, protocol_options=None): return _calls.blocking_unary_unary( - self._end, group, method, timeout, with_call, metadata, - request) + self._end, group, method, timeout, with_call, protocol_options, + metadata, request) def future_unary_unary( - self, group, method, request, timeout, metadata=None): + self, group, method, request, timeout, metadata=None, + protocol_options=None): return _calls.future_unary_unary( - self._end, group, method, timeout, metadata, request) + self._end, group, method, timeout, protocol_options, metadata, request) def inline_unary_stream( - self, group, method, request, timeout, metadata=None): + self, group, method, request, timeout, metadata=None, + protocol_options=None): return _calls.inline_unary_stream( - self._end, group, method, timeout, metadata, request) + self._end, group, method, timeout, protocol_options, metadata, request) def blocking_stream_unary( self, group, method, request_iterator, timeout, metadata=None, - with_call=None): + with_call=None, protocol_options=None): return _calls.blocking_stream_unary( - self._end, group, method, timeout, with_call, metadata, - request_iterator, self._pool) + self._end, group, method, timeout, with_call, protocol_options, + metadata, request_iterator, self._pool) def future_stream_unary( - self, group, method, request_iterator, timeout, metadata=None): + self, group, method, request_iterator, timeout, metadata=None, + protocol_options=None): return _calls.future_stream_unary( - self._end, group, method, timeout, metadata, + self._end, group, method, timeout, protocol_options, metadata, request_iterator, self._pool) def inline_stream_stream( - self, group, method, request_iterator, timeout, metadata=None): + self, group, method, request_iterator, timeout, metadata=None, + protocol_options=None): return _calls.inline_stream_stream( - self._end, group, method, timeout, metadata, + self._end, group, method, timeout, protocol_options, metadata, request_iterator, self._pool) def event_unary_unary( self, group, method, request, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): return _calls.event_unary_unary( - self._end, group, method, timeout, metadata, request, + self._end, group, method, timeout, protocol_options, metadata, request, receiver, abortion_callback, self._pool) def event_unary_stream( self, group, method, request, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): return _calls.event_unary_stream( - self._end, group, method, timeout, metadata, request, + self._end, group, method, timeout, protocol_options, metadata, request, receiver, abortion_callback, self._pool) def event_stream_unary( self, group, method, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): return _calls.event_stream_unary( - self._end, group, method, timeout, metadata, receiver, + self._end, group, method, timeout, protocol_options, metadata, receiver, abortion_callback, self._pool) def event_stream_stream( self, group, method, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): return _calls.event_stream_stream( - self._end, group, method, timeout, metadata, receiver, + self._end, group, method, timeout, protocol_options, metadata, receiver, abortion_callback, self._pool) def unary_unary(self, group, method): diff --git a/src/python/grpcio/grpc/framework/interfaces/base/base.py b/src/python/grpcio/grpc/framework/interfaces/base/base.py index 0d9d6b464e..013e7c66f2 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/base.py +++ b/src/python/grpcio/grpc/framework/interfaces/base/base.py @@ -274,7 +274,7 @@ class End(object): @abc.abstractmethod def operate( self, group, method, subscription, timeout, initial_metadata=None, - payload=None, completion=None): + payload=None, completion=None, protocol_options=None): """Commences an operation. Args: @@ -290,6 +290,8 @@ class End(object): payload: An initial payload for the operation. completion: A Completion value indicating the end of transmission to the other side of the operation. + protocol_options: A value specified by the provider of a Base interface + implementation affording custom state and behavior. Returns: A pair of objects affording information about the operation and action diff --git a/src/python/grpcio/grpc/framework/interfaces/face/face.py b/src/python/grpcio/grpc/framework/interfaces/face/face.py index 948e7505b6..bc9a434a76 100644 --- a/src/python/grpcio/grpc/framework/interfaces/face/face.py +++ b/src/python/grpcio/grpc/framework/interfaces/face/face.py @@ -184,6 +184,16 @@ class RpcContext(object): """ raise NotImplementedError() + @abc.abstractmethod + def protocol_context(self): + """Accesses a custom object specified by an implementation provider. + + Returns: + A value specified by the provider of a Face interface implementation + affording custom state and behavior. + """ + raise NotImplementedError() + class Call(RpcContext): """Invocation-side utility object for an RPC.""" @@ -354,7 +364,8 @@ class UnaryUnaryMultiCallable(object): @abc.abstractmethod def __call__( - self, request, timeout, metadata=None, with_call=False): + self, request, timeout, metadata=None, with_call=False, + protocol_options=None): """Synchronously invokes the underlying RPC. Args: @@ -364,6 +375,8 @@ class UnaryUnaryMultiCallable(object): the RPC. with_call: Whether or not to include return a Call for the RPC in addition to the reponse. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: The response value for the RPC, and a Call for the RPC if with_call was @@ -375,7 +388,7 @@ class UnaryUnaryMultiCallable(object): raise NotImplementedError() @abc.abstractmethod - def future(self, request, timeout, metadata=None): + def future(self, request, timeout, metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: @@ -383,6 +396,8 @@ class UnaryUnaryMultiCallable(object): timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and a future.Future. In the @@ -395,7 +410,7 @@ class UnaryUnaryMultiCallable(object): @abc.abstractmethod def event( self, request, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: @@ -406,6 +421,8 @@ class UnaryUnaryMultiCallable(object): timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: A Call for the RPC. @@ -418,7 +435,7 @@ class UnaryStreamMultiCallable(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod - def __call__(self, request, timeout, metadata=None): + def __call__(self, request, timeout, metadata=None, protocol_options=None): """Invokes the underlying RPC. Args: @@ -426,6 +443,8 @@ class UnaryStreamMultiCallable(object): timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and an iterator of response @@ -437,7 +456,7 @@ class UnaryStreamMultiCallable(object): @abc.abstractmethod def event( self, request, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: @@ -448,6 +467,8 @@ class UnaryStreamMultiCallable(object): timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: A Call object for the RPC. @@ -462,7 +483,7 @@ class StreamUnaryMultiCallable(object): @abc.abstractmethod def __call__( self, request_iterator, timeout, metadata=None, - with_call=False): + with_call=False, protocol_options=None): """Synchronously invokes the underlying RPC. Args: @@ -472,6 +493,8 @@ class StreamUnaryMultiCallable(object): the RPC. with_call: Whether or not to include return a Call for the RPC in addition to the reponse. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: The response value for the RPC, and a Call for the RPC if with_call was @@ -483,7 +506,8 @@ class StreamUnaryMultiCallable(object): raise NotImplementedError() @abc.abstractmethod - def future(self, request_iterator, timeout, metadata=None): + def future( + self, request_iterator, timeout, metadata=None, protocol_options=None): """Asynchronously invokes the underlying RPC. Args: @@ -491,6 +515,8 @@ class StreamUnaryMultiCallable(object): timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and a future.Future. In the @@ -502,7 +528,8 @@ class StreamUnaryMultiCallable(object): @abc.abstractmethod def event( - self, receiver, abortion_callback, timeout, metadata=None): + self, receiver, abortion_callback, timeout, metadata=None, + protocol_options=None): """Asynchronously invokes the underlying RPC. Args: @@ -512,6 +539,8 @@ class StreamUnaryMultiCallable(object): timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: A single object that is both a Call object for the RPC and a @@ -525,7 +554,8 @@ class StreamStreamMultiCallable(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod - def __call__(self, request_iterator, timeout, metadata=None): + def __call__( + self, request_iterator, timeout, metadata=None, protocol_options=None): """Invokes the underlying RPC. Args: @@ -533,6 +563,8 @@ class StreamStreamMultiCallable(object): timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and an iterator of response @@ -543,7 +575,8 @@ class StreamStreamMultiCallable(object): @abc.abstractmethod def event( - self, receiver, abortion_callback, timeout, metadata=None): + self, receiver, abortion_callback, timeout, metadata=None, + protocol_options=None): """Asynchronously invokes the underlying RPC. Args: @@ -553,6 +586,8 @@ class StreamStreamMultiCallable(object): timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: A single object that is both a Call object for the RPC and a @@ -646,7 +681,7 @@ class GenericStub(object): @abc.abstractmethod def blocking_unary_unary( self, group, method, request, timeout, metadata=None, - with_call=False): + with_call=False, protocol_options=None): """Invokes a unary-request-unary-response method. This method blocks until either returning the response value of the RPC @@ -661,6 +696,8 @@ class GenericStub(object): metadata: A metadata value to be passed to the service-side of the RPC. with_call: Whether or not to include return a Call for the RPC in addition to the reponse. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: The response value for the RPC, and a Call for the RPC if with_call was @@ -673,7 +710,8 @@ class GenericStub(object): @abc.abstractmethod def future_unary_unary( - self, group, method, request, timeout, metadata=None): + self, group, method, request, timeout, metadata=None, + protocol_options=None): """Invokes a unary-request-unary-response method. Args: @@ -682,6 +720,8 @@ class GenericStub(object): request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and a future.Future. In the @@ -693,7 +733,8 @@ class GenericStub(object): @abc.abstractmethod def inline_unary_stream( - self, group, method, request, timeout, metadata=None): + self, group, method, request, timeout, metadata=None, + protocol_options=None): """Invokes a unary-request-stream-response method. Args: @@ -702,6 +743,8 @@ class GenericStub(object): request: The request value for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and an iterator of response @@ -713,7 +756,7 @@ class GenericStub(object): @abc.abstractmethod def blocking_stream_unary( self, group, method, request_iterator, timeout, metadata=None, - with_call=False): + with_call=False, protocol_options=None): """Invokes a stream-request-unary-response method. This method blocks until either returning the response value of the RPC @@ -728,6 +771,8 @@ class GenericStub(object): metadata: A metadata value to be passed to the service-side of the RPC. with_call: Whether or not to include return a Call for the RPC in addition to the reponse. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: The response value for the RPC, and a Call for the RPC if with_call was @@ -740,7 +785,8 @@ class GenericStub(object): @abc.abstractmethod def future_stream_unary( - self, group, method, request_iterator, timeout, metadata=None): + self, group, method, request_iterator, timeout, metadata=None, + protocol_options=None): """Invokes a stream-request-unary-response method. Args: @@ -749,6 +795,8 @@ class GenericStub(object): request_iterator: An iterator that yields request values for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and a future.Future. In the @@ -760,7 +808,8 @@ class GenericStub(object): @abc.abstractmethod def inline_stream_stream( - self, group, method, request_iterator, timeout, metadata=None): + self, group, method, request_iterator, timeout, metadata=None, + protocol_options=None): """Invokes a stream-request-stream-response method. Args: @@ -769,6 +818,8 @@ class GenericStub(object): request_iterator: An iterator that yields request values for the RPC. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: An object that is both a Call for the RPC and an iterator of response @@ -780,7 +831,7 @@ class GenericStub(object): @abc.abstractmethod def event_unary_unary( self, group, method, request, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): """Event-driven invocation of a unary-request-unary-response method. Args: @@ -792,6 +843,8 @@ class GenericStub(object): in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: A Call for the RPC. @@ -801,7 +854,7 @@ class GenericStub(object): @abc.abstractmethod def event_unary_stream( self, group, method, request, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): """Event-driven invocation of a unary-request-stream-response method. Args: @@ -813,6 +866,8 @@ class GenericStub(object): in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: A Call for the RPC. @@ -822,7 +877,7 @@ class GenericStub(object): @abc.abstractmethod def event_stream_unary( self, group, method, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): """Event-driven invocation of a unary-request-unary-response method. Args: @@ -833,6 +888,8 @@ class GenericStub(object): in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: A pair of a Call object for the RPC and a stream.Consumer to which the @@ -843,7 +900,7 @@ class GenericStub(object): @abc.abstractmethod def event_stream_stream( self, group, method, receiver, abortion_callback, timeout, - metadata=None): + metadata=None, protocol_options=None): """Event-driven invocation of a unary-request-stream-response method. Args: @@ -854,6 +911,8 @@ class GenericStub(object): in the event of RPC abortion. timeout: A duration of time in seconds to allow for the RPC. metadata: A metadata value to be passed to the service-side of the RPC. + protocol_options: A value specified by the provider of a Face interface + implementation affording custom state and behavior. Returns: A pair of a Call object for the RPC and a stream.Consumer to which the diff --git a/src/python/grpcio/grpc/framework/interfaces/links/links.py b/src/python/grpcio/grpc/framework/interfaces/links/links.py index b98a30a399..24f0e3b354 100644 --- a/src/python/grpcio/grpc/framework/interfaces/links/links.py +++ b/src/python/grpcio/grpc/framework/interfaces/links/links.py @@ -34,14 +34,13 @@ import collections import enum -class Transport(collections.namedtuple('Transport', ('kind', 'value',))): - """A sum type for handles to an underlying transport system. +class Protocol(collections.namedtuple('Protocol', ('kind', 'value',))): + """A sum type for handles to a system that transmits tickets. Attributes: - kind: A Kind value identifying the kind of value being passed to or from - the underlying transport. - value: The value being passed through RPC Framework between the high-level - application and the underlying transport. + kind: A Kind value identifying the kind of value being passed. + value: The value being passed between the high-level application and the + system affording ticket transport. """ @enum.unique @@ -56,8 +55,7 @@ class Ticket( 'Ticket', ('operation_id', 'sequence_number', 'group', 'method', 'subscription', 'timeout', 'allowance', 'initial_metadata', 'payload', - 'terminal_metadata', 'code', 'message', 'termination', - 'transport',))): + 'terminal_metadata', 'code', 'message', 'termination', 'protocol',))): """A sum type for all values sent from a front to a back. Attributes: @@ -99,8 +97,8 @@ class Ticket( termination: A Termination value describing the end of the operation, or None if the operation has not yet terminated. If set, no further tickets may be sent in the same direction. - transport: A Transport value or None, with further semantics being a matter - between high-level application and underlying transport. + protocol: A Protocol value or None, with further semantics being a matter + between high-level application and underlying ticket transport. """ @enum.unique -- cgit v1.2.3 From 4edf83216ed009e9a86784fafde4144e22fec119 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Wed, 2 Sep 2015 23:46:40 -0700 Subject: Don’t strip -bin suffix from response metadata. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/objective-c/GRPCClient/private/NSDictionary+GRPC.m | 3 --- 1 file changed, 3 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m index 99c890e4ee..584fc8a8c1 100644 --- a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m +++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m @@ -105,8 +105,6 @@ + (instancetype)grpc_dictionaryFromMetadata:(grpc_metadata *)entries count:(size_t)count { NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count]; for (grpc_metadata *entry = entries; entry < entries + count; entry++) { - // TODO(jcanizales): Verify in a C library test that it's converting header names to lower case - // automatically. NSString *name = [NSString stringWithCString:entry->key encoding:NSASCIIStringEncoding]; if (!name || metadata[name]) { // Log if name is nil? @@ -114,7 +112,6 @@ } id value; if ([name hasSuffix:@"-bin"]) { - name = [name substringToIndex:name.length - 4]; value = [NSData grpc_dataFromMetadataValue:entry]; } else { value = [NSString grpc_stringFromMetadataValue:entry]; -- cgit v1.2.3 From ebfd11909cc0a223242ca05369744b86a08acbfe Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 01:53:06 -0700 Subject: Propagate parsing error if we get a bad response --- src/objective-c/ProtoRPC/ProtoRPC.m | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 889d71a308..61fc0e3531 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -65,14 +65,25 @@ } // A writer that serializes the proto messages to send. GRXWriter *bytesWriter = [requestsWriter map:^id(GPBMessage *proto) { - // TODO(jcanizales): Fail with an understandable error message if the requestsWriter isn't - // sending GPBMessages. + if (![proto isKindOfClass:GPBMessage.class]) { + [NSException raise:NSInvalidArgumentException + format:@"Request must be a proto message: %@", proto]; + } return [proto data]; }]; if ((self = [super initWithHost:host path:method.HTTPPath requestsWriter:bytesWriter])) { + __weak ProtoRPC *weakSelf = self; + // A writeable that parses the proto messages received. _responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) { - [responsesWriteable writeValue:[responseClass parseFromData:value error:NULL]]; + // TODO(jcanizales): This is done in the main thread, and needs to happen in another thread. + NSError *error = nil; + id parsed = [responseClass parseFromData:value error:&error]; + if (parsed) { + [responsesWriteable writeValue:parsed]; + } else { + [weakSelf finishWithError:error]; + } } completionHandler:^(NSError *errorOrNil) { [responsesWriteable writesFinishedWithError:errorOrNil]; }]; -- cgit v1.2.3 From f5d519464f0ce606ff8746cc324dc5c7626a8e02 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 02:39:36 -0700 Subject: Wrap parsing error appropriately before propagating. --- src/objective-c/ProtoRPC/ProtoRPC.m | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 61fc0e3531..735ce0bdb5 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -37,6 +37,20 @@ #import #import +static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) { + NSDictionary *info = @{ + NSLocalizedDescriptionKey: @"Unable to parse response from the server", + NSLocalizedRecoverySuggestionErrorKey: @"Retry with exponential backoff", + NSUnderlyingErrorKey: parsingError, + @"Expected class": expectedClass, + @"Received value": proto, + }; + // TODO(jcanizales): Use kGRPCErrorDomain and GRPCErrorCodeInternal when they're public. + return [NSError errorWithDomain:@"io.grpc" + code:13 + userInfo:info]; +} + @implementation ProtoRPC { id _responseWriteable; } @@ -82,7 +96,7 @@ if (parsed) { [responsesWriteable writeValue:parsed]; } else { - [weakSelf finishWithError:error]; + [weakSelf finishWithError:ErrorForBadProto(value, responseClass, error)]; } } completionHandler:^(NSError *errorOrNil) { [responsesWriteable writesFinishedWithError:errorOrNil]; -- cgit v1.2.3 From cabbcbfc840aa0b761fdf7c25ac6aa3b699a52a7 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 03:44:38 -0700 Subject: Documentation: Don’t retry if not idempotent! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/objective-c/ProtoRPC/ProtoRPC.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m index 735ce0bdb5..9bf66f347a 100644 --- a/src/objective-c/ProtoRPC/ProtoRPC.m +++ b/src/objective-c/ProtoRPC/ProtoRPC.m @@ -40,7 +40,9 @@ static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) { NSDictionary *info = @{ NSLocalizedDescriptionKey: @"Unable to parse response from the server", - NSLocalizedRecoverySuggestionErrorKey: @"Retry with exponential backoff", + NSLocalizedRecoverySuggestionErrorKey: @"If this RPC is idempotent, retry " + @"with exponential backoff. Otherwise, query the server status before " + @"retrying.", NSUnderlyingErrorKey: parsingError, @"Expected class": expectedClass, @"Received value": proto, -- cgit v1.2.3 From 29d4145a644326680ea1abadd6fd0ab5642261be Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 3 Sep 2015 14:34:09 -0700 Subject: avoid underflow --- src/core/support/sync_win32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/support/sync_win32.c b/src/core/support/sync_win32.c index df23492171..f546477067 100644 --- a/src/core/support/sync_win32.c +++ b/src/core/support/sync_win32.c @@ -88,9 +88,9 @@ int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) { SleepConditionVariableCS(cv, &mu->cs, INFINITE); } else { gpr_timespec now = gpr_now(abs_deadline.clock_type); - gpr_int64 now_ms = now.tv_sec * 1000 + now.tv_nsec / 1000000; + gpr_int64 now_ms = (gpr_int64)now.tv_sec * 1000 + now.tv_nsec / 1000000; gpr_int64 deadline_ms = - abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000; + (gpr_int64)abs_deadline.tv_sec * 1000 + abs_deadline.tv_nsec / 1000000; if (now_ms >= deadline_ms) { timeout = 1; } else { -- cgit v1.2.3 From 49d03c80c989fe04adb39602989ae847576184dd Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 3 Sep 2015 14:34:30 -0700 Subject: avoid infinite spin without checking condvar --- src/core/iomgr/iomgr.c | 26 +++++++++++++++---------- src/core/iomgr/tcp_client_windows.c | 39 ++++++++++++------------------------- 2 files changed, 28 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/core/iomgr/iomgr.c b/src/core/iomgr/iomgr.c index fdc9adf4af..1dd03992ae 100644 --- a/src/core/iomgr/iomgr.c +++ b/src/core/iomgr/iomgr.c @@ -108,8 +108,14 @@ static size_t count_objects(void) { return n; } -void grpc_iomgr_shutdown(void) { +static void dump_objects(const char *kind) { grpc_iomgr_object *obj; + for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { + gpr_log(GPR_DEBUG, "%s OBJECT: %s %p", kind, obj->name, obj); + } +} + +void grpc_iomgr_shutdown(void) { grpc_iomgr_closure *closure; gpr_timespec shutdown_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(10, GPR_TIMESPAN)); @@ -151,12 +157,14 @@ void grpc_iomgr_shutdown(void) { } if (g_root_object.next != &g_root_object) { int timeout = 0; - gpr_timespec short_deadline = gpr_time_add( + while (g_cbs_head == NULL) { + gpr_timespec short_deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(100, GPR_TIMESPAN)); - while (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) { - if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) { - timeout = 1; - break; + if (gpr_cv_wait(&g_rcv, &g_mu, short_deadline) && g_cbs_head == NULL) { + if (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), shutdown_deadline) > 0) { + timeout = 1; + break; + } } } if (timeout) { @@ -164,9 +172,7 @@ void grpc_iomgr_shutdown(void) { "Failed to free %d iomgr objects before shutdown deadline: " "memory leaks are likely", count_objects()); - for (obj = g_root_object.next; obj != &g_root_object; obj = obj->next) { - gpr_log(GPR_DEBUG, "LEAKED OBJECT: %s %p", obj->name, obj); - } + dump_objects("LEAKED"); break; } } @@ -188,7 +194,7 @@ void grpc_iomgr_register_object(grpc_iomgr_object *obj, const char *name) { obj->name = gpr_strdup(name); gpr_mu_lock(&g_mu); obj->next = &g_root_object; - obj->prev = obj->next->prev; + obj->prev = g_root_object.prev; obj->next->prev = obj->prev->next = obj; gpr_mu_unlock(&g_mu); } diff --git a/src/core/iomgr/tcp_client_windows.c b/src/core/iomgr/tcp_client_windows.c index 665ef2885f..05198dbff4 100644 --- a/src/core/iomgr/tcp_client_windows.c +++ b/src/core/iomgr/tcp_client_windows.c @@ -60,13 +60,13 @@ typedef struct { grpc_alarm alarm; char *addr_name; int refs; - int aborted; } async_connect; -static void async_connect_cleanup(async_connect *ac) { +static void async_connect_unlock_and_cleanup(async_connect *ac) { int done = (--ac->refs == 0); gpr_mu_unlock(&ac->mu); if (done) { + if (ac->socket != NULL) grpc_winsocket_destroy(ac->socket); gpr_mu_destroy(&ac->mu); gpr_free(ac->addr_name); gpr_free(ac); @@ -77,10 +77,11 @@ static void on_alarm(void *acp, int occured) { async_connect *ac = acp; gpr_mu_lock(&ac->mu); /* If the alarm didn't occur, it got cancelled. */ + gpr_log(GPR_DEBUG, "on_alarm: %p", ac->socket); if (ac->socket != NULL && occured) { grpc_winsocket_shutdown(ac->socket); } - async_connect_cleanup(ac); + async_connect_unlock_and_cleanup(ac); } static void on_connect(void *acp, int from_iocp) { @@ -90,12 +91,12 @@ static void on_connect(void *acp, int from_iocp) { grpc_winsocket_callback_info *info = &ac->socket->write_info; void (*cb)(void *arg, grpc_endpoint *tcp) = ac->cb; void *cb_arg = ac->cb_arg; - int aborted; - + grpc_alarm_cancel(&ac->alarm); gpr_mu_lock(&ac->mu); - aborted = ac->aborted; + + gpr_log(GPR_DEBUG, "on_connect: %p", ac->socket); if (from_iocp) { DWORD transfered_bytes = 0; @@ -107,31 +108,16 @@ static void on_connect(void *acp, int from_iocp) { char *utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message); gpr_free(utf8_message); - } else if (!aborted) { + } else { ep = grpc_tcp_create(ac->socket, ac->addr_name); + ac->socket = NULL; } - } else { - gpr_log(GPR_ERROR, "on_connect is shutting down"); - /* If the connection timeouts, we will still get a notification from - the IOCP whatever happens. So we're just going to flag that connection - as being in the process of being aborted, and wait for the IOCP. We - can't just orphan the socket now, because the IOCP might already have - gotten a successful connection, which is our worst-case scenario. - We need to call our callback now to respect the deadline. */ - ac->aborted = 1; - gpr_mu_unlock(&ac->mu); - cb(cb_arg, NULL); - return; } - /* If we don't have an endpoint, it means the connection failed, - so it doesn't matter if it aborted or failed. We need to orphan - that socket. */ - if (!ep || aborted) grpc_winsocket_destroy(ac->socket); - async_connect_cleanup(ac); + async_connect_unlock_and_cleanup(ac); /* If the connection was aborted, the callback was already called when the deadline was met. */ - if (!aborted) cb(cb_arg, ep); + cb(cb_arg, ep); } /* Tries to issue one async connection, then schedules both an IOCP @@ -212,7 +198,6 @@ void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *tcp), gpr_mu_init(&ac->mu); ac->refs = 2; ac->addr_name = grpc_sockaddr_to_uri(addr); - ac->aborted = 0; grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC)); @@ -223,7 +208,7 @@ failure: utf8_message = gpr_format_message(WSAGetLastError()); gpr_log(GPR_ERROR, message, utf8_message); gpr_free(utf8_message); - if (socket) { + if (socket != NULL) { grpc_winsocket_destroy(socket); } else if (sock != INVALID_SOCKET) { closesocket(sock); -- cgit v1.2.3 From d21781f39e74cbcac02b857b7ef6bd094cc0dcd1 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 03:42:02 -0700 Subject: Make the error domain and codes public and documented. --- src/objective-c/GRPCClient/GRPCCall.h | 82 +++++++++++++++++++++++ src/objective-c/GRPCClient/private/NSError+GRPC.h | 23 ------- 2 files changed, 82 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 4eda499b1a..b2968b8e98 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -48,11 +48,93 @@ #import #import +#pragma mark gRPC errors + +// Domain of NSError objects produced by gRPC. +extern NSString *const kGRPCErrorDomain; + +// gRPC error codes. +// Note that a few of these are never produced by the gRPC libraries, but are of general utility for +// server applications to produce. +typedef NS_ENUM(NSUInteger, GRPCErrorCode) { + // The operation was cancelled (typically by the caller). + GRPCErrorCodeCancelled = 1, + + // Unknown error. Errors raised by APIs that do not return enough error information may be + // converted to this error. + GRPCErrorCodeUnknown = 2, + + // The client specified an invalid argument. Note that this differs from FAILED_PRECONDITION. + // INVALID_ARGUMENT indicates arguments that are problematic regardless of the state of the + // server (e.g., a malformed file name). + GRPCErrorCodeInvalidArgument = 3, + + // Deadline expired before operation could complete. For operations that change the state of the + // server, this error may be returned even if the operation has completed successfully. For + // example, a successful response from the server could have been delayed long enough for the + // deadline to expire. + GRPCErrorCodeDeadlineExceeded = 4, + + // Some requested entity (e.g., file or directory) was not found. + GRPCErrorCodeNotFound = 5, + + // Some entity that we attempted to create (e.g., file or directory) already exists. + GRPCErrorCodeAlreadyExists = 6, + + // The caller does not have permission to execute the specified operation. PERMISSION_DENIED isn't + // used for rejections caused by exhausting some resource (RESOURCE_EXHAUSTED is used instead for + // those errors). PERMISSION_DENIED doesn't indicate a failure to identify the caller + // (UNAUTHENTICATED is used instead for those errors). + GRPCErrorCodePermissionDenied = 7, + + // The request does not have valid authentication credentials for the operation (e.g. the caller's + // identity can't be verified). + GRPCErrorCodeUnauthenticated = 16, + + // Some resource has been exhausted, perhaps a per-user quota. + GRPCErrorCodeResourceExhausted = 8, + + // The RPC was rejected because the server is not in a state required for the procedure's + // execution. For example, a directory to be deleted may be non-empty, etc. + // The client should not retry until the server state has been explicitly fixed (e.g. by + // performing another RPC). The details depend on the service being called, and should be found in + // the NSError's userInfo. + GRPCErrorCodeFailedPrecondition = 9, + + // The RPC was aborted, typically due to a concurrency issue like sequencer check failures, + // transaction aborts, etc. The client should retry at a higher-level (e.g., restarting a read- + // modify-write sequence). + GRPCErrorCodeAborted = 10, + + // The RPC was attempted past the valid range. E.g., enumerating past the end of a list. + // Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed if the system state + // changes. For example, an RPC to get elements of a list will generate INVALID_ARGUMENT if asked + // to return the element at a negative index, but it will generate OUT_OF_RANGE if asked to return + // the element at an index past the current size of the list. + GRPCErrorCodeOutOfRange = 11, + + // The procedure is not implemented or not supported/enabled in this server. + GRPCErrorCodeUnimplemented = 12, + + // Internal error. Means some invariant expected by the server application or the gRPC library has + // been broken. + GRPCErrorCodeInternal = 13, + + // The server is currently unavailable. This is most likely a transient condition and may be + // corrected by retrying with a backoff. + GRPCErrorCodeUnavailable = 14, + + // Unrecoverable data loss or corruption. + GRPCErrorCodeDataLoss = 15, +}; + // Keys used in |NSError|'s |userInfo| dictionary to store the response headers and trailers sent by // the server. extern id const kGRPCHeadersKey; extern id const kGRPCTrailersKey; +#pragma mark GRPCCall + // Represents a single gRPC remote call. @interface GRPCCall : GRXWriter diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.h b/src/objective-c/GRPCClient/private/NSError+GRPC.h index e712791271..f4729dc8a1 100644 --- a/src/objective-c/GRPCClient/private/NSError+GRPC.h +++ b/src/objective-c/GRPCClient/private/NSError+GRPC.h @@ -34,29 +34,6 @@ #import #include -// TODO(jcanizales): Make the domain string public. -extern NSString *const kGRPCErrorDomain; - -// TODO(jcanizales): Make this public and document each code. -typedef NS_ENUM(NSInteger, GRPCErrorCode) { - GRPCErrorCodeCancelled = 1, - GRPCErrorCodeUnknown = 2, - GRPCErrorCodeInvalidArgument = 3, - GRPCErrorCodeDeadlineExceeded = 4, - GRPCErrorCodeNotFound = 5, - GRPCErrorCodeAlreadyExists = 6, - GRPCErrorCodePermissionDenied = 7, - GRPCErrorCodeUnauthenticated = 16, - GRPCErrorCodeResourceExhausted = 8, - GRPCErrorCodeFailedPrecondition = 9, - GRPCErrorCodeAborted = 10, - GRPCErrorCodeOutOfRange = 11, - GRPCErrorCodeUnimplemented = 12, - GRPCErrorCodeInternal = 13, - GRPCErrorCodeUnavailable = 14, - GRPCErrorCodeDataLoss = 15 -}; - @interface NSError (GRPC) // Returns nil if the status code is OK. Otherwise, a NSError whose code is one of |GRPCErrorCode| // and whose domain is |kGRPCErrorDomain|. -- cgit v1.2.3 From fd2f3a7e9ab64708ef57ad6a3c284d7e475d4ea4 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 10:37:51 -0700 Subject: Remove unneeded include of grpc.h --- src/objective-c/GRPCClient/GRPCCall.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index c098d4b701..210ea709a3 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -48,8 +48,6 @@ #import #import -#include - #pragma mark gRPC errors // Domain of NSError objects produced by gRPC. -- cgit v1.2.3 From 78a4c7490e9d991f48c0c0cb95446ee0acf241ce Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 05:24:19 -0700 Subject: Make request headers a @property property. --- src/objective-c/GRPCClient/GRPCCall.h | 6 ++---- src/objective-c/GRPCClient/GRPCCall.m | 14 -------------- 2 files changed, 2 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h index 210ea709a3..35f7e16af7 100644 --- a/src/objective-c/GRPCClient/GRPCCall.h +++ b/src/objective-c/GRPCClient/GRPCCall.h @@ -169,10 +169,8 @@ extern id const kGRPCTrailersKey; // // After the call is started, trying to modify this property is an error. // -// For convenience, the property is initialized to an empty NSMutableDictionary, and the setter -// accepts (and copies) both mutable and immutable dictionaries. -- (id)requestHeaders; // nonatomic -- (void)setRequestHeaders:(NSDictionary *)requestHeaders; // nonatomic, copy +// The property is initialized to an empty NSMutableDictionary. +@property(atomic, readonly) id requestHeaders; // This dictionary is populated with the HTTP headers received from the server. This happens before // any response message is received from the server. It has the same structure as the request diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m index 1be753e688..b6986bf59c 100644 --- a/src/objective-c/GRPCClient/GRPCCall.m +++ b/src/objective-c/GRPCClient/GRPCCall.m @@ -130,20 +130,6 @@ NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey"; return self; } -#pragma mark Metadata - -- (id)requestHeaders { - return _requestHeaders; -} - -- (void)setRequestHeaders:(NSDictionary *)requestHeaders { - GRPCRequestHeaders *newHeaders = [[GRPCRequestHeaders alloc] initWithCall:self]; - for (id key in requestHeaders) { - newHeaders[key] = requestHeaders[key]; - } - _requestHeaders = newHeaders; -} - #pragma mark Finish - (void)finishWithError:(NSError *)errorOrNil { -- cgit v1.2.3 From cff8aa2a01df7aed5c494f35873ebb44aab99b7b Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 10:11:19 -0700 Subject: Point SwiftSample’s Podfile to submodule protobuf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/objective-c/examples/SwiftSample/Podfile | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/Podfile b/src/objective-c/examples/SwiftSample/Podfile index 7b5941eef7..3611b00863 100644 --- a/src/objective-c/examples/SwiftSample/Podfile +++ b/src/objective-c/examples/SwiftSample/Podfile @@ -1,6 +1,7 @@ source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' +pod 'Protobuf', :path => "../../../../third_party/protobuf" pod 'gRPC', :path => "../../../.." pod 'RemoteTest', :path => "../RemoteTestClient" -- cgit v1.2.3 From 4682f8f9941c55af2d3d64d04971f09d04d35759 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 10:21:35 -0700 Subject: Point sample proto podspec to latest gRPC and protobuf --- src/objective-c/examples/RemoteTestClient/RemoteTest.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec index dcb0c4e500..d4f8084cb5 100644 --- a/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec +++ b/src/objective-c/examples/RemoteTestClient/RemoteTest.podspec @@ -15,14 +15,14 @@ Pod::Spec.new do |s| ms.source_files = "*.pbobjc.{h,m}" ms.header_mappings_dir = "." ms.requires_arc = false - ms.dependency "Protobuf", "~> 3.0.0-alpha-3" + ms.dependency "Protobuf", "~> 3.0.0-alpha-4" end s.subspec "Services" do |ss| ss.source_files = "*.pbrpc.{h,m}" ss.header_mappings_dir = "." ss.requires_arc = true - ss.dependency "gRPC", "~> 0.5" + ss.dependency "gRPC", "~> 0.7" ss.dependency "#{s.name}/Messages" end end -- cgit v1.2.3 From ff6466b7269174dbd792df7252a99e2791f3b0ed Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 10:10:34 -0700 Subject: Add header manipulation examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With both raw and codegen’d library --- .../examples/SwiftSample/Bridging-Header.h | 1 + .../examples/SwiftSample/ViewController.swift | 42 ++++++++++++++++------ 2 files changed, 33 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/objective-c/examples/SwiftSample/Bridging-Header.h b/src/objective-c/examples/SwiftSample/Bridging-Header.h index 33db2dd1cb..65f768a760 100644 --- a/src/objective-c/examples/SwiftSample/Bridging-Header.h +++ b/src/objective-c/examples/SwiftSample/Bridging-Header.h @@ -39,6 +39,7 @@ #import #import #import +#import #import #endif diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift index e4e7aeae49..76dad9e132 100644 --- a/src/objective-c/examples/SwiftSample/ViewController.swift +++ b/src/objective-c/examples/SwiftSample/ViewController.swift @@ -45,17 +45,37 @@ class ViewController: UIViewController { request.fillUsername = true request.fillOauthScope = true + // Example gRPC call using a generated proto client library: let service = RMTTestService(host: RemoteHost) - service.unaryCallWithRequest(request) { (response: RMTSimpleResponse?, error: NSError?) in + service.unaryCallWithRequest(request) { response, error in + if let response = response { + NSLog("1. Finished successfully with response:\n\(response)") + } else { + NSLog("1. Finished with error: \(error!)") + } + } + + + // Same but manipulating headers: + + var RPC : ProtoRPC! // Needed to convince Swift to capture by reference (__block) + RPC = service.RPCToUnaryCallWithRequest(request) { response, error in if let response = response { - NSLog("Finished successfully with response:\n\(response)") + NSLog("2. Finished successfully with response:\n\(response)") } else { - NSLog("Finished with error: \(error!)") + NSLog("2. Finished with error: \(error!)") } + NSLog("2. Response headers: \(RPC.responseHeaders)") + NSLog("2. Response trailers: \(RPC.responseTrailers)") } + RPC.requestHeaders["My-Header"] = "My value" + + RPC.start() + + // Same example call using the generic gRPC client library: let method = ProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall") @@ -64,14 +84,16 @@ class ViewController: UIViewController { let call = GRPCCall(host: RemoteHost, path: method.HTTPPath, requestsWriter: requestsWriter) - let responsesWriteable = GRXWriteable { (value: AnyObject?, error: NSError?) in - if let value = value as? NSData { - NSLog("Received response:\n\(RMTSimpleResponse(data: value, error: nil))") + call.requestHeaders["My-Header"] = "My value" + + call.startWithWriteable(GRXWriteable { response, error in + if let response = response as? NSData { + NSLog("3. Received response:\n\(RMTSimpleResponse(data: response, error: nil))") } else { - NSLog("Finished with error: \(error!)") + NSLog("3. Finished with error: \(error!)") } - } - - call.startWithWriteable(responsesWriteable) + NSLog("3. Response headers: \(call.responseHeaders)") + NSLog("3. Response trailers: \(call.responseTrailers)") + }) } } -- cgit v1.2.3 From 3569ae43ac07ce7cc6a4aaf60eedab6db0074bd3 Mon Sep 17 00:00:00 2001 From: Jorge Canizales Date: Thu, 3 Sep 2015 13:37:58 -0700 Subject: Fix Bazel breakage due to magic Cocoapods header search path --- src/objective-c/GRPCClient/private/GRPCRequestHeaders.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m index dfec2a7e7e..761677ce50 100644 --- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m +++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m @@ -35,7 +35,7 @@ #import -#import "GRPCCall.h" +#import "../GRPCCall.h" #import "NSDictionary+GRPC.h" // Used by the setter. -- cgit v1.2.3 From 791a48012768d8ebe824d0d9d5ae156db33edfb8 Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Fri, 4 Sep 2015 00:36:10 +0200 Subject: Even if the stream was cancelled, notify of its state change. --- src/core/transport/chttp2_transport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index aa6a860c67..9e3d7dd551 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -695,9 +695,9 @@ static void perform_stream_op_locked( } grpc_chttp2_incoming_metadata_live_op_buffer_end( &stream_global->outstanding_metadata); + grpc_chttp2_list_add_read_write_state_changed(transport_global, + stream_global); if (stream_global->id != 0) { - grpc_chttp2_list_add_read_write_state_changed(transport_global, - stream_global); grpc_chttp2_list_add_writable_stream(transport_global, stream_global); } } -- cgit v1.2.3 From 61e461e890ff6bc7e88ca98ad93abbdc0aed6901 Mon Sep 17 00:00:00 2001 From: yang-g Date: Thu, 3 Sep 2015 13:08:59 -0700 Subject: Guard against empty vector --- src/cpp/server/secure_server_credentials.cc | 8 +++++--- src/cpp/server/server_builder.cc | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index dfa9229c98..90afebfd2e 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -101,7 +101,9 @@ void AuthMetadataProcessorAyncWrapper::InvokeProcessor( 0, {{nullptr, nullptr, nullptr, nullptr}}}); } - cb(user_data, &consumed_md[0], consumed_md.size(), &response_md[0], + auto consumed_md_data = consumed_md.empty() ? nullptr : &consumed_md[0]; + auto response_md_data = response_md.empty() ? nullptr : &response_md[0]; + cb(user_data, consumed_md_data, consumed_md.size(), response_md_data, response_md.size(), static_cast(status.error_code()), status.error_message().c_str()); } @@ -130,8 +132,8 @@ std::shared_ptr 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, nullptr); + pem_key_cert_pairs.empty() ? nullptr : &pem_key_cert_pairs[0], + pem_key_cert_pairs.size(), options.force_client_auth, nullptr); return std::shared_ptr( new SecureServerCredentials(c_creds)); } diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index b739cbfe62..99bc8147a0 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -128,7 +128,8 @@ std::unique_ptr ServerBuilder::BuildAndStart() { *port->selected_port = r; } } - if (!server->Start(&cqs_[0], cqs_.size())) { + auto cqs_data = cqs_.empty() ? nullptr : &cqs_[0]; + if (!server->Start(cqs_data, cqs_.size())) { return nullptr; } return server; -- cgit v1.2.3 From 77ccdb99f8b9f06e606082d7a44f35e7e3faf38d Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Thu, 3 Sep 2015 17:35:26 -0700 Subject: Fixing lingering bytes clipping issue on socket shutdown. For more information, see comments on https://msdn.microsoft.com/en-us/library/windows/desktop/ms738547(v=vs.85).aspx --- src/core/iomgr/socket_windows.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src') diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c index 2cbe945ca3..557ca82226 100644 --- a/src/core/iomgr/socket_windows.c +++ b/src/core/iomgr/socket_windows.c @@ -35,8 +35,12 @@ #ifdef GPR_WINSOCK_SOCKET +#include +#include + #include #include +#include #include #include "src/core/iomgr/iocp_windows.h" @@ -63,6 +67,24 @@ grpc_winsocket *grpc_winsocket_create(SOCKET socket, const char *name) { various callsites of that function, which happens to be in various mutex hold states, and that'd be unsafe to call them directly. */ void grpc_winsocket_shutdown(grpc_winsocket *winsocket) { + /* Grab the function pointer for DisconnectEx for that specific socket. + It may change depending on the interface. */ + int status; + GUID guid = WSAID_DISCONNECTEX; + LPFN_DISCONNECTEX DisconnectEx; + DWORD ioctl_num_bytes; + + status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER, + &guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx), + &ioctl_num_bytes, NULL, NULL); + + if (status == 0) { + DisconnectEx(winsocket->socket, NULL, 0, 0); + } else { + char *utf8_message = gpr_format_message(WSAGetLastError()); + gpr_log(GPR_ERROR, "Unable to retrieve DisconnectEx pointer : %s", utf8_message); + gpr_free(utf8_message); + } closesocket(winsocket->socket); } -- cgit v1.2.3 From b26972fab46cb8ef26945372b1f26942cd41972d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 3 Sep 2015 17:47:14 -0700 Subject: update the interop tests based on spec --- .../Grpc.IntegrationTesting.csproj | 3 + .../Grpc.IntegrationTesting/InteropClient.cs | 233 +++++++-------------- .../Grpc.IntegrationTesting/InteropServer.cs | 82 +++----- src/csharp/Grpc.IntegrationTesting/packages.config | 1 + 4 files changed, 105 insertions(+), 214 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index a5945be922..a0bcf431f7 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -42,6 +42,9 @@ False ..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll + + ..\packages\CommandLineParser.1.9.71\lib\net45\CommandLine.dll + False ..\packages\Google.Apis.Auth.1.9.3\lib\net40\Google.Apis.Auth.dll diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index 8343e54122..830206bea2 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -37,6 +37,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using CommandLine; using Google.Apis.Auth.OAuth2; using Google.Protobuf; using Grpc.Auth; @@ -44,25 +45,54 @@ using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; using NUnit.Framework; +using CommandLine.Text; +using System.IO; namespace Grpc.IntegrationTesting { public class InteropClient { - private const string ServiceAccountUser = "155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk@developer.gserviceaccount.com"; - private const string ComputeEngineUser = "155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel@developer.gserviceaccount.com"; - private const string AuthScope = "https://www.googleapis.com/auth/xapi.zoo"; - private const string AuthScopeResponse = "xapi.zoo"; - private class ClientOptions { - public bool help; - public string serverHost = "127.0.0.1"; - public string serverHostOverride = TestCredentials.DefaultHostOverride; - public int? serverPort; - public string testCase = "large_unary"; - public bool useTls; - public bool useTestCa; + [Option("server_host", DefaultValue = "127.0.0.1")] + public string ServerHost { get; set; } + + [Option("server_host_override", DefaultValue = TestCredentials.DefaultHostOverride)] + public string ServerHostOverride { get; set; } + + [Option("server_port", Required = true)] + public int ServerPort { get; set; } + + [Option("test_case", DefaultValue = "large_unary")] + public string TestCase { get; set; } + + [Option("use_tls")] + public bool UseTls { get; set; } + + [Option("use_test_ca")] + public bool UseTestCa { get; set; } + + [Option("default_service_account", Required = false)] + public string DefaultServiceAccount { get; set; } + + [Option("oauth_scope", Required = false)] + public string OAuthScope { get; set; } + + [Option("service_account_key_file", Required = false)] + public string ServiceAccountKeyFile { get; set; } + + [HelpOption] + public string GetUsage() + { + var help = new HelpText + { + Heading = "gRPC C# interop testing client", + AddDashesToOption = true + }; + help.AddPreOptionsLine("Usage:"); + help.AddOptions(this); + return help; + } } ClientOptions options; @@ -74,26 +104,9 @@ namespace Grpc.IntegrationTesting public static void Run(string[] args) { - Console.WriteLine("gRPC C# interop testing client"); - ClientOptions options = ParseArguments(args); - - if (options.serverHost == null || !options.serverPort.HasValue || options.testCase == null) - { - Console.WriteLine("Missing required argument."); - Console.WriteLine(); - options.help = true; - } - - if (options.help) + var options = new ClientOptions(); + if (!Parser.Default.ParseArguments(args, options)) { - Console.WriteLine("Usage:"); - Console.WriteLine(" --server_host=HOSTNAME"); - Console.WriteLine(" --server_host_override=HOSTNAME"); - Console.WriteLine(" --server_port=PORT"); - Console.WriteLine(" --test_case=TESTCASE"); - Console.WriteLine(" --use_tls=BOOLEAN"); - Console.WriteLine(" --use_test_ca=BOOLEAN"); - Console.WriteLine(); Environment.Exit(1); } @@ -103,30 +116,27 @@ namespace Grpc.IntegrationTesting private async Task Run() { - Credentials credentials = null; - if (options.useTls) - { - credentials = TestCredentials.CreateTestClientCredentials(options.useTestCa); - } - + var credentials = options.UseTls ? TestCredentials.CreateTestClientCredentials(options.UseTestCa) : Credentials.Insecure; + List channelOptions = null; - if (!string.IsNullOrEmpty(options.serverHostOverride)) + if (!string.IsNullOrEmpty(options.ServerHostOverride)) { channelOptions = new List { - new ChannelOption(ChannelOptions.SslTargetNameOverride, options.serverHostOverride) + new ChannelOption(ChannelOptions.SslTargetNameOverride, options.ServerHostOverride) }; } - - var channel = new Channel(options.serverHost, options.serverPort.Value, credentials, channelOptions); + Console.WriteLine(options.ServerHost); + Console.WriteLine(options.ServerPort); + var channel = new Channel(options.ServerHost, options.ServerPort, credentials, channelOptions); TestService.TestServiceClient client = new TestService.TestServiceClient(channel); - await RunTestCaseAsync(options.testCase, client); + await RunTestCaseAsync(client, options); channel.ShutdownAsync().Wait(); } - private async Task RunTestCaseAsync(string testCase, TestService.TestServiceClient client) + private async Task RunTestCaseAsync(TestService.TestServiceClient client, ClientOptions options) { - switch (testCase) + switch (options.TestCase) { case "empty_unary": RunEmptyUnary(client); @@ -146,20 +156,17 @@ namespace Grpc.IntegrationTesting case "empty_stream": await RunEmptyStreamAsync(client); break; - case "service_account_creds": - await RunServiceAccountCredsAsync(client); - break; case "compute_engine_creds": - await RunComputeEngineCredsAsync(client); + await RunComputeEngineCredsAsync(client, options.DefaultServiceAccount, options.OAuthScope); break; case "jwt_token_creds": - await RunJwtTokenCredsAsync(client); + await RunJwtTokenCredsAsync(client, options.DefaultServiceAccount); break; case "oauth2_auth_token": - await RunOAuth2AuthTokenAsync(client); + await RunOAuth2AuthTokenAsync(client, options.DefaultServiceAccount, options.OAuthScope); break; case "per_rpc_creds": - await RunPerRpcCredsAsync(client); + await RunPerRpcCredsAsync(client, options.DefaultServiceAccount); break; case "cancel_after_begin": await RunCancelAfterBeginAsync(client); @@ -174,7 +181,7 @@ namespace Grpc.IntegrationTesting RunBenchmarkEmptyUnary(client); break; default: - throw new ArgumentException("Unknown test case " + testCase); + throw new ArgumentException("Unknown test case " + options.TestCase); } } @@ -313,32 +320,7 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunServiceAccountCredsAsync(TestService.TestServiceClient client) - { - Console.WriteLine("running service_account_creds"); - var credential = await GoogleCredential.GetApplicationDefaultAsync(); - credential = credential.CreateScoped(new[] { AuthScope }); - client.HeaderInterceptor = AuthInterceptors.FromCredential(credential); - - var request = new SimpleRequest - { - ResponseType = PayloadType.COMPRESSABLE, - ResponseSize = 314159, - Payload = CreateZerosPayload(271828), - FillUsername = true, - FillOauthScope = true - }; - - var response = client.UnaryCall(request); - - Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); - Assert.AreEqual(314159, response.Payload.Body.Length); - Assert.AreEqual(AuthScopeResponse, response.OauthScope); - Assert.AreEqual(ServiceAccountUser, response.Username); - Console.WriteLine("Passed!"); - } - - public static async Task RunComputeEngineCredsAsync(TestService.TestServiceClient client) + public static async Task RunComputeEngineCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope) { Console.WriteLine("running compute_engine_creds"); var credential = await GoogleCredential.GetApplicationDefaultAsync(); @@ -358,16 +340,16 @@ namespace Grpc.IntegrationTesting Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); Assert.AreEqual(314159, response.Payload.Body.Length); - Assert.AreEqual(AuthScopeResponse, response.OauthScope); - Assert.AreEqual(ComputeEngineUser, response.Username); + Assert.False(string.IsNullOrEmpty(response.OauthScope)); + Assert.True(oauthScope.Contains(response.OauthScope)); + Assert.AreEqual(defaultServiceAccount, response.Username); Console.WriteLine("Passed!"); } - public static async Task RunJwtTokenCredsAsync(TestService.TestServiceClient client) + public static async Task RunJwtTokenCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount) { Console.WriteLine("running jwt_token_creds"); var credential = await GoogleCredential.GetApplicationDefaultAsync(); - // check this a credential with scope support, but don't add the scope. Assert.IsTrue(credential.IsCreateScopedRequired); client.HeaderInterceptor = AuthInterceptors.FromCredential(credential); @@ -377,21 +359,20 @@ namespace Grpc.IntegrationTesting ResponseSize = 314159, Payload = CreateZerosPayload(271828), FillUsername = true, - FillOauthScope = true }; var response = client.UnaryCall(request); Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type); Assert.AreEqual(314159, response.Payload.Body.Length); - Assert.AreEqual(ServiceAccountUser, response.Username); + Assert.AreEqual(defaultServiceAccount, response.Username); Console.WriteLine("Passed!"); } - public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client) + public static async Task RunOAuth2AuthTokenAsync(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope) { Console.WriteLine("running oauth2_auth_token"); - ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { AuthScope }); + ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope }); string oauth2Token = await credential.GetAccessTokenForRequestAsync(); client.HeaderInterceptor = AuthInterceptors.FromAccessToken(oauth2Token); @@ -404,31 +385,30 @@ namespace Grpc.IntegrationTesting var response = client.UnaryCall(request); - Assert.AreEqual(AuthScopeResponse, response.OauthScope); - Assert.AreEqual(ServiceAccountUser, response.Username); + Assert.False(string.IsNullOrEmpty(response.OauthScope)); + Assert.True(oauthScope.Contains(response.OauthScope)); + Assert.AreEqual(defaultServiceAccount, response.Username); Console.WriteLine("Passed!"); } - public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client) + public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount) { Console.WriteLine("running per_rpc_creds"); - ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { AuthScope }); - string oauth2Token = await credential.GetAccessTokenForRequestAsync(); - var headerInterceptor = AuthInterceptors.FromAccessToken(oauth2Token); + ITokenAccess credential = await GoogleCredential.GetApplicationDefaultAsync(); + string accessToken = await credential.GetAccessTokenForRequestAsync(); + var headerInterceptor = AuthInterceptors.FromAccessToken(accessToken); var request = new SimpleRequest { FillUsername = true, - FillOauthScope = true }; var headers = new Metadata(); headerInterceptor(null, "", headers); var response = client.UnaryCall(request, headers: headers); - Assert.AreEqual(AuthScopeResponse, response.OauthScope); - Assert.AreEqual(ServiceAccountUser, response.Username); + Assert.AreEqual(defaultServiceAccount, response.Username); Console.WriteLine("Passed!"); } @@ -508,68 +488,5 @@ namespace Grpc.IntegrationTesting { return new Payload { Body = ByteString.CopyFrom(new byte[size]) }; } - - private static ClientOptions ParseArguments(string[] args) - { - var options = new ClientOptions(); - foreach (string arg in args) - { - ParseArgument(arg, options); - if (options.help) - { - break; - } - } - return options; - } - - private static void ParseArgument(string arg, ClientOptions options) - { - Match match; - match = Regex.Match(arg, "--server_host=(.*)"); - if (match.Success) - { - options.serverHost = match.Groups[1].Value.Trim(); - return; - } - - match = Regex.Match(arg, "--server_host_override=(.*)"); - if (match.Success) - { - options.serverHostOverride = match.Groups[1].Value.Trim(); - return; - } - - match = Regex.Match(arg, "--server_port=(.*)"); - if (match.Success) - { - options.serverPort = int.Parse(match.Groups[1].Value.Trim()); - return; - } - - match = Regex.Match(arg, "--test_case=(.*)"); - if (match.Success) - { - options.testCase = match.Groups[1].Value.Trim(); - return; - } - - match = Regex.Match(arg, "--use_tls=(.*)"); - if (match.Success) - { - options.useTls = bool.Parse(match.Groups[1].Value.Trim()); - return; - } - - match = Regex.Match(arg, "--use_test_ca=(.*)"); - if (match.Success) - { - options.useTestCa = bool.Parse(match.Groups[1].Value.Trim()); - return; - } - - Console.WriteLine(string.Format("Unrecognized argument \"{0}\"", arg)); - options.help = true; - } } } diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs index 718278f30a..513f8722d6 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs @@ -37,6 +37,9 @@ using System.Diagnostics; using System.IO; using System.Text.RegularExpressions; using System.Threading.Tasks; + +using CommandLine; +using CommandLine.Text; using Grpc.Core; using Grpc.Core.Utils; using Grpc.Testing; @@ -48,9 +51,24 @@ namespace Grpc.IntegrationTesting { private class ServerOptions { - public bool help; - public int? port = 8070; - public bool useTls; + [Option("port", DefaultValue = 8070)] + public int Port { get; set; } + + [Option("use_tls")] + public bool UseTls { get; set; } + + [HelpOption] + public string GetUsage() + { + var help = new HelpText + { + Heading = "gRPC C# interop testing server", + AddDashesToOption = true + }; + help.AddPreOptionsLine("Usage:"); + help.AddOptions(this); + return help; + } } ServerOptions options; @@ -62,22 +80,9 @@ namespace Grpc.IntegrationTesting public static void Run(string[] args) { - Console.WriteLine("gRPC C# interop testing server"); - ServerOptions options = ParseArguments(args); - - if (!options.port.HasValue) - { - Console.WriteLine("Missing required argument."); - Console.WriteLine(); - options.help = true; - } - - if (options.help) + var options = new ServerOptions(); + if (!Parser.Default.ParseArguments(args, options)) { - Console.WriteLine("Usage:"); - Console.WriteLine(" --port=PORT"); - Console.WriteLine(" --use_tls=BOOLEAN"); - Console.WriteLine(); Environment.Exit(1); } @@ -93,54 +98,19 @@ namespace Grpc.IntegrationTesting }; string host = "0.0.0.0"; - int port = options.port.Value; - if (options.useTls) + int port = options.Port; + if (options.UseTls) { server.Ports.Add(host, port, TestCredentials.CreateTestServerCredentials()); } else { - server.Ports.Add(host, options.port.Value, ServerCredentials.Insecure); + server.Ports.Add(host, options.Port, ServerCredentials.Insecure); } Console.WriteLine("Running server on " + string.Format("{0}:{1}", host, port)); server.Start(); server.ShutdownTask.Wait(); } - - private static ServerOptions ParseArguments(string[] args) - { - var options = new ServerOptions(); - foreach (string arg in args) - { - ParseArgument(arg, options); - if (options.help) - { - break; - } - } - return options; - } - - private static void ParseArgument(string arg, ServerOptions options) - { - Match match; - match = Regex.Match(arg, "--port=(.*)"); - if (match.Success) - { - options.port = int.Parse(match.Groups[1].Value.Trim()); - return; - } - - match = Regex.Match(arg, "--use_tls=(.*)"); - if (match.Success) - { - options.useTls = bool.Parse(match.Groups[1].Value.Trim()); - return; - } - - Console.WriteLine(string.Format("Unrecognized argument \"{0}\"", arg)); - options.help = true; - } } } diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config index 8dfded1964..bdb3dadf44 100644 --- a/src/csharp/Grpc.IntegrationTesting/packages.config +++ b/src/csharp/Grpc.IntegrationTesting/packages.config @@ -1,6 +1,7 @@  + -- cgit v1.2.3 From ee0ef4dfde3176a8f7a136b7728eb69757ef0ea9 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Thu, 3 Sep 2015 18:40:42 -0700 Subject: ugly fix of per_rpc_creds test --- src/csharp/Grpc.IntegrationTesting/InteropClient.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index 830206bea2..34d5157d3e 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -396,7 +396,9 @@ namespace Grpc.IntegrationTesting Console.WriteLine("running per_rpc_creds"); ITokenAccess credential = await GoogleCredential.GetApplicationDefaultAsync(); - string accessToken = await credential.GetAccessTokenForRequestAsync(); + // TODO: currently there's no way how to obtain AuthURI for JWT per-rpc creds. + string authUri = "https://grpc-test.sandbox.google.com/grpc.testing.TestService"; + string accessToken = await credential.GetAccessTokenForRequestAsync(authUri); var headerInterceptor = AuthInterceptors.FromAccessToken(accessToken); var request = new SimpleRequest -- cgit v1.2.3 From 37b0044844a82a43ef64b581340db00bc3af5095 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 4 Sep 2015 08:39:14 -0700 Subject: Fix a case where :status could be returned to applications --- src/core/channel/http_client_filter.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c index 2b61d33c29..ec832a0367 100644 --- a/src/core/channel/http_client_filter.c +++ b/src/core/channel/http_client_filter.c @@ -85,16 +85,14 @@ static grpc_mdelem *client_filter(void *user_data, grpc_mdelem *md) { static void hc_on_recv(void *user_data, int success) { grpc_call_element *elem = user_data; call_data *calld = elem->call_data; - if (success) { - size_t i; - size_t nops = calld->recv_ops->nops; - grpc_stream_op *ops = calld->recv_ops->ops; - for (i = 0; i < nops; i++) { - grpc_stream_op *op = &ops[i]; - if (op->type != GRPC_OP_METADATA) continue; - calld->got_initial_metadata = 1; - grpc_metadata_batch_filter(&op->data.metadata, client_filter, elem); - } + size_t i; + size_t nops = calld->recv_ops->nops; + grpc_stream_op *ops = calld->recv_ops->ops; + for (i = 0; i < nops; i++) { + grpc_stream_op *op = &ops[i]; + if (op->type != GRPC_OP_METADATA) continue; + calld->got_initial_metadata = 1; + grpc_metadata_batch_filter(&op->data.metadata, client_filter, elem); } calld->on_done_recv->cb(calld->on_done_recv->cb_arg, success); } -- cgit v1.2.3 From 581846ba9b84087313fec0f565ffcc6c74e45991 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 4 Sep 2015 12:04:17 -0700 Subject: Update debian install instructions, jessie-backports --- INSTALL | 4 ++-- src/node/README.md | 6 +++--- src/php/README.md | 6 +++--- src/python/README.md | 6 +++--- src/ruby/README.md | 6 +++--- 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/INSTALL b/INSTALL index de13d65d41..a0df57dcd3 100644 --- a/INSTALL +++ b/INSTALL @@ -11,12 +11,12 @@ wiki pages: On Linux (Debian): - Note: you will need to add the Debian 'testing' distribution to your sources + Note: you will need to add the Debian 'jessie-backports' distribution to your sources file first. Add the following line to your `/etc/apt/sources.list` file: - deb http://ftp.us.debian.org/debian testing main contrib non-free + deb http://http.debian.net/debian jessie-backports main Install the gRPC library: diff --git a/src/node/README.md b/src/node/README.md index 0b97680feb..7719d08290 100644 --- a/src/node/README.md +++ b/src/node/README.md @@ -11,10 +11,10 @@ Beta **Linux (Debian):** -Add [Debian testing][] to your `sources.list` file. Example: +Add [Debian jessie-backports][] to your `sources.list` file. Example: ```sh -echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \ +echo "deb http://http.debian.net/debian jessie-backports main" | \ 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 testing]:https://www.debian.org/releases/stretch/ +[Debian jessie-backports]:http://backports.debian.org/Instructions/ diff --git a/src/php/README.md b/src/php/README.md index afa09d79a1..51322c7526 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 testing][] to your `sources.list` file. Example: +Add [Debian jessie-backports][] to your `sources.list` file. Example: ```sh -echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \ +echo "deb http://http.debian.net/debian jessie-backports main" | \ sudo tee -a /etc/apt/sources.list ``` @@ -167,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 testing]:https://www.debian.org/releases/stretch/ +[Debian jessie-backports]:http://backports.debian.org/Instructions/ diff --git a/src/python/README.md b/src/python/README.md index 67d1a173a2..afe7c731f1 100644 --- a/src/python/README.md +++ b/src/python/README.md @@ -16,10 +16,10 @@ INSTALLATION **Linux (Debian):** -Add [Debian testing][] to your `sources.list` file. Example: +Add [Debian jessie-backports][] to your `sources.list` file. Example: ```sh -echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \ +echo "deb http://http.debian.net/debian jessie-backports main" | \ 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 testing]:https://www.debian.org/releases/stretch/ +[Debian jessie-backports]:http://backports.debian.org/Instructions/ diff --git a/src/ruby/README.md b/src/ruby/README.md index 7f75c0e313..8c56ceb135 100644 --- a/src/ruby/README.md +++ b/src/ruby/README.md @@ -19,10 +19,10 @@ INSTALLATION **Linux (Debian):** -Add [Debian testing][] to your `sources.list` file. Example: +Add [Debian jessie-backports][] to your `sources.list` file. Example: ```sh -echo "deb http://ftp.us.debian.org/debian testing main contrib non-free" | \ +echo "deb http://http.debian.net/debian jessie-backports main" | \ 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 testing]:https://www.debian.org/releases/stretch/ +[Debian jessie-backports]:http://backports.debian.org/Instructions/ -- cgit v1.2.3 From bea7cbd9a565a853e5147a8f4e42a91376e3e52d Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 4 Sep 2015 14:08:19 -0700 Subject: use service account credentials for per RPC test --- src/csharp/Grpc.IntegrationTesting/InteropClient.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs index 34d5157d3e..0884c6ea60 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs @@ -166,7 +166,7 @@ namespace Grpc.IntegrationTesting await RunOAuth2AuthTokenAsync(client, options.DefaultServiceAccount, options.OAuthScope); break; case "per_rpc_creds": - await RunPerRpcCredsAsync(client, options.DefaultServiceAccount); + await RunPerRpcCredsAsync(client, options.DefaultServiceAccount, options.OAuthScope); break; case "cancel_after_begin": await RunCancelAfterBeginAsync(client); @@ -391,14 +391,11 @@ namespace Grpc.IntegrationTesting Console.WriteLine("Passed!"); } - public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount) + public static async Task RunPerRpcCredsAsync(TestService.TestServiceClient client, string defaultServiceAccount, string oauthScope) { Console.WriteLine("running per_rpc_creds"); - - ITokenAccess credential = await GoogleCredential.GetApplicationDefaultAsync(); - // TODO: currently there's no way how to obtain AuthURI for JWT per-rpc creds. - string authUri = "https://grpc-test.sandbox.google.com/grpc.testing.TestService"; - string accessToken = await credential.GetAccessTokenForRequestAsync(authUri); + ITokenAccess credential = (await GoogleCredential.GetApplicationDefaultAsync()).CreateScoped(new[] { oauthScope }); + string accessToken = await credential.GetAccessTokenForRequestAsync(); var headerInterceptor = AuthInterceptors.FromAccessToken(accessToken); var request = new SimpleRequest -- cgit v1.2.3 From 13db8e517dd390cb1ede0146f5b0182e5f1e4dd5 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Fri, 4 Sep 2015 19:03:32 +0000 Subject: Plumb protocol objects through RPC Framework core --- src/python/grpcio/grpc/_links/service.py | 4 +- .../grpcio/grpc/framework/core/_ingestion.py | 17 +- .../grpcio/grpc/framework/core/_interfaces.py | 25 +++ .../grpcio/grpc/framework/core/_operation.py | 16 +- src/python/grpcio/grpc/framework/core/_protocol.py | 176 +++++++++++++++++++++ .../grpcio/grpc/framework/core/_reception.py | 14 +- src/python/grpcio/grpc/framework/crust/_calls.py | 8 +- src/python/grpcio/grpc/framework/crust/_control.py | 29 +++- src/python/grpcio/grpc/framework/crust/_service.py | 8 +- .../grpcio/grpc/framework/interfaces/base/base.py | 17 ++ .../grpc/framework/interfaces/base/utilities.py | 13 +- .../framework/interfaces/base/test_cases.py | 16 +- 12 files changed, 319 insertions(+), 24 deletions(-) create mode 100644 src/python/grpcio/grpc/framework/core/_protocol.py (limited to 'src') diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py index 34d3b262c9..07772c7de3 100644 --- a/src/python/grpcio/grpc/_links/service.py +++ b/src/python/grpcio/grpc/_links/service.py @@ -167,10 +167,12 @@ class _Kernel(object): request_deserializer, response_serializer, 1, _Read.READING, None, 1, _HighWrite.OPEN, _LowWrite.OPEN, False, None, None, None, set((_READ, _FINISH,))) + protocol = links.Protocol( + links.Protocol.Kind.SERVICER_CONTEXT, 'TODO: Service Context Object!') ticket = links.Ticket( call, 0, group, method, links.Ticket.Subscription.FULL, service_acceptance.deadline - time.time(), None, event.metadata, None, - None, None, None, None, 'TODO: Service Context Object!') + None, None, None, None, protocol) self._relay.add_value(ticket) def _on_read_event(self, event): diff --git a/src/python/grpcio/grpc/framework/core/_ingestion.py b/src/python/grpcio/grpc/framework/core/_ingestion.py index 9a7959a2dd..4129a8ce43 100644 --- a/src/python/grpcio/grpc/framework/core/_ingestion.py +++ b/src/python/grpcio/grpc/framework/core/_ingestion.py @@ -140,7 +140,7 @@ class _IngestionManager(_interfaces.IngestionManager): def __init__( self, lock, pool, subscription, subscription_creator, termination_manager, - transmission_manager, expiration_manager): + transmission_manager, expiration_manager, protocol_manager): """Constructor. Args: @@ -157,12 +157,14 @@ class _IngestionManager(_interfaces.IngestionManager): transmission_manager: The _interfaces.TransmissionManager for the operation. expiration_manager: The _interfaces.ExpirationManager for the operation. + protocol_manager: The _interfaces.ProtocolManager for the operation. """ self._lock = lock self._pool = pool self._termination_manager = termination_manager self._transmission_manager = transmission_manager self._expiration_manager = expiration_manager + self._protocol_manager = protocol_manager if subscription is None: self._subscription_creator = subscription_creator @@ -296,6 +298,8 @@ class _IngestionManager(_interfaces.IngestionManager): self._abort_and_notify( base.Outcome.Kind.REMOTE_FAILURE, code, details) elif outcome.return_value.subscription.kind is base.Subscription.Kind.FULL: + self._protocol_manager.set_protocol_receiver( + outcome.return_value.subscription.protocol_receiver) self._operator_post_create(outcome.return_value.subscription) else: # TODO(nathaniel): Support other subscriptions. @@ -378,7 +382,7 @@ class _IngestionManager(_interfaces.IngestionManager): def invocation_ingestion_manager( subscription, lock, pool, termination_manager, transmission_manager, - expiration_manager): + expiration_manager, protocol_manager): """Creates an IngestionManager appropriate for invocation-side use. Args: @@ -390,18 +394,20 @@ def invocation_ingestion_manager( transmission_manager: The _interfaces.TransmissionManager for the operation. expiration_manager: The _interfaces.ExpirationManager for the operation. + protocol_manager: The _interfaces.ProtocolManager for the operation. Returns: An IngestionManager appropriate for invocation-side use. """ return _IngestionManager( lock, pool, subscription, None, termination_manager, transmission_manager, - expiration_manager) + expiration_manager, protocol_manager) def service_ingestion_manager( servicer, operation_context, output_operator, lock, pool, - termination_manager, transmission_manager, expiration_manager): + termination_manager, transmission_manager, expiration_manager, + protocol_manager): """Creates an IngestionManager appropriate for service-side use. The returned IngestionManager will require its set_group_and_name method to be @@ -420,6 +426,7 @@ def service_ingestion_manager( transmission_manager: The _interfaces.TransmissionManager for the operation. expiration_manager: The _interfaces.ExpirationManager for the operation. + protocol_manager: The _interfaces.ProtocolManager for the operation. Returns: An IngestionManager appropriate for service-side use. @@ -428,4 +435,4 @@ def service_ingestion_manager( servicer, operation_context, output_operator) return _IngestionManager( lock, pool, None, subscription_creator, termination_manager, - transmission_manager, expiration_manager) + transmission_manager, expiration_manager, protocol_manager) diff --git a/src/python/grpcio/grpc/framework/core/_interfaces.py b/src/python/grpcio/grpc/framework/core/_interfaces.py index 7ac440722c..ffa686b2b7 100644 --- a/src/python/grpcio/grpc/framework/core/_interfaces.py +++ b/src/python/grpcio/grpc/framework/core/_interfaces.py @@ -203,6 +203,31 @@ class ExpirationManager(object): raise NotImplementedError() +class ProtocolManager(object): + """A manager of protocol-specific values passing through an operation.""" + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def set_protocol_receiver(self, protocol_receiver): + """Registers the customer object that will receive protocol objects. + + Args: + protocol_receiver: A base.ProtocolReceiver to which protocol objects for + the operation should be passed. + """ + raise NotImplementedError() + + @abc.abstractmethod + def accept_protocol_context(self, protocol_context): + """Accepts the protocol context object for the operation. + + Args: + protocol_context: An object designated for use as the protocol context + of the operation, with further semantics implementation-determined. + """ + raise NotImplementedError() + + class EmissionManager(base.Operator): """A manager of values emitted by customer code.""" __metaclass__ = abc.ABCMeta diff --git a/src/python/grpcio/grpc/framework/core/_operation.py b/src/python/grpcio/grpc/framework/core/_operation.py index d4eacc5a3f..020c0c9ed9 100644 --- a/src/python/grpcio/grpc/framework/core/_operation.py +++ b/src/python/grpcio/grpc/framework/core/_operation.py @@ -36,6 +36,7 @@ from grpc.framework.core import _emission from grpc.framework.core import _expiration from grpc.framework.core import _ingestion from grpc.framework.core import _interfaces +from grpc.framework.core import _protocol from grpc.framework.core import _reception from grpc.framework.core import _termination from grpc.framework.core import _transmission @@ -123,16 +124,19 @@ def invocation_operate( operation_id, ticket_sink, lock, pool, termination_manager) expiration_manager = _expiration.invocation_expiration_manager( timeout, lock, termination_manager, transmission_manager) + protocol_manager = _protocol.invocation_protocol_manager( + subscription, lock, pool, termination_manager, transmission_manager, + expiration_manager) operation_context = _context.OperationContext( lock, termination_manager, transmission_manager, expiration_manager) emission_manager = _emission.EmissionManager( lock, termination_manager, transmission_manager, expiration_manager) ingestion_manager = _ingestion.invocation_ingestion_manager( subscription, lock, pool, termination_manager, transmission_manager, - expiration_manager) + expiration_manager, protocol_manager) reception_manager = _reception.ReceptionManager( termination_manager, transmission_manager, expiration_manager, - ingestion_manager) + protocol_manager, ingestion_manager) termination_manager.set_expiration_manager(expiration_manager) transmission_manager.set_expiration_manager(expiration_manager) @@ -174,16 +178,20 @@ def service_operate( ticket.timeout, servicer_package.default_timeout, servicer_package.maximum_timeout, lock, termination_manager, transmission_manager) + protocol_manager = _protocol.service_protocol_manager( + lock, pool, termination_manager, transmission_manager, + expiration_manager) operation_context = _context.OperationContext( lock, termination_manager, transmission_manager, expiration_manager) emission_manager = _emission.EmissionManager( lock, termination_manager, transmission_manager, expiration_manager) ingestion_manager = _ingestion.service_ingestion_manager( servicer_package.servicer, operation_context, emission_manager, lock, - pool, termination_manager, transmission_manager, expiration_manager) + pool, termination_manager, transmission_manager, expiration_manager, + protocol_manager) reception_manager = _reception.ReceptionManager( termination_manager, transmission_manager, expiration_manager, - ingestion_manager) + protocol_manager, ingestion_manager) termination_manager.set_expiration_manager(expiration_manager) transmission_manager.set_expiration_manager(expiration_manager) diff --git a/src/python/grpcio/grpc/framework/core/_protocol.py b/src/python/grpcio/grpc/framework/core/_protocol.py new file mode 100644 index 0000000000..3177b5e302 --- /dev/null +++ b/src/python/grpcio/grpc/framework/core/_protocol.py @@ -0,0 +1,176 @@ +# 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. + +"""State and behavior for passing protocol objects in an operation.""" + +import collections +import enum + +from grpc.framework.core import _constants +from grpc.framework.core import _interfaces +from grpc.framework.core import _utilities +from grpc.framework.foundation import callable_util +from grpc.framework.interfaces.base import base + +_EXCEPTION_LOG_MESSAGE = 'Exception delivering protocol object!' + +_LOCAL_FAILURE_OUTCOME = _utilities.Outcome( + base.Outcome.Kind.LOCAL_FAILURE, None, None) + + +class _Awaited( + collections.namedtuple('_Awaited', ('kind', 'value',))): + + @enum.unique + class Kind(enum.Enum): + NOT_YET_ARRIVED = 'not yet arrived' + ARRIVED = 'arrived' + +_NOT_YET_ARRIVED = _Awaited(_Awaited.Kind.NOT_YET_ARRIVED, None) +_ARRIVED_AND_NONE = _Awaited(_Awaited.Kind.ARRIVED, None) + + +class _Transitory( + collections.namedtuple('_Transitory', ('kind', 'value',))): + + @enum.unique + class Kind(enum.Enum): + NOT_YET_SEEN = 'not yet seen' + PRESENT = 'present' + GONE = 'gone' + +_NOT_YET_SEEN = _Transitory(_Transitory.Kind.NOT_YET_SEEN, None) +_GONE = _Transitory(_Transitory.Kind.GONE, None) + + +class _ProtocolManager(_interfaces.ProtocolManager): + """An implementation of _interfaces.ExpirationManager.""" + + def __init__( + self, protocol_receiver, lock, pool, termination_manager, + transmission_manager, expiration_manager): + """Constructor. + + Args: + protocol_receiver: An _Awaited wrapping of the base.ProtocolReceiver to + which protocol objects should be passed during the operation. May be + of kind _Awaited.Kind.NOT_YET_ARRIVED if the customer's subscription is + not yet known and may be of kind _Awaited.Kind.ARRIVED but with a value + of None if the customer's subscription did not include a + ProtocolReceiver. + lock: The operation-wide lock. + pool: A thread pool. + termination_manager: The _interfaces.TerminationManager for the operation. + transmission_manager: The _interfaces.TransmissionManager for the + operation. + expiration_manager: The _interfaces.ExpirationManager for the operation. + """ + self._lock = lock + self._pool = pool + self._termination_manager = termination_manager + self._transmission_manager = transmission_manager + self._expiration_manager = expiration_manager + + self._protocol_receiver = protocol_receiver + self._context = _NOT_YET_SEEN + + def _abort_and_notify(self, outcome): + if self._termination_manager.outcome is None: + self._termination_manager.abort(outcome) + self._transmission_manager.abort(outcome) + self._expiration_manager.terminate() + + def _deliver(self, behavior, value): + def deliver(): + delivery_outcome = callable_util.call_logging_exceptions( + behavior, _EXCEPTION_LOG_MESSAGE, value) + if delivery_outcome.kind is callable_util.Outcome.Kind.RAISED: + with self._lock: + self._abort_and_notify(_LOCAL_FAILURE_OUTCOME) + self._pool.submit( + callable_util.with_exceptions_logged( + deliver, _constants.INTERNAL_ERROR_LOG_MESSAGE)) + + def set_protocol_receiver(self, protocol_receiver): + """See _interfaces.ProtocolManager.set_protocol_receiver for spec.""" + self._protocol_receiver = _Awaited(_Awaited.Kind.ARRIVED, protocol_receiver) + if (self._context.kind is _Transitory.Kind.PRESENT and + protocol_receiver is not None): + self._deliver(protocol_receiver.context, self._context.value) + self._context = _GONE + + def accept_protocol_context(self, protocol_context): + """See _interfaces.ProtocolManager.accept_protocol_context for spec.""" + if self._protocol_receiver.kind is _Awaited.Kind.ARRIVED: + if self._protocol_receiver.value is not None: + self._deliver(self._protocol_receiver.value.context, protocol_context) + self._context = _GONE + else: + self._context = _Transitory(_Transitory.Kind.PRESENT, protocol_context) + + +def invocation_protocol_manager( + subscription, lock, pool, termination_manager, transmission_manager, + expiration_manager): + """Creates an _interfaces.ProtocolManager for invocation-side use. + + Args: + subscription: The local customer's subscription to the operation. + lock: The operation-wide lock. + pool: A thread pool. + termination_manager: The _interfaces.TerminationManager for the operation. + transmission_manager: The _interfaces.TransmissionManager for the + operation. + expiration_manager: The _interfaces.ExpirationManager for the operation. + """ + if subscription.kind is base.Subscription.Kind.FULL: + awaited_protocol_receiver = _Awaited( + _Awaited.Kind.ARRIVED, subscription.protocol_receiver) + else: + awaited_protocol_receiver = _ARRIVED_AND_NONE + return _ProtocolManager( + awaited_protocol_receiver, lock, pool, termination_manager, + transmission_manager, expiration_manager) + + +def service_protocol_manager( + lock, pool, termination_manager, transmission_manager, expiration_manager): + """Creates an _interfaces.ProtocolManager for service-side use. + + Args: + lock: The operation-wide lock. + pool: A thread pool. + termination_manager: The _interfaces.TerminationManager for the operation. + transmission_manager: The _interfaces.TransmissionManager for the + operation. + expiration_manager: The _interfaces.ExpirationManager for the operation. + """ + return _ProtocolManager( + _NOT_YET_ARRIVED, lock, pool, termination_manager, transmission_manager, + expiration_manager) diff --git a/src/python/grpcio/grpc/framework/core/_reception.py b/src/python/grpcio/grpc/framework/core/_reception.py index d374cf0c8c..ff81450dee 100644 --- a/src/python/grpcio/grpc/framework/core/_reception.py +++ b/src/python/grpcio/grpc/framework/core/_reception.py @@ -51,23 +51,31 @@ _RECEPTION_FAILURE_OUTCOME = _utilities.Outcome( base.Outcome.Kind.RECEPTION_FAILURE, None, None) +def _carrying_protocol_context(ticket): + return ticket.protocol is not None and ticket.protocol.kind in ( + links.Protocol.Kind.INVOCATION_CONTEXT, + links.Protocol.Kind.SERVICER_CONTEXT,) + + class ReceptionManager(_interfaces.ReceptionManager): """A ReceptionManager based around a _Receiver passed to it.""" def __init__( self, termination_manager, transmission_manager, expiration_manager, - ingestion_manager): + protocol_manager, ingestion_manager): """Constructor. Args: termination_manager: The operation's _interfaces.TerminationManager. transmission_manager: The operation's _interfaces.TransmissionManager. expiration_manager: The operation's _interfaces.ExpirationManager. + protocol_manager: The operation's _interfaces.ProtocolManager. ingestion_manager: The operation's _interfaces.IngestionManager. """ self._termination_manager = termination_manager self._transmission_manager = transmission_manager self._expiration_manager = expiration_manager + self._protocol_manager = protocol_manager self._ingestion_manager = ingestion_manager self._lowest_unseen_sequence_number = 0 @@ -100,6 +108,10 @@ class ReceptionManager(_interfaces.ReceptionManager): def _process_one(self, ticket): if ticket.sequence_number == 0: self._ingestion_manager.set_group_and_method(ticket.group, ticket.method) + if _carrying_protocol_context(ticket): + self._protocol_manager.accept_protocol_context(ticket.protocol.value) + else: + self._protocol_manager.accept_protocol_context(None) if ticket.timeout is not None: self._expiration_manager.change_timeout(ticket.timeout) if ticket.termination is None: diff --git a/src/python/grpcio/grpc/framework/crust/_calls.py b/src/python/grpcio/grpc/framework/crust/_calls.py index 68db9fab8e..bff940d747 100644 --- a/src/python/grpcio/grpc/framework/crust/_calls.py +++ b/src/python/grpcio/grpc/framework/crust/_calls.py @@ -42,10 +42,12 @@ def _invoke( end, group, method, timeout, protocol_options, initial_metadata, payload, complete): rendezvous = _control.Rendezvous(None, None) + subscription = utilities.full_subscription( + rendezvous, _control.protocol_receiver(rendezvous)) operation_context, operator = end.operate( - group, method, utilities.full_subscription(rendezvous), timeout, - protocol_options=protocol_options, initial_metadata=initial_metadata, - payload=payload, completion=_EMPTY_COMPLETION if complete else None) + group, method, subscription, timeout, protocol_options=protocol_options, + initial_metadata=initial_metadata, payload=payload, + completion=_EMPTY_COMPLETION if complete else None) rendezvous.set_operator_and_context(operator, operation_context) outcome = operation_context.add_termination_callback(rendezvous.set_outcome) if outcome is not None: diff --git a/src/python/grpcio/grpc/framework/crust/_control.py b/src/python/grpcio/grpc/framework/crust/_control.py index e02a41d720..5e9efdf732 100644 --- a/src/python/grpcio/grpc/framework/crust/_control.py +++ b/src/python/grpcio/grpc/framework/crust/_control.py @@ -182,6 +182,8 @@ class Rendezvous(base.Operator, future.Future, stream.Consumer, face.Call): self._operator = operator self._operation_context = operation_context + self._protocol_context = _NOT_YET_ARRIVED + self._up_initial_metadata = _NOT_YET_ARRIVED self._up_payload = None self._up_allowance = 1 @@ -444,7 +446,13 @@ class Rendezvous(base.Operator, future.Future, stream.Consumer, face.Call): def protocol_context(self): with self._condition: - raise NotImplementedError('TODO: protocol context implementation!') + while True: + if self._protocol_context.kind is _Awaited.Kind.ARRIVED: + return self._protocol_context.value + elif self._termination.abortion_error is not None: + raise self._termination.abortion_error + else: + self._condition.wait() def initial_metadata(self): with self._condition: @@ -518,11 +526,30 @@ class Rendezvous(base.Operator, future.Future, stream.Consumer, face.Call): else: self._down_details = _Transitory(_Transitory.Kind.PRESENT, details) + def set_protocol_context(self, protocol_context): + with self._condition: + self._protocol_context = _Awaited( + _Awaited.Kind.ARRIVED, protocol_context) + self._condition.notify_all() + def set_outcome(self, outcome): with self._condition: return self._set_outcome(outcome) +class _ProtocolReceiver(base.ProtocolReceiver): + + def __init__(self, rendezvous): + self._rendezvous = rendezvous + + def context(self, protocol_context): + self._rendezvous.set_protocol_context(protocol_context) + + +def protocol_receiver(rendezvous): + return _ProtocolReceiver(rendezvous) + + def pool_wrap(behavior, operation_context): """Wraps an operation-related behavior so that it may be called in a pool. diff --git a/src/python/grpcio/grpc/framework/crust/_service.py b/src/python/grpcio/grpc/framework/crust/_service.py index f1855c2f47..9903415c09 100644 --- a/src/python/grpcio/grpc/framework/crust/_service.py +++ b/src/python/grpcio/grpc/framework/crust/_service.py @@ -74,10 +74,12 @@ class _ServicerContext(face.ServicerContext): def _adaptation(pool, in_pool): def adaptation(operator, operation_context): rendezvous = _control.Rendezvous(operator, operation_context) + subscription = utilities.full_subscription( + rendezvous, _control.protocol_receiver(rendezvous)) outcome = operation_context.add_termination_callback(rendezvous.set_outcome) if outcome is None: pool.submit(_control.pool_wrap(in_pool, operation_context), rendezvous) - return utilities.full_subscription(rendezvous) + return subscription else: raise abandonment.Abandoned() return adaptation @@ -154,6 +156,8 @@ def adapt_event_stream_stream(method, pool): def adapt_multi_method(multi_method, pool): def adaptation(group, method, operator, operation_context): rendezvous = _control.Rendezvous(operator, operation_context) + subscription = utilities.full_subscription( + rendezvous, _control.protocol_receiver(rendezvous)) outcome = operation_context.add_termination_callback(rendezvous.set_outcome) if outcome is None: def in_pool(): @@ -163,7 +167,7 @@ def adapt_multi_method(multi_method, pool): request_consumer.consume(request) request_consumer.terminate() pool.submit(_control.pool_wrap(in_pool, operation_context), rendezvous) - return utilities.full_subscription(rendezvous) + return subscription else: raise abandonment.Abandoned() return adaptation diff --git a/src/python/grpcio/grpc/framework/interfaces/base/base.py b/src/python/grpcio/grpc/framework/interfaces/base/base.py index 013e7c66f2..a1e70be5e8 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/base.py +++ b/src/python/grpcio/grpc/framework/interfaces/base/base.py @@ -184,6 +184,19 @@ class Operator(object): """ raise NotImplementedError() +class ProtocolReceiver(object): + """A means of receiving protocol values during an operation.""" + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def context(self, protocol_context): + """Accepts the protocol context object for the operation. + + Args: + protocol_context: The protocol context object for the operation. + """ + raise NotImplementedError() + class Subscription(object): """Describes customer code's interest in values from the other side. @@ -199,7 +212,11 @@ class Subscription(object): otherwise. operator: An Operator to be passed values from the other side of the operation. Must be non-None if kind is Kind.FULL. Must be None otherwise. + protocol_receiver: A ProtocolReceiver to be passed protocol objects as they + become available during the operation. Must be non-None if kind is + Kind.FULL. """ + __metaclass__ = abc.ABCMeta @enum.unique class Kind(enum.Enum): diff --git a/src/python/grpcio/grpc/framework/interfaces/base/utilities.py b/src/python/grpcio/grpc/framework/interfaces/base/utilities.py index a9ee1a0981..87a85018f5 100644 --- a/src/python/grpcio/grpc/framework/interfaces/base/utilities.py +++ b/src/python/grpcio/grpc/framework/interfaces/base/utilities.py @@ -45,11 +45,12 @@ class _Subscription( base.Subscription, collections.namedtuple( '_Subscription', - ('kind', 'termination_callback', 'allowance', 'operator',))): + ('kind', 'termination_callback', 'allowance', 'operator', + 'protocol_receiver',))): """A trivial implementation of base.Subscription.""" _NONE_SUBSCRIPTION = _Subscription( - base.Subscription.Kind.NONE, None, None, None) + base.Subscription.Kind.NONE, None, None, None, None) def completion(terminal_metadata, code, message): @@ -66,14 +67,16 @@ def completion(terminal_metadata, code, message): return _Completion(terminal_metadata, code, message) -def full_subscription(operator): +def full_subscription(operator, protocol_receiver): """Creates a "full" base.Subscription for the given base.Operator. Args: operator: A base.Operator to be used in an operation. + protocol_receiver: A base.ProtocolReceiver to be used in an operation. Returns: A base.Subscription of kind base.Subscription.Kind.FULL wrapping the given - base.Operator. + base.Operator and base.ProtocolReceiver. """ - return _Subscription(base.Subscription.Kind.FULL, None, None, operator) + return _Subscription( + base.Subscription.Kind.FULL, None, None, operator, protocol_receiver) diff --git a/src/python/grpcio_test/grpc_test/framework/interfaces/base/test_cases.py b/src/python/grpcio_test/grpc_test/framework/interfaces/base/test_cases.py index 5065a3f38a..ddda1018c3 100644 --- a/src/python/grpcio_test/grpc_test/framework/interfaces/base/test_cases.py +++ b/src/python/grpcio_test/grpc_test/framework/interfaces/base/test_cases.py @@ -119,6 +119,17 @@ class _Operator(base.Operator): 'Deliberately raised exception from Operator.advance (in a test)!') +class _ProtocolReceiver(base.ProtocolReceiver): + + def __init__(self): + self._condition = threading.Condition() + self._contexts = [] + + def context(self, protocol_context): + with self._condition: + self._contexts.append(protocol_context) + + class _Servicer(base.Servicer): """A base.Servicer with instrumented for testing.""" @@ -144,7 +155,7 @@ class _Servicer(base.Servicer): controller.service_on_termination) if outcome is not None: controller.service_on_termination(outcome) - return utilities.full_subscription(operator) + return utilities.full_subscription(operator, _ProtocolReceiver()) class _OperationTest(unittest.TestCase): @@ -169,7 +180,8 @@ class _OperationTest(unittest.TestCase): test_operator = _Operator( self._controller, self._controller.on_invocation_advance, self._pool, None) - subscription = utilities.full_subscription(test_operator) + subscription = utilities.full_subscription( + test_operator, _ProtocolReceiver()) else: # TODO(nathaniel): support and test other subscription kinds. self.fail('Non-full subscriptions not yet supported!') -- cgit v1.2.3 From 41abb052b8ed180ca14b9ff1427a215b8e4dcd60 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Sat, 5 Sep 2015 02:46:08 +0000 Subject: gRPC protocol objects --- .../grpcio/grpc/_adapter/_intermediary_low.py | 10 +- src/python/grpcio/grpc/_adapter/fore.py | 4 +- src/python/grpcio/grpc/_adapter/rear.py | 6 +- src/python/grpcio/grpc/_links/invocation.py | 57 ++++- src/python/grpcio/grpc/_links/service.py | 39 +++- src/python/grpcio/grpc/beta/interfaces.py | 58 ++++++ .../grpc_test/_adapter/_intermediary_low_test.py | 8 +- .../grpc_test/beta/_beta_features_test.py | 231 +++++++++++++++++++++ 8 files changed, 389 insertions(+), 24 deletions(-) create mode 100644 src/python/grpcio_test/grpc_test/beta/_beta_features_test.py (limited to 'src') diff --git a/src/python/grpcio/grpc/_adapter/_intermediary_low.py b/src/python/grpcio/grpc/_adapter/_intermediary_low.py index 735ad205a4..e2feec6ffb 100644 --- a/src/python/grpcio/grpc/_adapter/_intermediary_low.py +++ b/src/python/grpcio/grpc/_adapter/_intermediary_low.py @@ -59,6 +59,7 @@ from grpc._adapter import _types _IGNORE_ME_TAG = object() Code = _types.StatusCode +WriteFlags = _types.OpWriteFlags class Status(collections.namedtuple('Status', ['code', 'details'])): @@ -125,9 +126,9 @@ class Call(object): ], _TagAdapter(finish_tag, Event.Kind.FINISH)) return err0 if err0 != _types.CallError.OK else err1 if err1 != _types.CallError.OK else err2 if err2 != _types.CallError.OK else _types.CallError.OK - def write(self, message, tag): + def write(self, message, tag, flags): return self._internal.start_batch([ - _types.OpArgs.send_message(message, 0) + _types.OpArgs.send_message(message, flags) ], _TagAdapter(tag, Event.Kind.WRITE_ACCEPTED)) def complete(self, tag): @@ -163,8 +164,11 @@ class Call(object): def cancel(self): return self._internal.cancel() + def peer(self): + return self._internal.peer() + def set_credentials(self, creds): - return self._internal.set_credentials(creds) + return self._internal.set_credentials(creds._internal) class Channel(object): diff --git a/src/python/grpcio/grpc/_adapter/fore.py b/src/python/grpcio/grpc/_adapter/fore.py index daa41e8bde..acdd69c420 100644 --- a/src/python/grpcio/grpc/_adapter/fore.py +++ b/src/python/grpcio/grpc/_adapter/fore.py @@ -56,7 +56,7 @@ class _LowWrite(enum.Enum): def _write(call, rpc_state, payload): serialized_payload = rpc_state.serializer(payload) if rpc_state.write.low is _LowWrite.OPEN: - call.write(serialized_payload, call) + call.write(serialized_payload, call, 0) rpc_state.write.low = _LowWrite.ACTIVE else: rpc_state.write.pending.append(serialized_payload) @@ -164,7 +164,7 @@ class ForeLink(base_interfaces.ForeLink, activated.Activated): if rpc_state.write.pending: serialized_payload = rpc_state.write.pending.pop(0) - call.write(serialized_payload, call) + call.write(serialized_payload, call, 0) elif rpc_state.write.high is _common.HighWrite.CLOSED: _status(call, rpc_state) else: diff --git a/src/python/grpcio/grpc/_adapter/rear.py b/src/python/grpcio/grpc/_adapter/rear.py index fd6f45f7a7..17fa47f746 100644 --- a/src/python/grpcio/grpc/_adapter/rear.py +++ b/src/python/grpcio/grpc/_adapter/rear.py @@ -78,7 +78,7 @@ class _RPCState(object): def _write(operation_id, call, outstanding, write_state, serialized_payload): if write_state.low is _LowWrite.OPEN: - call.write(serialized_payload, operation_id) + call.write(serialized_payload, operation_id, 0) outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) write_state.low = _LowWrite.ACTIVE elif write_state.low is _LowWrite.ACTIVE: @@ -144,7 +144,7 @@ class RearLink(base_interfaces.RearLink, activated.Activated): if event.write_accepted: if rpc_state.common.write.pending: rpc_state.call.write( - rpc_state.common.write.pending.pop(0), operation_id) + rpc_state.common.write.pending.pop(0), operation_id, 0) rpc_state.outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) elif rpc_state.common.write.high is _common.HighWrite.CLOSED: rpc_state.call.complete(operation_id) @@ -263,7 +263,7 @@ class RearLink(base_interfaces.RearLink, activated.Activated): low_state = _LowWrite.OPEN else: serialized_payload = request_serializer(payload) - call.write(serialized_payload, operation_id) + call.write(serialized_payload, operation_id, 0) outstanding.add(_low.Event.Kind.WRITE_ACCEPTED) low_state = _LowWrite.ACTIVE diff --git a/src/python/grpcio/grpc/_links/invocation.py b/src/python/grpcio/grpc/_links/invocation.py index fecb550ae0..67ef86a176 100644 --- a/src/python/grpcio/grpc/_links/invocation.py +++ b/src/python/grpcio/grpc/_links/invocation.py @@ -37,6 +37,7 @@ import time from grpc._adapter import _intermediary_low from grpc._links import _constants +from grpc.beta import interfaces as beta_interfaces from grpc.framework.foundation import activated from grpc.framework.foundation import logging_pool from grpc.framework.foundation import relay @@ -73,11 +74,28 @@ class _LowWrite(enum.Enum): CLOSED = 'CLOSED' +class _Context(beta_interfaces.GRPCInvocationContext): + + def __init__(self): + self._lock = threading.Lock() + self._disable_next_compression = False + + def disable_next_request_compression(self): + with self._lock: + self._disable_next_compression = True + + def next_compression_disabled(self): + with self._lock: + disabled = self._disable_next_compression + self._disable_next_compression = False + return disabled + + class _RPCState(object): def __init__( self, call, request_serializer, response_deserializer, sequence_number, - read, allowance, high_write, low_write, due): + read, allowance, high_write, low_write, due, context): self.call = call self.request_serializer = request_serializer self.response_deserializer = response_deserializer @@ -87,6 +105,7 @@ class _RPCState(object): self.high_write = high_write self.low_write = low_write self.due = due + self.context = context def _no_longer_due(kind, rpc_state, key, rpc_states): @@ -209,7 +228,7 @@ class _Kernel(object): def _invoke( self, operation_id, group, method, initial_metadata, payload, termination, - timeout, allowance): + timeout, allowance, options): """Invoke an RPC. Args: @@ -224,6 +243,7 @@ class _Kernel(object): timeout: A duration of time in seconds to allow for the RPC. allowance: The number of payloads (beyond the free first one) that the local ticket exchange mate has granted permission to be read. + options: A beta_interfaces.GRPCCallOptions value or None. """ if termination is links.Ticket.Termination.COMPLETION: high_write = _HighWrite.CLOSED @@ -241,6 +261,8 @@ class _Kernel(object): call = _intermediary_low.Call( self._channel, self._completion_queue, '/%s/%s' % (group, method), self._host, time.time() + timeout) + if options is not None and options.credentials is not None: + call.set_credentials(options.credentials._intermediary_low_credentials) if transformed_initial_metadata is not None: for metadata_key, metadata_value in transformed_initial_metadata: call.add_metadata(metadata_key, metadata_value) @@ -254,17 +276,33 @@ class _Kernel(object): low_write = _LowWrite.OPEN due = set((_METADATA, _FINISH,)) else: - call.write(request_serializer(payload), operation_id) + if options is not None and options.disable_compression: + flags = _intermediary_low.WriteFlags.WRITE_NO_COMPRESS + else: + flags = 0 + call.write(request_serializer(payload), operation_id, flags) low_write = _LowWrite.ACTIVE due = set((_WRITE, _METADATA, _FINISH,)) + context = _Context() self._rpc_states[operation_id] = _RPCState( - call, request_serializer, response_deserializer, 0, + call, request_serializer, response_deserializer, 1, _Read.AWAITING_METADATA, 1 if allowance is None else (1 + allowance), - high_write, low_write, due) + high_write, low_write, due, context) + protocol = links.Protocol(links.Protocol.Kind.INVOCATION_CONTEXT, context) + ticket = links.Ticket( + operation_id, 0, None, None, None, None, None, None, None, None, None, + None, None, protocol) + self._relay.add_value(ticket) 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) + disable_compression = rpc_state.context.next_compression_disabled() + if disable_compression: + flags = _intermediary_low.WriteFlags.WRITE_NO_COMPRESS + else: + flags = 0 + rpc_state.call.write( + rpc_state.request_serializer(payload), operation_id, flags) rpc_state.low_write = _LowWrite.ACTIVE rpc_state.due.add(_WRITE) @@ -292,10 +330,15 @@ class _Kernel(object): if self._completion_queue is None: logging.error('Received invocation ticket %s after stop!', ticket) else: + if (ticket.protocol is not None and + ticket.protocol.kind is links.Protocol.Kind.CALL_OPTION): + grpc_call_options = ticket.protocol.value + else: + grpc_call_options = None self._invoke( ticket.operation_id, ticket.group, ticket.method, ticket.initial_metadata, ticket.payload, ticket.termination, - ticket.timeout, ticket.allowance) + ticket.timeout, ticket.allowance, grpc_call_options) else: rpc_state = self._rpc_states.get(ticket.operation_id) if rpc_state is not None: diff --git a/src/python/grpcio/grpc/_links/service.py b/src/python/grpcio/grpc/_links/service.py index 07772c7de3..f56df84007 100644 --- a/src/python/grpcio/grpc/_links/service.py +++ b/src/python/grpcio/grpc/_links/service.py @@ -37,6 +37,7 @@ import time from grpc._adapter import _intermediary_low from grpc._links import _constants +from grpc.beta import interfaces as beta_interfaces from grpc.framework.foundation import logging_pool from grpc.framework.foundation import relay from grpc.framework.interfaces.links import links @@ -89,12 +90,34 @@ class _LowWrite(enum.Enum): CLOSED = 'CLOSED' +class _Context(beta_interfaces.GRPCServicerContext): + + def __init__(self, call): + self._lock = threading.Lock() + self._call = call + self._disable_next_compression = False + + def peer(self): + with self._lock: + return self._call.peer() + + def disable_next_response_compression(self): + with self._lock: + self._disable_next_compression = True + + def next_compression_disabled(self): + with self._lock: + disabled = self._disable_next_compression + self._disable_next_compression = False + return disabled + + 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, due): + terminal_metadata, code, message, due, context): self.request_deserializer = request_deserializer self.response_serializer = response_serializer self.sequence_number = sequence_number @@ -110,6 +133,7 @@ class _RPCState(object): self.code = code self.message = message self.due = due + self.context = context def _no_longer_due(kind, rpc_state, key, rpc_states): @@ -163,12 +187,12 @@ class _Kernel(object): (group, method), _IDENTITY) call.read(call) + context = _Context(call) self._rpc_states[call] = _RPCState( request_deserializer, response_serializer, 1, _Read.READING, None, 1, _HighWrite.OPEN, _LowWrite.OPEN, False, None, None, None, - set((_READ, _FINISH,))) - protocol = links.Protocol( - links.Protocol.Kind.SERVICER_CONTEXT, 'TODO: Service Context Object!') + set((_READ, _FINISH,)), context) + protocol = links.Protocol(links.Protocol.Kind.SERVICER_CONTEXT, context) ticket = links.Ticket( call, 0, group, method, links.Ticket.Subscription.FULL, service_acceptance.deadline - time.time(), None, event.metadata, None, @@ -313,7 +337,12 @@ class _Kernel(object): self._relay.add_value(early_read_ticket) if ticket.payload is not None: - call.write(rpc_state.response_serializer(ticket.payload), call) + disable_compression = rpc_state.context.next_compression_disabled() + if disable_compression: + flags = _intermediary_low.WriteFlags.WRITE_NO_COMPRESS + else: + flags = 0 + call.write(rpc_state.response_serializer(ticket.payload), call, flags) rpc_state.due.add(_WRITE) rpc_state.low_write = _LowWrite.ACTIVE diff --git a/src/python/grpcio/grpc/beta/interfaces.py b/src/python/grpcio/grpc/beta/interfaces.py index 25e6a9c66b..79f2620dd4 100644 --- a/src/python/grpcio/grpc/beta/interfaces.py +++ b/src/python/grpcio/grpc/beta/interfaces.py @@ -29,6 +29,7 @@ """Constants and interfaces of the Beta API of gRPC Python.""" +import abc import enum @@ -52,3 +53,60 @@ class StatusCode(enum.Enum): UNAVAILABLE = 14 DATA_LOSS = 15 UNAUTHENTICATED = 16 + + +class GRPCCallOptions(object): + """A value encapsulating gRPC-specific options passed on RPC invocation. + + 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, disable_compression, subcall_of, credentials): + self.disable_compression = disable_compression + self.subcall_of = subcall_of + self.credentials = credentials + + +def grpc_call_options(disable_compression=False, credentials=None): + """Creates a GRPCCallOptions value to be passed at RPC invocation. + + All parameters are optional and should always be passed by keyword. + + Args: + disable_compression: A boolean indicating whether or not compression should + be disabled for the request object of the RPC. Only valid for + request-unary RPCs. + credentials: A ClientCredentials object to use for the invoked RPC. + """ + return GRPCCallOptions(disable_compression, None, credentials) + + +class GRPCServicerContext(object): + """Exposes gRPC-specific options and behaviors to code servicing RPCs.""" + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def peer(self): + """Identifies the peer that invoked the RPC being serviced. + + Returns: + A string identifying the peer that invoked the RPC being serviced. + """ + raise NotImplementedError() + + @abc.abstractmethod + def disable_next_response_compression(self): + """Disables compression of the next response passed by the application.""" + raise NotImplementedError() + + +class GRPCInvocationContext(object): + """Exposes gRPC-specific options and behaviors to code invoking RPCs.""" + __metaclass__ = abc.ABCMeta + + @abc.abstractmethod + def disable_next_request_compression(self): + """Disables compression of the next request passed by the application.""" + raise NotImplementedError() diff --git a/src/python/grpcio_test/grpc_test/_adapter/_intermediary_low_test.py b/src/python/grpcio_test/grpc_test/_adapter/_intermediary_low_test.py index 27a5b82e9c..90ad0b9bcb 100644 --- a/src/python/grpcio_test/grpc_test/_adapter/_intermediary_low_test.py +++ b/src/python/grpcio_test/grpc_test/_adapter/_intermediary_low_test.py @@ -191,7 +191,7 @@ class EchoTest(unittest.TestCase): metadata[server_leading_binary_metadata_key]) for datum in test_data: - client_call.write(datum, write_tag) + client_call.write(datum, write_tag, _low.WriteFlags.WRITE_NO_COMPRESS) write_accepted = self.client_events.get() self.assertIsNotNone(write_accepted) self.assertIs(write_accepted.kind, _low.Event.Kind.WRITE_ACCEPTED) @@ -206,7 +206,7 @@ class EchoTest(unittest.TestCase): self.assertIsNotNone(read_accepted.bytes) server_data.append(read_accepted.bytes) - server_call.write(read_accepted.bytes, write_tag) + server_call.write(read_accepted.bytes, write_tag, 0) write_accepted = self.server_events.get() self.assertIsNotNone(write_accepted) self.assertEqual(_low.Event.Kind.WRITE_ACCEPTED, write_accepted.kind) @@ -370,14 +370,14 @@ class CancellationTest(unittest.TestCase): self.assertIsNotNone(metadata_accepted) for datum in test_data: - client_call.write(datum, write_tag) + client_call.write(datum, write_tag, 0) write_accepted = self.client_events.get() server_call.read(read_tag) read_accepted = self.server_events.get() server_data.append(read_accepted.bytes) - server_call.write(read_accepted.bytes, write_tag) + server_call.write(read_accepted.bytes, write_tag, 0) write_accepted = self.server_events.get() self.assertIsNotNone(write_accepted) diff --git a/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py b/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py new file mode 100644 index 0000000000..89fe4b2acf --- /dev/null +++ b/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py @@ -0,0 +1,231 @@ +# 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 threading +import unittest + +from grpc.beta import beta +from grpc.beta import interfaces +from grpc.framework.common import cardinality +from grpc.framework.interfaces.face import utilities +from grpc_test import resources +from grpc_test.beta import test_utilities +from grpc_test.framework.common import test_constants + +_SERVER_HOST_OVERRIDE = 'foo.test.google.fr' + +_GROUP = 'group' +_UNARY_UNARY = 'unary-unary' +_UNARY_STREAM = 'unary-stream' +_STREAM_UNARY = 'stream-unary' +_STREAM_STREAM = 'stream-stream' + +_REQUEST = b'abc' +_RESPONSE = b'123' + + +class _Servicer(object): + + def __init__(self): + self._condition = threading.Condition() + self._peer = None + self._serviced = False + + def unary_unary(self, request, context): + with self._condition: + self._request = request + self._peer = context.protocol_context().peer() + context.protocol_context().disable_next_response_compression() + self._serviced = True + self._condition.notify_all() + return _RESPONSE + + def unary_stream(self, request, context): + with self._condition: + self._request = request + self._peer = context.protocol_context().peer() + context.protocol_context().disable_next_response_compression() + self._serviced = True + self._condition.notify_all() + return + yield + + def stream_unary(self, request_iterator, context): + for request in request_iterator: + self._request = request + with self._condition: + self._peer = context.protocol_context().peer() + context.protocol_context().disable_next_response_compression() + self._serviced = True + self._condition.notify_all() + return _RESPONSE + + def stream_stream(self, request_iterator, context): + for request in request_iterator: + with self._condition: + self._peer = context.protocol_context().peer() + context.protocol_context().disable_next_response_compression() + yield _RESPONSE + with self._condition: + self._serviced = True + self._condition.notify_all() + + def peer(self): + with self._condition: + return self._peer + + def block_until_serviced(self): + with self._condition: + while not self._serviced: + self._condition.wait() + + +class _BlockingIterator(object): + + def __init__(self, upstream): + self._condition = threading.Condition() + self._upstream = upstream + self._allowed = [] + + def __iter__(self): + return self + + def next(self): + with self._condition: + while True: + if self._allowed is None: + raise StopIteration() + elif self._allowed: + return self._allowed.pop(0) + else: + self._condition.wait() + + def allow(self): + with self._condition: + try: + self._allowed.append(next(self._upstream)) + except StopIteration: + self._allowed = None + self._condition.notify_all() + + +class BetaFeaturesTest(unittest.TestCase): + + def setUp(self): + self._servicer = _Servicer() + method_implementations = { + (_GROUP, _UNARY_UNARY): + utilities.unary_unary_inline(self._servicer.unary_unary), + (_GROUP, _UNARY_STREAM): + utilities.unary_stream_inline(self._servicer.unary_stream), + (_GROUP, _STREAM_UNARY): + utilities.stream_unary_inline(self._servicer.stream_unary), + (_GROUP, _STREAM_STREAM): + utilities.stream_stream_inline(self._servicer.stream_stream), + } + + cardinalities = { + _UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY, + _UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM, + _STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY, + _STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, + } + + server_options = beta.server_options( + thread_pool_size=test_constants.POOL_SIZE) + self._server = beta.server(method_implementations, options=server_options) + server_credentials = beta.ssl_server_credentials( + [(resources.private_key(), resources.certificate_chain(),),]) + port = self._server.add_secure_port('[::]:0', server_credentials) + self._server.start() + self._client_credentials = beta.ssl_client_credentials( + resources.test_root_certificates(), None, None) + channel = test_utilities.create_not_really_secure_channel( + 'localhost', port, self._client_credentials, _SERVER_HOST_OVERRIDE) + stub_options = beta.stub_options( + thread_pool_size=test_constants.POOL_SIZE) + self._dynamic_stub = beta.dynamic_stub( + channel, _GROUP, cardinalities, options=stub_options) + + def tearDown(self): + self._dynamic_stub = None + self._server.stop(test_constants.SHORT_TIMEOUT).wait() + + def test_unary_unary(self): + call_options = interfaces.grpc_call_options( + disable_compression=True, credentials=self._client_credentials) + response = getattr(self._dynamic_stub, _UNARY_UNARY)( + _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options) + self.assertEqual(_RESPONSE, response) + self.assertIsNotNone(self._servicer.peer()) + + def test_unary_stream(self): + call_options = interfaces.grpc_call_options( + disable_compression=True, credentials=self._client_credentials) + response_iterator = getattr(self._dynamic_stub, _UNARY_STREAM)( + _REQUEST, test_constants.LONG_TIMEOUT, protocol_options=call_options) + self._servicer.block_until_serviced() + self.assertIsNotNone(self._servicer.peer()) + + def test_stream_unary(self): + call_options = interfaces.grpc_call_options( + credentials=self._client_credentials) + request_iterator = _BlockingIterator(iter((_REQUEST,))) + response_future = getattr(self._dynamic_stub, _STREAM_UNARY).future( + request_iterator, test_constants.LONG_TIMEOUT, + protocol_options=call_options) + response_future.protocol_context().disable_next_request_compression() + request_iterator.allow() + response_future.protocol_context().disable_next_request_compression() + request_iterator.allow() + self._servicer.block_until_serviced() + self.assertIsNotNone(self._servicer.peer()) + self.assertEqual(_RESPONSE, response_future.result()) + + def test_stream_stream(self): + call_options = interfaces.grpc_call_options( + credentials=self._client_credentials) + request_iterator = _BlockingIterator(iter((_REQUEST,))) + response_iterator = getattr(self._dynamic_stub, _STREAM_STREAM)( + request_iterator, test_constants.SHORT_TIMEOUT, + protocol_options=call_options) + response_iterator.protocol_context().disable_next_request_compression() + request_iterator.allow() + response = next(response_iterator) + response_iterator.protocol_context().disable_next_request_compression() + request_iterator.allow() + self._servicer.block_until_serviced() + self.assertIsNotNone(self._servicer.peer()) + self.assertEqual(_RESPONSE, response) + + +if __name__ == '__main__': + unittest.main(verbosity=2) -- cgit v1.2.3 From f65d3c11023cd39b73c8832947889f656f2427a3 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Sat, 5 Sep 2015 03:55:19 +0000 Subject: Beta API clean-ups (1) Renamed the "beta" module "implementations" because it hasn't been monolithic since "interfaces" was factored out of it a few changes back. (2) Moved ChannelConnectivity from grpc.beta.beta to grpc.beta.interfaces since it is constants that don't depend on the beta implementation. (3) Moved the Server interface definition from grpc.beta.beta to grpc.beta.interfaces since it is an interface. (4) Dropped the "create_" prefix from "create_<...>_channel" functions to better match the other creation functions throughout the codebase. --- src/compiler/python_generator.cc | 16 +- .../grpcio/grpc/beta/_connectivity_channel.py | 16 +- src/python/grpcio/grpc/beta/_server.py | 6 +- src/python/grpcio/grpc/beta/beta.py | 491 --------------------- src/python/grpcio/grpc/beta/implementations.py | 367 +++++++++++++++ src/python/grpcio/grpc/beta/interfaces.py | 102 +++++ src/python/grpcio/grpc/beta/utilities.py | 21 +- .../grpc_protoc_plugin/beta_python_plugin_test.py | 4 +- .../grpc_test/beta/_beta_features_test.py | 17 +- .../grpc_test/beta/_connectivity_channel_test.py | 59 ++- .../grpc_test/beta/_face_interface_test.py | 19 +- .../grpcio_test/grpc_test/beta/_not_found_test.py | 8 +- .../grpcio_test/grpc_test/beta/_utilities_test.py | 6 +- .../grpcio_test/grpc_test/beta/test_utilities.py | 12 +- 14 files changed, 574 insertions(+), 570 deletions(-) delete mode 100644 src/python/grpcio/grpc/beta/beta.py create mode 100644 src/python/grpcio/grpc/beta/implementations.py (limited to 'src') diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index fe2b9fad99..83133f2b6e 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -339,7 +339,7 @@ bool PrintAlphaServerFactory(const grpc::string& package_qualified_service_name, } out->Print("}\n"); out->Print( - "return implementations.server(" + "return early_adopter_implementations.server(" "\"$PackageQualifiedServiceName$\"," " method_service_descriptions, port, private_key=private_key," " certificate_chain=certificate_chain)\n", @@ -422,7 +422,7 @@ bool PrintAlphaStubFactory(const grpc::string& package_qualified_service_name, } out->Print("}\n"); out->Print( - "return implementations.stub(" + "return early_adopter_implementations.stub(" "\"$PackageQualifiedServiceName$\"," " method_invocation_descriptions, host, port," " metadata_transformer=metadata_transformer, secure=secure," @@ -586,13 +586,13 @@ bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name, "Constructor", name_and_implementation_constructor->second); } out->Print("}\n"); - out->Print("server_options = beta.server_options(" + out->Print("server_options = beta_implementations.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, " + out->Print("return beta_implementations.server(method_implementations, " "options=server_options)\n"); } return true; @@ -685,13 +685,13 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name, "Cardinality", name_and_cardinality->second); } out->Print("}\n"); - out->Print("stub_options = beta.stub_options(" + out->Print("stub_options = beta_implementations.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$\', " + "return beta_implementations.dynamic_stub(channel, \'$PackageQualifiedServiceName$\', " "cardinalities, options=stub_options)\n", "PackageQualifiedServiceName", package_qualified_service_name); } @@ -701,9 +701,9 @@ bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name, bool PrintPreamble(const FileDescriptor* file, const GeneratorConfiguration& config, Printer* out) { out->Print("import abc\n"); - out->Print("from $Package$ import beta\n", + out->Print("from $Package$ import implementations as beta_implementations\n", "Package", config.beta_package_root); - out->Print("from $Package$ import implementations\n", + out->Print("from $Package$ import implementations as early_adopter_implementations\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"); diff --git a/src/python/grpcio/grpc/beta/_connectivity_channel.py b/src/python/grpcio/grpc/beta/_connectivity_channel.py index 457ede79f2..61674a70ad 100644 --- a/src/python/grpcio/grpc/beta/_connectivity_channel.py +++ b/src/python/grpcio/grpc/beta/_connectivity_channel.py @@ -33,18 +33,24 @@ import threading import time from grpc._adapter import _low +from grpc._adapter import _types +from grpc.beta import interfaces from grpc.framework.foundation import callable_util _CHANNEL_SUBSCRIPTION_CALLBACK_ERROR_LOG_MESSAGE = ( 'Exception calling channel subscription callback!') +_LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY = { + state: connectivity for state, connectivity in zip( + _types.ConnectivityState, interfaces.ChannelConnectivity) +} + class ConnectivityChannel(object): - def __init__(self, low_channel, mapping): + def __init__(self, low_channel): self._lock = threading.Lock() self._low_channel = low_channel - self._mapping = mapping self._polling = False self._connectivity = None @@ -88,7 +94,8 @@ class ConnectivityChannel(object): 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] + self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ + low_connectivity] callbacks = tuple( callback for callback, unused_but_known_to_be_none_connectivity in self._callbacks_and_connectivities) @@ -112,7 +119,8 @@ class ConnectivityChannel(object): 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] + self._connectivity = _LOW_CONNECTIVITY_STATE_TO_CHANNEL_CONNECTIVITY[ + low_connectivity] if not self._delivering: callbacks = self._deliveries(self._connectivity) if callbacks: diff --git a/src/python/grpcio/grpc/beta/_server.py b/src/python/grpcio/grpc/beta/_server.py index ebf91d80ab..daa42c475a 100644 --- a/src/python/grpcio/grpc/beta/_server.py +++ b/src/python/grpcio/grpc/beta/_server.py @@ -72,7 +72,7 @@ def _disassemble(grpc_link, end_link, pool, event, grace): event.set() -class Server(object): +class Server(interfaces.Server): def __init__(self, grpc_link, end_link, pool): self._grpc_link = grpc_link @@ -82,9 +82,9 @@ class Server(object): def add_insecure_port(self, address): return self._grpc_link.add_port(address, None) - def add_secure_port(self, address, intermediary_low_server_credentials): + def add_secure_port(self, address, server_credentials): return self._grpc_link.add_port( - address, intermediary_low_server_credentials) + address, server_credentials._intermediary_low_credentials) # pylint: disable=protected-access def start(self): self._grpc_link.join_link(self._end_link) diff --git a/src/python/grpcio/grpc/beta/beta.py b/src/python/grpcio/grpc/beta/beta.py deleted file mode 100644 index b3a161087f..0000000000 --- a/src/python/grpcio/grpc/beta/beta.py +++ /dev/null @@ -1,491 +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. - -"""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/implementations.py b/src/python/grpcio/grpc/beta/implementations.py new file mode 100644 index 0000000000..9b461fb3dd --- /dev/null +++ b/src/python/grpcio/grpc/beta/implementations.py @@ -0,0 +1,367 @@ +# 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.beta import interfaces +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!') + + +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) + + def subscribe(self, callback, try_to_connect=None): + """Subscribes to this Channel's connectivity. + + Args: + callback: A callable to be invoked and passed an + interfaces.ChannelConnectivity identifying 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 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 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 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) + + +def server(service_implementations, options=None): + """Creates an interfaces.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: + An interfaces.Server with which RPCs can be serviced. + """ + effective_options = _EMPTY_SERVER_OPTIONS if options is None else options + return _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) diff --git a/src/python/grpcio/grpc/beta/interfaces.py b/src/python/grpcio/grpc/beta/interfaces.py index 79f2620dd4..07c8618f70 100644 --- a/src/python/grpcio/grpc/beta/interfaces.py +++ b/src/python/grpcio/grpc/beta/interfaces.py @@ -32,6 +32,28 @@ import abc import enum +from grpc._adapter import _types + + +@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',) + @enum.unique class StatusCode(enum.Enum): @@ -110,3 +132,83 @@ class GRPCInvocationContext(object): def disable_next_request_compression(self): """Disables compression of the next request passed by the application.""" raise NotImplementedError() + + +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() diff --git a/src/python/grpcio/grpc/beta/utilities.py b/src/python/grpcio/grpc/beta/utilities.py index 1b5356e3ad..fb07a76579 100644 --- a/src/python/grpcio/grpc/beta/utilities.py +++ b/src/python/grpcio/grpc/beta/utilities.py @@ -32,7 +32,9 @@ import threading import time -from grpc.beta import beta +# implementations is referenced from specification in this module. +from grpc.beta import implementations # pylint: disable=unused-import +from grpc.beta import interfaces from grpc.framework.foundation import callable_util from grpc.framework.foundation import future @@ -70,7 +72,8 @@ class _ChannelReadyFuture(future.Future): def _update(self, connectivity): with self._condition: - if not self._cancelled and connectivity is beta.ChannelConnectivity.READY: + if (not self._cancelled and + connectivity is interfaces.ChannelConnectivity.READY): self._matured = True self._channel.unsubscribe(self._update) self._condition.notify_all() @@ -141,19 +144,19 @@ class _ChannelReadyFuture(future.Future): def channel_ready_future(channel): - """Creates a future.Future that matures when a beta.Channel is ready. + """Creates a future.Future tracking when an implementations.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. + Cancelling the returned future.Future does not tell the given + implementations.Channel to abandon attempts it may have been making to + connect; cancelling merely deactivates the return future.Future's + subscription to the given implementations.Channel's connectivity. Args: - channel: A beta.Channel. + channel: An implementations.Channel. Returns: A future.Future that matures when the given Channel has connectivity - beta.ChannelConnectivity.READY. + interfaces.ChannelConnectivity.READY. """ ready_future = _ChannelReadyFuture(channel) ready_future.start() 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 index 4c8c64b06d..259b978de2 100644 --- 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 @@ -42,7 +42,7 @@ import threading import time import unittest -from grpc.beta import beta +from grpc.beta import implementations from grpc.framework.foundation import future from grpc.framework.interfaces.face import face from grpc_test.framework.common import test_constants @@ -170,7 +170,7 @@ def _CreateService(test_pb2): server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer) port = server.add_insecure_port('[::]:0') server.start() - channel = beta.create_insecure_channel('localhost', port) + channel = implementations.insecure_channel('localhost', port) stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)(channel) yield servicer_methods, stub server.stop(0) diff --git a/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py b/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py index 89fe4b2acf..fad57da9d0 100644 --- a/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py +++ b/src/python/grpcio_test/grpc_test/beta/_beta_features_test.py @@ -32,7 +32,7 @@ import threading import unittest -from grpc.beta import beta +from grpc.beta import implementations from grpc.beta import interfaces from grpc.framework.common import cardinality from grpc.framework.interfaces.face import utilities @@ -159,20 +159,21 @@ class BetaFeaturesTest(unittest.TestCase): _STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM, } - server_options = beta.server_options( + server_options = implementations.server_options( thread_pool_size=test_constants.POOL_SIZE) - self._server = beta.server(method_implementations, options=server_options) - server_credentials = beta.ssl_server_credentials( + self._server = implementations.server( + method_implementations, options=server_options) + server_credentials = implementations.ssl_server_credentials( [(resources.private_key(), resources.certificate_chain(),),]) port = self._server.add_secure_port('[::]:0', server_credentials) self._server.start() - self._client_credentials = beta.ssl_client_credentials( + self._client_credentials = implementations.ssl_client_credentials( resources.test_root_certificates(), None, None) - channel = test_utilities.create_not_really_secure_channel( + channel = test_utilities.not_really_secure_channel( 'localhost', port, self._client_credentials, _SERVER_HOST_OVERRIDE) - stub_options = beta.stub_options( + stub_options = implementations.stub_options( thread_pool_size=test_constants.POOL_SIZE) - self._dynamic_stub = beta.dynamic_stub( + self._dynamic_stub = implementations.dynamic_stub( channel, _GROUP, cardinalities, options=stub_options) def tearDown(self): 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 index 038464889d..b3c05bdb0c 100644 --- a/src/python/grpcio_test/grpc_test/beta/_connectivity_channel_test.py +++ b/src/python/grpcio_test/grpc_test/beta/_connectivity_channel_test.py @@ -36,14 +36,9 @@ import unittest from grpc._adapter import _low from grpc._adapter import _types from grpc.beta import _connectivity_channel +from grpc.beta import interfaces 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: @@ -84,7 +79,7 @@ class ChannelConnectivityTest(unittest.TestCase): callback = _Callback() connectivity_channel = _connectivity_channel.ConnectivityChannel( - low_channel, _MAPPING) + low_channel) 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) @@ -98,11 +93,16 @@ class ChannelConnectivityTest(unittest.TestCase): 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) + self.assertSequenceEqual( + (interfaces.ChannelConnectivity.IDLE,), first_connectivities) + self.assertNotIn( + interfaces.ChannelConnectivity.READY, second_connectivities) + self.assertNotIn( + interfaces.ChannelConnectivity.READY, third_connectivities) + self.assertNotIn( + interfaces.ChannelConnectivity.READY, fourth_connectivities) + self.assertNotIn( + interfaces.ChannelConnectivity.READY, fifth_connectivities) def test_immediately_connectable_channel_connectivity(self): server_completion_queue = _low.CompletionQueue() @@ -117,7 +117,7 @@ class ChannelConnectivityTest(unittest.TestCase): second_callback = _Callback() connectivity_channel = _connectivity_channel.ConnectivityChannel( - low_channel, _MAPPING) + low_channel) connectivity_channel.subscribe(first_callback.update, try_to_connect=False) first_connectivities = first_callback.block_until_connectivities_satisfy( bool) @@ -132,9 +132,11 @@ class ChannelConnectivityTest(unittest.TestCase): bool) # Wait for a connection that will happen (or may already have happened). first_callback.block_until_connectivities_satisfy( - lambda connectivities: _READY in connectivities) + lambda connectivities: + interfaces.ChannelConnectivity.READY in connectivities) second_callback.block_until_connectivities_satisfy( - lambda connectivities: _READY in connectivities) + lambda connectivities: + interfaces.ChannelConnectivity.READY in connectivities) connectivity_channel.unsubscribe(first_callback.update) connectivity_channel.unsubscribe(second_callback.update) @@ -142,12 +144,19 @@ class ChannelConnectivityTest(unittest.TestCase): 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) + self.assertSequenceEqual( + (interfaces.ChannelConnectivity.IDLE,), first_connectivities) + self.assertSequenceEqual( + (interfaces.ChannelConnectivity.IDLE,), second_connectivities) + self.assertNotIn( + interfaces.ChannelConnectivity.TRANSIENT_FAILURE, third_connectivities) + self.assertNotIn( + interfaces.ChannelConnectivity.FATAL_FAILURE, third_connectivities) + self.assertNotIn( + interfaces.ChannelConnectivity.TRANSIENT_FAILURE, + fourth_connectivities) + self.assertNotIn( + interfaces.ChannelConnectivity.FATAL_FAILURE, fourth_connectivities) def test_reachable_then_unreachable_channel_connectivity(self): server_completion_queue = _low.CompletionQueue() @@ -161,14 +170,16 @@ class ChannelConnectivityTest(unittest.TestCase): callback = _Callback() connectivity_channel = _connectivity_channel.ConnectivityChannel( - low_channel, _MAPPING) + low_channel) connectivity_channel.subscribe(callback.update, try_to_connect=True) callback.block_until_connectivities_satisfy( - lambda connectivities: _READY in connectivities) + lambda connectivities: + interfaces.ChannelConnectivity.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) + lambda connectivities: + connectivities[-1] is not interfaces.ChannelConnectivity.READY) connectivity_channel.unsubscribe(callback.update) server.shutdown() 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 index e9087a7949..aa33e1e6f8 100644 --- a/src/python/grpcio_test/grpc_test/beta/_face_interface_test.py +++ b/src/python/grpcio_test/grpc_test/beta/_face_interface_test.py @@ -32,7 +32,7 @@ import collections import unittest -from grpc.beta import beta +from grpc.beta import implementations from grpc.beta import interfaces from grpc_test import resources from grpc_test import test_common as grpc_test_common @@ -81,25 +81,26 @@ class _Implementation(test_interfaces.Implementation): method: method_object.cardinality() for (group, method), method_object in methods.iteritems()} - server_options = beta.server_options( + server_options = implementations.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( + server = implementations.server( + method_implementations, options=server_options) + server_credentials = implementations.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( + client_credentials = implementations.ssl_client_credentials( resources.test_root_certificates(), None, None) - channel = test_utilities.create_not_really_secure_channel( + channel = test_utilities.not_really_secure_channel( 'localhost', port, client_credentials, _SERVER_HOST_OVERRIDE) - stub_options = beta.stub_options( + stub_options = implementations.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( + generic_stub = implementations.generic_stub(channel, options=stub_options) + dynamic_stub = implementations.dynamic_stub( channel, service, cardinalities, options=stub_options) return generic_stub, {service: dynamic_stub}, server diff --git a/src/python/grpcio_test/grpc_test/beta/_not_found_test.py b/src/python/grpcio_test/grpc_test/beta/_not_found_test.py index ecd10f2175..5feb997fef 100644 --- a/src/python/grpcio_test/grpc_test/beta/_not_found_test.py +++ b/src/python/grpcio_test/grpc_test/beta/_not_found_test.py @@ -31,7 +31,7 @@ import unittest -from grpc.beta import beta +from grpc.beta import implementations from grpc.beta import interfaces from grpc.framework.interfaces.face import face from grpc_test.framework.common import test_constants @@ -40,10 +40,10 @@ from grpc_test.framework.common import test_constants class NotFoundTest(unittest.TestCase): def setUp(self): - self._server = beta.server({}) + self._server = implementations.server({}) port = self._server.add_insecure_port('[::]:0') - channel = beta.create_insecure_channel('localhost', port) - self._generic_stub = beta.generic_stub(channel) + channel = implementations.insecure_channel('localhost', port) + self._generic_stub = implementations.generic_stub(channel) self._server.start() def tearDown(self): diff --git a/src/python/grpcio_test/grpc_test/beta/_utilities_test.py b/src/python/grpcio_test/grpc_test/beta/_utilities_test.py index 998e74ccf4..996cea9118 100644 --- a/src/python/grpcio_test/grpc_test/beta/_utilities_test.py +++ b/src/python/grpcio_test/grpc_test/beta/_utilities_test.py @@ -35,7 +35,7 @@ import unittest from grpc._adapter import _low from grpc._adapter import _types -from grpc.beta import beta +from grpc.beta import implementations from grpc.beta import utilities from grpc.framework.foundation import future from grpc_test.framework.common import test_constants @@ -69,7 +69,7 @@ class _Callback(object): class ChannelConnectivityTest(unittest.TestCase): def test_lonely_channel_connectivity(self): - channel = beta.create_insecure_channel('localhost', 12345) + channel = implementations.insecure_channel('localhost', 12345) callback = _Callback() ready_future = utilities.channel_ready_future(channel) @@ -94,7 +94,7 @@ class ChannelConnectivityTest(unittest.TestCase): 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) + channel = implementations.insecure_channel('localhost', port) callback = _Callback() try: diff --git a/src/python/grpcio_test/grpc_test/beta/test_utilities.py b/src/python/grpcio_test/grpc_test/beta/test_utilities.py index 338670478d..24a8600e12 100644 --- a/src/python/grpcio_test/grpc_test/beta/test_utilities.py +++ b/src/python/grpcio_test/grpc_test/beta/test_utilities.py @@ -30,25 +30,27 @@ """Test-appropriate entry points into the gRPC Python Beta API.""" from grpc._adapter import _intermediary_low -from grpc.beta import beta +from grpc.beta import implementations -def create_not_really_secure_channel( +def 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. + client_credentials: The implementations.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. + An implementations.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( + return implementations.Channel( intermediary_low_channel._internal, intermediary_low_channel) -- cgit v1.2.3 From 796d0a22fccc6a3617b59018a95ce512a0126731 Mon Sep 17 00:00:00 2001 From: vjpai Date: Tue, 8 Sep 2015 09:47:00 -0700 Subject: Removing some unused vestiges --- src/core/surface/call.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'src') diff --git a/src/core/surface/call.c b/src/core/surface/call.c index a8b4d65fbc..6ece56371b 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -61,18 +61,6 @@ - status/close recv (depending on client/server) */ #define MAX_CONCURRENT_COMPLETIONS 6 -typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state; - -typedef enum { - SEND_NOTHING, - SEND_INITIAL_METADATA, - SEND_BUFFERED_INITIAL_METADATA, - SEND_MESSAGE, - SEND_BUFFERED_MESSAGE, - SEND_TRAILING_METADATA_AND_FINISH, - SEND_FINISH -} send_action; - typedef struct { grpc_ioreq_completion_func on_complete; void *user_data; -- cgit v1.2.3 From bc81291f7e37c4163ed4490af5ef02e88acc7f63 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 8 Sep 2015 12:14:03 -0700 Subject: Remove check for no workers I *believe* this is actually safe, and the assert was errantly copy-pasted a while back. Fixes #3022 --- src/core/iomgr/pollset_multipoller_with_epoll.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/core/iomgr/pollset_multipoller_with_epoll.c b/src/core/iomgr/pollset_multipoller_with_epoll.c index fe66ebed77..8f62ce2954 100644 --- a/src/core/iomgr/pollset_multipoller_with_epoll.c +++ b/src/core/iomgr/pollset_multipoller_with_epoll.c @@ -99,7 +99,6 @@ static void perform_delayed_add(void *arg, int iomgr_status) { if (da->pollset->shutting_down) { /* We don't care about this pollset anymore. */ if (da->pollset->in_flight_cbs == 0 && !da->pollset->called_shutdown) { - GPR_ASSERT(!grpc_pollset_has_workers(da->pollset)); da->pollset->called_shutdown = 1; do_shutdown_cb = 1; } -- cgit v1.2.3 From 1fe38ffb7476df086c7d470e7f136dda92610c8e Mon Sep 17 00:00:00 2001 From: Julien Boeuf Date: Tue, 8 Sep 2015 17:21:05 -0700 Subject: Fixing #3286 - We cannot use call_data after the final callback as this one may trigger the deletion of the call object (hence the call_data). --- src/core/security/server_auth_filter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c index b767f85498..d134201e87 100644 --- a/src/core/security/server_auth_filter.c +++ b/src/core/security/server_auth_filter.c @@ -128,9 +128,11 @@ static void on_md_processing_done( calld->num_consumed_md = num_consumed_md; grpc_metadata_batch_filter(&calld->md_op->data.metadata, remove_consumed_md, elem); + grpc_metadata_array_destroy(&calld->md); calld->on_done_recv->cb(calld->on_done_recv->cb_arg, 1); } else { gpr_slice message; + grpc_metadata_array_destroy(&calld->md); error_details = error_details != NULL ? error_details : "Authentication metadata processing failed."; @@ -139,7 +141,6 @@ 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) { -- cgit v1.2.3